Skip to content

Commit 701f5c6

Browse files
committed
Add ACTSClusterer
1 parent 084d23c commit 701f5c6

File tree

8 files changed

+235
-22
lines changed

8 files changed

+235
-22
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)

Detectors/Upgrades/ALICE3/TRK/reconstruction/include/TRKReconstruction/Clusterer.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,17 @@ class Clusterer
161161
};
162162
//----------------------------------------------
163163

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:
164+
virtual 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+
protected:
175175
int mNHugeClus = 0;
176176
std::unique_ptr<ClustererThread> mThread;
177177
std::vector<int> mSortIdx; ///< reusable per-ROF sort buffer
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+
#include "TRKReconstruction/Clusterer.h"
19+
20+
namespace o2::trk
21+
{
22+
23+
class GeometryTGeo;
24+
25+
class ClustererACTS : public Clusterer
26+
{
27+
public:
28+
void process(gsl::span<const Digit> digits,
29+
gsl::span<const DigROFRecord> digitROFs,
30+
std::vector<o2::trk::Cluster>& clusters,
31+
std::vector<unsigned char>& patterns,
32+
std::vector<o2::trk::ROFRecord>& clusterROFs,
33+
const ConstDigitTruth* digitLabels = nullptr,
34+
ClusterTruth* clusterLabels = nullptr,
35+
gsl::span<const DigMC2ROFRecord> digMC2ROFs = {},
36+
std::vector<o2::trk::MC2ROFRecord>* clusterMC2ROFs = nullptr) override;
37+
38+
private:
39+
};
40+
41+
} // namespace o2::trk
42+
43+
#endif
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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.cxx
13+
/// \brief Implementation of the TRK cluster finder with the ACTS
14+
15+
#include "TRKReconstruction/ClustererACTS.h"
16+
#include "TRKBase/GeometryTGeo.h"
17+
#include <Acts/Clusterization/Clusterization.hpp>
18+
19+
#include <algorithm>
20+
#include <numeric>
21+
22+
using namespace o2::trk;
23+
24+
struct Cell2D {
25+
Cell2D(int rowv, int colv) : row(rowv), col(colv) {}
26+
int row, col;
27+
Acts::Ccl::Label label{Acts::Ccl::NO_LABEL};
28+
};
29+
30+
struct Cluster2D {
31+
std::vector<Cell2D> cells;
32+
std::size_t hash{0};
33+
};
34+
35+
//__________________________________________________
36+
void ClustererACTS::process(gsl::span<const Digit> digits,
37+
gsl::span<const DigROFRecord> digitROFs,
38+
std::vector<o2::trk::Cluster>& clusters,
39+
std::vector<unsigned char>& patterns,
40+
std::vector<o2::trk::ROFRecord>& clusterROFs,
41+
const ConstDigitTruth* digitLabels,
42+
ClusterTruth* clusterLabels,
43+
gsl::span<const DigMC2ROFRecord> digMC2ROFs,
44+
std::vector<o2::trk::MC2ROFRecord>* clusterMC2ROFs)
45+
{
46+
if (!mThread) {
47+
mThread = std::make_unique<ClustererThread>(this);
48+
}
49+
50+
auto* geom = o2::trk::GeometryTGeo::Instance();
51+
52+
for (size_t iROF = 0; iROF < digitROFs.size(); ++iROF) {
53+
const auto& inROF = digitROFs[iROF];
54+
const auto outFirst = static_cast<int>(clusters.size());
55+
const int first = inROF.getFirstEntry();
56+
const int nEntries = inROF.getNEntries();
57+
58+
if (nEntries == 0) {
59+
clusterROFs.emplace_back(inROF.getBCData(), inROF.getROFrame(), outFirst, 0);
60+
continue;
61+
}
62+
63+
// template <typename CellCollection, typename ClusterCollection,
64+
// std::size_t GridDim = 2,
65+
// typename Connect = DefaultConnect<typename CellCollection::value_type, GridDim>>
66+
// requires(GridDim == 1 || GridDim == 2)
67+
// void createClusters(Acts::Ccl::ClusteringData& data,
68+
// CellCollection& cells,
69+
// ClusterCollection& clusters,
70+
// Connect&& connect = Connect());
71+
using Cell = Cell2D;
72+
using CellCollection = std::vector<Cell>;
73+
using Cluster = Cluster2D;
74+
using ClusterCollection = std::vector<Cluster>;
75+
CellCollection cells;
76+
Acts::Ccl::ClusteringData data;
77+
ClusterCollection collection;
78+
79+
Acts::Ccl::createClusters<CellCollection, ClusterCollection,
80+
2>(data, cells, collection, Acts::Ccl::DefaultConnect<Cell, 2>(false));
81+
82+
// Sort digit indices within this ROF by (chipID, col, row) so we can process
83+
// chip by chip, column by column -- the same ordering the ALPIDE scanner expects.
84+
mSortIdx.resize(nEntries);
85+
std::iota(mSortIdx.begin(), mSortIdx.end(), first);
86+
std::sort(mSortIdx.begin(), mSortIdx.end(), [&digits](int a, int b) {
87+
const auto& da = digits[a];
88+
const auto& db = digits[b];
89+
if (da.getChipIndex() != db.getChipIndex()) {
90+
return da.getChipIndex() < db.getChipIndex();
91+
}
92+
if (da.getColumn() != db.getColumn()) {
93+
return da.getColumn() < db.getColumn();
94+
}
95+
return da.getRow() < db.getRow();
96+
});
97+
98+
// Process one chip at a time
99+
int sliceStart = 0;
100+
while (sliceStart < nEntries) {
101+
const int chipFirst = sliceStart;
102+
const uint16_t chipID = digits[mSortIdx[sliceStart]].getChipIndex();
103+
while (sliceStart < nEntries && digits[mSortIdx[sliceStart]].getChipIndex() == chipID) {
104+
++sliceStart;
105+
}
106+
const int chipN = sliceStart - chipFirst;
107+
108+
mThread->processChip(digits, chipFirst, chipN, &clusters, &patterns, digitLabels, clusterLabels, geom);
109+
}
110+
111+
clusterROFs.emplace_back(inROF.getBCData(), inROF.getROFrame(),
112+
outFirst, static_cast<int>(clusters.size()) - outFirst);
113+
}
114+
115+
if (clusterMC2ROFs && !digMC2ROFs.empty()) {
116+
clusterMC2ROFs->reserve(clusterMC2ROFs->size() + digMC2ROFs.size());
117+
for (const auto& in : digMC2ROFs) {
118+
clusterMC2ROFs->emplace_back(in.eventRecordID, in.rofRecordID, in.minROF, in.maxROF);
119+
}
120+
}
121+
}

