27 float yPlaneMLOT)
noexcept
29 const uint8_t rowSpan = *patt++;
30 const uint8_t colSpan = *patt++;
31 const int nBytes = (rowSpan * colSpan + 7) / 8;
33 float cogDr{0.f}, cogDc{0.f};
34 int nPix{0}, pixIdx{0};
35 for (
int ib = 0; ib < nBytes; ib++) {
36 const uint8_t
byte = *patt++;
37 for (
int bit = 7; bit >= 0 && pixIdx < rowSpan * colSpan; bit--, pixIdx++) {
38 if (
byte & (1 << bit)) {
39 cogDr += pixIdx / colSpan;
40 cogDc += pixIdx % colSpan;
50 float x{0.f},
y{0.f},
z{0.f};
52 cluster.subDetID, cluster.layer, cluster.disk);
56 x -= cogDr * pitchRow;
57 z += cogDc * pitchCol;
59 if (cluster.subDetID == 0) {
72 gsl::span<const DigROFRecord> digitROFs,
73 std::vector<o2::trk::Cluster>&
clusters,
74 std::vector<unsigned char>& patterns,
75 std::vector<o2::trk::ROFRecord>& clusterROFs,
78 gsl::span<const DigMC2ROFRecord> digMC2ROFs,
79 std::vector<o2::trk::MC2ROFRecord>* clusterMC2ROFs)
82 mThread = std::make_unique<ClustererThread>(
this);
87 for (
size_t iROF = 0; iROF < digitROFs.size(); ++iROF) {
88 const auto& inROF = digitROFs[iROF];
89 const auto outFirst =
static_cast<int>(
clusters.size());
90 const int first = inROF.getFirstEntry();
91 const int nEntries = inROF.getNEntries();
94 clusterROFs.emplace_back(inROF.getBCData(), inROF.getROFrame(), outFirst, 0);
103 const auto& da = digits[a];
104 const auto& db = digits[b];
105 if (da.getChipIndex() != db.getChipIndex()) {
106 return da.getChipIndex() < db.getChipIndex();
108 if (da.getColumn() != db.getColumn()) {
109 return da.getColumn() < db.getColumn();
111 return da.getRow() < db.getRow();
116 while (sliceStart < nEntries) {
117 const int chipFirst = sliceStart;
118 const uint16_t chipID =
digits[
mSortIdx[sliceStart]].getChipIndex();
119 while (sliceStart < nEntries &&
digits[
mSortIdx[sliceStart]].getChipIndex() == chipID) {
122 const int chipN = sliceStart - chipFirst;
124 mThread->processChip(
digits, chipFirst, chipN, &
clusters, &patterns, digitLabels, clusterLabels, geom);
127 clusterROFs.emplace_back(inROF.getBCData(), inROF.getROFrame(),
128 outFirst,
static_cast<int>(
clusters.size()) - outFirst);
131 if (clusterMC2ROFs && !digMC2ROFs.empty()) {
132 clusterMC2ROFs->reserve(clusterMC2ROFs->size() + digMC2ROFs.size());
133 for (
const auto& in : digMC2ROFs) {
134 clusterMC2ROFs->emplace_back(in.eventRecordID, in.rofRecordID, in.minROF, in.maxROF);
140void Clusterer::ClustererThread::processChip(gsl::span<const Digit>
digits,
141 int chipFirst,
int chipN,
142 std::vector<Cluster>* clustersOut,
143 std::vector<unsigned char>* patternsOut,
151 const auto& sortIdx = parent->mSortIdx;
154 finishChipSingleHitFast(
digits, sortIdx[chipFirst], labelsDigPtr, labelsClusPtr, geom);
156 initChip(
digits, sortIdx[chipFirst], geom);
157 for (
int i = chipFirst + 1;
i < chipFirst + chipN; ++
i) {
158 updateChip(
digits, sortIdx[
i]);
160 finishChip(
digits, labelsDigPtr, labelsClusPtr, geom);
168 if (!patterns.empty()) {
169 patternsOut->insert(patternsOut->end(), patterns.begin(), patterns.end());
181 const uint16_t chipID =
digits[
first].getChipIndex();
184 size = constants::moduleMLOT::chip::nRows + 2;
188 size = constants::VD::petal::layer::nRows[
layer] + 2;
194 column1 =
new int[
size];
195 column2 =
new int[
size];
196 column1[0] = column1[
size - 1] = -1;
197 column2[0] = column2[
size - 1] = -1;
203 preClusterHeads.clear();
204 preClusterIndices.clear();
207 currCol = pix.getColumn();
208 curr[pix.getRow()] = 0;
209 preClusterHeads.push_back(0);
210 preClusterIndices.push_back(0);
216void Clusterer::ClustererThread::updateChip(gsl::span<const Digit>
digits, uint32_t ip)
218 const auto& pix =
digits[ip];
219 uint16_t
row = pix.getRow();
221 if (currCol != pix.getColumn()) {
225 if (pix.getColumn() > currCol + 1) {
227 currCol = pix.getColumn();
228 addNewPreCluster(ip,
row);
232 currCol = pix.getColumn();
238 if (curr[
row - 1] >= 0) {
239 expandPreCluster(ip,
row, curr[
row - 1]);
243#ifdef _ALLOW_DIAGONAL_TRK_CLUSTERS_
244 int neighbours[]{curr[
row - 1], prev[
row], prev[
row + 1], prev[
row - 1]};
246 int neighbours[]{curr[
row - 1], prev[
row]};
248 for (
auto pci : neighbours) {
253 expandPreCluster(ip,
row, pci);
258 if (preClusterIndices[pci] < preClusterIndices[curr[
row]]) {
259 preClusterIndices[curr[
row]] = preClusterIndices[pci];
261 preClusterIndices[pci] = preClusterIndices[curr[
row]];
266 addNewPreCluster(ip,
row);
271void Clusterer::ClustererThread::finishChip(gsl::span<const Digit>
digits,
276 const uint16_t chipID =
digits[
pixels[0].second].getChipIndex();
278 for (
size_t i1 = 0; i1 < preClusterHeads.size(); ++i1) {
279 auto ci = preClusterIndices[i1];
285 uint32_t totalCharge = 0;
292 const auto& pixEntry =
pixels[next];
293 const auto& d =
digits[pixEntry.second];
294 uint16_t
r = d.getRow(),
c = d.getColumn();
295 pixArrBuff.emplace_back(
r,
c);
297 totalCharge += d.getCharge();
299 fetchMCLabels(pixEntry.second, labelsDigPtr, nlab);
301 next = pixEntry.first;
306 preClusterIndices[i1] = -1;
308 for (
size_t i2 = i1 + 1; i2 < preClusterHeads.size(); ++i2) {
309 if (preClusterIndices[i2] != ci) {
313 preClusterIndices[i2] = -1;
317 int subDetID = -1,
layer = -1, disk = -1;
324 const bool doLabels = (labelsClusPtr !=
nullptr);
325 if (
bbox.isAcceptableSize()) {
326 streamCluster(
bbox, pixArrBuff, totalCharge, doLabels, nlab, chipID, subDetID,
layer, disk);
329 auto warnLeft = MaxHugeClusWarn - parent->mNHugeClus;
331 LOGP(warn,
"Splitting huge TRK cluster: chipID {}, rows {}:{} cols {}:{}{}",
333 warnLeft == 1 ?
" (further warnings muted)" :
"");
334 parent->mNHugeClus++;
343 std::vector<std::pair<uint16_t, uint16_t>> subPix;
344 uint32_t subCharge = 0;
345 for (
const auto& [
r,
c] : pixArrBuff) {
347 subPix.emplace_back(
r,
c);
351 if (!subPix.empty()) {
352 streamCluster(bboxT, subPix, subCharge, doLabels, nlab, chipID, subDetID,
layer, disk);
364void Clusterer::ClustererThread::finishChipSingleHitFast(gsl::span<const Digit>
digits, uint32_t hit,
369 const auto& d =
digits[hit];
370 const uint16_t chipID = d.getChipIndex();
371 const uint16_t
row = d.getRow();
372 const uint16_t
col = d.getColumn();
376 fetchMCLabels(hit, labelsDigPtr, nlab);
377 const auto cnt =
static_cast<uint32_t
>(
clusters.size());
378 for (
int i = nlab;
i--;) {
379 labels.addElement(cnt, labelsBuff[
i]);
384 patterns.emplace_back(1);
385 patterns.emplace_back(1);
386 patterns.emplace_back(0x80);
402void Clusterer::ClustererThread::streamCluster(
const BBox&
bbox,
403 const std::vector<std::pair<uint16_t, uint16_t>>& pixbuf,
404 uint32_t totalCharge,
405 bool doLabels,
int nlab,
406 uint16_t chipID,
int subDetID,
int layer,
int disk)
409 const auto cnt =
static_cast<uint32_t
>(
clusters.size());
410 for (
int i = nlab;
i--;) {
411 labels.addElement(cnt, labelsBuff[
i]);
415 const uint16_t rowSpanW =
bbox.rowSpan();
416 const uint16_t colSpanW =
bbox.colSpan();
419 std::array<unsigned char, o2::itsmft::ClusterPattern::MaxPatternBytes> patt{};
420 for (
const auto& [
r,
c] : pixbuf) {
422 int nbit =
ir * colSpanW + ic;
423 patt[nbit >> 3] |= (0x1 << (7 - (nbit % 8)));
425 patterns.emplace_back(
static_cast<unsigned char>(rowSpanW));
426 patterns.emplace_back(
static_cast<unsigned char>(colSpanW));
427 int nBytes = (rowSpanW * colSpanW + 7) / 8;
428 patterns.insert(patterns.end(), patt.begin(), patt.begin() + nBytes);
434 cluster.
size =
static_cast<uint16_t
>(pixbuf.size());
435 cluster.
subDetID =
static_cast<int16_t
>(subDetID);
437 cluster.
disk =
static_cast<int16_t
>(disk);
442void Clusterer::ClustererThread::fetchMCLabels(uint32_t digID,
const ConstDigitTruth* labelsDig,
int& nfilled)
444 if (nfilled >= MaxLabels) {
450 const auto& lbls = labelsDig->
getLabels(digID);
451 for (
int i = lbls.size();
i--;) {
454 if (labelsBuff[ic] == lbls[
i]) {
458 labelsBuff[nfilled++] = lbls[
i];
459 if (nfilled >= MaxLabels) {
std::vector< std::string > labels
int collectPixels(int which, int N, double *xyDxy, double *q)
Definition of the SegmentationChipclass.
Definition of the TRK cluster finder.
static constexpr uint8_t MaxRowSpan
static constexpr uint8_t MaxColSpan
static o2::math_utils::Point3D< float > getClusterLocalCoordinates(const Cluster &cluster, const uint8_t *patt, float yPlaneMLOT=0.f) noexcept
std::unique_ptr< ClustererThread > mThread
virtual 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)
std::vector< int > mSortIdx
reusable per-ROF sort buffer
int getSubDetID(int index) const
int getLayer(int index) const
local layer index within the sub-detector (0-based per VD/MLOT)
int getDisk(int index) const
static GeometryTGeo * Instance()
static constexpr math_utils::Vector2D< float > flatToCurved(int layer, float xFlat, float yFlat) noexcept
static void detectorToLocalUnchecked(int row, int col, float &xRow, float &zCol, int subDetID, int layer, int disk) noexcept
static constexpr float PitchColVD
static constexpr float PitchColMLOT
static constexpr float PitchRowMLOT
static constexpr float PitchRowVD
GLboolean GLboolean GLboolean b
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
GLenum GLuint GLint GLint layer
GLboolean GLboolean GLboolean GLboolean a
GLdouble GLdouble GLdouble z
bool isInside(uint16_t r, uint16_t c) const
o2::InteractionRecord ir(0, 0)
std::vector< Cluster > clusters
std::vector< Digit > digits