Skip to content

Commit 4281d17

Browse files
committed
Add ACTSClusterer
1 parent 084d23c commit 4281d17

File tree

7 files changed

+662
-11
lines changed

7 files changed

+662
-11
lines changed

Detectors/Upgrades/ALICE3/TRK/reconstruction/CMakeLists.txt

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,15 @@
99
# granted to it by virtue of its status as an Intergovernmental Organization
1010
# or submit itself to any jurisdiction.
1111

12+
if(Acts_FOUND)
13+
set(actsTarget Acts::Core)
14+
endif()
15+
1216
o2_add_library(TRKReconstruction
1317
TARGETVARNAME targetName
1418
SOURCES src/TimeFrame.cxx
1519
src/Clusterer.cxx
20+
$<$<BOOL:${Acts_FOUND}>:src/ClustererACTS.cxx>
1621
PUBLIC_LINK_LIBRARIES
1722
O2::ITStracking
1823
O2::GPUCommon
@@ -27,11 +32,22 @@ o2_add_library(TRKReconstruction
2732
O2::DataFormatsITS
2833
O2::TRKSimulation
2934
nlohmann_json::nlohmann_json
35+
${actsTarget}
3036
PRIVATE_LINK_LIBRARIES
3137
O2::Steer
3238
TBB::tbb)
3339

40+
if(Acts_FOUND)
41+
target_compile_definitions(${targetName} PUBLIC O2_WITH_ACTS)
42+
endif()
43+
44+
set(dictHeaders include/TRKReconstruction/TimeFrame.h
45+
include/TRKReconstruction/Clusterer.h)
46+
47+
if(Acts_FOUND)
48+
list(APPEND dictHeaders include/TRKReconstruction/ClustererACTS.h)
49+
endif()
50+
3451
o2_target_root_dictionary(TRKReconstruction
35-
HEADERS include/TRKReconstruction/TimeFrame.h
36-
include/TRKReconstruction/Clusterer.h
52+
HEADERS ${dictHeaders}
3753
LINKDEF src/TRKReconstructionLinkDef.h)
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
// Copyright 2019-2026 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+
12+
/// \file ClustererACTS.h
13+
/// \brief Definition of the TRK cluster finder
14+
15+
#ifndef ALICEO2_TRK_CLUSTERERACTS_H
16+
#define ALICEO2_TRK_CLUSTERERACTS_H
17+
18+
// uncomment to allow diagonal clusters, e.g. |* |
19+
// | *|
20+
#define _ALLOW_DIAGONAL_TRK_CLUSTERS_
21+
22+
#include "DataFormatsITSMFT/Digit.h"
23+
#include "DataFormatsITSMFT/ROFRecord.h"
24+
#include "DataFormatsITSMFT/ClusterPattern.h"
25+
#include "DataFormatsTRK/Cluster.h"
26+
#include "DataFormatsTRK/ROFRecord.h"
27+
#include "SimulationDataFormat/ConstMCTruthContainer.h"
28+
#include "SimulationDataFormat/MCCompLabel.h"
29+
#include "SimulationDataFormat/MCTruthContainer.h"
30+
#include "TRKBase/Specs.h"
31+
#include <gsl/span>
32+
#include <vector>
33+
#include <array>
34+
#include <memory>
35+
#include <cstring>
36+
#include <utility>
37+
38+
namespace o2::trk
39+
{
40+
41+
class GeometryTGeo;
42+
43+
class ClustererACTS
44+
{
45+
public:
46+
static constexpr int MaxLabels = 10;
47+
static constexpr int MaxHugeClusWarn = 5;
48+
49+
using Digit = o2::itsmft::Digit;
50+
using DigROFRecord = o2::itsmft::ROFRecord;
51+
using DigMC2ROFRecord = o2::itsmft::MC2ROFRecord;
52+
using ClusterTruth = o2::dataformats::MCTruthContainer<o2::MCCompLabel>;
53+
using ConstDigitTruth = o2::dataformats::ConstMCTruthContainerView<o2::MCCompLabel>;
54+
using Label = o2::MCCompLabel;
55+
56+
//----------------------------------------------
57+
struct BBox {
58+
uint16_t chipID = 0xffff;
59+
uint16_t rowMin = 0xffff, colMin = 0xffff;
60+
uint16_t rowMax = 0, colMax = 0;
61+
explicit BBox(uint16_t c) : chipID(c) {}
62+
bool isInside(uint16_t r, uint16_t c) const { return r >= rowMin && r <= rowMax && c >= colMin && c <= colMax; }
63+
uint16_t rowSpan() const { return rowMax - rowMin + 1; }
64+
uint16_t colSpan() const { return colMax - colMin + 1; }
65+
bool isAcceptableSize() const
66+
{
67+
return rowSpan() <= o2::itsmft::ClusterPattern::MaxRowSpan &&
68+
colSpan() <= o2::itsmft::ClusterPattern::MaxColSpan;
69+
}
70+
void adjust(uint16_t r, uint16_t c)
71+
{
72+
if (r < rowMin) {
73+
rowMin = r;
74+
}
75+
if (r > rowMax) {
76+
rowMax = r;
77+
}
78+
if (c < colMin) {
79+
colMin = c;
80+
}
81+
if (c > colMax) {
82+
colMax = c;
83+
}
84+
}
85+
};
86+
87+
//----------------------------------------------
88+
struct ClustererThread {
89+
ClustererACTS* parent = nullptr;
90+
// column buffers (pre-cluster state); extra sentinel entries at [0] and [size-1]
91+
int* column1 = nullptr;
92+
int* column2 = nullptr;
93+
int* curr = nullptr; ///< current column pre-cluster indices
94+
int* prev = nullptr; ///< previous column pre-cluster indices
95+
int size = constants::moduleMLOT::chip::nRows + 2; ///< reallocated per chip in initChip
96+
97+
// pixels[i] = {next_in_chain, global_digit_index}
98+
std::vector<std::pair<int, uint32_t>> pixels;
99+
std::vector<int> preClusterHeads;
100+
std::vector<int> preClusterIndices;
101+
uint16_t currCol = 0xffff;
102+
bool noLeftCol = true;
103+
104+
std::array<Label, MaxLabels> labelsBuff; ///< MC label buffer for one cluster
105+
std::vector<std::pair<uint16_t, uint16_t>> pixArrBuff; ///< (row,col) pixel buffer for pattern
106+
107+
// per-thread output (accumulated, then merged back by caller)
108+
std::vector<Cluster> clusters;
109+
std::vector<unsigned char> patterns;
110+
ClusterTruth labels;
111+
112+
///< reset column buffer
113+
void resetColumn(int* buff) const { std::memset(buff, -1, sizeof(int) * (size - 2)); }
114+
///< swap current and previous column buffers
115+
void swapColumnBuffers() { std::swap(prev, curr); }
116+
117+
///< append pixel ip to the pre-cluster headed at preClusterIndex
118+
void expandPreCluster(uint32_t ip, uint16_t row, int preClusterIndex)
119+
{
120+
auto& firstIndex = preClusterHeads[preClusterIndices[preClusterIndex]];
121+
pixels.emplace_back(firstIndex, ip);
122+
firstIndex = pixels.size() - 1;
123+
curr[row] = preClusterIndex;
124+
}
125+
126+
///< start a new pre-cluster with pixel ip at given row
127+
void addNewPreCluster(uint32_t ip, uint16_t row)
128+
{
129+
preClusterHeads.push_back(pixels.size());
130+
pixels.emplace_back(-1, ip);
131+
int lastIndex = preClusterIndices.size();
132+
preClusterIndices.push_back(lastIndex);
133+
curr[row] = lastIndex;
134+
}
135+
136+
void fetchMCLabels(uint32_t digID, const ConstDigitTruth* labelsDig, int& nfilled);
137+
void initChip(gsl::span<const Digit> digits, uint32_t first, GeometryTGeo* geom);
138+
void updateChip(gsl::span<const Digit> digits, uint32_t ip);
139+
void finishChip(gsl::span<const Digit> digits,
140+
const ConstDigitTruth* labelsDigPtr, ClusterTruth* labelsClusPtr,
141+
GeometryTGeo* geom);
142+
void finishChipSingleHitFast(gsl::span<const Digit> digits, uint32_t hit,
143+
const ConstDigitTruth* labelsDigPtr, ClusterTruth* labelsClusPtr,
144+
GeometryTGeo* geom);
145+
void processChip(gsl::span<const Digit> digits, int chipFirst, int chipN,
146+
std::vector<Cluster>* clustersOut, std::vector<unsigned char>* patternsOut,
147+
const ConstDigitTruth* labelsDigPtr, ClusterTruth* labelsClusPtr,
148+
GeometryTGeo* geom);
149+
void streamCluster(const BBox& bbox, const std::vector<std::pair<uint16_t, uint16_t>>& pixbuf,
150+
uint32_t totalCharge, bool doLabels, int nlab,
151+
uint16_t chipID, int subDetID, int layer, int disk);
152+
153+
~ClustererThread()
154+
{
155+
delete[] column1;
156+
delete[] column2;
157+
}
158+
explicit ClustererThread(ClustererACTS* par = nullptr) : parent(par) {}
159+
ClustererThread(const ClustererThread&) = delete;
160+
ClustererThread& operator=(const ClustererThread&) = delete;
161+
};
162+
//----------------------------------------------
163+
164+
void process(gsl::span<const Digit> digits,
165+
gsl::span<const DigROFRecord> digitROFs,
166+
std::vector<o2::trk::Cluster>& clusters,
167+
std::vector<unsigned char>& patterns,
168+
std::vector<o2::trk::ROFRecord>& clusterROFs,
169+
const ConstDigitTruth* digitLabels = nullptr,
170+
ClusterTruth* clusterLabels = nullptr,
171+
gsl::span<const DigMC2ROFRecord> digMC2ROFs = {},
172+
std::vector<o2::trk::MC2ROFRecord>* clusterMC2ROFs = nullptr);
173+
174+
private:
175+
int mNHugeClus = 0;
176+
std::unique_ptr<ClustererThread> mThread;
177+
std::vector<int> mSortIdx; ///< reusable per-ROF sort buffer
178+
};
179+
180+
} // namespace o2::trk
181+
182+
#endif

0 commit comments

Comments
 (0)