LDMX Software
recon::ParticleFlow Class Reference

Public Member Functions

 ParticleFlow (const std::string &name, framework::Process &process)
 
virtual void configure (framework::config::Parameters &ps)
 Callback for the EventProcessor to configure itself from the given set of parameters.
 
virtual void produce (framework::Event &event)
 Process the event and put new data products into it.
 
virtual void onProcessEnd ()
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
void fillCandTrack (ldmx::PFCandidate &cand, const ldmx::Track &tk, const std::vector< ldmx::SimTrackerHit > &sp_hits)
 
void fillCandEMCalo (ldmx::PFCandidate &cand, const ldmx::CaloCluster &em)
 
void fillCandHadCalo (ldmx::PFCandidate &cand, const ldmx::CaloCluster &had)
 
void identifyCharged (ldmx::PFCandidate &cand) const
 
std::vector< ldmx::CaloCluster > linkHcalClusters (const std::vector< ldmx::CaloCluster > &clusters) const
 
double ecalDepth (const ldmx::CaloCluster &cl) const
 
double ecalWidth (const ldmx::CaloCluster &cl, const ldmx::Track &tk) const
 
void absorbHadronShower (ldmx::PFCandidate &cand, const ldmx::Track &tk, const std::vector< ldmx::CaloCluster > &ecal, std::vector< bool > &ecal_used, const std::vector< ldmx::CaloCluster > &hcal, std::vector< bool > &hcal_used) const
 
int linkTrackHcal (const ldmx::Track &tk, const std::vector< ldmx::CaloCluster > &clusters, const std::vector< bool > &used) const
 
void recoverEcal (ldmx::PFCandidate &cand, const ldmx::Track &tk, const std::vector< ldmx::CaloCluster > &clusters, std::vector< bool > &used) const
 
double trackClusterDist (const std::vector< double > &xyz, const std::vector< double > &pxyz, const ldmx::CaloCluster &cl) const
 
std::vector< ldmx::CaloCluster > linkEcalClusters (const std::vector< ldmx::CaloCluster > &clusters, const std::vector< ldmx::Track > &tracks) const
 
- Public Member Functions inherited from framework::Producer
 Producer (const std::string &name, Process &process)
 Class constructor.
 
virtual void process (Event &event) final
 Processing an event for a Producer is calling produce.
 
- 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 beforeNewRun (ldmx::RunHeader &run_header)
 Callback for Producers to add parameters to the run header before conditions are initialized.
 
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.
 

Static Public Member Functions

static ldmx::CaloCluster mergeClusters (const std::vector< ldmx::CaloCluster > &clusters, int root, const std::vector< int > &members)
 

Private Member Functions

const std::vector< ldmx::CaloCluster > getEcalClusters (framework::Event &event, std::string inputClusterCollName, std::string inputClusterPassName)
 

Static Private Member Functions

static double correction (const std::vector< double > &energies, const std::vector< double > &factors, double energy)
 

Private Attributes

std::vector< double > ecal_corr_energies_
 
std::vector< double > ecal_corr_factors_
 
std::vector< double > hcal_corr_energies_
 
std::vector< double > hcal_corr_factors_
 
std::string input_ecal_coll_name_
 
std::string input_hcal_coll_name_
 
std::string input_track_coll_name_
 
std::string input_ecal_passname_
 
std::string input_hcal_passname_
 
std::string input_tracks_passname_
 
std::string truth_sp_coll_name_
 
std::string truth_sp_passname_
 
bool use_existing_ecal_clusters_
 
std::string output_coll_name_
 
bool single_particle_
 
std::string input_mass_coll_name_
 
std::string input_mass_passname_
 
double link_max_dist_ {}
 
double link_min_rms_ {}
 
double electron_ep_min_ {}
 
double excess_ep_ {}
 
double proton_min_mass2_ {}
 
double kaon_min_mass2_ {}
 
double proton_max_p_ {}
 
double kaon_max_p_ {}
 
double recovery_radius_ {}
 
double recovery_stop_ep_ {}
 
double hcal_merge_angle_ {}
 
double hcal_track_angle_ {}
 
double hadron_ecal_radius_ {}
 
double hadron_absorb_ep_ {}
 
double min_neutral_e_ {}
 
double ecal_front_z_ {}
 
double electron_max_depth_ {}
 
double electron_depth_slope_ {}
 
double ecal_link_radius_ {}
 
double ecal_link_ratio_ {}
 
int ecal_link_min_layers_ {}
 
double photon_keep_min_e_ {}
 
double photon_keep_min_dist_ {}
 
double photon_keep_max_zstart_ {}
 
int dedx_min_hits_ {}
 

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
 
NtupleManager & ntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger the_log_
 The logger for this EventProcessor.
 

Detailed Description

Definition at line 25 of file ParticleFlow.h.

Constructor & Destructor Documentation

◆ ParticleFlow()

recon::ParticleFlow::ParticleFlow ( const std::string & name,
framework::Process & process )
inline

Definition at line 27 of file ParticleFlow.h.

Base class for a module which produces a data product.
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.

Member Function Documentation

◆ absorbHadronShower()

void recon::ParticleFlow::absorbHadronShower ( ldmx::PFCandidate & cand,
const ldmx::Track & tk,
const std::vector< ldmx::CaloCluster > & ecal,
std::vector< bool > & ecal_used,
const std::vector< ldmx::CaloCluster > & hcal,
std::vector< bool > & hcal_used ) const

Definition at line 356 of file ParticleFlow.cxx.

