LDMX Software
tracking::dqm::TrackingRecoDQM Class Reference

Public Member Functions

 TrackingRecoDQM (const std::string &name, framework::Process &process)
 
 ~TrackingRecoDQM ()=default
 Destructor.
 
void analyze (const framework::Event &event) override
 Process the event and make histograms or summaries.
 
void trackMonitoring (const std::vector< ldmx::Track > &tracks, const std::vector< ldmx::Measurement > &measurements, const std::string title, const bool &doDetail, const bool &doTruth)
 
void efficiencyPlots (const std::vector< ldmx::Track > &tracks, const std::vector< ldmx::Measurement > &measurements, const std::string &title)
 
void trackStateMonitoring (const std::vector< ldmx::Track > &tracks, ldmx::TrackStateType ts_type, const std::string &ts_title)
 Monitoring plots for tracks extrapolated to the ECAL Scoring plane.
 
void configure (framework::config::Parameters &parameters) override
 Configure the analyzer using the given user specified parameters.
 
void onProcessEnd () override
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
void sortTracks (const std::vector< ldmx::Track > &tracks, std::vector< ldmx::Track > &uniqueTracks, std::vector< ldmx::Track > &duplicateTracks, std::vector< ldmx::Track > &fakeTracks)
 
- Public Member Functions inherited from framework::Analyzer
 Analyzer (const std::string &name, Process &process)
 Class constructor.
 
virtual void process (Event &event) final
 Processing an event for an Analyzer is calling analyze.
 
virtual void beforeNewRun (ldmx::RunHeader &run_header) final
 Don't allow Analyzers to add parameters to the run header.
 
- Public Member Functions inherited from framework::EventProcessor
 DECLARE_FACTORY (EventProcessor, EventProcessor *, const std::string &, Process &)
 declare that we have a factory for this class
 
 EventProcessor (const std::string &name, Process &process)
 Class constructor.
 
virtual ~EventProcessor ()=default
 Class destructor.
 
virtual void onNewRun (const ldmx::RunHeader &run_header)
 Callback for the EventProcessor to take any necessary action when the run being processed changes.
 
