LDMX Software
dqm::ParticleFlowDQM Class Reference

Monitor PF candidates, their ID, and the match to truth. More...

#include <ParticleFlowDQM.h>

Public Member Functions

 ParticleFlowDQM (const std::string &name, framework::Process &process)
 
void configure (framework::config::Parameters &ps) override
 Callback for the EventProcessor to configure itself from the given set of parameters.
 
void analyze (const framework::Event &event) override
 Process the event and make histograms or summaries.
 
- 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.
 
virtual void onProcessEnd ()
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
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 Member Functions

void analyzeTruth (const framework::Event &event, std::vector< ldmx::PFCandidate > &cands)
 
bool reconstructable (int pdg, double px, double py, double pz, double ke) const
 
int interactionRegion (const std::vector< double > &end) const
 

Private Attributes

std::string pf_cand_coll_name_ {"PFCandidates"}
 
std::string pf_cand_pass_name_ {""}
 
std::string ecal_sp_coll_name_ {"EcalScoringPlaneHits"}
 
std::string ecal_sp_pass_name_ {""}
 
std::string sim_particles_coll_name_ {"SimParticles"}
 
std::string sim_particles_pass_name_ {""}
 
double truth_min_energy_ {50.}
 
double neutral_match_dist_ {30.}
 
double neutral_match_max_ratio_ {2.}
 
double neutral_hcal_match_angle_ {30.}
 
double reco_max_theta_ {80.}
 
double reco_min_p_pion_ {100.}
 
double reco_min_p_heavy_ {800.}
 
double reco_min_ke_neutral_ {1000.}
 
double reco_min_ke_pi0_ {2000.}
 
double ecal_back_z_ {760.}
 
double ecal_half_xy_ {300.}
 
double hcal_max_z_ {4000.}
 
double hcal_max_xy_ {1600.}
 

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

Monitor PF candidates, their ID, and the match to truth.

Truth is every particle entering the Ecal front face. Charged candidates match by track ID, neutral ones by position.

Definition at line 20 of file ParticleFlowDQM.h.

Constructor & Destructor Documentation

◆ ParticleFlowDQM()

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

Definition at line 22 of file ParticleFlowDQM.h.

23 : Analyzer(name, process) {}
virtual void process(Event &event) final
Processing an event for an Analyzer is calling analyze.
Analyzer(const std::string &name, Process &process)
Class constructor.

Member Function Documentation

◆ analyze()

void dqm::ParticleFlowDQM::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 188 of file ParticleFlowDQM.cxx.

