LDMX Software
ecal::EcalDigiProducer Class Reference

Performs basic ECal digitization. More...

#include <EcalDigiProducer.h>

Public Member Functions

 EcalDigiProducer (const std::string &name, framework::Process &process)
 Constructor.
 
virtual ~EcalDigiProducer ()=default
 Destructor.
 
virtual void configure (framework::config::Parameters &) override
 Configure this producer from the python configuration.
 
virtual void produce (framework::Event &event) override
 Simulates measurement of pulse and creates digi collection for input event.
 
virtual void onNewRun (const ldmx::RunHeader &runHeader) override
 Set up random number / noise generation.
 
- Public Member Functions inherited from framework::Producer
 Producer (const std::string &name, Process &process)
 Class constructor.
 
virtual void process (Event &event) final
 Processing an event for a Producer is calling produce.
 
- 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 beforeNewRun (ldmx::RunHeader &run_header)
 Callback for Producers to add parameters to the run header before conditions are initialized.
 
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 Attributes

std::string input_coll_name_
 input hit collection name
 
std::string input_pass_name_
 input pass name
 
std::string digi_coll_name_
 output hit collection name
 
double clock_cycle_
 Time interval for chip clock in ns.
 
int n_adcs_
 Depth of ADC buffer.
 
int i_soi_
 Index for the Sample Of Interest in the list of digi samples.
 
double mev_
 Conversion from energy in MeV to voltage in mV.
 
bool zero_suppression_
 When emulating noise in empty channels, do we zero suppress?
 
bool noise_ {true}
 Put noise into empty channels, not configurable, only helpful in development.
 
std::unique_ptr< ldmx::HgcrocEmulator > hgcroc_
 Hgcroc Emulator to digitize analog voltage signals.
 
double ns_
 Conversion from time in ns to ticks of the internal clock.
 
double readout_threshold_
 Read out threshold.
 
double pedestal_
 Read out pedestal.
 
double noise_rms_
 Noise RMS.
 
std::unique_ptr< ldmx::NoiseGenerator > noise_generator_
 Generates noise hits based off of number of cells that are not hit.
 
std::mt19937 rng_
 Generates random numbers for which channels to fill up with noise.
 

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
 
NtupleManager & ntuple_ {NtupleManager::getInstance()}
 Manager for any ntuples.
 
logging::logger the_log_
 The logger for this EventProcessor.
 

Detailed Description

Performs basic ECal digitization.

Definition at line 33 of file EcalDigiProducer.h.

Constructor & Destructor Documentation

◆ EcalDigiProducer()

ecal::EcalDigiProducer::EcalDigiProducer ( const std::string & name,
framework::Process & process )
inline

Constructor.

Definition at line 38 of file EcalDigiProducer.h.

39 : Producer(name, process) {}
Producer(const std::string &name, Process &process)
Class constructor.
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.

Member Function Documentation

◆ configure()

void ecal::EcalDigiProducer::configure ( framework::config::Parameters & ps)
overridevirtual

Configure this producer from the python configuration.

Sets event constants and configures the noise generator, noise injector, and pulse function. Creates digi collection

Reimplemented from framework::EventProcessor.

Definition at line 21 of file EcalDigiProducer.cxx.

