245 if (mMemoryPool.get() ==
nullptr) {
246 mMemoryPool = std::make_shared<its::BoundedMemoryResource>();
248 if (mTaskArena.get() ==
nullptr) {
249 mTaskArena = std::make_shared<tbb::task_arena>(1);
252 auto trackingParams = createTrackingParamsFromConfig();
254 auto cput = mTimer.CpuTime();
255 auto realt = mTimer.RealTime();
259#ifndef TRK_HAS_GPU_TRACKING
261 LOGP(fatal,
"TRK GPU tracking was requested but this build has no TRK GPU tracking backend");
264#ifdef TRK_HAS_CUDA_TRACKING
266 LOGP(fatal,
"This build provides the CUDA TRK tracking backend only, but device type {} was requested",
static_cast<int>(mDeviceType));
268#elif defined(TRK_HAS_HIP_TRACKING)
270 LOGP(fatal,
"This build provides the HIP TRK tracking backend only, but device type {} was requested",
static_cast<int>(mDeviceType));
275 auto runTracking = [&](
auto& timeFrame,
auto& trackerTraits) {
277 timeFrame.setMemoryPool(mMemoryPool);
278 trackerTraits.setMemoryPool(mMemoryPool);
279 trackerTraits.setNThreads(mTaskArena->max_concurrency(), mTaskArena);
282 trackerTraits.updateTrackingParameters(trackingParams);
285 if (!mHitRecoConfig.empty()) {
286 TFile hitsFile(mHitRecoConfig[
"inputfiles"][
"hits"].
get<std::string>().c_str(),
"READ");
287 TFile mcHeaderFile(mHitRecoConfig[
"inputfiles"][
"mcHeader"].
get<std::string>().c_str(),
"READ");
288 TTree* hitsTree = hitsFile.Get<TTree>(
"o2sim");
289 std::vector<o2::trk::Hit>* trkHit =
nullptr;
290 hitsTree->SetBranchAddress(
"TRKHit", &trkHit);
292 TTree* mcHeaderTree = mcHeaderFile.Get<TTree>(
"o2sim");
294 mcHeaderTree->SetBranchAddress(
"MCEventHeader.", &mcheader);
299 const Long64_t
nEvents{hitsTree->GetEntries()};
300 LOGP(info,
"Starting {} reconstruction from hits for {} events", trackerTraits.getName(),
nEvents);
302 trackerTraits.setBz(mHitRecoConfig[
"geometry"][
"bz"].get<float>());
304 TGeoGlobalMagField::Instance()->SetField(field);
305 TGeoGlobalMagField::Instance()->Lock();
307 nRofs = timeFrame.loadROFsFromHitTree(hitsTree, gman, mHitRecoConfig);
308 const int inROFpileup{mHitRecoConfig.contains(
"inROFpileup") ? mHitRecoConfig[
"inROFpileup"].get<
int>() : 1};
309 timeFrame.getPrimaryVerticesFromMC(mcHeaderTree, nRofs,
nEvents, inROFpileup);
310 }
else if (!mClusterRecoConfig.empty()) {
311 LOGP(info,
"Starting {} reconstruction from clusters", trackerTraits.getName());
316 trackerTraits.setBz(mClusterRecoConfig[
"geometry"][
"bz"].get<float>());
318 TGeoGlobalMagField::Instance()->SetField(field);
319 TGeoGlobalMagField::Instance()->Lock();
321 constexpr int nLayers{11};
322 std::array<gsl::span<const o2::trk::Cluster>, nLayers> layerClusters;
323 std::array<gsl::span<const unsigned char>, nLayers> layerPatterns;
324 std::array<gsl::span<const o2::trk::ROFRecord>, nLayers> layerROFs;
325 std::array<const dataformats::MCTruthContainer<MCCompLabel>*, nLayers> layerLabels{};
327 size_t nInputRofs{0};
328 for (
int iLayer = 0; iLayer < nLayers; ++iLayer) {
329 layerClusters[iLayer] = pc.
inputs().
get<gsl::span<o2::trk::Cluster>>(std::format(
"compClusters_{}", iLayer));
330 layerPatterns[iLayer] = pc.
inputs().
get<gsl::span<unsigned char>>(std::format(
"patterns_{}", iLayer));
331 layerROFs[iLayer] = pc.
inputs().
get<gsl::span<o2::trk::ROFRecord>>(std::format(
"ROframes_{}", iLayer));
332 nInputRofs = std::max(nInputRofs, layerROFs[iLayer].
size());
338 timeFrame.deriveAndInitTiming(layerROFs);
340 const float yPlaneMLOT = 0.0010f;
341 nRofs = timeFrame.loadROFrameData(layerROFs, layerClusters, layerPatterns, mIsMC ? &layerLabels :
nullptr, yPlaneMLOT);
342 timeFrame.addTruthSeedingVertices();
345 const auto trackingLoopStart = std::chrono::steady_clock::now();
346 for (
size_t iter{0}; iter < trackingParams.size(); ++iter) {
347 LOGP(info,
"{}", trackingParams[iter].
asString());
348 trackerTraits.initialiseTimeFrame(iter);
349 trackerTraits.computeLayerTracklets(iter, -1);
350 LOGP(info,
"Number of tracklets in iteration {}: {}", iter, timeFrame.getNumberOfTracklets());
351 trackerTraits.computeLayerCells(iter);
352 LOGP(info,
"Number of cells in iteration {}: {}", iter, timeFrame.getNumberOfCells());
353 trackerTraits.findCellsNeighbours(iter);
354 LOGP(info,
"Number of cell neighbours in iteration {}: {}", iter, timeFrame.getNumberOfNeighbours());
355 trackerTraits.findRoads(iter);
356 LOGP(info,
"Number of roads in iteration {}: {}", iter, timeFrame.getNumberOfTracks());
358 const auto trackingLoopElapsedMs = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - trackingLoopStart).count();
359 LOGP(info,
"Tracking iterations block took {} ms", trackingLoopElapsedMs);
365 const auto& tracks = timeFrame.getTracks();
366 const auto&
labels = timeFrame.getTracksLabel();
367 std::vector<o2::its::TrackITS> allTracks(tracks.begin(), tracks.end());
368 std::vector<o2::MCCompLabel> allLabels;
370 int totalTracks = allTracks.size();
376 for (
const auto&
label : allLabels) {
377 if (
label.isFake()) {
385 LOGP(info,
"=== Tracking Summary ===");
386 LOGP(info,
"Total tracks reconstructed: {}", totalTracks);
387 LOGP(info,
"Good tracks: {} ({:.1f}%)", goodTracks, totalTracks > 0 ? 100.0 * goodTracks / totalTracks : 0);
388 LOGP(info,
"Fake tracks: {} ({:.1f}%)", fakeTracks, totalTracks > 0 ? 100.0 * fakeTracks / totalTracks : 0);
390 const auto& rofView = timeFrame.getROFOverlapTableView();
391 const auto& clockLayer = rofView.getClockLayer();
392 const int clockLayerId = rofView.getClock();
393 const int64_t anchorBC = timeFrame.getTFAnchorIR().toLong();
395 int highestROF =
static_cast<int>(clockLayer.mNROFsTF);
396 for (
const auto& trc : allTracks) {
397 highestROF = std::max(highestROF,
static_cast<int>(clockLayer.getROF(trc.getTimeStamp())));
399 for (
const auto& vtx : timeFrame.getPrimaryVertices()) {
400 highestROF = std::max(highestROF,
static_cast<int>(clockLayer.getROF(vtx.getTimeStamp().lower())));
403 std::vector<o2::trk::ROFRecord> allTrackROFs(highestROF);
404 for (
size_t iROF = 0; iROF < allTrackROFs.size(); ++iROF) {
405 auto& rof = allTrackROFs[iROF];
407 ir.
setFromLong(anchorBC +
static_cast<int64_t
>(clockLayer.getROFStartInBC(iROF)));
409 rof.setROFrame(iROF);
410 rof.setFirstEntry(0);
414 std::vector<int> rofEntries(highestROF + 1, 0);
415 for (
const auto& trc : allTracks) {
416 const int rof =
static_cast<int>(clockLayer.getROF(trc.getTimeStamp()));
417 if (rof >= 0 && rof < highestROF) {
421 std::exclusive_scan(rofEntries.begin(), rofEntries.end(), rofEntries.begin(), 0);
423 std::vector<o2::dataformats::IRFrame> irFrames;
424 irFrames.reserve(allTrackROFs.size());
425 const auto& maskView = timeFrame.getROFMaskView();
426 const auto rofLenMinus1 = clockLayer.mROFLength > 0 ? clockLayer.mROFLength - 1 : 0;
427 for (
size_t iROF = 0; iROF < allTrackROFs.size(); ++iROF) {
428 allTrackROFs[iROF].setFirstEntry(rofEntries[iROF]);
429 allTrackROFs[iROF].setNEntries(rofEntries[iROF + 1] - rofEntries[iROF]);
430 if (maskView.isROFEnabled(clockLayerId,
static_cast<int>(iROF))) {
431 const auto& bcStart = allTrackROFs[iROF].getBCData();
432 auto& irFrame = irFrames.emplace_back(bcStart, bcStart + rofLenMinus1);
433 irFrame.info = allTrackROFs[iROF].getNEntries();
444 LOGP(info,
"TRK pushed {} tracks in {} ROFs and {} IR frames{}",
445 allTracks.size(), allTrackROFs.size(), irFrames.size(),
446 mIsMC ?
" (with MC labels)" :
"");
451#ifdef TRK_HAS_GPU_TRACKING
455 if (!mGPUAllocator) {
456 mGPUAllocator = std::make_shared<o2::trk::GPUExternalAllocator>();
458 timeFrame.setFrameworkAllocator(mGPUAllocator.get());
459 runTracking(timeFrame, itsTrackerTraits);
465 runTracking(timeFrame, itsTrackerTraits);
472 LOGP(info,
"CPU Reconstruction time for this TF {} s (cpu), {} s (wall)", mTimer.CpuTime() - cput, mTimer.RealTime() - realt);
482 std::vector<InputSpec> inputs;
483 std::vector<OutputSpec> outputs;
484 outputs.emplace_back(
"TRK",
"TRACKS", 0, Lifetime::Timeframe);
485 outputs.emplace_back(
"TRK",
"TRACKSROF", 0, Lifetime::Timeframe);
486 outputs.emplace_back(
"TRK",
"IRFRAMES", 0, Lifetime::Timeframe);
487 auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(
false,
496 if (!hitRecoConfig.empty()) {
498 outputs.emplace_back(
"TRK",
"TRACKSMCTR", 0, Lifetime::Timeframe);
517 inputs.emplace_back(
"dummy",
"TRK",
"DUMMY", 0, Lifetime::Timeframe);
519 if (!clusterRecoConfig.empty()) {
521 constexpr int nLayers{11};
522 for (
int iLayer = 0; iLayer < nLayers; ++iLayer) {
523 inputs.emplace_back(std::format(
"compClusters_{}", iLayer),
"TRK",
"COMPCLUSTERS", iLayer, Lifetime::Timeframe);
524 inputs.emplace_back(std::format(
"patterns_{}", iLayer),
"TRK",
"PATTERNS", iLayer, Lifetime::Timeframe);
525 inputs.emplace_back(std::format(
"ROframes_{}", iLayer),
"TRK",
"CLUSTERSROF", iLayer, Lifetime::Timeframe);
527 inputs.emplace_back(std::format(
"trkmclabels_{}", iLayer),
"TRK",
"CLUSTERSMCTR", iLayer, Lifetime::Timeframe);
533 outputs.emplace_back(
"TRK",
"TRACKSMCTR", 0, Lifetime::Timeframe);