26 gsl::span<const DigROFRecord> digitROFs,
27 std::vector<o2::trk::Cluster>&
clusters,
28 std::vector<unsigned char>& patterns,
29 std::vector<o2::trk::ROFRecord>& clusterROFs,
32 gsl::span<const DigMC2ROFRecord> digMC2ROFs,
33 std::vector<o2::trk::MC2ROFRecord>* clusterMC2ROFs)
36 mThread = std::make_unique<ClustererThread>(
this);
41 for (
size_t iROF = 0; iROF < digitROFs.size(); ++iROF) {
42 const auto& inROF = digitROFs[iROF];
43 const auto outFirst =
static_cast<int>(
clusters.size());
44 const int first = inROF.getFirstEntry();
45 const int nEntries = inROF.getNEntries();
48 clusterROFs.emplace_back(inROF.getBCData(), inROF.getROFrame(), outFirst, 0);
54 mSortIdx.resize(nEntries);
55 std::iota(mSortIdx.begin(), mSortIdx.end(),
first);
56 std::sort(mSortIdx.begin(), mSortIdx.end(), [&
digits](
int a,
int b) {
57 const auto& da = digits[a];
58 const auto& db = digits[b];
59 if (da.getChipIndex() != db.getChipIndex()) {
60 return da.getChipIndex() < db.getChipIndex();
62 if (da.getColumn() != db.getColumn()) {
63 return da.getColumn() < db.getColumn();
65 return da.getRow() < db.getRow();
70 while (sliceStart < nEntries) {
71 const int chipFirst = sliceStart;
72 const uint16_t chipID =
digits[mSortIdx[sliceStart]].getChipIndex();
73 while (sliceStart < nEntries &&
digits[mSortIdx[sliceStart]].getChipIndex() == chipID) {
76 const int chipN = sliceStart - chipFirst;
78 mThread->processChip(
digits, chipFirst, chipN, &
clusters, &patterns, digitLabels, clusterLabels, geom);
81 clusterROFs.emplace_back(inROF.getBCData(), inROF.getROFrame(),
82 outFirst,
static_cast<int>(
clusters.size()) - outFirst);
85 if (clusterMC2ROFs && !digMC2ROFs.empty()) {
86 clusterMC2ROFs->reserve(clusterMC2ROFs->size() + digMC2ROFs.size());
87 for (
const auto& in : digMC2ROFs) {
88 clusterMC2ROFs->emplace_back(in.eventRecordID, in.rofRecordID, in.minROF, in.maxROF);
94void Clusterer::ClustererThread::processChip(gsl::span<const Digit>
digits,
95 int chipFirst,
int chipN,
96 std::vector<Cluster>* clustersOut,
97 std::vector<unsigned char>* patternsOut,
105 const auto& sortIdx = parent->mSortIdx;
108 finishChipSingleHitFast(
digits, sortIdx[chipFirst], labelsDigPtr, labelsClusPtr, geom);
110 initChip(
digits, sortIdx[chipFirst], geom);
111 for (
int i = chipFirst + 1;
i < chipFirst + chipN; ++
i) {
112 updateChip(
digits, sortIdx[
i]);
114 finishChip(
digits, labelsDigPtr, labelsClusPtr, geom);
122 if (!patterns.empty()) {
123 patternsOut->insert(patternsOut->end(), patterns.begin(), patterns.end());
135 const uint16_t chipID =
digits[
first].getChipIndex();
138 size = constants::moduleMLOT::chip::nRows + 2;
142 size = constants::VD::petal::layer::nRows[
layer] + 2;
148 column1 =
new int[
size];
149 column2 =
new int[
size];
150 column1[0] = column1[
size - 1] = -1;
151 column2[0] = column2[
size - 1] = -1;
157 preClusterHeads.clear();
158 preClusterIndices.clear();
161 currCol = pix.getColumn();
162 curr[pix.getRow()] = 0;
163 preClusterHeads.push_back(0);
164 preClusterIndices.push_back(0);
170void Clusterer::ClustererThread::updateChip(gsl::span<const Digit>
digits, uint32_t ip)
172 const auto& pix =
digits[ip];
173 uint16_t
row = pix.getRow();
175 if (currCol != pix.getColumn()) {
179 if (pix.getColumn() > currCol + 1) {
181 currCol = pix.getColumn();
182 addNewPreCluster(ip,
row);
186 currCol = pix.getColumn();
192 if (curr[
row - 1] >= 0) {
193 expandPreCluster(ip,
row, curr[
row - 1]);
197#ifdef _ALLOW_DIAGONAL_TRK_CLUSTERS_
198 int neighbours[]{curr[
row - 1], prev[
row], prev[
row + 1], prev[
row - 1]};
200 int neighbours[]{curr[
row - 1], prev[
row]};
202 for (
auto pci : neighbours) {
207 expandPreCluster(ip,
row, pci);
212 if (preClusterIndices[pci] < preClusterIndices[curr[
row]]) {
213 preClusterIndices[curr[
row]] = preClusterIndices[pci];
215 preClusterIndices[pci] = preClusterIndices[curr[
row]];
220 addNewPreCluster(ip,
row);
225void Clusterer::ClustererThread::finishChip(gsl::span<const Digit>
digits,
230 const uint16_t chipID =
digits[
pixels[0].second].getChipIndex();
232 for (
size_t i1 = 0; i1 < preClusterHeads.size(); ++i1) {
233 auto ci = preClusterIndices[i1];
239 uint32_t totalCharge = 0;
246 const auto& pixEntry =
pixels[next];
247 const auto& d =
digits[pixEntry.second];
248 uint16_t
r = d.getRow(),
c = d.getColumn();
249 pixArrBuff.emplace_back(
r,
c);
251 totalCharge += d.getCharge();
253 fetchMCLabels(pixEntry.second, labelsDigPtr, nlab);
255 next = pixEntry.first;
260 preClusterIndices[i1] = -1;
262 for (
size_t i2 = i1 + 1; i2 < preClusterHeads.size(); ++i2) {
263 if (preClusterIndices[i2] != ci) {
267 preClusterIndices[i2] = -1;
271 int subDetID = -1,
layer = -1, disk = -1;
278 const bool doLabels = (labelsClusPtr !=
nullptr);
279 if (
bbox.isAcceptableSize()) {
280 streamCluster(
bbox, pixArrBuff, totalCharge, doLabels, nlab, chipID, subDetID,
layer, disk);
283 auto warnLeft = MaxHugeClusWarn - parent->mNHugeClus;
285 LOGP(warn,
"Splitting huge TRK cluster: chipID {}, rows {}:{} cols {}:{}{}",
287 warnLeft == 1 ?
" (further warnings muted)" :
"");
288 parent->mNHugeClus++;
297 std::vector<std::pair<uint16_t, uint16_t>> subPix;
298 uint32_t subCharge = 0;
299 for (
const auto& [
r,
c] : pixArrBuff) {
301 subPix.emplace_back(
r,
c);
305 if (!subPix.empty()) {
306 streamCluster(bboxT, subPix, subCharge, doLabels, nlab, chipID, subDetID,
layer, disk);
318void Clusterer::ClustererThread::finishChipSingleHitFast(gsl::span<const Digit>
digits, uint32_t hit,
323 const auto& d =
digits[hit];
324 const uint16_t chipID = d.getChipIndex();
325 const uint16_t
row = d.getRow();
326 const uint16_t
col = d.getColumn();
330 fetchMCLabels(hit, labelsDigPtr, nlab);
331 const auto cnt =
static_cast<uint32_t
>(
clusters.size());
332 for (
int i = nlab;
i--;) {
333 labels.addElement(cnt, labelsBuff[
i]);
338 patterns.emplace_back(1);
339 patterns.emplace_back(1);
340 patterns.emplace_back(0x80);
356void Clusterer::ClustererThread::streamCluster(
const BBox&
bbox,
357 const std::vector<std::pair<uint16_t, uint16_t>>& pixbuf,
358 uint32_t totalCharge,
359 bool doLabels,
int nlab,
360 uint16_t chipID,
int subDetID,
int layer,
int disk)
363 const auto cnt =
static_cast<uint32_t
>(
clusters.size());
364 for (
int i = nlab;
i--;) {
365 labels.addElement(cnt, labelsBuff[
i]);
369 const uint16_t rowSpanW =
bbox.rowSpan();
370 const uint16_t colSpanW =
bbox.colSpan();
373 std::array<unsigned char, o2::itsmft::ClusterPattern::MaxPatternBytes> patt{};
374 for (
const auto& [
r,
c] : pixbuf) {
376 int nbit =
ir * colSpanW + ic;
377 patt[nbit >> 3] |= (0x1 << (7 - (nbit % 8)));
379 patterns.emplace_back(
static_cast<unsigned char>(rowSpanW));
380 patterns.emplace_back(
static_cast<unsigned char>(colSpanW));
381 int nBytes = (rowSpanW * colSpanW + 7) / 8;
382 patterns.insert(patterns.end(), patt.begin(), patt.begin() + nBytes);
388 cluster.
size =
static_cast<uint16_t
>(pixbuf.size());
389 cluster.
subDetID =
static_cast<int16_t
>(subDetID);
391 cluster.
disk =
static_cast<int16_t
>(disk);
void process(gsl::span< const Digit > digits, gsl::span< const DigROFRecord > digitROFs, std::vector< o2::trk::Cluster > &clusters, std::vector< unsigned char > &patterns, std::vector< o2::trk::ROFRecord > &clusterROFs, const ConstDigitTruth *digitLabels=nullptr, ClusterTruth *clusterLabels=nullptr, gsl::span< const DigMC2ROFRecord > digMC2ROFs={}, std::vector< o2::trk::MC2ROFRecord > *clusterMC2ROFs=nullptr)