17std::vector<const ldmx::SimParticle*> NuclearDQM::findDaughters(
18 const std::map<int, ldmx::SimParticle>& particleMap,
20 std::vector<const ldmx::SimParticle*> daughters;
22 for (
const auto& daughter_track_id : parent->
getDaughters()) {
23 if (particleMap.count(daughter_track_id) == 0)
continue;
25 auto daughter{&(particleMap.at(daughter_track_id))};
27 if (require_process_type >= 0 &&
28 daughter->getProcessType() != require_process_type)
31 auto pdg_id{daughter->getPdgID()};
33 (pdg_id > 10000 && (!count_light_ions_ || !isLightIon(pdg_id))))
36 daughters.push_back(daughter);
39 std::sort(daughters.begin(), daughters.end(),
40 [](
const auto& lhs,
const auto& rhs) {
41 return (lhs->getEnergy() - lhs->getMass()) >
42 (rhs->getEnergy() - rhs->getMass());
48void NuclearDQM::findParticleKinematics(
49 const std::vector<const ldmx::SimParticle*>& daughters,
50 const std::string& prefix) {
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};
59 for (
const auto* daughter : daughters) {
60 auto pdg_id{daughter->getPdgID()};
61 double ke{daughter->getEnergy() - daughter->getMass()};
64 std::vector<double> vec{daughter->getMomentum()};
65 ROOT::Math::XYZVector pvec(vec[0], vec[1], vec[2]);
66 auto theta{pvec.Theta() * (180 / 3.14159)};
68 if (hardest_ke < ke) {
70 hardest_theta = theta;
74 total_neutron_ke += ke;
75 neutron_multiplicity++;
76 if (hardest_neutron_ke < ke) {
77 hardest_neutron_ke = ke;
78 hardest_neutron_theta = theta;
82 if (pdg_id == 2212 && hardest_proton_ke < ke) {
83 hardest_proton_ke = ke;
84 hardest_proton_theta = theta;
88 if ((std::abs(pdg_id) == 211 || pdg_id == 111) && hardest_pion_ke < ke) {
90 hardest_pion_theta = theta;
94 histograms_.fill(
"hardest_ke", hardest_ke);
95 histograms_.fill(
"hardest_theta", hardest_theta);
96 histograms_.fill(
"h_ke_h_theta", hardest_ke, hardest_theta);
97 histograms_.fill(
"hardest_p_ke", hardest_proton_ke);
98 histograms_.fill(
"hardest_p_theta", hardest_proton_theta);
99 histograms_.fill(
"hardest_n_ke", hardest_neutron_ke);
100 histograms_.fill(
"hardest_n_theta", hardest_neutron_theta);
101 histograms_.fill(
"hardest_pi_ke", hardest_pion_ke);
102 histograms_.fill(
"hardest_pi_theta", hardest_pion_theta);
104 histograms_.fill(prefix +
"_neutron_mult", neutron_multiplicity);
105 histograms_.fill(prefix +
"_total_ke", total_ke);
106 histograms_.fill(prefix +
"_total_neutron_ke", total_neutron_ke);
109void NuclearDQM::findExtendedKinematics(
110 const std::vector<const ldmx::SimParticle*>& daughters,
111 const std::string& prefix) {
116 double hardest_ke{-1}, hardest_theta{-1};
117 double hardest_n_ke{-1}, hardest_n_theta{-1};
118 double hardest_p_ke{-1}, hardest_p_theta{-1};
119 double hardest_pi0_ke{-1}, hardest_pi0_theta{-1};
120 double total_ke{0}, total_neutron_ke{0};
121 int neutron_multiplicity{0};
122 int proton_multiplicity{0};
123 int charged_pion_multiplicity{0};
124 int neutral_pion_multiplicity{0};
126 for (
const auto* daughter : daughters) {
127 auto pdg_id{daughter->getPdgID()};
128 double ke{daughter->getEnergy() - daughter->getMass()};
131 std::vector<double> vec{daughter->getMomentum()};
132 ROOT::Math::XYZVector pvec(vec[0], vec[1], vec[2]);
133 auto theta{pvec.Theta() * (180 / 3.14159)};
135 if (hardest_ke < ke) {
137 hardest_theta = theta;
140 if (pdg_id == 2112) {
141 neutron_multiplicity++;
142 total_neutron_ke += ke;
143 if (hardest_n_ke < ke) {
145 hardest_n_theta = theta;
147 }
else if (pdg_id == 2212) {
148 proton_multiplicity++;
149 if (hardest_p_ke < ke) {
151 hardest_p_theta = theta;
153 }
else if (std::abs(pdg_id) == 211) {
154 charged_pion_multiplicity++;
155 }
else if (pdg_id == 111) {
156 neutral_pion_multiplicity++;
157 if (hardest_pi0_ke < ke) {
159 hardest_pi0_theta = theta;
166 if (!daughters.empty()) {
167 auto leading_pdg{std::abs(daughters[0]->getPdgID())};
169 if (leading_pdg == 211)
171 else if (leading_pdg == 111)
173 else if (leading_pdg == 321)
175 else if (leading_pdg == 130 || leading_pdg == 310)
177 else if (leading_pdg == 2212)
179 else if (leading_pdg == 2112)
181 histograms_.fill(
"leading_particle_type", leading_type);
184 histograms_.fill(
"hardest_ke", hardest_ke);
185 histograms_.fill(
"hardest_theta", hardest_theta);
186 histograms_.fill(
"h_ke_h_theta", hardest_ke, hardest_theta);
187 histograms_.fill(
"hardest_n_ke", hardest_n_ke);
188 histograms_.fill(
"hardest_n_theta", hardest_n_theta);
189 histograms_.fill(
"hardest_p_ke", hardest_p_ke);
190 histograms_.fill(
"hardest_p_theta", hardest_p_theta);
191 histograms_.fill(
"hardest_pi0_ke", hardest_pi0_ke);
192 histograms_.fill(
"hardest_pi0_theta", hardest_pi0_theta);
193 histograms_.fill(prefix +
"_neutron_mult", neutron_multiplicity);
194 histograms_.fill(prefix +
"_proton_mult", proton_multiplicity);
195 histograms_.fill(prefix +
"_charged_pion_mult", charged_pion_multiplicity);
196 histograms_.fill(prefix +
"_neutral_pion_mult", neutral_pion_multiplicity);
197 histograms_.fill(prefix +
"_total_ke", total_ke);
198 histograms_.fill(prefix +
"_total_neutron_ke", total_neutron_ke);
201void NuclearDQM::findSubleadingKinematics(
203 const std::vector<const ldmx::SimParticle*>& daughters,
207 double subleading_ke{-9999};
208 double n_energy{-9999}, energy_diff{-9999}, energy_frac{-9999};
210 n_energy = daughters[0]->getEnergy() - daughters[0]->getMass();
211 if (daughters.size() > 1) {
212 subleading_ke = daughters[1]->getEnergy() - daughters[1]->getMass();
214 energy_diff = initiator->
getEnergy() - n_energy;
215 energy_frac = n_energy / initiator->
getEnergy();
217 if (eventType == EventType::single_neutron) {
218 histograms_.fill(
"1n_ke:2nd_h_ke", n_energy, subleading_ke);
219 histograms_.fill(
"1n_neutron_energy", n_energy);
220 histograms_.fill(
"1n_energy_diff", energy_diff);
221 histograms_.fill(
"1n_energy_frac", energy_frac);
222 }
else if (eventType == EventType::two_neutrons) {
223 histograms_.fill(
"2n_n2_energy", subleading_ke);
224 auto energy_frac2n = (n_energy + subleading_ke) / initiator->
getEnergy();
225 histograms_.fill(
"2n_energy_frac", energy_frac2n);
226 histograms_.fill(
"2n_energy_other", initiator->
getEnergy() - energy_frac2n);
227 }
else if (eventType == EventType::charged_kaon) {
228 histograms_.fill(
"1kp_ke:2nd_h_ke", n_energy, subleading_ke);
229 histograms_.fill(
"1kp_energy", n_energy);
230 histograms_.fill(
"1kp_energy_diff", energy_diff);
231 histograms_.fill(
"1kp_energy_frac", energy_frac);
232 }
else if (eventType == EventType::klong || eventType == EventType::kshort) {
233 histograms_.fill(
"1k0_ke:2nd_h_ke", n_energy, subleading_ke);
234 histograms_.fill(
"1k0_energy", n_energy);
235 histograms_.fill(
"1k0_energy_diff", energy_diff);
236 histograms_.fill(
"1k0_energy_frac", energy_frac);
241 const std::vector<const ldmx::SimParticle*>& daughters,
double threshold) {
242 short n{0}, p{0}, pi{0}, pi0{0}, exotic{0}, k0l{0}, kp{0}, k0s{0};
244 for (
const auto& daughter : daughters) {
245 auto ke{daughter->getEnergy() - daughter->getMass()};
247 if (ke <= threshold)
break;
249 auto pdg_id{std::abs(daughter->getPdgID())};
252 else if (pdg_id == 2212)
254 else if (pdg_id == 211)
256 else if (pdg_id == 111)
258 else if (pdg_id == 130)
260 else if (pdg_id == 321)
262 else if (pdg_id == 310)
268 int kaons{k0l + kp + k0s};
271 int count{nucleons + pions + exotic + kaons};
273 if (count == 0)
return EventType::nothing_hard;
276 if (n == 1)
return EventType::single_neutron;
277 if (p == 1)
return EventType::single_proton;
278 if (pi0 == 1)
return EventType::single_neutral_pion;
279 if (pi == 1)
return EventType::single_charged_pion;
282 if (n == 2)
return EventType::two_neutrons;
283 if (n == 1 && p == 1)
return EventType::proton_neutron;
284 if (p == 2)
return EventType::two_protons;
285 if (pi == 2)
return EventType::two_charged_pions;
286 if (pi == 1 && nucleons == 1)
287 return EventType::single_charged_pion_and_nucleon;
288 if (pi0 == 1 && nucleons == 1)
289 return EventType::single_neutral_pion_and_nucleon;
292 if (pi == 1 && nucleons == 2)
293 return EventType::single_charged_pion_and_two_nucleons;
294 if (pi == 2 && nucleons == 1)
295 return EventType::two_charged_pions_and_nucleon;
296 if (pi0 == 1 && nucleons == 2)
297 return EventType::single_neutral_pion_and_two_nucleons;
298 if (pi0 == 1 && nucleons == 1 && pi == 1)
299 return EventType::single_neutral_pion_charged_pion_and_nucleon;
301 if (count >= 3 && count == n)
return EventType::three_or_more_neutrons;
304 if (k0l == 1)
return EventType::klong;
305 if (kp == 1)
return EventType::charged_kaon;
306 if (k0s == 1)
return EventType::kshort;
308 if (exotic == count && count != 0)
return EventType::exotics;
310 return EventType::multibody;
315 const std::vector<const ldmx::SimParticle*>& daughters,
double threshold) {
316 short n{0}, n_t{0}, k0l{0}, kp{0}, k0s{0}, soft{0};
318 for (
const auto& daughter : daughters) {
319 auto ke{daughter->getEnergy() - daughter->getMass()};
320 auto pdg_id{std::abs(daughter->getPdgID())};
327 if (ke >= 0.8 * initiator->
getEnergy()) {
330 else if (pdg_id == 130)
332 else if (pdg_id == 321)
334 else if (pdg_id == 310)
339 if (pdg_id == 2112 && ke > threshold) n_t++;
342 int neutral_kaons{k0l + k0s};
343 if (n != 0)
return CompactEventType::single_neutron;
344 if (kp != 0)
return CompactEventType::single_charged_kaon;
345 if (neutral_kaons != 0)
return CompactEventType::single_neutral_kaon;
346 if (n_t == 2)
return CompactEventType::two_neutrons;
347 if (soft ==
static_cast<short>(daughters.size()))
348 return CompactEventType::soft;
349 return CompactEventType::other;
Class representing a simulated particle.
double getEnergy() const
Get the energy of this particle [MeV].
std::vector< int > getDaughters() const
Get a vector containing the track IDs of all daughter particles.