21std::vector<const ldmx::SimParticle*> NuclearDQM::findDaughters(
22 const std::map<int, ldmx::SimParticle>& particleMap,
24 std::vector<const ldmx::SimParticle*> daughters;
26 for (
const auto& daughter_track_id : parent->
getDaughters()) {
27 if (particleMap.count(daughter_track_id) == 0)
continue;
29 auto daughter{&(particleMap.at(daughter_track_id))};
31 if (require_process_type >= 0 &&
32 daughter->getProcessType() != require_process_type)
35 auto pdg_id{daughter->getPdgID()};
37 (pdg_id > 10000 && (!count_light_ions_ || !isLightIon(pdg_id))))
40 daughters.push_back(daughter);
43 std::sort(daughters.begin(), daughters.end(),
44 [](
const auto& lhs,
const auto& rhs) {
45 return (lhs->getEnergy() - lhs->getMass()) >
46 (rhs->getEnergy() - rhs->getMass());
52void NuclearDQM::findParticleKinematics(
53 const std::vector<const ldmx::SimParticle*>& daughters,
54 const std::string& prefix) {
55 double hardest_ke{-1}, hardest_theta{-1};
56 double hardest_proton_ke{-1}, hardest_proton_theta{-1};
57 double hardest_neutron_ke{-1}, hardest_neutron_theta{-1};
58 double hardest_pion_ke{-1}, hardest_pion_theta{-1};
60 double total_neutron_ke{0};
61 int neutron_multiplicity{0};
63 for (
const auto* daughter : daughters) {
64 auto pdg_id{daughter->getPdgID()};
65 double ke{daughter->getEnergy() - daughter->getMass()};
68 std::vector<double> vec{daughter->getMomentum()};
69 ROOT::Math::XYZVector pvec(vec[0], vec[1], vec[2]);
70 auto theta{pvec.Theta() * (180 / 3.14159)};
72 if (hardest_ke < ke) {
74 hardest_theta = theta;
78 total_neutron_ke += ke;
79 neutron_multiplicity++;
80 if (hardest_neutron_ke < ke) {
81 hardest_neutron_ke = ke;
82 hardest_neutron_theta = theta;
86 if (pdg_id == 2212 && hardest_proton_ke < ke) {
87 hardest_proton_ke = ke;
88 hardest_proton_theta = theta;
92 if ((std::abs(pdg_id) == 211 || pdg_id == 111) && hardest_pion_ke < ke) {
94 hardest_pion_theta = theta;
98 histograms_.fill(
"hardest_ke", hardest_ke);
99 histograms_.fill(
"hardest_theta", hardest_theta);
100 histograms_.fill(
"h_ke_h_theta", hardest_ke, hardest_theta);
101 histograms_.fill(
"hardest_p_ke", hardest_proton_ke);
102 histograms_.fill(
"hardest_p_theta", hardest_proton_theta);
103 histograms_.fill(
"hardest_n_ke", hardest_neutron_ke);
104 histograms_.fill(
"hardest_n_theta", hardest_neutron_theta);
105 histograms_.fill(
"hardest_pi_ke", hardest_pion_ke);
106 histograms_.fill(
"hardest_pi_theta", hardest_pion_theta);
108 histograms_.fill(prefix +
"_neutron_mult", neutron_multiplicity);
109 histograms_.fill(prefix +
"_total_ke", total_ke);
110 histograms_.fill(prefix +
"_total_neutron_ke", total_neutron_ke);
113void NuclearDQM::findExtendedKinematics(
114 const std::vector<const ldmx::SimParticle*>& daughters,
115 const std::string& prefix) {
120 double hardest_ke{-1}, hardest_theta{-1};
121 double hardest_n_ke{-1}, hardest_n_theta{-1};
122 double hardest_p_ke{-1}, hardest_p_theta{-1};
123 double hardest_pi0_ke{-1}, hardest_pi0_theta{-1};
124 double total_ke{0}, total_neutron_ke{0};
125 int neutron_multiplicity{0};
126 int proton_multiplicity{0};
127 int charged_pion_multiplicity{0};
128 int neutral_pion_multiplicity{0};
130 for (
const auto* daughter : daughters) {
131 auto pdg_id{daughter->getPdgID()};
132 double ke{daughter->getEnergy() - daughter->getMass()};
135 std::vector<double> vec{daughter->getMomentum()};
136 ROOT::Math::XYZVector pvec(vec[0], vec[1], vec[2]);
137 auto theta{pvec.Theta() * (180 / 3.14159)};
139 if (hardest_ke < ke) {
141 hardest_theta = theta;
144 if (pdg_id == 2112) {
145 neutron_multiplicity++;
146 total_neutron_ke += ke;
147 if (hardest_n_ke < ke) {
149 hardest_n_theta = theta;
151 }
else if (pdg_id == 2212) {
152 proton_multiplicity++;
153 if (hardest_p_ke < ke) {
155 hardest_p_theta = theta;
157 }
else if (std::abs(pdg_id) == 211) {
158 charged_pion_multiplicity++;
159 }
else if (pdg_id == 111) {
160 neutral_pion_multiplicity++;
161 if (hardest_pi0_ke < ke) {
163 hardest_pi0_theta = theta;
170 if (!daughters.empty()) {
171 auto leading_pdg{std::abs(daughters[0]->getPdgID())};
173 if (leading_pdg == 211)
175 else if (leading_pdg == 111)
177 else if (leading_pdg == 321)
179 else if (leading_pdg == 130 || leading_pdg == 310)
181 else if (leading_pdg == 2212)
183 else if (leading_pdg == 2112)
185 histograms_.fill(
"leading_particle_type", leading_type);
188 histograms_.fill(
"hardest_ke", hardest_ke);
189 histograms_.fill(
"hardest_theta", hardest_theta);
190 histograms_.fill(
"h_ke_h_theta", hardest_ke, hardest_theta);
191 histograms_.fill(
"hardest_n_ke", hardest_n_ke);
192 histograms_.fill(
"hardest_n_theta", hardest_n_theta);
193 histograms_.fill(
"hardest_p_ke", hardest_p_ke);
194 histograms_.fill(
"hardest_p_theta", hardest_p_theta);
195 histograms_.fill(
"hardest_pi0_ke", hardest_pi0_ke);
196 histograms_.fill(
"hardest_pi0_theta", hardest_pi0_theta);
197 histograms_.fill(prefix +
"_neutron_mult", neutron_multiplicity);
198 histograms_.fill(prefix +
"_proton_mult", proton_multiplicity);
199 histograms_.fill(prefix +
"_charged_pion_mult", charged_pion_multiplicity);
200 histograms_.fill(prefix +
"_neutral_pion_mult", neutral_pion_multiplicity);
201 histograms_.fill(prefix +
"_total_ke", total_ke);
202 histograms_.fill(prefix +
"_total_neutron_ke", total_neutron_ke);
205void NuclearDQM::findSubleadingKinematics(
207 const std::vector<const ldmx::SimParticle*>& daughters,
211 double subleading_ke{-9999};
212 double n_energy{-9999}, energy_diff{-9999}, energy_frac{-9999};
214 n_energy = daughters[0]->getEnergy() - daughters[0]->getMass();
215 if (daughters.size() > 1) {
216 subleading_ke = daughters[1]->getEnergy() - daughters[1]->getMass();
218 energy_diff = initiator->
getEnergy() - n_energy;
219 energy_frac = n_energy / initiator->
getEnergy();
221 if (eventType == EventType::single_neutron) {
222 histograms_.fill(
"1n_ke:2nd_h_ke", n_energy, subleading_ke);
223 histograms_.fill(
"1n_neutron_energy", n_energy);
224 histograms_.fill(
"1n_energy_diff", energy_diff);
225 histograms_.fill(
"1n_energy_frac", energy_frac);
226 }
else if (eventType == EventType::two_neutrons) {
227 histograms_.fill(
"2n_n2_energy", subleading_ke);
228 auto energy_frac2n = (n_energy + subleading_ke) / initiator->
getEnergy();
229 histograms_.fill(
"2n_energy_frac", energy_frac2n);
230 histograms_.fill(
"2n_energy_other", initiator->
getEnergy() - energy_frac2n);
231 }
else if (eventType == EventType::charged_kaon) {
232 histograms_.fill(
"1kp_ke:2nd_h_ke", n_energy, subleading_ke);
233 histograms_.fill(
"1kp_energy", n_energy);
234 histograms_.fill(
"1kp_energy_diff", energy_diff);
235 histograms_.fill(
"1kp_energy_frac", energy_frac);
236 }
else if (eventType == EventType::klong || eventType == EventType::kshort) {
237 histograms_.fill(
"1k0_ke:2nd_h_ke", n_energy, subleading_ke);
238 histograms_.fill(
"1k0_energy", n_energy);
239 histograms_.fill(
"1k0_energy_diff", energy_diff);
240 histograms_.fill(
"1k0_energy_frac", energy_frac);
245 const std::vector<const ldmx::SimParticle*>& daughters,
double threshold) {
246 short n{0}, p{0}, pi{0}, pi0{0}, exotic{0}, k0l{0}, kp{0}, k0s{0};
248 for (
const auto& daughter : daughters) {
249 auto ke{daughter->getEnergy() - daughter->getMass()};
251 if (ke <= threshold)
break;
253 auto pdg_id{std::abs(daughter->getPdgID())};
256 else if (pdg_id == 2212)
258 else if (pdg_id == 211)
260 else if (pdg_id == 111)
262 else if (pdg_id == 130)
264 else if (pdg_id == 321)
266 else if (pdg_id == 310)
272 int kaons{k0l + kp + k0s};
275 int count{nucleons + pions + exotic + kaons};
277 if (count == 0)
return EventType::nothing_hard;
280 if (n == 1)
return EventType::single_neutron;
281 if (p == 1)
return EventType::single_proton;
282 if (pi0 == 1)
return EventType::single_neutral_pion;
283 if (pi == 1)
return EventType::single_charged_pion;
286 if (n == 2)
return EventType::two_neutrons;
287 if (n == 1 && p == 1)
return EventType::proton_neutron;
288 if (p == 2)
return EventType::two_protons;
289 if (pi == 2)
return EventType::two_charged_pions;
290 if (pi == 1 && nucleons == 1)
291 return EventType::single_charged_pion_and_nucleon;
292 if (pi0 == 1 && nucleons == 1)
293 return EventType::single_neutral_pion_and_nucleon;
296 if (pi == 1 && nucleons == 2)
297 return EventType::single_charged_pion_and_two_nucleons;
298 if (pi == 2 && nucleons == 1)
299 return EventType::two_charged_pions_and_nucleon;
300 if (pi0 == 1 && nucleons == 2)
301 return EventType::single_neutral_pion_and_two_nucleons;
302 if (pi0 == 1 && nucleons == 1 && pi == 1)
303 return EventType::single_neutral_pion_charged_pion_and_nucleon;
305 if (count >= 3 && count == n)
return EventType::three_or_more_neutrons;
308 if (k0l == 1)
return EventType::klong;
309 if (kp == 1)
return EventType::charged_kaon;
310 if (k0s == 1)
return EventType::kshort;
312 if (exotic == count && count != 0)
return EventType::exotics;
314 return EventType::multibody;
319 const std::vector<const ldmx::SimParticle*>& daughters,
double threshold) {
320 short n{0}, n_t{0}, k0l{0}, kp{0}, k0s{0}, soft{0};
322 for (
const auto& daughter : daughters) {
323 auto ke{daughter->getEnergy() - daughter->getMass()};
324 auto pdg_id{std::abs(daughter->getPdgID())};
331 if (ke >= 0.8 * initiator->
getEnergy()) {
334 else if (pdg_id == 130)
336 else if (pdg_id == 321)
338 else if (pdg_id == 310)
343 if (pdg_id == 2112 && ke > threshold) n_t++;
346 int neutral_kaons{k0l + k0s};
347 if (n != 0)
return CompactEventType::single_neutron;
348 if (kp != 0)
return CompactEventType::single_charged_kaon;
349 if (neutral_kaons != 0)
return CompactEventType::single_neutral_kaon;
350 if (n_t == 2)
return CompactEventType::two_neutrons;
351 if (soft ==
static_cast<short>(daughters.size()))
352 return CompactEventType::soft;
353 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.