File indexing completed on 2025-02-22 09:38:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include "MPGDTrackerDigi.h"
0024
0025 #include <DD4hep/Alignments.h>
0026 #include <DD4hep/DetElement.h>
0027 #include <DD4hep/Handle.h>
0028 #include <DD4hep/IDDescriptor.h>
0029 #include <DD4hep/Objects.h>
0030 #include <DD4hep/Readout.h>
0031 #include <DD4hep/VolumeManager.h>
0032 #include <DD4hep/config.h>
0033 #include <DD4hep/detail/SegmentationsInterna.h>
0034 #include <DDSegmentation/BitFieldCoder.h>
0035 #include <Evaluator/DD4hepUnits.h>
0036 #include <JANA/JException.h>
0037 #include <Math/GenVector/Cartesian3D.h>
0038 #include <Math/GenVector/DisplacementVector3D.h>
0039 #include <Parsers/Primitives.h>
0040
0041 #include <algorithms/geo.h>
0042 #include <algorithms/logger.h>
0043 #include <edm4hep/EDM4hepVersion.h>
0044 #include <edm4eic/EDM4eicVersion.h>
0045 #include <edm4hep/MCParticleCollection.h>
0046 #include <edm4hep/Vector3d.h>
0047 #include <edm4hep/Vector3f.h>
0048 #include <fmt/core.h>
0049 #include <algorithm>
0050 #include <cmath>
0051 #include <cstdint>
0052 #include <gsl/pointers>
0053 #include <initializer_list>
0054 #include <unordered_map>
0055 #include <utility>
0056 #include <vector>
0057
0058 #include "algorithms/digi/MPGDTrackerDigiConfig.h"
0059
0060 using namespace dd4hep;
0061
0062 namespace eicrecon {
0063
0064 void MPGDTrackerDigi::init() {
0065
0066 m_gauss = [&](){
0067 return m_random.Gaus(0, m_cfg.timeResolution);
0068
0069 };
0070
0071
0072 m_detector = algorithms::GeoSvc::instance().detector();
0073 const dd4hep::BitFieldCoder* m_id_dec;
0074 if (m_cfg.readout.empty()) {
0075 throw JException("Readout is empty");
0076 }
0077 try {
0078 m_seg = m_detector->readout(m_cfg.readout).segmentation();
0079 m_id_dec = m_detector->readout(m_cfg.readout).idSpec().decoder();
0080 } catch (...) {
0081 critical("Failed to load ID decoder for \"{}\" readout.", m_cfg.readout);
0082 throw JException("Failed to load ID decoder");
0083 }
0084
0085
0086
0087
0088 if (m_id_dec->get(((CellID)0x3)<<30,"strip") != 0x3) {
0089 critical("Missing or invalid \"strip\" field in IDDescriptor for \"{}\" readout.",
0090 m_cfg.readout);
0091 throw JException("Invalid IDDescriptor");
0092 }
0093 debug("Find valid \"strip\" field in IDDescriptor for \"{}\" readout.",
0094 m_cfg.readout);
0095 }
0096
0097
0098 void MPGDTrackerDigi::process(
0099 const MPGDTrackerDigi::Input& input,
0100 const MPGDTrackerDigi::Output& output) const {
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 const auto [sim_hits] = input;
0114 auto [raw_hits,associations] = output;
0115
0116
0117 std::unordered_map<std::uint64_t, edm4eic::MutableRawTrackerHit> cell_hit_map;
0118
0119 const Position dummy(0,0,0);
0120 const VolumeManager& volman = m_detector->volumeManager();
0121
0122 using CellIDs = std::pair<CellID,CellID>;
0123 using Sim2IDs = std::vector<CellIDs>; Sim2IDs sim2IDs;
0124 for (const edm4hep::SimTrackerHit& sim_hit : *sim_hits) {
0125
0126
0127
0128
0129
0130
0131
0132 double time_smearing = m_gauss();
0133 double result_time = sim_hit.getTime() + time_smearing;
0134 auto hit_time_stamp = (std::int32_t) (result_time * 1e3);
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 const edm4hep::Vector3d &pos = sim_hit.getPosition();
0148 using dd4hep::mm;
0149 Position gpos(pos.x*mm,pos.y*mm,pos.z*mm);
0150 CellID vID =
0151
0152
0153 sim_hit.getCellID();
0154 DetElement local = volman.lookupDetElement(vID);
0155 const auto lpos = local.nominal().worldToLocal(gpos);
0156
0157 CellID stripBitp = ((CellID)0x1)<<30, vIDp = vID|stripBitp;
0158 CellID cIDp = m_seg->cellID(lpos,dummy,vIDp);
0159
0160 CellID stripBitn = ((CellID)0x2)<<30, vIDn = vID|stripBitn;
0161 CellID cIDn = m_seg->cellID(lpos,dummy,vIDn);
0162
0163 sim2IDs.push_back({cIDp,cIDn});
0164
0165 if(level() >= algorithms::LogLevel::kDebug) {
0166 CellID hIDp = cIDp>>32, sIDp = cIDp>>30&0x3;
0167 debug("--------------------");
0168 debug("Hit cellIDp = 0x{:08x}, 0x{:08x} 0x{:02x}", hIDp, vIDp, sIDp);
0169 CellID hIDn = cIDn>>32, sIDn = cIDn>>30&0x3;
0170 debug("Hit cellIDn = 0x{:08x}, 0x{:08x} 0x{:02x}", hIDn, vIDn, sIDn);
0171 debug(" position = ({:.2f}, {:.2f}, {:.2f})", sim_hit.getPosition().x, sim_hit.getPosition().y, sim_hit.getPosition().z);
0172 debug(" xy_radius = {:.2f}", std::hypot(sim_hit.getPosition().x, sim_hit.getPosition().y));
0173 debug(" momentum = ({:.2f}, {:.2f}, {:.2f})", sim_hit.getMomentum().x, sim_hit.getMomentum().y, sim_hit.getMomentum().z);
0174 debug(" edep = {:.2f}", sim_hit.getEDep());
0175 debug(" time = {:.4f}[ns]", sim_hit.getTime());
0176 #if EDM4HEP_BUILD_VERSION >= EDM4HEP_VERSION(0, 99, 0)
0177 debug(" particle time = {}[ns]", sim_hit.getParticle().getTime());
0178 #else
0179 debug(" particle time = {}[ns]", sim_hit.getMCParticle().getTime());
0180 #endif
0181 debug(" time smearing: {:.4f}, resulting time = {:.4f} [ns]", time_smearing, result_time);
0182 debug(" hit_time_stamp: {} [~ps]", hit_time_stamp);
0183 }
0184
0185
0186 if (sim_hit.getEDep() < m_cfg.threshold) {
0187 debug(" edep is below threshold of {:.2f} [keV]", m_cfg.threshold / keV);
0188 continue;
0189 }
0190
0191
0192 for (CellID cID : {cIDp,cIDn}) {
0193 if (cell_hit_map.count(cID) == 0) {
0194
0195 cell_hit_map[cID] = {
0196 cID,
0197 (std::int32_t) std::llround(sim_hit.getEDep() * 1e6),
0198 hit_time_stamp
0199 };
0200 } else {
0201
0202 auto& hit = cell_hit_map[cID];
0203 debug(" Hit already exists in cell ID={}, prev. hit time: {}", cID, hit.getTimeStamp());
0204
0205
0206 auto time_stamp = hit.getTimeStamp();
0207 hit.setTimeStamp(std::min(hit_time_stamp, hit.getTimeStamp()));
0208
0209
0210 auto charge = hit.getCharge();
0211 hit.setCharge(charge + (std::int32_t) std::llround(sim_hit.getEDep() * 1e6));
0212 }
0213 }
0214 }
0215
0216
0217 for (auto item : cell_hit_map) {
0218 raw_hits->push_back(item.second);
0219 Sim2IDs::const_iterator sim_it = sim2IDs.cbegin();
0220 for (const auto& sim_hit : *sim_hits) {
0221 CellIDs cIDs = *sim_it++;
0222 for (CellID cID : {cIDs.first,cIDs.second}) {
0223 if (item.first == cID) {
0224
0225 auto hitassoc = associations->create();
0226 hitassoc.setWeight(1.0);
0227 hitassoc.setRawHit(item.second);
0228 #if EDM4EIC_VERSION_MAJOR >= 6
0229 hitassoc.setSimHit(sim_hit);
0230 #else
0231 hitassoc.addToSimHits(sim_hit);
0232 #endif
0233 }
0234 }
0235 }
0236
0237 }
0238 }
0239
0240 }