virtual void onFileOpen (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a new event input ROOT file is opened.
 
virtual void onFileClose (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a event input ROOT file is closed.
 
virtual void onProcessStart ()
 Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.
 
template<class T >
const T & getCondition (const std::string &condition_name)
 Access a conditions object for the current event.
 
TDirectory * getHistoDirectory ()
 Access/create a directory in the histogram file for this event processor to create histograms and analysis tuples.
 
void setStorageHint (framework::StorageControl::Hint hint)
 Mark the current event as having the given storage control hint from this module_.
 
void setStorageHint (framework::StorageControl::Hint hint, const std::string &purposeString)
 Mark the current event as having the given storage control hint from this module and the given purpose string.
 
int getLogFrequency () const
 Get the current logging frequency from the process.
 
int getRunNumber () const
 Get the run number from the process.
 
std::string getName () const
 Get the processor name.
 
void createHistograms (const std::vector< framework::config::Parameters > &histos)
 Internal function which is used to create histograms passed from the python configuration @parma histos vector of Parameters that configure histograms to create.
 

Private Attributes

std::string track_collection_
 
std::string truth_collection_
 
std::string measurement_collection_
 
std::string measurement_passname_
 
std::string ecal_sp_coll_name_
 
std::string ecal_sp_passname_
 
std::string target_sp_coll_name_
 
std::string target_sp_passname_
 
std::string track_collection_events_passname_
 
std::string track_passname_
 
std::string truth_events_passname_
 
std::string truth_passname_
 
std::string title_ {"tagger_trk_"}
 
double track_prob_cut_ {0.5}
 
std::string subdetector_ {"Tagger"}
 
bool do_truth_comparison_ {false}
 
std::vector< std::string > track_states_
 
std::shared_ptr< std::vector< ldmx::Track > > truth_track_collection_ {nullptr}
 
std::shared_ptr< std::vector< ldmx::SimTrackerHit > > ecal_scoring_hits_ {nullptr}
 
std::shared_ptr< std::vector< ldmx::SimTrackerHit > > target_scoring_hits_
 
std::vector< ldmx::Trackunique_tracks_
 
std::vector< ldmx::Trackduplicate_tracks_
 
std::vector< ldmx::Trackfake_tracks_
 
std::map< int, int > pidmap_
 

Additional Inherited Members

- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 
- Protected Attributes inherited from framework::EventProcessor
HistogramPool histograms_
 helper object for making and filling histograms
 
NtupleManagerntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger the_log_
 The logger for this EventProcessor.
 

Detailed Description

Definition at line 28 of file TrackingRecoDQM.h.

Constructor & Destructor Documentation

◆ TrackingRecoDQM()

tracking::dqm::TrackingRecoDQM::TrackingRecoDQM ( const std::string & name,
framework::Process & process )
inline

Definition at line 30 of file TrackingRecoDQM.h.

Base class for a module which does not produce a data product.
virtual void process(Event &event) final
Processing an event for an Analyzer is calling analyze.

Member Function Documentation

◆ analyze()

void tracking::dqm::TrackingRecoDQM::analyze ( const framework::Event & event)
overridevirtual

Process the event and make histograms or summaries.

Parameters
eventThe Event to analyze

Implements framework::Analyzer.

Definition at line 37 of file TrackingRecoDQM.cxx.

37 {
38 ldmx_log(trace) << "DQM Reading in:" << track_collection_;
39
40 if (!event.exists(track_collection_, track_collection_events_passname_)) {
41 ldmx_log(error) << "TrackCollection " << track_collection_
42 << " with pass = " << track_collection_events_passname_
43 << " not in event";
44 return;
45 }
46
47 auto tracks{
48 event.getCollection<ldmx::Track>(track_collection_, track_passname_)};
49
50 if (!event.exists(measurement_collection_, measurement_passname_)) {
51 ldmx_log(error) << "Measurement collection " << measurement_collection_
52 << " with pass = " << measurement_passname_
53 << " not in event";
54 return;
55 }
56
57 auto measurements{event.getCollection<ldmx::Measurement>(
58 measurement_collection_, measurement_passname_)};
59
60 // The truth track collection
61 if (event.exists(truth_collection_, truth_events_passname_)) {
62 truth_track_collection_ = std::make_shared<std::vector<ldmx::Track>>(
63 event.getCollection<ldmx::Track>(truth_collection_, truth_passname_));
64 do_truth_comparison_ = true;
65 }
66
67 // The scoring plane hits_
68 if (event.exists(ecal_sp_coll_name_, ecal_sp_passname_)) {
69 ecal_scoring_hits_ = std::make_shared<std::vector<ldmx::SimTrackerHit>>(
70 event.getCollection<ldmx::SimTrackerHit>(ecal_sp_coll_name_,
71 ecal_sp_passname_));
72 }
73
74 if (event.exists(target_sp_coll_name_, target_sp_passname_)) {
75 target_scoring_hits_ = std::make_shared<std::vector<ldmx::SimTrackerHit>>(
76 event.getCollection<ldmx::SimTrackerHit>(target_sp_coll_name_,
77 target_sp_passname_));
78 }
79
80 ldmx_log(debug) << "Do truth comparison::" << do_truth_comparison_;
81
82 if (do_truth_comparison_) {
83 sortTracks(tracks, unique_tracks_, duplicate_tracks_, fake_tracks_);
84 } else {
85 unique_tracks_ = tracks;
86 }
87
88 ldmx_log(debug) << "Filling histograms for " << tracks.size() << " tracks";
89
90 // General Plots
91 histograms_.fill(title_ + "N_tracks", tracks.size());
92
93 if (!unique_tracks_.empty()) {
94 ldmx_log(debug) << "Track Monitoring on " << unique_tracks_.size()
95 << " Unique Tracks";
96 trackMonitoring(unique_tracks_, measurements, title_, true,
97 do_truth_comparison_);
98 }
99
100 // Fakes and duplicates
101 if (!duplicate_tracks_.empty()) {
102 ldmx_log(debug) << "Track Monitoring on " << duplicate_tracks_.size()
103 << " duplicates";
104 trackMonitoring(duplicate_tracks_, measurements, title_ + "dup_", false,
105 false);
106 }
107 if (!fake_tracks_.empty()) {
108 ldmx_log(debug) << "Track Monitoring on " << fake_tracks_.size()
109 << " fakes";
110 trackMonitoring(fake_tracks_, measurements, title_ + "fake_", false, false);
111 }
112
113 // Track Extrapolation to Ecal Monitoring
114 // trackStateMonitoring requires truth_track_collection_ to be available
115 ldmx_log(trace) << "Track Extrapolation to Ecal Monitoring";
116 if (do_truth_comparison_) {
117 if (std::find(track_states_.begin(), track_states_.end(), "target") !=
118 track_states_.end()) {
119 trackStateMonitoring(tracks, ldmx::AtTarget, "target");
120 }
121
122 if (std::find(track_states_.begin(), track_states_.end(), "ecal") !=
123 track_states_.end()) {
124 trackStateMonitoring(tracks, ldmx::AtECAL, "ecal");
125 }
126
127 if (std::find(track_states_.begin(), track_states_.end(), "beamOrigin") !=
128 track_states_.end()) {
129 trackStateMonitoring(tracks, ldmx::AtBeamOrigin, "beamOrigin");
130 }
131 }
132
133 // Technical Efficiency plots
134 if (do_truth_comparison_) {
135 ldmx_log(trace) << "Technical Efficiency plots";
136 efficiencyPlots(tracks, measurements, title_);
137 }
138
139 // Tagger Recoil Matching
140
141 // Clear the vectors
142 ldmx_log(trace) << "Clear the vectors";
143 unique_tracks_.clear();
144 duplicate_tracks_.clear();
145 fake_tracks_.clear();
146}
HistogramPool histograms_
helper object for making and filling histograms
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:105
void fill(const std::string &name, const T &val)
Fill a 1D histogram.
Represents a simulated tracker hit in the simulation.
Implementation of a track object.
Definition Track.h:53
void trackStateMonitoring(const std::vector< ldmx::Track > &tracks, ldmx::TrackStateType ts_type, const std::string &ts_title)
Monitoring plots for tracks extrapolated to the ECAL Scoring plane.

References framework::Event::exists(), framework::HistogramPool::fill(), framework::EventProcessor::histograms_, and trackStateMonitoring().

◆ configure()

void tracking::dqm::TrackingRecoDQM::configure ( framework::config::Parameters & parameters)
overridevirtual

Configure the analyzer using the given user specified parameters.

Parameters
parametersSet of parameters used to configure this analyzer.

Reimplemented from framework::EventProcessor.

Definition at line 5 of file TrackingRecoDQM.cxx.

5 {
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_coll_name_ = parameters.get<std::string>("ecal_sp_coll_name");
13 ecal_sp_passname_ = parameters.get<std::string>("ecal_sp_passname");
14 target_sp_coll_name_ = parameters.get<std::string>("target_sp_coll_name");
15 target_sp_passname_ = parameters.get<std::string>("target_sp_passname");
16 truth_passname_ = parameters.get<std::string>("truth_passname");
17 truth_events_passname_ = parameters.get<std::string>("truth_events_passname");
18 track_passname_ = parameters.get<std::string>("track_passname");
19 track_collection_events_passname_ =
20 parameters.get<std::string>("track_collection_events_passname");
21
22 title_ = parameters.get<std::string>("title", "tagger_trk_");
23 track_prob_cut_ = parameters.get<double>("trackProb_cut", 0.5);
24 subdetector_ = parameters.get<std::string>("subdetector", "Tagger");
25 track_states_ = parameters.get<std::vector<std::string>>("track_states", {});
26
27 pidmap_[-321] = PIDBins::kminus;
28 pidmap_[321] = PIDBins::kplus;
29 pidmap_[-211] = PIDBins::piminus;
30 pidmap_[211] = PIDBins::piplus;
31 pidmap_[11] = PIDBins::electron;
32 pidmap_[-11] = PIDBins::positron;
33 pidmap_[2212] = PIDBins::proton;
34 pidmap_[-2212] = PIDBins::antiproton;
35}
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78

References framework::config::Parameters::get().

◆ efficiencyPlots()

void tracking::dqm::TrackingRecoDQM::efficiencyPlots ( const std::vector< ldmx::Track > & tracks,
const std::vector< ldmx::Measurement > & measurements,
const std::string & title )

Definition at line 152 of file TrackingRecoDQM.cxx.

155 {
156 // Do all truth track plots - denominator
157
158 histograms_.fill(title + "truth_N_tracks", truth_track_collection_->size());
159 for (auto& truth_trk : *(truth_track_collection_)) {
160 auto truth_phi = truth_trk.getPhi();
161 auto truth_d0 = truth_trk.getD0();
162 auto truth_z0 = truth_trk.getZ0();
163 auto truth_theta = truth_trk.getTheta();
164 auto truth_qop = truth_trk.getQoP();
165 auto truth_p = 1000. / abs(truth_trk.getQoP()); // MeV
166 auto truth_n_hits = truth_trk.getNhits();
167
168 auto truth_mom = truth_trk.getMomentumAtTarget();
169 double truth_pt_beam{0.}, truth_beam_angle{0.};
170 if (truth_mom.size() == 3) {
171 truth_pt_beam =
172 std::sqrt(truth_mom[0] * truth_mom[0] + truth_mom[1] * truth_mom[1]);
173 truth_beam_angle = std::atan2(truth_pt_beam, truth_mom[2]);
174 }
175
176 histograms_.fill(title + "truth_nHits", truth_n_hits);
177 histograms_.fill(title + "truth_d0", truth_d0);
178 histograms_.fill(title + "truth_z0", truth_z0);
179 histograms_.fill(title + "truth_phi", truth_phi);
180 histograms_.fill(title + "truth_theta", truth_theta);
181 histograms_.fill(title + "truth_qop", truth_qop);
182 histograms_.fill(title + "truth_p", truth_p);
183 histograms_.fill(title + "truth_beam_angle", truth_beam_angle);
184
185 if (pidmap_.count(truth_trk.getPdgID()) != 0) {
186 histograms_.fill(title + "truth_PID", pidmap_[truth_trk.getPdgID()]);
187
188 // TODO do this properly.
189
190 if (pidmap_[truth_trk.getPdgID()] == PIDBins::kminus) {
191 histograms_.fill(title + "truth_kminus_p", truth_p);
192 }
193
194 if (pidmap_[truth_trk.getPdgID()] == PIDBins::kplus) {
195 histograms_.fill(title + "truth_kplus_p", truth_p);
196 }
197
198 if (pidmap_[truth_trk.getPdgID()] == PIDBins::piminus) {
199 histograms_.fill(title + "truth_piminus_p", truth_p);
200 }
201
202 if (pidmap_[truth_trk.getPdgID()] == PIDBins::piplus) {
203 histograms_.fill(title + "truth_piplus_p", truth_p);
204 }
205
206 if (pidmap_[truth_trk.getPdgID()] == PIDBins::electron) {
207 histograms_.fill(title + "truth_electron_p", truth_p);
208 }
209
210 if (pidmap_[truth_trk.getPdgID()] == PIDBins::positron) {
211 histograms_.fill(title + "truth_positron_p", truth_p);
212 }
213
214 if (pidmap_[truth_trk.getPdgID()] == PIDBins::proton) {
215 histograms_.fill(title + "truth_proton_p", truth_p);
216 }
217 }
218
219 } // loop on truth tracks
220
221 for (auto& track : tracks) {
222 // Match the tracks to truth
223 ldmx::Track* truth_trk = nullptr;
224
225 auto it = std::find_if(truth_track_collection_->begin(),
226 truth_track_collection_->end(),
227 [&](const ldmx::Track& tt) {
228 return tt.getTrackID() == track.getTrackID();
229 });
230
231 double track_truth_prob = track.getTruthProb();
232
233 if (it != truth_track_collection_->end() &&
234 track_truth_prob >= track_prob_cut_)
235 truth_trk = &(*it);
236
237 // Match not found
238 if (!truth_trk) return;
239
240 auto truth_phi = truth_trk->getPhi();
241 auto truth_d0 = truth_trk->getD0();
242 auto truth_z0 = truth_trk->getZ0();
243 auto truth_theta = truth_trk->getTheta();
244 auto truth_qop = truth_trk->getQoP();
245 auto truth_p = 1000. / abs(truth_trk->getQoP()); // MeV
246
247 auto truth_mom = truth_trk->getMomentumAtTarget();
248 double truth_pt_beam{0.}, truth_beam_angle{0.};
249 if (truth_mom.size() == 3) {
250 truth_pt_beam =
251 std::sqrt(truth_mom[0] * truth_mom[0] + truth_mom[1] * truth_mom[1]);
252 truth_beam_angle = std::atan2(truth_pt_beam, truth_mom[2]);
253 }
254
255 // Fill reco plots for efficiencies - numerator. The quantities are truth
256 histograms_.fill(title + "match_prob", track_truth_prob);
257 histograms_.fill(title + "match_d0", truth_d0);
258 histograms_.fill(title + "match_z0", truth_z0);
259 histograms_.fill(title + "match_phi", truth_phi);
260 histograms_.fill(title + "match_theta", truth_theta);
261 histograms_.fill(title + "match_p", truth_p);
262 histograms_.fill(title + "match_qop", truth_qop);
263 histograms_.fill(title + "match_beam_angle", truth_beam_angle);
264 histograms_.fill(title + "match_nHits", measurements.size());
265 auto dedx_measurements = track.getDedxMeasurements();
266 auto measurement_idxs = track.getMeasurementsIdxs();
267 for (size_t i = 0; i < measurement_idxs.size(); ++i) {
268 histograms_.fill(title + "match_layers_hit",
269 measurements.at(measurement_idxs[i]).getLayer());
270 // Add histogram of the measurement dE/dx
271 if (i < dedx_measurements.size()) {
272 histograms_.fill(title + "match_measurement_dedx",
273 dedx_measurements[i]);
274 }
275 }
276
277 // For some particles
278
279 if (pidmap_.count(truth_trk->getPdgID()) != 0) {
280 histograms_.fill(title + "match_PID", pidmap_[truth_trk->getPdgID()]);
281
282 // TODO do this properly.
283
284 if (pidmap_[truth_trk->getPdgID()] == PIDBins::kminus) {
285 histograms_.fill(title + "match_kminus_p", truth_p);
286 }
287
288 if (pidmap_[truth_trk->getPdgID()] == PIDBins::kplus) {
289 histograms_.fill(title + "match_kplus_p", truth_p);
290 }
291
292 if (pidmap_[truth_trk->getPdgID()] == PIDBins::piminus) {
293 histograms_.fill(title + "match_piminus_p", truth_p);
294 }
295
296 if (pidmap_[truth_trk->getPdgID()] == PIDBins::piplus) {
297 histograms_.fill(title + "match_piplus_p", truth_p);
298 }
299
300 if (pidmap_[truth_trk->getPdgID()] == PIDBins::electron) {
301 histograms_.fill(title + "match_electron_p", truth_p);
302 }
303
304 if (pidmap_[truth_trk->getPdgID()] == PIDBins::positron) {
305 histograms_.fill(title + "match_positron_p", truth_p);
306 }
307
308 if (pidmap_[truth_trk->getPdgID()] == PIDBins::proton) {
309 histograms_.fill(title + "match_proton_p", truth_p);
310 }
311 }
312 } // Loop on tracks
313
314} // Efficiency plots
std::vector< double > getMomentumAtTarget() const
Returns the momentum (px, py, pz) in MeV in the LDMX global frame from the AtTarget TrackState.
Definition Track.h:218

◆ onProcessEnd()

void tracking::dqm::TrackingRecoDQM::onProcessEnd ( )
overridevirtual

Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.

Reimplemented from framework::EventProcessor.

Definition at line 148 of file TrackingRecoDQM.cxx.

148 {
149 // Produce the efficiency plots. (TODO::Switch to TEfficiency instead)
150}

◆ sortTracks()

void tracking::dqm::TrackingRecoDQM::sortTracks ( const std::vector< ldmx::Track > & tracks,
std::vector< ldmx::Track > & uniqueTracks,
std::vector< ldmx::Track > & duplicateTracks,
std::vector< ldmx::Track > & fakeTracks )

Definition at line 643 of file TrackingRecoDQM.cxx.

646 {
647 // Create a copy of the const vector so we can sort it
648 std::vector<ldmx::Track> sorted_tracks = tracks;
649
650 // Sort the vector of Track objects based on their trackID member
651 std::sort(sorted_tracks.begin(), sorted_tracks.end(),
652 [](ldmx::Track& t1, ldmx::Track& t2) {
653 return t1.getTrackID() < t2.getTrackID();
654 });
655
656 // Loop over the sorted vector of Track objects
657 for (size_t i = 0; i < sorted_tracks.size(); i++) {
658 if (sorted_tracks[i].getTruthProb() < track_prob_cut_)
659 fakeTracks.push_back(sorted_tracks[i]);
660 else { // not a fake track
661 // If this is the first Track object with this trackID, add it to the
662 // uniqueTracks vector directly
663 if (uniqueTracks.size() == 0 ||
664 sorted_tracks[i].getTrackID() != sorted_tracks[i - 1].getTrackID()) {
665 uniqueTracks.push_back(sorted_tracks[i]);
666 }
667 // Otherwise, add it to the duplicateTracks vector if its truthProb is
668 // lower than the existing Track object Otherwise, if the truthProbability
669 // is higher than the track stored in uniqueTracks, put it in uniqueTracks
670 // and move the uniqueTracks.back to duplicateTracks.
671 else if (sorted_tracks[i].getTruthProb() >
672 uniqueTracks.back().getTruthProb()) {
673 duplicateTracks.push_back(uniqueTracks.back());
674 uniqueTracks.back() = sorted_tracks[i];
675 }
676 // Otherwise, add it to the duplicateTracks vector
677 else {
678 duplicateTracks.push_back(sorted_tracks[i]);
679 }
680 } // a real track
681 } // loop on sorted tracks
682 // The total number of elements in the uniqueTracks and duplicateTracks
683 // vectors should be equal to the number of elements in the original tracks
684 // vector
685 if (uniqueTracks.size() + duplicateTracks.size() + fakeTracks.size() !=
686 tracks.size()) {
687 std::cerr << "Error: unique and duplicate tracks vectors do not add up to "
688 "original tracks vector";
689 return;
690 }
691
692 // Iterate through the uniqueTracks vector and duplicateTracks vector
693 ldmx_log(trace) << "Unique tracks:";
694 for (const ldmx::Track& track : uniqueTracks) {
695 ldmx_log(trace) << "\tTrack ID: " << track.getTrackID()
696 << ", Truth Prob: " << track.getTruthProb();
697 }
698 ldmx_log(trace) << "Duplicate tracks:";
699 for (const ldmx::Track& track : duplicateTracks) {
700 ldmx_log(trace) << "\tTrack ID: " << track.getTrackID()
701 << ", Truth Prob: " << track.getTruthProb();
702 }
703 ldmx_log(trace) << "Fake tracks:";
704 for (const ldmx::Track& track : fakeTracks) {
705 ldmx_log(trace) << "\tTrack ID: " << track.getTrackID()
706 << ", Truth Prob: " << track.getTruthProb();
707 }
708}

◆ trackMonitoring()

void tracking::dqm::TrackingRecoDQM::trackMonitoring ( const std::vector< ldmx::Track > & tracks,
const std::vector< ldmx::Measurement > & measurements,
const std::string title,
const bool & doDetail,
const bool & doTruth )

Definition at line 316 of file TrackingRecoDQM.cxx.

319 {
320 for (auto& track : tracks) {
321 // Perigee track parameters
322 auto trk_d0 = track.getD0();
323 auto trk_z0 = track.getZ0();
324 auto trk_qop = track.getQoP();
325 auto trk_theta = track.getTheta();
326 auto trk_phi = track.getPhi();
327 auto trk_p = 1000. / abs(trk_qop); // MeV
328 auto dedx_measurements = track.getDedxMeasurements();
329 auto measurement_idxs = track.getMeasurementsIdxs();
330 for (size_t i = 0; i < measurement_idxs.size(); ++i) {
331 histograms_.fill(title + "layers_hit",
332 measurements.at(measurement_idxs[i]).getLayer());
333 // Add histogram of the measurement dE/dx
334 if (i < dedx_measurements.size()) {
335 histograms_.fill(title + "measurement_dedx", dedx_measurements[i]);
336 }
337 }
338
339 // Per-layer unbiased U-residuals — only filled for the main unique-track
340 // call (title == title_). Fakes/duplicates use a different title prefix
341 // and do not have these histograms declared.
342 //
343 // Algebraic leave-one-out unbiasing (NIM A 262, 444, 1987):
344 // r_smooth = m - x_smooth
345 // denom = V - C (V = cov_uu, C = smoothed cov[loc0,loc0])
346 // r_ubs = V / denom * r_smooth
347 // pull = r_smooth / sqrt(denom)
348 if (title == title_) {
349 const auto& sm_loc0 = track.getSmoothedLoc0();
350 const auto& sm_cov = track.getSmoothedCovLoc0();
351 for (size_t i = 0; i < measurement_idxs.size(); ++i) {
352 if (i >= sm_loc0.size()) break;
353 const auto& meas = measurements.at(measurement_idxs[i]);
354 int layer = meas.getLayer();
355 float meas_u = meas.getLocalPosition()[0];
356 float V = meas.getLocalCovariance()[0]; // cov_uu
357 float C = sm_cov[i]; // smoothed cov[loc0, loc0]
358 float denom = V - C;
359 if (denom <= 0.f) continue; // degenerate — skip
360 float r_smooth = meas_u - sm_loc0[i];
361 float res_ubs = r_smooth * V / denom;
362 float pull_ubs = r_smooth / std::sqrt(denom);
363 histograms_.fill(title_ + "unbiased_res_u_l" + std::to_string(layer),
364 res_ubs);
365 histograms_.fill(title_ + "unbiased_pull_u_l" + std::to_string(layer),
366 pull_ubs);
367 }
368 }
369
370 auto trk_mom = track.getMomentumAtTarget();
371 // getMomentumAtTarget() returns MeV (LDMX convention)
372 double px_ldmx{0.}, py_ldmx{0.}, pz_ldmx{0.};
373 double pt_bending{0.}, pt_beam{0.};
374 if (trk_mom.size() == 3) {
375 px_ldmx = trk_mom[0]; // MeV
376 py_ldmx = trk_mom[1];
377 pz_ldmx = trk_mom[2];
378 // Bending-plane pT: horizontal (x_ldmx) + downstream (z_ldmx)
379 pt_bending = std::sqrt(px_ldmx * px_ldmx + pz_ldmx * pz_ldmx);
380 // Transverse pT perpendicular to beam: horizontal + vertical
381 pt_beam = std::sqrt(px_ldmx * px_ldmx + py_ldmx * py_ldmx);
382 }
383
384 // Covariance matrix
385 Acts::BoundSquareMatrix cov =
386 tracking::sim::utils::unpackCov(track.getPerigeeCov());
387
388 double sigmad0 = sqrt(
389 cov(Acts::BoundIndices::eBoundLoc0, Acts::BoundIndices::eBoundLoc0));
390 double sigmaz0 = sqrt(
391 cov(Acts::BoundIndices::eBoundLoc1, Acts::BoundIndices::eBoundLoc1));
392 double sigmaphi =
393 sqrt(cov(Acts::BoundIndices::eBoundPhi, Acts::BoundIndices::eBoundPhi));
394 double sigmatheta = sqrt(
395 cov(Acts::BoundIndices::eBoundTheta, Acts::BoundIndices::eBoundTheta));
396 double sigmaqop = sqrt(cov(Acts::BoundIndices::eBoundQOverP,
397 Acts::BoundIndices::eBoundQOverP));
398 double sigmap =
399 (1000. / trk_qop) * (1000. / trk_qop) * sigmaqop / 1000.; // MeV
400
401 histograms_.fill(title + "d0", trk_d0);
402 histograms_.fill(title + "z0", trk_z0);
403 histograms_.fill(title + "qop", trk_qop);
404 histograms_.fill(title + "phi", trk_phi);
405 histograms_.fill(title + "theta", trk_theta);
406 histograms_.fill(title + "p", trk_p);
407
408 if (doDetail) {
409 histograms_.fill(title + "px", px_ldmx);
410 histograms_.fill(title + "py", py_ldmx);
411 histograms_.fill(title + "pz", pz_ldmx);
412
413 histograms_.fill(title + "pt_bending", pt_bending);
414 histograms_.fill(title + "pt_beam", pt_beam);
415
416 histograms_.fill(title + "nHits", track.getNhits());
417 histograms_.fill(title + "Chi2", track.getChi2());
418 histograms_.fill(title + "ndf", track.getNdf());
419 histograms_.fill(title + "Chi2_per_ndf",
420 track.getChi2() / track.getNdf());
421 histograms_.fill(title + "nShared", track.getNsharedHits());
422
423 histograms_.fill(title + "d0_err", sigmad0);
424 histograms_.fill(title + "z0_err", sigmaz0);
425 histograms_.fill(title + "phi_err", sigmaphi);
426 histograms_.fill(title + "theta_err", sigmatheta);
427 histograms_.fill(title + "qop_err", sigmaqop);
428 histograms_.fill(title + "p_err", sigmap);
429
430 // 2D Error plots (p in MeV)
431 histograms_.fill(title + "d0_err_vs_p", trk_p, sigmad0);
432 histograms_.fill(title + "z0_err_vs_p", trk_p, sigmaz0);
433 histograms_.fill(title + "p_err_vs_p", trk_p, sigmap);
434
435 if (track.getNhits() == 8)
436 histograms_.fill(title + "p_err_vs_p_8hits", trk_p, sigmap);
437 else if (track.getNhits() == 9)
438 histograms_.fill(title + "p_err_vs_p_9hits", trk_p, sigmap);
439 else if (track.getNhits() == 10)
440 histograms_.fill(title + "p_err_vs_p_10hits", trk_p, sigmap);
441 }
442
443 if (doTruth) {
444 // Match to the truth track
445 ldmx::Track* truth_trk = nullptr;
446
447 auto it = std::find_if(truth_track_collection_->begin(),
448 truth_track_collection_->end(),
449 [&](const ldmx::Track& tt) {
450 return tt.getTrackID() == track.getTrackID();
451 });
452
453 double track_truth_prob = track.getTruthProb();
454
455 if (it != truth_track_collection_->end() &&
456 track_truth_prob >= track_prob_cut_)
457 truth_trk = &(*it);
458
459 // Found matched track
460 if (truth_trk) {
461 auto truth_d0 = truth_trk->getD0();
462 auto truth_z0 = truth_trk->getZ0();
463 auto truth_phi = truth_trk->getPhi();
464 auto truth_theta = truth_trk->getTheta();
465 auto truth_qop = truth_trk->getQoP();
466 auto truth_p = 1000. / abs(truth_trk->getQoP()); // MeV
467 auto truth_mom = truth_trk->getMomentumAtTarget();
468 // getMomentumAtTarget() returns MeV (LDMX convention)
469 double truth_pt_beam{0.};
470 if (truth_mom.size() == 3) {
471 truth_pt_beam = std::sqrt(truth_mom[0] * truth_mom[0] +
472 truth_mom[1] * truth_mom[1]);
473 }
474
475 // histograms_.fill(title+"truth_d0", truth_d0);
476 // histograms_.fill(title+"truth_z0", truth_z0);
477 // histograms_.fill(title+"truth_phi", truth_phi);
478 // histograms_.fill(title+"truth_theta",truth_theta);
479 // histograms_.fill(title+"truth_qop", truth_qop);
480 // histograms_.fill(title+"truth_p", truth_p);
481
482 double res_d0 = trk_d0 - truth_d0;
483 double res_z0 = trk_z0 - truth_z0;
484 double res_phi = trk_phi - truth_phi;
485 double res_theta = trk_theta - truth_theta;
486 double res_qop = trk_qop - truth_qop;
487 double res_p = trk_p - truth_p;
488 double res_pt_beam = pt_beam - truth_pt_beam;
489
490 histograms_.fill(title + "res_d0", res_d0);
491 histograms_.fill(title + "res_z0", res_z0);
492 histograms_.fill(title + "res_phi", res_phi);
493 histograms_.fill(title + "res_theta", res_theta);
494 histograms_.fill(title + "res_qop", res_qop);
495 histograms_.fill(title + "res_p", res_p);
496 histograms_.fill(title + "res_pt_beam", res_pt_beam);
497
498 double pull_d0 = res_d0 / sigmad0;
499 double pull_z0 = res_z0 / sigmaz0;
500 double pull_phi = res_phi / sigmaphi;
501 double pull_theta = res_theta / sigmatheta;
502 double pull_qop = res_qop / sigmaqop;
503 double pull_p = res_p / sigmap;
504
505 histograms_.fill(title + "pull_d0", pull_d0);
506 histograms_.fill(title + "pull_z0", pull_z0);
507 histograms_.fill(title + "pull_phi", pull_phi);
508 histograms_.fill(title + "pull_theta", pull_theta);
509 histograms_.fill(title + "pull_qop", pull_qop);
510 histograms_.fill(title + "pull_p", pull_p);
511
512 // Error plots from residuals
513
514 histograms_.fill(title + "res_p_vs_p", truth_p, res_p);
515
516 histograms_.fill(title + "res_qop_vs_p", truth_p, res_qop);
517 histograms_.fill(title + "res_d0_vs_p", truth_p, res_d0);
518 histograms_.fill(title + "res_z0_vs_p", truth_p, res_z0);
519 histograms_.fill(title + "res_phi_vs_p", truth_p, res_phi);
520 histograms_.fill(title + "res_theta_vs_p", truth_p, res_theta);
521
522 histograms_.fill(title + "pull_qop_vs_p", truth_p, pull_qop);
523 histograms_.fill(title + "pull_d0_vs_p", truth_p, pull_d0);
524 histograms_.fill(title + "pull_z0_vs_p", truth_p, pull_z0);
525 histograms_.fill(title + "pull_phi_vs_p", truth_p, pull_phi);
526 histograms_.fill(title + "pull_theta_vs_p", truth_p, pull_theta);
527
528 if (track.getNhits() == 8)
529 histograms_.fill(title + "res_p_vs_p_8hits", truth_p, res_p);
530 else if (track.getNhits() == 9)
531 histograms_.fill(title + "res_p_vs_p_9hits", truth_p, res_p);
532 else if (track.getNhits() == 10)
533 histograms_.fill(title + "res_p_vs_p_10hits", truth_p, res_p);
534
535 histograms_.fill(title + "res_pt_beam_vs_p", truth_pt_beam,
536 res_pt_beam);
537
538 } // found matched track
539 } // do TruthComparison
540 } // loop on tracks
541
542} // Track Monitoring

◆ trackStateMonitoring()

void tracking::dqm::TrackingRecoDQM::trackStateMonitoring ( const std::vector< ldmx::Track > & tracks,
ldmx::TrackStateType ts_type,
const std::string & ts_title )

Monitoring plots for tracks extrapolated to the ECAL Scoring plane.

This aims Tracks will be truth matched first to get the trackID. The hit with the trackID

Definition at line 544 of file TrackingRecoDQM.cxx.

546 {
547 for (auto& track : tracks) {
548 // Match the tracks to truth
549 ldmx::Track* truth_trk = nullptr;
550
551 auto it = std::find_if(truth_track_collection_->begin(),
552 truth_track_collection_->end(),
553 [&](const ldmx::Track& tt) {
554 return tt.getTrackID() == track.getTrackID();
555 });
556
557 double track_truth_prob = track.getTruthProb();
558
559 if (it != truth_track_collection_->end() &&
560 track_truth_prob >= track_prob_cut_)
561 truth_trk = &(*it);
562
563 // Match not found, skip track
564 if (!truth_trk) continue;
565
566 auto trk_ts = track.getTrackState(ts_type);
567 auto truth_ts = truth_trk->getTrackState(ts_type);
568
569 if (!trk_ts.has_value()) continue;
570 if (!truth_ts.has_value()) continue;
571
572 const ldmx::Track::TrackState& target_state = trk_ts.value();
573 const ldmx::Track::TrackState& truth_target_state = truth_ts.value();
574
575 // Check that the covariance is filled
576 if (target_state.pos_mom_cov_.size() < 21) continue;
577
578 // Sigma from Cartesian position covariance (LDMX frame):
579 // pos_mom_cov_ upper-triangle layout: xx=0, yy=6
580 double sigmaloc0 = std::sqrt(target_state.pos_mom_cov_[0]); // sigma_x
581 double sigmaloc1 = std::sqrt(target_state.pos_mom_cov_[6]); // sigma_y
582
583 double trk_qop = track.getQoP();
584 double trk_p = 1000. / abs(trk_qop); // MeV
585
586 // loc0/loc1 = x/y position at the surface in LDMX global frame
587 double track_state_loc0 = target_state.pos_[0];
588 double track_state_loc1 = target_state.pos_[1];
589
590 double truth_state_loc0 = truth_target_state.pos_[0];
591 double truth_state_loc1 = truth_target_state.pos_[1];
592
593 histograms_.fill(title_ + "trk_" + ts_title + "_loc0", track_state_loc0);
594 histograms_.fill(title_ + "trk_" + ts_title + "_loc1", track_state_loc1);
595 histograms_.fill(title_ + ts_title + "_truth_loc0", truth_state_loc0);
596 histograms_.fill(title_ + ts_title + "_truth_loc1", truth_state_loc1);
597
598 // TH1F residuals
600 title_ + "trk_" + ts_title + "_loc0-truth_" + ts_title + "_loc0",
601 track_state_loc0 - truth_state_loc0);
603 title_ + "trk_" + ts_title + "_loc1-truth_" + ts_title + "_loc1",
604 track_state_loc1 - truth_state_loc1);
605
606 // TH1F The pulls of loc0 and loc1
607 histograms_.fill(title_ + ts_title + "_Pulls_of_loc0",
608 (track_state_loc0 - truth_state_loc0) / sigmaloc0);
609 histograms_.fill(title_ + ts_title + "_Pulls_of_loc1",
610 (track_state_loc1 - truth_state_loc1) / sigmaloc1);
611
612 // TODO:: TH1F The pulls of phi, theta, qop
613
614 // TH2F residual vs Nhits
615 histograms_.fill(title_ + ts_title + "_res_loc0-vs-N_hits",
616 track.getNhits(), track_state_loc0 - truth_state_loc0);
617 histograms_.fill(title_ + ts_title + "_res_loc1-vs-N_hits",
618 track.getNhits(), track_state_loc1 - truth_state_loc1);
619
620 // TH2F pulls vs Nhits
621 histograms_.fill(title_ + ts_title + "_pulls_loc0-vs-N_hits",
622 track.getNhits(),
623 (track_state_loc0 - truth_state_loc0) / sigmaloc0);
624 histograms_.fill(title_ + ts_title + "_pulls_loc1-vs-N_hits",
625 track.getNhits(),
626 (track_state_loc1 - truth_state_loc1) / sigmaloc1);
627
628 // TH2F residual vs trk_p
629 histograms_.fill(title_ + ts_title + "_res_loc0-vs-trk_p", trk_p,
630 track_state_loc0 - truth_state_loc0);
631 histograms_.fill(title_ + ts_title + "_res_loc1-vs-trk_p", trk_p,
632 track_state_loc1 - truth_state_loc1);
633
634 // TH2F pulls vs trk_p
635 histograms_.fill(title_ + ts_title + "_pulls_loc0-vs-trk_p", trk_p,
636 (track_state_loc0 - truth_state_loc0) / sigmaloc0);
637 histograms_.fill(title_ + ts_title + "_pulls_loc1-vs-trk_p", trk_p,
638 (track_state_loc1 - truth_state_loc1) / sigmaloc1);
639
640 } // loop on tracks
641}

