LDMX Software
hcal::HcalDigiProducer Class Reference

Performs basic HCal digitization. More...

#include <HcalDigiProducer.h>

Public Member Functions

 HcalDigiProducer (const std::string &name, framework::Process &process)
 Constructor Makes unique noise generator and injector for this class.
 
virtual ~HcalDigiProducer ()=default
 Default destructor.
 
void configure (framework::config::Parameters &) override
 Configure this producer from the python configuration.
 
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
 Random number 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
 
std::string pulse_truth_coll_name_
 output pulse truth collection name
 
double clock_cycle_
 Time interval for chip clock in ns.
 
int n_ad_cs_
 Depth of ADC buffer.
 
int i_soi_
 Index for the Sample Of Interest in the list of digi samples.
 
double me_v_
 Conversion from energy in MeV to voltage in mV.
 
double attlength_
 Strip attenuation length [m].
 
bool noise_ {true}
 Put noise into empty channels, not configurable, only helpful in development.
 
bool save_pulse_truth_info_ {false}
 If true, save the "analog" composite pulse shape in the HGCROC emulator before it gets digitized.
 
bool zero_suppression_ {true}
 If false, save digis from all channels, even pure noise in empty bars Helpful when comparing with test beam data.
 
std::unique_ptr< ldmx::HgcrocEmulatorhgcroc_
 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 gain_
 Read out gain.
 
double noise_rms_
 Noise RMS.
 
std::unique_ptr< ldmx::NoiseGeneratornoise_generator_
 Generates noise hits based off of number of cells that are not hit.
 
std::mt19937 rng_
 Generates Gaussian noise on top of real hits_.
 

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

Performs basic HCal digitization.

Definition at line 32 of file HcalDigiProducer.h.

Constructor & Destructor Documentation

◆ HcalDigiProducer()

hcal::HcalDigiProducer::HcalDigiProducer ( const std::string & name,
framework::Process & process )

Constructor Makes unique noise generator and injector for this class.

Definition at line 14 of file HcalDigiProducer.cxx.

16 : Producer(name, process) {
17 /*
18 * Noise generator by default uses a Gausian model for noise
19 * i.e. It assumes the noise is distributed around a mean (setPedestal)
20 * with a certain RMS (setNoise) and then calculates
21 * how many hits_ should be generated for a given number of empty
22 * channels and a minimum readout value (setNoiseThreshold)
23 */
24 noise_generator_ = std::make_unique<ldmx::NoiseGenerator>();
25}
Producer(const std::string &name, Process &process)
Class constructor.
virtual void process(Event &event) final
Processing an event for a Producer is calling produce.
std::unique_ptr< ldmx::NoiseGenerator > noise_generator_
Generates noise hits based off of number of cells that are not hit.

References noise_generator_.

Member Function Documentation

◆ configure()

void hcal::HcalDigiProducer::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 27 of file HcalDigiProducer.cxx.

