Project
Loading...
Searching...
No Matches
Clusterer.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 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
15#include <algorithm>
16
21
22#ifdef WITH_OPENMP
23#include <omp.h>
24#endif
25using namespace o2::itsmft;
26
27namespace o2::its3
28{
29void Clusterer::process(int nThreads, PixelReader& reader, CompClusCont* compClus,
30 PatternCont* patterns, ROFRecCont* vecROFRec, MCTruth* labelsCl)
31{
32#ifdef _PERFORM_TIMING_
33 mTimer.Start(kFALSE);
34#endif
35 nThreads = std::max(nThreads, 1);
36 auto autoDecode = reader.getDecodeNextAuto();
37 o2::InteractionRecord lastIR{};
38 do {
39 if (autoDecode) {
40 reader.setDecodeNextAuto(false); // internally do not autodecode
41 if (!reader.decodeNextTrigger()) {
42 break; // on the fly decoding was requested, but there were no data left
43 }
44 }
45 if (reader.getInteractionRecord().isDummy()) {
46 continue; // No IR info was found
47 }
48 if (!lastIR.isDummy() && lastIR >= reader.getInteractionRecord()) {
49 const int MaxErrLog = 2;
50 static int errLocCount = 0;
51 if (errLocCount++ < MaxErrLog) {
52 LOGP(warn, "Impossible ROF IR {}, does not exceed previous {}, discarding in clusterization", reader.getInteractionRecord().asString(), lastIR.asString());
53 }
54 continue;
55 }
56 lastIR = reader.getInteractionRecord();
57 // pre-fetch all non-empty chips of current ROF
58 ChipPixelData* curChipData = nullptr;
59 mFiredChipsPtr.clear();
60 size_t nPix = 0;
61 while ((curChipData = reader.getNextChipData(mChips))) {
62 mFiredChipsPtr.push_back(curChipData);
63 nPix += curChipData->getData().size();
64 }
65
66 auto& rof = vecROFRec->emplace_back(reader.getInteractionRecord(), vecROFRec->size(), compClus->size(), 0); // create new ROF
67
68 uint16_t nFired = mFiredChipsPtr.size();
69 if (!nFired) {
70 if (autoDecode) {
71 continue;
72 }
73 break; // just 1 ROF was asked to be processed
74 }
75 nThreads = std::min<int>(nFired, nThreads);
76#ifndef WITH_OPENMP
77 nThreads = 1;
78#endif
79 uint16_t chipStep = nThreads > 1 ? (nThreads == 2 ? 20 : 10) : nFired;
80 int dynGrp = std::min(4, std::max(1, nThreads / 2));
81 if (nThreads > mThreads.size()) {
82 int oldSz = mThreads.size();
83 mThreads.resize(nThreads);
84 for (int i = oldSz; i < nThreads; i++) {
85 mThreads[i] = std::make_unique<ClustererThread>(this, i);
86 }
87 }
88#ifdef WITH_OPENMP
89#pragma omp parallel for schedule(dynamic, dynGrp) num_threads(nThreads)
90 //>> start of MT region
91 for (uint16_t ic = 0; ic < nFired; ic += chipStep) {
92 auto ith = omp_get_thread_num();
93 if (nThreads > 1) {
94 mThreads[ith]->process(ic, std::min(chipStep, uint16_t(nFired - ic)),
95 &mThreads[ith]->compClusters,
96 patterns ? &mThreads[ith]->patterns : nullptr,
97 labelsCl ? reader.getDigitsMCTruth() : nullptr,
98 labelsCl ? &mThreads[ith]->labels : nullptr, rof);
99 } else { // put directly to the destination
100 mThreads[0]->process(0, nFired, compClus, patterns, labelsCl ? reader.getDigitsMCTruth() : nullptr, labelsCl, rof);
101 }
102 }
103 //<< end of MT region
104#else
105 mThreads[0]->process(0, nFired, compClus, patterns, labelsCl ? reader.getDigitsMCTruth() : nullptr, labelsCl, rof);
106#endif
107 // copy data of all threads but the 1st one to final destination
108 if (nThreads > 1) {
109#ifdef _PERFORM_TIMING_
110 mTimerMerge.Start(false);
111#endif
112 size_t nClTot = 0, nPattTot = 0;
113 int chid = 0, thrStatIdx[nThreads];
114 for (int ith = 0; ith < nThreads; ith++) {
115 std::sort(mThreads[ith]->stats.begin(), mThreads[ith]->stats.end(), [](const ThreadStat& a, const ThreadStat& b) { return a.firstChip < b.firstChip; });
116 thrStatIdx[ith] = 0;
117 nClTot += mThreads[ith]->compClusters.size();
118 nPattTot += mThreads[ith]->patterns.size();
119 }
120 compClus->reserve(nClTot);
121 if (patterns) {
122 patterns->reserve(nPattTot);
123 }
124 while (chid < nFired) {
125 for (int ith = 0; ith < nThreads; ith++) {
126 if (thrStatIdx[ith] >= mThreads[ith]->stats.size()) {
127 continue;
128 }
129 const auto& stat = mThreads[ith]->stats[thrStatIdx[ith]];
130 if (stat.firstChip == chid) {
131 thrStatIdx[ith]++;
132 chid += stat.nChips; // next chip to look
133 if (stat.nClus > 0) {
134 const auto clbeg = mThreads[ith]->compClusters.begin() + stat.firstClus;
135 compClus->insert(compClus->end(), clbeg, clbeg + stat.nClus);
136 if (patterns) {
137 const auto ptbeg = mThreads[ith]->patterns.begin() + stat.firstPatt;
138 patterns->insert(patterns->end(), ptbeg, ptbeg + stat.nPatt);
139 }
140 if (labelsCl) {
141 labelsCl->mergeAtBack(mThreads[ith]->labels, stat.firstClus, stat.nClus);
142 }
143 }
144 }
145 }
146 }
147 for (int ith = 0; ith < nThreads; ith++) {
148 mThreads[ith]->patterns.clear();
149 mThreads[ith]->compClusters.clear();
150 mThreads[ith]->labels.clear();
151 mThreads[ith]->stats.clear();
152 }
153#ifdef _PERFORM_TIMING_
154 mTimerMerge.Stop();
155#endif
156 } else {
157 mThreads[0]->stats.clear();
158 }
159 rof.setNEntries(compClus->size() - rof.getFirstEntry()); // update
160 } while (autoDecode);
161 reader.setDecodeNextAuto(autoDecode); // restore setting
162#ifdef _PERFORM_TIMING_
163 mTimer.Stop();
164#endif
165}
166
167//__________________________________________________
168void Clusterer::ClustererThread::process(uint16_t chip, uint16_t nChips, CompClusCont* compClusPtr, PatternCont* patternsPtr,
169 const ConstMCTruth* labelsDigPtr, MCTruth* labelsClPtr, const ROFRecord& rofPtr)
170{
171 if (stats.empty() || stats.back().firstChip + stats.back().nChips != chip) { // there is a jump, register new block
172 stats.emplace_back(ThreadStat{.firstChip = chip, .nChips = 0, .firstClus = uint32_t(compClusPtr->size()), .firstPatt = patternsPtr ? uint32_t(patternsPtr->size()) : 0, .nClus = 0, .nPatt = 0});
173 }
174 for (int ic = 0; ic < nChips; ic++) {
175 auto* curChipData = parent->mFiredChipsPtr[chip + ic];
176 auto chipID = curChipData->getChipID();
177 if (parent->mMaxBCSeparationToMask > 0) { // mask pixels fired from the previous ROF
178 const auto& chipInPrevROF = parent->mChipsOld[chipID];
179 if (std::abs(rofPtr.getBCData().differenceInBC(chipInPrevROF.getInteractionRecord())) < parent->mMaxBCSeparationToMask) {
180 parent->mMaxRowColDiffToMask ? curChipData->maskFiredInSample(parent->mChipsOld[chipID], parent->mMaxRowColDiffToMask) : curChipData->maskFiredInSample(parent->mChipsOld[chipID]);
181 }
182 }
183 auto validPixID = curChipData->getFirstUnmasked();
184 auto npix = curChipData->getData().size();
185 if (validPixID < npix) { // chip data may have all of its pixels masked!
186 auto valp = validPixID++;
187 if (validPixID == npix) { // special case of a single pixel fired on the chip
188 finishChipSingleHitFast(valp, curChipData, compClusPtr, patternsPtr, labelsDigPtr, labelsClPtr);
189 } else {
190 initChip(curChipData, valp);
191 for (; validPixID < npix; validPixID++) {
192 if (!curChipData->getData()[validPixID].isMasked()) {
193 updateChip(curChipData, validPixID);
194 }
195 }
196 finishChip(curChipData, compClusPtr, patternsPtr, labelsDigPtr, labelsClPtr);
197 }
198 }
199 if (parent->mMaxBCSeparationToMask > 0) { // current chip data will be used in the next ROF to mask overflow pixels
200 parent->mChipsOld[chipID].swap(*curChipData);
201 }
202 }
203 auto& currStat = stats.back();
204 currStat.nChips += nChips;
205 currStat.nClus = compClusPtr->size() - currStat.firstClus;
206 currStat.nPatt = patternsPtr ? (patternsPtr->size() - currStat.firstPatt) : 0;
207}
208
209//__________________________________________________
211 PatternCont* patternsPtr, const ConstMCTruth* labelsDigPtr, MCTruth* labelsClusPtr)
212{
213 const auto& pixData = curChipData->getData();
214 int nPreclusters = preClusters.size();
215 // account for the eventual reindexing of preClusters: Id2 might have been reindexed to Id1, which later was reindexed to Id0
216 for (int i = 1; i < nPreclusters; i++) {
217 if (preClusters[i].index != i) { // reindexing is always done towards smallest index
218 preClusters[i].index = preClusters[preClusters[i].index].index;
219 }
220 }
221 for (int i1 = 0; i1 < nPreclusters; ++i1) {
222 auto& preCluster = preClusters[i1];
223 auto ci = preCluster.index;
224 if (ci < 0) {
225 continue;
226 }
227 BBox bbox(curChipData->getChipID());
228 int nlab = 0;
229 int next = preCluster.head;
230 pixArrBuff.clear();
231 while (next >= 0) {
232 const auto& pixEntry = pixels[next];
233 const auto pix = pixData[pixEntry.second];
234 pixArrBuff.push_back(pix); // needed for cluster topology
235 bbox.adjust(pix.getRowDirect(), pix.getCol());
236 if (labelsClusPtr) {
237 if (parent->mSquashingDepth) { // the MCtruth for this pixel is stored in chip data: due to squashing we lose contiguity
238 fetchMCLabels(curChipData->getOrderedPixId(pixEntry.second), labelsDigPtr, nlab);
239 } else { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second
240 fetchMCLabels(pixEntry.second + curChipData->getStartID(), labelsDigPtr, nlab);
241 }
242 }
243 next = pixEntry.first;
244 }
245 preCluster.index = -1;
246 for (int i2 = i1 + 1; i2 < nPreclusters; ++i2) {
247 auto& preCluster2 = preClusters[i2];
248 if (preCluster2.index != ci) {
249 continue;
250 }
251 next = preCluster2.head;
252 while (next >= 0) {
253 const auto& pixEntry = pixels[next];
254 const auto pix = pixData[pixEntry.second]; // PixelData
255 pixArrBuff.push_back(pix); // needed for cluster topology
256 bbox.adjust(pix.getRowDirect(), pix.getCol());
257 if (labelsClusPtr) {
258 if (parent->mSquashingDepth) { // the MCtruth for this pixel is stored in chip data: due to squashing we lose contiguity
259 fetchMCLabels(curChipData->getOrderedPixId(pixEntry.second), labelsDigPtr, nlab);
260 } else { // the MCtruth for this pixel is at curChipData->startID+pixEntry.second
261 fetchMCLabels(pixEntry.second + curChipData->getStartID(), labelsDigPtr, nlab);
262 }
263 }
264 next = pixEntry.first;
265 }
266 preCluster2.index = -1;
267 }
268 if (bbox.isAcceptableSize()) {
269 const bool isIB = constants::detID::isDetITS3(curChipData->getChipID());
270 parent->streamCluster(pixArrBuff, &labelsBuff, bbox, parent->mPattIdConverter, compClusPtr, patternsPtr, labelsClusPtr, nlab, isIB);
271 } else {
272 auto warnLeft = MaxHugeClusWarn - parent->mNHugeClus;
273 if (!parent->mDropHugeClusters) {
274 if (warnLeft > 0) {
275 LOGP(warn, "Splitting a huge cluster: chipID {}, rows {}:{} cols {}:{}{}", bbox.chipID, bbox.rowMin, bbox.rowMax, bbox.colMin, bbox.colMax,
276 warnLeft == 1 ? " (Further warnings will be muted)" : "");
277#ifdef WITH_OPENMP
278#pragma omp critical
279#endif
280 {
281 parent->mNHugeClus++;
282 }
283 }
284 BBox bboxT(bbox); // truncated box
285 std::vector<PixelData> pixbuf;
286 do {
287 bboxT.rowMin = bbox.rowMin;
288 bboxT.colMax = std::min(bbox.colMax, uint16_t(bboxT.colMin + o2::itsmft::ClusterPattern::MaxColSpan - 1));
289 do { // Select a subset of pixels fitting the reduced bounding box
290 bboxT.rowMax = std::min(bbox.rowMax, uint16_t(bboxT.rowMin + o2::itsmft::ClusterPattern::MaxRowSpan - 1));
291 for (const auto& pix : pixArrBuff) {
292 if (bboxT.isInside(pix.getRowDirect(), pix.getCol())) {
293 pixbuf.push_back(pix);
294 }
295 }
296 if (!pixbuf.empty()) { // Stream a piece of cluster only if the reduced bounding box is not empty
297 const bool isIB = constants::detID::isDetITS3(curChipData->getChipID());
298 parent->streamCluster(pixbuf, &labelsBuff, bboxT, parent->mPattIdConverter, compClusPtr, patternsPtr, labelsClusPtr, nlab, isIB, true);
299 pixbuf.clear();
300 }
301 bboxT.rowMin = bboxT.rowMax + 1;
302 } while (bboxT.rowMin < bbox.rowMax);
303 bboxT.colMin = bboxT.colMax + 1;
304 } while (bboxT.colMin < bbox.colMax);
305 }
306 }
307 }
308}
309
310//__________________________________________________
312 PatternCont* patternsPtr, const ConstMCTruth* labelsDigPtr, MCTruth* labelsClusPtr)
313{
314 auto pix = curChipData->getData()[hit];
315 uint16_t row = pix.getRowDirect(), col = pix.getCol();
316
317 if (labelsClusPtr) { // MC labels were requested
318 int nlab = 0;
319 fetchMCLabels(curChipData->getStartID() + hit, labelsDigPtr, nlab);
320 auto cnt = compClusPtr->size();
321 for (int i = nlab; i--;) {
322 labelsClusPtr->addElement(cnt, labelsBuff[i]);
323 }
324 }
325
326 auto ib = constants::detID::isDetITS3(curChipData->getChipID());
327
328 // add to compact clusters, which must be always filled
329 unsigned char patt[ClusterPattern::MaxPatternBytes]{0x1 << (7 - (0 % 8))}; // unrolled 1 hit version of full loop in finishChip
330 uint16_t pattID = (parent->mPattIdConverter.size(ib) == 0) ? CompCluster::InvalidPatternID : parent->mPattIdConverter.findGroupID(1, 1, ib, patt);
331 if ((pattID == CompCluster::InvalidPatternID || parent->mPattIdConverter.isGroup(pattID, ib)) && patternsPtr) {
332 patternsPtr->emplace_back(1); // rowspan
333 patternsPtr->emplace_back(1); // colspan
334 patternsPtr->insert(patternsPtr->end(), std::begin(patt), std::begin(patt) + 1);
335 }
336 compClusPtr->emplace_back(row, col, pattID, curChipData->getChipID());
337}
338
339//__________________________________________________
341{
342#ifdef _PERFORM_TIMING_
343 mTimer.Stop();
344 mTimer.Reset();
345 mTimerMerge.Stop();
346 mTimerMerge.Reset();
347#endif
348}
349
350//__________________________________________________
352{
353 // init chip with the 1st unmasked pixel (entry "from" in the mChipData)
355 int chipId = curChipData->getChipID();
358 }
359
360 delete[] column1;
361 delete[] column2;
362 column1 = new int[size];
363 column2 = new int[size];
364 column1[0] = column1[size - 1] = -1;
365 column2[0] = column2[size - 1] = -1;
366 // init chip with the 1st unmasked pixel (entry "from" in the mChipData)
367 prev = column1 + 1;
368 curr = column2 + 1;
369 resetColumn(curr);
370
371 pixels.clear();
372 preClusters.clear();
373 auto pix = curChipData->getData()[first];
374 currCol = pix.getCol();
375 curr[pix.getRowDirect()] = 0; // can use getRowDirect since the pixel is not masked
376 // start the first pre-cluster
377 preClusters.emplace_back();
378 pixels.emplace_back(-1, first); // id of current pixel
379 noLeftCol = true; // flag that there is no column on the left to check yet
380}
381
382//__________________________________________________
383void Clusterer::ClustererThread::updateChip(const ChipPixelData* curChipData, uint32_t ip)
384{
385 const auto pix = curChipData->getData()[ip];
386 uint16_t row = pix.getRowDirect(); // can use getRowDirect since the pixel is not masked
387 if (currCol != pix.getCol()) { // switch the buffers
388 swapColumnBuffers();
389 resetColumn(curr);
390 noLeftCol = false;
391 if (pix.getCol() > currCol + 1) {
392 // no connection with previous column, this pixel cannot belong to any of the
393 // existing preclusters, create a new precluster and flag to check only the row above for next pixels of this column
394 currCol = pix.getCol();
395 addNewPrecluster(ip, row);
396 noLeftCol = true;
397 return;
398 }
399 currCol = pix.getCol();
400 }
401
402 if (noLeftCol) { // check only the row above
403 if (curr[row - 1] >= 0) {
404 expandPreCluster(ip, row, curr[row - 1]); // attach to the precluster of the previous row
405 } else {
406 addNewPrecluster(ip, row); // start new precluster
407 }
408 } else {
409 // row above should be always checked
410 int nnb = 0, lowestIndex = curr[row - 1], *nbrCol[4], nbrRow[4];
411 if (lowestIndex >= 0) {
412 nbrCol[nnb] = curr;
413 nbrRow[nnb++] = row - 1;
414 } else {
415 lowestIndex = 0x7ffff;
416 }
417#ifdef _ALLOW_DIAGONAL_ALPIDE_CLUSTERS_
418 for (int i : {-1, 0, 1}) {
419 auto v = prev[row + i];
420 if (v >= 0) {
421 nbrCol[nnb] = prev;
422 nbrRow[nnb] = row + i;
423 if (v < lowestIndex) {
424 lowestIndex = v;
425 }
426 nnb++;
427 }
428 }
429#else
430 if (prev[row] >= 0) {
431 nbrCol[nnb] = prev;
432 nbrRow[nnb] = row;
433 if (prev[row] < lowestIndex) {
434 lowestIndex = prev[row];
435 }
436 nnb++;
437 }
438#endif
439 if (!nnb) { // no neighbours, create new precluster
440 addNewPrecluster(ip, row); // start new precluster
441 } else {
442 expandPreCluster(ip, row, lowestIndex); // attach to the adjascent precluster with smallest index
443 if (nnb > 1) {
444 for (int inb = 0; inb < nnb; inb++) { // reassign precluster index to smallest one, replicating updated values to columns caches
445 auto& prevIndex = (nbrCol[inb])[nbrRow[inb]];
446 prevIndex = preClusters[prevIndex].index = lowestIndex;
447 }
448 }
449 }
450 }
451}
452
453//__________________________________________________
454void Clusterer::ClustererThread::fetchMCLabels(int digID, const ConstMCTruth* labelsDig, int& nfilled)
455{
456 // transfer MC labels to cluster
457 if (nfilled >= MaxLabels) {
458 return;
459 }
460 const auto& lbls = labelsDig->getLabels(digID);
461 for (int i = lbls.size(); i--;) {
462 int ic = nfilled;
463 for (; ic--;) { // check if the label is already present
464 if (labelsBuff[ic] == lbls[i]) {
465 return; // label is found, do nothing
466 }
467 }
468 labelsBuff[nfilled++] = lbls[i];
469 if (nfilled >= MaxLabels) {
470 break;
471 }
472 }
473 //
474}
475
476//__________________________________________________
478{
479 // reset
480#ifdef _PERFORM_TIMING_
481 mTimer.Stop();
482 mTimer.Reset();
483 mTimerMerge.Stop();
484 mTimerMerge.Reset();
485#endif
486}
487
488//__________________________________________________
489void Clusterer::print(bool showsTiming) const
490{
491 // print settings
492 if (mSquashingLayerDepth.empty()) {
493 LOGP(info, "Clusterizer squashes overflow pixels separated by {} BC and <= {} in row/col seeking down to {} neighbour ROFs", mMaxBCSeparationToSquash, mMaxRowColDiffToMask, mSquashingDepth);
494 } else {
495 LOGP(info, "Clusterizer squashes overflow pixels <= {} in row/col", mMaxRowColDiffToMask);
496 for (size_t i{0}; i < mSquashingLayerDepth.size(); ++i) {
497 LOGP(info, "\tClusterizer on layer {} separated by {} BC seeking down to {} neighbour ROFs", i, mMaxBCSeparationToSquashLayer[i], mSquashingLayerDepth[i]);
498 }
499 }
500 LOGP(info, "Clusterizer masks overflow pixels separated by < {} BC and <= {} in row/col", mMaxBCSeparationToMask, mMaxRowColDiffToMask);
501 LOGP(info, "Clusterizer does {} drop huge clusters", mDropHugeClusters ? "" : "not");
502
503 if (showsTiming) {
504#ifdef _PERFORM_TIMING_
505 auto& tmr = const_cast<TStopwatch&>(mTimer); // ugly but this is what root does internally
506 auto& tmrm = const_cast<TStopwatch&>(mTimerMerge);
507 LOG(info) << "Inclusive clusterization timing (w/o disk IO): Cpu: " << tmr.CpuTime()
508 << " Real: " << tmr.RealTime() << " s in " << tmr.Counter() << " slots";
509 LOG(info) << "Threads output merging timing : Cpu: " << tmrm.CpuTime()
510 << " Real: " << tmrm.RealTime() << " s in " << tmrm.Counter() << " slots";
511
512#endif
513 }
514}
515} // namespace o2::its3
std::vector< std::string > labels
int32_t i
Definition of a container to keep Monte Carlo truth external to simulation objects.
uint32_t col
Definition RawData.h:4
Definition of the SegmentationMosaix class.
Definition of the ITS cluster finder.
gsl::span< const TruthElement > getLabels(uint32_t dataindex) const
void mergeAtBack(MCTruthContainer< TruthElement > const &other)
void addElement(uint32_t dataindex, TruthElement const &element, bool noElement=false)
static constexpr int MaxLabels
Definition Clusterer.h:77
void process(int nThreads, PixelReader &r, CompClusCont *compClus, PatternCont *patterns, ROFRecCont *vecROFRec, MCTruth *labelsCl=nullptr)
Definition Clusterer.cxx:29
void clear()
load the dictionary of cluster topologies
void print(bool showsTiming) const
static constexpr int MaxHugeClusWarn
Definition Clusterer.h:78
uint32_t getOrderedPixId(int pos) const
Definition PixelData.h:275
uint32_t getStartID() const
Definition PixelData.h:110
uint16_t getChipID() const
Definition PixelData.h:108
const std::vector< PixelData > & getData() const
Definition PixelData.h:115
static constexpr int MaxPatternBytes
static constexpr uint8_t MaxRowSpan
static constexpr uint8_t MaxColSpan
static constexpr unsigned short InvalidPatternID
Definition CompCluster.h:46
PixelReader class for the ITSMFT.
Definition PixelReader.h:34
virtual int decodeNextTrigger()=0
bool getDecodeNextAuto() const
Definition PixelReader.h:62
void setDecodeNextAuto(bool v)
Definition PixelReader.h:63
const o2::InteractionRecord & getInteractionRecord() const
Definition PixelReader.h:53
virtual const o2::dataformats::ConstMCTruthContainerView< o2::MCCompLabel > * getDigitsMCTruth() const
Definition PixelReader.h:49
virtual bool getNextChipData(ChipPixelData &chipData)=0
const BCData & getBCData() const
Definition ROFRecord.h:58
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
GLuint index
Definition glcorearb.h:781
GLint first
Definition glcorearb.h:399
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
Definition glcorearb.h:275
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
bool isDetITS3(T detID)
Definition SpecsV2.h:210
std::vector< unsigned char > PatternCont
Definition Clusterer.h:60
std::vector< itsmft::CompClusterExt > CompClusCont
Definition Clusterer.h:59
std::vector< itsmft::ROFRecord > ROFRecCont
Definition Clusterer.h:61
std::string asString() const
int64_t differenceInBC(const InteractionRecord &other) const
bool isInside(uint16_t row, uint16_t col) const
Definition Clusterer.h:87
std::vector< ThreadStat > stats
Definition Clusterer.h:143
void finishChipSingleHitFast(uint32_t hit, ChipPixelData *curChipData, CompClusCont *compClusPtr, PatternCont *patternsPtr, const ConstMCTruth *labelsDigPtr, MCTruth *labelsClusPTr)
void process(uint16_t chip, uint16_t nChips, CompClusCont *compClusPtr, PatternCont *patternsPtr, const ConstMCTruth *labelsDigPtr, MCTruth *labelsClPtr, const itsmft::ROFRecord &rofPtr)
void updateChip(const ChipPixelData *curChipData, uint32_t ip)
void fetchMCLabels(int digID, const ConstMCTruth *labelsDig, int &nfilled)
void initChip(const ChipPixelData *curChipData, uint32_t first)
void finishChip(ChipPixelData *curChipData, CompClusCont *compClus, PatternCont *patterns, const ConstMCTruth *labelsDig, MCTruth *labelsClus)
methods and transient data used within a thread
Definition Clusterer.h:107
std::vector< o2::mch::DsChannelId > chid
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< int > row