2#include "Tools/HgcrocEmulator.h"
9 noise_ = ps.getParameter<
bool>(
"noise");
15 timePeak_ = ps.getParameter<
double>(
"timePeak");
16 clockCycle_ = ps.getParameter<
double>(
"clockCycle");
17 nADCs_ = ps.getParameter<
int>(
"nADCs");
18 iSOI_ = ps.getParameter<
int>(
"iSOI");
29 "[0]*((1.0+exp([1]*(-[2]+[3])))*(1.0+exp([5]*(-[6]+[3]))))/"
30 "((1.0+exp([1]*(x-[2]+[3]-[4])))*(1.0+exp([5]*(x-[6]+[3]-[4]))))",
47 std::vector<std::pair<double, double>> &arriving_pulses,
48 std::vector<ldmx::HgcrocDigiCollection::Sample> &digiToAdd)
const {
54 double padCapacitance =
getCondition(channelID,
"PAD_CAPACITANCE");
57 double toaThreshold =
getCondition(channelID,
"TOA_THRESHOLD");
58 double totThreshold =
getCondition(channelID,
"TOT_THRESHOLD");
63 double drainRate =
getCondition(channelID,
"DRAIN_RATE");
70 arriving_pulses.begin(), arriving_pulses.end(),
71 [](
const std::pair<double, double> &a,
72 const std::pair<double, double> &b) { return a.first > b.first; });
87 for (
int iADC = 0; iADC <
nADCs_; iADC++) {
89 ldmx_log(trace) <<
" iADC = " << iADC <<
" at startBX = " << startBX;
93 bool startTOT =
false;
97 for (
auto hit : pulse.
hits()) {
104 double vpeak = pulse(hit.second);
106 if (vpeak > totThreshold) {
109 if (toverTOT < hit.second) {
110 toverTOT = hit.second;
114 if (vpeak > toaThreshold) {
115 if (!overTOA || hit.second < toverTOA) toverTOA = hit.second;
122 if (!overTOA && pulse(startBX +
clockCycle_) > toaThreshold) {
123 if (pulse(startBX) < toaThreshold) {
137 double charge_deposited =
149 double tot = charge_deposited / drainRate;
150 ldmx_log(trace) <<
" we are in TOT read-out mode, TOT = " << tot;
155 int tdc_counts = int(tot * 4096 / totMax) +
pedestal;
162 toa = digiToAdd.back().toa();
165 double timecross = pulse.
findCrossing(startBX, toverTOT, toaThreshold);
166 toa = int((timecross - startBX) *
ns_);
168 if (toa == 0) toa = 1;
169 if (toa > 1023) toa = 1023;
171 ldmx_log(trace) <<
" Adding TOT hit with toa = " << toa
172 <<
", tdc_counts = " << tdc_counts
173 <<
" adc_t at prev iADC = "
174 << digiToAdd.at(iADC - 1).adc_t();
176 auto adc_at_tminus1 =
177 (iADC > 0) ? digiToAdd.at(iADC - 1).adc_t() :
pedestal;
178 auto i_tot_sample = digiToAdd.size();
180 digiToAdd.emplace_back(
false,
true, adc_at_tminus1, tdc_counts, toa);
184 ldmx_log(trace) <<
" Adding further hits with ADC [t-1] = 0x3FF, toa = "
185 "0x3FF, until digiToAdd.size() = "
186 << digiToAdd.size() <<
" < nADCs_(" <<
nADCs_ <<
")";
187 while (digiToAdd.size() <
nADCs_) {
189 digiToAdd.emplace_back(
true,
false, 0x3FF, 0x3FF, 0);
192 return (i_tot_sample <=
iSOI_ + 1);
199 int adc = bxvolts /
gain;
200 ldmx_log(trace) <<
" we are in ADC read-out mode, adc = " << adc;
201 if (adc < 0) adc = 0;
202 if (adc > 1023) adc = 1023;
206 if (pulse(startBX) < toaThreshold && overTOA) {
207 double timecross = pulse.
findCrossing(startBX, toverTOA, toaThreshold);
208 toa = int((timecross - startBX) *
ns_);
210 if (toa == 0) toa = 1;
211 if (toa > 1023) toa = 1023;
218 (iADC > 0) ? digiToAdd.at(iADC - 1).adc_t() :
pedestal;
220 digiToAdd.emplace_back(
false,
false, adc_t_minus1, adc, toa);
226 ldmx_log(trace) <<
" we are adding the hit IFF iSOI= " <<
iSOI_
227 <<
"'s adc_t = " << digiToAdd.at(
iSOI_).adc_t()
233 const int &channel,
const double &soi_amplitude)
const {
238 std::vector<ldmx::HgcrocDigiCollection::Sample> noise_digi;
239 for (
int iADC{0}; iADC <
nADCs_; iADC++) {
242 int adc_tm1{
static_cast<int>(
pedestal)};
244 adc_tm1 = noise_digi.at(iADC - 1).adc_t();
251 if (iADC ==
iSOI_) adc_t += soi_amplitude /
gain;
255 noise_digi.emplace_back(
false,
false, adc_tm1, adc_t, 0);
Class encapsulating parameters for configuring a processor.
const std::vector< std::pair< double, double > > & hits() const
Get list of individual pulses that are entering the chip.
double findCrossing(double low, double high, double level, double prec=0.01)
Find the time at which we cross the input level.
void addOrMerge(const std::pair< double, double > &hit, double hit_merge_ns)
Put another hit into this composite pulse.
double readoutThreshold(const int &id) const
Readout Threshold (ADC Counts)
double rateUpSlope_
Rate of Up Slope in Pulse Shape [1/ns].
void seedGenerator(uint64_t seed)
Seed the emulator for random number generation.
double noise(const int &channelID) const
Get random noise amplitdue for input channel [mV].
double pedestal(const int &id) const
Pedestal [ADC Counts] for input channel.
double getCondition(int id, const std::string &name) const
Get condition for input chip ID, condition name, and default value.
double hit_merge_ns_
Hit merging time [ns].
double timeUpSlope_
Time of Up Slope relative to Pulse Shape Fit [ns].
double timePeak_
Time of Peak relative to pulse shape fit [ns].
int iSOI_
Index for the Sample Of Interest in the list of digi samples.
bool digitize(const int &channelID, std::vector< std::pair< double, double > > &arriving_pulses, std::vector< ldmx::HgcrocDigiCollection::Sample > &digiToAdd) const
Digitize the signals from the simulated hits.
std::unique_ptr< TRandom3 > noiseInjector_
Generates Gaussian noise on top of real hits.
double gain(const int &channelID) const
Gain for input channel.
double timingJitter_
Jitter of timing mechanism in the chip [ns].
int nADCs_
Depth of ADC buffer.
bool noise_
Put noise in channels, only configure to false if testing.
double timeDnSlope_
Time of Down Slope relative to Pulse Shape Fit [ns].
TF1 pulseFunc_
Functional shape of signal pulse in time.
double clockCycle_
Time interval for chip clock [ns].
std::vector< ldmx::HgcrocDigiCollection::Sample > noiseDigi(const int &channel, const double &soi_amplitude=0) const
Generate a digi of pure noise.
double rateDnSlope_
Rate of Down Slope in Pulse Shape [1/ns].
HgcrocEmulator(const framework::config::Parameters &ps)
Constructor.
double ns_
Conversion from time [ns] to counts.