Project
Loading...
Searching...
No Matches
TrackerACTS.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 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
18
20
21#include <Acts/EventData/Seed.hpp>
22#include <Acts/EventData/SpacePointContainer.hpp>
23#include <Acts/Seeding/BinnedGroup.hpp>
24#include <Acts/Seeding/SeedFilter.hpp>
25#include <Acts/Seeding/SeedFilterConfig.hpp>
26#include <Acts/Seeding/SeedFinder.hpp>
27#include <Acts/Seeding/SeedFinderConfig.hpp>
28#include <Acts/Seeding/detail/CylindricalSpacePointGrid.hpp>
29#include <Acts/Utilities/GridBinFinder.hpp>
30#include <Acts/Utilities/RangeXD.hpp>
31
32namespace o2::trk
33{
34
35template <int nLayers>
37{
38 // Initialize space points storage per layer
39 mSpacePointsPerLayer.resize(nLayers);
40 mHistSpacePoints = new TH2F("hSpacePoints", "Space points; x (cm); y (cm)", 200, -100, 100, 200, -100, 100);
41}
42
43template <int nLayers>
48
49template <int nLayers>
51{
52 mSpacePoints.clear();
53 for (auto& layerSPs : mSpacePointsPerLayer) {
54 layerSPs.clear();
55 }
56
57 // Get clusters from the TimeFrame and convert to space points
58 for (int layer = 0; layer < nLayers; ++layer) {
59 // For now we take unsorted clusters, as soon as the cluster trackin is in place we can piggy back on it and switch to the clusters
60 auto clusters = mTimeFrame->getUnsortedClusters()[layer];
61 // Resize the clusters to the first 100 clusters for testing
62 // clusters = clusters.subspan(0, std::min<size_t>(clusters.size(), 100));
63 LOG(debug) << "ACTSTracker: got " << clusters.size() << " clusters";
64
65 for (size_t iCluster = 0; iCluster < clusters.size(); ++iCluster) {
66 const auto& cluster = clusters[iCluster];
67
68 SpacePoint sp;
69 // Check that these are in global coordinates
70 sp.x = cluster.xCoordinate * Acts::UnitConstants::cm;
71 sp.y = cluster.yCoordinate * Acts::UnitConstants::cm;
72 sp.z = cluster.zCoordinate * Acts::UnitConstants::cm;
73
74 if (mHistSpacePoints) {
75 mHistSpacePoints->Fill(sp.x / Acts::UnitConstants::cm, sp.y / Acts::UnitConstants::cm);
76 }
77 sp.layer = layer;
78 sp.clusterId = static_cast<int>(iCluster);
79 sp.rof = rof;
80
81 // Position uncertainties (could be refined based on cluster properties)
82 sp.varianceR = 0.01f; // ~100 um resolution squared
83 sp.varianceZ = 0.01f;
84
85 mSpacePoints.push_back(sp);
86 }
87 }
88
89 // Build per-layer pointers for seeding
90 for (auto& sp : mSpacePoints) {
91 if (sp.layer >= 0 && sp.layer < nLayers) {
92 mSpacePointsPerLayer[sp.layer].push_back(&sp);
93 }
94 }
95}
96
97template <int nLayers>
98void TrackerACTS<nLayers>::createSeeds()
99{
100 if (mSpacePoints.empty()) {
101 LOGF(info, "No space points available for seeding");
102 return;
103 }
104 mSeeds.clear();
105
106 // Backend adaptor that exposes mSpacePoints to Acts::SpacePointContainer
107 struct SpacePointBackend {
108 using ValueType = SpacePoint;
109 explicit SpacePointBackend(const std::vector<SpacePoint>& sps) : m_sps{&sps} {}
110 std::size_t size_impl() const { return m_sps->size(); }
111 float x_impl(std::size_t i) const { return (*m_sps)[i].x; }
112 float y_impl(std::size_t i) const { return (*m_sps)[i].y; }
113 float z_impl(std::size_t i) const { return (*m_sps)[i].z; }
114 float varianceR_impl(std::size_t i) const { return (*m_sps)[i].varianceR; }
115 float varianceZ_impl(std::size_t i) const { return (*m_sps)[i].varianceZ; }
116 const SpacePoint& get_impl(std::size_t i) const { return (*m_sps)[i]; }
117 std::any component_impl(Acts::HashedString /*key*/, std::size_t /*i*/) const
118 {
119 LOG(fatal) << "No additional components available for space points";
120 throw std::runtime_error("SpacePointBackend: no strip component available");
121 }
122 const std::vector<SpacePoint>* m_sps;
123 };
124
125 // Wrap mSpacePoints in an Acts space-point container
126 SpacePointBackend backend{mSpacePoints};
127
128 // Configure the ACTS space point container
129 Acts::SpacePointContainerConfig spContainerConfig;
130 Acts::SpacePointContainerOptions spContainerOpts;
131 spContainerOpts.beamPos = {0.f, 0.f};
132 Acts::SpacePointContainer<SpacePointBackend, Acts::detail::RefHolder> spContainer{spContainerConfig, spContainerOpts, backend};
133
134 // Configure the ACTS seed finder
135 const unsigned int maxSeeds = static_cast<unsigned int>(mConfig.maxSeedsPerMiddleSP);
136 Acts::SeedFilterConfig filterConfig;
137 filterConfig.maxSeedsPerSpM = maxSeeds;
138
139 // ACTS requires minPt / bFieldInZ >= rMax / 2 (minHelixRadius >= rMax/2).
140 // Cap rMax so that the constraint is satisfied for the configured minPt and field.
141 const float bFieldInZ = mBz * Acts::UnitConstants::T;
142 const float safeRMax = 1.8f * mConfig.minPt / bFieldInZ; // 10% margin below the hard limit
143
144 using SPProxy = typename Acts::SpacePointContainer<SpacePointBackend, Acts::detail::RefHolder>::SpacePointProxyType;
145 Acts::SeedFinderConfig<SPProxy> finderConfig;
146 finderConfig.rMin = 0.f;
147 finderConfig.rMax = 100.f * Acts::UnitConstants::cm;
148 finderConfig.zMin = mConfig.zMin;
149 finderConfig.zMax = mConfig.zMax;
150 finderConfig.deltaRMin = std::min(mConfig.deltaRMinBottom, mConfig.deltaRMinTop);
151 finderConfig.deltaRMax = std::max(mConfig.deltaRMaxBottom, mConfig.deltaRMaxTop);
152 finderConfig.deltaRMinBottomSP = mConfig.deltaRMinBottom;
153 finderConfig.deltaRMaxBottomSP = mConfig.deltaRMaxBottom;
154 finderConfig.deltaRMinTopSP = mConfig.deltaRMinTop;
155 finderConfig.deltaRMaxTopSP = mConfig.deltaRMaxTop;
156 finderConfig.collisionRegionMin = mConfig.collisionRegionMin;
157 finderConfig.collisionRegionMax = mConfig.collisionRegionMax;
158 finderConfig.cotThetaMax = mConfig.cotThetaMax;
159 finderConfig.minPt = mConfig.minPt;
160 finderConfig.impactMax = mConfig.maxImpactParameter;
161 finderConfig.maxSeedsPerSpM = maxSeeds;
162 finderConfig.sigmaScattering = 5.f;
163 finderConfig.radLengthPerSeed = 0.05f;
164 finderConfig.seedFilter = std::make_shared<Acts::SeedFilter<SPProxy>>(filterConfig);
165 finderConfig = finderConfig.calculateDerivedQuantities();
166 Acts::SeedFinder<SPProxy, Acts::CylindricalSpacePointGrid<SPProxy>> seedFinder{finderConfig,
167 Acts::getDefaultLogger("Finder", Acts::Logging::Level::VERBOSE)};
168
169 // Configure and create the cylindrical space-point grid
170 Acts::CylindricalSpacePointGridConfig gridConfig;
171 gridConfig.minPt = finderConfig.minPt;
172 gridConfig.rMin = finderConfig.rMin;
173 gridConfig.rMax = finderConfig.rMax;
174 gridConfig.zMin = finderConfig.zMin;
175 gridConfig.zMax = finderConfig.zMax;
176 gridConfig.deltaRMax = finderConfig.deltaRMax;
177 gridConfig.cotThetaMax = finderConfig.cotThetaMax;
178 gridConfig.impactMax = finderConfig.impactMax;
179
180 Acts::CylindricalSpacePointGridOptions gridOpts;
181 gridOpts.bFieldInZ = bFieldInZ;
182
183 Acts::SeedFinderOptions finderOpts;
184 finderOpts.beamPos = spContainerOpts.beamPos;
185 finderOpts.bFieldInZ = gridOpts.bFieldInZ;
186 try {
187 finderOpts = finderOpts.calculateDerivedQuantities(finderConfig);
188 } catch (const std::exception& e) {
189 LOG(fatal) << "Error in seed finder configuration: " << e.what();
190 return;
191 }
192
193 Acts::CylindricalSpacePointGrid<SPProxy> grid = Acts::CylindricalSpacePointGridCreator::createGrid<SPProxy>(gridConfig, gridOpts);
194 try {
195 Acts::CylindricalSpacePointGridCreator::fillGrid(finderConfig, finderOpts, grid,
196 spContainer.begin(), spContainer.end());
197 } catch (const std::exception& e) {
198 LOG(fatal) << "Error during grid creation/filling: " << e.what();
199 return;
200 }
201 LOG(debug) << "Grid created with " << grid.dimensions();
202
203 // Build the binned group and iterate over triplet combinations
204 Acts::GridBinFinder<3ul> bottomBinFinder{1, std::vector<std::pair<int, int>>{}, 0};
205 Acts::GridBinFinder<3ul> topBinFinder{1, std::vector<std::pair<int, int>>{}, 0};
206 Acts::CylindricalBinnedGroup<SPProxy> spGroup{std::move(grid), bottomBinFinder, topBinFinder};
207
208 std::vector<std::vector<Acts::Seed<SPProxy>>> seedsPerGroup;
209 typename Acts::SeedFinder<SPProxy, Acts::CylindricalSpacePointGrid<SPProxy>>::SeedingState seedingState;
210 seedingState.spacePointMutableData.resize(spContainer.size());
211 const Acts::Range1D<float> rMiddleSPRange;
212 for (auto [bottom, middle, top] : spGroup) {
213 auto& v = seedsPerGroup.emplace_back();
214 try {
215 seedFinder.createSeedsForGroup(finderOpts, seedingState, spGroup.grid(), v, bottom, middle, top, rMiddleSPRange);
216 } catch (const std::exception& e) {
217 LOG(fatal) << "Error during seed finding for a group: " << e.what();
218 return;
219 }
220 }
221 LOG(debug) << "Seed finding completed, found " << seedsPerGroup.size() << " groups with seeds";
222
223 // Convert Acts seeds to the internal SeedACTS representation
224 for (const auto& groupSeeds : seedsPerGroup) {
225 for (const auto& actsSeed : groupSeeds) {
226 SeedACTS seed;
227 seed.bottom = &actsSeed.sp()[0]->externalSpacePoint();
228 seed.middle = &actsSeed.sp()[1]->externalSpacePoint();
229 seed.top = &actsSeed.sp()[2]->externalSpacePoint();
230 seed.quality = actsSeed.seedQuality();
231 mSeeds.push_back(seed);
232 }
233 }
234
235 LOGF(info, "Created %zu seeds from %zu space points", mSeeds.size(), mSpacePoints.size());
236}
237
238template <int nLayers>
239bool TrackerACTS<nLayers>::estimateTrackParams(const SeedACTS& seed, o2::its::TrackITSExt& track) const
240{
241 return true;
242}
243
244template <int nLayers>
245void TrackerACTS<nLayers>::findTracks()
246{
247}
248
249template <int nLayers>
250void TrackerACTS<nLayers>::computeTracksMClabels()
251{
252}
253
254template <int nLayers>
256{
257 if (!mTimeFrame) {
258 LOG(error) << "Cannot run TrackerACTS: No TimeFrame adopted";
259 return;
260 }
261
262 double totalTime = 0.;
263 LOG(info) << "==== TRK ACTS Tracking ====";
264 LOG(info) << "Processing " << mTimeFrame->getNrof() << " ROFs with B = " << mBz << " T";
265
266 // Process each ROF
267 for (int iROF = 0; iROF < mTimeFrame->getNrof(); ++iROF) {
268 LOG(info) << "Processing ROF " << iROF;
269 // Build space points
270 mCurState = SpacePointBuilding;
271 totalTime += evaluateTask([this, iROF]() { buildSpacePoints(iROF); },
272 StateNames[mCurState]);
273
274 // Run seeding
275 mCurState = Seeding;
276 totalTime += evaluateTask([this]() { createSeeds(); },
277 StateNames[mCurState]);
278
279 // Find tracks
280 mCurState = TrackFinding;
281 totalTime += evaluateTask([this]() { findTracks(); },
282 StateNames[mCurState]);
283 }
284
285 // MC labeling
286 if (mTimeFrame->hasMCinformation()) {
287 computeTracksMClabels();
288 }
289
290 LOG(info) << "=== TimeFrame " << mTimeFrameCounter << " completed in: " << totalTime << " ms ===";
291
292 ++mTimeFrameCounter;
293 mTotalTime += totalTime;
294}
295
296template <int nLayers>
298{
299 float avgTF = mTimeFrameCounter > 0 ? static_cast<float>(mTotalTime) / mTimeFrameCounter : 0.f;
300 LOGP(info, "TrackerACTS summary: Processed {} TFs in TOT={:.2f} ms, AVG/TF={:.2f} ms",
301 mTimeFrameCounter, mTotalTime, avgTF);
302}
303
304// Explicit template instantiations
305template class TrackerACTS<11>;
306} // namespace o2::trk
std::ostringstream debug
int32_t i
TRK tracker using ACTS seeding algorithm.
TRK Tracker using ACTS algorithms for seeding and track finding.
Definition TrackerACTS.h:87
void clustersToTracks()
Main tracking entry point: convert clusters to tracks.
void adoptTimeFrame(o2::its::TimeFrame< nLayers > &tf)
Adopt a TimeFrame for processing.
void printSummary() const
Print tracking summary.
const GLdouble * v
Definition glcorearb.h:832
GLdouble GLdouble GLdouble GLdouble top
Definition glcorearb.h:4077
GLint GLint bottom
Definition glcorearb.h:1979
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
std::unique_ptr< GPUReconstructionTimeframe > tf
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters