LDMX Software
dqm::ElectroNuclearDQM Class Reference

DQM analyzer for Geant4 electro-nuclear (EN) interactions. More...

#include <ElectroNuclearDQM.h>

Public Member Functions

 ElectroNuclearDQM (const std::string &name, framework::Process &process)
 
void configure (framework::config::Parameters &parameters) override
 Callback for the EventProcessor to configure itself from the given set of parameters.
 
void analyze (const framework::Event &event) override
 Process the event and make histograms or summaries.
 
- Public Member Functions inherited from dqm::NuclearDQM
 NuclearDQM (const std::string &name, framework::Process &process)
 
void configure (framework::config::Parameters &parameters) override
 Read common configuration parameters: sim_particles_coll_name, sim_particles_passname, count_light_ions.
 
- 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.
 

Private Member Functions

void findENElectronProperties (const ldmx::SimParticle *en_electron, const std::vector< const ldmx::SimParticle * > &en_daughters)
 Fill histograms describing the EN electron and the interaction vertex.
 
void findReconstructableKinematics (const std::vector< const ldmx::SimParticle * > &en_daughters)
 Fill "reconstructable" kinematic histograms applying the semi-inclusive acceptance cuts from the analysis definition:
 

Additional Inherited Members

- Public Types inherited from dqm::NuclearDQM
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
}
 Classification of PN/EN events by the hard particles produced above a kinetic-energy threshold. More...
 
enum class  CompactEventType {
  single_neutron = 0 , single_charged_kaon = 1 , single_neutral_kaon = 2 , two_neutrons = 3 ,
  soft = 4 , other = 5
}
 Compact classification focusing on very-high-energy single particles. More...
 
- Protected Member Functions inherited from dqm::NuclearDQM
std::vector< const ldmx::SimParticle * > findDaughters (const std::map< int, ldmx::SimParticle > &particleMap, const ldmx::SimParticle *parent, int require_process_type=-1) const
 Return daughters of parent that pass PDG-based filtering:
 
void findParticleKinematics (const std::vector< const ldmx::SimParticle * > &daughters, const std::string &prefix)
 Fill kinematic histograms for the nuclear interaction products.
 
void findExtendedKinematics (const std::vector< const ldmx::SimParticle * > &daughters, const std::string &prefix)
 Fill extended kinematic histograms for EN interactions: hardest_pi_ke/theta (π± only), hardest_pi0_ke/theta, {prefix}_proton_mult, {prefix}_charged_pion_mult, {prefix}_neutral_pion_mult, leading_particle_type.
 
void findSubleadingKinematics (const ldmx::SimParticle *initiator, const std::vector< const ldmx::SimParticle * > &daughters, EventType eventType)
 Fill subleading-kinematics histograms for 1n, 2n, charged-kaon and neutral-kaon event types.
 
EventType classifyEvent (const std::vector< const ldmx::SimParticle * > &daughters, double threshold)
 Classify the event by the number and type of hard daughters above threshold [MeV] of kinetic energy.
 
CompactEventType classifyCompactEvent (const ldmx::SimParticle *initiator, const std::vector< const ldmx::SimParticle * > &daughters, double threshold)
 Compact classification: looks for a single particle carrying >= 80% of the initiator energy, or two neutrons each above threshold [MeV].
 
constexpr bool isLightIon (int pdgCode) const
 Return true if pdgCode is a light ion (Z <= 4).
 
- Protected Member Functions inherited from framework::EventProcessor
void abortEvent ()
 Abort the event immediately.
 
- Protected Attributes inherited from dqm::NuclearDQM
std::string sim_particles_coll_name_
 
std::string sim_particles_passname_
 
bool count_light_ions_ {true}
 
- 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

DQM analyzer for Geant4 electro-nuclear (EN) interactions.

Finds the primary (recoil) electron in the SimParticle map and collects its daughters that were produced by the electronNuclear process. These products are then classified and their kinematics histogrammed using the shared machinery in NuclearDQM.

Definition at line 17 of file ElectroNuclearDQM.h.

Constructor & Destructor Documentation

◆ ElectroNuclearDQM()

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

Definition at line 6 of file ElectroNuclearDQM.cxx.

8 : NuclearDQM(name, process) {}
virtual void process(Event &event) final
Processing an event for an Analyzer is calling analyze.

Member Function Documentation

◆ analyze()

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

Process the event and make histograms or summaries.

Parameters
eventThe Event to analyze

Implements framework::Analyzer.

Definition at line 153 of file ElectroNuclearDQM.cxx.

