Project
Loading...
Searching...
No Matches
TrackerSpec.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
12#include <vector>
13#include <algorithm>
14#include <array>
15#include <chrono>
16#include <format>
17#include <fstream>
18#include <numeric>
19
27#include "Field/MagneticField.h"
28#include "Field/MagFieldParam.h"
38#include "TRKSimulation/Hit.h"
42#include <TGeoGlobalMagField.h>
43
44#ifdef O2_WITH_ACTS
46#endif
47
48#include <TFile.h>
49#include <TTree.h>
50
51namespace o2
52{
53using namespace framework;
54namespace trk
55{
57
58namespace
59{
60class ALICE3TrackingBackendLoader : public o2::utils::DLLoaderBase<ALICE3TrackingBackendLoader>
61{
62 O2DLLoaderDef(ALICE3TrackingBackendLoader)
63};
64
65O2DLLoaderImpl(ALICE3TrackingBackendLoader)
66
67 constexpr const char* kGPUBackendFunction = "runALICE3GPUTracking";
68} // namespace
69
70TrackerDPL::TrackerDPL(std::shared_ptr<o2::base::GRPGeomRequest> gr,
71 bool isMC,
72 const std::string& hitRecoConfigFileName,
73 const std::string& clusterRecoConfigFileName,
75 int trackingThreads)
76{
77 if (!hitRecoConfigFileName.empty()) {
78 std::ifstream configFile(hitRecoConfigFileName);
79 mHitRecoConfig = nlohmann::json::parse(configFile);
80 }
81 if (!clusterRecoConfigFileName.empty()) {
82 std::ifstream configFile(clusterRecoConfigFileName);
83 mClusterRecoConfig = nlohmann::json::parse(configFile);
84 }
85 mIsMC = isMC;
86 mDeviceType = dType;
87 mTrackingThreads = std::max(1, trackingThreads);
88}
89
91{
92#ifdef O2_WITH_ACTS
93 mUseACTS = ic.options().get<bool>("useACTS");
94#endif
95}
96
98{
99 LOGF(info, "CPU Reconstruction total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
100}
101
102std::vector<o2::its::TrackingParameters> TrackerDPL::createTrackingParamsFromConfig()
103{
104 std::vector<o2::its::TrackingParameters> trackingParams;
105 auto loadTrackingParamsFromJson = [](std::vector<o2::its::TrackingParameters>& trackingParams, const nlohmann::json& paramConfigJson) {
106 for (const auto& paramConfig : paramConfigJson) {
108 auto applyPassFlag = [&](const char* name, o2::its::IterationStep step) {
109 if (paramConfig.contains(name)) {
110 if (paramConfig[name].get<bool>()) {
111 params.PassFlags.set(step);
112 } else {
113 params.PassFlags.reset(step);
114 }
115 }
116 };
117
118 if (paramConfig.contains("NLayers")) {
119 params.NLayers = paramConfig["NLayers"].get<int>();
120 }
121 if (paramConfig.contains("ZBins")) {
122 params.ZBins = paramConfig["ZBins"].get<int>();
123 }
124 if (paramConfig.contains("PhiBins")) {
125 params.PhiBins = paramConfig["PhiBins"].get<int>();
126 }
127 if (paramConfig.contains("SharedMaxClusters")) {
128 params.SharedMaxClusters = paramConfig["SharedMaxClusters"].get<int>();
129 }
130 if (paramConfig.contains("MinTrackLength")) {
131 params.MinTrackLength = paramConfig["MinTrackLength"].get<int>();
132 }
133 if (paramConfig.contains("ReseedIfShorter")) {
134 params.ReseedIfShorter = paramConfig["ReseedIfShorter"].get<int>();
135 }
136 if (paramConfig.contains("StartLayerMask")) {
137 params.StartLayerMask = paramConfig["StartLayerMask"].get<uint16_t>();
138 }
139
140 if (paramConfig.contains("NSigmaCut")) {
141 params.NSigmaCut = paramConfig["NSigmaCut"].get<float>();
142 }
143 if (paramConfig.contains("PVres")) {
144 params.PVres = paramConfig["PVres"].get<float>();
145 }
146 if (paramConfig.contains("TrackletMinPt")) {
147 params.TrackletMinPt = paramConfig["TrackletMinPt"].get<float>();
148 }
149 if (paramConfig.contains("CellDeltaTanLambdaSigma")) {
150 params.CellDeltaTanLambdaSigma = paramConfig["CellDeltaTanLambdaSigma"].get<float>();
151 }
152 if (paramConfig.contains("MaxChi2ClusterAttachment")) {
153 params.MaxChi2ClusterAttachment = paramConfig["MaxChi2ClusterAttachment"].get<float>();
154 }
155 if (paramConfig.contains("MaxChi2NDF")) {
156 params.MaxChi2NDF = paramConfig["MaxChi2NDF"].get<float>();
157 }
158
159 if (paramConfig.contains("UseDiamond")) {
160 params.UseDiamond = paramConfig["UseDiamond"].get<bool>();
161 }
162 if (paramConfig.contains("AllowSharingFirstCluster")) {
163 params.AllowSharingFirstCluster = paramConfig["AllowSharingFirstCluster"].get<bool>();
164 }
165 if (paramConfig.contains("RepeatRefitOut")) {
166 params.RepeatRefitOut = paramConfig["RepeatRefitOut"].get<bool>();
167 }
168 if (paramConfig.contains("ShiftRefToCluster")) {
169 params.ShiftRefToCluster = paramConfig["ShiftRefToCluster"].get<bool>();
170 }
171 if (paramConfig.contains("PerPrimaryVertexProcessing")) {
172 params.PerPrimaryVertexProcessing = paramConfig["PerPrimaryVertexProcessing"].get<bool>();
173 }
174 if (paramConfig.contains("SaveTimeBenchmarks")) {
175 params.SaveTimeBenchmarks = paramConfig["SaveTimeBenchmarks"].get<bool>();
176 }
177 if (paramConfig.contains("DoUPCIteration")) {
178 params.DoUPCIteration = paramConfig["DoUPCIteration"].get<bool>();
179 }
180 if (paramConfig.contains("FataliseUponFailure")) {
181 params.FataliseUponFailure = paramConfig["FataliseUponFailure"].get<bool>();
182 }
183 if (paramConfig.contains("CreateArtefactLabels")) {
184 params.CreateArtefactLabels = paramConfig["CreateArtefactLabels"].get<bool>();
185 }
186 if (paramConfig.contains("TrackFollower")) {
187 const auto mode = paramConfig["TrackFollower"].get<std::string>();
188 if (mode == "top" || mode == "outward") {
190 } else if (mode == "bot" || mode == "bottom" || mode == "inward") {
192 } else if (mode == "mix" || mode == "both") {
195 } else if (mode != "off") {
196 LOGP(fatal, "Invalid ALICE3 TRK tracking parameter TrackFollower: {}", mode);
197 }
198 }
199 if (paramConfig.contains("TrackFollowerNSigmaCutZ")) {
200 params.TrackFollowerNSigmaCutZ = paramConfig["TrackFollowerNSigmaCutZ"].get<float>();
201 }
202 if (paramConfig.contains("TrackFollowerNSigmaCutPhi")) {
203 params.TrackFollowerNSigmaCutPhi = paramConfig["TrackFollowerNSigmaCutPhi"].get<float>();
204 }
205 if (paramConfig.contains("TrackFollowerMaxHypotheses")) {
206 params.TrackFollowerMaxHypotheses = std::max(1, paramConfig["TrackFollowerMaxHypotheses"].get<int>());
207 }
208 applyPassFlag("FirstPass", o2::its::IterationStep::FirstPass);
209 applyPassFlag("RebuildClusterLUT", o2::its::IterationStep::RebuildClusterLUT);
210 applyPassFlag("UseUPCMask", o2::its::IterationStep::UseUPCMask);
211 applyPassFlag("SelectUPCVertices", o2::its::IterationStep::SelectUPCVertices);
212 applyPassFlag("ResetVertices", o2::its::IterationStep::ResetVertices);
213 applyPassFlag("SkipROFsAboveThreshold", o2::its::IterationStep::SkipROFsAboveThreshold);
214 applyPassFlag("MarkVerticesAsUPC", o2::its::IterationStep::MarkVerticesAsUPC);
215 applyPassFlag("TrackFollowerTop", o2::its::IterationStep::TrackFollowerTop);
216 applyPassFlag("TrackFollowerBot", o2::its::IterationStep::TrackFollowerBot);
217 if (paramConfig.contains("PrintMemory")) {
218 params.PrintMemory = paramConfig["PrintMemory"].get<bool>();
219 }
220 if (paramConfig.contains("DropTFUponFailure")) {
221 params.DropTFUponFailure = paramConfig["DropTFUponFailure"].get<bool>();
222 }
223
224 if (paramConfig.contains("LayerZ")) {
225 params.LayerZ = paramConfig["LayerZ"].get<std::vector<float>>();
226 }
227 if (paramConfig.contains("LayerRadii")) {
228 params.LayerRadii = paramConfig["LayerRadii"].get<std::vector<float>>();
229 }
230 if (paramConfig.contains("LayerxX0")) {
231 params.LayerxX0 = paramConfig["LayerxX0"].get<std::vector<float>>();
232 }
233 if (paramConfig.contains("LayerResolution")) {
234 params.LayerResolution = paramConfig["LayerResolution"].get<std::vector<float>>();
235 }
236 if (paramConfig.contains("SystErrorY2")) {
237 params.SystErrorY2 = paramConfig["SystErrorY2"].get<std::vector<float>>();
238 }
239 if (paramConfig.contains("SystErrorZ2")) {
240 params.SystErrorZ2 = paramConfig["SystErrorZ2"].get<std::vector<float>>();
241 }
242 if (paramConfig.contains("MinPt")) {
243 params.MinPt = paramConfig["MinPt"].get<std::vector<float>>();
244 }
245 if (paramConfig.contains("AddTimeError")) {
246 params.AddTimeError = paramConfig["AddTimeError"].get<std::vector<UInt_t>>();
247 }
248
249 if (paramConfig.contains("Diamond") && paramConfig["Diamond"].is_array() && paramConfig["Diamond"].size() == 3) {
250 params.Diamond[0] = paramConfig["Diamond"][0].get<float>();
251 params.Diamond[1] = paramConfig["Diamond"][1].get<float>();
252 params.Diamond[2] = paramConfig["Diamond"][2].get<float>();
253 }
254
255 if (paramConfig.contains("MaxMemory")) {
256 params.MaxMemory = paramConfig["MaxMemory"].get<size_t>();
257 }
258
259 if (paramConfig.contains("CorrType")) {
260 int corrTypeInt = paramConfig["CorrType"].get<int>();
261 params.CorrType = static_cast<o2::base::PropagatorImpl<float>::MatCorrType>(corrTypeInt);
262 }
263
264 const auto nLayers = static_cast<size_t>(params.NLayers);
265 LOG_IF(fatal, params.LayerZ.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter LayerZ: expected " << nLayers << " entries, got " << params.LayerZ.size();
266 LOG_IF(fatal, params.LayerRadii.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter LayerRadii: expected " << nLayers << " entries, got " << params.LayerRadii.size();
267 LOG_IF(fatal, params.LayerxX0.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter LayerxX0: expected " << nLayers << " entries, got " << params.LayerxX0.size();
268 LOG_IF(fatal, params.LayerResolution.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter LayerResolution: expected " << nLayers << " entries, got " << params.LayerResolution.size();
269 LOG_IF(fatal, params.SystErrorY2.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter SystErrorY2: expected " << nLayers << " entries, got " << params.SystErrorY2.size();
270 LOG_IF(fatal, params.SystErrorZ2.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter SystErrorZ2: expected " << nLayers << " entries, got " << params.SystErrorZ2.size();
271 LOG_IF(fatal, params.AddTimeError.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter AddTimeError: expected " << nLayers << " entries, got " << params.AddTimeError.size();
272
273 LOG_IF(fatal, params.MinTrackLength > params.NLayers) << "Invalid ALICE3 TRK tracking parameter MinTrackLength: expected <= NLayers (" << params.NLayers << "), got " << params.MinTrackLength;
274 const auto minPtSize = static_cast<size_t>(params.NLayers - params.MinTrackLength + 1);
275 LOG_IF(fatal, params.MinPt.size() != minPtSize) << "Invalid ALICE3 TRK tracking parameter MinPt: expected " << minPtSize << " entries, got " << params.MinPt.size();
276
277 trackingParams.push_back(params);
278 }
279 };
280
281 if (mHitRecoConfig.contains("trackingparams") && mHitRecoConfig["trackingparams"].is_array()) {
282 loadTrackingParamsFromJson(trackingParams, mHitRecoConfig["trackingparams"]);
283 } else if (mClusterRecoConfig.contains("trackingparams") && mClusterRecoConfig["trackingparams"].is_array()) {
284 loadTrackingParamsFromJson(trackingParams, mClusterRecoConfig["trackingparams"]);
285 } else {
286 LOGP(fatal, "No trackingparams field found in configuration or it is not an array. Returning empty vector.");
287 return trackingParams;
288 }
289
290 LOGP(info, "Loaded {} tracking parameter sets from configuration", trackingParams.size());
291 return trackingParams;
292}
293
295{
296 if (mMemoryPool.get() == nullptr) {
297 mMemoryPool = std::make_shared<its::BoundedMemoryResource>();
298 }
299 if (mTaskArena.get() == nullptr) {
300 mTaskArena = std::make_shared<tbb::task_arena>(mTrackingThreads);
301 }
302
303 mTrackingParams = createTrackingParamsFromConfig();
304
305 auto cput = mTimer.CpuTime();
306 auto realt = mTimer.RealTime();
307 mTimer.Start(false);
308
309 const bool useGPU = mDeviceType != o2::gpu::gpudatatypes::DeviceType::CPU;
310
311 if (useGPU) {
312 runGPUTracking(pc);
313 } else {
314 o2::trk::TimeFrame<11> timeFrame;
315 o2::its::TrackerTraits<11> itsTrackerTraits;
316 runTracking(pc, timeFrame, itsTrackerTraits);
317 }
318
321
322 mTimer.Stop();
323 LOGP(info, "CPU Reconstruction time for this TF {} s (cpu), {} s (wall)", mTimer.CpuTime() - cput, mTimer.RealTime() - realt);
324}
325
326void TrackerDPL::runGPUTracking(ProcessingContext& pc)
327{
328 auto& loader = ALICE3TrackingBackendLoader::Instance();
329 switch (mDeviceType) {
331#ifdef TRK_HAS_CUDA_TRACKING
332 loader.executeFunctionAlias<int, TrackerDPL*, ProcessingContext*>("O2ALICE3GlobalReconstructionWorkflowCUDA", kGPUBackendFunction, this, &pc);
333 return;
334#else
335 LOGP(fatal, "CUDA TRK GPU tracking was requested but this build has no CUDA TRK GPU tracking backend");
336#endif
338#ifdef TRK_HAS_HIP_TRACKING
339 loader.executeFunctionAlias<int, TrackerDPL*, ProcessingContext*>("O2ALICE3GlobalReconstructionWorkflowHIP", kGPUBackendFunction, this, &pc);
340 return;
341#else
342 LOGP(fatal, "HIP TRK GPU tracking was requested but this build has no HIP TRK GPU tracking backend");
343#endif
344 default:
345 LOGP(fatal, "Unsupported TRK GPU device type {}", static_cast<int>(mDeviceType));
346 }
347}
348
350{
351 LOGF(info, "TRK CA-Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
352}
353
354DataProcessorSpec getTrackerSpec(bool useMC, const std::string& hitRecoConfig, const std::string& clusterRecoConfig, o2::gpu::gpudatatypes::DeviceType dType, int trackingThreads)
355{
356 std::vector<InputSpec> inputs;
357 std::vector<OutputSpec> outputs;
358 outputs.emplace_back("TRK", "TRACKS", 0, Lifetime::Timeframe);
359 outputs.emplace_back("TRK", "TRACKSROF", 0, Lifetime::Timeframe);
360 outputs.emplace_back("TRK", "IRFRAMES", 0, Lifetime::Timeframe);
361 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false, // orbitResetTime
362 false, // GRPECS=true
363 false, // GRPLHCIF
364 false, // GRPMagField
365 false, // askMatLUT
366 o2::base::GRPGeomRequest::None, // geometry, but ignored until it will be put in the CCDB
367 inputs,
368 true);
369
370 if (!hitRecoConfig.empty()) {
371 if (useMC) {
372 outputs.emplace_back("TRK", "TRACKSMCTR", 0, Lifetime::Timeframe);
373 }
374 return DataProcessorSpec{
375 "trk-hits-tracker",
376 {},
377 outputs,
378 AlgorithmSpec{adaptFromTask<TrackerDPL>(ggRequest,
379 useMC,
380 hitRecoConfig,
381 clusterRecoConfig,
382 dType,
383 trackingThreads)},
384 Options{ConfigParamSpec{"max-loops", VariantType::Int, 1, {"max number of loops"}}
385#ifdef O2_WITH_ACTS
386 ,
387 {"useACTS", o2::framework::VariantType::Bool, false, {"Use ACTS for tracking"}}
388#endif
389 }};
390 }
391
392 inputs.emplace_back("dummy", "TRK", "DUMMY", 0, Lifetime::Timeframe);
393
394 if (!clusterRecoConfig.empty()) {
395 inputs.pop_back();
396 constexpr int nLayers{11};
397 for (int iLayer = 0; iLayer < nLayers; ++iLayer) {
398 inputs.emplace_back(std::format("compClusters_{}", iLayer), "TRK", "COMPCLUSTERS", iLayer, Lifetime::Timeframe);
399 inputs.emplace_back(std::format("patterns_{}", iLayer), "TRK", "PATTERNS", iLayer, Lifetime::Timeframe);
400 inputs.emplace_back(std::format("ROframes_{}", iLayer), "TRK", "CLUSTERSROF", iLayer, Lifetime::Timeframe);
401 if (useMC) {
402 inputs.emplace_back(std::format("trkmclabels_{}", iLayer), "TRK", "CLUSTERSMCTR", iLayer, Lifetime::Timeframe);
403 }
404 }
405 }
406
407 if (useMC) {
408 outputs.emplace_back("TRK", "TRACKSMCTR", 0, Lifetime::Timeframe);
409 }
410
411 return DataProcessorSpec{
412 "trk-tracker",
413 inputs,
414 outputs,
415 AlgorithmSpec{adaptFromTask<TrackerDPL>(ggRequest,
416 useMC,
417 hitRecoConfig,
418 clusterRecoConfig,
419 dType,
420 trackingThreads)},
421 Options{}};
422}
423
424} // namespace trk
425} // namespace o2
#define O2DLLoaderDef(classname)
#define O2DLLoaderImpl(classname)
Definition of the GeometryManager class.
CPU TRK TimeFrame wrapper.
Definition of the TRK Hit class.
Class to delimit start and end IR of certain time period.
Definition of a container to keep Monte Carlo truth external to simulation objects.
Definition of the MagFieldParam: container for ALICE mag. field parameters.
Definition of the MagF class.
Definition of the SegmentationChipclass.
TRK tracker using ACTS seeding algorithm.
ConfigParamRegistry const & options()
Definition InitContext.h:33
ServiceRegistryRef services()
The services registry associated with this processing context.
TrackerDPL(std::shared_ptr< o2::base::GRPGeomRequest > gr, bool isMC, const std::string &hitRecoConfig, const std::string &clusterRecoConfig, gpu::gpudatatypes::DeviceType dType=gpu::gpudatatypes::DeviceType::CPU, int trackingThreads=1)
void runTracking(framework::ProcessingContext &pc, TimeFrameT &timeFrame, TrackerTraitsT &trackerTraits)
void endOfStream(framework::EndOfStreamContext &ec) final
This is invoked whenever we have an EndOfStream event.
void run(framework::ProcessingContext &pc) final
void stop() final
This is invoked on stop.
void init(framework::InitContext &ic) final
void set(const std::string &s, int base=DefaultBase)
Definition EnumFlags.h:435
GLenum mode
Definition glcorearb.h:266
GLuint const GLchar * name
Definition glcorearb.h:781
GLenum const GLfloat * params
Definition glcorearb.h:272
@ Me
Only quit this data processor.
std::vector< ConfigParamSpec > Options
const bool const int nLayers
framework::DataProcessorSpec getTrackerSpec(bool useMC, const std::string &hitRecoConfig, const std::string &clusterRecoConfig, gpu::gpudatatypes::DeviceType dType=gpu::gpudatatypes::DeviceType::CPU, int trackingThreads=1)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...