References framework::HistogramPool::fill(), and framework::EventProcessor::histograms_.

Referenced by analyze().

Member Data Documentation

◆ do_truth_comparison_

bool tracking::dqm::TrackingRecoDQM::do_truth_comparison_ {false}
private

Definition at line 90 of file TrackingRecoDQM.h.

90{false};

◆ duplicate_tracks_

std::vector<ldmx::Track> tracking::dqm::TrackingRecoDQM::duplicate_tracks_
private

Definition at line 108 of file TrackingRecoDQM.h.

◆ ecal_scoring_hits_

std::shared_ptr<std::vector<ldmx::SimTrackerHit> > tracking::dqm::TrackingRecoDQM::ecal_scoring_hits_ {nullptr}
private

Definition at line 97 of file TrackingRecoDQM.h.

97{nullptr};

◆ ecal_sp_coll_name_

std::string tracking::dqm::TrackingRecoDQM::ecal_sp_coll_name_
private

Definition at line 78 of file TrackingRecoDQM.h.

◆ ecal_sp_passname_

std::string tracking::dqm::TrackingRecoDQM::ecal_sp_passname_
private

Definition at line 79 of file TrackingRecoDQM.h.

◆ fake_tracks_

std::vector<ldmx::Track> tracking::dqm::TrackingRecoDQM::fake_tracks_
private

Definition at line 110 of file TrackingRecoDQM.h.

◆ measurement_collection_

std::string tracking::dqm::TrackingRecoDQM::measurement_collection_
private

Definition at line 75 of file TrackingRecoDQM.h.

◆ measurement_passname_

std::string tracking::dqm::TrackingRecoDQM::measurement_passname_
private

Definition at line 76 of file TrackingRecoDQM.h.

◆ pidmap_

std::map<int, int> tracking::dqm::TrackingRecoDQM::pidmap_
private

Definition at line 113 of file TrackingRecoDQM.h.

◆ subdetector_

std::string tracking::dqm::TrackingRecoDQM::subdetector_ {"Tagger"}
private

Definition at line 89 of file TrackingRecoDQM.h.

89{"Tagger"};

◆ target_scoring_hits_

std::shared_ptr<std::vector<ldmx::SimTrackerHit> > tracking::dqm::TrackingRecoDQM::target_scoring_hits_
private
Initial value:
{
nullptr}

Definition at line 100 of file TrackingRecoDQM.h.

100 {
101 nullptr};

◆ target_sp_coll_name_

std::string tracking::dqm::TrackingRecoDQM::target_sp_coll_name_
private

Definition at line 80 of file TrackingRecoDQM.h.

◆ target_sp_passname_