27 {
28 // settings of readout chip
29 // used in actual digitization
30 auto hgcroc_params = ps.get<framework::config::Parameters>("hgcroc");
31 hgcroc_ = std::make_unique<ldmx::HgcrocEmulator>(hgcroc_params);
32 clock_cycle_ = hgcroc_params.get<double>("clockCycle");
33 n_ad_cs_ = hgcroc_params.get<int>("nADCs");
34 i_soi_ = hgcroc_params.get<int>("iSOI");
35 noise_ = hgcroc_params.get<bool>("noise");
36
37 // If true, ignore readout threshold
38 // and generate pedestal noise digis in every empty channel
39 zero_suppression_ = ps.get<bool>("zeroSuppression");
40
41 // Save full analog pulse shapes from the HGCROC emulation
42 save_pulse_truth_info_ = ps.get<bool>("savePulseTruthInfo");
43
44 // collection names
45 input_coll_name_ = ps.get<std::string>("inputCollName");
46 input_pass_name_ = ps.get<std::string>("inputPassName");
47 digi_coll_name_ = ps.get<std::string>("digiCollName");
48 pulse_truth_coll_name_ = ps.get<std::string>("pulseTruthCollName");
49
50 // physical constants
51 // used to calculate unit conversions
52 me_v_ = ps.get<double>("MeV");
53 attlength_ = ps.get<double>("attenuationLength");
54
55 // Time -> clock counts conversion
56 // time [ns] * ( 2^10 / max time in ns ) = clock counts
57 ns_ = 1024. / clock_cycle_;
58
59 // Configure generator that will produce noise hits_ in empty channels
60 gain_ = ps.get<double>("avgGain");
61 readout_threshold_ = ps.get<double>("avgReadoutThreshold");
62 pedestal_ = ps.get<double>("avgPedestal");
63 noise_rms_ = ps.get<double>("avgNoiseRMS");
64}
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:29
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:78
bool noise_
Put noise into empty channels, not configurable, only helpful in development.
int n_ad_cs_
Depth of ADC buffer.
double gain_
Read out gain.
double attlength_
Strip attenuation length [m].
bool zero_suppression_
If false, save digis from all channels, even pure noise in empty bars Helpful when comparing with tes...
std::string pulse_truth_coll_name_
output pulse truth collection name
std::string digi_coll_name_
output hit collection name
double me_v_
Conversion from energy in MeV to voltage in mV.
double ns_
Conversion from time in ns to ticks of the internal clock.
double noise_rms_
Noise RMS.
std::unique_ptr< ldmx::HgcrocEmulator > hgcroc_
Hgcroc Emulator to digitize analog voltage signals.
std::string input_coll_name_
input hit collection name
double readout_threshold_
Read out threshold.
double clock_cycle_
Time interval for chip clock in ns.
std::string input_pass_name_
input pass name
bool save_pulse_truth_info_
If true, save the "analog" composite pulse shape in the HGCROC emulator before it gets digitized.
int i_soi_
Index for the Sample Of Interest in the list of digi samples.
double pedestal_
Read out pedestal.

References attlength_, clock_cycle_, digi_coll_name_, gain_, framework::config::Parameters::get(), hgcroc_, i_soi_, input_coll_name_, input_pass_name_, me_v_, n_ad_cs_, noise_, noise_rms_, ns_, pedestal_, pulse_truth_coll_name_, readout_threshold_, save_pulse_truth_info_, and zero_suppression_.

◆ onNewRun()

void hcal::HcalDigiProducer::onNewRun ( const ldmx::RunHeader & runHeader)
overridevirtual

Random number generation.

Reimplemented from framework::EventProcessor.

Definition at line 66 of file HcalDigiProducer.cxx.

66 {
67 // rms noise in mV
69 // mean noise amplitude (if using Gaussian Model for the noise) in mV
70 noise_generator_->setPedestal(gain_ * pedestal_);
71 // threshold for readout in mV
72 noise_generator_->setNoiseThreshold(gain_ * readout_threshold_);
73
74 // Set up seeds
77 noise_generator_->seedGenerator(
78 rseed.getSeed("HcalDigiProducer::NoiseGenerator"));
79
80 // Random number generator for layer_ / module_ / cell
81 rng_.seed(rseed.getSeed("HcalDigiProducer"));
82 // Setting up the read-out chip
83 hgcroc_->seedGenerator(rseed.getSeed("HcalDigiProducer::HgcrocEmulator"));
84}
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.
std::mt19937 rng_
Generates Gaussian noise on top of real hits_.

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

◆ produce()

void hcal::HcalDigiProducer::produce ( framework::Event & event)
overridevirtual

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

Define two pulses: with positive and negative ends. For this we need to: (1) Find the position along the bar: For back Hcal: x (y) for horizontal (vertical) layers. For side Hcal: x (top,bottom) and y (left,right).

(2) Define the end of the bar: The end of an HcalDigiID is based on its distance (x,y) along the bar.

  • A positive end (endID=0), corresponds to top,left.
  • A negative end (endID=1), corresponds to bottom,right. For back Hcal:
  • if the position along the bar > 0, the close pulse's end is 0, else 1. For side Hcal:
  • if the position along the bar > half_width point of the bar, the close pulse's end is 0, else 1. The far pulse's end will be opposite to the close pulse's end.

(3) Find the distance to each end (positive and negative) from the origin. For the back Hcal, the half point of the bar coincides with the coordinates of the origin. For the side Hcal, the length of the bar from the origin is:

  • 2 *(half_width) - Ecal_dx(y_)/2 away from the positive end, and,
  • Ecal_dx(y_) away from the negative end.

