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) {
168 "SimParticles", sim_particles_passname_)};
169 if (particle_map.size() == 0) {
174 auto [trackID, recoil] = analysis::getRecoil(particle_map);
179 auto pn_gamma{analysis::getPNGamma(particle_map, recoil, 2500.)};
180 if (pn_gamma ==
nullptr) {
181 ldmx_log(warn) <<
"PN Daughter is lost, skipping";
185 const auto pn_daughters{
findDaughters(particle_map, pn_gamma)};
187 if (!pn_daughters.empty()) {
188 auto pn_vertex_volume{pn_daughters[0]->getVertexVolume()};
189 auto pn_interaction_material{pn_daughters[0]->getInteractionMaterial()};
192 if (pn_vertex_volume.find(
"W_cooling") != std::string::npos) {
195 }
else if (pn_vertex_volume.find(
"C_volume") != std::string::npos) {
198 }
else if (pn_vertex_volume.find(
"PCB_volume") != std::string::npos) {
200 }
else if (pn_vertex_volume.find(
"CarbonBasePlate") != std::string::npos) {
203 }
else if (pn_vertex_volume.find(
"W_front") != std::string::npos) {
206 }
else if (pn_vertex_volume.find(
"Si_volume") != std::string::npos) {
208 }
else if (pn_vertex_volume.find(
"Glue") != std::string::npos) {
210 }
else if (pn_vertex_volume.find(
"motherboard") != std::string::npos) {
214 ldmx_log(debug) <<
" Else pn_vertex_volume = " << pn_vertex_volume
215 <<
" with pn_interaction_material = "
216 << pn_interaction_material;
221 if (pn_interaction_material.find(
"G4_Si") != std::string::npos) {
223 }
else if (pn_interaction_material.find(
"G4_W") != std::string::npos) {
225 }
else if (pn_interaction_material.find(
"FR4") != std::string::npos) {
228 }
else if (pn_interaction_material.find(
"Steel") != std::string::npos) {
230 }
else if (pn_interaction_material.find(
"Epoxy") != std::string::npos) {
233 }
else if (pn_interaction_material.find(
"Scintillator") !=
237 }
else if (pn_interaction_material.find(
"Glue") != std::string::npos) {
240 }
else if (pn_interaction_material.find(
"G4_AIR") != std::string::npos) {
244 ldmx_log(debug) <<
" Else pn_interaction_material = "
245 << pn_interaction_material
246 <<
" with pn_vertex_volume = " << pn_vertex_volume;
260 histograms_.
fill(
"pn_gamma_int_x:pn_gamma_int_y", pn_gamma->getEndPoint()[0],
261 pn_gamma->getEndPoint()[1]);
273 auto event_type_comp500_me_v{
275 auto event_type_comp2000_me_v{
279 histograms_.
fill(
"event_type_500mev",
static_cast<int>(event_type500_me_v));
280 histograms_.
fill(
"event_type_2000mev",
static_cast<int>(event_type2000_me_v));
282 histograms_.
fill(
"event_type_compact",
static_cast<int>(event_type_comp));
284 static_cast<int>(event_type_comp500_me_v));
286 static_cast<int>(event_type_comp2000_me_v));
288 switch (event_type) {
289 case EventType::single_neutron:
290 if (pn_daughters.size() > 1) {
291 auto second_hardest_pdg_id{abs(pn_daughters[1]->getPdgID())};
292 auto n_event_type{-10};
293 if (second_hardest_pdg_id == 2112) {
295 }
else if (second_hardest_pdg_id == 2212) {
297 }
else if (second_hardest_pdg_id == 211) {
299 }
else if (second_hardest_pdg_id == 111) {
307 case EventType::two_neutrons:
308 case EventType::charged_kaon:
309 case EventType::klong:
310 case EventType::kshort:
319 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
320 short n{0}, p{0}, pi{0}, pi0{0}, exotic{0}, k0l{0}, kp{0}, k0s{0};
324 for (
const auto &daughter : daughters) {
326 auto ke{daughter->getEnergy() - daughter->getMass()};
331 if (ke <= threshold) {
336 auto pdg_id{abs(daughter->getPdgID())};
338 if (pdg_id == 2112) {
340 }
else if (pdg_id == 2212) {
342 }
else if (pdg_id == 211) {
344 }
else if (pdg_id == 111) {
346 }
else if (pdg_id == 130) {
348 }
else if (pdg_id == 321) {
350 }
else if (pdg_id == 310) {
357 int kaons = k0l + kp + k0s;
358 int nucleons = n + p;
359 int pions = pi + pi0;
360 int count = nucleons + pions + exotic + kaons;
363 return EventType::nothing_hard;
367 return EventType::single_neutron;
369 return EventType::single_proton;
370 }
else if (pi0 == 1) {
371 return EventType::single_neutral_pion;
372 }
else if (pi == 1) {
373 return EventType::single_charged_pion;
378 return EventType::two_neutrons;
379 }
else if (n == 1 && p == 1) {
380 return EventType::proton_neutron;
382 return EventType::two_protons;
383 }
else if (pi == 2) {
384 return EventType::two_charged_pions;
385 }
else if (pi == 1 && nucleons == 1) {
386 return EventType::single_charged_pion_and_nucleon;
387 }
else if (pi0 == 1 && nucleons == 1) {
388 return EventType::single_neutral_pion_and_nucleon;
393 if (pi == 1 && nucleons == 2) {
394 return EventType::single_charged_pion_and_two_nucleons;
395 }
else if (pi == 2 && nucleons == 1) {
396 return EventType::two_charged_pions_and_nucleon;
398 else if (pi0 == 1 && nucleons == 2) {
399 return EventType::single_neutral_pion_and_two_nucleons;
400 }
else if (pi0 == 1 && nucleons == 1 && pi == 1) {
401 return EventType::single_neutral_pion_charged_pion_and_nucleon;
404 if (count >= 3 && count == n) {
405 return EventType::three_or_more_neutrons;
410 return EventType::klong;
411 }
else if (kp == 1) {
412 return EventType::charged_kaon;
413 }
else if (k0s == 1) {
414 return EventType::kshort;
417 if (exotic == count && count != 0) {
418 return EventType::exotics;
421 return EventType::multibody;
426 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
427 short n{0}, n_t{0}, k0l{0}, kp{0}, k0s{0}, soft{0};
431 for (
const auto &daughter : daughters) {
433 auto ke{daughter->getEnergy() - daughter->getMass()};
436 auto pdg_id{abs(daughter->getPdgID())};
444 if (pdg_id == 2112) {
446 }
else if (pdg_id == 130) {
448 }
else if (pdg_id == 321) {
450 }
else if (pdg_id == 310) {
456 if ((pdg_id == 2112) && ke > threshold) {
461 int neutral_kaons{k0l + k0s};
464 return PhotoNuclearDQM::CompactEventType::single_neutron;
467 return PhotoNuclearDQM::CompactEventType::single_charged_kaon;
469 if (neutral_kaons != 0) {
470 return PhotoNuclearDQM::CompactEventType::single_neutral_kaon;
473 return PhotoNuclearDQM::CompactEventType::two_neutrons;
475 if (soft == daughters.size()) {
476 return PhotoNuclearDQM::CompactEventType::soft;
479 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.