360 {
361 auto ts = tk.getTrackState(ldmx::AtECAL);
362 if (hadron_absorb_ep_ <= 0 || !ts || ts->mom_.size() < 3 || ts->mom_[2] <= 0)
363 return;
364 const auto& pos = ts->pos_;
365 const auto& mom = ts->mom_;
366 double pm = std::hypot(mom[0], mom[1], mom[2]);
367 double budget = hadron_absorb_ep_ * pm;
368 double calo = cand.getEcalEnergy() + cand.getHcalEnergy();
369
370 // (distance key, is_hcal, index), Ecal in mm and Hcal in angle scaled to mm
371 std::vector<std::tuple<double, bool, int>> near;
372 for (int j = 0; j < static_cast<int>(ecal.size()); j++) {
373 if (ecal_used[j]) continue;
374 double z = ecal[j].getCentroidZ();
375 double d = std::hypot(
376 pos[0] + mom[0] / mom[2] * (z - pos[2]) - ecal[j].getCentroidX(),
377 pos[1] + mom[1] / mom[2] * (z - pos[2]) - ecal[j].getCentroidY());
378 if (d < hadron_ecal_radius_) near.emplace_back(d, false, j);
379 }
380 double cos_max = std::cos(hcal_track_angle_ * M_PI / 180.);
381 for (int j = 0; j < static_cast<int>(hcal.size()); j++) {
382 if (hcal_used[j]) continue;
383 double dx = hcal[j].getCentroidX() - pos[0];
384 double dy = hcal[j].getCentroidY() - pos[1];
385 double dz = hcal[j].getCentroidZ() - pos[2];
386 double cs = (dx * mom[0] + dy * mom[1] + dz * mom[2]) /
387 (pm * std::hypot(dx, dy, dz));
388 if (cs > cos_max) {
389 // rank Hcal after nearby Ecal pieces, by angle
390 double ang = std::acos(std::min(1., cs)) * 180. / M_PI;
391 near.emplace_back(hadron_ecal_radius_ + ang, true, j);
392 }
393 }
394 std::sort(near.begin(), near.end());
395 for (const auto& [d, is_hcal, j] : near) {
396 const auto& cl = is_hcal ? hcal[j] : ecal[j];
397 double raw = cl.getEnergy();
398 double e =
399 raw * (is_hcal
400 ? correction(hcal_corr_energies_, hcal_corr_factors_, raw)
401 : correction(ecal_corr_energies_, ecal_corr_factors_, raw));
402 if (calo + e > budget) continue;
403 calo += e;
404 if (is_hcal) {
405 cand.setHcalEnergy(cand.getHcalEnergy() + e);
406 cand.setHcalRawEnergy(cand.getHcalRawEnergy() + raw);
407 cand.addHcalHits(cl.getHitIDs(), cl.getHitE());
408 cand.setPID(cand.getPID() | 4);
409 hcal_used[j] = true;
410 } else {
411 cand.setEcalEnergy(cand.getEcalEnergy() + e);
412 cand.setEcalRawEnergy(cand.getEcalRawEnergy() + raw);
413 cand.addEcalHits(cl.getHitIDs(), cl.getHitE());
414 ecal_used[j] = true;
415 }
416 }
417}

◆ configure()

void recon::ParticleFlow::configure ( framework::config::Parameters & parameters)
virtual

Callback for the EventProcessor to configure itself from the given set of parameters.

The parameters a processor has access to are the member variables of the python class in the sequence that has class_name equal to the EventProcessor class name.

For an example, look at MyProcessor.

Parameters
parametersParameters for configuration.

Reimplemented from framework::EventProcessor.

Definition at line 17 of file ParticleFlow.cxx.

17 {
18 // I/O
19 input_ecal_coll_name_ = ps.get<std::string>("input_ecal_coll_name");
20 input_hcal_coll_name_ = ps.get<std::string>("input_hcal_coll_name");
21 input_track_coll_name_ = ps.get<std::string>("input_track_coll_name");
22 output_coll_name_ = ps.get<std::string>("output_coll_name");
23 input_ecal_passname_ = ps.get<std::string>("input_ecal_passname");
24 input_hcal_passname_ = ps.get<std::string>("input_hcal_passname");
25 input_tracks_passname_ = ps.get<std::string>("input_tracks_passname");
26 truth_sp_coll_name_ = ps.get<std::string>("truth_sp_coll_name");
27 truth_sp_passname_ = ps.get<std::string>("truth_sp_passname");
28
29 // Algorithm configuration
30 single_particle_ = ps.get<bool>("single_particle");
31 use_existing_ecal_clusters_ = ps.get<bool>("use_existing_ecal_clusters");
32 input_mass_coll_name_ = ps.get<std::string>("input_mass_coll_name");
33 input_mass_passname_ = ps.get<std::string>("input_mass_passname");
34 link_max_dist_ = ps.get<double>("link_max_dist");
35 electron_ep_min_ = ps.get<double>("electron_ep_min");
36 link_min_rms_ = ps.get<double>("link_min_rms");
37 excess_ep_ = ps.get<double>("excess_ep");
38 proton_min_mass2_ = ps.get<double>("proton_min_mass2");
39 kaon_min_mass2_ = ps.get<double>("kaon_min_mass2");
40 proton_max_p_ = ps.get<double>("proton_max_p");
41 kaon_max_p_ = ps.get<double>("kaon_max_p");
42 recovery_radius_ = ps.get<double>("recovery_radius");
43 hcal_merge_angle_ = ps.get<double>("hcal_merge_angle");
44 hcal_track_angle_ = ps.get<double>("hcal_track_angle");
45 hadron_ecal_radius_ = ps.get<double>("hadron_ecal_radius");
46 hadron_absorb_ep_ = ps.get<double>("hadron_absorb_ep");
47 min_neutral_e_ = ps.get<double>("min_neutral_e");
48 ecal_front_z_ = ps.get<double>("ecal_front_z");
49 electron_max_depth_ = ps.get<double>("electron_max_depth");
50 electron_depth_slope_ = ps.get<double>("electron_depth_slope");
51 recovery_stop_ep_ = ps.get<double>("recovery_stop_ep");
52 ecal_link_radius_ = ps.get<double>("ecal_link_radius");
53 ecal_link_ratio_ = ps.get<double>("ecal_link_ratio");
54 ecal_link_min_layers_ = ps.get<int>("ecal_link_min_layers");
55 photon_keep_min_e_ = ps.get<double>("photon_keep_min_e");
56 photon_keep_min_dist_ = ps.get<double>("photon_keep_min_dist");
57 photon_keep_max_zstart_ = ps.get<double>("photon_keep_max_zstart");
58 dedx_min_hits_ = ps.get<int>("dedx_min_hits");
59
60 // energy correction tables, empty means no correction
61 ecal_corr_energies_ = ps.get<std::vector<double>>("ecal_corr_energies", {});
62 ecal_corr_factors_ = ps.get<std::vector<double>>("ecal_corr_factors", {});
63 hcal_corr_energies_ = ps.get<std::vector<double>>("hcal_corr_energies", {});
64 hcal_corr_factors_ = ps.get<std::vector<double>>("hcal_corr_factors", {});
65 for (const auto& [x, y] :
66 {std::pair{&ecal_corr_energies_, &ecal_corr_factors_},
67 std::pair{&hcal_corr_energies_, &hcal_corr_factors_}}) {
68 if (x->size() != y->size() || !std::is_sorted(x->begin(), x->end())) {
69 EXCEPTION_RAISE("InvalidArg",
70 "Correction energies must be sorted and match factors");
71 }
72 }
73}

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

◆ correction()

double recon::ParticleFlow::correction ( const std::vector< double > & energies,
const std::vector< double > & factors,
double energy )
staticprivate

Definition at line 76 of file ParticleFlow.cxx.

78 {
79 if (energies.empty()) return 1.;
80 if (energy <= energies.front()) return factors.front();
81 if (energy >= energies.back()) return factors.back();
82 auto hi = std::upper_bound(energies.begin(), energies.end(), energy);
83 size_t i = hi - energies.begin();
84 double t = (energy - energies[i - 1]) / (energies[i] - energies[i - 1]);
85 return factors[i - 1] + t * (factors[i] - factors[i - 1]);
86}

◆ ecalDepth()

