Skip to content

Commit ecd2aca

Browse files
committed
Fix ITS/MFT clusterization for some complex shapes, O2-6424.
1 parent 494f76c commit ecd2aca

File tree

2 files changed

+80
-51
lines changed

2 files changed

+80
-51
lines changed

Detectors/ITSMFT/common/reconstruction/include/ITSMFTReconstruction/Clusterer.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ class Clusterer
121121
};
122122

123123
struct ClustererThread {
124+
struct PreCluster {
125+
int head = 0; // index of precluster head in the pixels
126+
int index = 0;
127+
};
124128
int id = -1;
125129
Clusterer* parent = nullptr; // parent clusterer
126130
// buffers for entries in preClusterIndices in 2 columns, to avoid boundary checks, we reserve
@@ -132,12 +136,11 @@ class Clusterer
132136
// pixels[].first is the index of the next pixel of the same precluster in the pixels
133137
// pixels[].second is the index of the referred pixel in the ChipPixelData (element of mChips)
134138
std::vector<std::pair<int, uint32_t>> pixels;
135-
std::vector<int> preClusterHeads; // index of precluster head in the pixels
136-
std::vector<int> preClusterIndices;
137139
uint16_t currCol = 0xffff; ///< Column being processed
138140
bool noLeftCol = true; ///< flag that there is no column on the left to check
139141
std::array<Label, MaxLabels> labelsBuff; //! temporary buffer for building cluster labels
140142
std::vector<PixelData> pixArrBuff; //! temporary buffer for pattern calc.
143+
std::vector<PreCluster> preClusters; //! preclusters info
141144
//
142145
/// temporary storage for the thread output
143146
CompClusCont compClusters;
@@ -154,7 +157,7 @@ class Clusterer
154157
///< add cluster at row (entry ip in the ChipPixeData) to the precluster with given index
155158
void expandPreCluster(uint32_t ip, uint16_t row, int preClusIndex)
156159
{
157-
auto& firstIndex = preClusterHeads[preClusterIndices[preClusIndex]];
160+
auto& firstIndex = preClusters[preClusters[preClusIndex].index].head;
158161
pixels.emplace_back(firstIndex, ip);
159162
firstIndex = pixels.size() - 1;
160163
curr[row] = preClusIndex;
@@ -163,11 +166,10 @@ class Clusterer
163166
///< add new precluster at given row of current column for the fired pixel with index ip in the ChipPixelData
164167
void addNewPrecluster(uint32_t ip, uint16_t row)
165168
{
166-
preClusterHeads.push_back(pixels.size());
169+
int lastIndex = preClusters.size();
170+
preClusters.emplace_back(pixels.size(), lastIndex);
167171
// new head does not point yet (-1) on other pixels, store just the entry of the pixel in the ChipPixelData
168172
pixels.emplace_back(-1, ip);
169-
int lastIndex = preClusterIndices.size();
170-
preClusterIndices.push_back(lastIndex);
171173
curr[row] = lastIndex; // store index of the new precluster in the current column buffer
172174
}
173175

Detectors/ITSMFT/common/reconstruction/src/Clusterer.cxx

Lines changed: 72 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,17 @@ void Clusterer::process(int nThreads, PixelReader& reader, CompClusCont* compClu
133133
if (stat.firstChip == chid) {
134134
thrStatIdx[ith]++;
135135
chid += stat.nChips; // next chip to look
136-
const auto clbeg = mThreads[ith]->compClusters.begin() + stat.firstClus;
137-
auto szold = compClus->size();
138-
compClus->insert(compClus->end(), clbeg, clbeg + stat.nClus);
139-
if (patterns) {
140-
const auto ptbeg = mThreads[ith]->patterns.begin() + stat.firstPatt;
141-
patterns->insert(patterns->end(), ptbeg, ptbeg + stat.nPatt);
142-
}
143-
if (labelsCl) {
144-
labelsCl->mergeAtBack(mThreads[ith]->labels, stat.firstClus, stat.nClus);
136+
if (stat.nClus > 0) {
137+
const auto clbeg = mThreads[ith]->compClusters.begin() + stat.firstClus;
138+
auto szold = compClus->size();
139+
compClus->insert(compClus->end(), clbeg, clbeg + stat.nClus);
140+
if (patterns) {
141+
const auto ptbeg = mThreads[ith]->patterns.begin() + stat.firstPatt;
142+
patterns->insert(patterns->end(), ptbeg, ptbeg + stat.nPatt);
143+
}
144+
if (labelsCl) {
145+
labelsCl->mergeAtBack(mThreads[ith]->labels, stat.firstClus, stat.nClus);
146+
}
145147
}
146148
}
147149
}
@@ -214,14 +216,22 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus
214216
PatternCont* patternsPtr, const ConstMCTruth* labelsDigPtr, MCTruth* labelsClusPtr)
215217
{
216218
const auto& pixData = curChipData->getData();
217-
for (int i1 = 0; i1 < preClusterHeads.size(); ++i1) {
218-
auto ci = preClusterIndices[i1];
219+
int nPreclusters = preClusters.size();
220+
// account for the eventual reindexing of preClusters: Id2 might have been reindexed to Id1, which later was reindexed to Id0
221+
for (int i = 1; i < nPreclusters; i++) {
222+
if (preClusters[i].index != i) { // reindexing is always done towards smallest index
223+
preClusters[i].index = preClusters[preClusters[i].index].index;
224+
}
225+
}
226+
for (int i1 = 0; i1 < nPreclusters; ++i1) {
227+
auto& preCluster = preClusters[i1];
228+
auto ci = preCluster.index;
219229
if (ci < 0) {
220230
continue;
221231
}
222232
BBox bbox(curChipData->getChipID());
223233
int nlab = 0;
224-
int next = preClusterHeads[i1];
234+
int next = preCluster.head;
225235
pixArrBuff.clear();
226236
while (next >= 0) {
227237
const auto& pixEntry = pixels[next];
@@ -237,12 +247,13 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus
237247
}
238248
next = pixEntry.first;
239249
}
240-
preClusterIndices[i1] = -1;
241-
for (int i2 = i1 + 1; i2 < preClusterHeads.size(); ++i2) {
242-
if (preClusterIndices[i2] != ci) {
250+
preCluster.index = -1;
251+
for (int i2 = i1 + 1; i2 < nPreclusters; ++i2) {
252+
auto& preCluster2 = preClusters[i2];
253+
if (preCluster2.index != ci) {
243254
continue;
244255
}
245-
next = preClusterHeads[i2];
256+
next = preCluster2.head;
246257
while (next >= 0) {
247258
const auto& pixEntry = pixels[next];
248259
const auto pix = pixData[pixEntry.second]; // PixelData
@@ -257,7 +268,7 @@ void Clusterer::ClustererThread::finishChip(ChipPixelData* curChipData, CompClus
257268
}
258269
next = pixEntry.first;
259270
}
260-
preClusterIndices[i2] = -1;
271+
preCluster2.index = -1;
261272
}
262273
if (bbox.isAcceptableSize()) {
263274
parent->streamCluster(pixArrBuff, &labelsBuff, bbox, parent->mPattIdConverter, compClusPtr, patternsPtr, labelsClusPtr, nlab);
@@ -344,18 +355,15 @@ void Clusterer::ClustererThread::initChip(const ChipPixelData* curChipData, uint
344355
prev = column1 + 1;
345356
curr = column2 + 1;
346357
resetColumn(curr);
347-
348358
pixels.clear();
349-
preClusterHeads.clear();
350-
preClusterIndices.clear();
359+
preClusters.clear();
351360
auto pix = curChipData->getData()[first];
352361
currCol = pix.getCol();
353362
curr[pix.getRowDirect()] = 0; // can use getRowDirect since the pixel is not masked
354363
// start the first pre-cluster
355-
preClusterHeads.push_back(0);
356-
preClusterIndices.push_back(0);
364+
preClusters.emplace_back();
357365
pixels.emplace_back(-1, first); // id of current pixel
358-
noLeftCol = true; // flag that there is no column on the left to check yet
366+
noLeftCol = true;
359367
}
360368

361369
//__________________________________________________
@@ -378,39 +386,58 @@ void Clusterer::ClustererThread::updateChip(const ChipPixelData* curChipData, ui
378386
currCol = pix.getCol();
379387
}
380388

381-
Bool_t orphan = true;
382-
383389
if (noLeftCol) { // check only the row above
384390
if (curr[row - 1] >= 0) {
385391
expandPreCluster(ip, row, curr[row - 1]); // attach to the precluster of the previous row
386-
return;
392+
} else {
393+
addNewPrecluster(ip, row); // start new precluster
387394
}
388395
} else {
396+
// row above should be always checked
397+
int nnb = 0, lowestIndex = curr[row - 1], lowestNb = 0, *nbrCol[4], nbrRow[4];
398+
if (lowestIndex >= 0) {
399+
nbrCol[nnb] = curr;
400+
nbrRow[nnb++] = row - 1;
401+
} else {
402+
lowestIndex = 0x7ffff;
403+
lowestNb = -1;
404+
}
389405
#ifdef _ALLOW_DIAGONAL_ALPIDE_CLUSTERS_
390-
int neighbours[]{curr[row - 1], prev[row], prev[row + 1], prev[row - 1]};
391-
#else
392-
int neighbours[]{curr[row - 1], prev[row]};
393-
#endif
394-
for (auto pci : neighbours) {
395-
if (pci < 0) {
396-
continue;
406+
for (int i : {-1, 0, 1}) {
407+
auto v = prev[row + i];
408+
if (v >= 0) {
409+
nbrCol[nnb] = prev;
410+
nbrRow[nnb] = row + i;
411+
if (v < lowestIndex) {
412+
lowestIndex = v;
413+
lowestNb = nnb;
414+
}
415+
nnb++;
397416
}
398-
if (orphan) {
399-
expandPreCluster(ip, row, pci); // attach to the adjascent precluster
400-
orphan = false;
401-
continue;
417+
}
418+
#else
419+
if (prev[row] >= 0) {
420+
nbrCol[nnb] = prev;
421+
nbrRow[nnb] = row;
422+
if (prev[row] < lowestIndex) {
423+
lowestIndex = v;
424+
lowestNb = nnb;
402425
}
403-
// reassign precluster index to smallest one
404-
if (preClusterIndices[pci] < preClusterIndices[curr[row]]) {
405-
preClusterIndices[curr[row]] = preClusterIndices[pci];
406-
} else {
407-
preClusterIndices[pci] = preClusterIndices[curr[row]];
426+
nnb++;
427+
}
428+
#endif
429+
if (!nnb) { // no neighbours, create new precluster
430+
addNewPrecluster(ip, row); // start new precluster
431+
} else {
432+
expandPreCluster(ip, row, lowestIndex); // attach to the adjascent precluster with smallest index
433+
if (nnb > 1) {
434+
for (int inb = 0; inb < nnb; inb++) { // reassign precluster index to smallest one, replicating updated values to columns caches
435+
auto& prevIndex = (nbrCol[inb])[nbrRow[inb]];
436+
prevIndex = preClusters[prevIndex].index = lowestIndex;
437+
}
408438
}
409439
}
410440
}
411-
if (orphan) {
412-
addNewPrecluster(ip, row); // start new precluster
413-
}
414441
}
415442

416443
//__________________________________________________

0 commit comments

Comments
 (0)