188 {
189 if (!event.exists(pf_cand_coll_name_, pf_cand_pass_name_)) {
190 ldmx_log(debug) << "No collection " << pf_cand_coll_name_;
191 return;
192 }
193 auto cands = event.getCollection<ldmx::PFCandidate>(pf_cand_coll_name_,
194 pf_cand_pass_name_);
195 histograms_.fill("n_cands", cands.size());
196
197 int n_charged = 0, n_neutral = 0;
198 double charged_p = 0, neutral_e = 0, pf_e = 0;
199 for (auto& cand : cands) {
200 int pid = cand.getPID();
201 histograms_.fill("pid", pid);
202 histograms_.fill("reco_type", pfType(cand.getPdgId()));
203 if (pfType(cand.getPdgId()) == kPFH) {
204 histograms_.fill("charged_hadron_mass", massColumn(cand.getMass()));
205 }
206 pf_e += cand.getEnergy();
207 double ecal_e = cand.getEcalEnergy();
208 double hcal_e = cand.getHcalEnergy();
209
210 if (pid & 1) {
211 n_charged++;
212 auto p = cand.getTrackPxPyPz();
213 double trk_p = std::hypot(p[0], p[1], p[2]);
214 charged_p += trk_p;
215 histograms_.fill("charged_track_p", trk_p);
216 histograms_.fill("charged_is_ecal_linked", (pid & 2) ? 1 : 0);
217 if (cand.getDeDxNhits() > 0) {
218 histograms_.fill("charged_dedx_mass2_vs_p", trk_p,
219 cand.getDeDxMassSquared());
220 }
221 if ((pid & 2) && trk_p > 0) {
222 histograms_.fill("charged_ecal_e_over_p", ecal_e / trk_p);
223 histograms_.fill("charged_ecal_raw_e_over_p",
224 cand.getEcalRawEnergy() / trk_p);
225 // track at Ecal face vs linked cluster centroid
226 auto trk_pos = cand.getEcalPositionXYZ();
227 auto cl_pos = cand.getEcalClusterXYZ();
228 histograms_.fill("charged_cluster_dx", cl_pos[0] - trk_pos[0]);
229 histograms_.fill("charged_cluster_dy", cl_pos[1] - trk_pos[1]);
230 }
231 if (cand.getTruthPdgId() != 0) {
232 histograms_.fill("charged_truth_pdg", cand.getTruthPdgId());
233 auto tp = cand.getTruthPxPyPz();
234 double true_p = std::hypot(tp[0], tp[1], tp[2]);
235 if (true_p > 0) {
236 histograms_.fill("charged_dp_over_p", (trk_p - true_p) / true_p);
237 histograms_.fill("charged_p_vs_truth_p", true_p, trk_p);
238 }
239 auto t_pos = cand.getTruthEcalXYZ();
240 auto r_pos = cand.getEcalPositionXYZ();
241 histograms_.fill("charged_dx_truth", r_pos[0] - t_pos[0]);
242 histograms_.fill("charged_dy_truth", r_pos[1] - t_pos[1]);
243 int t_cat = category(cand.getTruthPdgId());
244 if ((pid & 2) && trk_p > 0) {
245 histograms_.fill("charged_e_over_p_vs_truth", t_cat, ecal_e / trk_p);
246 }
247 if (cand.getDeDxNhits() > 0) {
248 histograms_.fill("charged_dedx_mass2_vs_truth", t_cat,
249 cand.getDeDxMassSquared());
250 }
251 }
252 } else {
253 n_neutral++;
254 neutral_e += cand.getEnergy();
255 if (pid == 2) histograms_.fill("neutral_ecal_only_e", ecal_e);
256 if (pid == 6) {
257 histograms_.fill("neutral_ecal_hcal_ecal_e", ecal_e);
258 histograms_.fill("neutral_ecal_hcal_hcal_e", hcal_e);
259 }
260 if (pid == 4) histograms_.fill("neutral_hcal_only_e", hcal_e);
261 }
262 }
263 histograms_.fill("n_charged", n_charged);
264 histograms_.fill("n_neutral", n_neutral);
265 histograms_.fill("sum_charged_p", charged_p);
266 histograms_.fill("sum_neutral_e", neutral_e);
267 histograms_.fill("sum_pf_e", pf_e);
268
269 // reco diphoton mass, directions from the target
270 std::vector<int> photons;
271 for (int i = 0; i < static_cast<int>(cands.size()); i++) {
272 if (cands[i].getPdgId() == 22) photons.push_back(i);
273 }
274 for (size_t a = 0; a < photons.size(); a++) {
275 for (size_t b = a + 1; b < photons.size(); b++) {
276 const auto& c1 = cands[photons[a]];
277 const auto& c2 = cands[photons[b]];
278 auto d1 = direction(c1);
279 auto d2 = direction(c2);
280 double cos12 = d1[0] * d2[0] + d1[1] * d2[1] + d1[2] * d2[2];
281 double m2 = 2 * c1.getEnergy() * c2.getEnergy() * (1 - cos12);
282 histograms_.fill("mgg", std::sqrt(std::max(0., m2)));
283 }
284 }
285
286 analyzeTruth(event, cands);
287}
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:107
void fill(const std::string &name, const T &val)
Fill a 1D histogram.
Represents a reconstructed particle.
Definition PFCandidate.h:21

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

◆ analyzeTruth()

void dqm::ParticleFlowDQM::analyzeTruth ( const framework::Event & event,
std::vector< ldmx::PFCandidate > & cands )
private

Definition at line 289 of file ParticleFlowDQM.cxx.