double recon::ParticleFlow::ecalDepth ( const ldmx::CaloCluster & cl) const

Definition at line 442 of file ParticleFlow.cxx.

442 {
443 const auto& hz = cl.getHitZ();
444 const auto& he = cl.getHitE();
445 double e = 0, ez = 0;
446 for (size_t k = 0; k < hz.size() && k < he.size(); k++) {
447 e += he[k];
448 ez += he[k] * hz[k];
449 }
450 return (e > 0 ? ez / e : cl.getCentroidZ()) - ecal_front_z_;
451}
double getCentroidZ() const
centroid z-location

◆ ecalWidth()

double recon::ParticleFlow::ecalWidth ( const ldmx::CaloCluster & cl,
const ldmx::Track & tk ) const

Definition at line 421 of file ParticleFlow.cxx.

422 {
423 auto ts = tk.getTrackState(ldmx::AtECAL);
424 if (!ts || ts->mom_.size() < 3 || ts->mom_[2] <= 0) return 0.;
425 const auto& pos = ts->pos_;
426 const auto& mom = ts->mom_;
427 const auto& hx = cl.getHitX();
428 const auto& hy = cl.getHitY();
429 const auto& hz = cl.getHitZ();
430 const auto& he = cl.getHitE();
431 double e = 0, er2 = 0;
432 for (size_t k = 0; k < he.size() && k < hz.size(); k++) {
433 double x = pos[0] + mom[0] / mom[2] * (hz[k] - pos[2]);
434 double y = pos[1] + mom[1] / mom[2] * (hz[k] - pos[2]);
435 e += he[k];
436 er2 += he[k] * (std::pow(hx[k] - x, 2) + std::pow(hy[k] - y, 2));
437 }
438 return e > 0 ? std::sqrt(er2 / e) : 0.;
439}

◆ fillCandEMCalo()

void recon::ParticleFlow::fillCandEMCalo ( ldmx::PFCandidate & cand,
const ldmx::CaloCluster & em )

Definition at line 134 of file ParticleFlow.cxx.

135 {
136 float energy = em.getEnergy();
137 float corr = correction(ecal_corr_energies_, ecal_corr_factors_, energy);
138 cand.setEcalEnergy(energy * corr);
139 cand.setEcalRawEnergy(energy);
140 cand.setEcalClusterXYZ(em.getCentroidX(), em.getCentroidY(),
141 em.getCentroidZ());
142 cand.setEcalClusterEXYZ(em.getRMSX(), em.getRMSY(), em.getRMSZ());
143 cand.setEcalClusterDXDZ(em.getDXDZ());
144 cand.setEcalClusterDYDZ(em.getDYDZ());
145 cand.setEcalClusterEDXDZ(em.getEDXDZ());
146 cand.setEcalClusterEDYDZ(em.getEDYDZ());
147 cand.setEcalDepth(ecalDepth(em));
148 cand.clearEcalHits();
149 cand.addEcalHits(em.getHitIDs(), em.getHitE());
150 cand.setPID(cand.getPID() | 2); // OR with 010
151}
double getRMSX() const
rms in x
double getDYDZ() const
Delta in y-z plane.
double getCentroidX() const
centroid x-location
double getRMSZ() const
rms in z
double getRMSY() const
rms in y
double getCentroidY() const
centroid y-location
double getEDXDZ() const
Delta unc on unc in x-z plane.
double getDXDZ() const
Delta in x-z plane.
double getEDYDZ() const
Delta unc on unc in y-z plane.

◆ fillCandHadCalo()

void recon::ParticleFlow::fillCandHadCalo ( ldmx::PFCandidate & cand,
const ldmx::CaloCluster & had )

Definition at line 153 of file ParticleFlow.cxx.

154 {
155 float energy = had.getEnergy();
156 float corr = correction(hcal_corr_energies_, hcal_corr_factors_, energy);
157 cand.setHcalEnergy(energy * corr);
158 cand.setHcalRawEnergy(energy);
159 cand.clearHcalHits();
160 cand.addHcalHits(had.getHitIDs(), had.getHitE());
161 cand.setHcalClusterXYZ(had.getCentroidX(), had.getCentroidY(),
162 had.getCentroidZ());
163 cand.setHcalClusterEXYZ(had.getRMSX(), had.getRMSY(), had.getRMSZ());
164 cand.setHcalClusterDXDZ(had.getDXDZ());
165 cand.setHcalClusterDYDZ(had.getDYDZ());
166 cand.setHcalClusterEDXDZ(had.getEDXDZ());
167 cand.setHcalClusterEDYDZ(had.getEDYDZ());
168 cand.setPID(cand.getPID() | 4); // OR with 100
169}

◆ fillCandTrack()

void recon::ParticleFlow::fillCandTrack ( ldmx::PFCandidate & cand,
const ldmx::Track & tk,
const std::vector< ldmx::SimTrackerHit > & sp_hits )

Definition at line 89 of file ParticleFlow.cxx.

91 {
92 auto ts = tk.getTrackState(ldmx::AtECAL);
93 if (!ts || ts->pos_.size() < 3 || ts->mom_.size() < 3) return;
94 const std::vector<double>& xyz = ts->pos_;
95 const std::vector<double>& pxyz = ts->mom_;
96 float ecal_z = 248;
97 float ecal_x =
98 xyz[0] + pxyz[0] / pxyz[2] * (ecal_z - xyz[2]); // project onto ecal face
99 float ecal_y = xyz[1] + pxyz[1] / pxyz[2] * (ecal_z - xyz[2]);
100 cand.setEcalPositionXYZ(ecal_x, ecal_y, ecal_z);
101 cand.setTrackPxPyPz(pxyz[0], pxyz[1], pxyz[2]);
102 cand.setPID(cand.getPID() | 1); // OR with 001
103
104 // truth from the matched Ecal SP hit closest in momentum
105 const ldmx::SimTrackerHit* best = nullptr;
106 double best_dp = 9e9;
107 for (const auto& sp : sp_hits) {
108 if (sp.getTrackID() != tk.getTrackID()) continue;
109 if (fabs(240 - sp.getPosition()[2]) > 0.1) continue;
110 auto sp_p = sp.getMomentum();
111 double dp =
112 std::hypot(sp_p[0] - pxyz[0], sp_p[1] - pxyz[1], sp_p[2] - pxyz[2]);
113 if (dp < best_dp) {
114 best_dp = dp;
115 best = &sp;
116 }
117 }
118 if (!best) return;
119 std::vector<float> t_xyz = best->getPosition();
120 std::vector<double> t_pxyz = best->getMomentum();
121 cand.setTruthEcalXYZ(t_xyz[0] + t_pxyz[0] / t_pxyz[2] * (ecal_z - t_xyz[2]),
122 t_xyz[1] + t_pxyz[1] / t_pxyz[2] * (ecal_z - t_xyz[2]),
123 ecal_z);
124 cand.setTruthPxPyPz(t_pxyz[0], t_pxyz[1], t_pxyz[2]);
125 float m2 = pow(best->getEnergy(), 2) - pow(t_pxyz[0], 2) - pow(t_pxyz[1], 2) -
126 pow(t_pxyz[2], 2);
127 if (m2 < 0) m2 = 0;
128 cand.setTruthMass(sqrt(m2));
129 cand.setTruthEnergy(best->getEnergy());
130 cand.setTruthPdgId(best->getPdgID());
131 cand.setTruthTrackId(best->getTrackID());
132}
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].
float getEnergy() const
Get the energy.
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.

