Project
Loading...
Searching...
No Matches
Tracker.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.
15
16#include "ITStracking/Tracker.h"
17
19#include "ITStracking/Cell.h"
25
27#include <cassert>
28#include <format>
29#include <cstdlib>
30#include <string>
31#include <climits>
32
33namespace o2::its
34{
36
37template <int nLayers>
39{
41 mTrkParams.resize(1);
42 if (traits->isGPU()) {
44 ITSGpuTrackingParamConfig::Instance().printKeyValues(true, true);
45 }
46}
47
48template <int nLayers>
49void Tracker<nLayers>::clustersToTracks(const LogFunc& logger, const LogFunc& error)
50{
51 LogFunc evalLog = [](const std::string&) {};
52
53 double total{0};
54 mTraits->updateTrackingParameters(mTrkParams);
55 int maxNvertices{-1};
56 if (mTrkParams[0].PerPrimaryVertexProcessing) {
57 for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) {
58 int minRof = o2::gpu::CAMath::Max(0, iROF - mTrkParams[0].DeltaROF);
59 int maxRof = o2::gpu::CAMath::Min(mTimeFrame->getNrof(), iROF + mTrkParams[0].DeltaROF);
60 maxNvertices = std::max(maxNvertices, (int)mTimeFrame->getPrimaryVertices(minRof, maxRof).size());
61 }
62 }
63
64 int iteration{0}, iROFs{0}, iVertex{0};
65 auto handleException = [&](const auto& err) {
66 LOGP(error, "Too much memory used during {} in iteration {} in ROF span {}-{} iVtx={}: {:.2f} GB. Current limit is {:.2f} GB, check the detector status and/or the selections.",
67 StateNames[mCurState], iteration, iROFs, iROFs + mTrkParams[iteration].nROFsPerIterations, iVertex,
68 (double)mTimeFrame->getArtefactsMemory() / GB, (double)mTrkParams[iteration].MaxMemory / GB);
69 if (typeid(err) != typeid(std::bad_alloc)) { // only print if the exceptions is different from what is expected
70 LOGP(error, "Exception: {}", err.what());
71 }
72 if (mTrkParams[iteration].DropTFUponFailure) {
73 mMemoryPool->print();
74 mTimeFrame->wipe();
75 ++mNumberOfDroppedTFs;
76 error("...Dropping Timeframe...");
77 } else {
78 throw err;
79 }
80 };
81
82 try {
83 for (iteration = 0; iteration < (int)mTrkParams.size(); ++iteration) {
84 mMemoryPool->setMaxMemory(mTrkParams[iteration].MaxMemory);
85 if (iteration == 3 && mTrkParams[0].DoUPCIteration) {
86 mTimeFrame->swapMasks();
87 }
88 double timeTracklets{0.}, timeCells{0.}, timeNeighbours{0.}, timeRoads{0.};
89 int nTracklets{0}, nCells{0}, nNeighbours{0}, nTracks{-static_cast<int>(mTimeFrame->getNumberOfTracks())};
90 int nROFsIterations = (mTrkParams[iteration].nROFsPerIterations > 0 && !mTimeFrame->isGPU()) ? mTimeFrame->getNrof() / mTrkParams[iteration].nROFsPerIterations + bool(mTimeFrame->getNrof() % mTrkParams[iteration].nROFsPerIterations) : 1;
91 iVertex = std::min(maxNvertices, 0);
92 logger(std::format("==== ITS {} Tracking iteration {} summary ====", mTraits->getName(), iteration));
93
94 total += evaluateTask(&Tracker::initialiseTimeFrame, StateNames[mCurState = TFInit], iteration, logger, iteration);
95 do {
96 for (iROFs = 0; iROFs < nROFsIterations; ++iROFs) {
97 timeTracklets += evaluateTask(&Tracker::computeTracklets, StateNames[mCurState = Trackleting], iteration, evalLog, iteration, iROFs, iVertex);
98 nTracklets += mTraits->getTFNumberOfTracklets();
99 float trackletsPerCluster = mTraits->getTFNumberOfClusters() > 0 ? float(mTraits->getTFNumberOfTracklets()) / float(mTraits->getTFNumberOfClusters()) : 0.f;
100 if (trackletsPerCluster > mTrkParams[iteration].TrackletsPerClusterLimit) {
101 error(std::format("Too many tracklets per cluster ({}) in iteration {} in ROF span {}-{}:, check the detector status and/or the selections. Current limit is {}",
102 trackletsPerCluster, iteration, iROFs, iROFs + mTrkParams[iteration].nROFsPerIterations, mTrkParams[iteration].TrackletsPerClusterLimit));
103 break;
104 }
105 timeCells += evaluateTask(&Tracker::computeCells, StateNames[mCurState = Celling], iteration, evalLog, iteration);
106 nCells += mTraits->getTFNumberOfCells();
107 float cellsPerCluster = mTraits->getTFNumberOfClusters() > 0 ? float(mTraits->getTFNumberOfCells()) / float(mTraits->getTFNumberOfClusters()) : 0.f;
108 if (cellsPerCluster > mTrkParams[iteration].CellsPerClusterLimit) {
109 error(std::format("Too many cells per cluster ({}) in iteration {} in ROF span {}-{}, check the detector status and/or the selections. Current limit is {}",
110 cellsPerCluster, iteration, iROFs, iROFs + mTrkParams[iteration].nROFsPerIterations, mTrkParams[iteration].CellsPerClusterLimit));
111 break;
112 }
113 timeNeighbours += evaluateTask(&Tracker::findCellsNeighbours, StateNames[mCurState = Neighbouring], iteration, evalLog, iteration);
114 nNeighbours += mTimeFrame->getNumberOfNeighbours();
115 timeRoads += evaluateTask(&Tracker::findRoads, StateNames[mCurState = Roading], iteration, evalLog, iteration);
116 }
117 } while (++iVertex < maxNvertices);
118 logger(std::format(" - Tracklet finding: {} tracklets found in {:.2f} ms", nTracklets, timeTracklets));
119 logger(std::format(" - Cell finding: {} cells found in {:.2f} ms", nCells, timeCells));
120 logger(std::format(" - Neighbours finding: {} neighbours found in {:.2f} ms", nNeighbours, timeNeighbours));
121 logger(std::format(" - Track finding: {} tracks found in {:.2f} ms", nTracks + mTimeFrame->getNumberOfTracks(), timeRoads));
122 total += timeTracklets + timeCells + timeNeighbours + timeRoads;
123 if (mTraits->supportsExtendTracks() && mTrkParams[iteration].UseTrackFollower) {
124 int nExtendedTracks{-mTimeFrame->mNExtendedTracks}, nExtendedClusters{-mTimeFrame->mNExtendedUsedClusters};
125 auto timeExtending = evaluateTask(&Tracker::extendTracks, "Extending tracks", iteration, evalLog, iteration);
126 total += timeExtending;
127 logger(std::format(" - Extending Tracks: {} extended tracks using {} clusters found in {:.2f} ms", nExtendedTracks + mTimeFrame->mNExtendedTracks, nExtendedClusters + mTimeFrame->mNExtendedUsedClusters, timeExtending));
128 }
129 if (mTrkParams[iteration].PrintMemory) {
130 mMemoryPool->print();
131 }
132 }
133 if (mTraits->supportsFindShortPrimaries() && mTrkParams[0].FindShortTracks) {
134 auto nTracksB = mTimeFrame->getNumberOfTracks();
135 total += evaluateTask(&Tracker::findShortPrimaries, "Short primaries finding", 0, logger);
136 auto nTracksA = mTimeFrame->getNumberOfTracks();
137 logger(std::format(" `-> found {} additional tracks", nTracksA - nTracksB));
138 }
139 if constexpr (constants::DoTimeBenchmarks) {
140 logger(std::format("=== TimeFrame {} processing completed in: {:.2f} ms using {} thread(s) ===", mTimeFrameCounter, total, mTraits->getNThreads()));
141 }
142 } catch (const BoundedMemoryResource::MemoryLimitExceeded& err) {
143 handleException(err);
144 return;
145 } catch (const std::bad_alloc& err) {
146 handleException(err);
147 return;
148 } catch (const std::exception& err) {
149 error(std::format("Uncaught exception, all bets are off... {}", err.what()));
150 // clear tracks explicitly since if not fatalising on exception this may contain partial output
151 for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) {
152 mTimeFrame->getTracks(iROF).clear();
153 }
154 return;
155 }
156
157 if (mTimeFrame->hasMCinformation()) {
158 computeTracksMClabels();
159 }
160 rectifyClusterIndices();
161 ++mTimeFrameCounter;
162 mTotalTime += total;
163
164 if (mTrkParams[0].PrintMemory) {
165 mTimeFrame->printArtefactsMemory();
166 mMemoryPool->print();
167 }
168}
169
170template <int nLayers>
172{
174 if (!mTimeFrame->hasMCinformation()) {
175 return;
176 }
177
178 mTimeFrame->initialiseRoadLabels();
179
180 int roadsNum{static_cast<int>(mTimeFrame->getRoads().size())};
181
182 for (int iRoad{0}; iRoad < roadsNum; ++iRoad) {
183
184 auto& currentRoad{mTimeFrame->getRoads()[iRoad]};
185 std::vector<std::pair<MCCompLabel, size_t>> occurrences;
186 bool isFakeRoad{false};
187 bool isFirstRoadCell{true};
188
189 for (int iCell{0}; iCell < mTrkParams[0].CellsPerRoad(); ++iCell) {
190 const int currentCellIndex{currentRoad[iCell]};
191
192 if (currentCellIndex == constants::UnusedIndex) {
193 if (isFirstRoadCell) {
194 continue;
195 } else {
196 break;
197 }
198 }
199
200 const auto& currentCell{mTimeFrame->getCells()[iCell][currentCellIndex]};
201
202 if (isFirstRoadCell) {
203
204 const int cl0index{mTimeFrame->getClusters()[iCell][currentCell.getFirstClusterIndex()].clusterId};
205 auto cl0labs{mTimeFrame->getClusterLabels(iCell, cl0index)};
206 bool found{false};
207 for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) {
208 std::pair<o2::MCCompLabel, size_t>& occurrence = occurrences[iOcc];
209 for (const auto& label : cl0labs) {
210 if (label == occurrence.first) {
211 ++occurrence.second;
212 found = true;
213 // break; // uncomment to stop to the first hit
214 }
215 }
216 }
217 if (!found) {
218 for (const auto& label : cl0labs) {
219 occurrences.emplace_back(label, 1);
220 }
221 }
222
223 const int cl1index{mTimeFrame->getClusters()[iCell + 1][currentCell.getSecondClusterIndex()].clusterId};
224
225 const auto& cl1labs{mTimeFrame->getClusterLabels(iCell + 1, cl1index)};
226 found = false;
227 for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) {
228 std::pair<o2::MCCompLabel, size_t>& occurrence = occurrences[iOcc];
229 for (auto& label : cl1labs) {
230 if (label == occurrence.first) {
231 ++occurrence.second;
232 found = true;
233 // break; // uncomment to stop to the first hit
234 }
235 }
236 }
237 if (!found) {
238 for (auto& label : cl1labs) {
239 occurrences.emplace_back(label, 1);
240 }
241 }
242
243 isFirstRoadCell = false;
244 }
245
246 const int cl2index{mTimeFrame->getClusters()[iCell + 2][currentCell.getThirdClusterIndex()].clusterId};
247 const auto& cl2labs{mTimeFrame->getClusterLabels(iCell + 2, cl2index)};
248 bool found{false};
249 for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) {
250 std::pair<o2::MCCompLabel, size_t>& occurrence = occurrences[iOcc];
251 for (auto& label : cl2labs) {
252 if (label == occurrence.first) {
253 ++occurrence.second;
254 found = true;
255 // break; // uncomment to stop to the first hit
256 }
257 }
258 }
259 if (!found) {
260 for (auto& label : cl2labs) {
261 occurrences.emplace_back(label, 1);
262 }
263 }
264 }
265
266 std::sort(occurrences.begin(), occurrences.end(), [](auto e1, auto e2) {
267 return e1.second > e2.second;
268 });
269
270 auto maxOccurrencesValue = occurrences[0].first;
271 mTimeFrame->setRoadLabel(iRoad, maxOccurrencesValue.getRawValue(), isFakeRoad);
272 }
273}
274
275template <int nLayers>
276void Tracker<nLayers>::computeTracksMClabels()
277{
278 for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) {
279 for (auto& track : mTimeFrame->getTracks(iROF)) {
280 std::vector<std::pair<MCCompLabel, size_t>> occurrences;
281 occurrences.clear();
282
283 for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) {
284 const int index = track.getClusterIndex(iCluster);
285 if (index == constants::UnusedIndex) {
286 continue;
287 }
288 auto labels = mTimeFrame->getClusterLabels(iCluster, index);
289 bool found{false};
290 for (size_t iOcc{0}; iOcc < occurrences.size(); ++iOcc) {
291 std::pair<o2::MCCompLabel, size_t>& occurrence = occurrences[iOcc];
292 for (const auto& label : labels) {
293 if (label == occurrence.first) {
294 ++occurrence.second;
295 found = true;
296 // break; // uncomment to stop to the first hit
297 }
298 }
299 }
300 if (!found) {
301 for (const auto& label : labels) {
302 occurrences.emplace_back(label, 1);
303 }
304 }
305 }
306 std::sort(std::begin(occurrences), std::end(occurrences), [](auto e1, auto e2) {
307 return e1.second > e2.second;
308 });
309
310 auto maxOccurrencesValue = occurrences[0].first;
311 uint32_t pattern = track.getPattern();
312 // set fake clusters pattern
313 for (int ic{TrackITSExt::MaxClusters}; ic--;) {
314 auto clid = track.getClusterIndex(ic);
315 if (clid != constants::UnusedIndex) {
316 auto labelsSpan = mTimeFrame->getClusterLabels(ic, clid);
317 for (const auto& currentLabel : labelsSpan) {
318 if (currentLabel == maxOccurrencesValue) {
319 pattern |= 0x1 << (16 + ic); // set bit if correct
320 break;
321 }
322 }
323 }
324 }
325 track.setPattern(pattern);
326 if (occurrences[0].second < track.getNumberOfClusters()) {
327 maxOccurrencesValue.setFakeFlag();
328 }
329 mTimeFrame->getTracksLabel(iROF).emplace_back(maxOccurrencesValue);
330 }
331 }
332}
333
334template <int nLayers>
335void Tracker<nLayers>::rectifyClusterIndices()
336{
337 for (int iROF{0}; iROF < mTimeFrame->getNrof(); ++iROF) {
338 for (auto& track : mTimeFrame->getTracks(iROF)) {
339 for (int iCluster = 0; iCluster < TrackITSExt::MaxClusters; ++iCluster) {
340 const int index = track.getClusterIndex(iCluster);
341 if (index != constants::UnusedIndex) {
342 track.setExternalClusterIndex(iCluster, mTimeFrame->getClusterExternalIndex(iCluster, index));
343 }
344 }
345 }
346 }
347}
348
349template <int nLayers>
351{
352 mTimeFrame = &tf;
353 mTraits->adoptTimeFrame(&tf);
354}
355
356template <int nLayers>
358{
359 auto avgTF = mTotalTime * 1.e-3 / ((mTimeFrameCounter > 0) ? (double)mTimeFrameCounter : -1.0);
360 auto avgTFwithDropped = mTotalTime * 1.e-3 / (((mTimeFrameCounter + mNumberOfDroppedTFs) > 0) ? (double)(mTimeFrameCounter + mNumberOfDroppedTFs) : -1.0);
361 LOGP(info, "Tracker summary: Processed {} TFs (dropped {}) in TOT={:.2f} s, AVG/TF={:.2f} ({:.2f}) s", mTimeFrameCounter, mNumberOfDroppedTFs, mTotalTime * 1.e-3, avgTF, avgTFwithDropped);
362}
363
364template class Tracker<7>;
365// ALICE3 upgrade
366#ifdef ENABLE_UPGRADES
367template class Tracker<11>;
368#endif
369
370} // namespace o2::its
std::vector< std::string > labels
Base track model for the Barrel, params only, w/o covariance.
#define GB
Definition Utils.h:40
static constexpr int MaxClusters
< heavy version of TrackITS, with clusters embedded
Definition TrackITS.h:169
virtual bool isGPU() const noexcept
void printSummary() const
Definition Tracker.cxx:357
void adoptTimeFrame(TimeFrame< nLayers > &tf)
Definition Tracker.cxx:350
void clustersToTracks(const LogFunc &=[](const std::string &s) { std::cout<< s<< '\n';}, const LogFunc &=[](const std::string &s) { std::cerr<< s<< '\n';})
Definition Tracker.cxx:49
Tracker(TrackerTraits< nLayers > *traits)
Definition Tracker.cxx:38
GLuint index
Definition glcorearb.h:781
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
constexpr float GB
Definition Constants.h:30
constexpr bool DoTimeBenchmarks
Definition Constants.h:31
std::unique_ptr< GPUReconstructionTimeframe > tf
std::array< uint16_t, 5 > pattern