21 {
22 // settings of readout chip
23 // used in actual digitization
24 auto hgcroc_params = ps.get<framework::config::Parameters>("hgcroc");
25 hgcroc_ = std::make_unique<ldmx::HgcrocEmulator>(hgcroc_params);
26 clock_cycle_ = hgcroc_params.get<double>("clock_cycle");
27 n_adcs_ = hgcroc_params.get<int>("n_adcs");
28 i_soi_ = hgcroc_params.get<int>("i_soi");
29 noise_ = hgcroc_params.get<bool>("noise");
30
31 // collection names
32 input_coll_name_ = ps.get<std::string>("input_coll_name");
33 input_pass_name_ = ps.get<std::string>("input_pass_name");
34 digi_coll_name_ = ps.get<std::string>("digi_coll_name");
35
36 zero_suppression_ = ps.get<bool>("zero_suppression");
37
38 // physical constants
39 // used to calculate unit conversions
40 mev_ = ps.get<double>("mev");
41
42 // Time -> clock counts conversion
43 // time [ns] * ( 2^10 / max time in ns ) = clock counts
44 ns_ = 1024. / clock_cycle_;
45
46 readout_threshold_ = ps.get<double>("avg_readout_threshold");
47 pedestal_ = ps.get<double>("avg_pedestal");
48 noise_rms_ = ps.get<double>("avg_noise_rms");
49}
std::string input_pass_name_
input pass name
double noise_rms_
Noise RMS.
bool noise_
Put noise into empty channels, not configurable, only helpful in development.
double readout_threshold_
Read out threshold.
double pedestal_
Read out pedestal.
double mev_
Conversion from energy in MeV to voltage in mV.
int i_soi_
Index for the Sample Of Interest in the list of digi samples.
double clock_cycle_
Time interval for chip clock in ns.
double ns_
Conversion from time in ns to ticks of the internal clock.
std::string digi_coll_name_
output hit collection name
int n_adcs_
Depth of ADC buffer.
std::string input_coll_name_
input hit collection name
std::unique_ptr< ldmx::HgcrocEmulator > hgcroc_
Hgcroc Emulator to digitize analog voltage signals.
bool zero_suppression_
When emulating noise in empty channels, do we zero suppress?
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:26
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:75

References clock_cycle_, digi_coll_name_, framework::config::Parameters::get(), hgcroc_, i_soi_, input_coll_name_, input_pass_name_, mev_, n_adcs_, noise_, noise_rms_, ns_, pedestal_, readout_threshold_, and zero_suppression_.

◆ onNewRun()

void ecal::EcalDigiProducer::onNewRun ( const ldmx::RunHeader & runHeader)
overridevirtual

Set up random number / noise generation.

Reimplemented from framework::EventProcessor.

Definition at line 51 of file EcalDigiProducer.cxx.

