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