◆ getEcalClusters()

const std::vector< ldmx::CaloCluster > recon::ParticleFlow::getEcalClusters ( framework::Event & event,
std::string inputClusterCollName,
std::string inputClusterPassName )
private

Definition at line 785 of file ParticleFlow.cxx.

787 {
788 const auto tmp_clusters = event.getCollection<ldmx::EcalCluster>(
789 inputClusterCollName, inputClusterPassName);
790 std::string new_name = inputClusterCollName + "Cast";
791 std::vector<ldmx::CaloCluster> new_clusters;
792 for (auto cl : tmp_clusters) {
793 new_clusters.emplace_back(cl);
794 }
795 event.add(new_name, new_clusters);
796 const auto calo_clusters =
797 event.getCollection<ldmx::CaloCluster>(new_name, event.getPassName());
798 return calo_clusters;
799}
Stores cluster information from the ECal.
Definition CaloCluster.h:25
Stores cluster information from the ECal.
Definition EcalCluster.h:20

◆ identifyCharged()

void recon::ParticleFlow::identifyCharged ( ldmx::PFCandidate & cand) const

Definition at line 489 of file ParticleFlow.cxx.

489 {
490 auto p = cand.getTrackPxPyPz();
491 double trk_p = std::hypot(p[0], p[1], p[2]);
492 double ep = trk_p > 0 ? cand.getEcalEnergy() / trk_p : 0;
493 int q = cand.getCharge() >= 0 ? 1 : -1;
494 // m2 resolution grows as p^2, so dE/dx only separates at low p
495 bool has_dedx = cand.getDeDxNhits() >= dedx_min_hits_;
496 double m2 = cand.getDeDxMassSquared();
497 bool is_proton = has_dedx && trk_p < proton_max_p_ && m2 > proton_min_mass2_;
498 bool is_kaon = has_dedx && trk_p < kaon_max_p_ && m2 > kaon_min_mass2_ &&
499 m2 <= proton_min_mass2_;
500 if (is_proton) {
501 cand.setPdgId(211 * q);
502 cand.setMass(938.27);
503 } else if (is_kaon) {
504 cand.setPdgId(211 * q);
505 cand.setMass(493.68);
506 } else if ((cand.getPID() & 2) && ep > electron_ep_min_ &&
507 cand.getEcalDepth() <
508 electron_max_depth_ +
509 electron_depth_slope_ *
510 std::log2(std::max(trk_p, 100.) / 1000.)) {
511 // EM showers stay shallow, hadronic ones start late and go deep
512 // no upper E/p, overlapping photons are split off as excess
513 cand.setPdgId(-11 * q);
514 cand.setMass(0.511);
515 } else {
516 cand.setPdgId(211 * q);
517 cand.setMass(139.57);
518 }
519}

◆ linkEcalClusters()

std::vector< ldmx::CaloCluster > recon::ParticleFlow::linkEcalClusters ( const std::vector< ldmx::CaloCluster > & clusters,
const std::vector< ldmx::Track > & tracks ) const

Definition at line 188 of file ParticleFlow.cxx.

190 {
191 int n = clusters.size();
192 std::vector<int> nlay(n), parent(n, -1);
193 std::vector<double> zstart(n);
194 std::vector<bool> tk_linked(n, false);
195 for (int i = 0; i < n; i++) {
196 std::set<int> layers;
197 double zmin = 9e9;
198 for (float z : clusters[i].getHitZ()) {
199 layers.insert(std::lround(z));
200 zmin = std::min<double>(zmin, z);
201 }
202 nlay[i] = layers.size();
203 zstart[i] = layers.empty() ? clusters[i].getCentroidZ() : zmin;
204 for (const auto& tk : tracks) {
205 auto ts = tk.getTrackState(ldmx::AtECAL);
206 if (!ts || ts->mom_.size() < 3 || ts->mom_[2] <= 0) continue;
207 if (trackClusterDist(ts->pos_, ts->mom_, clusters[i]) < link_max_dist_) {
208 tk_linked[i] = true;
209 break;
210 }
211 }
212 }
213 for (int s = 0; s < n; s++) {
214 if (tk_linked[s]) continue;
215 double es = clusters[s].getEnergy();
216 int best = -1;
217 double best_d = ecal_link_radius_;
218 double nearest = 9e9; // to any more energetic cluster
219 for (int p = 0; p < n; p++) {
220 if (p == s || clusters[p].getEnergy() <= es) continue;
221 double d =
222 std::hypot(clusters[p].getCentroidX() - clusters[s].getCentroidX(),
223 clusters[p].getCentroidY() - clusters[s].getCentroidY());
224 nearest = std::min(nearest, d);
225 bool satellite = nlay[s] < ecal_link_min_layers_ ||
226 es < ecal_link_ratio_ * clusters[p].getEnergy();
227 if (nlay[p] >= ecal_link_min_layers_ && satellite && d < best_d) {
228 best_d = d;
229 best = p;
230 }
231 }
232 // isolated, early showers look like photons from the target
233 bool photon_like = es >= photon_keep_min_e_ &&
234 nearest > photon_keep_min_dist_ &&
235 zstart[s] < photon_keep_max_zstart_;
236 if (best >= 0 && !photon_like) parent[s] = best;
237 }
238
239 // follow chains to the final parent and merge
240 auto root = [&parent](int i) {
241 while (parent[i] >= 0) i = parent[i];
242 return i;
243 };
244 std::map<int, std::vector<int>> groups;
245 for (int i = 0; i < n; i++) groups[root(i)].push_back(i);
246 std::vector<ldmx::CaloCluster> merged;
247 for (const auto& [r, members] : groups) {
248 merged.push_back(mergeClusters(clusters, r, members));
249 }
250 std::sort(merged.begin(), merged.end(), [](const auto& a, const auto& b) {
251 return a.getEnergy() > b.getEnergy();
252 });
253 return merged;
254}

◆ linkHcalClusters()

std::vector< ldmx::CaloCluster > recon::ParticleFlow::linkHcalClusters ( const std::vector< ldmx::CaloCluster > & clusters) const

Definition at line 291 of file ParticleFlow.cxx.