153 {
154 auto particle_map{event.getMap<int, ldmx::SimParticle>(
155 sim_particles_coll_name_, sim_particles_passname_)};
156 if (particle_map.empty()) return;
157
158 // The EN electron is the primary beam electron (recoil)
159 auto [trackID, en_electron] = analysis::getRecoil(particle_map);
160
161 // Collect daughters produced by the electronNuclear process, applying the
162 // same PDG filtering as PhotoNuclearDQM (exclude photons, heavy nuclei)
163 const auto en_daughters{
164 findDaughters(particle_map, en_electron,
165 ldmx::SimParticle::ProcessType::electronNuclear)};
166
167 findENElectronProperties(en_electron, en_daughters);
168
169 histograms_.fill("en_particle_mult", en_electron->getDaughters().size());
170
171 if (en_daughters.empty()) {
172 ldmx_log(warn) << "No EN daughters found, skipping kinematics";
173 return;
174 }
175
176 findExtendedKinematics(en_daughters, "en");
177 findReconstructableKinematics(en_daughters);
178}
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 findReconstructableKinematics(const std::vector< const ldmx::SimParticle * > &en_daughters)
Fill "reconstructable" kinematic histograms applying the semi-inclusive acceptance cuts from the anal...
void findENElectronProperties(const ldmx::SimParticle *en_electron, const std::vector< const ldmx::SimParticle * > &en_daughters)
Fill histograms describing the EN electron and the interaction vertex.
std::vector< const ldmx::SimParticle * > findDaughters(const std::map< int, ldmx::SimParticle > &particleMap, const ldmx::SimParticle *parent, int require_process_type=-1) const
Return daughters of parent that pass PDG-based filtering:
void findExtendedKinematics(const std::vector< const ldmx::SimParticle * > &daughters, const std::string &prefix)
Fill extended kinematic histograms for EN interactions: hardest_pi_ke/theta (π± only),...
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:24

◆ configure()

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

Callback for the EventProcessor to configure itself from the given set of parameters.

The parameters a processor has access to are the member variables of the python class in the sequence that has class_name equal to the EventProcessor class name.

For an example, look at MyProcessor.

Parameters
parametersParameters for configuration.

Reimplemented from framework::EventProcessor.

Definition at line 10 of file ElectroNuclearDQM.cxx.

10 {
11 NuclearDQM::configure(parameters);
12}
void configure(framework::config::Parameters &parameters) override
Read common configuration parameters: sim_particles_coll_name, sim_particles_passname,...
Definition NuclearDQM.cxx:9

◆ findENElectronProperties()

void dqm::ElectroNuclearDQM::findENElectronProperties ( const ldmx::SimParticle * en_electron,
const std::vector< const ldmx::SimParticle * > & en_daughters )
private

Fill histograms describing the EN electron and the interaction vertex.

Uses the EN electron's initial energy and vertex position, and takes the vertex position from the first EN daughter (where the reaction occurred).

Definition at line 14 of file ElectroNuclearDQM.cxx.

16 {
17 histograms_.fill("en_electron_energy", en_electron->getEnergy());
18 histograms_.fill("en_electron_vertex_x", en_electron->getVertex()[0]);
19 histograms_.fill("en_electron_vertex_y", en_electron->getVertex()[1]);
20 histograms_.fill("en_electron_vertex_z", en_electron->getVertex()[2]);
21
22 // The EN interaction vertex is where the first EN daughter was created
23 if (!en_daughters.empty()) {
24 histograms_.fill("en_vertex_x", en_daughters[0]->getVertex()[0]);
25 histograms_.fill("en_vertex_y", en_daughters[0]->getVertex()[1]);
26 histograms_.fill("en_vertex_z", en_daughters[0]->getVertex()[2]);
27 }
28}
double getEnergy() const
Get the energy of this particle [MeV].
Definition SimParticle.h:73
std::vector< double > getVertex() const
Get a vector containing the vertex of this particle in mm.

References ldmx::SimParticle::getEnergy(), and ldmx::SimParticle::getVertex().

◆ findReconstructableKinematics()

void dqm::ElectroNuclearDQM::findReconstructableKinematics ( const std::vector< const ldmx::SimParticle * > & en_daughters)
private

Fill "reconstructable" kinematic histograms applying the semi-inclusive acceptance cuts from the analysis definition:

  • theta < 80 deg from beam axis
  • |p| > 100 MeV/c for charged pions
  • |p| > 800 MeV/c for protons and kaons
  • KE > 1000 MeV for neutrons
  • KE > 2000 MeV for pi0

Fills recon_* and en_recon_* histograms mirroring the extended kinematics set, plus event_type_recon for the reconstructable subset classification.

Definition at line 30 of file ElectroNuclearDQM.cxx.

