8#include "Tracking/Event/Track.h"
13 truth_tracking_ = ps.
get<
bool>(
"truth_tracking");
14 input_track_coll_name_ = ps.
get<std::string>(
"input_track_coll_name");
15 input_pass_name_ = ps.
get<std::string>(
"input_pass_name");
16 output_track_coll_name_ = ps.
get<std::string>(
"output_track_coll_name");
17 do_electron_tracking_ = ps.
get<
bool>(
"do_electron_tracking");
18 min_electron_momentum_z_ = ps.
get<
double>(
"min_electron_momentum_z");
19 max_electron_track_id_ = ps.
get<
int>(
"max_electron_track_id");
20 reco_track_coll_name_ = ps.
get<std::string>(
"reco_track_coll_name");
21 reco_track_pass_name_ = ps.
get<std::string>(
"reco_track_pass_name");
22 min_n_hits_ = ps.
get<
int>(
"min_n_hits");
23 max_chi2_ndf_ = ps.
get<
double>(
"max_chi2_ndf");
24 min_momentum_ = ps.
get<
double>(
"min_momentum");
25 max_shared_frac_ = ps.
get<
double>(
"max_shared_frac");
30double getP(
const std::vector<double>& pxyz) {
31 return sqrt(pow(pxyz[0], 2) + pow(pxyz[1], 2) + pow(pxyz[2], 2));
36 return pxyz.empty() ? 0. : getP(pxyz);
40int chargeFromPdg(
int pdg) {
41 int sign = pdg > 0 ? 1 : -1;
42 switch (std::abs(pdg)) {
60 ts.pos_ = {xyz[0], xyz[1], xyz[2]};
62 ts.ts_type_ = ldmx::AtECAL;
67 tk.setCharge(chargeFromPdg(sp_hit.
getPdgID()));
82 if (!event.
exists(input_track_coll_name_, input_pass_name_)) {
83 ldmx_log(fatal) <<
"Couldn't find input collection "
84 << input_track_coll_name_ <<
"_" << input_pass_name_;
88 input_track_coll_name_, input_pass_name_);
90 std::vector<ldmx::Track> pf_tracks;
91 for (
const auto& sp_hit : ecal_sp_hits) {
93 if (fabs(240 - sp_hit.
getPosition()[2]) > 0.1)
continue;
94 if (do_electron_tracking_) {
95 if (sp_hit.
getPdgID() != 11)
continue;
97 sp_hit.
getMomentum()[2] > min_electron_momentum_z_) {
99 pf_tracks.push_back(trackFromSPHit(sp_hit));
100 ldmx_log(debug) <<
"Added beam electron SP hit: trackID="
103 }
else if (sp_hit.
getTrackID() <= max_electron_track_id_ &&
107 pf_tracks.push_back(trackFromSPHit(sp_hit));
108 ldmx_log(debug) <<
"Adding SP hit: trackID=" << sp_hit.
getTrackID()
116 pf_tracks.push_back(trackFromSPHit(sp_hit));
117 ldmx_log(debug) <<
"Adding SP hit: trackID=" << sp_hit.
getTrackID()
123 std::sort(pf_tracks.begin(), pf_tracks.end(),
125 return getP(a) > getP(b);
127 event.add(output_track_coll_name_, pf_tracks);
131 if (!event.
exists(reco_track_coll_name_, reco_track_pass_name_)) {
132 ldmx_log(fatal) <<
"Couldn't find input collection "
133 << reco_track_coll_name_ <<
"_" << reco_track_pass_name_;
136 const auto tracks =
event.getCollection<
ldmx::Track>(reco_track_coll_name_,
137 reco_track_pass_name_);
140 std::vector<const ldmx::Track*> ranked;
141 for (
const auto& tk : tracks) ranked.push_back(&tk);
143 return t->getNdf() > 0 ? t->getChi2() / t->getNdf() : 9e9;
145 std::stable_sort(ranked.begin(), ranked.end(), [&](
auto a,
auto b) {
146 if (a->getNhits() != b->getNhits()) return a->getNhits() > b->getNhits();
147 return chi2ndf(a) < chi2ndf(b);
150 std::vector<ldmx::Track> pf_tracks;
151 std::vector<std::set<unsigned int>> used_hits;
152 for (
const auto* tk_ptr : ranked) {
153 const auto& tk = *tk_ptr;
157 ldmx_log(debug) <<
"Dropping track without AtECAL state";
160 if (mom[2] <= 0)
continue;
161 if (tk.getNhits() < min_n_hits_)
continue;
162 if (max_chi2_ndf_ >= 0 &&
163 (tk.getNdf() <= 0 || tk.getChi2() / tk.getNdf() > max_chi2_ndf_))
165 if (getP(mom) < min_momentum_)
continue;
167 auto idxs = tk.getMeasurementsIdxs();
168 std::set<unsigned int> hits(idxs.begin(), idxs.end());
169 bool duplicate =
false;
170 for (
const auto& prev : used_hits) {
172 for (
auto h : hits) n_shared += prev.count(h);
173 if (!hits.empty() && n_shared > max_shared_frac_ * hits.size()) {
178 if (duplicate)
continue;
179 used_hits.push_back(hits);
180 pf_tracks.push_back(tk);
181 ldmx_log(debug) <<
"Adding track: nhits=" << tk.getNhits()
182 <<
", p = " << getP(mom) <<
", trackID=" << tk.getTrackID();
184 std::sort(pf_tracks.begin(), pf_tracks.end(),
186 return getP(a) > getP(b);
188 event.add(output_track_coll_name_, pf_tracks);
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Track selection for PFlow Reco.
Class which encapsulates information from a hit in a simulated tracking detector.
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 encapsulating parameters for configuring a processor.
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Represents a simulated tracker hit in the simulation.
int getPdgID() const
Get the Sim particle track ID of the hit.
std::vector< float > getPosition() const
Get the XYZ position of the hit [mm].
std::vector< double > getMomentum() const
Get the XYZ momentum of the particle at the position at which the hit took place [MeV].
int getTrackID() const
Get the Sim particle track ID of the hit.
Implementation of a track object.
std::vector< double > getMomentum(TrackStateType tstype) const
Returns the momentum (px, py, pz) in MeV in the LDMX global frame for the requested TrackState type.
Selects the tracks passed to ParticleFlow.
virtual void produce(framework::Event &event)
Process the event and put new data products into it.
virtual void configure(framework::config::Parameters &ps)
Callback for the EventProcessor to configure itself from the given set of parameters.