292 {
293 int n = clusters.size();
294 std::vector<int> order(n);
295 for (int i = 0; i < n; i++) order[i] = i;
296 std::sort(order.begin(), order.end(), [&clusters](int a, int b) {
297 return clusters[a].getEnergy() > clusters[b].getEnergy();
298 });
299 auto dir = [&clusters](int i) {
300 const auto& c = clusters[i];
301 double r = std::hypot(c.getCentroidX(), c.getCentroidY(), c.getCentroidZ());
302 return std::array<double, 3>{c.getCentroidX() / r, c.getCentroidY() / r,
303 c.getCentroidZ() / r};
304 };
305 double cos_max = std::cos(hcal_merge_angle_ * M_PI / 180.);
306 std::vector<bool> used(n, false);
307 std::vector<ldmx::CaloCluster> merged;
308 for (int s : order) {
309 if (used[s]) continue;
310 auto ds = dir(s);
311 std::vector<int> members;
312 for (int o : order) {
313 if (used[o]) continue;
314 auto d = dir(o);
315 if (ds[0] * d[0] + ds[1] * d[1] + ds[2] * d[2] >= cos_max) {
316 used[o] = true;
317 members.push_back(o);
318 }
319 }
320 merged.push_back(mergeClusters(clusters, s, members));
321 }
322 return merged;
323}

◆ linkTrackHcal()

int recon::ParticleFlow::linkTrackHcal ( const ldmx::Track & tk,
const std::vector< ldmx::CaloCluster > & clusters,
const std::vector< bool > & used ) const

Definition at line 327 of file ParticleFlow.cxx.

329 {
330 auto ts = tk.getTrackState(ldmx::AtECAL);
331 if (hcal_track_angle_ <= 0 || !ts || ts->mom_.size() < 3) return -1;
332 const auto& pos = ts->pos_;
333 const auto& mom = ts->mom_;
334 double pm = std::hypot(mom[0], mom[1], mom[2]);
335 int best = -1;
336 double best_cos = std::cos(hcal_track_angle_ * M_PI / 180.);
337 for (int j = 0; j < static_cast<int>(clusters.size()); j++) {
338 if (used[j]) continue;
339 double dx = clusters[j].getCentroidX() - pos[0];
340 double dy = clusters[j].getCentroidY() - pos[1];
341 double dz = clusters[j].getCentroidZ() - pos[2];
342 double c = (dx * mom[0] + dy * mom[1] + dz * mom[2]) /
343 (pm * std::hypot(dx, dy, dz));
344 if (c > best_cos) {
345 best_cos = c;
346 best = j;
347 }
348 }
349 return best;
350}

◆ mergeClusters()

ldmx::CaloCluster recon::ParticleFlow::mergeClusters ( const std::vector< ldmx::CaloCluster > & clusters,
int root,
const std::vector< int > & members )
static

Definition at line 258 of file ParticleFlow.cxx.

260 {
261 if (members.size() == 1) return clusters[root];
262 ldmx::CaloCluster cl = clusters[root];
263 double e = 0, x = 0, y = 0, z = 0;
264 std::vector<unsigned int> ids;
265 std::vector<float> hx, hy, hz, he;
266 for (int m : members) {
267 const auto& c = clusters[m];
268 e += c.getEnergy();
269 x += c.getEnergy() * c.getCentroidX();
270 y += c.getEnergy() * c.getCentroidY();
271 z += c.getEnergy() * c.getCentroidZ();
272 ids.insert(ids.end(), c.getHitIDs().begin(), c.getHitIDs().end());
273 hx.insert(hx.end(), c.getHitX().begin(), c.getHitX().end());
274 hy.insert(hy.end(), c.getHitY().begin(), c.getHitY().end());
275 hz.insert(hz.end(), c.getHitZ().begin(), c.getHitZ().end());
276 he.insert(he.end(), c.getHitE().begin(), c.getHitE().end());
277 }
278 cl.setEnergy(e);
279 if (e > 0) cl.setCentroidXYZ(x / e, y / e, z / e);
280 cl.setNHits(ids.size());
281 cl.setIDs(ids);
282 cl.setHitValsX(hx);
283 cl.setHitValsY(hy);
284 cl.setHitValsZ(hz);
285 cl.setHitValsE(he);
286 return cl;
287}
void setNHits(int nHits)
Sets total number of hits in the cluster.
Definition CaloCluster.h:64
void setCentroidXYZ(double centroid_x, double centroid_y, double centroid_z)
Sets the three coordinates of the cluster centroid.
Definition CaloCluster.h:84
void setEnergy(double energy)
Sets total energy for the cluster.
Definition CaloCluster.h:58
void setIDs(std::vector< unsigned int > &hitIDs)
Sets a sorted vector for the IDs of the hits_ that make up the cluster.
Definition CaloCluster.h:71

◆ onProcessEnd()

void recon::ParticleFlow::onProcessEnd ( )
virtual

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 801 of file ParticleFlow.cxx.

801{ ldmx_log(debug) << "Process ends!"; }

◆ produce()

void recon::ParticleFlow::produce ( framework::Event & event)
virtual

Process the event and put new data products into it.

Parameters
eventThe Event to process.

Implements framework::Producer.

Definition at line 522 of file ParticleFlow.cxx.

