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
14
19#include "MathUtils/Cartesian.h"
22
23#include <TRandom.h>
24#include <climits>
25#include <vector>
26#include <numeric>
27#include <fairlogger/Logger.h> // for LOG
28
30using o2::itsmft::Hit;
32
33using namespace o2::itsmft;
34// using namespace o2::base;
35
36//_______________________________________________________________________
38{
39 mNumberOfChips = mGeometry->getNumberOfChips();
40 mChips.resize(mNumberOfChips);
41 for (int i = mNumberOfChips; i--;) {
42 mChips[i].setChipIndex(i);
43 if (mNoiseMap) {
44 mChips[i].setNoiseMap(mNoiseMap);
45 }
46 if (mDeadChanMap) {
47 mChips[i].disable(mDeadChanMap->isFullChipMasked(i));
48 mChips[i].setDeadChanMap(mDeadChanMap);
49 }
50 }
51 // initializing for both collection tables
52 /*for (int i = 0; i < 2; i++) {
53 mAlpSimResp[i].initData(i);
54 }*/
55
56 // importing the charge collection tables
57 // (initialized while building O2)
58 auto file = TFile::Open(mResponseFile.data());
59 if (!file) {
60 LOG(fatal) << "Cannot open response file " << mResponseFile;
61 }
62 /*std::string response = "response";
63 for (int i=0; i<2; i++) {
64 response.append(std::to_string(i));
65 mAlpSimResp[i] = *(o2::itsmft::AlpideSimResponse*)file->Get(response.data());
66 }*/
67 mAlpSimResp[0] = *(o2::itsmft::AlpideSimResponse*)file->Get("response0");
68 mAlpSimResp[1] = *(o2::itsmft::AlpideSimResponse*)file->Get("response1");
69
70 // importing the parameters from DPLDigitizerParam.h
73
74 // initializing response according to detector and back-bias value
75 if (doptMFT.Vbb == 0.0) { // for MFT
76 mAlpSimRespMFT = mAlpSimResp;
77 LOG(info) << "Choosing Vbb=0V for MFT";
78 } else if (doptMFT.Vbb == 3.0) {
79 mAlpSimRespMFT = mAlpSimResp + 1;
80 LOG(info) << "Choosing Vbb=-3V for MFT";
81 } else {
82 LOG(fatal) << "Invalid MFT back-bias value";
83 }
84
85 if (doptITS.IBVbb == 0.0) { // for ITS Inner Barrel
86 mAlpSimRespIB = mAlpSimResp;
87 LOG(info) << "Choosing Vbb=0V for ITS IB";
88 } else if (doptITS.IBVbb == 3.0) {
89 mAlpSimRespIB = mAlpSimResp + 1;
90 LOG(info) << "Choosing Vbb=-3V for ITS IB";
91 } else {
92 LOG(fatal) << "Invalid ITS Inner Barrel back-bias value";
93 }
94 if (doptITS.OBVbb == 0.0) { // for ITS Outter Barrel
95 mAlpSimRespOB = mAlpSimResp;
96 LOG(info) << "Choosing Vbb=0V for ITS OB";
97 } else if (doptITS.OBVbb == 3.0) {
98 mAlpSimRespOB = mAlpSimResp + 1;
99 LOG(info) << "Choosing Vbb=-3V for ITS OB";
100 } else {
101 LOG(fatal) << "Invalid ITS Outter Barrel back-bias value";
102 }
103 mParams.print();
104 mIRFirstSampledTF = o2::raw::HBFUtils::Instance().getFirstSampledTFIR();
105
106 //
107 LOG(info) << "First IR sampled in digitization is: " << mIRFirstSampledTF;
108 LOG(info) << "First IR ns " << mIRFirstSampledTF.bc2ns();
109}
110
112{
113 if (mNumberOfChips < 10000) { // in MFT
114 return mAlpSimRespMFT;
115 }
116
117 if (chipID < 432) { // in ITS Inner Barrel
118 return mAlpSimRespIB;
119 } else { // in ITS Outter Barrel
120 return mAlpSimRespOB;
121 }
122}
123
124//_______________________________________________________________________
125void Digitizer::process(const std::vector<Hit>* hits, int evID, int srcID)
126{
127 // digitize single event, the time must have been set beforehand
128
129 LOG(info) << "Digitizing " << mGeometry->getName() << " hits of entry " << evID << " from source "
130 << srcID << " at time " << mEventTime << " ROFrame= " << mNewROFrame << ")"
131 << " cont.mode: " << isContinuous()
132 << " Min/Max ROFrames " << mROFrameMin << "/" << mROFrameMax;
133
134 // is there something to flush ?
135 if (mNewROFrame > mROFrameMin) {
136 fillOutputContainer(mNewROFrame - 1); // flush out all frame preceding the new one
137 }
138
139 int nHits = hits->size();
140 std::vector<int> hitIdx(nHits);
141 std::iota(std::begin(hitIdx), std::end(hitIdx), 0);
142 // sort hits to improve memory access
143 std::sort(hitIdx.begin(), hitIdx.end(),
144 [hits](auto lhs, auto rhs) {
145 return (*hits)[lhs].GetDetectorID() < (*hits)[rhs].GetDetectorID();
146 });
147 for (int i : hitIdx) {
148 processHit((*hits)[i], mROFrameMax, evID, srcID);
149 }
150 // in the triggered mode store digits after every MC event
151 // TODO: in the real triggered mode this will not be needed, this is actually for the
152 // single event processing only
153 if (!mParams.isContinuous()) {
154 fillOutputContainer(mROFrameMax);
155 }
156}
157
158//_______________________________________________________________________
160{
161 // assign event time in ns
162 mEventTime = irt;
163 if (!mParams.isContinuous()) {
164 mROFrameMin = 0; // in triggered mode reset the frame counters
165 mROFrameMax = 0;
166 }
167 // RO frame corresponding to provided time
168 mCollisionTimeWrtROF = mEventTime.timeInBCNS; // in triggered mode the ROF starts at BC (is there a delay?)
169 if (mParams.isContinuous()) {
170 auto nbc = mEventTime.differenceInBC(mIRFirstSampledTF);
171 if (mCollisionTimeWrtROF < 0 && nbc > 0) {
172 nbc--;
173 }
174
175 // we might get interactions to digitize from before
176 // the first sampled IR
177 if (nbc < 0) {
178 mNewROFrame = 0;
179 // this event is before the first RO
180 mIsBeforeFirstRO = true;
181 } else {
182 mNewROFrame = nbc / mParams.getROFrameLengthInBC();
183 mIsBeforeFirstRO = false;
184 }
185 LOG(info) << " NewROFrame " << mNewROFrame << " nbc " << nbc;
186
187 // in continuous mode depends on starts of periodic readout frame
188 mCollisionTimeWrtROF += (nbc % mParams.getROFrameLengthInBC()) * o2::constants::lhc::LHCBunchSpacingNS;
189 } else {
190 mNewROFrame = 0;
191 }
192
193 if (mNewROFrame < mROFrameMin) {
194 LOG(error) << "New ROFrame " << mNewROFrame << " (" << irt << ") precedes currently cashed " << mROFrameMin;
195 throw std::runtime_error("deduced ROFrame precedes already processed one");
196 }
197
198 if (mParams.isContinuous() && mROFrameMax < mNewROFrame) {
199 mROFrameMax = mNewROFrame - 1; // all frames up to this are finished
200 }
201}
202
203//_______________________________________________________________________
204void Digitizer::fillOutputContainer(uint32_t frameLast)
205{
206 // fill output with digits from min.cached up to requested frame, generating the noise beforehand
207 if (frameLast > mROFrameMax) {
208 frameLast = mROFrameMax;
209 }
210 // make sure all buffers for extra digits are created up to the maxFrame
211 getExtraDigBuffer(mROFrameMax);
212
213 LOG(info) << "Filling " << mGeometry->getName() << " digits output for RO frames " << mROFrameMin << ":"
214 << frameLast;
215
217
218 // we have to write chips in RO increasing order, therefore have to loop over the frames here
219 for (; mROFrameMin <= frameLast; mROFrameMin++) {
220 rcROF.setROFrame(mROFrameMin);
221 rcROF.setFirstEntry(mDigits->size()); // start of current ROF in digits
222
223 auto& extra = *(mExtraBuff.front().get());
224 for (auto& chip : mChips) {
225 if (chip.isDisabled()) {
226 continue;
227 }
228 chip.addNoise(mROFrameMin, mROFrameMin, &mParams);
229 auto& buffer = chip.getPreDigits();
230 if (buffer.empty()) {
231 continue;
232 }
233 auto itBeg = buffer.begin();
234 auto iter = itBeg;
235 ULong64_t maxKey = chip.getOrderingKey(mROFrameMin + 1, 0, 0) - 1; // fetch digits with key below that
236 for (; iter != buffer.end(); ++iter) {
237 if (iter->first > maxKey) {
238 break; // is the digit ROFrame from the key > the max requested frame
239 }
240 auto& preDig = iter->second; // preDigit
241 if (preDig.charge >= mParams.getChargeThreshold()) {
242 int digID = mDigits->size();
243 mDigits->emplace_back(chip.getChipIndex(), preDig.row, preDig.col, preDig.charge);
244 mMCLabels->addElement(digID, preDig.labelRef.label);
245 auto& nextRef = preDig.labelRef; // extra contributors are in extra array
246 while (nextRef.next >= 0) {
247 nextRef = extra[nextRef.next];
248 mMCLabels->addElement(digID, nextRef.label);
249 }
250 }
251 }
252 buffer.erase(itBeg, iter);
253 }
254 // finalize ROF record
255 rcROF.setNEntries(mDigits->size() - rcROF.getFirstEntry()); // number of digits
256 if (isContinuous()) {
257 rcROF.getBCData().setFromLong(mIRFirstSampledTF.toLong() + mROFrameMin * mParams.getROFrameLengthInBC());
258 } else {
259 rcROF.getBCData() = mEventTime; // RSTODO do we need to add trigger delay?
260 }
261 if (mROFRecords) {
262 mROFRecords->push_back(rcROF);
263 }
264 extra.clear(); // clear container for extra digits of the mROFrameMin ROFrame
265 // and move it as a new slot in the end
266 mExtraBuff.emplace_back(mExtraBuff.front().release());
267 mExtraBuff.pop_front();
268 }
269}
270
271//_______________________________________________________________________
272void Digitizer::processHit(const o2::itsmft::Hit& hit, uint32_t& maxFr, int evID, int srcID)
273{
274 // convert single hit to digits
275 int chipID = hit.GetDetectorID();
276 auto& chip = mChips[chipID];
277 if (chip.isDisabled()) {
278 LOG(debug) << "skip disabled chip " << chipID;
279 return;
280 }
281 float timeInROF = hit.GetTime() * sec2ns;
282 if (timeInROF > 20e3) {
283 const int maxWarn = 10;
284 static int warnNo = 0;
285 if (warnNo < maxWarn) {
286 LOG(warning) << "Ignoring hit with time_in_event = " << timeInROF << " ns"
287 << ((++warnNo < maxWarn) ? "" : " (suppressing further warnings)");
288 }
289 return;
290 }
291 if (isContinuous()) {
292 timeInROF += mCollisionTimeWrtROF;
293 }
294 if (mIsBeforeFirstRO && timeInROF < 0) {
295 // disregard this hit because it comes from an event before readout starts and it does not effect this RO
296 return;
297 }
298
299 // calculate RO Frame for this hit
300 if (timeInROF < 0) {
301 timeInROF = 0.;
302 }
303 float tTot = mParams.getSignalShape().getMaxDuration();
304 // frame of the hit signal start wrt event ROFrame
305 int roFrameRel = int(timeInROF * mParams.getROFrameLengthInv());
306 // frame of the hit signal end wrt event ROFrame: in the triggered mode we read just 1 frame
307 uint32_t roFrameRelMax = mParams.isContinuous() ? (timeInROF + tTot) * mParams.getROFrameLengthInv() : roFrameRel;
308 int nFrames = roFrameRelMax + 1 - roFrameRel;
309 uint32_t roFrameMax = mNewROFrame + roFrameRelMax;
310 if (roFrameMax > maxFr) {
311 maxFr = roFrameMax; // if signal extends beyond current maxFrame, increase the latter
312 }
313
314 // here we start stepping in the depth of the sensor to generate charge diffusion
315 float nStepsInv = mParams.getNSimStepsInv();
316 int nSteps = mParams.getNSimSteps();
317 const auto& matrix = mGeometry->getMatrixL2G(hit.GetDetectorID());
318 math_utils::Vector3D<float> xyzLocS(matrix ^ (hit.GetPosStart())); // start position in sensor frame
319 math_utils::Vector3D<float> xyzLocE(matrix ^ (hit.GetPos())); // end position in sensor frame
320
322 step -= xyzLocS;
323 step *= nStepsInv; // position increment at each step
324 // the electrons will injected in the middle of each step
325 math_utils::Vector3D<float> stepH(step * 0.5);
326 xyzLocS += stepH;
327 xyzLocE -= stepH;
328
329 int rowS = -1, colS = -1, rowE = -1, colE = -1, nSkip = 0;
330 // get entrance pixel row and col
331 while (!Segmentation::localToDetector(xyzLocS.X(), xyzLocS.Z(), rowS, colS)) { // guard-ring ?
332 if (++nSkip >= nSteps) {
333 return; // did not enter to sensitive matrix
334 }
335 xyzLocS += step;
336 }
337 // get exit pixel row and col
338 while (!Segmentation::localToDetector(xyzLocE.X(), xyzLocE.Z(), rowE, colE)) { // guard-ring ?
339 if (++nSkip >= nSteps) {
340 return; // did not enter to sensitive matrix
341 }
342 xyzLocE -= step;
343 }
344 // estimate the limiting min/max row and col where the non-0 response is possible
345 if (rowS > rowE) {
346 std::swap(rowS, rowE);
347 }
348 if (colS > colE) {
349 std::swap(colS, colE);
350 }
351 rowS -= AlpideRespSimMat::NPix / 2;
352 rowE += AlpideRespSimMat::NPix / 2;
353 if (rowS < 0) {
354 rowS = 0;
355 }
356 if (rowE >= Segmentation::NRows) {
357 rowE = Segmentation::NRows - 1;
358 }
359 colS -= AlpideRespSimMat::NPix / 2;
360 colE += AlpideRespSimMat::NPix / 2;
361 if (colS < 0) {
362 colS = 0;
363 }
364 if (colE >= Segmentation::NCols) {
365 colE = Segmentation::NCols - 1;
366 }
367 int rowSpan = rowE - rowS + 1, colSpan = colE - colS + 1; // size of plaquet where some response is expected
368
369 float respMatrix[rowSpan][colSpan]; // response accumulated here
370 std::fill(&respMatrix[0][0], &respMatrix[0][0] + rowSpan * colSpan, 0.f);
371
372 float nElectrons = hit.GetEnergyLoss() * mParams.getEnergyToNElectrons(); // total number of deposited electrons
373 nElectrons *= nStepsInv; // N electrons injected per step
374 if (nSkip) {
375 nSteps -= nSkip;
376 }
377 //
378 int rowPrev = -1, colPrev = -1, row, col;
379 float cRowPix = 0.f, cColPix = 0.f; // local coordinated of the current pixel center
380
382
383 // take into account that the AlpideSimResponse depth defintion has different min/max boundaries
384 // although the max should coincide with the surface of the epitaxial layer, which in the chip
385 // local coordinates has Y = +SensorLayerThickness/2
386
387 xyzLocS.SetY(xyzLocS.Y() + resp->getDepthMax() - Segmentation::SensorLayerThickness / 2.);
388
389 // collect charge in every pixel which might be affected by the hit
390 for (int iStep = nSteps; iStep--;) {
391 // Get the pixel ID
392 Segmentation::localToDetector(xyzLocS.X(), xyzLocS.Z(), row, col);
393 if (row != rowPrev || col != colPrev) { // update pixel and coordinates of its center
394 if (!Segmentation::detectorToLocal(row, col, cRowPix, cColPix)) {
395 continue; // should not happen
396 }
397 rowPrev = row;
398 colPrev = col;
399 }
400 bool flipCol, flipRow;
401 // note that response needs coordinates along column row (locX) (locZ) then depth (locY)
402 auto rspmat = resp->getResponse(xyzLocS.X() - cRowPix, xyzLocS.Z() - cColPix, xyzLocS.Y(), flipRow, flipCol);
403
404 xyzLocS += step;
405 if (!rspmat) {
406 continue;
407 }
408
409 for (int irow = AlpideRespSimMat::NPix; irow--;) {
410 int rowDest = row + irow - AlpideRespSimMat::NPix / 2 - rowS; // destination row in the respMatrix
411 if (rowDest < 0 || rowDest >= rowSpan) {
412 continue;
413 }
414 for (int icol = AlpideRespSimMat::NPix; icol--;) {
415 int colDest = col + icol - AlpideRespSimMat::NPix / 2 - colS; // destination column in the respMatrix
416 if (colDest < 0 || colDest >= colSpan) {
417 continue;
418 }
419 respMatrix[rowDest][colDest] += rspmat->getValue(irow, icol, flipRow, flipCol);
420 }
421 }
422 }
423
424 // fire the pixels assuming Poisson(n_response_electrons)
425 o2::MCCompLabel lbl(hit.GetTrackID(), evID, srcID, false);
426 auto roFrameAbs = mNewROFrame + roFrameRel;
427 for (int irow = rowSpan; irow--;) {
428 uint16_t rowIS = irow + rowS;
429 for (int icol = colSpan; icol--;) {
430 float nEleResp = respMatrix[irow][icol];
431 if (!nEleResp) {
432 continue;
433 }
434 int nEle = gRandom->Poisson(nElectrons * nEleResp); // total charge in given pixel
435 // ignore charge which have no chance to fire the pixel
436 if (nEle < mParams.getMinChargeToAccount()) {
437 continue;
438 }
439 uint16_t colIS = icol + colS;
440 if (mNoiseMap && mNoiseMap->isNoisy(chipID, rowIS, colIS)) {
441 continue;
442 }
443 if (mDeadChanMap && mDeadChanMap->isNoisy(chipID, rowIS, colIS)) {
444 continue;
445 }
446 //
447 registerDigits(chip, roFrameAbs, timeInROF, nFrames, rowIS, colIS, nEle, lbl);
448 }
449 }
450}
451
452//________________________________________________________________________________
453void Digitizer::registerDigits(ChipDigitsContainer& chip, uint32_t roFrame, float tInROF, int nROF,
454 uint16_t row, uint16_t col, int nEle, o2::MCCompLabel& lbl)
455{
456 // Register digits for given pixel, accounting for the possible signal contribution to
457 // multiple ROFrame. The signal starts at time tInROF wrt the start of provided roFrame
458 // In every ROFrame we check the collected signal during strobe
459
460 float tStrobe = mParams.getStrobeDelay() - tInROF; // strobe start wrt signal start
461 for (int i = 0; i < nROF; i++) {
462 uint32_t roFr = roFrame + i;
463 int nEleROF = mParams.getSignalShape().getCollectedCharge(nEle, tStrobe, tStrobe + mParams.getStrobeLength());
464 tStrobe += mParams.getROFrameLength(); // for the next ROF
465
466 // discard too small contributions, they have no chance to produce a digit
467 if (nEleROF < mParams.getMinChargeToAccount()) {
468 continue;
469 }
470 if (roFr > mEventROFrameMax) {
471 mEventROFrameMax = roFr;
472 }
473 if (roFr < mEventROFrameMin) {
474 mEventROFrameMin = roFr;
475 }
476 auto key = chip.getOrderingKey(roFr, row, col);
477 PreDigit* pd = chip.findDigit(key);
478 if (!pd) {
479 chip.addDigit(key, roFr, row, col, nEleROF, lbl);
480 } else { // there is already a digit at this slot, account as PreDigitExtra contribution
481 pd->charge += nEleROF;
482 if (pd->labelRef.label == lbl) { // don't store the same label twice
483 continue;
484 }
485 ExtraDig* extra = getExtraDigBuffer(roFr);
486 int& nxt = pd->labelRef.next;
487 bool skip = false;
488 while (nxt >= 0) {
489 if ((*extra)[nxt].label == lbl) { // don't store the same label twice
490 skip = true;
491 break;
492 }
493 nxt = (*extra)[nxt].next;
494 }
495 if (skip) {
496 continue;
497 }
498 // new predigit will be added in the end of the chain
499 nxt = extra->size();
500 extra->emplace_back(lbl);
501 }
502 }
503}
Definition of the ITSMFT digit.
int32_t i
Definition of the ITS digitizer.
Definition of a container to keep Monte Carlo truth external to simulation objects.
uint32_t col
Definition RawData.h:4
Definition of the SegmentationAlpide class.
std::ostringstream debug
StringRef key
int GetTrackID() const
Definition BaseHits.h:30
V GetEnergyLoss() const
Definition BaseHits.h:103
math_utils::Point3D< T > GetPos() const
Definition BaseHits.h:67
E GetTime() const
Definition BaseHits.h:71
short GetDetectorID() const
Definition BaseHits.h:73
void addElement(uint32_t dataindex, TruthElement const &element, bool noElement=false)
const char * getName() const
const Mat3D & getMatrixL2G(int sensID) const
float getCollectedCharge(float totalNEle, float tMin, float tMax) const
bool getResponse(float vRow, float vCol, float cDepth, AlpideRespSimMat &dest) const
Container for similated points connected to a given chip.
void addDigit(ULong64_t key, UInt_t roframe, UShort_t row, UShort_t col, int charge, o2::MCCompLabel lbl)
o2::itsmft::PreDigit * findDigit(ULong64_t key)
static ULong64_t getOrderingKey(UInt_t roframe, UShort_t row, UShort_t col)
Get global ordering key made of readout frame, column and row.
int getMinChargeToAccount() const
Definition DigiParams.h:82
float getROFrameLengthInv() const
Definition DigiParams.h:59
const SignalShape & getSignalShape() const
Definition DigiParams.h:96
float getEnergyToNElectrons() const
Definition DigiParams.h:85
int getROFrameLengthInBC() const
Definition DigiParams.h:54
float getStrobeDelay() const
Definition DigiParams.h:62
bool isContinuous() const
Definition DigiParams.h:52
int getChargeThreshold() const
Definition DigiParams.h:81
float getNSimStepsInv() const
Definition DigiParams.h:84
float getROFrameLength() const
Definition DigiParams.h:58
int getNSimSteps() const
Definition DigiParams.h:83
float getStrobeLength() const
Definition DigiParams.h:65
Digit class for the ITS.
Definition Digit.h:30
auto getChipResponse(int chipID)
void setEventTime(const o2::InteractionTimeRecord &irt)
bool isContinuous() const
Definition Digitizer.h:78
void process(const std::vector< Hit > *hits, int evID, int srcID)
Steer conversion of hits to digits.
void fillOutputContainer(uint32_t maxFrame=0xffffffff)
Int_t getNumberOfChips() const
math_utils::Point3D< Float_t > GetPosStart() const
Definition Hit.h:60
bool isFullChipMasked(int chip) const
Definition NoiseMap.h:186
bool isNoisy(int chip, int row, int col) const
Definition NoiseMap.h:151
void setNEntries(int n)
Definition ROFRecord.h:48
const BCData & getBCData() const
Definition ROFRecord.h:58
void setFirstEntry(int idx)
Definition ROFRecord.h:47
int getFirstEntry() const
Definition ROFRecord.h:63
void setROFrame(ROFtype rof)
Definition ROFRecord.h:45
static constexpr float SensorLayerThickness
static bool localToDetector(float x, float z, int &iRow, int &iCol)
static bool detectorToLocal(L row, L col, T &xRow, T &zCol)
GLuint buffer
Definition glcorearb.h:655
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
constexpr double LHCBunchSpacingNS
value_T step
Definition TrackUtils.h:42
static double bc2ns(int bc, unsigned int orbit)
int64_t differenceInBC(const InteractionRecord &other) const
void setFromLong(int64_t l)
double timeInBCNS
time in NANOSECONDS relative to orbit/bc
int next
eventual next contribution to the same pixel
Definition PreDigit.h:36
o2::MCCompLabel label
hit label
Definition PreDigit.h:35
int charge
N electrons.
Definition PreDigit.h:46
PreDigitLabelRef labelRef
label and reference to the next one
Definition PreDigit.h:47
IR getFirstSampledTFIR() const
get TF and HB (abs) for this IR
Definition HBFUtils.h:74
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< int > row