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