Project
Loading...
Searching...
No Matches
Digitizer.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13
14#include <TGeoManager.h>
15#include <TRandom.h>
16
17#include <fairlogger/Logger.h>
19
20#include "DataFormatsTRD/Hit.h"
21
22#include "TRDBase/Geometry.h"
24#include "TRDBase/PadPlane.h"
25#include "TRDBase/PadResponse.h"
27
28#include <cmath>
29
30#ifdef WITH_OPENMP
31#include <omp.h>
32#endif
33
34using namespace o2::trd;
35using namespace o2::trd::constants;
36using namespace o2::math_utils;
37
38// init method for late initialization
40{
41 mGeo = Geometry::instance();
42 mGeo->createClusterMatrixArray(); // Requiered for chamberInGeometry()
43
44 mSimParam.cacheMagField();
45
46 // obtain the number of threads from configuration
47#ifdef WITH_OPENMP
48 int askedthreads = TRDSimParams::Instance().digithreads;
49 int maxthreads = omp_get_max_threads();
50 if (askedthreads < 0) {
51 mNumThreads = maxthreads;
52 } else {
53 mNumThreads = std::min(maxthreads, askedthreads);
54 }
55 LOG(info) << "TRD: Digitizing with " << mNumThreads << " threads ";
56#endif
57
58 // initialize structures that we need per thread
59 mGausRandomRings.resize(mNumThreads);
60 mFlatRandomRings.resize(mNumThreads);
61 mLogRandomRings.resize(mNumThreads);
62 for (int i = 0; i < mNumThreads; ++i) {
63 mGausRandomRings[i].initialize(RandomRing<>::RandomType::Gaus);
64 mFlatRandomRings[i].initialize(RandomRing<>::RandomType::Flat);
65 mLogRandomRings[i].initialize([]() -> float { return std::log(gRandom->Rndm()); });
66 mDriftEstimators.emplace_back(mSimParam.getGasMixture(), mSimParam.getCachedField());
67 }
68
69 setSimulationParameters();
70}
71
72void Digitizer::setSimulationParameters()
73{
74 mNpad = mSimParam.getNumberOfPadsInPadResponse(); // Number of pads included in the pad response
75 if (mSimParam.trfOn()) {
76 mTimeBinTRFend = ((int)(mSimParam.getTRFhi() * mSimParam.getSamplingFrequency())) - 1;
77 }
78 mMaxTimeBins = TIMEBINS; // for signals, usually set at 30 tb = 3 microseconds
79 mMaxTimeBinsTRAP = TIMEBINS; // for adcs; should be read from the CCDB or the TRAP config
80 mSamplingRate = mSimParam.getSamplingFrequency();
81 mElAttachProp = mSimParam.getElAttachProp() / 100;
82}
83
85{
86 if (mPileupSignals.size() > 0) {
87 // Add the signals, all chambers are keept in the same signal container
88 SignalContainer smc = addSignalsFromPileup();
89 if (smc.size() > 0) {
90 bool status = convertSignalsToADC(smc, digits);
91 if (!status) {
92 LOG(warn) << "TRD conversion of signals to digits failed";
93 }
94 dumpLabels(smc, labels);
95 }
96 } else {
97 // since we don't have any pileup signals just flush the signals for each chamber
98 // we avoid flattening the array<map, ndets> to a single map
99 for (auto& smc : mSignalsMapCollection) {
100 bool status = convertSignalsToADC(smc, digits);
101 if (!status) {
102 LOG(warn) << "TRD conversion of signals to digits failed";
103 }
104 dumpLabels(smc, labels);
105 }
106 }
107 clearContainers();
108}
109
111{
112 for (const auto& iter : smc) {
113 if (iter.second.isDigit) {
114 labels.addElements(labels.getIndexedSize(), iter.second.labels);
115 if (iter.second.isShared) {
116 labels.addElements(labels.getIndexedSize(), iter.second.labels); // shared digit is a copy of the previous one, need to add the same labels again
117 }
118 }
119 }
120}
121
122SignalContainer Digitizer::addSignalsFromPileup()
123{
124 return pileupTool.addSignals(mPileupSignals, mCurrentTriggerTime);
125}
126
128{
129 mPileupSignals.push_back(mSignalsMapCollection);
130 clearContainers();
131}
132
133void Digitizer::clearContainers()
134{
135 for (auto& sm : mSignalsMapCollection) {
136 sm.clear();
137 }
138}
139
140void Digitizer::process(std::vector<Hit> const& hits)
141{
142 if (!mCalib) {
143 LOG(fatal) << "TRD Calibration database not available";
144 }
145
146 // Get the a hit container for all the hits in a given detector then call convertHits for a given detector (0 - 539)
147 std::array<std::vector<Hit>, MAXCHAMBER> hitsPerDetector;
148 getHitContainerPerDetector(hits, hitsPerDetector);
149
150#ifdef WITH_OPENMP
151// Loop over all TRD detectors (in a parallel fashion)
152#pragma omp parallel for schedule(dynamic) num_threads(mNumThreads)
153#endif
154 for (int det = 0; det < MAXCHAMBER; ++det) {
155#ifdef WITH_OPENMP
156 const int threadid = omp_get_thread_num();
157#else
158 const int threadid = 0;
159#endif
160 auto& signalsMap = mSignalsMapCollection[det];
161 // Jump to the next detector if the detector is
162 // switched off, not installed, etc
163 if (mCalib->getChamberStatus()->isNoData(det)) {
164 continue;
165 }
166 if (!mGeo->chamberInGeometry(det)) {
167 continue;
168 }
169
170 // Go to the next detector if there are no hits
171 if (hitsPerDetector[det].size() == 0) {
172 continue;
173 }
174
175 if (!convertHits(det, hitsPerDetector[det], signalsMap, threadid)) {
176 LOG(warn) << "TRD conversion of hits failed for detector " << det;
177 continue; // go to the next chamber
178 }
179 }
180}
181
182void Digitizer::getHitContainerPerDetector(const std::vector<Hit>& hits, std::array<std::vector<Hit>, MAXCHAMBER>& hitsPerDetector)
183{
184 //
185 // Fill an array of size MAXCHAMBER (540)
186 // The i-element of the array contains the hit collection for the i-detector
187 // To be called once, before doing the loop over all detectors and process the hits
188 //
189 for (const auto& hit : hits) {
190 hitsPerDetector[hit.GetDetectorID()].push_back(hit);
191 }
192}
193
194bool Digitizer::convertHits(const int det, const std::vector<Hit>& hits, SignalContainer& signalMapCont, int thread)
195{
196 //
197 // Convert the detector-wise sorted hits to detector signals
198 //
199
200 double padSignal[mNpad];
201
202 const double calExBDetValue = mCalib->getExB(det); // T * V/cm (check units)
203 const PadPlane* padPlane = mGeo->getPadPlane(det);
204 const int layer = mGeo->getLayer(det);
205 const float rowEndROC = padPlane->getRowEndROC();
206 const float row0 = padPlane->getRow0ROC();
207 const int nColMax = padPlane->getNcols();
208
209 // Loop over hits
210 for (const auto& hit : hits) {
211 const int qTotal = hit.GetCharge();
212 /*
213 Now the real local coordinate system of the ROC
214 column direction: locC
215 row direction: locR
216 time direction: locT
217 locR and locC are identical to the coordinates of the corresponding
218 volumina of the drift or amplification region.
219 locT is defined relative to the wire plane (i.e. middle of amplification
220 region), meaning locT = 0, and is negative for hits coming from the
221 drift region.
222 */
223 double locC = hit.getLocalC(); // col direction in amplification or drift volume
224 double locR = hit.getLocalR(); // row direction in amplification or drift volume
225 double locT = hit.getLocalT(); // time direction in amplification or drift volume
226 const double driftLength = -1 * locT; // The drift length in cm without diffusion
227 // Patch to take care of TR photons that are absorbed
228 // outside the chamber volume. A real fix would actually need
229 // a more clever implementation of the TR hit generation
230 if (qTotal < 0) {
231 if ((locR < rowEndROC) || (locR > row0)) {
232 continue;
233 }
234 if ((driftLength < DrMin) || (driftLength > DrMax)) {
235 continue;
236 }
237 }
238
239 int rowE = padPlane->getPadRowNumberROC(locR);
240 if (rowE < 0) {
241 continue;
242 }
243
244 double rowOffset = padPlane->getPadRowOffsetROC(rowE, locR);
245 double offsetTilt = padPlane->getTiltOffset(rowE, rowOffset);
246 int colE = padPlane->getPadColNumber(locC + offsetTilt);
247 if (colE < 0) {
248 continue;
249 }
250
251 double absDriftLength = std::fabs(driftLength); // Normalized drift length
252 if (mSimParam.isExBOn()) {
253 absDriftLength /= std::sqrt(1 / (1 + calExBDetValue * calExBDetValue));
254 }
255
256 float driftVelocity = mCalib->getVDrift(det, colE, rowE); // The drift velocity
257 float t0 = mCalib->getT0(det, colE, rowE); // The T0 velocity
258
259 // Loop over all created electrons
260 const int nElectrons = std::fabs(qTotal);
261 for (int el = 0; el < nElectrons; ++el) {
262 // Electron attachment
263 if (mSimParam.elAttachOn()) {
264 if (mFlatRandomRings[thread].getNextValue() < absDriftLength * mElAttachProp) {
265 continue;
266 }
267 }
268 // scoped diffused coordinates for each electron
269 double locRd{locR}, locCd{locC}, locTd{locT};
270
271 // Apply diffusion smearing
272 if (mSimParam.diffusionOn()) {
273 if (!diffusion(driftVelocity, absDriftLength, calExBDetValue, locR, locC, locT, locRd, locCd, locTd, thread)) {
274 continue;
275 }
276 }
277
278 // Apply E x B effects
279 if (mSimParam.isExBOn()) {
280 locCd = locCd + calExBDetValue * driftLength;
281 }
282 // The electron position after diffusion and ExB in pad coordinates.
283 rowE = padPlane->getPadRowNumberROC(locRd);
284 if (rowE < 0) {
285 continue;
286 }
287 rowOffset = padPlane->getPadRowOffsetROC(rowE, locRd);
288 // The pad column (rphi-direction)
289 offsetTilt = padPlane->getTiltOffset(rowE, rowOffset);
290 colE = padPlane->getPadColNumber(locCd + offsetTilt);
291 if (colE < 0) {
292 continue;
293 }
294 const double colOffset = padPlane->getPadColOffset(colE, locCd + offsetTilt);
295 driftVelocity = mCalib->getVDrift(det, colE, rowE); // The drift velocity for the updated col and row
296 t0 = mCalib->getT0(det, colE, rowE); // The T0 velocity for the updated col and row
297 // Convert the position to drift time [mus], using either constant drift velocity or
298 // time structure of drift cells (non-isochronity, GARFIELD calculation).
299 // Also add absolute time of hits to take pile-up events into account properly
300 double driftTime;
301 if (mSimParam.timeStructOn()) {
302 // Get z-position with respect to anode wire
303 double zz = row0 - locRd + padPlane->getAnodeWireOffset();
304 zz -= ((int)(2 * zz)) * 0.5;
305 if (zz > 0.25) {
306 zz = 0.5 - zz;
307 }
308 // Use drift time map (GARFIELD)
309 driftTime = mDriftEstimators[thread].timeStruct(driftVelocity, 0.5 * AmWidth - 1.0 * locTd, zz, &(mFlagVdriftOutOfRange[det])) + hit.GetTime();
310 } else {
311 // Use constant drift velocity
312 driftTime = std::fabs(locTd) / driftVelocity + hit.GetTime(); // drift time in microseconds
313 }
314
315 // Apply the gas gain including fluctuations
316 const double signal = -(mSimParam.getGasGain()) * mLogRandomRings[thread].getNextValue();
317
318 // Apply the pad response
319 if (mSimParam.prfOn()) {
320 // The distance of the electron to the center of the pad in units of pad width
321 double dist = (colOffset - 0.5 * padPlane->getColSize(colE)) / padPlane->getColSize(colE);
322 // ********************************************************************************
323 // This is a fixed parametrization, i.e. not dependent on calibration values !
324 // ********************************************************************************
325 if (!(mPRF.getPRF(signal, dist, layer, padSignal))) {
326 continue;
327 }
328 } else {
329 padSignal[0] = 0;
330 padSignal[1] = signal;
331 padSignal[2] = 0;
332 }
333
334 // The time bin (always positive), with t0 distortion
335 double timeBinIdeal = driftTime * mSamplingRate + t0;
336 // Protection
337 if (std::fabs(timeBinIdeal) > (2 * mMaxTimeBins)) { // OS: why 2*mMaxTimeBins?
338 timeBinIdeal = 2 * mMaxTimeBins;
339 }
340 int timeBinTruncated = ((int)timeBinIdeal);
341 // The distance of the position to the middle of the timebin
342 double timeOffset = ((float)timeBinTruncated + 0.5 - timeBinIdeal) / mSamplingRate;
343 // Sample the time response inside the drift region + additional time bins before and after.
344 // The sampling is done always in the middle of the time bin
345 const int firstTimeBin = std::max(timeBinTruncated, 0);
346 const int lastTimeBin = std::min(timeBinTruncated + mTimeBinTRFend, mMaxTimeBins);
347
348 // loop over pads first then over timebins for better cache friendliness
349 // and less access to signalMapCont
350 for (int pad = 0; pad < mNpad; ++pad) {
351 int colPos = colE + pad - 1;
352 if (colPos < 0) {
353 continue;
354 }
355 if (colPos >= nColMax) {
356 break;
357 }
358
359 const int key = calculateKey(det, rowE, colPos);
360 auto& currentSignalData = signalMapCont[key]; // Get the old signal or make a new one if it doesn't exist
361 auto& currentSignal = currentSignalData.signals;
362 auto& trackIds = currentSignalData.trackIds;
363 auto& labels = currentSignalData.labels;
364 currentSignalData.firstTBtime = mTime;
365 addLabel(hit.GetTrackID(), labels, trackIds); // add a label record only if needed
366
367 // add signal with crosstalk for the non-central pads only
368 if (colPos != colE) {
369 for (int tb = firstTimeBin; tb < lastTimeBin; ++tb) {
370 const double t = (tb - timeBinTruncated) / mSamplingRate + timeOffset;
371 const double timeResponse = mSimParam.trfOn() ? mSimParam.timeResponse(t) : 1;
372 const double crossTalk = mSimParam.ctOn() ? mSimParam.crossTalk(t) : 0;
373 currentSignal[tb] += padSignal[pad] * (timeResponse + crossTalk);
374 } // end of loop time bins
375 } else {
376 for (int tb = firstTimeBin; tb < lastTimeBin; ++tb) {
377 const double t = (tb - timeBinTruncated) / mSamplingRate + timeOffset;
378 const double timeResponse = mSimParam.trfOn() ? mSimParam.timeResponse(t) : 1;
379 currentSignal[tb] += padSignal[pad] * timeResponse;
380 } // end of loop time bins
381 }
382 } // end of loop over pads
383 } // end of loop over electrons
384 } // end of loop over hits
385 return true;
386}
387
388void Digitizer::addLabel(const int& trackId, std::vector<o2::MCCompLabel>& labels, std::unordered_set<int>& trackIds)
389{
390 if (trackIds.count(trackId) == 0) {
391 trackIds.insert(trackId);
392 MCLabel label(trackId, getEventID(), getSrcID());
393 labels.push_back(label);
394 }
395}
396
397float drawGaus(o2::math_utils::RandomRing<>& normaldistRing, float mu, float sigma)
398{
399 // this is using standard normally distributed random numbers and rescaling to make
400 // them gaussian distributed with general mu and sigma
401 return mu + sigma * normaldistRing.getNextValue();
402}
403
404bool Digitizer::convertSignalsToADC(SignalContainer& signalMapCont, DigitContainer& digits, int thread)
405{
406 //
407 // Converts the sampled electron signals to ADC values for a given chamber
408 //
409
410 constexpr double kEl2fC = 1.602e-19 * 1.0e15; // Converts number of electrons to fC
411 double coupling = mSimParam.getPadCoupling() * mSimParam.getTimeCoupling(); // Coupling factor
412 double convert = kEl2fC * mSimParam.getChipGain(); // Electronics conversion factor
413 double adcConvert = mSimParam.getADCoutRange() / mSimParam.getADCinRange(); // ADC conversion factor
414 double baseline = mSimParam.getADCbaseline() / adcConvert; // The electronics baseline in mV
415 double baselineEl = baseline / convert; // The electronics baseline in electrons
416
417 for (auto& signalMapIter : signalMapCont) {
418 const auto key = signalMapIter.first;
419 const int det = getDetectorFromKey(key);
420 const int row = getRowFromKey(key);
421 const int col = getColFromKey(key);
422 // halfchamber masking
423 int mcm = (int)(col / 18); // current group of 18 col pads
424 int halfchamberside = (mcm > 3) ? 1 : 0; // 0=Aside, 1=Bside
425
426 // Halfchambers that are switched off, masked by mCalib
427 if ((halfchamberside == 0 && mCalib->getChamberStatus()->isNoDataSideA(det)) ||
428 (halfchamberside == 1 && mCalib->getChamberStatus()->isNoDataSideB(det))) {
429 continue;
430 }
431
432 // Check whether pad is masked
433 // Bridged pads are not considered yet!!!
434 if (mCalib->getPadStatus()->isMasked(det, col, row) || mCalib->getPadStatus()->isNotConnected(det, col, row)) {
435 continue;
436 }
437
438 float padgain = mCalib->getPadGainFactor(det, row, col); // The gain factor
439 if (padgain <= 0) {
440 LOG(fatal) << "Not a valid gain " << padgain << ", " << det << ", " << col << ", " << row;
441 }
442
443 signalMapIter.second.isDigit = true; // flag the signal as digit
444 // Loop over the all timebins in the ADC array
445 const auto& signalArray = signalMapIter.second.signals;
446 ArrayADC adcs{};
447 for (int tb = 0; tb < mMaxTimeBinsTRAP; ++tb) {
448 float signalAmp = (float)signalArray[tb]; // The signal amplitude
449 signalAmp *= coupling; // Pad and time coupling
450 signalAmp *= padgain; // Gain factors
451 // Add the noise, starting from minus ADC baseline in electrons
452 signalAmp = std::max((double)drawGaus(mGausRandomRings[thread], signalAmp, mSimParam.getNoise()), -baselineEl);
453 signalAmp *= convert; // Convert to mV
454 signalAmp += baseline; // Add ADC baseline in mV
455 // Convert to ADC counts
456 // Set the overflow-bit fADCoutRange if the signal is larger than fADCinRange
457 ADC_t adc = 0;
458 if (signalAmp >= mSimParam.getADCinRange()) {
459 adc = ((ADC_t)mSimParam.getADCoutRange());
460 } else {
461 adc = std::lround(signalAmp * adcConvert);
462 }
463 // update the adc array value
464 adcs[tb] = adc;
465 } // loop over timebins
466 // Convert the map to digits here, and push them to the container
467 digits.emplace_back(det, row, col, adcs);
468 if (mCreateSharedDigits) {
469 auto digit = digits.back();
470 if ((digit.getChannel() == 2) && !((digit.getROB() % 2 != 0) && (digit.getMCM() % NMCMROBINCOL == 3))) {
471 // shared left, if not leftmost MCM of left ROB of chamber
472 int robShared = (digit.getMCM() % NMCMROBINCOL == 3) ? digit.getROB() + 1 : digit.getROB(); // for the leftmost MCM on a ROB the shared digit is added to the neighbouring ROB
473 int mcmShared = (robShared == digit.getROB()) ? digit.getMCM() + 1 : digit.getMCM() - 3;
474 digits.emplace_back(det, robShared, mcmShared, NADCMCM - 1, adcs);
475 signalMapIter.second.isShared = true;
476 } else if ((digit.getChannel() == 18 || digit.getChannel() == 19) && !((digit.getROB() % 2 == 0) && (digit.getMCM() % NMCMROBINCOL == 0))) {
477 // shared right, if not rightmost MCM of right ROB of chamber
478 int robShared = (digit.getMCM() % NMCMROBINCOL == 0) ? digit.getROB() - 1 : digit.getROB(); // for the rightmost MCM on a ROB the shared digit is added to the neighbouring ROB
479 int mcmShared = (robShared == digit.getROB()) ? digit.getMCM() - 1 : digit.getMCM() + 3;
480 digits.emplace_back(det, robShared, mcmShared, digit.getChannel() - NCOLMCM, adcs);
481 signalMapIter.second.isShared = true;
482 }
483 }
484 } // loop over digits
485 return true;
486}
487
488bool Digitizer::diffusion(float vdrift, float absdriftlength, float exbvalue,
489 float lRow0, float lCol0, float lTime0,
490 double& lRow, double& lCol, double& lTime, int thread)
491{
492 //
493 // Applies the diffusion smearing to the position of a single electron.
494 // Depends on absolute drift length.
495 //
496 float diffL = 0.0;
497 float diffT = 0.0;
498 if (mDriftEstimators[thread].getDiffCoeff(diffL, diffT, vdrift)) {
499 float driftSqrt = std::sqrt(absdriftlength);
500 float sigmaT = driftSqrt * diffT;
501 float sigmaL = driftSqrt * diffL;
502 lRow = drawGaus(mGausRandomRings[thread], lRow0, sigmaT);
503 if (mSimParam.isExBOn()) {
504 const float exbfactor = 1.f / (1.f + exbvalue * exbvalue);
505 lCol = drawGaus(mGausRandomRings[thread], lCol0, sigmaT * exbfactor);
506 lTime = drawGaus(mGausRandomRings[thread], lTime0, sigmaL * exbfactor);
507 } else {
508 lCol = drawGaus(mGausRandomRings[thread], lCol0, sigmaT);
509 lTime = drawGaus(mGausRandomRings[thread], lTime0, sigmaL);
510 }
511 return true;
512 } else {
513 return false;
514 }
515}
516
518{
519 std::string retVal = "";
520 for (int iDet = 0; iDet < MAXCHAMBER; ++iDet) {
521 if (mFlagVdriftOutOfRange[iDet]) {
522 retVal += std::to_string(iDet);
523 retVal += ", ";
524 }
525 }
526 if (!retVal.empty()) {
527 retVal.erase(retVal.size() - 2);
528 }
529 return retVal;
530}
uint16_t mcm
Definition of the GeometryManager class.
int32_t i
int32_t retVal
uint32_t col
Definition RawData.h:4
float drawGaus(o2::math_utils::RandomRing<> &normaldistRing, float mu, float sigma)
StringRef key
A container to hold and manage MC truth information/labels.
void addElements(uint32_t dataindex, gsl::span< CompatibleLabel > elements)
const ChamberStatus * getChamberStatus() const
float getPadGainFactor(int roc, int col, int row) const
const PadStatus * getPadStatus() const
float getVDrift(int roc, int col, int row) const
float getExB(int roc) const
float getT0(int roc, int col, int row) const
bool isNoDataSideB(int det) const
bool isNoDataSideA(int det) const
bool isNoData(int det) const
void process(std::vector< Hit > const &)
void dumpLabels(const SignalContainer &, o2::dataformats::MCTruthContainer< MCLabel > &)
void flush(DigitContainer &, o2::dataformats::MCTruthContainer< MCLabel > &)
Definition Digitizer.cxx:84
int getSrcID() const
Definition Digitizer.h:68
std::string dumpFlaggedChambers() const
int getEventID() const
Definition Digitizer.h:67
bool createClusterMatrixArray()
static Geometry * instance()
Definition Geometry.h:33
bool chamberInGeometry(int det) const
int getPRF(double, double, int, double *) const
bool isNotConnected(int roc, int col, int row) const
bool isMasked(int roc, int col, int row) const
float getADCoutRange() const
Definition SimParam.h:72
bool timeStructOn() const
Definition SimParam.h:84
float getCachedField() const
Definition SimParam.cxx:47
float getGasGain() const
Definition SimParam.h:69
double timeResponse(double) const
Definition SimParam.cxx:57
float getNoise() const
Definition SimParam.h:70
double crossTalk(double) const
Definition SimParam.cxx:74
bool isExBOn() const
Definition SimParam.h:89
bool trfOn() const
Definition SimParam.h:82
GasMixture getGasMixture() const
Definition SimParam.h:92
float getTRFhi() const
Definition SimParam.h:76
bool ctOn() const
Definition SimParam.h:83
bool diffusionOn() const
Definition SimParam.h:79
bool prfOn() const
Definition SimParam.h:85
float getADCinRange() const
Definition SimParam.h:73
float getPadCoupling() const
Definition SimParam.h:77
int getADCbaseline() const
Definition SimParam.h:74
bool elAttachOn() const
Definition SimParam.h:80
float getTimeCoupling() const
Definition SimParam.h:78
float getElAttachProp() const
Definition SimParam.h:81
float getSamplingFrequency() const
Definition SimParam.h:93
int getNumberOfPadsInPadResponse() const
Definition SimParam.h:86
float getChipGain() const
Definition SimParam.h:71
GLsizeiptr size
Definition glcorearb.h:659
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition glcorearb.h:5034
constexpr int NMCMROBINCOL
the number of MCMs per ROB in column direction
Definition Constants.h:49
constexpr int TIMEBINS
the number of time bins
Definition Constants.h:74
constexpr int NADCMCM
the number of ADC channels per MCM
Definition Constants.h:52
constexpr int NCOLMCM
the number of pads per MCM
Definition Constants.h:53
constexpr int MAXCHAMBER
the maximum number of installed chambers
Definition Constants.h:30
std::uint16_t ADC_t
Definition Digit.h:31
std::unordered_map< int, SignalArray > SignalContainer
Definition Digitizer.h:44
std::vector< Digit > DigitContainer
Definition Digitizer.h:43
std::array< ADC_t, constants::TIMEBINS > ArrayADC
Definition Digit.h:32
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
SignalContainer addSignals(std::deque< std::array< SignalContainer, constants::MAXCHAMBER > > &, const double &)
int digithreads
number of digitizer threads
std::vector< uint64_t > convert(gsl::span< const uint64_t > page)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Digit > digits
std::vector< int > row
ArrayADC adc