11 const std::map<int, ldmx::SimParticle> &particleMap,
13 std::vector<const ldmx::SimParticle *> pnDaughters;
14 for (
const auto &daughterTrackID : parent->
getDaughters()) {
16 if (particleMap.count(daughterTrackID) == 0) {
20 auto daughter{&(particleMap.at(daughterTrackID))};
23 auto pdgID{daughter->getPdgID()};
27 (pdgID > 10000 && (!count_light_ions_ || !
isLightIon(pdgID)))) {
30 pnDaughters.push_back(daughter);
33 std::sort(pnDaughters.begin(), pnDaughters.end(),
34 [](
const auto &lhs,
const auto &rhs) {
35 double lhs_ke = lhs->getEnergy() - lhs->getMass();
36 double rhs_ke = rhs->getEnergy() - rhs->getMass();
37 return lhs_ke > rhs_ke;
50 const std::vector<const ldmx::SimParticle *> &pnDaughters) {
51 double hardest_ke{-1}, hardest_theta{-1};
52 double hardest_proton_ke{-1}, hardest_proton_theta{-1};
53 double hardest_neutron_ke{-1}, hardest_neutron_theta{-1};
54 double hardest_pion_ke{-1}, hardest_pion_theta{-1};
56 double total_neutron_ke{0};
57 int neutron_multiplicity{0};
60 for (
const auto *daughter : pnDaughters) {
64 auto pdgID{daughter->getPdgID()};
67 double ke{daughter->getEnergy() - daughter->getMass()};
70 std::vector<double> vec{daughter->getMomentum()};
71 TVector3 pvec(vec[0], vec[1], vec[2]);
74 auto theta{pvec.Theta() * (180 / 3.14159)};
76 if (hardest_ke < ke) {
78 hardest_theta = theta;
82 total_neutron_ke += ke;
83 neutron_multiplicity++;
84 if (hardest_neutron_ke < ke) {
85 hardest_neutron_ke = ke;
86 hardest_neutron_theta = theta;
90 if ((pdgID == 2212) && (hardest_proton_ke < ke)) {
91 hardest_proton_ke = ke;
92 hardest_proton_theta = theta;
95 if (((std::abs(pdgID) == 211) || (pdgID == 111)) &&
96 (hardest_pion_ke < ke)) {
98 hardest_pion_theta = theta;
118 const std::vector<const ldmx::SimParticle *> &pnDaughters,
119 const PhotoNuclearDQM::EventType eventType) {
122 double subleading_ke{-9999};
123 double nEnergy{-9999}, energyDiff{-9999}, energyFrac{-9999};
125 nEnergy = pnDaughters[0]->getEnergy() - pnDaughters[0]->getMass();
126 subleading_ke = -9999;
127 if (pnDaughters.size() > 1) {
128 subleading_ke = pnDaughters[1]->getEnergy() - pnDaughters[1]->getMass();
130 energyDiff = pnGamma->
getEnergy() - nEnergy;
131 energyFrac = nEnergy / pnGamma->
getEnergy();
133 if (eventType == EventType::single_neutron) {
138 }
else if (eventType == EventType::two_neutrons) {
140 auto energyFrac2n = (nEnergy + subleading_ke) / pnGamma->
getEnergy();
144 }
else if (eventType == EventType::charged_kaon) {
149 }
else if (eventType == EventType::klong || eventType == EventType::kshort) {
228 if (particleMap.size() == 0) {
233 auto [trackID, recoil] = Analysis::getRecoil(particleMap);
238 auto pnGamma{Analysis::getPNGamma(particleMap, recoil, 2500.)};
239 if (pnGamma ==
nullptr) {
240 ldmx_log(warn) <<
"PN Daughter is lost, skipping";
246 if (!pnDaughters.empty()) {
247 auto pn_vertex_volume{pnDaughters[0]->getVertexVolume()};
248 auto pn_interaction_material{pnDaughters[0]->getInteractionMaterial()};
251 if (pn_vertex_volume.find(
"W_cooling") != std::string::npos) {
254 }
else if (pn_vertex_volume.find(
"C_volume") != std::string::npos) {
257 }
else if (pn_vertex_volume.find(
"PCB_volume") != std::string::npos) {
259 }
else if (pn_vertex_volume.find(
"CarbonBasePlate") != std::string::npos) {
262 }
else if (pn_vertex_volume.find(
"W_front") != std::string::npos) {
265 }
else if (pn_vertex_volume.find(
"Si_volume") != std::string::npos) {
267 }
else if (pn_vertex_volume.find(
"Glue") != std::string::npos) {
269 }
else if (pn_vertex_volume.find(
"motherboard") != std::string::npos) {
273 ldmx_log(debug) <<
" Else pn_vertex_volume = " << pn_vertex_volume
274 <<
" with pn_interaction_material = "
275 << pn_interaction_material;
280 if (pn_interaction_material.find(
"G4_Si") != std::string::npos) {
282 }
else if (pn_interaction_material.find(
"G4_W") != std::string::npos) {
284 }
else if (pn_interaction_material.find(
"FR4") != std::string::npos) {
287 }
else if (pn_interaction_material.find(
"Steel") != std::string::npos) {
289 }
else if (pn_interaction_material.find(
"Epoxy") != std::string::npos) {
292 }
else if (pn_interaction_material.find(
"Scintillator") !=
296 }
else if (pn_interaction_material.find(
"Glue") != std::string::npos) {
299 }
else if (pn_interaction_material.find(
"G4_AIR") != std::string::npos) {
303 ldmx_log(debug) <<
" Else pn_interaction_material = "
304 << pn_interaction_material
305 <<
" with pn_vertex_volume = " << pn_vertex_volume;
319 histograms_.
fill(
"pn_gamma_int_x:pn_gamma_int_y", pnGamma->getEndPoint()[0],
320 pnGamma->getEndPoint()[1]);
336 histograms_.
fill(
"event_type_500mev",
static_cast<int>(eventType500MeV));
337 histograms_.
fill(
"event_type_2000mev",
static_cast<int>(eventType2000MeV));
339 histograms_.
fill(
"event_type_compact",
static_cast<int>(eventTypeComp));
341 static_cast<int>(eventTypeComp500MeV));
343 static_cast<int>(eventTypeComp2000MeV));
346 case EventType::single_neutron:
347 if (pnDaughters.size() > 1) {
348 auto secondHardestPdgID{abs(pnDaughters[1]->getPdgID())};
349 auto nEventType{-10};
350 if (secondHardestPdgID == 2112) {
352 }
else if (secondHardestPdgID == 2212) {
354 }
else if (secondHardestPdgID == 211) {
356 }
else if (secondHardestPdgID == 111) {
364 case EventType::two_neutrons:
365 case EventType::charged_kaon:
366 case EventType::klong:
367 case EventType::kshort:
376 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
377 short n{0}, p{0}, pi{0}, pi0{0}, exotic{0}, k0l{0}, kp{0}, k0s{0};
381 for (
const auto &daughter : daughters) {
383 auto ke{daughter->getEnergy() - daughter->getMass()};
388 if (ke <= threshold) {
393 auto pdgID{abs(daughter->getPdgID())};
397 }
else if (pdgID == 2212) {
399 }
else if (pdgID == 211) {
401 }
else if (pdgID == 111) {
403 }
else if (pdgID == 130) {
405 }
else if (pdgID == 321) {
407 }
else if (pdgID == 310) {
414 int kaons = k0l + kp + k0s;
415 int nucleons = n + p;
416 int pions = pi + pi0;
417 int count = nucleons + pions + exotic + kaons;
420 return EventType::nothing_hard;
424 return EventType::single_neutron;
426 return EventType::single_proton;
427 }
else if (pi0 == 1) {
428 return EventType::single_neutral_pion;
429 }
else if (pi == 1) {
430 return EventType::single_charged_pion;
435 return EventType::two_neutrons;
436 }
else if (n == 1 && p == 1) {
437 return EventType::proton_neutron;
439 return EventType::two_protons;
440 }
else if (pi == 2) {
441 return EventType::two_charged_pions;
442 }
else if (pi == 1 && nucleons == 1) {
443 return EventType::single_charged_pion_and_nucleon;
444 }
else if (pi0 == 1 && nucleons == 1) {
445 return EventType::single_neutral_pion_and_nucleon;
450 if (pi == 1 && nucleons == 2) {
451 return EventType::single_charged_pion_and_two_nucleons;
452 }
else if (pi == 2 && nucleons == 1) {
453 return EventType::two_charged_pions_and_nucleon;
455 else if (pi0 == 1 && nucleons == 2) {
456 return EventType::single_neutral_pion_and_two_nucleons;
457 }
else if (pi0 == 1 && nucleons == 1 && pi == 1) {
458 return EventType::single_neutral_pion_charged_pion_and_nucleon;
461 if (count >= 3 && count == n) {
462 return EventType::three_or_more_neutrons;
467 return EventType::klong;
468 }
else if (kp == 1) {
469 return EventType::charged_kaon;
470 }
else if (k0s == 1) {
471 return EventType::kshort;
474 if (exotic == count && count != 0) {
475 return EventType::exotics;
478 return EventType::multibody;
483 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
484 short n{0}, n_t{0}, k0l{0}, kp{0}, k0s{0}, soft{0};
488 for (
const auto &daughter : daughters) {
490 auto ke{daughter->getEnergy() - daughter->getMass()};
493 auto pdgID{abs(daughter->getPdgID())};
503 }
else if (pdgID == 130) {
505 }
else if (pdgID == 321) {
507 }
else if (pdgID == 310) {
513 if ((pdgID == 2112) && ke > threshold) {
518 int neutral_kaons{k0l + k0s};
521 return PhotoNuclearDQM::CompactEventType::single_neutron;
524 return PhotoNuclearDQM::CompactEventType::single_charged_kaon;
526 if (neutral_kaons != 0) {
527 return PhotoNuclearDQM::CompactEventType::single_neutral_kaon;
530 return PhotoNuclearDQM::CompactEventType::two_neutrons;
532 if (soft == daughters.size()) {
533 return PhotoNuclearDQM::CompactEventType::soft;
536 return PhotoNuclearDQM::CompactEventType::other;
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.