290 {
291 if (!event.exists(ecal_sp_coll_name_, ecal_sp_pass_name_)) return;
292 const auto& sp_hits = event.getCollection<ldmx::SimTrackerHit>(
293 ecal_sp_coll_name_, ecal_sp_pass_name_);
294
295 // particles entering the Ecal front face, highest energy per track
296 std::map<int, TruthParticle> by_id;
297 for (const auto& sp : sp_hits) {
298 auto pos = sp.getPosition();
299 auto mom = sp.getMomentum();
300 if (std::abs(240 - pos[2]) > 0.1 || mom[2] <= 0) continue;
301 double e = sp.getEnergy();
302 int apdg = std::abs(sp.getPdgID());
303 double vis = (apdg == 11 || apdg == 22)
304 ? e
305 : e - std::sqrt(std::max(0., e * e - mom[0] * mom[0] -
306 mom[1] * mom[1] -
307 mom[2] * mom[2]));
308 if (vis < truth_min_energy_) continue;
309 auto it = by_id.find(sp.getTrackID());
310 if (it != by_id.end() && it->second.visible_e_ >= vis) continue;
311 by_id[sp.getTrackID()] = {sp.getTrackID(), sp.getPdgID(), vis, e,
312 pos[0], pos[1], pos[2], mom[0],
313 mom[1], mom[2]};
314 }
315 std::vector<TruthParticle> truth;
316 double truth_e = 0;
317 // same convention as PF: total for charged, visible for neutral
318 for (auto& [id, t] : by_id) {
319 truth.push_back(t);
320 int cat = category(t.pdg_);
321 truth_e += (cat <= kP) ? t.total_e_ : t.visible_e_;
322 }
323 histograms_.fill("sum_truth_e", truth_e);
324 double pf_e = 0;
325 for (const auto& c : cands) pf_e += c.getEnergy();
326 if (truth_e > 0) histograms_.fill("sum_pf_e_over_truth", pf_e / truth_e);
327
328 // charged candidates match by track ID
329 std::vector<int> cand_truth(cands.size(), -1);
330 for (size_t i = 0; i < cands.size(); i++) {
331 if (!(cands[i].getPID() & 1)) continue;
332 for (size_t j = 0; j < truth.size(); j++) {
333 if (!truth[j].matched_ &&
334 truth[j].track_id_ == cands[i].getTruthTrackId()) {
335 truth[j].matched_ = true;
336 cand_truth[i] = j;
337 break;
338 }
339 }
340 }
341
342 // neutral candidates match by position, highest energy first
343 std::vector<size_t> neutral;
344 for (size_t i = 0; i < cands.size(); i++) {
345 if (!(cands[i].getPID() & 1)) neutral.push_back(i);
346 }
347 std::sort(neutral.begin(), neutral.end(), [&cands](size_t a, size_t b) {
348 return cands[a].getEnergy() > cands[b].getEnergy();
349 });
350 for (size_t i : neutral) {
351 bool has_ecal = cands[i].getPID() & 2;
352 auto xyz =
353 has_ecal ? cands[i].getEcalClusterXYZ() : cands[i].getHcalClusterXYZ();
354 // Ecal: distance at the cluster [mm]; Hcal only: angle from the target
355 // [rad], hadron showers are wide and the side Hcal is not along z
356 auto cand_dir = direction(cands[i]);
357 int best = -1;
358 double best_d = has_ecal ? neutral_match_dist_
359 : neutral_hcal_match_angle_ * M_PI / 180.;
360 for (size_t j = 0; j < truth.size(); j++) {
361 if (truth[j].matched_) continue;
362 // fragments must not count as found particles
363 double ratio = cands[i].getEnergy() / truth[j].visible_e_;
364 if (ratio < 1. / neutral_match_max_ratio_ ||
365 ratio > neutral_match_max_ratio_)
366 continue;
367 double d;
368 if (has_ecal) {
369 auto [tx, ty] = project(truth[j], xyz[2]);
370 d = std::hypot(tx - xyz[0], ty - xyz[1]);
371 } else {
372 const auto& t = truth[j];
373 double pt = std::hypot(t.px_, t.py_, t.pz_);
374 double c =
375 (t.px_ * cand_dir[0] + t.py_ * cand_dir[1] + t.pz_ * cand_dir[2]) /
376 pt;
377 d = std::acos(std::clamp(c, -1., 1.));
378 }
379 if (d < best_d) {
380 best_d = d;
381 best = j;
382 }
383 }
384 if (best >= 0) {
385 truth[best].matched_ = true;
386 cand_truth[i] = best;
387 }
388 }
389
390 // unmatched candidates and energy response
391 std::vector<int> truth_cand(truth.size(), -1);
392 for (size_t i = 0; i < cands.size(); i++) {
393 int r_type = pfType(cands[i].getPdgId());
394 if (cand_truth[i] < 0) {
395 // last truth bin: candidates without a truth particle
396 histograms_.fill("pf_confusion", kPFNotFound, r_type);
397 if (r_type == kPFH) {
398 histograms_.fill("charged_hadron_confusion", 3,
399 massColumn(cands[i].getMass()));
400 }
401 if (!(cands[i].getPID() & 1)) {
402 histograms_.fill("unmatched_neutral_e", cands[i].getEnergy());
403 }
404 continue;
405 }
406 truth_cand[cand_truth[i]] = i;
407 const auto& t = truth[cand_truth[i]];
408 // charged energy includes the mass, calorimeters see the visible part
409 double ref = (cands[i].getPID() & 1) ? t.total_e_ : t.visible_e_;
410 if (ref > 0) {
411 histograms_.fill("response_vs_type", r_type, cands[i].getEnergy() / ref);
412 }
413 }
414
415 // sim particles give where neutral hadrons interact, and pi0 parents
416 bool has_particles =
417 event.exists(sim_particles_coll_name_, sim_particles_pass_name_);
418 std::map<int, ldmx::SimParticle> particles;
419 if (has_particles) {
420 particles = event.getMap<int, ldmx::SimParticle>(sim_particles_coll_name_,
421 sim_particles_pass_name_);
422 }
423
424 // unmatched truth with any candidate at its position: seen, but with the
425 // wrong energy or merged into another particle ("other"), not lost
426 std::vector<bool> seen(truth.size(), false);
427 for (size_t j = 0; j < truth.size(); j++) {
428 if (truth_cand[j] >= 0) continue;
429 for (const auto& cand : cands) {
430 int pid = cand.getPID();
431 if (pid & 4 && !(pid & 2)) {
432 auto d = direction(cand);
433 const auto& t = truth[j];
434 double pt = std::hypot(t.px_, t.py_, t.pz_);
435 double cs = (t.px_ * d[0] + t.py_ * d[1] + t.pz_ * d[2]) / pt;
436 if (cs > std::cos(neutral_hcal_match_angle_ * M_PI / 180.))
437 seen[j] = true;
438 } else {
439 auto xyz =
440 (pid & 2) ? cand.getEcalClusterXYZ() : cand.getEcalPositionXYZ();
441 auto [tx, ty] = project(truth[j], xyz[2]);
442 if (std::hypot(tx - xyz[0], ty - xyz[1]) < neutral_match_dist_)
443 seen[j] = true;
444 }
445 if (seen[j]) break;
446 }
447 }
448
449 // confusion per truth particle; last two reco bins: other (seen, wrong
450 // energy or merged) and not found (nothing at its position)
451 for (size_t j = 0; j < truth.size(); j++) {
452 const auto& t = truth[j];
453 int c = truth_cand[j];
454 int r_type = c >= 0 ? pfType(cands[c].getPdgId())
455 : (seen[j] ? kPFOther : kPFNotFound);
456 bool reco = reconstructable(t.pdg_, t.px_, t.py_, t.pz_, t.visible_e_);
457 histograms_.fill("pf_confusion", truthPFType(t.pdg_), r_type);
458 if (reco) {
459 histograms_.fill("pf_confusion_reconstructable", truthPFType(t.pdg_),
460 r_type);
461 }
462 int sp = category(t.pdg_);
463 if (sp == kPi || sp == kK || sp == kP) {
464 // columns: h with pi, K, p hypothesis, other, not found
465 int col = r_type == kPFH ? massColumn(cands[c].getMass())
466 : r_type == kPFNotFound ? 4
467 : 3;
468 histograms_.fill("charged_hadron_confusion", sp - kPi, col);
469 if (reco) {
470 histograms_.fill("charged_hadron_confusion_reconstructable", sp - kPi,
471 col);
472 }
473 }
474 if (sp == kNHad) {
475 // columns: h0, gamma, both gammas of a pi0, other, not found
476 int col = r_type == kPFNotFound ? 4 : 3;
477 if (r_type == kPFH0) col = 0;
478 if (r_type == kPFGamma) col = 1;
479 int region = kNoInteraction;
480 if (auto it = particles.find(t.track_id_); it != particles.end()) {
481 region = interactionRegion(it->second.getEndPoint());
482 }
483 int row = neutralRow(t.pdg_, region);
484 histograms_.fill("neutral_confusion", row, col);
485 if (reco) {
486 histograms_.fill("neutral_confusion_reconstructable", row, col);
487 }
488 }
489 }
490 for (const auto& t : truth) {
491 histograms_.fill("truth_type", category(t.pdg_));
492 if (t.matched_) histograms_.fill("truth_type_matched", category(t.pdg_));
493 if (t.pdg_ == 22) {
494 histograms_.fill("truth_gamma_e", t.visible_e_);
495 if (t.matched_) histograms_.fill("truth_gamma_e_matched", t.visible_e_);
496 }
497 }
498
499 // diphoton mass of photon pairs from the same pi0
500 if (!has_particles) return;
501 auto pi0_parent = [&particles](int track_id) {
502 auto it = particles.find(track_id);
503 if (it == particles.end() || it->second.getParents().empty()) return -1;
504 int parent = it->second.getParents()[0];
505 auto pit = particles.find(parent);
506 if (pit == particles.end() || pit->second.getPdgID() != 111) return -1;
507 return parent;
508 };
509 for (size_t a = 0; a < cands.size(); a++) {
510 if (cands[a].getPdgId() != 22 || cand_truth[a] < 0) continue;
511 int pa = pi0_parent(truth[cand_truth[a]].track_id_);
512 if (pa < 0) continue;
513 for (size_t b = a + 1; b < cands.size(); b++) {
514 if (cands[b].getPdgId() != 22 || cand_truth[b] < 0) continue;
515 if (pi0_parent(truth[cand_truth[b]].track_id_) != pa) continue;
516 auto d1 = direction(cands[a]);
517 auto d2 = direction(cands[b]);
518 double cos12 = d1[0] * d2[0] + d1[1] * d2[1] + d1[2] * d2[2];
519 double m2 = 2 * cands[a].getEnergy() * cands[b].getEnergy() * (1 - cos12);
520 histograms_.fill("mgg_pi0_matched", std::sqrt(std::max(0., m2)));
521 }
522 }
523 // truth pi0 photons entering the Ecal, for the pair efficiency
524 std::map<int, std::vector<int>> pi0_photons;
525 for (size_t j = 0; j < truth.size(); j++) {
526 if (truth[j].pdg_ != 22) continue;
527 int pa = pi0_parent(truth[j].track_id_);
528 if (pa >= 0) pi0_photons[pa].push_back(j);
529 }
530 for (const auto& [pa, photons] : pi0_photons) {
531 histograms_.fill("truth_pi0_photons_in_ecal", photons.size());
532 if (photons.size() < 2) continue;
533 // pi0 row of the neutral matrix, both photons at the Ecal face
534 int n_gamma = 0, n_h0 = 0, n_seen = 0;
535 for (int j : photons) {
536 int c = truth_cand[j];
537 n_seen += c >= 0 || seen[j];
538 if (c < 0) continue;
539 int r_type = pfType(cands[c].getPdgId());
540 n_gamma += r_type == kPFGamma;
541 n_h0 += r_type == kPFH0;
542 }
543 int col = n_seen > 0 ? 3 : 4;
544 if (n_gamma >= 2)
545 col = 2;
546 else if (n_h0 > 0)
547 col = 0;
548 else if (n_gamma == 1)
549 col = 1;
550 histograms_.fill("neutral_confusion", 6, col);
551 const auto& pi0 = particles.at(pa);
552 double pi0_ke = pi0.getEnergy() - pi0.getMass();
553 double pi0_theta = std::acos(
554 pi0.getMomentum()[2] /
555 std::max(1e-9, std::hypot(pi0.getMomentum()[0], pi0.getMomentum()[1],
556 pi0.getMomentum()[2])));
557 if (pi0_ke > reco_min_ke_pi0_ &&
558 pi0_theta < reco_max_theta_ * M_PI / 180.) {
559 histograms_.fill("neutral_confusion_reconstructable", 6, col);
560 }
561 }
562}
Class representing a simulated particle.
Definition SimParticle.h:25
Represents a simulated tracker hit in the simulation.

◆ configure()

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

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 166 of file ParticleFlowDQM.cxx.

166 {
167 pf_cand_coll_name_ = ps.get<std::string>("pf_cand_coll_name");
168 pf_cand_pass_name_ = ps.get<std::string>("pf_cand_pass_name");
169 ecal_sp_coll_name_ = ps.get<std::string>("ecal_sp_coll_name");
170 ecal_sp_pass_name_ = ps.get<std::string>("ecal_sp_pass_name");
171 sim_particles_coll_name_ = ps.get<std::string>("sim_particles_coll_name");
172 sim_particles_pass_name_ = ps.get<std::string>("sim_particles_pass_name");
173 truth_min_energy_ = ps.get<double>("truth_min_energy");
174 neutral_match_dist_ = ps.get<double>("neutral_match_dist");
175 neutral_match_max_ratio_ = ps.get<double>("neutral_match_max_ratio");
176 neutral_hcal_match_angle_ = ps.get<double>("neutral_hcal_match_angle");
177 reco_max_theta_ = ps.get<double>("reco_max_theta");
178 reco_min_p_pion_ = ps.get<double>("reco_min_p_pion");
179 reco_min_p_heavy_ = ps.get<double>("reco_min_p_heavy");
180 reco_min_ke_neutral_ = ps.get<double>("reco_min_ke_neutral");
181 reco_min_ke_pi0_ = ps.get<double>("reco_min_ke_pi0");
182 ecal_back_z_ = ps.get<double>("ecal_back_z");
183 ecal_half_xy_ = ps.get<double>("ecal_half_xy");
184 hcal_max_z_ = ps.get<double>("hcal_max_z");
185 hcal_max_xy_ = ps.get<double>("hcal_max_xy");
186}

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

◆ interactionRegion()

int dqm::ParticleFlowDQM::interactionRegion ( const std::vector< double > & end) const
private

Definition at line 155 of file ParticleFlowDQM.cxx.

155 {
156 double x = std::abs(end[0]), y = std::abs(end[1]), z = end[2];
157 if (x > hcal_max_xy_ || y > hcal_max_xy_ || z > hcal_max_z_ || z < 0)
158 return kNoInteraction;
159 if (z < ecal_back_z_) {
160 return (x < ecal_half_xy_ && y < ecal_half_xy_) ? kRegionEcal
161 : kRegionSideHcal;
162 }
163 return kRegionBackHcal;
164}

◆ reconstructable()

bool dqm::ParticleFlowDQM::reconstructable ( int pdg,
double px,
double py,
double pz,
double ke ) const
private

Definition at line 136 of file ParticleFlowDQM.cxx.

137 {
138 double p = std::hypot(px, py, pz);
139 if (p <= 0 || std::acos(pz / p) > reco_max_theta_ * M_PI / 180.) return false;
140 switch (category(pdg)) {
141 case kPi:
142 return p > reco_min_p_pion_;
143 case kK:
144 case kP:
145 return p > reco_min_p_heavy_;
146 case kNHad:
147 return ke > reco_min_ke_neutral_;
148 default:
149 return true;
150 }
151}

