From 83adb35e83b6ff138cff9af7df435af1927bbde9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 7 Apr 2026 12:54:01 +0200 Subject: [PATCH 1/4] Add TrackerACTS header for ACTS-based tracking --- .../include/TRKReconstruction/TrackerACTS.h | 189 ++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 Detectors/Upgrades/ALICE3/TRK/reconstruction/include/TRKReconstruction/TrackerACTS.h diff --git a/Detectors/Upgrades/ALICE3/TRK/reconstruction/include/TRKReconstruction/TrackerACTS.h b/Detectors/Upgrades/ALICE3/TRK/reconstruction/include/TRKReconstruction/TrackerACTS.h new file mode 100644 index 0000000000000..2910abf480961 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/TRK/reconstruction/include/TRKReconstruction/TrackerACTS.h @@ -0,0 +1,189 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file TrackerACTS.h +/// \brief TRK tracker using ACTS seeding algorithm +/// \author Nicolò Jacazio, Università del Piemonte Orientale (IT) +/// \since 2026-04-01 +/// + +#ifndef ALICE3_INCLUDE_TRACKERACTS_H_ +#define ALICE3_INCLUDE_TRACKERACTS_H_ + +#include "Acts/Definitions/Units.hpp" +#include "Framework/Logger.h" + +#include "ITStracking/TimeFrame.h" +#include "TH2F.h" + +namespace o2::trk +{ + +/// Configuration for the ACTS-based tracker +struct TrackerACTSConfig { + // Seeding parameters + float minPt = 0.4f * Acts::UnitConstants::GeV; ///< Minimum pT for seeds + float maxImpactParameter = 10.f * Acts::UnitConstants::mm; ///< Maximum impact parameter + float cotThetaMax = std::sinh(4.0f); ///< Maximum cot(theta), corresponds to eta ~4 + + // Delta R cuts for doublet/triplet formation + float deltaRMinBottom = 5.f * Acts::UnitConstants::mm; ///< Min deltaR for bottom-middle + float deltaRMaxBottom = 200.f * Acts::UnitConstants::mm; ///< Max deltaR for bottom-middle + float deltaRMinTop = 5.f * Acts::UnitConstants::mm; ///< Min deltaR for middle-top + float deltaRMaxTop = 200.f * Acts::UnitConstants::mm; ///< Max deltaR for middle-top + + // Z cuts + float zMin = -3000.f * Acts::UnitConstants::mm; + float zMax = 3000.f * Acts::UnitConstants::mm; + + // Collision region + float collisionRegionMin = -150.f * Acts::UnitConstants::mm; + float collisionRegionMax = 150.f * Acts::UnitConstants::mm; + + // Quality cuts + float maxSeedsPerMiddleSP = 2; + float deltaPhiMax = 0.1f; ///< Maximum phi difference for doublets +}; + +/// Space point representation for tracking +struct SpacePoint { + float x{0.f}; + float y{0.f}; + float z{0.f}; + int layer{-1}; + int clusterId{-1}; + int rof{-1}; + + // Derived quantities + float r() const { return std::hypot(x, y); } + float radius() const { return r(); } // required by Acts::CylindricalGridElement concept + float phi() const { return std::atan2(y, x); } + + // Variance estimates (can be refined based on cluster properties) + float varianceR{0.01f}; // ~100 um resolution squared + float varianceZ{0.01f}; +}; + +/// Seed (triplet of space points) +struct SeedACTS { + const SpacePoint* bottom{nullptr}; + const SpacePoint* middle{nullptr}; + const SpacePoint* top{nullptr}; + float quality{0.f}; +}; + +/// TRK Tracker using ACTS algorithms for seeding and track finding +template +class TrackerACTS +{ + public: + TrackerACTS(); + ~TrackerACTS() + { + if (mHistSpacePoints) { + mHistSpacePoints->SaveAs("/tmp/mHistSpacePoints.C"); + delete mHistSpacePoints; + mHistSpacePoints = nullptr; + } + } + + /// Adopt a TimeFrame for processing + void adoptTimeFrame(o2::its::TimeFrame& tf); + + /// Main tracking entry point: convert clusters to tracks + void clustersToTracks(); + + /// Configuration + void setConfig(const TrackerACTSConfig& cfg) { mConfig = cfg; } + TrackerACTSConfig& getConfig() { return mConfig; } + const TrackerACTSConfig& getConfig() const { return mConfig; } + + /// Set the magnetic field strength + void setBz(float bz) { mBz = bz; } + + /// Get the magnetic field strength + float getBz() const { return mBz; } + + /// Print tracking summary + void printSummary() const; + + private: + TH2F* mHistSpacePoints = nullptr; + + /// Build space points from clusters in the TimeFrame + void buildSpacePoints(int rof); + + /// Create seeds (triplets) from space points using ACTS SeedFinder + void createSeeds(); + + /// Estimate track parameters from a seed using ACTS + bool estimateTrackParams(const SeedACTS& seed, o2::its::TrackITSExt& track) const; + + /// Run track finding from seeds + void findTracks(); + + /// Assign MC labels to tracks + void computeTracksMClabels(); + + /// Helper: time a task + template + float evaluateTask(Func&& task, std::string_view taskName); + + // Configuration + TrackerACTSConfig mConfig; + + // TimeFrame data + o2::its::TimeFrame* mTimeFrame = nullptr; + + // Space points built from clusters + std::vector mSpacePoints; + std::vector> mSpacePointsPerLayer; + + // Seeds + std::vector mSeeds; + + // Tracking state + float mBz{0.5f}; ///< Magnetic field in Tesla + unsigned int mTimeFrameCounter{0}; + double mTotalTime{0.}; + + // Tracking states for logging + enum State { + SpacePointBuilding = 0, + Seeding, + TrackFinding, + NStates, + }; + State mCurState{SpacePointBuilding}; + static constexpr std::array StateNames{ + "Space point building", + "ACTS seeding", + "Track finding"}; +}; + +template +template +float TrackerACTS::evaluateTask(Func&& task, std::string_view taskName) +{ + LOG(debug) << " + Starting " << taskName; + const auto start = std::chrono::high_resolution_clock::now(); + task(); + const auto end = std::chrono::high_resolution_clock::now(); + std::chrono::duration diff{end - start}; + + LOG(debug) << " - " << taskName << " completed in: " << std::fixed << std::setprecision(2) << diff.count() << " ms"; + return static_cast(diff.count()); +} + +} // namespace o2::trk + +#endif /* ALICE3_INCLUDE_TRACKERACTS_H_ */ From 1d645a99819df94b3b97d0be2f88092de4f1c895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 7 Apr 2026 12:54:44 +0200 Subject: [PATCH 2/4] Add TrackerACTS implementation for TRK reconstruction --- .../TRK/reconstruction/src/TrackerACTS.cxx | 306 ++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 Detectors/Upgrades/ALICE3/TRK/reconstruction/src/TrackerACTS.cxx diff --git a/Detectors/Upgrades/ALICE3/TRK/reconstruction/src/TrackerACTS.cxx b/Detectors/Upgrades/ALICE3/TRK/reconstruction/src/TrackerACTS.cxx new file mode 100644 index 0000000000000..67dcfe25e33bb --- /dev/null +++ b/Detectors/Upgrades/ALICE3/TRK/reconstruction/src/TrackerACTS.cxx @@ -0,0 +1,306 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file TrackerACTS.cxx +/// \brief TRK tracker using ACTS seeding and track finding +/// \author Nicolò Jacazio, Università del Piemonte Orientale (IT) +/// \since 2026-04-01 +/// + +#include "TRKReconstruction/TrackerACTS.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace o2::trk +{ + +template +TrackerACTS::TrackerACTS() +{ + // Initialize space points storage per layer + mSpacePointsPerLayer.resize(nLayers); + mHistSpacePoints = new TH2F("hSpacePoints", "Space points; x (cm); y (cm)", 200, -100, 100, 200, -100, 100); +} + +template +void TrackerACTS::adoptTimeFrame(o2::its::TimeFrame& tf) +{ + mTimeFrame = &tf; +} + +template +void TrackerACTS::buildSpacePoints(int rof) +{ + mSpacePoints.clear(); + for (auto& layerSPs : mSpacePointsPerLayer) { + layerSPs.clear(); + } + + // Get clusters from the TimeFrame and convert to space points + for (int layer = 0; layer < nLayers; ++layer) { + // 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 + auto clusters = mTimeFrame->getUnsortedClusters()[layer]; + // Resize the clusters to the first 100 clusters for testing + // clusters = clusters.subspan(0, std::min(clusters.size(), 100)); + LOG(debug) << "ACTSTracker: got " << clusters.size() << " clusters"; + + for (size_t iCluster = 0; iCluster < clusters.size(); ++iCluster) { + const auto& cluster = clusters[iCluster]; + + SpacePoint sp; + // Check that these are in global coordinates + sp.x = cluster.xCoordinate * Acts::UnitConstants::cm; + sp.y = cluster.yCoordinate * Acts::UnitConstants::cm; + sp.z = cluster.zCoordinate * Acts::UnitConstants::cm; + + if (mHistSpacePoints) { + mHistSpacePoints->Fill(sp.x / Acts::UnitConstants::cm, sp.y / Acts::UnitConstants::cm); + } + sp.layer = layer; + sp.clusterId = static_cast(iCluster); + sp.rof = rof; + + // Position uncertainties (could be refined based on cluster properties) + sp.varianceR = 0.01f; // ~100 um resolution squared + sp.varianceZ = 0.01f; + + mSpacePoints.push_back(sp); + } + } + + // Build per-layer pointers for seeding + for (auto& sp : mSpacePoints) { + if (sp.layer >= 0 && sp.layer < nLayers) { + mSpacePointsPerLayer[sp.layer].push_back(&sp); + } + } +} + +template +void TrackerACTS::createSeeds() +{ + if (mSpacePoints.empty()) { + LOGF(info, "No space points available for seeding"); + return; + } + mSeeds.clear(); + + // Backend adaptor that exposes mSpacePoints to Acts::SpacePointContainer + struct SpacePointBackend { + using ValueType = SpacePoint; + explicit SpacePointBackend(const std::vector& sps) : m_sps{&sps} {} + std::size_t size_impl() const { return m_sps->size(); } + float x_impl(std::size_t i) const { return (*m_sps)[i].x; } + float y_impl(std::size_t i) const { return (*m_sps)[i].y; } + float z_impl(std::size_t i) const { return (*m_sps)[i].z; } + float varianceR_impl(std::size_t i) const { return (*m_sps)[i].varianceR; } + float varianceZ_impl(std::size_t i) const { return (*m_sps)[i].varianceZ; } + const SpacePoint& get_impl(std::size_t i) const { return (*m_sps)[i]; } + std::any component_impl(Acts::HashedString /*key*/, std::size_t /*i*/) const + { + LOG(fatal) << "No additional components available for space points"; + throw std::runtime_error("SpacePointBackend: no strip component available"); + } + const std::vector* m_sps; + }; + + // Wrap mSpacePoints in an Acts space-point container + SpacePointBackend backend{mSpacePoints}; + + // Configure the ACTS space point container + Acts::SpacePointContainerConfig spContainerConfig; + Acts::SpacePointContainerOptions spContainerOpts; + spContainerOpts.beamPos = {0.f, 0.f}; + Acts::SpacePointContainer spContainer{spContainerConfig, spContainerOpts, backend}; + + // Configure the ACTS seed finder + const unsigned int maxSeeds = static_cast(mConfig.maxSeedsPerMiddleSP); + Acts::SeedFilterConfig filterConfig; + filterConfig.maxSeedsPerSpM = maxSeeds; + + // ACTS requires minPt / bFieldInZ >= rMax / 2 (minHelixRadius >= rMax/2). + // Cap rMax so that the constraint is satisfied for the configured minPt and field. + const float bFieldInZ = mBz * Acts::UnitConstants::T; + const float safeRMax = 1.8f * mConfig.minPt / bFieldInZ; // 10% margin below the hard limit + + using SPProxy = typename Acts::SpacePointContainer::SpacePointProxyType; + Acts::SeedFinderConfig finderConfig; + finderConfig.rMin = 0.f; + finderConfig.rMax = 100.f * Acts::UnitConstants::cm; + finderConfig.zMin = mConfig.zMin; + finderConfig.zMax = mConfig.zMax; + finderConfig.deltaRMin = std::min(mConfig.deltaRMinBottom, mConfig.deltaRMinTop); + finderConfig.deltaRMax = std::max(mConfig.deltaRMaxBottom, mConfig.deltaRMaxTop); + finderConfig.deltaRMinBottomSP = mConfig.deltaRMinBottom; + finderConfig.deltaRMaxBottomSP = mConfig.deltaRMaxBottom; + finderConfig.deltaRMinTopSP = mConfig.deltaRMinTop; + finderConfig.deltaRMaxTopSP = mConfig.deltaRMaxTop; + finderConfig.collisionRegionMin = mConfig.collisionRegionMin; + finderConfig.collisionRegionMax = mConfig.collisionRegionMax; + finderConfig.cotThetaMax = mConfig.cotThetaMax; + finderConfig.minPt = mConfig.minPt; + finderConfig.impactMax = mConfig.maxImpactParameter; + finderConfig.maxSeedsPerSpM = maxSeeds; + finderConfig.sigmaScattering = 5.f; + finderConfig.radLengthPerSeed = 0.05f; + finderConfig.seedFilter = std::make_shared>(filterConfig); + finderConfig = finderConfig.calculateDerivedQuantities(); + Acts::SeedFinder> seedFinder{finderConfig, + Acts::getDefaultLogger("Finder", Acts::Logging::Level::VERBOSE)}; + + // Configure and create the cylindrical space-point grid + Acts::CylindricalSpacePointGridConfig gridConfig; + gridConfig.minPt = finderConfig.minPt; + gridConfig.rMin = finderConfig.rMin; + gridConfig.rMax = finderConfig.rMax; + gridConfig.zMin = finderConfig.zMin; + gridConfig.zMax = finderConfig.zMax; + gridConfig.deltaRMax = finderConfig.deltaRMax; + gridConfig.cotThetaMax = finderConfig.cotThetaMax; + gridConfig.impactMax = finderConfig.impactMax; + + Acts::CylindricalSpacePointGridOptions gridOpts; + gridOpts.bFieldInZ = bFieldInZ; + + Acts::SeedFinderOptions finderOpts; + finderOpts.beamPos = spContainerOpts.beamPos; + finderOpts.bFieldInZ = gridOpts.bFieldInZ; + try { + finderOpts = finderOpts.calculateDerivedQuantities(finderConfig); + } catch (const std::exception& e) { + LOG(fatal) << "Error in seed finder configuration: " << e.what(); + return; + } + + Acts::CylindricalSpacePointGrid grid = Acts::CylindricalSpacePointGridCreator::createGrid(gridConfig, gridOpts); + try { + Acts::CylindricalSpacePointGridCreator::fillGrid(finderConfig, finderOpts, grid, + spContainer.begin(), spContainer.end()); + } catch (const std::exception& e) { + LOG(fatal) << "Error during grid creation/filling: " << e.what(); + return; + } + LOG(debug) << "Grid created with " << grid.dimensions(); + + // Build the binned group and iterate over triplet combinations + Acts::GridBinFinder<3ul> bottomBinFinder{1, std::vector>{}, 0}; + Acts::GridBinFinder<3ul> topBinFinder{1, std::vector>{}, 0}; + Acts::CylindricalBinnedGroup spGroup{std::move(grid), bottomBinFinder, topBinFinder}; + + std::vector>> seedsPerGroup; + typename Acts::SeedFinder>::SeedingState seedingState; + seedingState.spacePointMutableData.resize(spContainer.size()); + const Acts::Range1D rMiddleSPRange; + for (auto [bottom, middle, top] : spGroup) { + auto& v = seedsPerGroup.emplace_back(); + try { + seedFinder.createSeedsForGroup(finderOpts, seedingState, spGroup.grid(), v, bottom, middle, top, rMiddleSPRange); + } catch (const std::exception& e) { + LOG(fatal) << "Error during seed finding for a group: " << e.what(); + return; + } + } + LOG(debug) << "Seed finding completed, found " << seedsPerGroup.size() << " groups with seeds"; + + // Convert Acts seeds to the internal SeedACTS representation + for (const auto& groupSeeds : seedsPerGroup) { + for (const auto& actsSeed : groupSeeds) { + SeedACTS seed; + seed.bottom = &actsSeed.sp()[0]->externalSpacePoint(); + seed.middle = &actsSeed.sp()[1]->externalSpacePoint(); + seed.top = &actsSeed.sp()[2]->externalSpacePoint(); + seed.quality = actsSeed.seedQuality(); + mSeeds.push_back(seed); + } + } + + LOGF(info, "Created %zu seeds from %zu space points", mSeeds.size(), mSpacePoints.size()); +} + +template +bool TrackerACTS::estimateTrackParams(const SeedACTS& seed, o2::its::TrackITSExt& track) const +{ + return true; +} + +template +void TrackerACTS::findTracks() +{ +} + +template +void TrackerACTS::computeTracksMClabels() +{ +} + +template +void TrackerACTS::clustersToTracks() +{ + if (!mTimeFrame) { + LOG(error) << "Cannot run TrackerACTS: No TimeFrame adopted"; + return; + } + + double totalTime = 0.; + LOG(info) << "==== TRK ACTS Tracking ===="; + LOG(info) << "Processing " << mTimeFrame->getNrof() << " ROFs with B = " << mBz << " T"; + + // Process each ROF + for (int iROF = 0; iROF < mTimeFrame->getNrof(); ++iROF) { + LOG(info) << "Processing ROF " << iROF; + // Build space points + mCurState = SpacePointBuilding; + totalTime += evaluateTask([this, iROF]() { buildSpacePoints(iROF); }, + StateNames[mCurState]); + + // Run seeding + mCurState = Seeding; + totalTime += evaluateTask([this]() { createSeeds(); }, + StateNames[mCurState]); + + // Find tracks + mCurState = TrackFinding; + totalTime += evaluateTask([this]() { findTracks(); }, + StateNames[mCurState]); + } + + // MC labeling + if (mTimeFrame->hasMCinformation()) { + computeTracksMClabels(); + } + + LOG(info) << "=== TimeFrame " << mTimeFrameCounter << " completed in: " << totalTime << " ms ==="; + + ++mTimeFrameCounter; + mTotalTime += totalTime; +} + +template +void TrackerACTS::printSummary() const +{ + float avgTF = mTimeFrameCounter > 0 ? static_cast(mTotalTime) / mTimeFrameCounter : 0.f; + LOGP(info, "TrackerACTS summary: Processed {} TFs in TOT={:.2f} ms, AVG/TF={:.2f} ms", + mTimeFrameCounter, mTotalTime, avgTF); +} + +// Explicit template instantiations +template class TrackerACTS<11>; +} // namespace o2::trk From 61454325e18fd53e8602cca3ebccb9fae1d3e5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 7 Apr 2026 12:55:20 +0200 Subject: [PATCH 3/4] Add TrackerACTS to CMakeLists and dictionary headers --- Detectors/Upgrades/ALICE3/TRK/reconstruction/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Detectors/Upgrades/ALICE3/TRK/reconstruction/CMakeLists.txt b/Detectors/Upgrades/ALICE3/TRK/reconstruction/CMakeLists.txt index 81a75e209124a..59a7f47955938 100644 --- a/Detectors/Upgrades/ALICE3/TRK/reconstruction/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/TRK/reconstruction/CMakeLists.txt @@ -18,6 +18,7 @@ o2_add_library(TRKReconstruction SOURCES src/TimeFrame.cxx src/Clusterer.cxx $<$:src/ClustererACTS.cxx> + $<$:src/TrackerACTS.cxx> PUBLIC_LINK_LIBRARIES O2::ITStracking O2::GPUCommon @@ -45,7 +46,8 @@ set(dictHeaders include/TRKReconstruction/TimeFrame.h include/TRKReconstruction/Clusterer.h) if(Acts_FOUND) - list(APPEND dictHeaders include/TRKReconstruction/ClustererACTS.h) + list(APPEND dictHeaders include/TRKReconstruction/ClustererACTS.h + include/TRKReconstruction/TrackerACTS.h) endif() o2_target_root_dictionary(TRKReconstruction From feaa6801962c66f93219fe8ec76be263bd3f9126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Jacazio?= Date: Tue, 7 Apr 2026 12:58:39 +0200 Subject: [PATCH 4/4] Add ACTS support for tracking in TrackerSpec --- .../ALICE3/TRK/workflow/src/TrackerSpec.cxx | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/TRK/workflow/src/TrackerSpec.cxx b/Detectors/Upgrades/ALICE3/TRK/workflow/src/TrackerSpec.cxx index 20bd45557dac5..b587ec24775b4 100644 --- a/Detectors/Upgrades/ALICE3/TRK/workflow/src/TrackerSpec.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/workflow/src/TrackerSpec.cxx @@ -29,6 +29,10 @@ #include "TRKWorkflow/TrackerSpec.h" #include +#ifdef O2_WITH_ACTS +#include "TRKReconstruction/TrackerACTS.h" +#endif + #include #include @@ -61,6 +65,10 @@ void TrackerDPL::init(InitContext& ic) // mITSTrackingInterface.setTraitsFromProvider(mChainITS->GetITSVertexerTraits(), // mChainITS->GetITSTrackerTraits(), // mChainITS->GetITSTimeframe()); + +#ifdef O2_WITH_ACTS + mUseACTS = ic.options().get("useACTS"); +#endif } void TrackerDPL::stop() @@ -276,14 +284,13 @@ void TrackerDPL::run(ProcessingContext& pc) itsTrackerTraits.setMemoryPool(mMemoryPool); itsTrackerTraits.setNThreads(mTaskArena->max_concurrency(), mTaskArena); itsTrackerTraits.adoptTimeFrame(static_cast*>(&timeFrame)); - itsTracker.adoptTimeFrame(timeFrame); itsTrackerTraits.setBz(mHitRecoConfig["geometry"]["bz"].get()); auto field = new field::MagneticField("ALICE3Mag", "ALICE 3 Magnetic Field", mHitRecoConfig["geometry"]["bz"].get() / 5.f, 0.0, o2::field::MagFieldParam::k5kGUniform); TGeoGlobalMagField::Instance()->SetField(field); TGeoGlobalMagField::Instance()->Lock(); + itsTracker.adoptTimeFrame(timeFrame); - int nRofs = timeFrame.loadROFsFromHitTree(hitsTree, gman, mHitRecoConfig); - + const int nRofs = timeFrame.loadROFsFromHitTree(hitsTree, gman, mHitRecoConfig); const int inROFpileup{mHitRecoConfig.contains("inROFpileup") ? mHitRecoConfig["inROFpileup"].get() : 1}; // Add primary vertices from MC headers for each ROF @@ -293,6 +300,16 @@ void TrackerDPL::run(ProcessingContext& pc) itsTrackerTraits.updateTrackingParameters(trackingParams); +#ifdef O2_WITH_ACTS + if (mUseACTS) { + LOG(info) << "Running the tracking with ACTS"; + o2::trk::TrackerACTS<11> actsTracker; + actsTracker.setBz(mHitRecoConfig["geometry"]["bz"].get()); + actsTracker.adoptTimeFrame(timeFrame); + actsTracker.clustersToTracks(); + } +#endif + const auto trackingLoopStart = std::chrono::steady_clock::now(); for (size_t iter{0}; iter < trackingParams.size(); ++iter) { LOGP(info, "{}", trackingParams[iter].asString()); @@ -391,7 +408,12 @@ DataProcessorSpec getTrackerSpec(bool useMC, const std::string& hitRecoConfig, o useMC, hitRecoConfig, dType)}, - Options{ConfigParamSpec{"max-loops", VariantType::Int, 1, {"max number of loops"}}}}; + Options{ConfigParamSpec{"max-loops", VariantType::Int, 1, {"max number of loops"}} +#ifdef O2_WITH_ACTS + , + {"useACTS", o2::framework::VariantType::Bool, false, {"Use ACTS for tracking"}} +#endif + }}; } inputs.emplace_back("dummy", "TRK", "DUMMY", 0, Lifetime::Timeframe);