LDMX Software
dqm::PhotoNuclearDQM Class Reference

Public Member Functions

 PhotoNuclearDQM (const std::string &name, framework::Process &process)
 Constructor.
 
virtual ~PhotoNuclearDQM ()=default
 Destructor.
 
void configure (framework::config::Parameters &parameters) override
 Configure this analyzer using the user specified parameters.
 
void analyze (const framework::Event &event) override
 Process the event and create the histogram summaries.
 
constexpr bool isLightIon (const int pdgCode) const
 Check if the PDG code corresponds to a light ion.
 
- Public Member Functions inherited from framework::Analyzer
 Analyzer (const std::string &name, Process &process)
 Class constructor.
 
virtual void process (Event &event) final
 Processing an event for an Analyzer is calling analyze.
 
virtual void beforeNewRun (ldmx::RunHeader &run_header) final
 Don't allow Analyzers to add parameters to the run header.
 
- Public Member Functions inherited from framework::EventProcessor
 DECLARE_FACTORY (EventProcessor, EventProcessor *, const std::string &, Process &)
 declare that we have a factory for this class
 
 EventProcessor (const std::string &name, Process &process)
 Class constructor.
 
virtual ~EventProcessor ()=default
 Class destructor.
 
virtual void onNewRun (const ldmx::RunHeader &run_header)
 Callback for the EventProcessor to take any necessary action when the run being processed changes.
 