31 {
32 // Apply semi-inclusive acceptance cuts (daughters already sorted by KE desc):
33 // theta < 80 deg from beam axis
34 // |p| > 100 MeV/c for pi±
35 // |p| > 800 MeV/c for protons and kaons
36 // KE > 1000 MeV for neutrons
37 // KE > 2000 MeV for pi0
38 std::vector<const ldmx::SimParticle*> recon;
39 for (const auto* d : daughters) {
40 std::vector<double> pvec_raw{d->getMomentum()};
41 ROOT::Math::XYZVector pvec(pvec_raw[0], pvec_raw[1], pvec_raw[2]);
42 if (pvec.Theta() * (180.0 / 3.14159) >= 80.0) continue;
43
44 auto pdg_id{std::abs(d->getPdgID())};
45 double p_mag{pvec.R()};
46 double ke{d->getEnergy() - d->getMass()};
47
48 if (pdg_id == 2112) {
49 if (ke <= 1000.0) continue;
50 } else if (pdg_id == 211) {
51 if (p_mag <= 100.0) continue;
52 } else if (pdg_id == 2212 || pdg_id == 321 || pdg_id == 130 ||
53 pdg_id == 310) {
54 if (p_mag <= 800.0) continue;
55 } else if (pdg_id == 111) {
56 if (ke <= 2000.0) continue;
57 } else {
58 continue;
59 }
60 recon.push_back(d);
61 }
62
63 int recon_neutron_mult{0}, recon_proton_mult{0};
64 int recon_charged_pion_mult{0}, recon_neutral_pion_mult{0};
65 double recon_total_ke{0}, recon_total_neutron_ke{0};
66 double recon_hardest_ke{-1}, recon_hardest_theta{-1};
67 double recon_hardest_n_ke{-1}, recon_hardest_n_theta{-1};
68 double recon_hardest_p_ke{-1}, recon_hardest_p_theta{-1};
69 double recon_hardest_pi_ke{-1}, recon_hardest_pi_theta{-1};
70 double recon_hardest_pi0_ke{-1}, recon_hardest_pi0_theta{-1};
71
72 for (const auto* d : recon) {
73 auto pdg_id{std::abs(d->getPdgID())};
74 double ke{d->getEnergy() - d->getMass()};
75 recon_total_ke += ke;
76
77 std::vector<double> pvec_raw{d->getMomentum()};
78 ROOT::Math::XYZVector pvec(pvec_raw[0], pvec_raw[1], pvec_raw[2]);
79 auto theta{pvec.Theta() * (180.0 / 3.14159)};
80
81 if (recon_hardest_ke < ke) {
82 recon_hardest_ke = ke;
83 recon_hardest_theta = theta;
84 }
85
86 if (pdg_id == 2112) {
87 recon_neutron_mult++;
88 recon_total_neutron_ke += ke;
89 if (recon_hardest_n_ke < ke) {
90 recon_hardest_n_ke = ke;
91 recon_hardest_n_theta = theta;
92 }
93 } else if (pdg_id == 2212) {
94 recon_proton_mult++;
95 if (recon_hardest_p_ke < ke) {
96 recon_hardest_p_ke = ke;
97 recon_hardest_p_theta = theta;
98 }
99 } else if (pdg_id == 211) {
100 recon_charged_pion_mult++;
101 if (recon_hardest_pi_ke < ke) {
102 recon_hardest_pi_ke = ke;
103 recon_hardest_pi_theta = theta;
104 }
105 } else if (pdg_id == 111) {
106 recon_neutral_pion_mult++;
107 if (recon_hardest_pi0_ke < ke) {
108 recon_hardest_pi0_ke = ke;
109 recon_hardest_pi0_theta = theta;
110 }
111 }
112 }
113
114 if (!recon.empty()) {
115 auto leading_pdg{std::abs(recon[0]->getPdgID())};
116 int leading_type{6};
117 if (leading_pdg == 211)
118 leading_type = 0;
119 else if (leading_pdg == 111)
120 leading_type = 1;
121 else if (leading_pdg == 321)
122 leading_type = 2;
123 else if (leading_pdg == 130 || leading_pdg == 310)
124 leading_type = 3;
125 else if (leading_pdg == 2212)
126 leading_type = 4;
127 else if (leading_pdg == 2112)
128 leading_type = 5;
129 histograms_.fill("recon_leading_particle_type", leading_type);
130 }
131
132 auto recon_event_type{classifyEvent(recon, 0)};
133 histograms_.fill("event_type_recon", static_cast<int>(recon_event_type));
134
135 histograms_.fill("recon_hardest_ke", recon_hardest_ke);
136 histograms_.fill("recon_hardest_theta", recon_hardest_theta);
137 histograms_.fill("recon_hardest_n_ke", recon_hardest_n_ke);
138 histograms_.fill("recon_hardest_n_theta", recon_hardest_n_theta);
139 histograms_.fill("recon_hardest_p_ke", recon_hardest_p_ke);
140 histograms_.fill("recon_hardest_p_theta", recon_hardest_p_theta);
141 histograms_.fill("recon_hardest_pi_ke", recon_hardest_pi_ke);
142 histograms_.fill("recon_hardest_pi_theta", recon_hardest_pi_theta);
143 histograms_.fill("recon_hardest_pi0_ke", recon_hardest_pi0_ke);
144 histograms_.fill("recon_hardest_pi0_theta", recon_hardest_pi0_theta);
145 histograms_.fill("en_recon_neutron_mult", recon_neutron_mult);
146 histograms_.fill("en_recon_proton_mult", recon_proton_mult);
147 histograms_.fill("en_recon_charged_pion_mult", recon_charged_pion_mult);
148 histograms_.fill("en_recon_neutral_pion_mult", recon_neutral_pion_mult);
149 histograms_.fill("en_recon_total_ke", recon_total_ke);
150 histograms_.fill("en_recon_total_neutron_ke", recon_total_neutron_ke);
151}
EventType classifyEvent(const std::vector< const ldmx::SimParticle * > &daughters, double threshold)
Classify the event by the number and type of hard daughters above threshold [MeV] of kinetic energy.

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