std::string tracking::dqm::TrackingRecoDQM::target_sp_passname_
private

Definition at line 81 of file TrackingRecoDQM.h.

◆ title_

std::string tracking::dqm::TrackingRecoDQM::title_ {"tagger_trk_"}
private

Definition at line 87 of file TrackingRecoDQM.h.

87{"tagger_trk_"};

◆ track_collection_

std::string tracking::dqm::TrackingRecoDQM::track_collection_
private

Definition at line 73 of file TrackingRecoDQM.h.

◆ track_collection_events_passname_

std::string tracking::dqm::TrackingRecoDQM::track_collection_events_passname_
private

Definition at line 82 of file TrackingRecoDQM.h.

◆ track_passname_

std::string tracking::dqm::TrackingRecoDQM::track_passname_
private

Definition at line 83 of file TrackingRecoDQM.h.

◆ track_prob_cut_

double tracking::dqm::TrackingRecoDQM::track_prob_cut_ {0.5}
private

Definition at line 88 of file TrackingRecoDQM.h.

88{0.5};

◆ track_states_

std::vector<std::string> tracking::dqm::TrackingRecoDQM::track_states_
private

Definition at line 91 of file TrackingRecoDQM.h.

◆ truth_collection_

std::string tracking::dqm::TrackingRecoDQM::truth_collection_
private

Definition at line 74 of file TrackingRecoDQM.h.

◆ truth_events_passname_

std::string tracking::dqm::TrackingRecoDQM::truth_events_passname_
private

Definition at line 84 of file TrackingRecoDQM.h.

◆ truth_passname_

std::string tracking::dqm::TrackingRecoDQM::truth_passname_
private

Definition at line 85 of file TrackingRecoDQM.h.

◆ truth_track_collection_

std::shared_ptr<std::vector<ldmx::Track> > tracking::dqm::TrackingRecoDQM::truth_track_collection_ {nullptr}
private

Definition at line 94 of file TrackingRecoDQM.h.

94{nullptr};

◆ unique_tracks_

std::vector<ldmx::Track> tracking::dqm::TrackingRecoDQM::unique_tracks_
private

Definition at line 106 of file TrackingRecoDQM.h.


The documentation for this class was generated from the following files: