LDMX Software
CascadeHistoryDQM.cxx
1#include "DQM/CascadeHistoryDQM.h"
2
3#include <cmath>
4
6
7namespace dqm {
8
9CascadeHistoryDQM::CascadeHistoryDQM(const std::string& name,
10 framework::Process& process)
11 : framework::Analyzer(name, process) {}
12
13void CascadeHistoryDQM::configure(framework::config::Parameters& parameters) {
14 cascade_coll_name_ = parameters.get<std::string>(
15 "cascade_coll_name", "PhotonuclearCascadeHistories");
16 cascade_pass_name_ = parameters.get<std::string>("cascade_pass_name", "");
17}
18
19void CascadeHistoryDQM::analyze(const framework::Event& event) {
20 if (!event.exists(cascade_coll_name_, cascade_pass_name_)) {
21 return;
22 }
23
24 auto cascade_map = event.getMap<int, ldmx::CascadeHistory>(
25 cascade_coll_name_, cascade_pass_name_);
26 if (cascade_map.empty()) {
27 return;
28 }
29
30 histograms_.fill("n_cascades", cascade_map.size());
31
32 for (const auto& [trackId, history] : cascade_map) {
33 analyzeCascade(history);
34 }
35}
36
37void CascadeHistoryDQM::analyzeCascade(const ldmx::CascadeHistory& history) {
38 const auto& steps = history.getSteps();
39 if (steps.empty()) {
40 return;
41 }
42
43 // Basic cascade properties
44 histograms_.fill("cascade_n_steps", steps.size());
45 histograms_.fill("cascade_target_A", history.getTargetA());
46 histograms_.fill("cascade_target_Z", history.getTargetZ());
47
48 double incident_energy = history.getIncidentEnergy();
49 if (incident_energy > 0) {
50 histograms_.fill("incident_photon_energy", incident_energy);
51 }
52
53 // Count particles by type and status
54 int n_protons = 0, n_neutrons = 0, n_pions = 0, n_kaons = 0, n_other = 0;
55 int n_interacted = 0, n_escaped = 0;
56 int max_generation = 0;
57
58 // Primary reaction analysis
59 int primary_n_protons = 0, primary_n_neutrons = 0;
60 int primary_n_piplus = 0, primary_n_piminus = 0, primary_n_pizero = 0;
61 int primary_n_kaons = 0, primary_n_other = 0;
62 double primary_total_ke = 0;
63 double primary_max_ke = 0;
64
65 // De-excitation analysis
66 int n_deexcitation = 0;
67 int n_deexcitation_neutrons = 0, n_deexcitation_protons = 0;
68 int n_deexcitation_gammas = 0, n_deexcitation_alphas = 0;
69 double deexcitation_total_energy = 0;
70
71 for (const auto& step : steps) {
72 int pdg = step.getPdgId();
73 int abs_pdg = std::abs(pdg);
74 int category = getParticleCategory(pdg);
75 double ke = step.getKineticEnergy();
76
77 switch (category) {
78 case 0:
79 n_protons++;
80 break;
81 case 1:
82 n_neutrons++;
83 break;
84 case 2:
85 case 3:
86 case 4:
87 n_pions++;
88 break;
89 case 5:
90 n_kaons++;
91 break;
92 default:
93 n_other++;
94 break;
95 }
96
97 histograms_.fill("step_pdg_category", category);
98 histograms_.fill("step_generation", step.getGeneration());
99 histograms_.fill("step_stage", step.getStageInt());
100 histograms_.fill("step_ke", ke);
101 histograms_.fill("step_zone", step.getZone());
102
103 // Position within nucleus
104 double x = step.getX();
105 double y = step.getY();
106 double z = step.getZ();
107 double radius = std::sqrt(x * x + y * y + z * z);
108 histograms_.fill("step_radius", radius);
109 histograms_.fill("step_x", x);
110 histograms_.fill("step_y", y);
111 histograms_.fill("step_z", z);
112
113 if (step.getGeneration() > max_generation) {
114 max_generation = step.getGeneration();
115 }
116
117 if (step.didInteract()) {
118 n_interacted++;
119 }
120 if (step.didEscape()) {
121 n_escaped++;
122 histograms_.fill("escaped_pdg_category", category);
123 histograms_.fill("escaped_ke", ke);
124 }
125
126 // Primary reaction products (generation 1, from the initial gamma-nucleon
127 // interaction)
128 if (step.getStage() == ldmx::CascadeStage::PRIMARY) {
129 histograms_.fill("primary_daughter_pdg", category);
130 histograms_.fill("primary_daughter_ke", ke);
131 primary_total_ke += ke;
132 if (ke > primary_max_ke) primary_max_ke = ke;
133
134 if (pdg == 2212)
135 primary_n_protons++;
136 else if (pdg == 2112)
137 primary_n_neutrons++;
138 else if (pdg == 211)
139 primary_n_piplus++;
140 else if (pdg == -211)
141 primary_n_piminus++;
142 else if (pdg == 111)
143 primary_n_pizero++;
144 else if (abs_pdg == 321 || abs_pdg == 311 || abs_pdg == 310 ||
145 abs_pdg == 130)
146 primary_n_kaons++;
147 else
148 primary_n_other++;
149 }
150
151 // De-excitation products
152 if (step.getStage() == ldmx::CascadeStage::DEEXCITATION) {
153 n_deexcitation++;
154 deexcitation_total_energy += ke;
155 histograms_.fill("deexcitation_pdg", category);
156 histograms_.fill("deexcitation_ke", ke);
157
158 if (pdg == 2112) {
159 n_deexcitation_neutrons++;
160 histograms_.fill("deexcitation_neutron_ke", ke);
161 } else if (pdg == 2212) {
162 n_deexcitation_protons++;
163 histograms_.fill("deexcitation_proton_ke", ke);
164 } else if (pdg == 22) {
165 n_deexcitation_gammas++;
166 histograms_.fill("deexcitation_gamma_energy", ke);
167 } else if (abs_pdg == 1000020040) { // alpha
168 n_deexcitation_alphas++;
169 histograms_.fill("deexcitation_alpha_ke", ke);
170 }
171 }
172 }
173
174 // Per-cascade summary
175 histograms_.fill("cascade_n_protons", n_protons);
176 histograms_.fill("cascade_n_neutrons", n_neutrons);
177 histograms_.fill("cascade_n_pions", n_pions);
178 histograms_.fill("cascade_n_kaons", n_kaons);
179 histograms_.fill("cascade_n_other", n_other);
180 histograms_.fill("cascade_n_interacted", n_interacted);
181 histograms_.fill("cascade_n_escaped", n_escaped);
182 histograms_.fill("cascade_max_generation", max_generation);
183
184 // Primary reaction summary
185 int primary_n_daughters =
186 primary_n_protons + primary_n_neutrons + primary_n_piplus +
187 primary_n_piminus + primary_n_pizero + primary_n_kaons + primary_n_other;
188 int primary_n_pions = primary_n_piplus + primary_n_piminus + primary_n_pizero;
189
190 histograms_.fill("primary_n_daughters", primary_n_daughters);
191 histograms_.fill("primary_n_protons", primary_n_protons);
192 histograms_.fill("primary_n_neutrons", primary_n_neutrons);
193 histograms_.fill("primary_n_piplus", primary_n_piplus);
194 histograms_.fill("primary_n_piminus", primary_n_piminus);
195 histograms_.fill("primary_n_pizero", primary_n_pizero);
196 histograms_.fill("primary_n_pions", primary_n_pions);
197 histograms_.fill("primary_n_kaons", primary_n_kaons);
198 histograms_.fill("primary_n_other", primary_n_other);
199 histograms_.fill("primary_total_daughter_ke", primary_total_ke);
200 histograms_.fill("primary_max_daughter_ke", primary_max_ke);
201
202 // De-excitation summary
203 histograms_.fill("n_deexcitation", n_deexcitation);
204 histograms_.fill("n_deexcitation_neutrons", n_deexcitation_neutrons);
205 histograms_.fill("n_deexcitation_protons", n_deexcitation_protons);
206 histograms_.fill("n_deexcitation_gammas", n_deexcitation_gammas);
207 histograms_.fill("n_deexcitation_alphas", n_deexcitation_alphas);
208 histograms_.fill("deexcitation_total_energy", deexcitation_total_energy);
209
210 // Excitation and residual nucleus
211 histograms_.fill("excitation_energy", history.getExcitationEnergy());
212 histograms_.fill("residual_A", history.getResidualA());
213 histograms_.fill("residual_Z", history.getResidualZ());
214}
215
216int CascadeHistoryDQM::getParticleCategory(int pdgId) const {
217 int abs_pdg = std::abs(pdgId);
218 if (pdgId == 2212) return 0; // proton
219 if (pdgId == 2112) return 1; // neutron
220 if (pdgId == 211) return 2; // pi+
221 if (pdgId == -211) return 3; // pi-
222 if (pdgId == 111) return 4; // pi0
223 if (abs_pdg == 321 || abs_pdg == 311 || abs_pdg == 310 || abs_pdg == 130)
224 return 5; // kaons
225 return 6; // other
226}
227
228} // namespace dqm
229
Data class representing a single step in the Bertini intranuclear cascade.
#define DECLARE_ANALYZER(CLASS)
Macro which allows the framework to construct an analyzer given its name during configuration.
DQM analyzer for Bertini cascade history data.
Implements an event buffer system for storing event data.
Definition Event.h:40
bool exists(const std::string &name, const std::string &passName, bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.
Definition Event.cxx:107
Class which represents the process under execution.
Definition Process.h:34
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:26
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75
All CascadeSteps from a single photonuclear interaction.
All classes in the ldmx-sw project use this namespace.