LDMX Software
TrackingRecoDQM.cxx
1#include "Tracking/dqm/TrackingRecoDQM.h"
2
3namespace tracking::dqm {
4
6 track_collection_ = parameters.get<std::string>("track_collection");
7 truth_collection_ = parameters.get<std::string>("truth_collection");
8 measurement_collection_ =
9 parameters.get<std::string>("measurement_collection");
10 measurement_passname_ = parameters.get<std::string>("measurement_passname");
11
12 ecal_sp_events_passname_ =
13 parameters.get<std::string>("ecal_sp_events_passname");
14 ecal_sp_passname_ = parameters.get<std::string>("ecal_sp_passname");
15 target_sp_events_passname_ =
16 parameters.get<std::string>("target_sp_events_passname");
17 target_sp_passname_ = parameters.get<std::string>("target_sp_passname");
18 truth_passname_ = parameters.get<std::string>("truth_passname");
19 truth_events_passname_ = parameters.get<std::string>("truth_events_passname");
20 track_passname_ = parameters.get<std::string>("track_passname");
21 track_collection_events_passname_ =
22 parameters.get<std::string>("track_collection_events_passname");
23
24 title_ = parameters.get<std::string>("title", "tagger_trk_");
25 track_prob_cut_ = parameters.get<double>("trackProb_cut", 0.5);
26 subdetector_ = parameters.get<std::string>("subdetector", "Tagger");
27 track_states_ = parameters.get<std::vector<std::string>>("trackStates", {});
28
29 pidmap_[-321] = PIDBins::kminus;
30 pidmap_[321] = PIDBins::kplus;
31 pidmap_[-211] = PIDBins::piminus;
32 pidmap_[211] = PIDBins::piplus;
33 pidmap_[11] = PIDBins::electron;
34 pidmap_[-11] = PIDBins::positron;
35 pidmap_[2212] = PIDBins::proton;
36 pidmap_[-2212] = PIDBins::antiproton;
37}
38
40 ldmx_log(trace) << "DQM Reading in:" << track_collection_;
41
42 if (!event.exists(track_collection_, track_collection_events_passname_)) {
43 ldmx_log(error) << "TrackCollection " << track_collection_
44 << " with pass = " << track_collection_events_passname_
45 << " not in event";
46 return;
47 }
48
49 auto tracks{
50 event.getCollection<ldmx::Track>(track_collection_, track_passname_)};
51 auto measurements{event.getCollection<ldmx::Measurement>(
52 measurement_collection_, measurement_passname_)};
53
54 // The truth track collection
55 if (event.exists(truth_collection_, truth_events_passname_)) {
56 truth_track_collection_ = std::make_shared<ldmx::Tracks>(
57 event.getCollection<ldmx::Track>(truth_collection_, truth_passname_));
58 do_truth_comparison_ = true;
59 }
60
61 // The scoring plane hits_
62 if (event.exists("EcalScoringPlaneHits", ecal_sp_events_passname_)) {
63 ecal_scoring_hits_ = std::make_shared<std::vector<ldmx::SimTrackerHit>>(
64 event.getCollection<ldmx::SimTrackerHit>("EcalScoringPlaneHits",
65 ecal_sp_passname_));
66 }
67
68 if (event.exists("TargetScoringPlaneHits", target_sp_events_passname_)) {
69 target_scoring_hits_ = std::make_shared<std::vector<ldmx::SimTrackerHit>>(
70 event.getCollection<ldmx::SimTrackerHit>("TargetScoringPlaneHits",
71 target_sp_passname_));
72 }
73
74 ldmx_log(debug) << "Do truth comparison::" << do_truth_comparison_;
75
76 if (do_truth_comparison_) {
77 sortTracks(tracks, unique_tracks_, duplicate_tracks_, fake_tracks_);
78 } else {
79 unique_tracks_ = tracks;
80 }
81
82 ldmx_log(debug) << "Filling histograms for " << tracks.size() << " tracks";
83
84 // General Plots
85 histograms_.fill(title_ + "N_tracks", tracks.size());
86
87 if (!unique_tracks_.empty()) {
88 ldmx_log(debug) << "Track Monitoring on " << unique_tracks_.size()
89 << " Unique Tracks";
90 trackMonitoring(unique_tracks_, measurements, title_, true,
91 do_truth_comparison_);
92 }
93
94 // Fakes and duplicates
95 if (!duplicate_tracks_.empty()) {
96 ldmx_log(debug) << "Track Monitoring on " << duplicate_tracks_.size()
97 << " duplicates";
98 trackMonitoring(duplicate_tracks_, measurements, title_ + "dup_", false,
99 false);
100 }
101 if (!fake_tracks_.empty()) {
102 ldmx_log(debug) << "Track Monitoring on " << fake_tracks_.size()
103 << " fakes";
104 trackMonitoring(fake_tracks_, measurements, title_ + "fake_", false, false);
105 }
106
107 // Track Extrapolation to Ecal Monitoring
108 ldmx_log(trace) << "Track Extrapolation to Ecal Monitoring";
109 if (std::find(track_states_.begin(), track_states_.end(), "target") !=
110 track_states_.end()) {
111 trackStateMonitoring(tracks, ldmx::TrackStateType::AtTarget, "target");
112 }
113
114 if (std::find(track_states_.begin(), track_states_.end(), "ecal") !=
115 track_states_.end()) {
116 trackStateMonitoring(tracks, ldmx::TrackStateType::AtECAL, "ecal");
117 }
118
119 if (std::find(track_states_.begin(), track_states_.end(), "beamOrigin") !=
120 track_states_.end()) {
121 trackStateMonitoring(tracks, ldmx::TrackStateType::AtBeamOrigin,
122 "beamOrigin");
123 }
124
125 // Technical Efficiency plots
126 if (do_truth_comparison_) {
127 ldmx_log(trace) << "Technical Efficiency plots";
128 efficiencyPlots(tracks, measurements, title_);
129 }
130
131 // Tagger Recoil Matching
132
133 // Clear the vectors
134 ldmx_log(trace) << "Clear the vectors";
135 unique_tracks_.clear();
136 duplicate_tracks_.clear();
137 fake_tracks_.clear();
138}
139
141 // Produce the efficiency plots. (TODO::Switch to TEfficiency instead)
142}
143
144void TrackingRecoDQM::efficiencyPlots(
145 const std::vector<ldmx::Track>& tracks,
146 const std::vector<ldmx::Measurement>& measurements,
147 const std::string& title) {
148 // Do all truth track plots - denominator
149
150 histograms_.fill(title + "truth_N_tracks", truth_track_collection_->size());
151 for (auto& truth_trk : *(truth_track_collection_)) {
152 auto truth_phi = truth_trk.getPhi();
153 auto truth_d0 = truth_trk.getD0();
154 auto truth_z0 = truth_trk.getZ0();
155 auto truth_theta = truth_trk.getTheta();
156 auto truth_qop = truth_trk.getQoP();
157 auto truth_p = 1. / abs(truth_trk.getQoP());
158 auto truth_n_hits = truth_trk.getNhits();
159
160 std::vector<double> truth_mom = truth_trk.getMomentum();
161
162 // Polar angle
163 // The momentum in the plane transverse wrt the beam axis
164 auto truth_pt_beam =
165 std::sqrt(truth_mom[1] * truth_mom[1] + truth_mom[2] * truth_mom[2]);
166
167 auto truth_beam_angle = std::atan2(truth_pt_beam, truth_mom[0]);
168
169 histograms_.fill(title + "truth_nHits", truth_n_hits);
170 histograms_.fill(title + "truth_d0", truth_d0);
171 histograms_.fill(title + "truth_z0", truth_z0);
172 histograms_.fill(title + "truth_phi", truth_phi);
173 histograms_.fill(title + "truth_theta", truth_theta);
174 histograms_.fill(title + "truth_qop", truth_qop);
175 histograms_.fill(title + "truth_p", truth_p);
176 histograms_.fill(title + "truth_beam_angle", truth_beam_angle);
177
178 if (pidmap_.count(truth_trk.getPdgID()) != 0) {
179 histograms_.fill(title + "truth_PID", pidmap_[truth_trk.getPdgID()]);
180
181 // TODO do this properly.
182
183 if (pidmap_[truth_trk.getPdgID()] == PIDBins::kminus) {
184 histograms_.fill(title + "truth_kminus_p", truth_p);
185 }
186
187 if (pidmap_[truth_trk.getPdgID()] == PIDBins::kplus) {
188 histograms_.fill(title + "truth_kplus_p", truth_p);
189 }
190
191 if (pidmap_[truth_trk.getPdgID()] == PIDBins::piminus) {
192 histograms_.fill(title + "truth_piminus_p", truth_p);
193 }
194
195 if (pidmap_[truth_trk.getPdgID()] == PIDBins::piplus) {
196 histograms_.fill(title + "truth_piplus_p", truth_p);
197 }
198
199 if (pidmap_[truth_trk.getPdgID()] == PIDBins::electron) {
200 histograms_.fill(title + "truth_electron_p", truth_p);
201 }
202
203 if (pidmap_[truth_trk.getPdgID()] == PIDBins::positron) {
204 histograms_.fill(title + "truth_positron_p", truth_p);
205 }
206
207 if (pidmap_[truth_trk.getPdgID()] == PIDBins::proton) {
208 histograms_.fill(title + "truth_proton_p", truth_p);
209 }
210 }
211
212 } // loop on truth tracks
213
214 for (auto& track : tracks) {
215 // Match the tracks to truth
216 ldmx::Track* truth_trk = nullptr;
217
218 auto it = std::find_if(truth_track_collection_->begin(),
219 truth_track_collection_->end(),
220 [&](const ldmx::Track& tt) {
221 return tt.getTrackID() == track.getTrackID();
222 });
223
224 double track_truth_prob = track.getTruthProb();
225
226 if (it != truth_track_collection_->end() &&
227 track_truth_prob >= track_prob_cut_)
228 truth_trk = &(*it);
229
230 // Match not found
231 if (!truth_trk) return;
232
233 auto truth_phi = truth_trk->getPhi();
234 auto truth_d0 = truth_trk->getD0();
235 auto truth_z0 = truth_trk->getZ0();
236 auto truth_theta = truth_trk->getTheta();
237 auto truth_qop = truth_trk->getQoP();
238 auto truth_p = 1. / abs(truth_trk->getQoP());
239 std::vector<double> truth_mom = truth_trk->getMomentum();
240
241 // Polar angle
242 // The momentum in the plane transverse wrt the beam axis
243 auto truth_pt_beam =
244 std::sqrt(truth_mom[1] * truth_mom[1] + truth_mom[2] * truth_mom[2]);
245
246 auto truth_beam_angle = std::atan2(truth_pt_beam, truth_mom[0]);
247
248 // Fill reco plots for efficiencies - numerator. The quantities are truth
249 histograms_.fill(title + "match_prob", track_truth_prob);
250 histograms_.fill(title + "match_d0", truth_d0);
251 histograms_.fill(title + "match_z0", truth_z0);
252 histograms_.fill(title + "match_phi", truth_phi);
253 histograms_.fill(title + "match_theta", truth_theta);
254 histograms_.fill(title + "match_p", truth_p);
255 histograms_.fill(title + "match_qop", truth_qop);
256 histograms_.fill(title + "match_beam_angle", truth_beam_angle);
257 histograms_.fill(title + "match_nHits", measurements.size());
258 for (auto track_hit : track.getMeasurementsIdxs()) {
259 histograms_.fill(title + "match_LayersHit",
260 measurements.at(track_hit).getLayer());
261 }
262
263 // For some particles
264
265 if (pidmap_.count(truth_trk->getPdgID()) != 0) {
266 histograms_.fill(title + "match_PID", pidmap_[truth_trk->getPdgID()]);
267
268 // TODO do this properly.
269
270 if (pidmap_[truth_trk->getPdgID()] == PIDBins::kminus) {
271 histograms_.fill(title + "match_kminus_p", truth_p);
272 }
273
274 if (pidmap_[truth_trk->getPdgID()] == PIDBins::kplus) {
275 histograms_.fill(title + "match_kplus_p", truth_p);
276 }
277
278 if (pidmap_[truth_trk->getPdgID()] == PIDBins::piminus) {
279 histograms_.fill(title + "match_piminus_p", truth_p);
280 }
281
282 if (pidmap_[truth_trk->getPdgID()] == PIDBins::piplus) {
283 histograms_.fill(title + "match_piplus_p", truth_p);
284 }
285
286 if (pidmap_[truth_trk->getPdgID()] == PIDBins::electron) {
287 histograms_.fill(title + "match_electron_p", truth_p);
288 }
289
290 if (pidmap_[truth_trk->getPdgID()] == PIDBins::positron) {
291 histograms_.fill(title + "match_positron_p", truth_p);
292 }
293
294 if (pidmap_[truth_trk->getPdgID()] == PIDBins::proton) {
295 histograms_.fill(title + "match_proton_p", truth_p);
296 }
297 }
298 } // Loop on tracks
299
300} // Efficiency plots
301
302void TrackingRecoDQM::trackMonitoring(
303 const std::vector<ldmx::Track>& tracks,
304 const std::vector<ldmx::Measurement>& measurements, const std::string title,
305 const bool& doDetail, const bool& doTruth) {
306 for (auto& track : tracks) {
307 // Perigee track parameters
308 auto trk_d0 = track.getD0();
309 auto trk_z0 = track.getZ0();
310 auto trk_qop = track.getQoP();
311 auto trk_theta = track.getTheta();
312 auto trk_phi = track.getPhi();
313 auto trk_p = 1. / abs(trk_qop);
314 for (auto track_hit : track.getMeasurementsIdxs()) {
315 histograms_.fill(title + "LayersHit",
316 measurements.at(track_hit).getLayer());
317 }
318
319 std::vector<double> trk_mom = track.getMomentum();
320
321 // The transverse momentum in the bending plane
322 double pt_bending =
323 std::sqrt(trk_mom[0] * trk_mom[0] + trk_mom[1] * trk_mom[1]);
324
325 // The momentum in the plane transverse wrt the beam axis
326 double pt_beam =
327 std::sqrt(trk_mom[1] * trk_mom[1] + trk_mom[2] * trk_mom[2]);
328
329 // Covariance matrix
330 Acts::BoundSquareMatrix cov =
331 tracking::sim::utils::unpackCov(track.getPerigeeCov());
332
333 double sigmad0 = sqrt(
334 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0));
335 double sigmaz0 = sqrt(
336 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1));
337 double sigmaphi =
338 sqrt(cov(Acts::BoundIndices::eBoundPhi, Acts::BoundIndices::eBoundPhi));
339 double sigmatheta = sqrt(
340 cov(Acts::BoundIndices::eBoundTheta, Acts::BoundIndices::eBoundTheta));
341 double sigmaqop = sqrt(cov(Acts::BoundIndices::eBoundQOverP,
342 Acts::BoundIndices::eBoundQOverP));
343 double sigmap = (1. / trk_qop) * (1. / trk_qop) * sigmaqop;
344
345 histograms_.fill(title + "d0", trk_d0);
346 histograms_.fill(title + "z0", trk_z0);
347 histograms_.fill(title + "qop", trk_qop);
348 histograms_.fill(title + "phi", trk_phi);
349 histograms_.fill(title + "theta", trk_theta);
350 histograms_.fill(title + "p", std::abs(1. / trk_qop));
351
352 if (doDetail) {
353 histograms_.fill(title + "px", trk_mom[0]);
354 histograms_.fill(title + "py", trk_mom[1]);
355 histograms_.fill(title + "pz", trk_mom[2]);
356
357 histograms_.fill(title + "pt_bending", pt_bending);
358 histograms_.fill(title + "pt_beam", pt_beam);
359
360 histograms_.fill(title + "nHits", track.getNhits());
361 histograms_.fill(title + "Chi2", track.getChi2());
362 histograms_.fill(title + "ndf", track.getNdf());
363 histograms_.fill(title + "Chi2_per_ndf",
364 track.getChi2() / track.getNdf());
365 histograms_.fill(title + "nShared", track.getNsharedHits());
366
367 histograms_.fill(title + "d0_err", sigmad0);
368 histograms_.fill(title + "z0_err", sigmaz0);
369 histograms_.fill(title + "phi_err", sigmaphi);
370 histograms_.fill(title + "theta_err", sigmatheta);
371 histograms_.fill(title + "qop_err", sigmaqop);
372 histograms_.fill(title + "p_err", sigmap);
373
374 // 2D Error plots
375 double p = std::abs(1. / trk_qop);
376 histograms_.fill(title + "d0_err_vs_p", p, sigmad0);
377 histograms_.fill(title + "z0_err_vs_p", std::abs(1. / trk_qop), sigmaz0);
378 histograms_.fill(title + "p_err_vs_p", std::abs(1. / trk_qop), sigmap);
379
380 if (track.getNhits() == 8)
381 histograms_.fill(title + "p_err_vs_p_8hits", p, sigmap);
382 else if (track.getNhits() == 9)
383 histograms_.fill(title + "p_err_vs_p_9hits", p, sigmap);
384 else if (track.getNhits() == 10)
385 histograms_.fill(title + "p_err_vs_p_10hits", p, sigmap);
386 }
387
388 if (doTruth) {
389 // Match to the truth track
390 ldmx::Track* truth_trk = nullptr;
391
392 auto it = std::find_if(truth_track_collection_->begin(),
393 truth_track_collection_->end(),
394 [&](const ldmx::Track& tt) {
395 return tt.getTrackID() == track.getTrackID();
396 });
397
398 double track_truth_prob = track.getTruthProb();
399
400 if (it != truth_track_collection_->end() &&
401 track_truth_prob >= track_prob_cut_)
402 truth_trk = &(*it);
403
404 // Found matched track
405 if (truth_trk) {
406 auto truth_d0 = truth_trk->getD0();
407 auto truth_z0 = truth_trk->getZ0();
408 auto truth_phi = truth_trk->getPhi();
409 auto truth_theta = truth_trk->getTheta();
410 auto truth_qop = truth_trk->getQoP();
411 auto truth_p = 1. / abs(truth_trk->getQoP());
412 std::vector<double> truth_mom = truth_trk->getMomentum();
413 // Polar angle
414 // The momentum in the plane transverse wrt the beam axis
415 double truth_pt_beam = std::sqrt(truth_mom[1] * truth_mom[1] +
416 truth_mom[2] * truth_mom[2]);
417
418 // histograms_.fill(title+"truth_d0", truth_d0);
419 // histograms_.fill(title+"truth_z0", truth_z0);
420 // histograms_.fill(title+"truth_phi", truth_phi);
421 // histograms_.fill(title+"truth_theta",truth_theta);
422 // histograms_.fill(title+"truth_qop", truth_qop);
423 // histograms_.fill(title+"truth_p", truth_p);
424
425 double res_d0 = trk_d0 - truth_d0;
426 double res_z0 = trk_z0 - truth_z0;
427 double res_phi = trk_phi - truth_phi;
428 double res_theta = trk_theta - truth_theta;
429 double res_qop = trk_qop - truth_qop;
430 double res_p = trk_p - truth_p;
431 double res_pt_beam = pt_beam - truth_pt_beam;
432
433 histograms_.fill(title + "res_d0", res_d0);
434 histograms_.fill(title + "res_z0", res_z0);
435 histograms_.fill(title + "res_phi", res_phi);
436 histograms_.fill(title + "res_theta", res_theta);
437 histograms_.fill(title + "res_qop", res_qop);
438 histograms_.fill(title + "res_p", res_p);
439 histograms_.fill(title + "res_pt_beam", res_pt_beam);
440
441 double pull_d0 = res_d0 / sigmad0;
442 double pull_z0 = res_z0 / sigmaz0;
443 double pull_phi = res_phi / sigmaphi;
444 double pull_theta = res_theta / sigmatheta;
445 double pull_qop = res_qop / sigmaqop;
446 double pull_p = res_p / sigmap;
447
448 histograms_.fill(title + "pull_d0", pull_d0);
449 histograms_.fill(title + "pull_z0", pull_z0);
450 histograms_.fill(title + "pull_phi", pull_phi);
451 histograms_.fill(title + "pull_theta", pull_theta);
452 histograms_.fill(title + "pull_qop", pull_qop);
453 histograms_.fill(title + "pull_p", pull_p);
454
455 // Error plots from residuals
456
457 histograms_.fill(title + "res_p_vs_p", truth_p, res_p);
458
459 histograms_.fill(title + "res_qop_vs_p", truth_p, res_qop);
460 histograms_.fill(title + "res_d0_vs_p", truth_p, res_d0);
461 histograms_.fill(title + "res_z0_vs_p", truth_p, res_z0);
462 histograms_.fill(title + "res_phi_vs_p", truth_p, res_phi);
463 histograms_.fill(title + "res_theta_vs_p", truth_p, res_theta);
464
465 histograms_.fill(title + "pull_qop_vs_p", truth_p, pull_qop);
466 histograms_.fill(title + "pull_d0_vs_p", truth_p, pull_d0);
467 histograms_.fill(title + "pull_z0_vs_p", truth_p, pull_z0);
468 histograms_.fill(title + "pull_phi_vs_p", truth_p, pull_phi);
469 histograms_.fill(title + "pull_theta_vs_p", truth_p, pull_theta);
470
471 if (track.getNhits() == 8)
472 histograms_.fill(title + "res_p_vs_p_8hits", truth_p, res_p);
473 else if (track.getNhits() == 9)
474 histograms_.fill(title + "res_p_vs_p_9hits", truth_p, res_p);
475 else if (track.getNhits() == 10)
476 histograms_.fill(title + "res_p_vs_p_10hits", truth_p, res_p);
477
478 histograms_.fill(title + "res_pt_beam_vs_p", truth_pt_beam,
479 res_pt_beam);
480
481 } // found matched track
482 } // do TruthComparison
483 } // loop on tracks
484
485} // Track Monitoring
486
487void TrackingRecoDQM::trackStateMonitoring(const ldmx::Tracks& tracks,
488 ldmx::TrackStateType ts_type,
489 const std::string& ts_title) {
490 for (auto& track : tracks) {
491 // Match the tracks to truth
492 ldmx::Track* truth_trk = nullptr;
493
494 auto it = std::find_if(truth_track_collection_->begin(),
495 truth_track_collection_->end(),
496 [&](const ldmx::Track& tt) {
497 return tt.getTrackID() == track.getTrackID();
498 });
499
500 double track_truth_prob = track.getTruthProb();
501
502 if (it != truth_track_collection_->end() &&
503 track_truth_prob >= track_prob_cut_)
504 truth_trk = &(*it);
505
506 // Match not found, skip track
507 if (!truth_trk) continue;
508
509 // TruthTrack doesn't have the right amount of states
510
511 auto trk_ts = track.getTrackState(ts_type);
512 auto truth_ts = truth_trk->getTrackState(ts_type);
513
514 if (!trk_ts.has_value()) continue;
515
516 if (!truth_ts.has_value()) continue;
517
518 ldmx::Track::TrackState& truth_target_state = truth_ts.value();
519 ldmx::Track::TrackState& target_state = trk_ts.value();
520
521 ldmx_log(debug) << "Unpacking covariance matrix";
522 Acts::BoundSquareMatrix cov =
523 tracking::sim::utils::unpackCov(target_state.cov_);
524
525 [[maybe_unused]] double sigmaloc0 = sqrt(
526 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0));
527 [[maybe_unused]] double sigmaloc1 = sqrt(
528 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1));
529 [[maybe_unused]] double sigmaphi =
530 sqrt(cov(Acts::BoundIndices::eBoundPhi, Acts::BoundIndices::eBoundPhi));
531 [[maybe_unused]] double sigmatheta = sqrt(
532 cov(Acts::BoundIndices::eBoundTheta, Acts::BoundIndices::eBoundTheta));
533 [[maybe_unused]] double sigmaqop = sqrt(cov(
534 Acts::BoundIndices::eBoundQOverP, Acts::BoundIndices::eBoundQOverP));
535
536 double trk_qop = track.getQoP();
537 double trk_p = 1. / abs(trk_qop);
538
539 double track_state_loc0 = target_state.params_[0];
540 double track_state_loc1 = target_state.params_[1];
541 [[maybe_unused]] double track_state_phi = target_state.params_[2];
542 [[maybe_unused]] double track_state_theta = target_state.params_[3];
543 [[maybe_unused]] double track_state_p = target_state.params_[4];
544
545 double truth_state_loc0 = truth_target_state.params_[0];
546 double truth_state_loc1 = truth_target_state.params_[1];
547 [[maybe_unused]] double truth_state_phi = truth_target_state.params_[2];
548 [[maybe_unused]] double truth_state_theta = truth_target_state.params_[3];
549 [[maybe_unused]] double truth_state_p = truth_target_state.params_[4];
550
551 // Check that the track state is filled
552 if (target_state.params_.size() < 5) continue;
553
554 histograms_.fill(title_ + "trk_" + ts_title + "_loc0", track_state_loc0);
555 histograms_.fill(title_ + "trk_" + ts_title + "_loc1", track_state_loc1);
556 histograms_.fill(title_ + ts_title + "_sp_hit_X", truth_state_loc0);
557 histograms_.fill(title_ + ts_title + "_sp_hit_Y", truth_state_loc1);
558
559 // TH1F The difference(residual) between end_loc0 and sp_hit_X
560 histograms_.fill(title_ + "trk_" + ts_title + "_loc0-sp_hit_X",
561 track_state_loc0 - truth_state_loc0);
562 histograms_.fill(title_ + "trk_" + ts_title + "_loc1-sp_hit_Y",
563 track_state_loc1 - truth_state_loc1);
564
565 // TH1F The pulls of loc0 and loc1
566 histograms_.fill(title_ + ts_title + "_Pulls_of_loc0",
567 (track_state_loc0 - truth_state_loc0) / sigmaloc0);
568 histograms_.fill(title_ + ts_title + "_Pulls_of_loc1",
569 (track_state_loc1 - truth_state_loc1) / sigmaloc1);
570
571 // TODO:: TH1F The pulls of phi, theta, qop
572
573 // TH2F residual vs Nhits
574 histograms_.fill(title_ + ts_title + "_res_loc0-vs-N_hits",
575 track.getNhits(), track_state_loc0 - truth_state_loc0);
576 histograms_.fill(title_ + ts_title + "_res_loc1-vs-N_hits",
577 track.getNhits(), track_state_loc1 - truth_state_loc1);
578
579 // TH2F pulls vs Nhits
580 histograms_.fill(title_ + ts_title + "_pulls_loc0-vs-N_hits",
581 track.getNhits(),
582 (track_state_loc0 - truth_state_loc0) / sigmaloc0);
583 histograms_.fill(title_ + ts_title + "_pulls_loc1-vs-N_hits",
584 track.getNhits(),
585 (track_state_loc1 - truth_state_loc1) / sigmaloc1);
586
587 // TH2F residual vs trk_p
588 histograms_.fill(title_ + ts_title + "_res_loc0-vs-trk_p", trk_p,
589 track_state_loc0 - truth_state_loc0);
590 histograms_.fill(title_ + ts_title + "_res_loc1-vs-trk_p", trk_p,
591 track_state_loc1 - truth_state_loc1);
592
593 // TH2F pulls vs trk_p
594 histograms_.fill(title_ + ts_title + "_pulls_loc0-vs-trk_p", trk_p,
595 (track_state_loc0 - truth_state_loc0) / sigmaloc0);
596 histograms_.fill(title_ + ts_title + "_pulls_loc1-vs-trk_p", trk_p,
597 (track_state_loc1 - truth_state_loc1) / sigmaloc1);
598
599 } // loop on tracks
600}
601
602void TrackingRecoDQM::sortTracks(const std::vector<ldmx::Track>& tracks,
603 std::vector<ldmx::Track>& uniqueTracks,
604 std::vector<ldmx::Track>& duplicateTracks,
605 std::vector<ldmx::Track>& fakeTracks) {
606 // Create a copy of the const vector so we can sort it
607 std::vector<ldmx::Track> sorted_tracks = tracks;
608
609 // Sort the vector of Track objects based on their trackID member
610 std::sort(sorted_tracks.begin(), sorted_tracks.end(),
611 [](ldmx::Track& t1, ldmx::Track& t2) {
612 return t1.getTrackID() < t2.getTrackID();
613 });
614
615 // Loop over the sorted vector of Track objects
616 for (size_t i = 0; i < sorted_tracks.size(); i++) {
617 if (sorted_tracks[i].getTruthProb() < track_prob_cut_)
618 fakeTracks.push_back(sorted_tracks[i]);
619 else { // not a fake track
620 // If this is the first Track object with this trackID, add it to the
621 // uniqueTracks vector directly
622 if (uniqueTracks.size() == 0 ||
623 sorted_tracks[i].getTrackID() != sorted_tracks[i - 1].getTrackID()) {
624 uniqueTracks.push_back(sorted_tracks[i]);
625 }
626 // Otherwise, add it to the duplicateTracks vector if its truthProb is
627 // lower than the existing Track object Otherwise, if the truthProbability
628 // is higher than the track stored in uniqueTracks, put it in uniqueTracks
629 // and move the uniqueTracks.back to duplicateTracks.
630 else if (sorted_tracks[i].getTruthProb() >
631 uniqueTracks.back().getTruthProb()) {
632 duplicateTracks.push_back(uniqueTracks.back());
633 uniqueTracks.back() = sorted_tracks[i];
634 }
635 // Otherwise, add it to the duplicateTracks vector
636 else {
637 duplicateTracks.push_back(sorted_tracks[i]);
638 }
639 } // a real track
640 } // loop on sorted tracks
641 // The total number of elements in the uniqueTracks and duplicateTracks
642 // vectors should be equal to the number of elements in the original tracks
643 // vector
644 if (uniqueTracks.size() + duplicateTracks.size() + fakeTracks.size() !=
645 tracks.size()) {
646 std::cerr << "Error: unique and duplicate tracks vectors do not add up to "
647 "original tracks vector";
648 return;
649 }
650
651 // Iterate through the uniqueTracks vector and duplicateTracks vector
652 ldmx_log(trace) << "Unique tracks:";
653 for (const ldmx::Track& track : uniqueTracks) {
654 ldmx_log(trace) << "\tTrack ID: " << track.getTrackID()
655 << ", Truth Prob: " << track.getTruthProb();
656 }
657 ldmx_log(trace) << "Duplicate tracks:";
658 for (const ldmx::Track& track : duplicateTracks) {
659 ldmx_log(trace) << "\tTrack ID: " << track.getTrackID()
660 << ", Truth Prob: " << track.getTruthProb();
661 }
662 ldmx_log(trace) << "Fake tracks:";
663 for (const ldmx::Track& track : fakeTracks) {
664 ldmx_log(trace) << "\tTrack ID: " << track.getTrackID()
665 << ", Truth Prob: " << track.getTruthProb();
666 }
667}
668} // namespace tracking::dqm
669
#define DECLARE_ANALYZER(CLASS)
Macro which allows the framework to construct an analyzer given its name during configuration.
HistogramPool histograms_
helper object for making and filling histograms
Implements an event buffer system for storing event data.
Definition Event.h:42
bool exists(const std::string &name, const std::string &passName, bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.
Definition Event.cxx:92
const std::vector< ContentType > & getCollection(const std::string &collectionName, const std::string &passName) const
Get a collection (std::vector) of objects from the event bus.
Definition Event.h:400
void fill(const std::string &name, const T &val)
Fill a 1D histogram.
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
Represents a simulated tracker hit in the simulation.
Implementation of a track object.
Definition Track.h:53
void onProcessEnd() override
Callback for the EventProcessor to take any necessary action when the processing of events finishes,...
void configure(framework::config::Parameters &parameters) override
Configure the analyzer using the given user specified parameters.
void analyze(const framework::Event &event) override
Process the event and make histograms or summaries.
void trackStateMonitoring(const ldmx::Tracks &tracks, ldmx::TrackStateType ts_type, const std::string &ts_title)
Monitoring plots for tracks extrapolated to the ECAL Scoring plane.