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