LDMX Software
DigitizationProcessor.cxx
1#include "Tracking/Reco/DigitizationProcessor.h"
2
3#include <chrono>
4
5#include "Tracking/Event/Measurement.h"
6#include "Tracking/Sim/TrackingUtils.h"
7
8// Use this instead of CartesianSegmeter I think
9// BinUtility(std::size_t bins, float min, float max, BinningOption opt = open,
10// BinningValue value = BinningValue::binX,
11// const Transform3& tForm = Transform3::Identity())
12using namespace framework;
13
14namespace tracking::reco {
15
16DigitizationProcessor::DigitizationProcessor(const std::string& name,
17 framework::Process& process)
18 : TrackingGeometryUser(name, process) {}
19
20void DigitizationProcessor::onProcessStart() {
21 normal_ = std::make_shared<std::normal_distribution<float>>(0., 1.);
22 ldmx_log(info) << "Initialization done" << std::endl;
23}
24
25void DigitizationProcessor::configure(
27 hit_collection_ =
28 parameters.getParameter<std::string>("hit_collection", "TaggerSimHits");
29 out_collection_ = parameters.getParameter<std::string>("out_collection",
30 "OutputMeasuements");
31 min_e_dep_ = parameters.getParameter<double>("min_e_dep", 0.05);
32 track_id_ = parameters.getParameter<int>("track_id", -1);
33 do_smearing_ = parameters.getParameter<bool>("do_smearing", true);
34 sigma_u_ = parameters.getParameter<double>("sigma_u", 0.01);
35 sigma_v_ = parameters.getParameter<double>("sigma_v", 0.);
36 merge_hits_ = parameters.getParameter<bool>("merge_hits", false);
37}
38
39void DigitizationProcessor::onNewRun(const ldmx::RunHeader& runHeader) {
40 const auto& rseed = getCondition<framework::RandomNumberSeedService>(
42 generator_.seed(rseed.getSeed("Tracking::DigitizationProcessor"));
43}
44
45void DigitizationProcessor::produce(framework::Event& event) {
46 ldmx_log(debug) << " Getting the tracking geometry:" << geometry().getTG();
47
48 // Mode 0: Load simulated hits and produce smeared 1d measurements
49 // Mode 1: Load simulated hits and produce digitized 1d measurements
50
51 const std::vector<ldmx::SimTrackerHit> sim_hits =
52 event.getCollection<ldmx::SimTrackerHit>(hit_collection_);
53
54 std::vector<ldmx::SimTrackerHit> merged_hits;
55
56 std::vector<ldmx::Measurement> measurements;
57 if (merge_hits_) {
58 mergeSimHits(sim_hits, merged_hits);
59 measurements = digitizeHits(merged_hits);
60 }
61
62 else {
63 measurements = digitizeHits(sim_hits);
64 }
65
66 event.add(out_collection_, measurements);
67}
68
69// This method merges hits that have the same track_id on the same layer.
70// The energy of the merged hit is the sum of the energy of the single sub-hits
71// The position/momentum of the merged hit is the energy-weighted average
72// sihits = vector of hits to merge
73// mergedHits = total merged collection
74
75bool DigitizationProcessor::mergeHits(
76 const std::vector<ldmx::SimTrackerHit>& sihits,
77 std::vector<ldmx::SimTrackerHit>& mergedHits) {
78 if (sihits.size() < 1) return false;
79
80 if (sihits.size() == 1) {
81 mergedHits.push_back(sihits[0]);
82 return true;
83 }
84
85 ldmx::SimTrackerHit mergedHit;
86 // Since all the hits will be on the same sensor, just use the ID of the first
87 mergedHit.setLayerID(sihits[0].getLayerID());
88 mergedHit.setModuleID(sihits[0].getModuleID());
89 mergedHit.setID(sihits[0].getID());
90 mergedHit.setTrackID(sihits[0].getTrackID());
91
92 double X{0}, Y{0}, Z{0}, PX{0}, PY{0}, PZ{0};
93 double T{0}, E{0}, EDEP{0}, path{0};
94 int pdgID{0};
95
96 pdgID = sihits[0].getPdgID();
97
98 for (auto hit : sihits) {
99 double edep_hit = hit.getEdep();
100 EDEP += edep_hit;
101 E += hit.getEnergy();
102 T += edep_hit * hit.getTime();
103 X += edep_hit * hit.getPosition()[0];
104 Y += edep_hit * hit.getPosition()[1];
105 Z += edep_hit * hit.getPosition()[2];
106 PX += edep_hit * hit.getMomentum()[0];
107 PY += edep_hit * hit.getMomentum()[1];
108 PZ += edep_hit * hit.getMomentum()[2];
109 path += edep_hit * hit.getPathLength();
110
111 if (hit.getPdgID() != pdgID) {
112 ldmx_log(error)
113 << "ERROR:: Found hits with compatible sensorID and track_id "
114 "but different PDGID";
115 ldmx_log(error) << "TRACKID ==" << hit.getTrackID() << " vs "
116 << sihits[0].getTrackID();
117 ldmx_log(error) << "PDGID== " << hit.getPdgID() << " vs " << pdgID;
118 return false;
119 }
120 }
121
122 mergedHit.setTime(T / EDEP);
123 mergedHit.setPosition(X / EDEP, Y / EDEP, Z / EDEP);
124 mergedHit.setMomentum(PX / EDEP, PY / EDEP, PZ / EDEP);
125 mergedHit.setPathLength(path / EDEP);
126 mergedHit.setEnergy(E);
127 mergedHit.setEdep(EDEP);
128 mergedHit.setPdgID(pdgID);
129
130 mergedHits.push_back(mergedHit);
131
132 return true;
133}
134
135// TODO avoid copies and use references
136bool DigitizationProcessor::mergeSimHits(
137 const std::vector<ldmx::SimTrackerHit>& sim_hits,
138 std::vector<ldmx::SimTrackerHit>& merged_hits) {
139 // The first key is the index of the sensitive element ID, second key is the
140 // track_id
141 std::map<int, std::map<int, std::vector<ldmx::SimTrackerHit>>> hitmap;
142
143 for (auto hit : sim_hits) {
144 unsigned int index = tracking::sim::utils::getSensorID(hit);
145 unsigned int trackid = hit.getTrackID();
146 hitmap[index][trackid].push_back(hit);
147
148 ldmx_log(debug) << "hitmap being filled, size::[" << index << "]["
149 << trackid << "] size " << hitmap[index][trackid].size();
150 }
151
152 typedef std::map<int,
153 std::map<int, std::vector<ldmx::SimTrackerHit>>>::iterator
154 hitmap_it1;
155 typedef std::map<int, std::vector<ldmx::SimTrackerHit>>::iterator hitmap_it2;
156 for (hitmap_it1 it = hitmap.begin(); it != hitmap.end(); it++) {
157 for (hitmap_it2 it2 = it->second.begin(); it2 != it->second.end(); it2++) {
158 mergeHits(it2->second, merged_hits);
159 }
160 }
161
162 ldmx_log(debug) << "Sim_hits Size=" << sim_hits.size()
163 << "Merged_hits Size=" << merged_hits.size();
164
165 // for (auto hit : sim_hits) hit.Print();
166 // for (auto mhit : merged_hits) mhit.Print();
167
168 return true;
169}
170
171std::vector<ldmx::Measurement> DigitizationProcessor::digitizeHits(
172 const std::vector<ldmx::SimTrackerHit>& sim_hits) {
173 ldmx_log(debug) << "Found:" << sim_hits.size() << " sim hits in the "
174 << hit_collection_;
175
176 std::vector<ldmx::Measurement> measurements;
177
178 // Loop over all SimTrackerHits and
179 // * Use the position of the SimTrackerHit (global position) and the surface
180 // the hit was created on to extract the local coordinates.
181 // * If specified, smear the local coordinates and update the global
182 // coordinates.
183 // * Create a Measurement object.
184 for (auto& sim_hit : sim_hits) {
185 // Remove low energy deposit hits
186 if (sim_hit.getEdep() > min_e_dep_) {
187 if (track_id_ > 0 && sim_hit.getTrackID() != track_id_) continue;
188
189 ldmx::Measurement measurement(sim_hit);
190
191 // Get the layer ID.
192 auto layer_id = tracking::sim::utils::getSensorID(sim_hit);
193 measurement.setLayerID(layer_id);
194
195 // Get the surface
196 auto hit_surface{geometry().getSurface(layer_id)};
197
198 if (hit_surface) {
199 // Transform from global to local coordinates.
200 // hit_surface->toStream(geometry_context(), std::cout);
201 ldmx_log(debug)
202 << "Local to global" << std::endl
203 << hit_surface->transform(geometry_context()).rotation()
204 << std::endl
205 << hit_surface->transform(geometry_context()).translation();
206
207 Acts::Vector3 dummy_momentum;
208 Acts::Vector2 local_pos;
209 double surface_thickness = 0.320 * Acts::UnitConstants::mm;
210 Acts::Vector3 global_pos(measurement.getGlobalPosition()[0],
211 measurement.getGlobalPosition()[1],
212 measurement.getGlobalPosition()[2]);
213
214 try {
215 local_pos = hit_surface
216 ->globalToLocal(geometry_context(), global_pos,
217 dummy_momentum, surface_thickness)
218 .value();
219 } catch (const std::exception& e) {
220 ldmx_log(warn) << "hit not on surface... Skipping.";
221 continue;
222 }
223
224 // Smear the local position
225 if (do_smearing_) {
226 float smear_factor{(*normal_)(generator_)};
227
228 local_pos[0] += smear_factor * sigma_u_;
229 smear_factor = (*normal_)(generator_);
230 local_pos[1] += smear_factor * sigma_v_;
231
232 // update covariance
233 measurement.setLocalCovariance(sigma_u_ * sigma_u_,
234 sigma_v_ * sigma_v_);
235
236 // transform to global
237 auto transf_global_pos{hit_surface->localToGlobal(
238 geometry_context(), local_pos, dummy_momentum)};
239 measurement.setGlobalPosition(measurement.getGlobalPosition()[0],
240 transf_global_pos(1),
241 transf_global_pos(2));
242
243 } // do smearing
244 measurement.setLocalPosition(local_pos(0), local_pos(1));
245 measurements.push_back(measurement);
246 } // hit_surface exists
247
248 } // energy cut
249 } // loop on sim-hits
250
251 return measurements;
252
253} // digitizeHits
254} // namespace tracking::reco
255
256DECLARE_PRODUCER_NS(tracking::reco, DigitizationProcessor)
#define DECLARE_PRODUCER_NS(NS, CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Implements an event buffer system for storing event data.
Definition Event.h:41
Class which represents the process under execution.
Definition Process.h:36
static const std::string CONDITIONS_OBJECT_NAME
Conditions object name.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:27
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
std::array< float, 3 > getGlobalPosition() const
Definition Measurement.h:47
void setGlobalPosition(const float &x, const float &y, const float &z)
Set the global position i.e.
Definition Measurement.h:40
void setLayerID(const int &layerid)
Set the layer ID of the sensor where this measurement took place.
void setLocalPosition(const float &u, const float &v)
Set the local position i.e.
Definition Measurement.h:58
void setLocalCovariance(const float &cov_uu, const float &cov_vv)
Set cov(U,U) and cov(V, V).
Definition Measurement.h:74
Run-specific configuration and data stored in its own output TTree alongside the event TTree in the o...
Definition RunHeader.h:54
Represents a simulated tracker hit in the simulation.
void setEdep(const float edep)
Set the energy deposited on the hit [MeV].
void setModuleID(const int moduleID)
Set the module ID associated with a hit.
void setTime(const float time)
Set the global time of the hit [ns].
void setID(const long id)
Set the detector ID of the hit.
void setPosition(const float x, const float y, const float z)
Set the position of the hit [mm].
void setLayerID(const int layerID)
Set the geometric layer ID of the hit.
void setPathLength(const float pathLength)
Set the path length of the hit [mm].
void setEnergy(const float energy)
Set the energy of the hit.
void setPdgID(const int simPdgID)
Set the Sim particle track ID of the hit.
void setTrackID(const int simTrackID)
Set the Sim particle track ID of the hit.
void setMomentum(const float px, const float py, const float pz)
Set the momentum of the particle at the position at which the hit took place [GeV].
All classes in the ldmx-sw project use this namespace.
Definition PerfDict.cxx:45