virtual void onFileOpen (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a new event input ROOT file is opened.
 
virtual void onFileClose (EventFile &event_file)
 Callback for the EventProcessor to take any necessary action when a event input ROOT file is closed.
 
virtual void onProcessStart ()
 Callback for the EventProcessor to take any necessary action when the processing of events starts, such as creating histograms.
 
virtual void onProcessEnd ()
 Callback for the EventProcessor to take any necessary action when the processing of events finishes, such as calculating job-summary quantities.
 
template<class T >
const T & getCondition (const std::string &condition_name)
 Access a conditions object for the current event.
 
TDirectory * getHistoDirectory ()
 Access/create a directory in the histogram file for this event processor to create histograms and analysis tuples.
 
void setStorageHint (framework::StorageControl::Hint hint)
 Mark the current event as having the given storage control hint from this module_.
 
void setStorageHint (framework::StorageControl::Hint hint, const std::string &purposeString)
 Mark the current event as having the given storage control hint from this module and the given purpose string.
 
int getLogFrequency () const
 Get the current logging frequency from the process.
 
int getRunNumber () const
 Get the run number from the process.
 
std::string getName () const
 Get the processor name.
 
void createHistograms (const std::vector< framework::config::Parameters > &histos)
 Internal function which is used to create histograms passed from the python configuration @parma histos vector of Parameters that configure histograms to create.
 

Public Attributes

bool count_light_ions_
 

Private Types

enum class  CompactEventType {
  single_neutron = 0 , single_charged_kaon = 1 , single_neutral_kaon = 2 , two_neutrons = 3 ,
  soft = 4 , other = 5
}
 
enum class  EventType {
  nothing_hard = 0 , single_neutron = 1 , two_neutrons = 2 , three_or_more_neutrons = 3 ,
  single_charged_pion = 4 , two_charged_pions = 5 , single_neutral_pion = 6 , single_charged_pion_and_nucleon = 7 ,
  single_charged_pion_and_two_nucleons = 8 , two_charged_pions_and_nucleon = 9 , single_neutral_pion_and_nucleon = 10 , single_neutral_pion_and_two_nucleons = 11 ,
  single_neutral_pion_charged_pion_and_nucleon = 12 , single_proton = 13 , two_protons = 14 , proton_neutron = 15 ,
  klong = 16 , charged_kaon = 17 , kshort = 18 , exotics = 19 ,
  multibody = 20
}
 

Private Member Functions

EventType classifyEvent (const std::vector< const ldmx::SimParticle * > daughters, double threshold)
 Method used to classify events.
 
CompactEventType classifyCompactEvent (const ldmx::SimParticle *pnGamma, const std::vector< const ldmx::SimParticle * > daughters, double threshold)
 Method used to classify events in a compact manner.
 
void findRecoilProperties (const ldmx::SimParticle *recoil)
 Fill the recoil electron-histograms.
 
std::vector< const ldmx::SimParticle * > findDaughters (const std::map< int, ldmx::SimParticle > &particleMap, const ldmx::SimParticle *parent) const
 Find all daughter particles of a parent.
 
void findParticleKinematics (const std::vector< const ldmx::SimParticle * > &pnDaughters)
 Fill histograms related to kinematics of PN products.
 
void findSubleadingKinematics (const ldmx::SimParticle *pnGamma, const std::vector< const ldmx::SimParticle * > &pnDaughters, const EventType eventType)
 Fill histograms related to the kinematics and subleading particles for 1n, kaon, and 2n type events.
 

Private Attributes

std::string sim_particles_passname_
 

Additional Inherited Members

- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 
- Protected Attributes inherited from framework::EventProcessor
HistogramPool histograms_
 helper object for making and filling histograms
 
NtupleManagerntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger the_log_
 The logger for this EventProcessor.
 

Detailed Description

Definition at line 22 of file PhotoNuclearDQM.h.

Member Enumeration Documentation

◆ CompactEventType

enum class dqm::PhotoNuclearDQM::CompactEventType
strongprivate

Definition at line 24 of file PhotoNuclearDQM.h.

24 {
25 single_neutron = 0,
26 single_charged_kaon = 1,
27 single_neutral_kaon = 2,
28 two_neutrons = 3,
29 soft = 4,
30 other = 5,
31 };

◆ EventType

enum class dqm::PhotoNuclearDQM::EventType
strongprivate

Definition at line 32 of file PhotoNuclearDQM.h.

32 {
33 nothing_hard = 0,
34 single_neutron = 1,
35 two_neutrons = 2,
36 three_or_more_neutrons = 3,
37 single_charged_pion = 4,
38 two_charged_pions = 5,
39 single_neutral_pion = 6,
40 single_charged_pion_and_nucleon = 7,
41 single_charged_pion_and_two_nucleons = 8,
42 two_charged_pions_and_nucleon = 9,
43 single_neutral_pion_and_nucleon = 10,
44 single_neutral_pion_and_two_nucleons = 11,
45 single_neutral_pion_charged_pion_and_nucleon = 12,
46 single_proton = 13,
47 two_protons = 14,
48 proton_neutron = 15,
49 klong = 16,
50 charged_kaon = 17,
51 kshort = 18,
52 exotics = 19,
53 multibody = 20,
54 };

Constructor & Destructor Documentation

◆ PhotoNuclearDQM()

dqm::PhotoNuclearDQM::PhotoNuclearDQM ( const std::string & name,
framework::Process & process )

Constructor.

Definition at line 6 of file PhotoNuclearDQM.cxx.

Base class for a module which does not produce a data product.
virtual void process(Event &event) final
Processing an event for an Analyzer is calling analyze.

Member Function Documentation

◆ analyze()

void dqm::PhotoNuclearDQM::analyze ( const framework::Event & event)
overridevirtual

Process the event and create the histogram summaries.

Parameters
eventThe event to analyze.

Implements framework::Analyzer.

Definition at line 164 of file PhotoNuclearDQM.cxx.

164 {
165 // Get the particle map from the event. If the particle map is empty,
166 // don't process the event.
167 auto particle_map{event.getMap<int, ldmx::SimParticle>(
168 "SimParticles", sim_particles_passname_)};
169 if (particle_map.size() == 0) {
170 return;
171 }
172
173 // Get the recoil electron
174 auto [trackID, recoil] = analysis::getRecoil(particle_map);
175 findRecoilProperties(recoil);
176
177 // Use the recoil electron to retrieve the gamma that underwent a
178 // photo-nuclear reaction.
179 auto pn_gamma{analysis::getPNGamma(particle_map, recoil, 2500.)};
180 if (pn_gamma == nullptr) {
181 ldmx_log(warn) << "PN Daughter is lost, skipping";
182 return;
183 }
184
185 const auto pn_daughters{findDaughters(particle_map, pn_gamma)};
186
187 if (!pn_daughters.empty()) {
188 auto pn_vertex_volume{pn_daughters[0]->getVertexVolume()};
189 auto pn_interaction_material{pn_daughters[0]->getInteractionMaterial()};
190
191 // Let's start with the PN vertex volume
192 if (pn_vertex_volume.find("W_cooling") != std::string::npos) {
193 // W_cooling_volume_X
194 histograms_.fill("pn_vertex_volume", 2);
195 } else if (pn_vertex_volume.find("C_volume") != std::string::npos) {
196 // C_volume_X
197 histograms_.fill("pn_vertex_volume", 3);
198 } else if (pn_vertex_volume.find("PCB_volume") != std::string::npos) {
199 histograms_.fill("pn_vertex_volume", 4);
200 } else if (pn_vertex_volume.find("CarbonBasePlate") != std::string::npos) {
201 // CarbonBasePlate_volume
202 histograms_.fill("pn_vertex_volume", 5);
203 } else if (pn_vertex_volume.find("W_front") != std::string::npos) {
204 // W_front_volume_X
205 histograms_.fill("pn_vertex_volume", 6);
206 } else if (pn_vertex_volume.find("Si_volume") != std::string::npos) {
207 histograms_.fill("pn_vertex_volume", 7);
208 } else if (pn_vertex_volume.find("Glue") != std::string::npos) {
209 histograms_.fill("pn_vertex_volume", 8);
210 } else if (pn_vertex_volume.find("motherboard") != std::string::npos) {
211 histograms_.fill("pn_vertex_volume", 9);
212
213 } else {
214 ldmx_log(debug) << " Else pn_vertex_volume = " << pn_vertex_volume
215 << " with pn_interaction_material = "
216 << pn_interaction_material;
217 histograms_.fill("pn_vertex_volume", 1);
218 }
219
220 // Now the interaction material
221 if (pn_interaction_material.find("G4_Si") != std::string::npos) {
222 histograms_.fill("pn_interaction_material", 2);
223 } else if (pn_interaction_material.find("G4_W") != std::string::npos) {
224 histograms_.fill("pn_interaction_material", 3);
225 } else if (pn_interaction_material.find("FR4") != std::string::npos) {
226 // Glass epoxy
227 histograms_.fill("pn_interaction_material", 4);
228 } else if (pn_interaction_material.find("Steel") != std::string::npos) {
229 histograms_.fill("pn_interaction_material", 5);
230 } else if (pn_interaction_material.find("Epoxy") != std::string::npos) {
231 // CarbonEpoxyComposite
232 histograms_.fill("pn_interaction_material", 6);
233 } else if (pn_interaction_material.find("Scintillator") !=
234 std::string::npos) {
235 // This is the notion for PVT
236 histograms_.fill("pn_interaction_material", 7);
237 } else if (pn_interaction_material.find("Glue") != std::string::npos) {
238 // This is the notion for PVT
239 histograms_.fill("pn_interaction_material", 8);
240 } else if (pn_interaction_material.find("G4_AIR") != std::string::npos) {
241 // Air
242 histograms_.fill("pn_interaction_material", 9);
243 } else {
244 ldmx_log(debug) << " Else pn_interaction_material = "
245 << pn_interaction_material
246 << " with pn_vertex_volume = " << pn_vertex_volume;
247 histograms_.fill("pn_interaction_material", 1);
248 }
249 } else {
250 histograms_.fill("pn_vertex_volume", 0);
251 histograms_.fill("pn_interaction_material", 0);
252 }
253
254 findParticleKinematics(pn_daughters);
255
256 histograms_.fill("pn_particle_mult", pn_gamma->getDaughters().size());
257 histograms_.fill("pn_gamma_energy", pn_gamma->getEnergy());
258 histograms_.fill("pn_gamma_int_x", pn_gamma->getEndPoint()[0]);
259 histograms_.fill("pn_gamma_int_y", pn_gamma->getEndPoint()[1]);
260 histograms_.fill("pn_gamma_int_x:pn_gamma_int_y", pn_gamma->getEndPoint()[0],
261 pn_gamma->getEndPoint()[1]);
262 histograms_.fill("pn_gamma_int_z", pn_gamma->getEndPoint()[2]);
263 histograms_.fill("pn_gamma_vertex_x", pn_gamma->getVertex()[0]);
264 histograms_.fill("pn_gamma_vertex_y", pn_gamma->getVertex()[1]);
265 histograms_.fill("pn_gamma_vertex_z", pn_gamma->getVertex()[2]);
266
267 // Classify the event
268 auto event_type{classifyEvent(pn_daughters, 200)};
269 auto event_type500_me_v{classifyEvent(pn_daughters, 500)};
270 auto event_type2000_me_v{classifyEvent(pn_daughters, 2000)};
271
272 auto event_type_comp{classifyCompactEvent(pn_gamma, pn_daughters, 200)};
273 auto event_type_comp500_me_v{
274 classifyCompactEvent(pn_gamma, pn_daughters, 500)};
275 auto event_type_comp2000_me_v{
276 classifyCompactEvent(pn_gamma, pn_daughters, 2000)};
277
278 histograms_.fill("event_type", static_cast<int>(event_type));
279 histograms_.fill("event_type_500mev", static_cast<int>(event_type500_me_v));
280 histograms_.fill("event_type_2000mev", static_cast<int>(event_type2000_me_v));
281
282 histograms_.fill("event_type_compact", static_cast<int>(event_type_comp));
283 histograms_.fill("event_type_compact_500mev",
284 static_cast<int>(event_type_comp500_me_v));
285 histograms_.fill("event_type_compact_2000mev",
286 static_cast<int>(event_type_comp2000_me_v));
287
288 switch (event_type) {
289 case EventType::single_neutron:
290 if (pn_daughters.size() > 1) {
291 auto second_hardest_pdg_id{abs(pn_daughters[1]->getPdgID())};
292 auto n_event_type{-10};
293 if (second_hardest_pdg_id == 2112) {
294 n_event_type = 0; // n + n
295 } else if (second_hardest_pdg_id == 2212) {
296 n_event_type = 1; // p + n
297 } else if (second_hardest_pdg_id == 211) {
298 n_event_type = 2; // Pi+/- + n
299 } else if (second_hardest_pdg_id == 111) {
300 n_event_type = 3; // Pi0 + n
301 } else {
302 n_event_type = 4; // other
303 }
304 histograms_.fill("1n_event_type", n_event_type);
305 }
306 [[fallthrough]]; // Remaining code is important for 1n as well
307 case EventType::two_neutrons:
308 case EventType::charged_kaon:
309 case EventType::klong:
310 case EventType::kshort:
311 findSubleadingKinematics(pn_gamma, pn_daughters, event_type);
312 break;
313 default: // Nothing to do
314 break;
315 }
316}
const ldmx::SimParticle * getPNGamma(const std::map< int, ldmx::SimParticle > &particleMap, const ldmx::SimParticle *recoil, const float &energyThreshold)
Get a pointer to the sim particle associated with the photon that underwent a photo-nuclear reaction.
std::tuple< int, const ldmx::SimParticle * > getRecoil(const std::map< int, ldmx::SimParticle > &particleMap)
Find and return the sim particle associated with the recoil electron.
void findSubleadingKinematics(const ldmx::SimParticle *pnGamma, const std::vector< const ldmx::SimParticle * > &pnDaughters, const EventType eventType)
Fill histograms related to the kinematics and subleading particles for 1n, kaon, and 2n type events.
std::vector< const ldmx::SimParticle * > findDaughters(const std::map< int, ldmx::SimParticle > &particleMap, const ldmx::SimParticle *parent) const
Find all daughter particles of a parent.
EventType classifyEvent(const std::vector< const ldmx::SimParticle * > daughters, double threshold)
Method used to classify events.
CompactEventType classifyCompactEvent(const ldmx::SimParticle *pnGamma, const std::vector< const ldmx::SimParticle * > daughters, double threshold)
Method used to classify events in a compact manner.
void findRecoilProperties(const ldmx::SimParticle *recoil)
Fill the recoil electron-histograms.
void findParticleKinematics(const std::vector< const ldmx::SimParticle * > &pnDaughters)
Fill histograms related to kinematics of PN products.
HistogramPool histograms_
helper object for making and filling histograms
void fill(const std::string &name, const T &val)
Fill a 1D histogram.
Class representing a simulated particle.
Definition SimParticle.h:23

References classifyCompactEvent(), classifyEvent(), framework::HistogramPool::fill(), findDaughters(), findParticleKinematics(), findRecoilProperties(), findSubleadingKinematics(), and framework::EventProcessor::histograms_.

◆ classifyCompactEvent()

PhotoNuclearDQM::CompactEventType dqm::PhotoNuclearDQM::classifyCompactEvent ( const ldmx::SimParticle * pnGamma,
const std::vector< const ldmx::SimParticle * > daughters,
double threshold )
private

Method used to classify events in a compact manner.

Definition at line 424 of file PhotoNuclearDQM.cxx.

426 {
427 short n{0}, n_t{0}, k0l{0}, kp{0}, k0s{0}, soft{0};
428
429 // Loop through all of the PN daughters and extract kinematic
430 // information.
431 for (const auto &daughter : daughters) {
432 // Calculate the kinetic energy
433 auto ke{daughter->getEnergy() - daughter->getMass()};
434
435 // Get the PDG ID
436 auto pdg_id{abs(daughter->getPdgID())};
437
438 if (ke < 500) {
439 soft++;
440 continue;
441 }
442
443 if (ke >= 0.8 * pnGamma->getEnergy()) {
444 if (pdg_id == 2112) {
445 n++;
446 } else if (pdg_id == 130) {
447 k0l++;
448 } else if (pdg_id == 321) {
449 kp++;
450 } else if (pdg_id == 310) {
451 k0s++;
452 }
453 continue;
454 }
455
456 if ((pdg_id == 2112) && ke > threshold) {
457 n_t++;
458 }
459 }
460
461 int neutral_kaons{k0l + k0s};
462
463 if (n != 0) {
464 return PhotoNuclearDQM::CompactEventType::single_neutron;
465 }
466 if (kp != 0) {
467 return PhotoNuclearDQM::CompactEventType::single_charged_kaon;
468 }
469 if (neutral_kaons != 0) {
470 return PhotoNuclearDQM::CompactEventType::single_neutral_kaon;
471 }
472 if (n_t == 2) {
473 return PhotoNuclearDQM::CompactEventType::two_neutrons;
474 }
475 if (soft == daughters.size()) {
476 return PhotoNuclearDQM::CompactEventType::soft;
477 }
478
479 return PhotoNuclearDQM::CompactEventType::other;
480}
double getEnergy() const
Get the energy of this particle [MeV].
Definition SimParticle.h:72

References ldmx::SimParticle::getEnergy().

Referenced by analyze().

◆ classifyEvent()

PhotoNuclearDQM::EventType dqm::PhotoNuclearDQM::classifyEvent ( const std::vector< const ldmx::SimParticle * > daughters,
double threshold )
private

Method used to classify events.

Note: Assumes that daughters is sorted by kinetic energy.

Definition at line 318 of file PhotoNuclearDQM.cxx.

319 {
320 short n{0}, p{0}, pi{0}, pi0{0}, exotic{0}, k0l{0}, kp{0}, k0s{0};
321
322 // Loop through all of the PN daughters and extract kinematic
323 // information.
324 for (const auto &daughter : daughters) {
325 // Calculate the kinetic energy
326 auto ke{daughter->getEnergy() - daughter->getMass()};
327
328 // Assuming the daughters are sorted by kinetic energy, if the kinetic
329 // energy is below threshold, we don't need to look at any further
330 // particles.
331 if (ke <= threshold) {
332 break;
333 }
334
335 // Get the PDG ID
336 auto pdg_id{abs(daughter->getPdgID())};
337
338 if (pdg_id == 2112) {
339 n++;
340 } else if (pdg_id == 2212) {
341 p++;
342 } else if (pdg_id == 211) {
343 pi++;
344 } else if (pdg_id == 111) {
345 pi0++;
346 } else if (pdg_id == 130) {
347 k0l++;
348 } else if (pdg_id == 321) {
349 kp++;
350 } else if (pdg_id == 310) {
351 k0s++;
352 } else {
353 exotic++;
354 }
355 }
356
357 int kaons = k0l + kp + k0s;
358 int nucleons = n + p;
359 int pions = pi + pi0;
360 int count = nucleons + pions + exotic + kaons;
361
362 if (count == 0) {
363 return EventType::nothing_hard;
364 }
365 if (count == 1) {
366 if (n == 1) {
367 return EventType::single_neutron;
368 } else if (p == 1) {
369 return EventType::single_proton;
370 } else if (pi0 == 1) {
371 return EventType::single_neutral_pion;
372 } else if (pi == 1) {
373 return EventType::single_charged_pion;
374 }
375 }
376 if (count == 2) {
377 if (n == 2) {
378 return EventType::two_neutrons;
379 } else if (n == 1 && p == 1) {
380 return EventType::proton_neutron;
381 } else if (p == 2) {
382 return EventType::two_protons;
383 } else if (pi == 2) {
384 return EventType::two_charged_pions;
385 } else if (pi == 1 && nucleons == 1) {
386 return EventType::single_charged_pion_and_nucleon;
387 } else if (pi0 == 1 && nucleons == 1) {
388 return EventType::single_neutral_pion_and_nucleon;
389 }
390 }
391
392 if (count == 3) {
393 if (pi == 1 && nucleons == 2) {
394 return EventType::single_charged_pion_and_two_nucleons;
395 } else if (pi == 2 && nucleons == 1) {
396 return EventType::two_charged_pions_and_nucleon;
397 } // else
398 else if (pi0 == 1 && nucleons == 2) {
399 return EventType::single_neutral_pion_and_two_nucleons;
400 } else if (pi0 == 1 && nucleons == 1 && pi == 1) {
401 return EventType::single_neutral_pion_charged_pion_and_nucleon;
402 }
403 }
404 if (count >= 3 && count == n) {
405 return EventType::three_or_more_neutrons;
406 }
407
408 if (kaons == 1) {
409 if (k0l == 1) {
410 return EventType::klong;
411 } else if (kp == 1) {
412 return EventType::charged_kaon;
413 } else if (k0s == 1) {
414 return EventType::kshort;
415 }
416 }
417 if (exotic == count && count != 0) {
418 return EventType::exotics;
419 }
420
421 return EventType::multibody;
422}

Referenced by analyze().

◆ configure()

void dqm::PhotoNuclearDQM::configure ( framework::config::Parameters & parameters)
overridevirtual

Configure this analyzer using the user specified parameters.

Parameters
parametersSet of parameters used to configure this analyzer.

Reimplemented from framework::EventProcessor.

Definition at line 157 of file PhotoNuclearDQM.cxx.

157 {
158 count_light_ions_ = parameters.get<bool>("count_light_ions", true);
159
160 sim_particles_passname_ =
161 parameters.get<std::string>("sim_particles_passname");
162}
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78

References framework::config::Parameters::get().

◆ findDaughters()

std::vector< const ldmx::SimParticle * > dqm::PhotoNuclearDQM::findDaughters ( const std::map< int, ldmx::SimParticle > & particleMap,
const ldmx::SimParticle * parent ) const
private

Find all daughter particles of a parent.

Particles are included if they>

  • Are in the particle map,
  • Are not photons or nuclear fragment, and
  • Are not a light ion (Z < 4) if the count_light_ions_ parameter is set to false

The products are sorted by kinetic energy, in descending order.

Definition at line 10 of file PhotoNuclearDQM.cxx.

12 {
13 std::vector<const ldmx::SimParticle *> pn_daughters;
14 for (const auto &daughter_track_id : parent->getDaughters()) {
15 // skip daughters that weren't saved
16 if (particleMap.count(daughter_track_id) == 0) {
17 continue;
18 }
19
20 auto daughter{&(particleMap.at(daughter_track_id))};
21
22 // Get the PDG ID
23 auto pdg_id{daughter->getPdgID()};
24
25 // Ignore photons and nuclei
26 if (pdg_id == 22 ||
27 (pdg_id > 10000 && (!count_light_ions_ || !isLightIon(pdg_id)))) {
28 continue;
29 }
30 pn_daughters.push_back(daughter);
31 }
32
33 std::sort(pn_daughters.begin(), pn_daughters.end(),
34 [](const auto &lhs, const auto &rhs) {
35 double lhs_ke = lhs->getEnergy() - lhs->getMass();
36 double rhs_ke = rhs->getEnergy() - rhs->getMass();
37 return lhs_ke > rhs_ke;
38 });
39
40 return pn_daughters;
41}
constexpr bool isLightIon(const int pdgCode) const
Check if the PDG code corresponds to a light ion.
std::vector< int > getDaughters() const
Get a vector containing the track IDs of all daughter particles.

References ldmx::SimParticle::getDaughters(), and isLightIon().

Referenced by analyze().

◆ findParticleKinematics()

void dqm::PhotoNuclearDQM::findParticleKinematics ( const std::vector< const ldmx::SimParticle * > & pnDaughters)
private

Fill histograms related to kinematics of PN products.

Definition at line 49 of file PhotoNuclearDQM.cxx.

50 {
51 double hardest_ke{-1}, hardest_theta{-1};
52 double hardest_proton_ke{-1}, hardest_proton_theta{-1};
53 double hardest_neutron_ke{-1}, hardest_neutron_theta{-1};
54 double hardest_pion_ke{-1}, hardest_pion_theta{-1};
55 double total_ke{0};
56 double total_neutron_ke{0};
57 int neutron_multiplicity{0};
58 // Loop through all of the PN daughters and extract kinematic
59 // information.
60 for (const auto *daughter : pnDaughters) {
61 // skip daughters that weren't saved
62
63 // Get the PDG ID
64 auto pdg_id{daughter->getPdgID()};
65
66 // Calculate the kinetic energy
67 double ke{daughter->getEnergy() - daughter->getMass()};
68 total_ke += ke;
69
70 std::vector<double> vec{daughter->getMomentum()};
71 ROOT::Math::XYZVector pvec(vec[0], vec[1], vec[2]);
72
73 // Calculate the polar angle
74 auto theta{pvec.Theta() * (180 / 3.14159)};
75
76 if (hardest_ke < ke) {
77 hardest_ke = ke;
78 hardest_theta = theta;
79 }
80
81 if (pdg_id == 2112) {
82 total_neutron_ke += ke;
83 neutron_multiplicity++;
84 if (hardest_neutron_ke < ke) {
85 hardest_neutron_ke = ke;
86 hardest_neutron_theta = theta;
87 }
88 }
89
90 if ((pdg_id == 2212) && (hardest_proton_ke < ke)) {
91 hardest_proton_ke = ke;
92 hardest_proton_theta = theta;
93 }
94
95 if (((std::abs(pdg_id) == 211) || (pdg_id == 111)) &&
96 (hardest_pion_ke < ke)) {
97 hardest_pion_ke = ke;
98 hardest_pion_theta = theta;
99 }
100 }
101 histograms_.fill("hardest_ke", hardest_ke);
102 histograms_.fill("hardest_theta", hardest_theta);
103 histograms_.fill("h_ke_h_theta", hardest_ke, hardest_theta);
104 histograms_.fill("hardest_p_ke", hardest_proton_ke);
105 histograms_.fill("hardest_p_theta", hardest_proton_theta);
106 histograms_.fill("hardest_n_ke", hardest_neutron_ke);
107 histograms_.fill("hardest_n_theta", hardest_neutron_theta);
108 histograms_.fill("hardest_pi_ke", hardest_pion_ke);
109 histograms_.fill("hardest_pi_theta", hardest_pion_theta);
110
111 histograms_.fill("pn_neutron_mult", neutron_multiplicity);
112 histograms_.fill("pn_total_ke", total_ke);
113 histograms_.fill("pn_total_neutron_ke", total_neutron_ke);
114}

References framework::HistogramPool::fill(), and framework::EventProcessor::histograms_.

Referenced by analyze().

◆ findRecoilProperties()

void dqm::PhotoNuclearDQM::findRecoilProperties ( const ldmx::SimParticle * recoil)
private

Fill the recoil electron-histograms.

Definition at line 42 of file PhotoNuclearDQM.cxx.

42 {
43 histograms_.fill("recoil_vertex_x", recoil->getVertex()[0]);
44 histograms_.fill("recoil_vertex_y", recoil->getVertex()[1]);
45 histograms_.fill("recoil_vertex_z", recoil->getVertex()[2]);
46 histograms_.fill("recoil_vertex_x:recoil_vertex_y", recoil->getVertex()[0],
47 recoil->getVertex()[1]);
48}
std::vector< double > getVertex() const
Get a vector containing the vertex of this particle in mm.

References framework::HistogramPool::fill(), ldmx::SimParticle::getVertex(), and framework::EventProcessor::histograms_.

Referenced by analyze().

◆ findSubleadingKinematics()

void dqm::PhotoNuclearDQM::findSubleadingKinematics ( const ldmx::SimParticle * pnGamma,
const std::vector< const ldmx::SimParticle * > & pnDaughters,
const EventType eventType )
private

Fill histograms related to the kinematics and subleading particles for 1n, kaon, and 2n type events.

Note: This assumes that the daughter particles are sorted by energy.

Definition at line 116 of file PhotoNuclearDQM.cxx.

119 {
120 // Note: Assumes sorted by energy
121
122 double subleading_ke{-9999};
123 double n_energy{-9999}, energy_diff{-9999}, energy_frac{-9999};
124
125 n_energy = pnDaughters[0]->getEnergy() - pnDaughters[0]->getMass();
126 subleading_ke = -9999;
127 if (pnDaughters.size() > 1) {
128 subleading_ke = pnDaughters[1]->getEnergy() - pnDaughters[1]->getMass();
129 }
130 energy_diff = pnGamma->getEnergy() - n_energy;
131 energy_frac = n_energy / pnGamma->getEnergy();
132
133 if (eventType == EventType::single_neutron) {
134 histograms_.fill("1n_ke:2nd_h_ke", n_energy, subleading_ke);
135 histograms_.fill("1n_neutron_energy", n_energy);
136 histograms_.fill("1n_energy_diff", energy_diff);
137 histograms_.fill("1n_energy_frac", energy_frac);
138 } else if (eventType == EventType::two_neutrons) {
139 histograms_.fill("2n_n2_energy", subleading_ke);
140 auto energy_frac2n = (n_energy + subleading_ke) / pnGamma->getEnergy();
141 histograms_.fill("2n_energy_frac", energy_frac2n);
142 histograms_.fill("2n_energy_other", pnGamma->getEnergy() - energy_frac2n);
143
144 } else if (eventType == EventType::charged_kaon) {
145 histograms_.fill("1kp_ke:2nd_h_ke", n_energy, subleading_ke);
146 histograms_.fill("1kp_energy", n_energy);
147 histograms_.fill("1kp_energy_diff", energy_diff);
148 histograms_.fill("1kp_energy_frac", energy_frac);
149 } else if (eventType == EventType::klong || eventType == EventType::kshort) {
150 histograms_.fill("1k0_ke:2nd_h_ke", n_energy, subleading_ke);
151 histograms_.fill("1k0_energy", n_energy);
152 histograms_.fill("1k0_energy_diff", energy_diff);
153 histograms_.fill("1k0_energy_frac", energy_frac);
154 }
155}

References framework::HistogramPool::fill(), ldmx::SimParticle::getEnergy(), and framework::EventProcessor::histograms_.

Referenced by analyze().

◆ isLightIon()

bool dqm::PhotoNuclearDQM::isLightIon ( const int pdgCode) const
inlineconstexpr

Check if the PDG code corresponds to a light ion.

Nuclear PDG codes are given by ±10LZZZAAAI So to find the atomic number, we first divide by 10 (to lose the I-component) and then take the modulo with 1000.

TODO: Repeated code from SimCore, could probably live elsewhere.

Definition at line 142 of file PhotoNuclearDQM.h.

142 {
143 if (pdgCode > 1000000000) {
144 // Check if the atomic number is less than or equal to 4
145 return ((pdgCode / 10) % 1000) <= 4;
146 }
147 return false;
148 }

Referenced by findDaughters().

Member Data Documentation

◆ count_light_ions_

bool dqm::PhotoNuclearDQM::count_light_ions_

Definition at line 150 of file PhotoNuclearDQM.h.

◆ sim_particles_passname_

std::string dqm::PhotoNuclearDQM::sim_particles_passname_
private

Definition at line 84 of file PhotoNuclearDQM.h.


The documentation for this class was generated from the following files: