2#include "DQM/PhotoNuclearDQM.h"
31 const std::map<int, ldmx::SimParticle> &particleMap,
33 std::vector<const ldmx::SimParticle *> pnDaughters;
34 for (
const auto &daughterTrackID : parent->
getDaughters()) {
36 if (particleMap.count(daughterTrackID) == 0) {
40 auto daughter{&(particleMap.at(daughterTrackID))};
43 auto pdgID{daughter->getPdgID()};
47 (pdgID > 10000 && (!count_light_ions_ || !
isLightIon(pdgID)))) {
50 pnDaughters.push_back(daughter);
53 std::sort(pnDaughters.begin(), pnDaughters.end(),
54 [](
const auto &lhs,
const auto &rhs) {
55 double lhs_ke = lhs->getEnergy() - lhs->getMass();
56 double rhs_ke = rhs->getEnergy() - rhs->getMass();
57 return lhs_ke > rhs_ke;
70 const std::vector<const ldmx::SimParticle *> &pnDaughters) {
71 double hardest_ke{-1}, hardest_theta{-1};
72 double hardest_proton_ke{-1}, hardest_proton_theta{-1};
73 double hardest_neutron_ke{-1}, hardest_neutron_theta{-1};
74 double hardest_pion_ke{-1}, hardest_pion_theta{-1};
76 double total_neutron_ke{0};
77 int neutron_multiplicity{0};
80 for (
const auto *daughter : pnDaughters) {
84 auto pdgID{daughter->getPdgID()};
87 double ke{daughter->getEnergy() - daughter->getMass()};
90 std::vector<double> vec{daughter->getMomentum()};
91 TVector3 pvec(vec[0], vec[1], vec[2]);
94 auto theta{pvec.Theta() * (180 / 3.14159)};
96 if (hardest_ke < ke) {
98 hardest_theta = theta;
102 total_neutron_ke += ke;
103 neutron_multiplicity++;
104 if (hardest_neutron_ke < ke) {
105 hardest_neutron_ke = ke;
106 hardest_neutron_theta = theta;
110 if ((pdgID == 2212) && (hardest_proton_ke < ke)) {
111 hardest_proton_ke = ke;
112 hardest_proton_theta = theta;
115 if (((std::abs(pdgID) == 211) || (pdgID == 111)) &&
116 (hardest_pion_ke < ke)) {
117 hardest_pion_ke = ke;
118 hardest_pion_theta = theta;
138 const std::vector<const ldmx::SimParticle *> &pnDaughters,
139 const PhotoNuclearDQM::EventType eventType) {
142 double subleading_ke{-9999};
143 double nEnergy{-9999}, energyDiff{-9999}, energyFrac{-9999};
145 nEnergy = pnDaughters[0]->getEnergy() - pnDaughters[0]->getMass();
146 subleading_ke = -9999;
147 if (pnDaughters.size() > 1) {
148 subleading_ke = pnDaughters[1]->getEnergy() - pnDaughters[1]->getMass();
150 energyDiff = pnGamma->
getEnergy() - nEnergy;
151 energyFrac = nEnergy / pnGamma->
getEnergy();
153 if (eventType == EventType::single_neutron) {
158 }
else if (eventType == EventType::two_neutrons) {
160 auto energyFrac2n = (nEnergy + subleading_ke) / pnGamma->
getEnergy();
164 }
else if (eventType == EventType::charged_kaon) {
169 }
else if (eventType == EventType::klong || eventType == EventType::kshort) {
177 std::vector<std::string> labels = {
"",
201 std::vector<TH1 *> hists = {
208 for (
int ilabel{1}; ilabel < labels.size(); ++ilabel) {
209 for (
auto &hist : hists) {
210 hist->GetXaxis()->SetBinLabel(ilabel, labels[ilabel - 1].c_str());
229 for (
int ilabel{1}; ilabel < labels.size(); ++ilabel) {
230 for (
auto &hist : hists) {
231 hist->GetXaxis()->SetBinLabel(ilabel, labels[ilabel - 1].c_str());
235 std::vector<std::string> n_labels = {
"",
244 for (
int ilabel{1}; ilabel < n_labels.size(); ++ilabel) {
245 hist->GetXaxis()->SetBinLabel(ilabel, n_labels[ilabel - 1].c_str());
251 count_light_ions_ = parameters.
getParameter<
bool>(
"count_light_ions",
true);
258 if (particleMap.size() == 0) {
263 auto [trackID, recoil] = Analysis::getRecoil(particleMap);
268 auto pnGamma{Analysis::getPNGamma(particleMap, recoil, 2500.)};
269 if (pnGamma ==
nullptr) {
271 std::cout <<
"[ PhotoNuclearDQM ]: PN Daughter is lost, skipping."
296 histograms_.
fill(
"event_type_500mev",
static_cast<int>(eventType500MeV));
297 histograms_.
fill(
"event_type_2000mev",
static_cast<int>(eventType2000MeV));
299 histograms_.
fill(
"event_type_compact",
static_cast<int>(eventTypeComp));
301 static_cast<int>(eventTypeComp500MeV));
303 static_cast<int>(eventTypeComp2000MeV));
306 case EventType::single_neutron:
307 if (pnDaughters.size() > 1) {
308 auto secondHardestPdgID{abs(pnDaughters[1]->getPdgID())};
309 auto nEventType{-10};
310 if (secondHardestPdgID == 2112) {
312 }
else if (secondHardestPdgID == 2212) {
314 }
else if (secondHardestPdgID == 211) {
316 }
else if (secondHardestPdgID == 111) {
324 case EventType::two_neutrons:
325 case EventType::charged_kaon:
326 case EventType::klong:
327 case EventType::kshort:
336 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
337 short n{0}, p{0}, pi{0}, pi0{0}, exotic{0}, k0l{0}, kp{0}, k0s{0};
341 for (
const auto &daughter : daughters) {
343 auto ke{daughter->getEnergy() - daughter->getMass()};
348 if (ke <= threshold) {
353 auto pdgID{abs(daughter->getPdgID())};
357 }
else if (pdgID == 2212) {
359 }
else if (pdgID == 211) {
361 }
else if (pdgID == 111) {
363 }
else if (pdgID == 130) {
365 }
else if (pdgID == 321) {
367 }
else if (pdgID == 310) {
374 int kaons = k0l + kp + k0s;
375 int nucleons = n + p;
376 int pions = pi + pi0;
377 int count = nucleons + pions + exotic + kaons;
380 return EventType::nothing_hard;
384 return EventType::single_neutron;
386 return EventType::single_proton;
387 }
else if (pi0 == 1) {
388 return EventType::single_neutral_pion;
389 }
else if (pi == 1) {
390 return EventType::single_charged_pion;
395 return EventType::two_neutrons;
396 }
else if (n == 1 && p == 1) {
397 return EventType::proton_neutron;
399 return EventType::two_protons;
400 }
else if (pi == 2) {
401 return EventType::two_charged_pions;
402 }
else if (pi == 1 && nucleons == 1) {
403 return EventType::single_charged_pion_and_nucleon;
404 }
else if (pi0 == 1 && nucleons == 1) {
405 return EventType::single_neutral_pion_and_nucleon;
410 if (pi == 1 && nucleons == 2) {
411 return EventType::single_charged_pion_and_two_nucleons;
412 }
else if (pi == 2 && nucleons == 1) {
413 return EventType::two_charged_pions_and_nucleon;
415 else if (pi0 == 1 && nucleons == 2) {
416 return EventType::single_neutral_pion_and_two_nucleons;
417 }
else if (pi0 == 1 && nucleons == 1 && pi == 1) {
418 return EventType::single_neutral_pion_charged_pion_and_nucleon;
421 if (count >= 3 && count == n) {
422 return EventType::three_or_more_neutrons;
427 return EventType::klong;
428 }
else if (kp == 1) {
429 return EventType::charged_kaon;
430 }
else if (k0s == 1) {
431 return EventType::kshort;
434 if (exotic == count && count != 0) {
435 return EventType::exotics;
438 return EventType::multibody;
443 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
444 short n{0}, n_t{0}, k0l{0}, kp{0}, k0s{0}, soft{0};
448 for (
const auto &daughter : daughters) {
450 auto ke{daughter->getEnergy() - daughter->getMass()};
453 auto pdgID{abs(daughter->getPdgID())};
463 }
else if (pdgID == 130) {
465 }
else if (pdgID == 321) {
467 }
else if (pdgID == 310) {
473 if ((pdgID == 2112) && ke > threshold) {
478 int neutral_kaons{k0l + k0s};
481 return PhotoNuclearDQM::CompactEventType::single_neutron;
484 return PhotoNuclearDQM::CompactEventType::single_charged_kaon;
486 if (neutral_kaons != 0) {
487 return PhotoNuclearDQM::CompactEventType::single_neutral_kaon;
490 return PhotoNuclearDQM::CompactEventType::two_neutrons;
492 if (soft == daughters.size()) {
493 return PhotoNuclearDQM::CompactEventType::soft;
496 return PhotoNuclearDQM::CompactEventType::other;
Collection of utility functions useful for analysis.
#define DECLARE_ANALYZER_NS(NS, CLASS)
Macro which allows the framework to construct an analyzer given its name during configuration.
Class implementing an event buffer system for storing event data.
PhotoNuclearDQM(const std::string &name, framework::Process &process)
Constructor.
void findSubleadingKinematics(const ldmx::SimParticle *pnGamma, const std::vector< const ldmx::SimParticle * > &pnDaughters, const EventType eventType)
Fill histograms related to the kinematics and subleading particles for 1n, kaon, and 2n type events.
constexpr bool isLightIon(const int pdgCode) const
Check if the PDG code corresponds to a light ion.
std::vector< const ldmx::SimParticle * > findDaughters(const std::map< int, ldmx::SimParticle > &particleMap, const ldmx::SimParticle *parent) const
Find all daughter particles of a parent.
void analyze(const framework::Event &event) override
Process the event and create the histogram summaries.
EventType classifyEvent(const std::vector< const ldmx::SimParticle * > daughters, double threshold)
Method used to classify events.
void onProcessStart() override
Method executed before processing of events begins.
CompactEventType classifyCompactEvent(const ldmx::SimParticle *pnGamma, const std::vector< const ldmx::SimParticle * > daughters, double threshold)
Method used to classify events in a compact manner.
virtual ~PhotoNuclearDQM()
Destructor.
void findRecoilProperties(const ldmx::SimParticle *recoil)
Fill the recoil electron-histograms.
void findParticleKinematics(const std::vector< const ldmx::SimParticle * > &pnDaughters)
Fill histograms related to kinematics of PN products.
void configure(framework::config::Parameters ¶meters) override
Configure this analyzer using the user specified parameters.
HistogramHelper histograms_
Interface class for making and filling histograms.
Implements an event buffer system for storing event data.
TH1 * get(const std::string &name)
Get a pointer to a histogram by name.
void fill(const std::string &name, const double &val)
Fill a 1D histogram.
Class which represents the process under execution.
Class encapsulating parameters for configuring a processor.
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Class representing a simulated particle.
double getEnergy() const
Get the energy of this particle [MeV].
std::vector< double > getVertex() const
Get a vector containing the vertex of this particle in mm.
std::vector< int > getDaughters() const
Get a vector containing the track IDs of all daughter particles.
All classes in the ldmx-sw project use this namespace.