LDMX Software
TrigScintQIEDigiProducer.cxx
2
3#include <iostream>
4
5#include "Framework/Exception/Exception.h"
6#include "Framework/Logger.h"
8
9namespace trigscint {
10
11TrigScintQIEDigiProducer::TrigScintQIEDigiProducer(const std::string& name,
12 framework::Process& process)
13 : Producer(name, process) {}
14
15void TrigScintQIEDigiProducer::configure(
17 // Configure this instance of the producer
18 stripsPerArray_ = parameters.getParameter<int>("number_of_strips");
19 numberOfArrays_ = parameters.getParameter<int>("number_of_arrays");
20 meanNoise_ = parameters.getParameter<double>("mean_noise");
21 mevPerMip_ = parameters.getParameter<double>("mev_per_mip");
22 pePerMip_ = parameters.getParameter<double>("pe_per_mip");
23 inputCollection_ = parameters.getParameter<std::string>("input_collection");
24 inputPassName_ = parameters.getParameter<std::string>("input_pass_name");
25 outputCollection_ = parameters.getParameter<std::string>("output_collection");
26 verbose_ = parameters.getParameter<bool>("verbose");
27
28 // QIE specific parameters initialization
29 maxts_ = parameters.getParameter<int>("maxts");
30 toff_overall_ = parameters.getParameter<double>("toff_overall");
31 input_pulse_shape_ =
32 parameters.getParameter<std::string>("input_pulse_shape");
33 tdc_thr_ = parameters.getParameter<double>("tdc_thr");
34 pedestal_ = parameters.getParameter<double>("pedestal");
35 elec_noise_ = parameters.getParameter<double>("elec_noise");
36 sipm_gain_ = parameters.getParameter<double>("sipm_gain");
37 s_freq_ = parameters.getParameter<double>("qie_sf");
38 zeroSuppCut_ = parameters.getParameter<double>("zeroSupp_in_pe");
39
40 if (input_pulse_shape_ == "Expo") {
41 pulse_params_.clear();
42 pulse_params_.push_back(parameters.getParameter<double>("expo_k"));
43 pulse_params_.push_back(parameters.getParameter<double>("expo_tmax"));
44
45 ldmx_log(debug) << "expo_k =" << pulse_params_[0];
46 ldmx_log(debug) << "expo_tmax =" << pulse_params_[1];
47 }
48
49 // Debug mode: print parameter values.
50 ldmx_log(debug) << "maxts_ =" << maxts_;
51 ldmx_log(debug) << "toff_overall_ =" << toff_overall_;
52 ldmx_log(debug) << "input_pulse_shape_ =" << input_pulse_shape_;
53 ldmx_log(debug) << "tdc_thr =" << tdc_thr_;
54 ldmx_log(debug) << "pedestal =" << pedestal_;
55 ldmx_log(debug) << "elec_noise =" << elec_noise_;
56 ldmx_log(debug) << "sipm_gain =" << sipm_gain_;
57 ldmx_log(debug) << "qie_sf =" << s_freq_;
58 ldmx_log(debug) << "zeroSupp_in_pe =" << zeroSuppCut_;
59 ldmx_log(debug) << "pe_per_mip =" << pePerMip_;
60 ldmx_log(debug) << "mev_per_mip =" << mevPerMip_;
61}
62
63void TrigScintQIEDigiProducer::produce(framework::Event& event) {
64 // Need to handle seeding on the first event
65 if (random_.get() == nullptr) {
66 const auto& rseed = getCondition<framework::RandomNumberSeedService>(
68 const auto& rseed2 = getCondition<framework::RandomNumberSeedService>(
70
71 random_ = std::make_unique<TRandom3>(rseed.getSeed(outputCollection_));
72
73 // Initialize SimQIE instance with
74 // pedestal, electronic noise and the random seed
75 smq_ = new SimQIE(pedestal_, elec_noise_,
76 rseed2.getSeed(outputCollection_ + "SimQIE"));
77
78 smq_->setGain(sipm_gain_);
79 smq_->setFreq(s_freq_);
80 smq_->setNTimeSamples(maxts_);
81 smq_->setTDCThreshold(tdc_thr_);
82 }
83
84 // To simulate multiple pulses coming at different times, SiPMS
85 // Initialize with stripsPerArray_ zeros
86 std::vector<float> TrueEdep(stripsPerArray_, 0.);
87
88 // Initialize with stripsPerArray_ nullptrs
89 std::vector<Expo*> ex(stripsPerArray_, nullptr);
90 for (int i = 0; i < stripsPerArray_; i++) {
91 // Set the pulse shape with fixed parameters given by config. file
92 ex[i] = new Expo(pulse_params_[0], pulse_params_[1]);
93 TrueEdep[i] = 0;
94 }
95
96 // loop over sim hits and aggregate energy depositions for each detID
97 const auto simHits{event.getCollection<ldmx::SimCalorimeterHit>(
98 inputCollection_, inputPassName_)};
99
100 for (const auto& simHit : simHits) {
101 ldmx::TrigScintID id(simHit.getID());
102
103 ldmx_log(debug) << "Processing sim hit with bar ID: " << id.bar();
104
105 // Simulating the noise corresponding to uncertainity in
106 // detecting scintillating photons.
107 // Poissonian distribution with mean = mean PEs generated
108 double PulseAmp =
109 random_->Poisson(simHit.getEdep() / mevPerMip_ * pePerMip_);
110
111 // Adding a pulse for every sim hit recorded.
112 // time offset = global offset+simhit time
113 ex[id.bar()]->AddPulse(toff_overall_ + simHit.getTime(), PulseAmp);
114
115 // incrementing true energy deposited in appropriate bar.
116 TrueEdep[id.bar()] += simHit.getEdep();
117 }
118
119 // A container to hold the digitized trigger scintillator hits.
120 std::vector<trigscint::TrigScintQIEDigis> QDigis;
121
122 double TotalNoise = meanNoise_ * maxts_;
123
124 // time period[ns] = 1000/sampling freq.[MHz]
125 double SamplingTime = 1000 / s_freq_;
126
127 // Loop over all the bars available.
128 for (int bar_id = 0; bar_id < stripsPerArray_; bar_id++) {
129 // Dark current simulation
130 // e-hole pairs may be generated at random times in SiPM
131 // due to thermal fluctuations.
132 // Every e- thus generated, mimicks a Photo Electron.
133 // Hence we will creat 1PE pulses for each electron generated.
134 int n_noise_pulses = random_->Poisson(TotalNoise);
135 for (int i = 0; i < n_noise_pulses; i++) {
136 ex[bar_id]->AddPulse(random_->Uniform(0, maxts_ * SamplingTime), 1);
137 }
138
139 // Storing the "good" digis
140 if (smq_->PulseCut(ex[bar_id], zeroSuppCut_)) {
142
143 QIEInfo.setChanID(bar_id);
144 QIEInfo.setADC(smq_->Out_ADC(ex[bar_id]));
145 QIEInfo.setTDC(smq_->Out_TDC(ex[bar_id]));
146 QIEInfo.setCID(smq_->CapID(ex[bar_id]));
147
148 QDigis.push_back(QIEInfo);
149 }
150 }
151 event.add(outputCollection_, QDigis);
152}
153
154} // namespace trigscint
155
156DECLARE_PRODUCER_NS(trigscint, TrigScintQIEDigiProducer);
#define DECLARE_PRODUCER_NS(NS, CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Conditions object for random number seeds.
Class that simulates QIE chip of the trigger scintillator.
Implements an event buffer system for storing event data.
Definition Event.h:41
Class which represents the process under execution.
Definition Process.h:36
static const std::string CONDITIONS_OBJECT_NAME
Conditions object name.
Class encapsulating parameters for configuring a processor.
Definition Parameters.h:27
T getParameter(const std::string &name) const
Retrieve the parameter of the given name.
Definition Parameters.h:89
Stores simulated calorimeter hit information.
Class that defines the detector ID of the trigger scintillator.
Definition TrigScintID.h:14
piece-wise exponential pulse, modelled as an output of a capacitor
class for simulating QIE chip output
Definition SimQIE.h:17
class for storing QIE output
void setCID(const std::vector< int > cid)
Store cids of all time samples.
void setTDC(const std::vector< int > tdc)
Store tdcs of all time samples.
void setChanID(const int chanid)
Store the channel ID.
void setADC(const std::vector< int > adc)
Store adcs of all time samples.