1#include "Tracking/Reco/TrackComparisonProcessor.h"
6#include "Framework/Logger.h"
7#include "SimCore/Event/SimParticle.h"
8#include "Tracking/Event/Track.h"
10namespace tracking::reco {
12TrackComparisonProcessor::TrackComparisonProcessor(
const std::string& name,
16void TrackComparisonProcessor::configure(
18 trk_collection_smear_ =
19 parameters.
get<std::string>(
"trk_collection_smear",
"TaggerTracks");
20 trk_collection_digi_ =
21 parameters.
get<std::string>(
"trk_collection_digi",
"TaggerDigiTracks");
22 pass_name_smear_ = parameters.
get<std::string>(
"pass_name_smear",
"");
23 pass_name_digi_ = parameters.
get<std::string>(
"pass_name_digi",
"");
24 do_tagger_ = parameters.
get<
bool>(
"do_tagger",
true);
25 do_recoil_ = parameters.
get<
bool>(
"do_recoil",
false);
26 recoil_collection_smear_ =
27 parameters.
get<std::string>(
"recoil_collection_smear",
"RecoilTracks");
28 recoil_collection_digi_ =
29 parameters.
get<std::string>(
"recoil_collection_digi",
"RecoilDigiTracks");
30 recoil_pass_smear_ = parameters.
get<std::string>(
"recoil_pass_smear",
"");
31 recoil_pass_digi_ = parameters.
get<std::string>(
"recoil_pass_digi",
"");
32 min_truth_prob_ = parameters.
get<
double>(
"min_truth_prob", 0.5);
33 sim_particles_pass_ = parameters.
get<std::string>(
"sim_particles_pass",
"");
35 parameters.
get<std::string>(
"output_file",
"track_comparison.root");
38void TrackComparisonProcessor::setupTree(TTree* tree, PairVars& v) {
39 tree->Branch(
"track_id", &v.track_id);
40 tree->Branch(
"truth_prob_s", &v.truth_prob_s);
41 tree->Branch(
"truth_prob_d", &v.truth_prob_d);
42 tree->Branch(
"nhits_s", &v.nhits_s);
43 tree->Branch(
"nhits_d", &v.nhits_d);
44 tree->Branch(
"chi2ndf_s", &v.chi2ndf_s);
45 tree->Branch(
"chi2ndf_d", &v.chi2ndf_d);
46 tree->Branch(
"d0_s", &v.d0_s);
47 tree->Branch(
"d0_d", &v.d0_d);
48 tree->Branch(
"z0_s", &v.z0_s);
49 tree->Branch(
"z0_d", &v.z0_d);
50 tree->Branch(
"phi_s", &v.phi_s);
51 tree->Branch(
"phi_d", &v.phi_d);
52 tree->Branch(
"theta_s", &v.theta_s);
53 tree->Branch(
"theta_d", &v.theta_d);
54 tree->Branch(
"qop_s", &v.qop_s);
55 tree->Branch(
"qop_d", &v.qop_d);
56 tree->Branch(
"p_s", &v.p_s);
57 tree->Branch(
"p_d", &v.p_d);
58 tree->Branch(
"delta_d0", &v.delta_d0);
59 tree->Branch(
"delta_z0", &v.delta_z0);
60 tree->Branch(
"delta_phi", &v.delta_phi);
61 tree->Branch(
"delta_theta", &v.delta_theta);
62 tree->Branch(
"delta_p_over_p", &v.delta_p_over_p);
63 tree->Branch(
"px_s", &v.px_s);
64 tree->Branch(
"py_s", &v.py_s);
65 tree->Branch(
"pz_s", &v.pz_s);
66 tree->Branch(
"px_d", &v.px_d);
67 tree->Branch(
"py_d", &v.py_d);
68 tree->Branch(
"pz_d", &v.pz_d);
69 tree->Branch(
"px_t", &v.px_t);
70 tree->Branch(
"py_t", &v.py_t);
71 tree->Branch(
"pz_t", &v.pz_t);
72 tree->Branch(
"p_t", &v.p_t);
73 tree->Branch(
"vx_t", &v.vx_t);
74 tree->Branch(
"vy_t", &v.vy_t);
75 tree->Branch(
"vz_t", &v.vz_t);
76 tree->Branch(
"delta_p_over_p_s", &v.delta_p_over_p_s);
77 tree->Branch(
"delta_p_over_p_d", &v.delta_p_over_p_d);
80void TrackComparisonProcessor::onProcessStart() {
81 file_ =
new TFile(output_file_.c_str(),
"RECREATE");
86 new TTree(
"tagger_pairs",
"Tagger smear-vs-digi track pairs");
87 tagger_tree_->SetDirectory(file_);
88 setupTree(tagger_tree_, tagger_vars_);
90 histograms_.create(
"tagger_delta_d0",
"#Delta d_{0} (digi-smear) [mm]", 200,
92 histograms_.create(
"tagger_delta_z0",
"#Delta z_{0} (digi-smear) [mm]", 200,
94 histograms_.create(
"tagger_delta_phi",
"#Delta #phi (digi-smear) [rad]",
96 histograms_.create(
"tagger_delta_theta",
"#Delta #theta (digi-smear) [rad]",
98 histograms_.create(
"tagger_delta_p_over_p",
"#Delta p/p (digi-smear)/smear",
100 histograms_.create(
"tagger_nhits_s",
"N hits (smear)", 15, 0, 15);
101 histograms_.create(
"tagger_nhits_d",
"N hits (digi)", 15, 0, 15);
102 histograms_.create(
"tagger_chi2ndf_s",
"#chi^{2}/ndf (smear)", 100, 0, 10);
103 histograms_.create(
"tagger_chi2ndf_d",
"#chi^{2}/ndf (digi)", 100, 0, 10);
104 histograms_.create(
"tagger_p_s",
"p (smear) [MeV]", 200, 0, 8000);
105 histograms_.create(
"tagger_p_d",
"p (digi) [MeV]", 200, 0, 8000);
106 histograms_.create(
"tagger_p_t",
"p (truth) [MeV]", 200, 0, 8000);
107 histograms_.create(
"tagger_delta_p_over_p_s",
108 "#Delta p/p (smear-truth)/truth", 200, -0.1, 0.1);
109 histograms_.create(
"tagger_delta_p_over_p_d",
110 "#Delta p/p (digi-truth)/truth", 200, -0.1, 0.1);
115 new TTree(
"recoil_pairs",
"Recoil smear-vs-digi track pairs");
116 recoil_tree_->SetDirectory(file_);
117 setupTree(recoil_tree_, recoil_vars_);
119 histograms_.create(
"recoil_delta_d0",
"#Delta d_{0} (digi-smear) [mm]", 200,
121 histograms_.create(
"recoil_delta_z0",
"#Delta z_{0} (digi-smear) [mm]", 200,
123 histograms_.create(
"recoil_delta_phi",
"#Delta #phi (digi-smear) [rad]",
125 histograms_.create(
"recoil_delta_theta",
"#Delta #theta (digi-smear) [rad]",
127 histograms_.create(
"recoil_delta_p_over_p",
"#Delta p/p (digi-smear)/smear",
129 histograms_.create(
"recoil_nhits_s",
"N hits (smear)", 15, 0, 15);
130 histograms_.create(
"recoil_nhits_d",
"N hits (digi)", 15, 0, 15);
131 histograms_.create(
"recoil_chi2ndf_s",
"#chi^{2}/ndf (smear)", 100, 0, 10);
132 histograms_.create(
"recoil_chi2ndf_d",
"#chi^{2}/ndf (digi)", 100, 0, 10);
133 histograms_.create(
"recoil_p_s",
"p (smear) [MeV]", 200, 0, 8000);
134 histograms_.create(
"recoil_p_d",
"p (digi) [MeV]", 200, 0, 8000);
135 histograms_.create(
"recoil_p_t",
"p (truth) [MeV]", 200, 0, 8000);
136 histograms_.create(
"recoil_delta_p_over_p_s",
137 "#Delta p/p (smear-truth)/truth", 200, -0.4, 0.4);
138 histograms_.create(
"recoil_delta_p_over_p_d",
139 "#Delta p/p (digi-truth)/truth", 200, -0.4, 0.4);
143void TrackComparisonProcessor::fillPair(
const ldmx::Track& smear,
147 const std::string& prefix) {
148 v.track_id = smear.getTrackID();
149 v.truth_prob_s = smear.getTruthProb();
150 v.truth_prob_d = digi.getTruthProb();
151 v.nhits_s = smear.getNhits();
152 v.nhits_d = digi.getNhits();
153 v.chi2ndf_s = (smear.getNdf() > 0) ? smear.getChi2() / smear.getNdf() : -1;
154 v.chi2ndf_d = (digi.getNdf() > 0) ? digi.getChi2() / digi.getNdf() : -1;
155 v.d0_s = smear.getD0();
156 v.d0_d = digi.getD0();
157 v.z0_s = smear.getZ0();
158 v.z0_d = digi.getZ0();
159 v.phi_s = smear.getPhi();
160 v.phi_d = digi.getPhi();
161 v.theta_s = smear.getTheta();
162 v.theta_d = digi.getTheta();
163 v.qop_s = smear.getQoP();
164 v.qop_d = digi.getQoP();
167 v.p_s = (v.qop_s != 0) ? std::abs(1000.0 / v.qop_s) : -1;
168 v.p_d = (v.qop_d != 0) ? std::abs(1000.0 / v.qop_d) : -1;
169 v.delta_d0 = v.d0_d - v.d0_s;
170 v.delta_z0 = v.z0_d - v.z0_s;
171 v.delta_phi = v.phi_d - v.phi_s;
172 v.delta_theta = v.theta_d - v.theta_s;
173 v.delta_p_over_p = (v.p_s > 0) ? (v.p_d - v.p_s) / v.p_s : -999;
176 if (mom_s.size() == 3) {
182 if (mom_d.size() == 3) {
192 v.p_t = std::sqrt(v.px_t * v.px_t + v.py_t * v.py_t + v.pz_t * v.pz_t);
198 v.delta_p_over_p_s = (v.p_t > 0) ? (v.p_s - v.p_t) / v.p_t : -999;
199 v.delta_p_over_p_d = (v.p_t > 0) ? (v.p_d - v.p_t) / v.p_t : -999;
201 histograms_.fill(prefix +
"delta_d0", v.delta_d0);
202 histograms_.fill(prefix +
"delta_z0", v.delta_z0);
203 histograms_.fill(prefix +
"delta_phi", v.delta_phi);
204 histograms_.fill(prefix +
"delta_theta", v.delta_theta);
205 histograms_.fill(prefix +
"delta_p_over_p", v.delta_p_over_p);
206 histograms_.fill(prefix +
"nhits_s", v.nhits_s);
207 histograms_.fill(prefix +
"nhits_d", v.nhits_d);
208 histograms_.fill(prefix +
"chi2ndf_s", v.chi2ndf_s);
209 histograms_.fill(prefix +
"chi2ndf_d", v.chi2ndf_d);
210 histograms_.fill(prefix +
"p_s", v.p_s);
211 histograms_.fill(prefix +
"p_d", v.p_d);
212 histograms_.fill(prefix +
"p_t", v.p_t);
213 histograms_.fill(prefix +
"delta_p_over_p_s", v.delta_p_over_p_s);
214 histograms_.fill(prefix +
"delta_p_over_p_d", v.delta_p_over_p_d);
218 const std::string& coll_smear,
219 const std::string& pass_smear,
220 const std::string& coll_digi,
221 const std::string& pass_digi,
222 TTree* tree, PairVars& vars,
223 const std::string& histo_prefix) {
224 if (!event.
exists(coll_smear, pass_smear)) {
225 ldmx_log(warn) <<
"Smear collection " << coll_smear <<
" not found";
228 if (!event.
exists(coll_digi, pass_digi)) {
229 ldmx_log(warn) <<
"Digi collection " << coll_digi <<
" not found";
233 const auto& tracks_smear =
234 event.getCollection<
ldmx::Track>(coll_smear, pass_smear);
235 const auto& tracks_digi =
236 event.getCollection<
ldmx::Track>(coll_digi, pass_digi);
238 const auto& particle_map =
241 std::map<int, const ldmx::Track*> smear_by_id;
242 for (
const auto& t : tracks_smear) {
243 if (t.getTruthProb() >= min_truth_prob_) smear_by_id[t.getTrackID()] = &t;
246 for (
const auto& t : tracks_digi) {
247 if (t.getTruthProb() < min_truth_prob_)
continue;
248 auto it = smear_by_id.find(t.getTrackID());
249 if (it == smear_by_id.end())
continue;
250 auto pit = particle_map.find(t.getTrackID());
251 if (pit == particle_map.end())
continue;
253 fillPair(*it->second, t, pit->second, vars, histo_prefix);
260 processTracker(event, trk_collection_smear_, pass_name_smear_,
261 trk_collection_digi_, pass_name_digi_, tagger_tree_,
262 tagger_vars_,
"tagger_");
265 processTracker(event, recoil_collection_smear_, recoil_pass_smear_,
266 recoil_collection_digi_, recoil_pass_digi_, recoil_tree_,
267 recoil_vars_,
"recoil_");
271void TrackComparisonProcessor::onProcessEnd() {
273 if (tagger_tree_) tagger_tree_->Write(
"", TObject::kOverwrite);
274 if (recoil_tree_) recoil_tree_->Write(
"", TObject::kOverwrite);
#define DECLARE_ANALYZER(CLASS)
Macro which allows the framework to construct an analyzer given its name during configuration.
Implements an event buffer system for storing event data.
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.
Class which represents the process under execution.
Class encapsulating parameters for configuring a processor.
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Class representing a simulated particle.
std::vector< double > getVertex() const
Get a vector containing the vertex of this particle in mm.
std::vector< double > getMomentum() const
Get a vector containing the momentum of this particle [MeV].
Implementation of a track object.
std::vector< double > getMomentumAtTarget() const
Returns the momentum (px, py, pz) in MeV in the LDMX global frame from the AtTarget TrackState.
Compares tracking performance between a truth-smeared hit chain and a charge-digitized hit chain on a...
All classes in the ldmx-sw project use this namespace.