522 {
523 if (!event.exists(input_track_coll_name_, input_tracks_passname_)) {
524 ldmx_log(error) << "Unable to find (one) collection named "
525 << input_track_coll_name_ << "_" << input_tracks_passname_;
526 return;
527 }
528 if (!event.exists(input_ecal_coll_name_, input_ecal_passname_)) {
529 ldmx_log(error) << "Unable to find (one) collection named "
530 << input_ecal_coll_name_ << "_" << input_ecal_passname_;
531 return;
532 }
533 if (!event.exists(input_hcal_coll_name_, input_hcal_passname_)) {
534 ldmx_log(error) << "Unable to find (one) collection named "
535 << input_hcal_coll_name_ << "_" << input_hcal_passname_;
536 return;
537 }
538 // get the track and clustering info
539 auto hcal_clusters = event.getCollection<ldmx::CaloCluster>(
540 input_hcal_coll_name_, input_hcal_passname_);
541 if (hcal_merge_angle_ > 0) hcal_clusters = linkHcalClusters(hcal_clusters);
542 const auto tracks = event.getCollection<ldmx::Track>(input_track_coll_name_,
543 input_tracks_passname_);
544 // truth info is optional
545 std::vector<ldmx::SimTrackerHit> sp_hits;
546 if (event.exists(truth_sp_coll_name_, truth_sp_passname_))
547 sp_hits = event.getCollection<ldmx::SimTrackerHit>(truth_sp_coll_name_,
548 truth_sp_passname_);
549 // dE/dx estimates made on the input tracks, keyed by track index
550 std::map<int, ldmx::TrackDeDxMassEstimate> mass_estimates;
551 if (!input_mass_coll_name_.empty() &&
552 event.exists(input_mass_coll_name_, input_mass_passname_)) {
553 for (const auto& est : event.getCollection<ldmx::TrackDeDxMassEstimate>(
554 input_mass_coll_name_, input_mass_passname_)) {
555 mass_estimates[est.getTrackIndex()] = est;
556 }
557 }
558 // here allow for using existing clusters of different type (EcalCluster)
559 auto ecal_clusters =
560 use_existing_ecal_clusters_
561 ? getEcalClusters(event, input_ecal_coll_name_, input_ecal_passname_)
562 : event.getCollection<ldmx::CaloCluster>(input_ecal_coll_name_,
563 input_ecal_passname_);
564 if (ecal_link_radius_ > 0)
565 ecal_clusters = linkEcalClusters(ecal_clusters, tracks);
566
567 std::vector<ldmx::PFCandidate> pf_cands;
568 // multi-particle case
569 if (!single_particle_) {
570 /*
571 1. Build links maps at the Tk/Ecal and Hcal/Hcal interfaces
572 2. Categorize tracks as: Ecal-matched, (Side) Hcal-matched, unmatched
573 3. Categorize Ecal clusters as: Hcal-matched, unmatched
574 4a. (Upstream?) Categorize tracks with dedx?
575 4b. (Upstream?) Categorize ecal clusters as: EM/Had-like
576 4c. (Upstream?) Categorize hcal clusters as: EM/Had-like
577 5. Build candidates by category, moving from Tk-Ecal-Hcal
578 */
579
580 //
581 // track-calo linking
582 //
583 std::vector<bool> tk_usable(tracks.size(), false);
584 // linked Ecal clusters per track, closest first
585 std::map<int, std::vector<std::pair<float, int>>> tk_calo_map;
586 for (int i = 0; i < tracks.size(); i++) {
587 const auto& tk = tracks[i];
588 const std::vector<double> xyz = tk.getPosition(ldmx::AtECAL);
589 const std::vector<double> pxyz = tk.getMomentum(ldmx::AtECAL);
590 // need a forward Ecal face state to extrapolate
591 if (pxyz.empty() || pxyz[2] <= 0) {
592 ldmx_log(warn) << "Skipping track " << i << " without AtECAL state";
593 continue;
594 }
595 tk_usable[i] = true;
596 for (int j = 0; j < ecal_clusters.size(); j++) {
597 float dist = trackClusterDist(xyz, pxyz, ecal_clusters[j]);
598 // E/p is used for the ID, not the link
599 if (dist < link_max_dist_) tk_calo_map[i].emplace_back(dist, j);
600 }
601 std::sort(tk_calo_map[i].begin(), tk_calo_map[i].end());
602 }
603
604 // em-hadcalo linking
605 std::map<int, std::vector<int>> em_had_calo_map;
606 for (int i = 0; i < ecal_clusters.size(); i++) {
607 const auto& ecal = ecal_clusters[i];
608 for (int j = 0; j < hcal_clusters.size(); j++) {
609 const auto& hcal = hcal_clusters[j];
610 const float x_at_h_clus =
611 ecal.getCentroidX() +
612 ecal.getDXDZ() * (hcal.getCentroidZ() -
613 ecal.getCentroidZ()); // extrapolated position
614 const float y_at_h_clus =
615 ecal.getCentroidY() +
616 ecal.getDYDZ() * (hcal.getCentroidZ() - ecal.getCentroidZ());
617 float dist = sqrt(
618 pow(x_at_h_clus - hcal.getCentroidX(), 2) /
619 std::max(1.0, pow(hcal.getRMSX(), 2) + pow(ecal.getRMSX(), 2)) +
620 pow(y_at_h_clus - hcal.getCentroidY(), 2) /
621 std::max(1.0, pow(hcal.getRMSY(), 2) + pow(ecal.getRMSY(), 2)));
622 bool is_match = (dist < 5); // matching criteria, was 2
623 if (is_match) em_had_calo_map[i].push_back(j);
624 }
625 }
626
627 //
628 // track / ecal cluster arbitration
629 //
630 std::vector<bool> tk_is_em_linked(tracks.size(), false);
631 std::vector<bool> em_is_tk_linked(ecal_clusters.size(), false);
632 std::map<int, int> tk_em_pairs{};
633 for (int i = 0; i < tracks.size(); i++) {
634 if (tk_calo_map.count(i)) {
635 // pick the closest unused matching cluster
636 for (const auto& [dist, em_idx] : tk_calo_map[i]) {
637 if (!em_is_tk_linked[em_idx]) {
638 em_is_tk_linked[em_idx] = true;
639 tk_is_em_linked[i] = true;
640 tk_em_pairs[i] = em_idx;
641 break;
642 }
643 }
644 }
645 }
646
647 // ecal / hcal cluster arbitration
648 std::vector<bool> em_is_had_linked(ecal_clusters.size(), false);
649 std::vector<bool> had_is_em_linked(hcal_clusters.size(), false);
650 std::map<int, int> em_had_pairs{};
651 for (int i = 0; i < ecal_clusters.size(); i++) {
652 if (em_had_calo_map.count(i)) {
653 // pick first (highest-energy) unused matching cluster
654 for (int had_idx : em_had_calo_map[i]) {
655 if (!had_is_em_linked[had_idx]) {
656 had_is_em_linked[had_idx] = true;
657 em_is_had_linked[i] = true;
658 em_had_pairs[i] = had_idx;
659 break;
660 }
661 }
662 }
663 }
664
665 // can consider combining satellite clusters here...
666 // define some "primary cluster" ID criterion
667 // and can add fails to the primaries
668
669 //
670 // Begin building pf candidates from tracks
671 //
672 for (int i = 0; i < tracks.size(); i++) {
673 if (!tk_usable[i]) continue;
675 fillCandTrack(cand, tracks[i],
676 sp_hits); // append track info to candidate
677 cand.setTrackIndex(i);
678 if (tk_is_em_linked[i]) { // if track is linked with ECal cluster
679 int em_idx = tk_em_pairs[i];
680 fillCandEMCalo(cand, ecal_clusters[em_idx]);
681 cand.setEcalWidth(ecalWidth(ecal_clusters[em_idx], tracks[i]));
682 cand.setEcalIndex(em_idx);
683 if (em_is_had_linked[em_idx]) { // if ECal is linked with HCal
684 fillCandHadCalo(cand, hcal_clusters[em_had_pairs[em_idx]]);
685 cand.setHcalIndex(em_had_pairs[em_idx]);
686 }
687 recoverEcal(cand, tracks[i], ecal_clusters, em_is_tk_linked);
688 }
689 // charged hadron showers in the Hcal belong to the track, not to a
690 // neutral; takes the closest free cluster in angle
691 if (cand.getHcalIndex() < 0) {
692 int h = linkTrackHcal(tracks[i], hcal_clusters, had_is_em_linked);
693 if (h >= 0) {
694 fillCandHadCalo(cand, hcal_clusters[h]);
695 cand.setHcalIndex(h);
696 had_is_em_linked[h] = true;
697 }
698 }
699 if (auto it = mass_estimates.find(i); it != mass_estimates.end()) {
700 cand.setDeDxMassSquared(it->second.getMassSquared());
701 cand.setDeDxIh(it->second.getIh());
702 cand.setDeDxNhits(it->second.getNhits());
703 }
704 cand.setCharge(static_cast<int>(tracks[i].getCharge()));
705 identifyCharged(cand);
706 if (std::abs(cand.getPdgId()) == 211) {
707 absorbHadronShower(cand, tracks[i], ecal_clusters, em_is_tk_linked,
708 hcal_clusters, had_is_em_linked);
709 }
710 // charged energy from the track and the mass hypothesis
711 auto p = cand.getTrackPxPyPz();
712 double trk_p = std::hypot(p[0], p[1], p[2]);
713 cand.setEnergy(std::hypot(trk_p, cand.getMass()));
714 pf_cands.push_back(cand);
715
716 // Ecal energy well above the track momentum is a neutral overlap
717 double ecal_e = cand.getEcalEnergy();
718 if (tk_is_em_linked[i] && trk_p > 0 && ecal_e > excess_ep_ * trk_p) {
719 ldmx::PFCandidate excess;
720 fillCandEMCalo(excess, ecal_clusters[tk_em_pairs[i]]);
721 excess.setEcalIndex(tk_em_pairs[i]);
722 excess.setPdgId(22);
723 // hits stay with the charged candidate, one candidate per hit
724 excess.clearEcalHits();
725 excess.setEnergy(ecal_e - trk_p);
726 pf_cands.push_back(excess);
727 }
728 }
729
730 // neutral candidates from Ecal clusters not linked to a track
731 for (int i = 0; i < ecal_clusters.size(); i++) {
732 if (em_is_tk_linked[i]) continue;
734 fillCandEMCalo(cand, ecal_clusters[i]);
735 cand.setEcalIndex(i);
736 if (em_is_had_linked[i]) {
737 fillCandHadCalo(cand, hcal_clusters[em_had_pairs[i]]);
738 cand.setHcalIndex(em_had_pairs[i]);
739 }
740 // Hcal energy means a hadronic shower
741 // pdg 130 for neutral hadrons, as in CMS PF
742 cand.setPdgId(em_is_had_linked[i] ? 130 : 22);
743 cand.setEnergy(cand.getEcalEnergy() + cand.getHcalEnergy());
744 if (cand.getEnergy() >= min_neutral_e_) pf_cands.push_back(cand);
745 }
746
747 // neutral candidates from unlinked Hcal clusters
748 for (int i = 0; i < hcal_clusters.size(); i++) {
749 if (had_is_em_linked[i]) continue;
751 fillCandHadCalo(cand, hcal_clusters[i]);
752 cand.setHcalIndex(i);
753 cand.setPdgId(130);
754 cand.setEnergy(cand.getHcalEnergy());
755 if (cand.getEnergy() >= min_neutral_e_) pf_cands.push_back(cand);
756 }
757
758 } else {
759 // Single-particle builder
761 int pid = 0; // initialize pid to add
762 if (tracks.size() && !tracks[0].getMomentum(ldmx::AtECAL).empty()) {
763 fillCandTrack(pf, tracks[0], sp_hits);
764 pf.setTrackIndex(0);
765 pid += 1;
766 }
767 if (ecal_clusters.size()) {
768 fillCandEMCalo(pf, ecal_clusters[0]);
769 pf.setEcalIndex(0);
770 pid += 2;
771 }
772 if (hcal_clusters.size()) {
773 fillCandHadCalo(pf, hcal_clusters[0]);
774 pf.setHcalIndex(0);
775 pid += 4;
776 }
777 pf.setPID(pid);
778 pf.setEnergy(pf.getEcalEnergy() + pf.getHcalEnergy());
779 pf_cands.push_back(pf);
780 }
781
782 event.add(output_coll_name_, pf_cands);
783}
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
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:409
Represents a reconstructed particle.
Definition PFCandidate.h:21
Represents the estimated mass of a particle using tracker dE/dx information.
Implementation of a track object.
Definition Track.h:54

