30#ifdef _PERFORM_TIMING_
50 const int MaxErrLog = 2;
51 static int errLocCount = 0;
52 if (errLocCount++ < MaxErrLog) {
53 LOGP(warn,
"Impossible ROF IR {}, does not exceed previous {}, discarding in clusterization", reader.
getInteractionRecord().
asString(), lastIR.asString());
60 mFiredChipsPtr.clear();
63 mFiredChipsPtr.push_back(curChipData);
64 nPix += curChipData->
getData().size();
67 auto& rof = vecROFRec->emplace_back(reader.
getInteractionRecord(), vecROFRec->size(), compClus->size(), 0);
69 uint16_t nFired = mFiredChipsPtr.size();
76 if (nFired < nThreads) {
82 uint16_t chipStep = nThreads > 1 ? (nThreads == 2 ? 20 : 10) : nFired;
83 int dynGrp = std::min(4, std::max(1, nThreads / 2));
84 if (nThreads > mThreads.size()) {
85 int oldSz = mThreads.size();
86 mThreads.resize(nThreads);
87 for (
int i = oldSz;
i < nThreads;
i++) {
88 mThreads[
i] = std::make_unique<ClustererThread>(
this,
i);
92#pragma omp parallel for schedule(dynamic, dynGrp) num_threads(nThreads)
94 for (uint16_t ic = 0; ic < nFired; ic += chipStep) {
95 auto ith = omp_get_thread_num();
97 mThreads[ith]->process(ic, std::min(chipStep, uint16_t(nFired - ic)),
98 &mThreads[ith]->compClusters,
99 patterns ? &mThreads[ith]->patterns :
nullptr,
101 labelsCl ? &mThreads[ith]->labels :
nullptr, rof);
103 mThreads[0]->process(0, nFired, compClus, patterns, labelsCl ? reader.
getDigitsMCTruth() :
nullptr, labelsCl, rof);
108 mThreads[0]->process(0, nFired, compClus, patterns, labelsCl ? reader.
getDigitsMCTruth() :
nullptr, labelsCl, rof);
112#ifdef _PERFORM_TIMING_
113 mTimerMerge.Start(
false);
115 size_t nClTot = 0, nPattTot = 0;
116 int chid = 0, thrStatIdx[nThreads];
117 for (
int ith = 0; ith < nThreads; ith++) {
118 std::sort(mThreads[ith]->stats.begin(), mThreads[ith]->stats.end(), [](
const ThreadStat&
a,
const ThreadStat&
b) { return a.firstChip < b.firstChip; });
120 nClTot += mThreads[ith]->compClusters.size();
121 nPattTot += mThreads[ith]->patterns.size();
123 compClus->reserve(nClTot);
125 patterns->reserve(nPattTot);
127 while (
chid < nFired) {
128 for (
int ith = 0; ith < nThreads; ith++) {
129 if (thrStatIdx[ith] >= mThreads[ith]->stats.size()) {
132 const auto& stat = mThreads[ith]->stats[thrStatIdx[ith]];
133 if (stat.firstChip ==
chid) {
136 const auto clbeg = mThreads[ith]->compClusters.begin() + stat.firstClus;
137 auto szold = compClus->size();
138 compClus->insert(compClus->end(), clbeg, clbeg + stat.nClus);
140 const auto ptbeg = mThreads[ith]->patterns.begin() + stat.firstPatt;
141 patterns->insert(patterns->end(), ptbeg, ptbeg + stat.nPatt);
144 labelsCl->
mergeAtBack(mThreads[ith]->labels, stat.firstClus, stat.nClus);
149 for (
int ith = 0; ith < nThreads; ith++) {
150 mThreads[ith]->patterns.clear();
151 mThreads[ith]->compClusters.clear();
152 mThreads[ith]->labels.clear();
153 mThreads[ith]->stats.clear();
155#ifdef _PERFORM_TIMING_
159 mThreads[0]->stats.clear();
161 rof.setNEntries(compClus->size() - rof.getFirstEntry());
162 }
while (autoDecode);
164#ifdef _PERFORM_TIMING_
173 if (
stats.empty() ||
stats.back().firstChip +
stats.back().nChips != chip) {
174 stats.emplace_back(
ThreadStat{chip, 0, uint32_t(compClusPtr->size()), patternsPtr ? uint32_t(patternsPtr->size()) : 0, 0, 0});
176 for (
int ic = 0; ic < nChips; ic++) {
177 auto* curChipData =
parent->mFiredChipsPtr[chip + ic];
178 auto chipID = curChipData->getChipID();
179 if (
parent->mMaxBCSeparationToMask > 0) {
180 const auto& chipInPrevROF =
parent->mChipsOld[chipID];
182 parent->mMaxRowColDiffToMask ? curChipData->maskFiredInSample(
parent->mChipsOld[chipID],
parent->mMaxRowColDiffToMask) : curChipData->maskFiredInSample(
parent->mChipsOld[chipID]);
185 auto nclus0 = compClusPtr->size();
186 auto validPixID = curChipData->getFirstUnmasked();
187 auto npix = curChipData->getData().size();
188 if (validPixID < npix) {
189 auto valp = validPixID++;
190 if (validPixID == npix) {
194 for (; validPixID < npix; validPixID++) {
195 if (!curChipData->getData()[validPixID].isMasked()) {
199 finishChip(curChipData, compClusPtr, patternsPtr, labelsDigPtr, labelsClPtr);
202 if (
parent->mMaxBCSeparationToMask > 0) {
203 parent->mChipsOld[chipID].swap(*curChipData);
206 auto& currStat =
stats.back();
207 currStat.nChips += nChips;
208 currStat.nClus = compClusPtr->size() - currStat.firstClus;
209 currStat.nPatt = patternsPtr ? (patternsPtr->size() - currStat.firstPatt) : 0;
216 const auto& pixData = curChipData->
getData();
217 for (
int i1 = 0; i1 < preClusterHeads.size(); ++i1) {
218 auto ci = preClusterIndices[i1];
224 int next = preClusterHeads[i1];
227 const auto& pixEntry =
pixels[next];
228 const auto pix = pixData[pixEntry.second];
229 pixArrBuff.push_back(pix);
230 bbox.adjust(pix.getRowDirect(), pix.getCol());
232 if (parent->mSquashingDepth) {
233 fetchMCLabels(curChipData->
getOrderedPixId(pixEntry.second), labelsDigPtr, nlab);
235 fetchMCLabels(pixEntry.second + curChipData->
getStartID(), labelsDigPtr, nlab);
238 next = pixEntry.first;
240 preClusterIndices[i1] = -1;
241 for (
int i2 = i1 + 1; i2 < preClusterHeads.size(); ++i2) {
242 if (preClusterIndices[i2] != ci) {
245 next = preClusterHeads[i2];
247 const auto& pixEntry =
pixels[next];
248 const auto pix = pixData[pixEntry.second];
249 pixArrBuff.push_back(pix);
250 bbox.adjust(pix.getRowDirect(), pix.getCol());
252 if (parent->mSquashingDepth) {
253 fetchMCLabels(curChipData->
getOrderedPixId(pixEntry.second), labelsDigPtr, nlab);
255 fetchMCLabels(pixEntry.second + curChipData->
getStartID(), labelsDigPtr, nlab);
258 next = pixEntry.first;
260 preClusterIndices[i2] = -1;
262 if (
bbox.isAcceptableSize()) {
263 parent->streamCluster(pixArrBuff, &labelsBuff,
bbox, parent->mPattIdConverter, compClusPtr, patternsPtr, labelsClusPtr, nlab);
266 if (!parent->mDropHugeClusters) {
268 LOGP(warn,
"Splitting a huge cluster: chipID {}, rows {}:{} cols {}:{}{}",
bbox.chipID,
bbox.rowMin,
bbox.rowMax,
bbox.colMin,
bbox.colMax,
269 warnLeft == 1 ?
" (Further warnings will be muted)" :
"");
274 parent->mNHugeClus++;
278 std::vector<PixelData> pixbuf;
284 for (
const auto& pix : pixArrBuff) {
285 if (bboxT.
isInside(pix.getRowDirect(), pix.getCol())) {
286 pixbuf.push_back(pix);
289 if (!pixbuf.empty()) {
290 parent->streamCluster(pixbuf, &labelsBuff, bboxT, parent->mPattIdConverter, compClusPtr, patternsPtr, labelsClusPtr, nlab,
true);
306 auto pix = curChipData->
getData()[hit];
307 uint16_t
row = pix.getRowDirect(),
col = pix.getCol();
311 fetchMCLabels(curChipData->
getStartID() + hit, labelsDigPtr, nlab);
312 auto cnt = compClusPtr->size();
313 for (
int i = nlab;
i--;) {
322 patternsPtr->emplace_back(1);
323 patternsPtr->emplace_back(1);
324 patternsPtr->insert(patternsPtr->end(), std::begin(patt), std::begin(patt) + 1);