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"
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("MaxHoles")) {
134 params.MaxHoles = paramConfig["MaxHoles"].get<int>();
135 }
136 if (paramConfig.contains("HoleLayerMask")) {
137 params.HoleLayerMask = paramConfig["HoleLayerMask"].get<uint16_t>();
138 }
139 if (paramConfig.contains("InactiveLayerMask")) {
140 params.InactiveLayerMask = paramConfig["InactiveLayerMask"].get<uint16_t>();
141 }
142 if (paramConfig.contains("SeedingLayers")) {
143 params.SeedingLayers = paramConfig["SeedingLayers"].get<uint16_t>();
144 }
145 if (paramConfig.contains("ReseedIfShorter")) {
146 params.ReseedIfShorter = paramConfig["ReseedIfShorter"].get<int>();
147 }
148 if (paramConfig.contains("StartLayerMask")) {
149 params.StartLayerMask = paramConfig["StartLayerMask"].get<uint16_t>();
150 }
151
152 if (paramConfig.contains("NSigmaCut")) {
153 params.NSigmaCut = paramConfig["NSigmaCut"].get<float>();
154 }
155 if (paramConfig.contains("PVres")) {
156 params.PVres = paramConfig["PVres"].get<float>();
157 }
158 if (paramConfig.contains("TrackletMinPt")) {
159 params.TrackletMinPt = paramConfig["TrackletMinPt"].get<float>();
160 }
161 if (paramConfig.contains("CellDeltaTanLambdaSigma")) {
162 params.CellDeltaTanLambdaSigma = paramConfig["CellDeltaTanLambdaSigma"].get<float>();
163 }
164 if (paramConfig.contains("MaxChi2ClusterAttachment")) {
165 params.MaxChi2ClusterAttachment = paramConfig["MaxChi2ClusterAttachment"].get<float>();
166 }
167 if (paramConfig.contains("MaxChi2NDF")) {
168 params.MaxChi2NDF = paramConfig["MaxChi2NDF"].get<float>();
169 }
170
171 if (paramConfig.contains("UseDiamond")) {
172 params.UseDiamond = paramConfig["UseDiamond"].get<bool>();
173 }
174 if (paramConfig.contains("AllowSharingFirstCluster")) {
175 params.AllowSharingFirstCluster = paramConfig["AllowSharingFirstCluster"].get<bool>();
176 }
177 if (paramConfig.contains("RepeatRefitOut")) {
178 params.RepeatRefitOut = paramConfig["RepeatRefitOut"].get<bool>();
179 }
180 if (paramConfig.contains("ShiftRefToCluster")) {
181 params.ShiftRefToCluster = paramConfig["ShiftRefToCluster"].get<bool>();
182 }
183 if (paramConfig.contains("PerPrimaryVertexProcessing")) {
184 params.PerPrimaryVertexProcessing = paramConfig["PerPrimaryVertexProcessing"].get<bool>();
185 }
186 if (paramConfig.contains("SaveTimeBenchmarks")) {
187 params.SaveTimeBenchmarks = paramConfig["SaveTimeBenchmarks"].get<bool>();
188 }
189 if (paramConfig.contains("DoUPCIteration")) {
190 params.DoUPCIteration = paramConfig["DoUPCIteration"].get<bool>();
191 }
192 if (paramConfig.contains("FataliseUponFailure")) {
193 params.FataliseUponFailure = paramConfig["FataliseUponFailure"].get<bool>();
194 }
195 if (paramConfig.contains("CreateArtefactLabels")) {
196 params.CreateArtefactLabels = paramConfig["CreateArtefactLabels"].get<bool>();
197 }
198 if (paramConfig.contains("TrackFollower")) {
199 const auto mode = paramConfig["TrackFollower"].get<std::string>();
200 if (mode == "top" || mode == "outward") {
202 } else if (mode == "bot" || mode == "bottom" || mode == "inward") {
204 } else if (mode == "mix" || mode == "both") {
207 } else if (mode != "off") {
208 LOGP(fatal, "Invalid ALICE3 TRK tracking parameter TrackFollower: {}", mode);
209 }
210 }
211 if (paramConfig.contains("TrackFollowerNSigmaCutZ")) {
212 params.TrackFollowerNSigmaCutZ = paramConfig["TrackFollowerNSigmaCutZ"].get<float>();
213 }
214 if (paramConfig.contains("TrackFollowerNSigmaCutPhi")) {
215 params.TrackFollowerNSigmaCutPhi = paramConfig["TrackFollowerNSigmaCutPhi"].get<float>();
216 }
217 if (paramConfig.contains("TrackFollowerMaxHypotheses")) {
218 params.TrackFollowerMaxHypotheses = std::max(1, paramConfig["TrackFollowerMaxHypotheses"].get<int>());
219 }
220 applyPassFlag("FirstPass", o2::its::IterationStep::FirstPass);
221 applyPassFlag("RebuildClusterLUT", o2::its::IterationStep::RebuildClusterLUT);
222 applyPassFlag("UseUPCMask", o2::its::IterationStep::UseUPCMask);
223 applyPassFlag("SelectUPCVertices", o2::its::IterationStep::SelectUPCVertices);
224 applyPassFlag("ResetVertices", o2::its::IterationStep::ResetVertices);
225 applyPassFlag("SkipROFsAboveThreshold", o2::its::IterationStep::SkipROFsAboveThreshold);
226 applyPassFlag("MarkVerticesAsUPC", o2::its::IterationStep::MarkVerticesAsUPC);
227 applyPassFlag("TrackFollowerTop", o2::its::IterationStep::TrackFollowerTop);
228 applyPassFlag("TrackFollowerBot", o2::its::IterationStep::TrackFollowerBot);
229 if (paramConfig.contains("PrintMemory")) {
230 params.PrintMemory = paramConfig["PrintMemory"].get<bool>();
231 }
232 if (paramConfig.contains("DropTFUponFailure")) {
233 params.DropTFUponFailure = paramConfig["DropTFUponFailure"].get<bool>();
234 }
235
236 if (paramConfig.contains("LayerZ")) {
237 params.LayerZ = paramConfig["LayerZ"].get<std::vector<float>>();
238 }
239 if (paramConfig.contains("LayerRadii")) {
240 params.LayerRadii = paramConfig["LayerRadii"].get<std::vector<float>>();
241 }
242 if (paramConfig.contains("LayerxX0")) {
243 params.LayerxX0 = paramConfig["LayerxX0"].get<std::vector<float>>();
244 }
245 if (paramConfig.contains("LayerResolution")) {
246 params.LayerResolution = paramConfig["LayerResolution"].get<std::vector<float>>();
247 }
248 if (paramConfig.contains("SystErrorY2")) {
249 params.SystErrorY2 = paramConfig["SystErrorY2"].get<std::vector<float>>();
250 }
251 if (paramConfig.contains("SystErrorZ2")) {
252 params.SystErrorZ2 = paramConfig["SystErrorZ2"].get<std::vector<float>>();
253 }
254 if (paramConfig.contains("MinPt")) {
255 params.MinPt = paramConfig["MinPt"].get<std::vector<float>>();
256 }
257 if (paramConfig.contains("AddTimeError")) {
258 params.AddTimeError = paramConfig["AddTimeError"].get<std::vector<UInt_t>>();
259 }
260
261 if (paramConfig.contains("Diamond") && paramConfig["Diamond"].is_array() && paramConfig["Diamond"].size() == 3) {
262 params.Diamond[0] = paramConfig["Diamond"][0].get<float>();
263 params.Diamond[1] = paramConfig["Diamond"][1].get<float>();
264 params.Diamond[2] = paramConfig["Diamond"][2].get<float>();
265 }
266
267 if (paramConfig.contains("MaxMemory")) {
268 params.MaxMemory = paramConfig["MaxMemory"].get<size_t>();
269 }
270
271 if (paramConfig.contains("CorrType")) {
272 int corrTypeInt = paramConfig["CorrType"].get<int>();
273 params.CorrType = static_cast<o2::base::PropagatorImpl<float>::MatCorrType>(corrTypeInt);
274 }
275
276 const auto nLayers = static_cast<size_t>(params.NLayers);
277 LOG_IF(fatal, params.LayerZ.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter LayerZ: expected " << nLayers << " entries, got " << params.LayerZ.size();
278 LOG_IF(fatal, params.LayerRadii.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter LayerRadii: expected " << nLayers << " entries, got " << params.LayerRadii.size();
279 LOG_IF(fatal, params.LayerxX0.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter LayerxX0: expected " << nLayers << " entries, got " << params.LayerxX0.size();
280 LOG_IF(fatal, params.LayerResolution.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter LayerResolution: expected " << nLayers << " entries, got " << params.LayerResolution.size();
281 LOG_IF(fatal, params.SystErrorY2.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter SystErrorY2: expected " << nLayers << " entries, got " << params.SystErrorY2.size();
282 LOG_IF(fatal, params.SystErrorZ2.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter SystErrorZ2: expected " << nLayers << " entries, got " << params.SystErrorZ2.size();
283 LOG_IF(fatal, params.AddTimeError.size() != nLayers) << "Invalid ALICE3 TRK tracking parameter AddTimeError: expected " << nLayers << " entries, got " << params.AddTimeError.size();
284
285 LOG_IF(fatal, params.MinTrackLength > params.NLayers) << "Invalid ALICE3 TRK tracking parameter MinTrackLength: expected <= NLayers (" << params.NLayers << "), got " << params.MinTrackLength;
286 const auto minPtSize = static_cast<size_t>(params.NLayers - params.MinTrackLength + 1);
287 LOG_IF(fatal, params.MinPt.size() != minPtSize) << "Invalid ALICE3 TRK tracking parameter MinPt: expected " << minPtSize << " entries, got " << params.MinPt.size();
288
289 trackingParams.push_back(params);
290 }
291 };
292
293 if (mHitRecoConfig.contains("trackingparams") && mHitRecoConfig["trackingparams"].is_array()) {
294 loadTrackingParamsFromJson(trackingParams, mHitRecoConfig["trackingparams"]);
295 } else if (mClusterRecoConfig.contains("trackingparams") && mClusterRecoConfig["trackingparams"].is_array()) {
296 loadTrackingParamsFromJson(trackingParams, mClusterRecoConfig["trackingparams"]);
297 } else {
298 LOGP(fatal, "No trackingparams field found in configuration or it is not an array. Returning empty vector.");
299 return trackingParams;
300 }
301
302 LOGP(info, "Loaded {} tracking parameter sets from configuration", trackingParams.size());
303 return trackingParams;
304}
305
307{
308 if (mMemoryPool.get() == nullptr) {
309 mMemoryPool = std::make_shared<itsmft::tracking::BoundedMemoryResource>();
310 }
311 if (mTaskArena.get() == nullptr) {
312 mTaskArena = std::make_shared<tbb::task_arena>(mTrackingThreads);
313 }
314
315 mTrackingParams = createTrackingParamsFromConfig();
316
317 auto cput = mTimer.CpuTime();
318 auto realt = mTimer.RealTime();
319 mTimer.Start(false);
320
321 const bool useGPU = mDeviceType != o2::gpu::gpudatatypes::DeviceType::CPU;
322
323 if (useGPU) {
324 runGPUTracking(pc);
325 } else {
326 o2::trk::TimeFrame<11> timeFrame;
327 o2::its::TrackerTraits<11> itsTrackerTraits;
328 runTracking(pc, timeFrame, itsTrackerTraits);
329 }
330
333
334 mTimer.Stop();
335 LOGP(info, "CPU Reconstruction time for this TF {} s (cpu), {} s (wall)", mTimer.CpuTime() - cput, mTimer.RealTime() - realt);
336}
337
338void TrackerDPL::runGPUTracking(ProcessingContext& pc)
339{
340 auto& loader = ALICE3TrackingBackendLoader::Instance();
341 switch (mDeviceType) {
343#ifdef TRK_HAS_CUDA_TRACKING
344 loader.executeFunctionAlias<int, TrackerDPL*, ProcessingContext*>("O2ALICE3GlobalReconstructionWorkflowCUDA", kGPUBackendFunction, this, &pc);
345 return;
346#else
347 LOGP(fatal, "CUDA TRK GPU tracking was requested but this build has no CUDA TRK GPU tracking backend");
348#endif
350#ifdef TRK_HAS_HIP_TRACKING
351 loader.executeFunctionAlias<int, TrackerDPL*, ProcessingContext*>("O2ALICE3GlobalReconstructionWorkflowHIP", kGPUBackendFunction, this, &pc);
352 return;
353#else
354 LOGP(fatal, "HIP TRK GPU tracking was requested but this build has no HIP TRK GPU tracking backend");
355#endif
356 default:
357 LOGP(fatal, "Unsupported TRK GPU device type {}", static_cast<int>(mDeviceType));
358 }
359}
360
362{
363 LOGF(info, "TRK CA-Tracker total timing: Cpu: %.3e Real: %.3e s in %d slots", mTimer.CpuTime(), mTimer.RealTime(), mTimer.Counter() - 1);
364}
365
366DataProcessorSpec getTrackerSpec(bool useMC, const std::string& hitRecoConfig, const std::string& clusterRecoConfig, o2::gpu::gpudatatypes::DeviceType dType, int trackingThreads)
367{
368 std::vector<InputSpec> inputs;
369 std::vector<OutputSpec> outputs;
370 outputs.emplace_back("TRK", "TRACKS", 0, Lifetime::Timeframe);
371 outputs.emplace_back("TRK", "TRACKSROF", 0, Lifetime::Timeframe);
372 outputs.emplace_back("TRK", "IRFRAMES", 0, Lifetime::Timeframe);
373 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false, // orbitResetTime
374 false, // GRPECS=true
375 false, // GRPLHCIF
376 false, // GRPMagField
377 false, // askMatLUT
378 o2::base::GRPGeomRequest::None, // geometry, but ignored until it will be put in the CCDB
379 inputs,
380 true);
381
382 if (!hitRecoConfig.empty()) {
383 if (useMC) {
384 outputs.emplace_back("TRK", "TRACKSMCTR", 0, Lifetime::Timeframe);
385 }
386 return DataProcessorSpec{
387 "trk-hits-tracker",
388 {},
389 outputs,
390 AlgorithmSpec{adaptFromTask<TrackerDPL>(ggRequest,
391 useMC,
392 hitRecoConfig,
393 clusterRecoConfig,
394 dType,
395 trackingThreads)},
396 Options{ConfigParamSpec{"max-loops", VariantType::Int, 1, {"max number of loops"}}
397#ifdef O2_WITH_ACTS
398 ,
399 {"useACTS", o2::framework::VariantType::Bool, false, {"Use ACTS for tracking"}}
400#endif
401 }};
402 }
403
404 inputs.emplace_back("dummy", "TRK", "DUMMY", 0, Lifetime::Timeframe);
405
406 if (!clusterRecoConfig.empty()) {
407 inputs.pop_back();
408 constexpr int nLayers{11};
409 for (int iLayer = 0; iLayer < nLayers; ++iLayer) {
410 inputs.emplace_back(std::format("compClusters_{}", iLayer), "TRK", "COMPCLUSTERS", iLayer, Lifetime::Timeframe);
411 inputs.emplace_back(std::format("patterns_{}", iLayer), "TRK", "PATTERNS", iLayer, Lifetime::Timeframe);
412 inputs.emplace_back(std::format("ROframes_{}", iLayer), "TRK", "CLUSTERSROF", iLayer, Lifetime::Timeframe);
413 if (useMC) {
414 inputs.emplace_back(std::format("trkmclabels_{}", iLayer), "TRK", "CLUSTERSMCTR", iLayer, Lifetime::Timeframe);
415 }
416 }
417 }
418
419 if (useMC) {
420 outputs.emplace_back("TRK", "TRACKSMCTR", 0, Lifetime::Timeframe);
421 }
422
423 return DataProcessorSpec{
424 "trk-tracker",
425 inputs,
426 outputs,
427 AlgorithmSpec{adaptFromTask<TrackerDPL>(ggRequest,
428 useMC,
429 hitRecoConfig,
430 clusterRecoConfig,
431 dType,
432 trackingThreads)},
433 Options{}};
434}
435
436} // namespace trk
437} // namespace o2
#define O2DLLoaderDef(classname)
#define O2DLLoaderImpl(classname)
Definition of the GeometryManager class.
CPU TRK TimeFrame wrapper.
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 ...