References framework::Event::exists(), framework::Event::getCollection(), ldmx::Track::getMomentum(), and ldmx::Track::getPosition().

◆ recoverEcal()

void recon::ParticleFlow::recoverEcal ( ldmx::PFCandidate & cand,
const ldmx::Track & tk,
const std::vector< ldmx::CaloCluster > & clusters,
std::vector< bool > & used ) const

Definition at line 455 of file ParticleFlow.cxx.

457 {
458 auto ts = tk.getTrackState(ldmx::AtECAL);
459 if (recovery_radius_ <= 0 || !ts || ts->mom_.size() < 3 || ts->mom_[2] <= 0)
460 return;
461 const auto& xyz = ts->pos_;
462 const auto& pxyz = ts->mom_;
463 double trk_p = std::hypot(pxyz[0], pxyz[1], pxyz[2]);
464 if (cand.getEcalEnergy() >= electron_ep_min_ * trk_p) return;
465 std::vector<std::pair<double, int>> near;
466 for (int j = 0; j < static_cast<int>(clusters.size()); j++) {
467 if (used[j]) continue;
468 double z = clusters[j].getCentroidZ();
469 double d = std::hypot(
470 xyz[0] + pxyz[0] / pxyz[2] * (z - xyz[2]) - clusters[j].getCentroidX(),
471 xyz[1] + pxyz[1] / pxyz[2] * (z - xyz[2]) - clusters[j].getCentroidY());
472 if (d < recovery_radius_) near.emplace_back(d, j);
473 }
474 std::sort(near.begin(), near.end());
475 for (const auto& [d, j] : near) {
476 if (cand.getEcalEnergy() >= recovery_stop_ep_ * trk_p) break;
477 double e = clusters[j].getEnergy();
478 double corr = correction(ecal_corr_energies_, ecal_corr_factors_, e);
479 cand.setEcalEnergy(cand.getEcalEnergy() + e * corr);
480 cand.setEcalRawEnergy(cand.getEcalRawEnergy() + e);
481 cand.addEcalHits(clusters[j].getHitIDs(), clusters[j].getHitE());
482 used[j] = true;
483 }
484}

◆ trackClusterDist()

double recon::ParticleFlow::trackClusterDist ( const std::vector< double > & xyz,
const std::vector< double > & pxyz,
const ldmx::CaloCluster & cl ) const

Definition at line 172 of file ParticleFlow.cxx.

174 {
175 double z = cl.getCentroidZ();
176 double x = xyz[0] + pxyz[0] / pxyz[2] * (z - xyz[2]);
177 double y = xyz[1] + pxyz[1] / pxyz[2] * (z - xyz[2]);
178 // RMS floor covers scattering of soft tracks
179 return std::hypot(
180 (x - cl.getCentroidX()) / std::max(link_min_rms_, cl.getRMSX()),
181 (y - cl.getCentroidY()) / std::max(link_min_rms_, cl.getRMSY()));
182}