Detectors/Upgrades/ALICE3/TRK/reconstruction/src/TRKReconstructionLinkDef.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,8 @@
1717

1818
#pragma link C++ class o2::trk::TimeFrame < 11> + ;
1919
#pragma link C++ class o2::trk::Clusterer + ;
20+
#ifdef O2_WITH_ACTS
21+
#pragma link C++ class o2::trk::ClustererACTS + ;
22+
#endif
2023

2124
#endif

Detectors/Upgrades/ALICE3/TRK/workflow/include/TRKWorkflow/ClustererSpec.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include "Framework/DataProcessorSpec.h"
1616
#include "Framework/Task.h"
1717
#include "TRKReconstruction/Clusterer.h"
18+
#ifdef O2_WITH_ACTS
19+
#include "TRKReconstruction/ClustererACTS.h"
20+
#endif
1821

1922
namespace o2::trk
2023
{
@@ -29,7 +32,13 @@ class ClustererDPL : public o2::framework::Task
2932
private:
3033
bool mUseMC = true;
3134
int mNThreads = 1;
35+
#ifdef O2_WITH_ACTS
36+
bool mUseACTS = false;
37+
#endif
3238
o2::trk::Clusterer mClusterer;
39+
#ifdef O2_WITH_ACTS
40+
o2::trk::ClustererACTS mClustererACTS;
41+
#endif
3342
};
3443

3544
o2::framework::DataProcessorSpec getClustererSpec(bool useMC);

Detectors/Upgrades/ALICE3/TRK/workflow/src/ClustererSpec.cxx

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ namespace o2::trk
2323
void ClustererDPL::init(o2::framework::InitContext& ic)
2424
{
2525
mNThreads = std::max(1, ic.options().get<int>("nthreads"));
26+
#ifdef O2_WITH_ACTS
27+
mUseACTS = ic.options().get<bool>("useACTS");
28+
#endif
2629
}
2730

2831
void ClustererDPL::run(o2::framework::ProcessingContext& pc)
@@ -48,15 +51,30 @@ void ClustererDPL::run(o2::framework::ProcessingContext& pc)
4851
}
4952
o2::base::GeometryManager::loadGeometry("o2sim_geometry.root", false, true);
5053

51-
mClusterer.process(digits,
52-
rofs,
53-
clusters,
54-
patterns,
55-
clusterROFs,
56-
mUseMC ? &labels : nullptr,
57-
clusterLabels.get(),
58-
mc2rofs,
59-
mUseMC ? &clusterMC2ROFs : nullptr);
54+
#ifdef O2_WITH_ACTS
55+
if (mUseACTS) {
56+
mClustererACTS.process(digits,
57+
rofs,
58+
clusters,
59+
patterns,
60+
clusterROFs,
61+
mUseMC ? &labels : nullptr,
62+
clusterLabels.get(),
63+
mc2rofs,
64+
mUseMC ? &clusterMC2ROFs : nullptr);
65+
} else
66+
#endif
67+
{
68+
mClusterer.process(digits,
69+
rofs,
70+
clusters,
71+
patterns,
72+
clusterROFs,
73+
mUseMC ? &labels : nullptr,
74+
clusterLabels.get(),
75+
mc2rofs,
76+
mUseMC ? &clusterMC2ROFs : nullptr);
77+
}
6078

6179
pc.outputs().snapshot(o2::framework::Output{"TRK", "COMPCLUSTERS", 0}, clusters);
6280
pc.outputs().snapshot(o2::framework::Output{"TRK", "PATTERNS", 0}, patterns);

dependencies/O2Dependencies.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ set_package_properties(fmt PROPERTIES TYPE REQUIRED)
113113
find_package(nlohmann_json)
114114
set_package_properties(nlohmann_json PROPERTIES TYPE REQUIRED)
115115

116+
find_package(Acts)
117+
set_package_properties(Acts PROPERTIES TYPE OPTIONAL)
118+
116119
find_package(Boost 1.70
117120
COMPONENTS container
118121
thread

0 commit comments

Comments
 (0)