44 particle_coll_name_, particle_passname_)};
46 for (
const auto& [track_id, particle] : particle_map) {
47 if (track_id == 1) beam = &particle;
48 if (particle.getProcessType() ==
49 ldmx::SimParticle::ProcessType::eDarkBrem) {
50 if (particle.getPdgID() == 622) {
51 if (aprime !=
nullptr) {
52 EXCEPTION_RAISE(
"BadEvent",
"Found multiple A' in event.");
61 if (recoil ==
nullptr and aprime ==
nullptr) {
68 ldmx_log(error) <<
" No dark brem occured in this event";
72 if (recoil ==
nullptr or aprime ==
nullptr or beam ==
nullptr) {
76 <<
"Unable to find all necessary particles for DarkBrem interaction."
77 <<
" Missing: [ " << (recoil ==
nullptr ?
" recoil " :
"")
78 << (aprime ==
nullptr ?
" aprime " :
"")
79 << (beam ==
nullptr ?
" beam " :
"") <<
"]";
82 "Unable to find all necessary particles for DarkBrem interaction.");
87 const auto& aprime_p = aprime->getMomentum();
88 ROOT::Math::XYZVector recoil_pvec(recoil_p[0], recoil_p[1], recoil_p[2]);
89 ROOT::Math::XYZVector aprime_pvec(aprime_p[0], aprime_p[1], aprime_p[2]);
91 std::vector<double> incident_p = recoil_p;
92 for (std::size_t i{0}; i < recoil_p.size(); ++i)
93 incident_p[i] += aprime_p.at(i);
95 double incident_energy = energy(incident_p, recoil->getMass());
96 double recoil_energy = energy(recoil_p, recoil->getMass());
98 std::vector<double> ap_vertex{aprime->getVertex()};
99 std::string ap_vertex_volume{aprime->getVertexVolume()};
100 auto ap_vertex_material_it = std::find_if(
102 [&](
const auto& mat_pair) {
103 return ap_vertex_volume.find(mat_pair.first) != std::string::npos;
106 ? ap_vertex_material_it->second
109 if (ap_vertex_material == 0) {
110 ldmx_log(warn) <<
"Dark brem interaction occurred in an unknown material: "
114 int ap_parent_id{-1};
115 if (aprime->getParents().size() > 0) {
116 ap_parent_id = aprime->getParents().at(0);
118 ldmx_log(error) <<
"Found A' without a parent ID!";
121 float aprime_energy = energy(aprime_p, aprime->getMass());
122 int aprime_genstatus = aprime->getGenStatus();
123 double aprime_px{aprime_p.at(0)}, aprime_py{aprime_p.at(1)},
124 aprime_pz{aprime_p.at(2)};
125 event.add(
"APrimeEnergy", aprime_energy);
126 event.add(
"APrimePx", aprime_px);
127 event.add(
"APrimePy", aprime_py);
128 event.add(
"APrimePz", aprime_pz);
129 event.add(
"APrimeParentID", ap_parent_id);
130 event.add(
"APrimeGenStatus", aprime_genstatus);
134 histograms_.
fill(
"aprime_theta", aprime_pvec.Theta() * (180 / 3.14159));
136 int recoil_genstatus = recoil->getGenStatus();
137 double recoil_px{recoil_p.at(0)}, recoil_py{recoil_p.at(1)},
138 recoil_pz{recoil_p.at(2)};
139 event.add(
"RecoilEnergy", recoil_energy);
140 event.add(
"RecoilPx", recoil_px);
141 event.add(
"RecoilPy", recoil_py);
142 event.add(
"RecoilPz", recoil_pz);
143 event.add(
"RecoilGenStatus", recoil_genstatus);
147 histograms_.
fill(
"recoil_theta", recoil_pvec.Theta() * (180 / 3.14159));
149 event.add(
"IncidentEnergy", incident_energy);
150 double incident_px{incident_p.at(0)}, incident_py{incident_p.at(1)},
151 incident_pz{incident_p.at(2)};
152 event.add(
"IncidentPx", incident_px);
153 event.add(
"IncidentPy", incident_py);
154 event.add(
"IncidentPz", incident_pz);
159 double vtx_x{aprime->getVertex().at(0)}, vtx_y{aprime->getVertex().at(1)},
160 vtx_z{aprime->getVertex().at(2)};
161 event.add(
"DarkBremX", vtx_x);
162 event.add(
"DarkBremY", vtx_y);
163 event.add(
"DarkBremZ", vtx_z);
164 event.add(
"DarkBremVertexMaterial", ap_vertex_material);
165 float db_material_z =
166 event.getEventHeader().getFloatParameter(
"db_material_z");
167 event.add(
"DarkBremVertexMaterialZ", db_material_z);
168 float aprime_conversion_material_z =
169 event.getEventHeader().getFloatParameter(
"aprime_conversion_material_z");
174 if (db_material_z > 0) {
179 <<
"Dark brem interaction occurred in an unknown element with Z = "
180 << db_material_z <<
". Using index " << i_element
181 <<
" for this element.";
191 std::vector<int> aprime_daughters = aprime->getDaughters();
192 int n_ap_daughters = aprime_daughters.size();
193 ldmx_log(debug) <<
"A' with energy " << aprime->getEnergy() <<
" and momentum"
194 <<
" (" << aprime_px <<
", " << aprime_py <<
", " << aprime_pz
195 <<
") GeV " <<
" has " << n_ap_daughters <<
" daughters";
196 if (n_ap_daughters == 0) {
202 for (
const auto& [track_id, daughter_particle] : particle_map) {
203 for (
const auto& primary_daughter : aprime_daughters) {
204 if (track_id == primary_daughter) {
205 auto const& daughter_p = daughter_particle.getMomentum();
206 double daughter_px{daughter_p.at(0)}, daughter_py{daughter_p.at(1)},
207 daughter_pz{daughter_p.at(2)};
209 ldmx_log(debug) <<
" Daughter track ID " << track_id
210 <<
" with PDG ID " << daughter_particle.getPdgID()
211 <<
" and energy " << daughter_particle.getEnergy()
212 <<
" and charge " << daughter_particle.getCharge()
213 <<
" and mass " << daughter_particle.getMass()
214 <<
" GeV" <<
" and momentum (" << daughter_px <<
", "
215 << daughter_py <<
", " << daughter_pz <<
") GeV";
217 daughter_particle.getEnergy());
219 quadsum({daughter_px, daughter_py}));
222 double daughter_start_z = daughter_particle.getVertex().at(2);
228 std::string daughter_material_name =
229 daughter_particle.getInteractionMaterial();
230 std::string daughter_vertex_volume =
231 daughter_particle.getVertexVolume();
232 int daughter_material = 0;
234 if (daughter_material_name.find(
"Carbon") != std::string::npos) {
235 daughter_material = 1;
236 }
else if (daughter_material_name.find(
"FR4") != std::string::npos ||
237 daughter_material_name.find(
"PCB") != std::string::npos ||
238 daughter_vertex_volume.find(
"motherboard") !=
240 daughter_vertex_volume.find(
"PCB") != std::string::npos) {
241 daughter_material = 2;
242 }
else if (daughter_material_name.find(
"Glue") != std::string::npos ||
243 daughter_vertex_volume.find(
"Glue") != std::string::npos ||
244 daughter_vertex_volume.find(
"CFMix") !=
246 daughter_material = 3;
247 }
else if (daughter_material_name.find(
"Silicon") !=
249 daughter_material_name.find(
"Si") != std::string::npos ||
250 daughter_vertex_volume.find(
"Si") != std::string::npos ||
251 daughter_vertex_volume.find(
"Sensor") !=
253 daughter_vertex_volume.find(
"sensor") !=
255 daughter_material = 4;
256 }
else if (daughter_material_name.find(
"Al") != std::string::npos ||
257 daughter_material_name.find(
"Aluminum") !=
259 daughter_vertex_volume.find(
"strongback") !=
261 daughter_vertex_volume.find(
"support") !=
263 daughter_material = 5;
264 }
else if (daughter_material_name.find(
"W") != std::string::npos ||
265 daughter_material_name.find(
"Tungsten") !=
267 daughter_vertex_volume.find(
"target") !=
269 daughter_vertex_volume.find(
"W_front_volume") !=
271 daughter_vertex_volume.find(
"W_cooling") !=
273 daughter_material = 6;
274 }
else if (daughter_material_name.find(
"Polyvinyltoluene") !=
276 daughter_material_name.find(
"PVT") != std::string::npos ||
277 daughter_vertex_volume.find(
"trigger_pad") !=
279 daughter_material = 7;
280 }
else if (daughter_material_name.find(
"Air") != std::string::npos ||
281 daughter_vertex_volume.find(
"Air") != std::string::npos) {
282 daughter_material = 8;
284 ldmx_log(warn) <<
"Daughter particle track ID " << track_id
285 <<
" created in unknown material: "
286 << daughter_material_name
287 <<
" and vertex volume: " << daughter_vertex_volume;
294 int daughter_element = 0;
295 if (aprime_conversion_material_z > 0) {
301 static_cast<int>(aprime_conversion_material_z));
306 if (daughter_particle.getPdgID() == 11) {
308 }
else if (daughter_particle.getPdgID() == -11) {
310 }
else if (daughter_particle.getPdgID() == 13) {
312 }
else if (daughter_particle.getPdgID() == -13) {
314 }
else if (daughter_particle.getPdgID() == 17) {
316 }
else if (daughter_particle.getPdgID() == -17) {
318 }
else if (daughter_particle.getPdgID() == 211) {
320 }
else if (daughter_particle.getPdgID() == -211) {
331 std::vector<int> recoil_daughters = recoil->getDaughters();
332 int n_recoil_brem_daughters = 0;
334 for (
const auto& [track_id, daughter_particle] : particle_map) {
335 for (
const auto& primary_daughter : recoil_daughters) {
336 if (track_id == primary_daughter) {
337 if (daughter_particle.getEnergy() > (0.2 * recoil->getEnergy()) &&
338 (daughter_particle.getPdgID() == 22)) {
339 n_recoil_brem_daughters++;
341 daughter_particle.getEnergy());
343 daughter_particle.getEnergy() / recoil->getEnergy());
344 ldmx_log(debug) <<
" Recoil electron daughter track ID " << track_id
345 <<
" with PDG ID " << daughter_particle.getPdgID()
346 <<
" and energy " << daughter_particle.getEnergy();