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