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