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(
"Silicon") != std::string::npos ||
222 pn_interaction_material.find(
"G4_Si") != std::string::npos) {
224 }
else if (pn_interaction_material.find(
"Tungsten") != std::string::npos ||
225 pn_interaction_material.find(
"G4_W") != std::string::npos) {
227 }
else if (pn_interaction_material.find(
"FR4") != std::string::npos) {
230 }
else if (pn_interaction_material.find(
"Steel") != std::string::npos) {
232 }
else if (pn_interaction_material.find(
"Epoxy") != std::string::npos) {
235 }
else if (pn_interaction_material.find(
"Scintillator") !=
239 }
else if (pn_interaction_material.find(
"Glue") != std::string::npos) {
242 }
else if (pn_interaction_material.find(
"Air") != std::string::npos ||
243 pn_interaction_material.find(
"G4_AIR") != std::string::npos) {
247 ldmx_log(debug) <<
" Else pn_interaction_material = "
248 << pn_interaction_material
249 <<
" with pn_vertex_volume = " << pn_vertex_volume;
263 histograms_.
fill(
"pn_gamma_int_x:pn_gamma_int_y", pn_gamma->getEndPoint()[0],
264 pn_gamma->getEndPoint()[1]);
276 auto event_type_comp500_me_v{
278 auto event_type_comp2000_me_v{
282 histograms_.
fill(
"event_type_500mev",
static_cast<int>(event_type500_me_v));
283 histograms_.
fill(
"event_type_2000mev",
static_cast<int>(event_type2000_me_v));
285 histograms_.
fill(
"event_type_compact",
static_cast<int>(event_type_comp));
287 static_cast<int>(event_type_comp500_me_v));
289 static_cast<int>(event_type_comp2000_me_v));
291 switch (event_type) {
292 case EventType::single_neutron:
293 if (pn_daughters.size() > 1) {
294 auto second_hardest_pdg_id{abs(pn_daughters[1]->getPdgID())};
295 auto n_event_type{-10};
296 if (second_hardest_pdg_id == 2112) {
298 }
else if (second_hardest_pdg_id == 2212) {
300 }
else if (second_hardest_pdg_id == 211) {
302 }
else if (second_hardest_pdg_id == 111) {
310 case EventType::two_neutrons:
311 case EventType::charged_kaon:
312 case EventType::klong:
313 case EventType::kshort:
322 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
323 short n{0}, p{0}, pi{0}, pi0{0}, exotic{0}, k0l{0}, kp{0}, k0s{0};
327 for (
const auto &daughter : daughters) {
329 auto ke{daughter->getEnergy() - daughter->getMass()};
334 if (ke <= threshold) {
339 auto pdg_id{abs(daughter->getPdgID())};
341 if (pdg_id == 2112) {
343 }
else if (pdg_id == 2212) {
345 }
else if (pdg_id == 211) {
347 }
else if (pdg_id == 111) {
349 }
else if (pdg_id == 130) {
351 }
else if (pdg_id == 321) {
353 }
else if (pdg_id == 310) {
360 int kaons = k0l + kp + k0s;
361 int nucleons = n + p;
362 int pions = pi + pi0;
363 int count = nucleons + pions + exotic + kaons;
366 return EventType::nothing_hard;
370 return EventType::single_neutron;
372 return EventType::single_proton;
373 }
else if (pi0 == 1) {
374 return EventType::single_neutral_pion;
375 }
else if (pi == 1) {
376 return EventType::single_charged_pion;
381 return EventType::two_neutrons;
382 }
else if (n == 1 && p == 1) {
383 return EventType::proton_neutron;
385 return EventType::two_protons;
386 }
else if (pi == 2) {
387 return EventType::two_charged_pions;
388 }
else if (pi == 1 && nucleons == 1) {
389 return EventType::single_charged_pion_and_nucleon;
390 }
else if (pi0 == 1 && nucleons == 1) {
391 return EventType::single_neutral_pion_and_nucleon;
396 if (pi == 1 && nucleons == 2) {
397 return EventType::single_charged_pion_and_two_nucleons;
398 }
else if (pi == 2 && nucleons == 1) {
399 return EventType::two_charged_pions_and_nucleon;
401 else if (pi0 == 1 && nucleons == 2) {
402 return EventType::single_neutral_pion_and_two_nucleons;
403 }
else if (pi0 == 1 && nucleons == 1 && pi == 1) {
404 return EventType::single_neutral_pion_charged_pion_and_nucleon;
407 if (count >= 3 && count == n) {
408 return EventType::three_or_more_neutrons;
413 return EventType::klong;
414 }
else if (kp == 1) {
415 return EventType::charged_kaon;
416 }
else if (k0s == 1) {
417 return EventType::kshort;
420 if (exotic == count && count != 0) {
421 return EventType::exotics;
424 return EventType::multibody;
429 const std::vector<const ldmx::SimParticle *> daughters,
double threshold) {
430 short n{0}, n_t{0}, k0l{0}, kp{0}, k0s{0}, soft{0};
434 for (
const auto &daughter : daughters) {
436 auto ke{daughter->getEnergy() - daughter->getMass()};
439 auto pdg_id{abs(daughter->getPdgID())};
447 if (pdg_id == 2112) {
449 }
else if (pdg_id == 130) {
451 }
else if (pdg_id == 321) {
453 }
else if (pdg_id == 310) {
459 if ((pdg_id == 2112) && ke > threshold) {
464 int neutral_kaons{k0l + k0s};
467 return PhotoNuclearDQM::CompactEventType::single_neutron;
470 return PhotoNuclearDQM::CompactEventType::single_charged_kaon;
472 if (neutral_kaons != 0) {
473 return PhotoNuclearDQM::CompactEventType::single_neutral_kaon;
476 return PhotoNuclearDQM::CompactEventType::two_neutrons;
478 if (soft == daughters.size()) {
479 return PhotoNuclearDQM::CompactEventType::soft;
482 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.