41 particle_coll_name_, particle_passname_)};
43 for (
const auto& [track_id, particle] : particle_map) {
44 if (track_id == 1) beam = &particle;
45 if (particle.getProcessType() ==
46 ldmx::SimParticle::ProcessType::eDarkBrem) {
47 if (particle.getPdgID() == 622) {
48 if (aprime !=
nullptr) {
49 EXCEPTION_RAISE(
"BadEvent",
"Found multiple A' in event.");
58 if (recoil ==
nullptr and aprime ==
nullptr) {
65 ldmx_log(error) <<
" No dark brem occured in this event";
69 if (recoil ==
nullptr or aprime ==
nullptr or beam ==
nullptr) {
73 <<
"Unable to find all necessary particles for DarkBrem interaction."
74 <<
" Missing: [ " << (recoil ==
nullptr ?
" recoil " :
"")
75 << (aprime ==
nullptr ?
" aprime " :
"")
76 << (beam ==
nullptr ?
" beam " :
"") <<
"]";
79 "Unable to find all necessary particles for DarkBrem interaction.");
84 const auto& aprime_p = aprime->getMomentum();
85 ROOT::Math::XYZVector recoil_pvec(recoil_p[0], recoil_p[1], recoil_p[2]);
86 ROOT::Math::XYZVector aprime_pvec(aprime_p[0], aprime_p[1], aprime_p[2]);
88 std::vector<double> incident_p = recoil_p;
89 for (std::size_t i{0}; i < recoil_p.size(); ++i)
90 incident_p[i] += aprime_p.at(i);
92 double incident_energy = energy(incident_p, recoil->getMass());
93 double recoil_energy = energy(recoil_p, recoil->getMass());
95 std::vector<double> ap_vertex{aprime->getVertex()};
96 std::string ap_vertex_volume{aprime->getVertexVolume()};
97 auto ap_vertex_material_it = std::find_if(
99 [&](
const auto& mat_pair) {
100 return ap_vertex_volume.find(mat_pair.first) != std::string::npos;
103 ? ap_vertex_material_it->second
106 if (ap_vertex_material == 0) {
107 ldmx_log(warn) <<
"Dark brem interaction occurred in an unknown material: "
111 int ap_parent_id{-1};
112 if (aprime->getParents().size() > 0) {
113 ap_parent_id = aprime->getParents().at(0);
115 ldmx_log(error) <<
"Found A' without a parent ID!";
118 float aprime_energy = energy(aprime_p, aprime->getMass());
119 int aprime_genstatus = aprime->getGenStatus();
120 double aprime_px{aprime_p.at(0)}, aprime_py{aprime_p.at(1)},
121 aprime_pz{aprime_p.at(2)};
122 event.add(
"APrimeEnergy", aprime_energy);
123 event.add(
"APrimePx", aprime_px);
124 event.add(
"APrimePy", aprime_py);
125 event.add(
"APrimePz", aprime_pz);
126 event.add(
"APrimeParentID", ap_parent_id);
127 event.add(
"APrimeGenStatus", aprime_genstatus);
131 histograms_.
fill(
"aprime_theta", aprime_pvec.Theta() * (180 / 3.14159));
133 int recoil_genstatus = recoil->getGenStatus();
134 double recoil_px{recoil_p.at(0)}, recoil_py{recoil_p.at(1)},
135 recoil_pz{recoil_p.at(2)};
136 event.add(
"RecoilEnergy", recoil_energy);
137 event.add(
"RecoilPx", recoil_px);
138 event.add(
"RecoilPy", recoil_py);
139 event.add(
"RecoilPz", recoil_pz);
140 event.add(
"RecoilGenStatus", recoil_genstatus);
144 histograms_.
fill(
"recoil_theta", recoil_pvec.Theta() * (180 / 3.14159));
146 event.add(
"IncidentEnergy", incident_energy);
147 double incident_px{incident_p.at(0)}, incident_py{incident_p.at(1)},
148 incident_pz{incident_p.at(2)};
149 event.add(
"IncidentPx", incident_px);
150 event.add(
"IncidentPy", incident_py);
151 event.add(
"IncidentPz", incident_pz);
156 double vtx_x{aprime->getVertex().at(0)}, vtx_y{aprime->getVertex().at(1)},
157 vtx_z{aprime->getVertex().at(2)};
158 event.add(
"DarkBremX", vtx_x);
159 event.add(
"DarkBremY", vtx_y);
160 event.add(
"DarkBremZ", vtx_z);
161 event.add(
"DarkBremVertexMaterial", ap_vertex_material);
162 float db_material_z =
163 event.getEventHeader().getFloatParameter(
"db_material_z");
164 event.add(
"DarkBremVertexMaterialZ", db_material_z);
165 float aprime_conversion_material_z =
166 event.getEventHeader().getFloatParameter(
"aprime_conversion_material_z");
171 if (db_material_z > 0) {
176 <<
"Dark brem interaction occurred in an unknown element with Z = "
177 << db_material_z <<
". Using index " << i_element
178 <<
" for this element.";
188 std::vector<int> aprime_daughters = aprime->getDaughters();
189 int n_ap_daughters = aprime_daughters.size();
190 ldmx_log(debug) <<
"A' with energy " << aprime->getEnergy() <<
" and momentum"
191 <<
" (" << aprime_px <<
", " << aprime_py <<
", " << aprime_pz
192 <<
") GeV " <<
" has " << n_ap_daughters <<
" daughters";
193 if (n_ap_daughters == 0) {
199 for (
const auto& [track_id, daughter_particle] : particle_map) {
200 for (
const auto& primary_daughter : aprime_daughters) {
201 if (track_id == primary_daughter) {
202 auto const& daughter_p = daughter_particle.getMomentum();
203 double daughter_px{daughter_p.at(0)}, daughter_py{daughter_p.at(1)},
204 daughter_pz{daughter_p.at(2)};
206 ldmx_log(debug) <<
" Daughter track ID " << track_id
207 <<
" with PDG ID " << daughter_particle.getPdgID()
208 <<
" and energy " << daughter_particle.getEnergy()
209 <<
" and charge " << daughter_particle.getCharge()
210 <<
" and mass " << daughter_particle.getMass()
211 <<
" GeV" <<
" and momentum (" << daughter_px <<
", "
212 << daughter_py <<
", " << daughter_pz <<
") GeV";
214 daughter_particle.getEnergy());
216 quadsum({daughter_px, daughter_py}));
219 double daughter_start_z = daughter_particle.getVertex().at(2);
225 std::string daughter_material_name =
226 daughter_particle.getInteractionMaterial();
227 std::string daughter_vertex_volume =
228 daughter_particle.getVertexVolume();
229 int daughter_material = 0;
231 if (daughter_material_name.find(
"Carbon") != std::string::npos) {
232 daughter_material = 1;
233 }
else if (daughter_material_name.find(
"FR4") != std::string::npos ||
234 daughter_material_name.find(
"PCB") != std::string::npos ||
235 daughter_vertex_volume.find(
"motherboard") !=
237 daughter_vertex_volume.find(
"PCB") != std::string::npos) {
238 daughter_material = 2;
239 }
else if (daughter_material_name.find(
"Glue") != std::string::npos ||
240 daughter_vertex_volume.find(
"Glue") != std::string::npos ||
241 daughter_vertex_volume.find(
"CFMix") !=
243 daughter_material = 3;
244 }
else if (daughter_material_name.find(
"Silicon") !=
246 daughter_material_name.find(
"Si") != std::string::npos ||
247 daughter_vertex_volume.find(
"Si") != std::string::npos ||
248 daughter_vertex_volume.find(
"Sensor") !=
250 daughter_vertex_volume.find(
"sensor") !=
252 daughter_material = 4;
253 }
else if (daughter_material_name.find(
"Al") != std::string::npos ||
254 daughter_material_name.find(
"Aluminum") !=
256 daughter_vertex_volume.find(
"strongback") !=
258 daughter_vertex_volume.find(
"support") !=
260 daughter_material = 5;
261 }
else if (daughter_material_name.find(
"W") != std::string::npos ||
262 daughter_material_name.find(
"Tungsten") !=
264 daughter_vertex_volume.find(
"target") !=
266 daughter_vertex_volume.find(
"W_front_volume") !=
268 daughter_vertex_volume.find(
"W_cooling") !=
270 daughter_material = 6;
271 }
else if (daughter_material_name.find(
"Polyvinyltoluene") !=
273 daughter_material_name.find(
"PVT") != std::string::npos ||
274 daughter_vertex_volume.find(
"trigger_pad") !=
276 daughter_material = 7;
277 }
else if (daughter_material_name.find(
"Air") != std::string::npos ||
278 daughter_vertex_volume.find(
"Air") != std::string::npos) {
279 daughter_material = 8;
281 ldmx_log(warn) <<
"Daughter particle track ID " << track_id
282 <<
" created in unknown material: "
283 << daughter_material_name
284 <<
" and vertex volume: " << daughter_vertex_volume;
291 int daughter_element = 0;
292 if (aprime_conversion_material_z > 0) {
298 static_cast<int>(aprime_conversion_material_z));
303 if (daughter_particle.getPdgID() == 11) {
305 }
else if (daughter_particle.getPdgID() == -11) {
307 }
else if (daughter_particle.getPdgID() == 13) {
309 }
else if (daughter_particle.getPdgID() == -13) {
311 }
else if (daughter_particle.getPdgID() == 17) {
313 }
else if (daughter_particle.getPdgID() == -17) {
315 }
else if (daughter_particle.getPdgID() == 211) {
317 }
else if (daughter_particle.getPdgID() == -211) {
328 std::vector<int> recoil_daughters = recoil->getDaughters();
329 int n_recoil_brem_daughters = 0;
331 for (
const auto& [track_id, daughter_particle] : particle_map) {
332 for (
const auto& primary_daughter : recoil_daughters) {
333 if (track_id == primary_daughter) {
334 if (daughter_particle.getEnergy() > (0.2 * recoil->getEnergy()) &&
335 (daughter_particle.getPdgID() == 22)) {
336 n_recoil_brem_daughters++;
338 daughter_particle.getEnergy());
340 daughter_particle.getEnergy() / recoil->getEnergy());
341 ldmx_log(debug) <<
" Recoil electron daughter track ID " << track_id
342 <<
" with PDG ID " << daughter_particle.getPdgID()
343 <<
" and energy " << daughter_particle.getEnergy();