LDMX Software
TrackDeDxMassEstimator.cxx
1// LDMX
3
5
6// STL
7#include <algorithm> // for std::transform
8#include <cctype> // for ::tolower
9#include <cmath>
10
12#include "Tracking/Event/Track.h"
13
14namespace recon {
15
17 fit_res_c_ = ps.get<double>("fit_res_c");
18 fit_res_k_ = ps.get<double>("fit_res_k");
19 input_pass_name_ = ps.get<std::string>("input_pass_name");
20 track_collection_ = ps.get<std::string>("track_collection");
21 out_collection_ = ps.get<std::string>("out_collection");
22
23 ldmx_log(info) << "Track Collection used for TrackDeDxMassEstimator "
24 << track_collection_;
25}
26
28 std::vector<ldmx::TrackDeDxMassEstimate> mass_estimates;
29
30 if (!event.exists(track_collection_, input_pass_name_)) {
31 ldmx_log(error) << "Track collection " << track_collection_ << "_"
32 << input_pass_name_ << " not in event, exiting...";
33 event.add(out_collection_, mass_estimates);
34 return;
35 }
36 const std::vector<ldmx::Track> tracks{
37 event.getCollection<ldmx::Track>(track_collection_, input_pass_name_)};
38
39 int track_type;
40 std::string track_coll_str = track_collection_;
41 std::transform(track_coll_str.begin(), track_coll_str.end(),
42 track_coll_str.begin(), ::tolower);
43
44 bool is_truth = track_coll_str.find("truth") != std::string::npos;
45
46 if (is_truth) {
47 if (track_coll_str.find("tagger") != std::string::npos) {
48 track_type = 1;
49 simhit_collection_ = "TaggerSimHits";
50 } else if (track_coll_str.find("recoil") != std::string::npos) {
51 track_type = 2;
52 simhit_collection_ = "RecoilSimHits";
53 } else {
54 track_type = 0;
55 simhit_collection_ = "";
56 }
57 } else {
58 // Reco tracks (e.g. RecoilTracks, RecoilTracksClean)
59 track_type = 4;
60 simhit_collection_ = "";
61 }
62
63 // Retrieve simhits only for truth tracks
64 std::vector<ldmx::SimTrackerHit> simhits;
65 if (is_truth) {
66 if (!event.exists(simhit_collection_, input_pass_name_)) {
67 ldmx_log(error) << " SimHit collection (" << simhit_collection_ << "_"
68 << input_pass_name_ << ") does not exists, exiting...";
69 event.add(out_collection_, mass_estimates);
70 return;
71 }
72 simhits = event.getCollection<ldmx::SimTrackerHit>(simhit_collection_,
73 input_pass_name_);
74 }
75
76 // Loop over the collection of tracks
77 for (uint i = 0; i < tracks.size(); i++) {
78 auto track = tracks.at(i);
79 // If track momentum doen't exist, skip
80 auto the_qop = track.getQoP();
81 if (the_qop == 0) {
82 ldmx_log(debug) << "Track " << i << "has zero q/p ";
83 continue;
84 }
85
86 int pdg_id = track.getPdgID();
87 float momentum = 1. / std::abs(the_qop) * 1000; // unit: MeV
88 ldmx_log(debug) << "Track " << i << " has momentum " << momentum;
89
91 float sum_dedx_inv2 = 0.;
92 float dedx;
93 int n_hits = 0;
94
95 if (is_truth) {
96 // Use simhits associated with the truth track
97 for (auto hit : simhits) {
98 if (hit.getTrackID() != track.getTrackID()) continue;
99 if (hit.getEdep() >= 0 && hit.getPathLength() > 0) {
100 dedx = hit.getEdep() / hit.getPathLength() * 10; // unit: MeV/cm
101 sum_dedx_inv2 += 1. / (dedx * dedx);
102 n_hits++;
103 }
104 }
105 } else {
106 // Use dE/dx measurements stored on the reco track (in MeV/mm)
107 for (auto dedx_meas : track.getDedxMeasurements()) {
108 if (dedx_meas > 0) {
109 dedx = dedx_meas * 10; // convert MeV/mm to MeV/cm
110 sum_dedx_inv2 += 1. / (dedx * dedx);
111 n_hits++;
112 }
113 }
114 } // end of loop over measurements
115
116 if (sum_dedx_inv2 == 0) {
117 ldmx_log(debug) << "Track " << i << " has no dEdx measurements";
118 continue;
119 }
120
121 // Ih = (1/N * sum_i^N(dE/dx_i)^-2)^-1/2
122 float the_ih = 1. / sqrt(1. / n_hits * sum_dedx_inv2);
123 // m^2 = (Ih - C) p^2 / K [MeV^2], for every track, negative when Ih < C
124 float mass2 = (the_ih - fit_res_c_) * momentum * momentum / fit_res_k_;
125
126 float mass = 0.;
127 if (the_ih > fit_res_c_) {
128 mass = momentum * sqrt((the_ih - fit_res_c_) / fit_res_k_);
129 } else {
130 ldmx_log(info) << "Track " << i << " has Ih " << the_ih
131 << " which is less than fit_res_C " << fit_res_c_;
132 mass = -100.;
133 }
134
135 mass_est.setMomentum(momentum);
136 mass_est.setNhits(n_hits);
137 mass_est.setIh(the_ih);
138 mass_est.setMass(mass);
139 mass_est.setMassSquared(mass2);
140 mass_est.setTrackIndex(i);
141 mass_est.setTrackType(track_type);
142 mass_est.setPdgId(pdg_id);
143 mass_estimates.push_back(mass_est);
144 }
145
146 // Add the mass estimates to the event
147 event.add(out_collection_, mass_estimates);
148}
149} // namespace recon
150
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Class which encapsulates information from a hit in a simulated tracking detector.
Class that represents the estimated mass of a particle using tracker dE/dx information.
Class that estimates the mass of a particle using tracker dE/dx information.
Implements an event buffer system for storing event data.
Definition Event.h:40
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:107
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:26
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
Represents a simulated tracker hit in the simulation.
Represents the estimated mass of a particle using tracker dE/dx information.
void setNhits(int nhits)
Set the number of hits used in the dEdx calculation.
void setTrackType(int track_type)
Set the type of the track.
void setMassSquared(float mass_squared)
Set the estimated mass squared of the particle/track.
void setPdgId(int pdg_id)
Set the PDG ID of the track.
void setIh(float the_ih)
Set the Ih of the particle/track.
void setMomentum(float momentum)
Set the momentum of the particle/track.
void setMass(float mass)
Set the estimated mass of the particle/track.
void setTrackIndex(int track_index)
Set the index of the track.
Implementation of a track object.
Definition Track.h:54
virtual void produce(framework::Event &event) override
Process the event and put new data products into it.
virtual void configure(framework::config::Parameters &ps) override
Callback for the EventProcessor to configure itself from the given set of parameters.