11 const std::map<int, ldmx::SimParticle> &particleMap,
13 std::vector<const ldmx::SimParticle *> pn_daughters;
14 for (
const auto &daughter_track_id : parent->
getDaughters()) {
16 if (particleMap.count(daughter_track_id) == 0) {
20 auto daughter{&(particleMap.at(daughter_track_id))};
23 auto pdg_id{daughter->getPdgID()};
27 (pdg_id > 10000 && (!count_light_ions_ || !
isLightIon(pdg_id)))) {
30 pn_daughters.push_back(daughter);
33 std::sort(pn_daughters.begin(), pn_daughters.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 pdg_id{daughter->getPdgID()};
67 double ke{daughter->getEnergy() - daughter->getMass()};
70 std::vector<double> vec{daughter->getMomentum()};
71 ROOT::Math::XYZVector 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 ((pdg_id == 2212) && (hardest_proton_ke < ke)) {
91 hardest_proton_ke = ke;
92 hardest_proton_theta = theta;
95 if (((std::abs(pdg_id) == 211) || (pdg_id == 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 n_energy{-9999}, energy_diff{-9999}, energy_frac{-9999};
125 n_energy = 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 energy_diff = pnGamma->
getEnergy() - n_energy;
131 energy_frac = n_energy / pnGamma->
getEnergy();
133 if (eventType == EventType::single_neutron) {
138 }
else if (eventType == EventType::two_neutrons) {
140 auto energy_frac2n = (n_energy + subleading_ke) / pnGamma->
getEnergy();
144 }
else if (eventType == EventType::charged_kaon) {
149 }
else if (eventType == EventType::klong || eventType == EventType::kshort) {
169 sim_particles_coll_name_, sim_particles_passname_)};
170 if (particle_map.size() == 0) {
175 auto [trackID, recoil] = analysis::getRecoil(particle_map);
180 auto pn_gamma{analysis::getPNGamma(particle_map, recoil, 2500.)};
181 if (pn_gamma ==
nullptr) {
182 ldmx_log(warn) <<
"PN Daughter is lost, skipping";
186 const auto pn_daughters{
findDaughters(particle_map, pn_gamma)};
188 if (!pn_daughters.empty()) {
189 auto pn_vertex_volume{pn_daughters[0]->getVertexVolume()};
190 auto pn_interaction_material{pn_daughters[0]->getInteractionMaterial()};
193 if (pn_vertex_volume.find(
"W_cooling") != std::string::npos) {
196 }
else if (pn_vertex_volume.find(
"C_volume") != std::string::npos) {
199 }
else if (pn_vertex_volume.find(
"PCB_volume") != std::string::npos) {
201 }
else if (pn_vertex_volume.find(
"CarbonBasePlate") != std::string::npos) {
204 }
else if (pn_vertex_volume.find(
"W_front") != std::string::npos) {
207 }
else if (pn_vertex_volume.find(
"Si_volume") != std::string::npos) {
209 }
else if (pn_vertex_volume.find(
"Glue") != std::string::npos) {
211 }
else if (pn_vertex_volume.find(
"motherboard") != std::string::npos) {
215 ldmx_log(debug) <<
" Else pn_vertex_volume = " << pn_vertex_volume
216 <<
" with pn_interaction_material = "
217 << pn_interaction_material;
222 if (pn_interaction_material.find(
"Silicon") != std::string::npos ||
223 pn_interaction_material.find(
"G4_Si") != std::string::npos) {
225 }
else if (pn_interaction_material.find(
"Tungsten") != std::string::npos ||
226 pn_interaction_material.find(
"G4_W") != std::string::npos) {
228 }
else if (pn_interaction_material.find(
"FR4") != std::string::npos) {
231 }
else if (pn_interaction_material.find(
"Steel") != std::string::npos) {
233 }
else if (pn_interaction_material.find(
"Epoxy") != std::string::npos) {
236 }
else if (pn_interaction_material.find(
"Scintillator") !=
240 }
else if (pn_interaction_material.find(
"Glue") != std::string::npos) {
243 }
else if (pn_interaction_material.find(
"Air") != std::string::npos ||
244 pn_interaction_material.find(
"G4_AIR") != std::string::npos) {
248 ldmx_log(debug) <<
" Else pn_interaction_material = "
249 << pn_interaction_material
250 <<
" with pn_vertex_volume = " << pn_vertex_volume;
264 histograms_.
fill(
"pn_gamma_int_x:pn_gamma_int_y", pn_gamma->getEndPoint()[0],
265 pn_gamma->getEndPoint()[1]);
277 auto event_type_comp500_me_v{
279 auto event_type_comp2000_me_v{
283 histograms_.
fill(
"event_type_500mev",
static_cast<int>(event_type500_me_v));
284 histograms_.
fill(
"event_type_2000mev",
static_cast<int>(event_type2000_me_v));
286 histograms_.
fill(
"event_type_compact",
static_cast<int>(event_type_comp));
288 static_cast<int>(event_type_comp500_me_v));
290 static_cast<int>(event_type_comp2000_me_v));
292 switch (event_type) {
293 case EventType::single_neutron:
294 if (pn_daughters.size() > 1) {
295 auto second_hardest_pdg_id{abs(pn_daughters[1]->getPdgID())};
296 auto n_event_type{-10};
297 if (second_hardest_pdg_id == 2112) {
299 }
else if (second_hardest_pdg_id == 2212) {
301 }
else if (second_hardest_pdg_id == 211) {
303 }
else if (second_hardest_pdg_id == 111) {
311 case EventType::two_neutrons:
312 case EventType::charged_kaon:
313 case EventType::klong:
314 case EventType::kshort:
323 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
324 short n{0}, p{0}, pi{0}, pi0{0}, exotic{0}, k0l{0}, kp{0}, k0s{0};
328 for (
const auto &daughter : daughters) {
330 auto ke{daughter->getEnergy() - daughter->getMass()};
335 if (ke <= threshold) {
340 auto pdg_id{abs(daughter->getPdgID())};
342 if (pdg_id == 2112) {
344 }
else if (pdg_id == 2212) {
346 }
else if (pdg_id == 211) {
348 }
else if (pdg_id == 111) {
350 }
else if (pdg_id == 130) {
352 }
else if (pdg_id == 321) {
354 }
else if (pdg_id == 310) {
361 int kaons = k0l + kp + k0s;
362 int nucleons = n + p;
363 int pions = pi + pi0;
364 int count = nucleons + pions + exotic + kaons;
367 return EventType::nothing_hard;
371 return EventType::single_neutron;
373 return EventType::single_proton;
374 }
else if (pi0 == 1) {
375 return EventType::single_neutral_pion;
376 }
else if (pi == 1) {
377 return EventType::single_charged_pion;
382 return EventType::two_neutrons;
383 }
else if (n == 1 && p == 1) {
384 return EventType::proton_neutron;
386 return EventType::two_protons;
387 }
else if (pi == 2) {
388 return EventType::two_charged_pions;
389 }
else if (pi == 1 && nucleons == 1) {
390 return EventType::single_charged_pion_and_nucleon;
391 }
else if (pi0 == 1 && nucleons == 1) {
392 return EventType::single_neutral_pion_and_nucleon;
397 if (pi == 1 && nucleons == 2) {
398 return EventType::single_charged_pion_and_two_nucleons;
399 }
else if (pi == 2 && nucleons == 1) {
400 return EventType::two_charged_pions_and_nucleon;
402 else if (pi0 == 1 && nucleons == 2) {
403 return EventType::single_neutral_pion_and_two_nucleons;
404 }
else if (pi0 == 1 && nucleons == 1 && pi == 1) {
405 return EventType::single_neutral_pion_charged_pion_and_nucleon;
408 if (count >= 3 && count == n) {
409 return EventType::three_or_more_neutrons;
414 return EventType::klong;
415 }
else if (kp == 1) {
416 return EventType::charged_kaon;
417 }
else if (k0s == 1) {
418 return EventType::kshort;
421 if (exotic == count && count != 0) {
422 return EventType::exotics;
425 return EventType::multibody;
430 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
431 short n{0}, n_t{0}, k0l{0}, kp{0}, k0s{0}, soft{0};
435 for (
const auto &daughter : daughters) {
437 auto ke{daughter->getEnergy() - daughter->getMass()};
440 auto pdg_id{abs(daughter->getPdgID())};
448 if (pdg_id == 2112) {
450 }
else if (pdg_id == 130) {
452 }
else if (pdg_id == 321) {
454 }
else if (pdg_id == 310) {
460 if ((pdg_id == 2112) && ke > threshold) {
465 int neutral_kaons{k0l + k0s};
468 return PhotoNuclearDQM::CompactEventType::single_neutron;
471 return PhotoNuclearDQM::CompactEventType::single_charged_kaon;
473 if (neutral_kaons != 0) {
474 return PhotoNuclearDQM::CompactEventType::single_neutral_kaon;
477 return PhotoNuclearDQM::CompactEventType::two_neutrons;
479 if (soft == daughters.size()) {
480 return PhotoNuclearDQM::CompactEventType::soft;
483 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.