Member Data Documentation

◆ ecal_back_z_

double dqm::ParticleFlowDQM::ecal_back_z_ {760.}
private

Definition at line 59 of file ParticleFlowDQM.h.

59{760.};

◆ ecal_half_xy_

double dqm::ParticleFlowDQM::ecal_half_xy_ {300.}
private

Definition at line 60 of file ParticleFlowDQM.h.

60{300.};

◆ ecal_sp_coll_name_

std::string dqm::ParticleFlowDQM::ecal_sp_coll_name_ {"EcalScoringPlaneHits"}
private

Definition at line 38 of file ParticleFlowDQM.h.

38{"EcalScoringPlaneHits"};

◆ ecal_sp_pass_name_

std::string dqm::ParticleFlowDQM::ecal_sp_pass_name_ {""}
private

Definition at line 39 of file ParticleFlowDQM.h.

39{""};

◆ hcal_max_xy_

double dqm::ParticleFlowDQM::hcal_max_xy_ {1600.}
private

Definition at line 62 of file ParticleFlowDQM.h.

62{1600.};

◆ hcal_max_z_

double dqm::ParticleFlowDQM::hcal_max_z_ {4000.}
private

Definition at line 61 of file ParticleFlowDQM.h.

61{4000.};

◆ neutral_hcal_match_angle_

double dqm::ParticleFlowDQM::neutral_hcal_match_angle_ {30.}
private

Definition at line 49 of file ParticleFlowDQM.h.

49{30.};

◆ neutral_match_dist_

double dqm::ParticleFlowDQM::neutral_match_dist_ {30.}
private

Definition at line 45 of file ParticleFlowDQM.h.

45{30.};

◆ neutral_match_max_ratio_

double dqm::ParticleFlowDQM::neutral_match_max_ratio_ {2.}
private

Definition at line 47 of file ParticleFlowDQM.h.

47{2.};

◆ pf_cand_coll_name_

std::string dqm::ParticleFlowDQM::pf_cand_coll_name_ {"PFCandidates"}
private

Definition at line 36 of file ParticleFlowDQM.h.

36{"PFCandidates"};

◆ pf_cand_pass_name_

std::string dqm::ParticleFlowDQM::pf_cand_pass_name_ {""}
private

Definition at line 37 of file ParticleFlowDQM.h.

37{""};

◆ reco_max_theta_

double dqm::ParticleFlowDQM::reco_max_theta_ {80.}
private

Definition at line 52 of file ParticleFlowDQM.h.

52{80.};

◆ reco_min_ke_neutral_

double dqm::ParticleFlowDQM::reco_min_ke_neutral_ {1000.}
private

Definition at line 55 of file ParticleFlowDQM.h.

55{1000.};

◆ reco_min_ke_pi0_

double dqm::ParticleFlowDQM::reco_min_ke_pi0_ {2000.}
private

Definition at line 56 of file ParticleFlowDQM.h.

56{2000.};

◆ reco_min_p_heavy_

double dqm::ParticleFlowDQM::reco_min_p_heavy_ {800.}
private

Definition at line 54 of file ParticleFlowDQM.h.

54{800.};

◆ reco_min_p_pion_

double dqm::ParticleFlowDQM::reco_min_p_pion_ {100.}
private

Definition at line 53 of file ParticleFlowDQM.h.

53{100.};

◆ sim_particles_coll_name_

std::string dqm::ParticleFlowDQM::sim_particles_coll_name_ {"SimParticles"}
private

Definition at line 40 of file ParticleFlowDQM.h.

40{"SimParticles"};

◆ sim_particles_pass_name_

std::string dqm::ParticleFlowDQM::sim_particles_pass_name_ {""}
private

Definition at line 41 of file ParticleFlowDQM.h.

41{""};

◆ truth_min_energy_

double dqm::ParticleFlowDQM::truth_min_energy_ {50.}
private

Definition at line 43 of file ParticleFlowDQM.h.

43{50.};

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