51 {
52 // noise generator by default uses a Gausian model for noise
53 // i.e. It assumes the noise is distributed around a mean (setPedestal)
54 // with a certain RMS (setNoise) and then calculates
55 // how many hits_ should be generated for a given number of empty
56 // channels and a minimum readout value (setNoiseThreshold)
57 noise_generator_ = std::make_unique<ldmx::NoiseGenerator>();
58 // Configure generator that will produce noise hits_ in empty channels
59 // rms noise in mV
61 // mean noise amplitude (if using Gaussian Model for the noise) in mV
62 noise_generator_->setPedestal(pedestal_);
63 // threshold for readout in mV
64 noise_generator_->setNoiseThreshold(readout_threshold_);
65 // Set up seeds
68 noise_generator_->seedGenerator(
69 rseed.getSeed("EcalDigiProducer::NoiseGenerator"));
70 // Random number generator for layer_ / module_ / cell
71 rng_.seed(rseed.getSeed("EcalDigiProducer"));
72 // Setting up the read-out chip
73 hgcroc_->seedGenerator(rseed.getSeed("EcalDigiProducer::HgcrocEmulator"));
74 hgcroc_->condition(
76}
std::unique_ptr< ldmx::NoiseGenerator > noise_generator_
Generates noise hits based off of number of cells that are not hit.
std::mt19937 rng_
Generates random numbers for which channels to fill up with noise.
const T & getCondition(const std::string &condition_name)
Access a conditions object for the current event.
static const std::string CONDITIONS_OBJECT_NAME
Conditions object name.

References framework::RandomNumberSeedService::CONDITIONS_OBJECT_NAME, framework::EventProcessor::getCondition(), hgcroc_, noise_generator_, noise_rms_, pedestal_, readout_threshold_, and rng_.

◆ produce()

void ecal::EcalDigiProducer::produce ( framework::Event & event)
overridevirtual

Simulates measurement of pulse and creates digi collection for input event.

HACK ALERT The shifting of the time should not be done this sloppily. In reality, each chip has a set time phase that it samples at (relative to target), so the time shifting should be at the emulator level.

Implements framework::Producer.

Definition at line 78 of file EcalDigiProducer.cxx.

78 {
79 // Empty collection to be filled
81 ecal_digis.setNumSamplesPerDigi(n_adcs_);
83
84 // detector IDs that already have a hit in them
85 std::set<unsigned int> filled_det_i_ds;
86
87 /******************************************************************************************
88 * HGCROC Emulation on Simulated Hits
89 *****************************************************************************************/
90 // std::cout << "Sim Hits" << std::endl;
91 // get simulated ecal hits_ from Geant4
92 // the class EcalHitIO in the SimApplication module_ handles the translation
93 // from G4CalorimeterHits to SimCalorimeterHits this class ensures that only
94 // one SimCalorimeterHit is generated per cell, but multiple "contributions"
95 // are still handled within SimCalorimeterHit
96 auto ecal_sim_hits{event.getCollection<ldmx::SimCalorimeterHit>(
98
99 /* debug printout
100 std::cout << "Energy to Voltage Conversion: " << mev_ << " mV/MeV" <<
101 std::endl;
102 */
103
104 for (auto const& sim_hit : ecal_sim_hits) {
105 std::vector<std::pair<double, double>> pulses_at_chip;
106 for (int i_contrib = 0; i_contrib < sim_hit.getNumberOfContribs();
107 i_contrib++) {
108 /* debug printout
109 std::cout << simHit.getContrib(iContrib).edep << " MeV" << std::endl;
110 */
117 pulses_at_chip.emplace_back(
118 sim_hit.getContrib(i_contrib).edep_ * mev_,
119 sim_hit.getContrib(i_contrib).time_ // global time (t=0ns at target)
120 - sim_hit.getPosition().at(2) /
121 299.702547 // shift light-speed particle traveling along z_
122 );
123 }
124
125 unsigned int hit_id = sim_hit.getID();
126 filled_det_i_ds.insert(hit_id);
127
128 ldmx_log(debug) << " Emulation of hitID = " << hit_id
129 << " with energy = " << sim_hit.getEdep()
130 << " MeV at time = "
131 << sim_hit.getTime() -
132 sim_hit.getPosition().at(2) / 299.702547;
133
134 // container emulator uses to write out samples and
135 // transfer samples into the digi collection
136 std::vector<ldmx::HgcrocDigiCollection::Sample> digi_to_add;
137 if (hgcroc_->digitize(hit_id, pulses_at_chip, digi_to_add)) {
138 ldmx_log(debug) << " --> The HGCROC will read-out this hit!";
139 ecal_digis.addDigi(hit_id, digi_to_add);
140 }
141 }
142
143 /******************************************************************************************
144 * Noise Simulation on Empty Channels
145 *****************************************************************************************/
146 if (noise_) {
147 // put noise into some empty channels
148
149 // geometry constants
150 // These are used in the noise generation so that we can randomly
151 // distribute the noise uniformly throughout the ECal channels.
152 const auto& geom = getCondition<ldmx::EcalGeometry>(
153 ldmx::EcalGeometry::CONDITIONS_OBJECT_NAME);
154 int n_ecal_layers = geom.getNumLayers();
155 int n_modules_per_layer = geom.getNumModulesPerLayer();
156 int n_cells_per_module = geom.getNumCellsPerModule();
157 int num_empty_channels =
158 n_ecal_layers * n_modules_per_layer * n_cells_per_module -
159 ecal_digis.getNumDigis();
160
161 // Uniform distributions for integer generation
162 std::uniform_int_distribution<int> layer_dist(0, n_ecal_layers - 1);
163 std::uniform_int_distribution<int> module_dist(0, n_modules_per_layer - 1);
164 std::uniform_int_distribution<int> cell_dist(0, n_cells_per_module - 1);
165
166 if (zero_suppression_) {
167 // noise generator gives us a list of noise amplitudes [mV] that randomly
168 // populate the empty channels and are above the readout threshold
169 auto noise_hit_amplitudes{
170 noise_generator_->generateNoiseHits(num_empty_channels)};
171 std::vector<std::pair<double, double>> fake_pulse(1, {0., 0.});
172 for (double noise_hit : noise_hit_amplitudes) {
173 // generate detector ID for noise hit
174 // making sure that it is in an empty channel
175 unsigned int noise_id;
176 do {
177 int layer_id = layer_dist(rng_);
178 int module_id = module_dist(rng_);
179 int cell_id = cell_dist(rng_);
180 auto det_id = ldmx::EcalID(layer_id, module_id, cell_id);
181 noise_id = det_id.raw();
182 } while (filled_det_i_ds.find(noise_id) != filled_det_i_ds.end());
183 filled_det_i_ds.insert(noise_id);
184
185 // noise generator gives the amplitude above the readout threshold
186 // we need to convert it to the amplitude above the pedestal
187 noise_hit +=
188 hgcroc_->gain(noise_id) *
189 (hgcroc_->readoutThreshold(noise_id) - hgcroc_->pedestal(noise_id));
190
191 // create a digi as put it into the collection
192 ecal_digis.addDigi(noise_id, hgcroc_->noiseDigi(noise_id, noise_hit));
193 } // loop over noise amplitudes
194 } else {
195 // no zero suppression, put some noise emulation in **all** empty channels
196 // loop through all channels
197 for (int layer{0}; layer < n_ecal_layers; layer++) {
198 for (int module{0}; module < n_modules_per_layer; module++) {
199 for (int cell{0}; cell < n_cells_per_module; cell++) {
200 unsigned int channel{ldmx::EcalID(layer, module, cell).raw()};
201 // check if channel already has a (real) hit in it
202 if (filled_det_i_ds.find(channel) != filled_det_i_ds.end())
203 continue;
204 // create a digi as put it into the collection
205 ecal_digis.addDigi(channel, hgcroc_->noiseDigi(channel));
206 } // cells in each module_
207 } // modules in each layer_
208 } // layers in ECal
209 } // yes or no zero suppression
210 } // if we should do the noise
211
212 event.add(digi_coll_name_, ecal_digis);
213
214 return;
215} // produce
RawValue raw() const
Definition DetectorID.h:69
Extension of DetectorID providing access to ECal layers and cell numbers in a hex grid.
Definition EcalID.h:20
Represents a collection of the digi hits readout by an HGCROC.
void setNumSamplesPerDigi(unsigned int n)
Set number of samples for each digi.
void setSampleOfInterestIndex(unsigned int n)
Set index of sample of interest.
void addDigi(unsigned int id, const std::vector< Sample > &digi)
Add samples to collection.
unsigned int getNumDigis() const
Get total number of digis.
Stores simulated calorimeter hit information.

References ldmx::HgcrocDigiCollection::addDigi(), framework::EventProcessor::getCondition(), ldmx::HgcrocDigiCollection::getNumDigis(), hgcroc_, i_soi_, input_coll_name_, input_pass_name_, mev_, n_adcs_, noise_, noise_generator_, ldmx::DetectorID::raw(), rng_, ldmx::HgcrocDigiCollection::setNumSamplesPerDigi(), ldmx::HgcrocDigiCollection::setSampleOfInterestIndex(), and zero_suppression_.

Member Data Documentation

◆ clock_cycle_

double ecal::EcalDigiProducer::clock_cycle_
private

Time interval for chip clock in ns.

Definition at line 77 of file EcalDigiProducer.h.

Referenced by configure().

◆ digi_coll_name_

std::string ecal::EcalDigiProducer::digi_coll_name_
private

output hit collection name

Definition at line 74 of file EcalDigiProducer.h.

Referenced by configure().

◆ hgcroc_

std::unique_ptr<ldmx::HgcrocEmulator> ecal::EcalDigiProducer::hgcroc_
private

Hgcroc Emulator to digitize analog voltage signals.

Definition at line 110 of file EcalDigiProducer.h.

Referenced by configure(), onNewRun(), and produce().

◆ i_soi_

int ecal::EcalDigiProducer::i_soi_
private

Index for the Sample Of Interest in the list of digi samples.

Definition at line 83 of file EcalDigiProducer.h.

Referenced by configure(), and produce().

◆ input_coll_name_

std::string ecal::EcalDigiProducer::input_coll_name_
private

input hit collection name

Definition at line 68 of file EcalDigiProducer.h.

Referenced by configure(), and produce().

◆ input_pass_name_

std::string ecal::EcalDigiProducer::input_pass_name_
private

input pass name

Definition at line 71 of file EcalDigiProducer.h.

Referenced by configure(), and produce().

◆ mev_

double ecal::EcalDigiProducer::mev_
private

Conversion from energy in MeV to voltage in mV.

Definition at line 86 of file EcalDigiProducer.h.

Referenced by configure(), and produce().

◆ n_adcs_

int ecal::EcalDigiProducer::n_adcs_
private

Depth of ADC buffer.

Definition at line 80 of file EcalDigiProducer.h.

Referenced by configure(), and produce().

◆ noise_

bool ecal::EcalDigiProducer::noise_ {true}
private

Put noise into empty channels, not configurable, only helpful in development.

Definition at line 107 of file EcalDigiProducer.h.

107{true};

Referenced by configure(), and produce().

◆ noise_generator_

std::unique_ptr<ldmx::NoiseGenerator> ecal::EcalDigiProducer::noise_generator_
private

Generates noise hits based off of number of cells that are not hit.

Definition at line 123 of file EcalDigiProducer.h.

Referenced by onNewRun(), and produce().

◆ noise_rms_

double ecal::EcalDigiProducer::noise_rms_
private

Noise RMS.

Definition at line 120 of file EcalDigiProducer.h.

Referenced by configure(), and onNewRun().

◆ ns_

double ecal::EcalDigiProducer::ns_
private

Conversion from time in ns to ticks of the internal clock.

Definition at line 113 of file EcalDigiProducer.h.

Referenced by configure().

◆ pedestal_

double ecal::EcalDigiProducer::pedestal_
private

Read out pedestal.

Definition at line 118 of file EcalDigiProducer.h.

Referenced by configure(), and onNewRun().

◆ readout_threshold_

double ecal::EcalDigiProducer::readout_threshold_
private

Read out threshold.

Definition at line 116 of file EcalDigiProducer.h.

Referenced by configure(), and onNewRun().

◆ rng_

std::mt19937 ecal::EcalDigiProducer::rng_
private

Generates random numbers for which channels to fill up with noise.

Definition at line 126 of file EcalDigiProducer.h.

Referenced by onNewRun(), and produce().

◆ zero_suppression_

bool ecal::EcalDigiProducer::zero_suppression_
private

When emulating noise in empty channels, do we zero suppress?

There are two ways to emulate the noise in the chip: 1) (with zero suppression) Use the NoiseGenerator to get a list of amplitudes (about 3-5 on avg) and put those noise hits which are above the readout threshold in random empty channels. 2) (without zero suppresion) Go through all channels and put noise in each channel that doesn't have a real hit in it. This will mean many channels with have a DIGI below readout threshold.

Definition at line 100 of file EcalDigiProducer.h.

Referenced by configure(), and produce().


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