Member Data Documentation

◆ dedx_min_hits_

int recon::ParticleFlow::dedx_min_hits_ {}
private

Definition at line 140 of file ParticleFlow.h.

140{};

◆ ecal_corr_energies_

std::vector<double> recon::ParticleFlow::ecal_corr_energies_
private

Definition at line 75 of file ParticleFlow.h.

◆ ecal_corr_factors_

std::vector<double> recon::ParticleFlow::ecal_corr_factors_
private

Definition at line 76 of file ParticleFlow.h.

◆ ecal_front_z_

double recon::ParticleFlow::ecal_front_z_ {}
private

Definition at line 129 of file ParticleFlow.h.

129{};

◆ ecal_link_min_layers_

int recon::ParticleFlow::ecal_link_min_layers_ {}
private

Definition at line 135 of file ParticleFlow.h.

135{};

◆ ecal_link_radius_

double recon::ParticleFlow::ecal_link_radius_ {}
private

Definition at line 133 of file ParticleFlow.h.

133{};

◆ ecal_link_ratio_

double recon::ParticleFlow::ecal_link_ratio_ {}
private

Definition at line 134 of file ParticleFlow.h.

134{};

◆ electron_depth_slope_

double recon::ParticleFlow::electron_depth_slope_ {}
private

Definition at line 131 of file ParticleFlow.h.

131{};

◆ electron_ep_min_

double recon::ParticleFlow::electron_ep_min_ {}
private

Definition at line 104 of file ParticleFlow.h.

104{};

◆ electron_max_depth_

double recon::ParticleFlow::electron_max_depth_ {}
private

Definition at line 130 of file ParticleFlow.h.

130{};

◆ excess_ep_

double recon::ParticleFlow::excess_ep_ {}
private

Definition at line 106 of file ParticleFlow.h.

106{};

◆ hadron_absorb_ep_

double recon::ParticleFlow::hadron_absorb_ep_ {}
private

Definition at line 124 of file ParticleFlow.h.

124{};

◆ hadron_ecal_radius_

double recon::ParticleFlow::hadron_ecal_radius_ {}
private

Definition at line 123 of file ParticleFlow.h.

123{};

◆ hcal_corr_energies_

std::vector<double> recon::ParticleFlow::hcal_corr_energies_
private

Definition at line 77 of file ParticleFlow.h.

◆ hcal_corr_factors_

std::vector<double> recon::ParticleFlow::hcal_corr_factors_
private

Definition at line 78 of file ParticleFlow.h.

◆ hcal_merge_angle_

double recon::ParticleFlow::hcal_merge_angle_ {}
private

Definition at line 118 of file ParticleFlow.h.

118{};

◆ hcal_track_angle_

double recon::ParticleFlow::hcal_track_angle_ {}
private

Definition at line 120 of file ParticleFlow.h.

120{};

◆ input_ecal_coll_name_

std::string recon::ParticleFlow::input_ecal_coll_name_
private

Definition at line 81 of file ParticleFlow.h.

◆ input_ecal_passname_

std::string recon::ParticleFlow::input_ecal_passname_
private

Definition at line 84 of file ParticleFlow.h.

◆ input_hcal_coll_name_

std::string recon::ParticleFlow::input_hcal_coll_name_
private

Definition at line 82 of file ParticleFlow.h.

◆ input_hcal_passname_

std::string recon::ParticleFlow::input_hcal_passname_
private

Definition at line 85 of file ParticleFlow.h.

◆ input_mass_coll_name_

std::string recon::ParticleFlow::input_mass_coll_name_
private

Definition at line 97 of file ParticleFlow.h.

◆ input_mass_passname_

std::string recon::ParticleFlow::input_mass_passname_
private

Definition at line 98 of file ParticleFlow.h.

◆ input_track_coll_name_

std::string recon::ParticleFlow::input_track_coll_name_
private

Definition at line 83 of file ParticleFlow.h.

◆ input_tracks_passname_

std::string recon::ParticleFlow::input_tracks_passname_
private

Definition at line 86 of file ParticleFlow.h.

◆ kaon_max_p_

double recon::ParticleFlow::kaon_max_p_ {}
private

Definition at line 112 of file ParticleFlow.h.

112{};

◆ kaon_min_mass2_

double recon::ParticleFlow::kaon_min_mass2_ {}
private

Definition at line 110 of file ParticleFlow.h.

110{};

◆ link_max_dist_

double recon::ParticleFlow::link_max_dist_ {}
private

Definition at line 100 of file ParticleFlow.h.

100{};

◆ link_min_rms_

double recon::ParticleFlow::link_min_rms_ {}
private

Definition at line 102 of file ParticleFlow.h.

102{};

◆ min_neutral_e_

double recon::ParticleFlow::min_neutral_e_ {}
private

Definition at line 126 of file ParticleFlow.h.

126{};

◆ output_coll_name_

std::string recon::ParticleFlow::output_coll_name_
private

Definition at line 93 of file ParticleFlow.h.

◆ photon_keep_max_zstart_

double recon::ParticleFlow::photon_keep_max_zstart_ {}
private

Definition at line 139 of file ParticleFlow.h.

139{};

◆ photon_keep_min_dist_

double recon::ParticleFlow::photon_keep_min_dist_ {}
private

Definition at line 138 of file ParticleFlow.h.

138{};

◆ photon_keep_min_e_

double recon::ParticleFlow::photon_keep_min_e_ {}
private

Definition at line 137 of file ParticleFlow.h.

137{};

◆ proton_max_p_

double recon::ParticleFlow::proton_max_p_ {}
private

Definition at line 111 of file ParticleFlow.h.

111{};

◆ proton_min_mass2_

double recon::ParticleFlow::proton_min_mass2_ {}
private

Definition at line 109 of file ParticleFlow.h.

109{};

◆ recovery_radius_

double recon::ParticleFlow::recovery_radius_ {}
private

Definition at line 115 of file ParticleFlow.h.

115{};

◆ recovery_stop_ep_

double recon::ParticleFlow::recovery_stop_ep_ {}
private

Definition at line 116 of file ParticleFlow.h.

116{};

◆ single_particle_

bool recon::ParticleFlow::single_particle_
private

Definition at line 95 of file ParticleFlow.h.

◆ truth_sp_coll_name_

std::string recon::ParticleFlow::truth_sp_coll_name_
private

Definition at line 88 of file ParticleFlow.h.

◆ truth_sp_passname_

std::string recon::ParticleFlow::truth_sp_passname_
private

Definition at line 89 of file ParticleFlow.h.

◆ use_existing_ecal_clusters_

bool recon::ParticleFlow::use_existing_ecal_clusters_
private

Definition at line 91 of file ParticleFlow.h.


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