Now we have all the sub-hits_ from all the simhits Digitize: For back Hcal return two digis. For side Hcal we choose which pulse to readout based on the position of the hit and the sub-section. For Top and Left we read the positive end digi. For Bottom and Right we read the negative end digi.

Implements framework::Producer.

Definition at line 86 of file HcalDigiProducer.cxx.

86 {
87 // Get the Hgcroc Conditions
88 hgcroc_->condition(
90
91 // Get the Hcal Geometry
92 const auto& hcal_geometry = getCondition<ldmx::HcalGeometry>(
94
95 // Empty collection to be filled
99
100 std::map<unsigned int, std::vector<const ldmx::SimCalorimeterHit*>>
101 hits_by_id;
102
103 // get simulated hcal hits_ from Geant4 and group them by id
104 auto hcal_sim_hits{event.getCollection<ldmx::SimCalorimeterHit>(
106
107 for (auto const& sim_hit : hcal_sim_hits) {
108 // get ID
109 unsigned int hit_id = sim_hit.getID();
110
111 auto idh = hits_by_id.find(hit_id);
112 if (idh == hits_by_id.end()) {
113 hits_by_id[hit_id] =
114 std::vector<const ldmx::SimCalorimeterHit*>(1, &sim_hit);
115 } else {
116 idh->second.push_back(&sim_hit);
117 }
118 }
119
120 ldmx::HgcrocPulseTruthCollection hcal_pulse_truth_coll;
122 hgcroc_->pulse_truth_coll_ = &hcal_pulse_truth_coll;
123 hgcroc_->save_pulse_truth_info_ = true;
124 }
125
126 /******************************************************************************************
127 * HGCROC Emulation on Simulated Hits (grouped by HcalID)
128 ******************************************************************************************/
129 for (auto const& sim_bar : hits_by_id) {
130 ldmx::HcalID det_id(sim_bar.first);
131 int section = det_id.section();
132 int layer = det_id.layer();
133 int strip = det_id.strip();
134
135 // get position
136 double half_total_width = hcal_geometry.getHalfTotalWidth(section, layer);
137 double ecal_dx = hcal_geometry.getEcalDx();
138 double ecal_dy = hcal_geometry.getEcalDy();
139
140 // contributions
141 std::vector<std::pair<double, double>> pulses_posend;
142 std::vector<std::pair<double, double>> pulses_negend;
143
144 for (auto psim_hit : sim_bar.second) {
145 const ldmx::SimCalorimeterHit& sim_hit = *psim_hit;
146
147 std::vector<float> position = sim_hit.getPosition();
148
177 float distance_along_bar, distance_ecal;
178 float distance_close, distance_far;
179 int end_close;
180 const auto orientation{hcal_geometry.getScintillatorOrientation(det_id)};
181 if (section == ldmx::HcalID::HcalSection::BACK) {
182 distance_along_bar =
183 (orientation ==
184 ldmx::HcalGeometry::ScintillatorOrientation::horizontal)
185 ? position[0]
186 : position[1];
187 end_close = (distance_along_bar > 0) ? 0 : 1;
188 distance_close = half_total_width;
189 distance_far = half_total_width;
190 } else {
191 if ((section == ldmx::HcalID::HcalSection::TOP) ||
192 ((section == ldmx::HcalID::HcalSection::BOTTOM))) {
193 distance_along_bar = position[0];
194 distance_ecal = ecal_dx;
195 } else if ((section == ldmx::HcalID::HcalSection::LEFT) ||
196 (section == ldmx::HcalID::HcalSection::RIGHT)) {
197 distance_along_bar = position[1];
198 distance_ecal = ecal_dy;
199 } else {
200 distance_along_bar = -9999.;
201 EXCEPTION_RAISE(
202 "BadCode",
203 "We should never end up here "
204 "All cases of HCAL considered, end_close is meaningless");
205 }
206 end_close = (distance_along_bar > half_total_width) ? 0 : 1;
207 distance_close = (end_close == 0)
208 ? 2 * half_total_width - distance_ecal / 2
209 : distance_ecal / 2;
210 distance_far = (end_close == 0)
211 ? distance_ecal / 2
212 : 2 * half_total_width - distance_ecal / 2;
213 }
214
215 // Calculate voltage attenuation and time shift for the close and far
216 // pulse.
217 // velocity of light in Polystyrene, n = 1.6 = c/v mm/ns
218 float v = 299.792 / 1.6;
219 double att_close =
220 exp(-1. * ((distance_close - fabs(distance_along_bar)) / 1000.) /
221 attlength_);
222 double att_far =
223 exp(-1. * ((distance_far + fabs(distance_along_bar)) / 1000.) /
224 attlength_);
225 double shift_close =
226 fabs((distance_close - fabs(distance_along_bar)) / v);
227 double shift_far = fabs((distance_far + fabs(distance_along_bar)) / v);
228
229 // Get voltages and times.
230 for (int i_contrib = 0; i_contrib < sim_hit.getNumberOfContribs();
231 i_contrib++) {
232 double voltage = sim_hit.getContrib(i_contrib).edep_ * me_v_;
233 // global time (t=0ns at target)
234 double time = sim_hit.getContrib(i_contrib).time_;
235 // shift light-speed particle traveling along z_
236 time -= position.at(2) / 299.702547;
237
238 if (end_close == 0) {
239 pulses_posend.emplace_back(voltage * att_close, time + shift_close);
240 pulses_negend.emplace_back(voltage * att_far, time + shift_far);
241 } else {
242 pulses_posend.emplace_back(voltage * att_far, time + shift_far);
243 pulses_negend.emplace_back(voltage * att_close, time + shift_close);
244 }
245 }
246 }
247
257 if (section == ldmx::HcalID::HcalSection::BACK) {
258 std::vector<ldmx::HgcrocDigiCollection::Sample> digi_to_add_posend,
259 digi_to_add_negend;
260 ldmx::HcalDigiID posend_id(section, layer, strip, 0);
261 ldmx::HcalDigiID negend_id(section, layer, strip, 1);
262
263 bool pos_end_activity =
264 hgcroc_->digitize(posend_id.raw(), pulses_posend, digi_to_add_posend);
265 bool neg_end_activity =
266 hgcroc_->digitize(negend_id.raw(), pulses_negend, digi_to_add_negend);
267
268 if (pos_end_activity && neg_end_activity && zero_suppression_) {
269 hcal_digis.addDigi(posend_id.raw(), digi_to_add_posend);
270 hcal_digis.addDigi(negend_id.raw(), digi_to_add_negend);
271 } // If zeroSuppression == true, Back Hcal needs to digitize both
272 // pulses or none
273
274 if (!zero_suppression_) {
275 if (pos_end_activity) {
276 hcal_digis.addDigi(posend_id.raw(), digi_to_add_posend);
277 } else {
278 std::vector<ldmx::HgcrocDigiCollection::Sample> digi =
279 hgcroc_->noiseDigi(posend_id.raw(), 0.0);
280 hcal_digis.addDigi(posend_id.raw(), digi);
281 }
282 if (neg_end_activity) {
283 hcal_digis.addDigi(negend_id.raw(), digi_to_add_negend);
284 } else {
285 std::vector<ldmx::HgcrocDigiCollection::Sample> digi =
286 hgcroc_->noiseDigi(negend_id.raw(), 0.0);
287 hcal_digis.addDigi(negend_id.raw(), digi);
288 }
289 }
290
291 } else {
292 bool is_posend = false;
293 std::vector<ldmx::HgcrocDigiCollection::Sample> digi_to_add;
294 if ((section == ldmx::HcalID::HcalSection::TOP) ||
295 (section == ldmx::HcalID::HcalSection::LEFT)) {
296 is_posend = true;
297 } else if ((section == ldmx::HcalID::HcalSection::BOTTOM) ||
298 (section == ldmx::HcalID::HcalSection::RIGHT)) {
299 is_posend = false;
300 }
301 if (is_posend) {
302 ldmx::HcalDigiID digi_id(section, layer, strip, 0);
303 if (hgcroc_->digitize(digi_id.raw(), pulses_posend, digi_to_add)) {
304 hcal_digis.addDigi(digi_id.raw(), digi_to_add);
305 } else if (!zero_suppression_) {
306 std::vector<ldmx::HgcrocDigiCollection::Sample> digi =
307 hgcroc_->noiseDigi(digi_id.raw(), 0.0);
308 hcal_digis.addDigi(digi_id.raw(), digi);
309 }
310 } else {
311 ldmx::HcalDigiID digi_id(section, layer, strip, 1);
312 if (hgcroc_->digitize(digi_id.raw(), pulses_negend, digi_to_add)) {
313 hcal_digis.addDigi(digi_id.raw(), digi_to_add);
314 } else if (!zero_suppression_) {
315 std::vector<ldmx::HgcrocDigiCollection::Sample> digi =
316 hgcroc_->noiseDigi(digi_id.raw(), 0.0);
317 hcal_digis.addDigi(digi_id.raw(), digi);
318 }
319 }
320 }
321 }
322
323 /******************************************************************************************
324 * Noise Simulation on Empty Channels
325 *****************************************************************************************/
326 if (noise_) {
327 std::vector<ldmx::HcalDigiID> channel_map;
328 int num_channels = 0;
329 for (int section = 0; section < hcal_geometry.getNumSections(); section++) {
330 for (int layer = 1; layer <= hcal_geometry.getNumLayers(section);
331 layer++) {
332 // Note zero-indexed strip numbering...
333 for (int strip = 0; strip < hcal_geometry.getNumStrips(section, layer);
334 strip++) {
335 if (section == ldmx::HcalID::HcalSection::BACK) {
336 auto digi_i_dend0 = ldmx::HcalDigiID(section, layer, strip, 0);
337 auto digi_i_dend1 = ldmx::HcalDigiID(section, layer, strip, 1);
338 channel_map.push_back(digi_i_dend0);
339 channel_map.push_back(digi_i_dend1);
340 num_channels += 2;
341 } else {
342 auto digi_id = ldmx::HcalDigiID(section, layer, strip, 0);
343 channel_map.push_back(digi_id);
344 num_channels++;
345 }
346 }
347 }
348 }
349
350 // Uniform distributions for integer generation
351 std::uniform_int_distribution<int> section_dist(
352 0, hcal_geometry.getNumSections() - 1);
353 std::uniform_int_distribution<int> end_dist(0, 1);
354 std::uniform_int_distribution<int> clock_dist(0, clock_cycle_);
355
356 // Fast noise sim
357 if (zero_suppression_) {
358 int num_empty_channels = num_channels - hcal_digis.getNumDigis();
359 // noise generator gives us a list of noise amplitudes [mV] that randomly
360 // populate the empty channels and are above the readout threshold
361 auto noise_hit_amplitudes{
362 noise_generator_->generateNoiseHits(num_empty_channels)};
363 std::vector<std::pair<double, double>> fake_pulse(1, {0., 0.});
364
365 for (double noise_hit : noise_hit_amplitudes) {
366 // generate detector ID for noise hit
367 // making sure that it is in an empty channel
368 unsigned int noise_id;
369 int section_id, layer_id, strip_id, end_id;
370 do {
371 // Get a random section value
372 section_id = section_dist(rng_);
373
374 // Get a random value for the layer_
375 std::uniform_int_distribution<int> layer_dist(
376 0, hcal_geometry.getNumLayers(section_id) - 1);
377 layer_id = layer_dist(rng_);
378 // set layer_ to 1 if the generator says it is 0 (geometry map starts
379 // from 1)
380 if (layer_id == 0) layer_id = 1;
381
382 // Get a random value for the strip
383 std::uniform_int_distribution<int> strips_dist(
384 0, hcal_geometry.getNumStrips(section_id, layer_id) - 1);
385 strip_id = strips_dist(rng_);
386
387 // Get a random value for the end
388 if ((section_id == ldmx::HcalID::HcalSection::TOP) ||
389 (section_id == ldmx::HcalID::HcalSection::LEFT)) {
390 end_id = 0;
391 } else if ((section_id == ldmx::HcalID::HcalSection::BOTTOM) ||
392 (section_id == ldmx::HcalID::HcalSection::RIGHT)) {
393 end_id = 1;
394 } else {
395 end_id = end_dist(rng_);
396 }
397 auto det_id =
398 ldmx::HcalDigiID(section_id, layer_id, strip_id, end_id);
399 noise_id = det_id.raw();
400 } while (hits_by_id.find(noise_id) != hits_by_id.end());
401 hits_by_id[noise_id] =
402 std::vector<const ldmx::SimCalorimeterHit*>(); // mark this as used
403
404 // get a time for this noise hit
405 fake_pulse[0].second = clock_dist(rng_);
406
407 // noise generator gives the amplitude above the readout threshold
408 // we need to convert it to the amplitude above the pedestal
409 double gain = hgcroc_->gain(noise_id);
410 fake_pulse[0].first = noise_hit +
411 gain * hgcroc_->readoutThreshold(noise_id) -
412 gain * hgcroc_->pedestal(noise_id);
413
414 if (section_id == ldmx::HcalID::HcalSection::BACK) {
415 std::vector<ldmx::HgcrocDigiCollection::Sample> digi_to_add_posend,
416 digi_to_add_negend;
417 ldmx::HcalDigiID posend_id(section_id, layer_id, strip_id, 0);
418 ldmx::HcalDigiID negend_id(section_id, layer_id, strip_id, 1);
419 if (hgcroc_->digitize(posend_id.raw(), fake_pulse,
420 digi_to_add_posend) &&
421 hgcroc_->digitize(negend_id.raw(), fake_pulse,
422 digi_to_add_negend)) {
423 hcal_digis.addDigi(posend_id.raw(), digi_to_add_posend);
424 hcal_digis.addDigi(negend_id.raw(), digi_to_add_negend);
425 }
426 } else {
427 std::vector<ldmx::HgcrocDigiCollection::Sample> digi_to_add;
428 if (hgcroc_->digitize(noise_id, fake_pulse, digi_to_add)) {
429 hcal_digis.addDigi(noise_id, digi_to_add);
430 }
431 }
432 } // loop over noise amplitudes
433 } else { // If zero_suppression_ == false, add noise digis for all bars
434 // without simhits
435 for (auto digi_id : channel_map) {
436 // Convert from digi ID to det ID (since simhits don't know about
437 // different ends of the bar)
438 ldmx::HcalID detid(digi_id.section(), digi_id.layer(), digi_id.strip());
439 unsigned int rawdet_id = detid.raw();
440 if (hits_by_id.find(rawdet_id) == hits_by_id.end()) {
441 std::vector<ldmx::HgcrocDigiCollection::Sample> digi =
442 hgcroc_->noiseDigi(digi_id.raw(), 0.0);
443 hcal_digis.addDigi(digi_id.raw(), digi);
444 }
445 }
446 }
447 } // if we should add noise
448
449 event.add(digi_coll_name_, hcal_digis);
451 event.add(pulse_truth_coll_name_, hcal_pulse_truth_coll);
452
453 return;
454} // produce
Extension of HcalAbstractID providing access to HCal digi information.
Definition HcalDigiID.h:13
static constexpr const char * CONDITIONS_OBJECT_NAME
Conditions object: The name of the python configuration calling this class (Hcal/python/HcalGeometry....
Implements detector ids for HCal subdetector.
Definition HcalID.h:19
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.
unsigned getNumberOfContribs() const
Get the number of hit contributions.
std::vector< float > getPosition() const
Get the XYZ position of the hit [mm].
Contrib getContrib(int i) const
Get a hit contribution by index_.
float time_
Time this contributor made the hit (global Geant4 time)
float edep_
Energy depostied by this contributor.

References ldmx::HgcrocDigiCollection::addDigi(), attlength_, clock_cycle_, ldmx::HcalGeometry::CONDITIONS_OBJECT_NAME, digi_coll_name_, ldmx::SimCalorimeterHit::Contrib::edep_, framework::EventProcessor::getCondition(), ldmx::SimCalorimeterHit::getContrib(), ldmx::SimCalorimeterHit::getNumberOfContribs(), ldmx::HgcrocDigiCollection::getNumDigis(), ldmx::SimCalorimeterHit::getPosition(), hgcroc_, i_soi_, input_coll_name_, input_pass_name_, ldmx::HcalID::layer(), me_v_, n_ad_cs_, noise_, noise_generator_, pulse_truth_coll_name_, ldmx::DetectorID::raw(), rng_, save_pulse_truth_info_, ldmx::HgcrocDigiCollection::setNumSamplesPerDigi(), ldmx::HgcrocDigiCollection::setSampleOfInterestIndex(), ldmx::HcalID::strip(), ldmx::SimCalorimeterHit::Contrib::time_, and zero_suppression_.

Member Data Documentation

◆ attlength_

double hcal::HcalDigiProducer::attlength_
private

Strip attenuation length [m].

Definition at line 89 of file HcalDigiProducer.h.

Referenced by configure(), and produce().

◆ clock_cycle_

double hcal::HcalDigiProducer::clock_cycle_
private

Time interval for chip clock in ns.

Definition at line 77 of file HcalDigiProducer.h.

Referenced by configure(), and produce().

◆ digi_coll_name_

std::string hcal::HcalDigiProducer::digi_coll_name_
private

output hit collection name

Definition at line 71 of file HcalDigiProducer.h.

Referenced by configure(), and produce().

◆ gain_

double hcal::HcalDigiProducer::gain_
private

Read out gain.

Definition at line 117 of file HcalDigiProducer.h.

Referenced by configure(), and onNewRun().

◆ hgcroc_

std::unique_ptr<ldmx::HgcrocEmulator> hcal::HcalDigiProducer::hgcroc_
private

Hgcroc Emulator to digitize analog voltage signals.

Definition at line 107 of file HcalDigiProducer.h.

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

◆ i_soi_

int hcal::HcalDigiProducer::i_soi_
private

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

Definition at line 83 of file HcalDigiProducer.h.

Referenced by configure(), and produce().

◆ input_coll_name_

std::string hcal::HcalDigiProducer::input_coll_name_
private

input hit collection name

Definition at line 65 of file HcalDigiProducer.h.

Referenced by configure(), and produce().

◆ input_pass_name_

std::string hcal::HcalDigiProducer::input_pass_name_
private

input pass name

Definition at line 68 of file HcalDigiProducer.h.

Referenced by configure(), and produce().

◆ me_v_

double hcal::HcalDigiProducer::me_v_
private

Conversion from energy in MeV to voltage in mV.

Definition at line 86 of file HcalDigiProducer.h.

Referenced by configure(), and produce().

◆ n_ad_cs_

int hcal::HcalDigiProducer::n_ad_cs_
private

Depth of ADC buffer.

Definition at line 80 of file HcalDigiProducer.h.

Referenced by configure(), and produce().

◆ noise_

bool hcal::HcalDigiProducer::noise_ {true}
private

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

Definition at line 96 of file HcalDigiProducer.h.

96{true};

Referenced by configure(), and produce().

◆ noise_generator_

std::unique_ptr<ldmx::NoiseGenerator> hcal::HcalDigiProducer::noise_generator_
private

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

Definition at line 122 of file HcalDigiProducer.h.

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

◆ noise_rms_

double hcal::HcalDigiProducer::noise_rms_
private

Noise RMS.

Definition at line 119 of file HcalDigiProducer.h.

Referenced by configure(), and onNewRun().

◆ ns_

double hcal::HcalDigiProducer::ns_
private

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

Definition at line 110 of file HcalDigiProducer.h.

Referenced by configure().

◆ pedestal_

double hcal::HcalDigiProducer::pedestal_
private

Read out pedestal.

Definition at line 115 of file HcalDigiProducer.h.

Referenced by configure(), and onNewRun().

◆ pulse_truth_coll_name_

std::string hcal::HcalDigiProducer::pulse_truth_coll_name_
private

output pulse truth collection name

Definition at line 74 of file HcalDigiProducer.h.

Referenced by configure(), and produce().

◆ readout_threshold_

double hcal::HcalDigiProducer::readout_threshold_
private

Read out threshold.

Definition at line 113 of file HcalDigiProducer.h.

Referenced by configure(), and onNewRun().

◆ rng_

std::mt19937 hcal::HcalDigiProducer::rng_
private

Generates Gaussian noise on top of real hits_.

Definition at line 125 of file HcalDigiProducer.h.

Referenced by onNewRun(), and produce().

◆ save_pulse_truth_info_

bool hcal::HcalDigiProducer::save_pulse_truth_info_ {false}
private

If true, save the "analog" composite pulse shape in the HGCROC emulator before it gets digitized.

Definition at line 100 of file HcalDigiProducer.h.

100{false};

Referenced by configure(), and produce().

◆ zero_suppression_

bool hcal::HcalDigiProducer::zero_suppression_ {true}
private

If false, save digis from all channels, even pure noise in empty bars Helpful when comparing with test beam data.

Definition at line 104 of file HcalDigiProducer.h.

104{true};

Referenced by configure(), and produce().


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