ATLAS Offline Software
Loading...
Searching...
No Matches
TrackFindingGNNAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7// Athena
12
13// ACTS
14#include "Acts/Definitions/Units.hpp"
15#include "Acts/EventData/VectorMultiTrajectory.hpp"
16#include "Acts/EventData/VectorTrackContainer.hpp"
17#include "Acts/Geometry/TrackingGeometry.hpp"
18#include "Acts/Surfaces/Surface.hpp"
19
20// ActsTrk
24
25// STL
26#include <algorithm>
27#include <optional>
28#include <stdexcept>
29#include <string>
30#include <utility>
31#include <vector>
32
33using namespace Acts::UnitLiterals;
34
35namespace ActsTrk {
36
37
39 ISvcLocator *pSvcLocator)
40 : AthReentrantAlgorithm(name, pSvcLocator) {}
41
43
44// === initialize ==========================================================
45
47 // Athena tools
48 m_logger = makeActsAthenaLogger(this, "Acts GNN Algorithm");
49 ACTS_DEBUG("TrackFindingGNNAlg::initialize() - begin");
51 ATH_CHECK(m_trackContainerKey.initialize());
52 ATH_CHECK(m_ctxProvider.initialize());
56 ATH_CHECK(m_trackContainerKey.initialize());
57 ATH_CHECK(m_chronoSvc.retrieve());
59 ATH_CHECK(m_fitterTool.retrieve());
60 ATH_CHECK(m_gnnPipelineTool.retrieve());
61
67
68 using TSC = Acts::TrackSelector::Config;
69 m_trackSelectorConfig = Acts::TrackSelector::EtaBinnedConfig(0.0);
70
71 auto commonConfig = [&](TSC &config) {
72 config.requireReferenceSurface = true;
73 config.loc1Min = m_offlineZ0Sel.value() ? -200_mm : -150_mm; // z0 min
74 config.loc1Max = m_offlineZ0Sel.value() ? 200_mm : 150_mm; // z0 max
75 };
76
78 .addCuts(2.0,
79 [&](TSC &config) {
80 commonConfig(config);
81 config.maxHoles = m_relaxCentralHoleSel.value() ? 4 : 2;
82 config.minMeasurements = m_relaxMeasurementSel.value() ? 7 : 9;
83 config.ptMin = 900_MeV;
84 config.loc0Max = 2_mm; // d0 max
85 config.loc0Min = -2_mm; // d0 min
86 })
87 .addCuts(2.6,
88 [&](TSC &config) {
89 commonConfig(config);
90 config.maxHoles = m_relaxCentralHoleSel.value() ? 4 : 2;
91 config.minMeasurements = m_relaxMeasurementSel.value() ? 7 : 8;
92 config.ptMin = 400_MeV;
93 config.loc0Max = 2_mm; // d0 max
94 config.loc0Min = -2_mm; // d0 min
95 })
96 .addCuts([&](TSC &config) {
97 commonConfig(config);
98 config.maxHoles = 2;
99 config.minMeasurements = 7;
100 config.ptMin = 400_MeV;
101 config.loc0Max = 10_mm; // d0 max
102 config.loc0Min = -10_mm; // d0 min
103 });
104
105 ACTS_INFO("Track selector config:\n" << m_trackSelectorConfig);
106
107 ACTS_DEBUG("TrackFindingGNNAlg::initialize() - end");
108 return StatusCode::SUCCESS;
109}
110
111// === execute =============================================================
112
113StatusCode TrackFindingGNNAlg::execute(const EventContext &ctx) const {
114 ACTS_DEBUG("TrackFindingGNNAlg::execute() - begin");
115
116 std::optional<Athena::Chrono> timer;
117 timer.emplace("GNN get spacepoint handles", m_chronoSvc.get());
118
119 const Acts::GeometryContext gctx = m_ctxProvider.getGeometryContext(ctx);
120 const Acts::MagneticFieldContext mctx = m_ctxProvider.getMagneticFieldContext(ctx);
121 const Acts::CalibrationContext cctx = m_ctxProvider.getCalibrationContext(ctx);
122
123 auto detElToGeoIdMap = m_trackingGeometrySvc->surfaceIdMap();
124
125 // Collect the spacepoint containers and hand them to the GNN pipeline
126 auto pixelSPHandle = SG::makeHandle(m_xaodPixelSpacePointContainerKey, ctx);
127 ATH_CHECK(pixelSPHandle.isValid());
128 auto stripSPHandle = SG::makeHandle(m_xaodStripSpacePointContainerKey, ctx);
129 ATH_CHECK(stripSPHandle.isValid());
130 auto stripSPOVHandle =
132 ATH_CHECK(stripSPOVHandle.isValid());
133
134 std::vector<const xAOD::SpacePointContainer*> spacePointCollections{
135 pixelSPHandle.cptr(), stripSPHandle.cptr(), stripSPOVHandle.cptr()};
136
137 timer.reset();
138 timer.emplace("GNN seed building", m_chronoSvc.get());
139
140 ActsTrk::SeedContainer gnnSeeds;
141 ATH_CHECK(m_gnnPipelineTool->buildSeed(spacePointCollections, gnnSeeds));
142
143 ACTS_DEBUG("GNN produced " << gnnSeeds.size() << " seed candidates");
144
145 timer.reset();
146 timer.emplace("GNN parameter estimation + fit", m_chronoSvc.get());
147
148 Acts::VectorTrackContainer trackBackend;
149 Acts::VectorMultiTrajectory trackStateBackend;
150 constexpr std::size_t nTracksExpected = 3000;
151 trackBackend.reserve(nTracksExpected);
152 trackStateBackend.reserve(nTracksExpected * 30);
153 detail::RecoTrackContainer tracks(trackBackend, trackStateBackend);
155
156 auto retrieveSurface = [&](const ActsTrk::Seed& seed) -> const Acts::Surface& {
157 const xAOD::SpacePoint* sp = seed.sp().front();
158 auto geoId = ActsTrk::getSurfaceGeometryIdOfMeasurement(*detElToGeoIdMap, *sp->measurements().front());
159 const auto* surface = m_trackingGeometrySvc->trackingGeometry()->findSurface(geoId);
160 if (!surface) {
161 throw std::runtime_error("retrieveSurface: no Acts surface for GeometryIdentifier " + std::to_string(geoId.value()));
162 }
163 return *surface;
164 };
165
166 for (const ActsTrk::Seed gnnSeed : gnnSeeds) {
167 ActsTrk::SpacePointRange cand = gnnSeed.sp();
168
169 // The parameter estimation tool selects the SPs used for the estimate (see its parameterEstimationMode property)
170 const auto& [initialParamsOpt, estimationStatus] = m_paramEstimationTool->estimateTrackParameters(
171 gnnSeed, gctx, mctx, cctx, retrieveSurface);
172 if (!initialParamsOpt.has_value()) continue;
173
174 // Space points are already ordered by radius by the GNN pipeline tool
175 std::vector<const xAOD::UncalibratedMeasurement*> measList;
176 measList.reserve(cand.size() * 2);
177 for (const xAOD::SpacePoint* sp : cand) {
178 for (const xAOD::UncalibratedMeasurement* m : sp->measurements()) {
179 measList.push_back(m);
180 }
181 }
182
183 auto fitted = m_fitterTool->fit(measList, *initialParamsOpt, gctx, mctx, cctx);
184 if (fitted) {
185 for (auto track : *fitted) {
186 auto newTrack = tracks.makeTrack();
187 newTrack.copyFrom(track);
188 }
189 }
190 }
191
192 ACTS_DEBUG("After track fit: " << tracks.size() << " / " << gnnSeeds.size()
193 << " successfull");
194
195 timer.reset();
196 timer.emplace("Track selection & conversion", m_chronoSvc.get());
197
198 Acts::VectorTrackContainer selTrackBackend;
199 selTrackBackend.reserve(trackBackend.size());
200 detail::RecoTrackContainer selectedTracks(selTrackBackend, trackStateBackend);
202
203 Acts::TrackSelector selector(m_trackSelectorConfig);
204 for (auto track : tracks) {
205 if (selector.isValidTrack(track)) {
206 auto newTrack = selectedTracks.makeTrack();
207
208 // v45: copyFrom now copies everything including tip/stem indices
209 newTrack.copyFrom(track);
210 }
211 }
212
213 ACTS_DEBUG("GNN seeds: " << gnnSeeds.size() << ", fitted: " << tracks.size()
214 << ", selected: " << selectedTracks.size());
215
216 // Write tracks to storage again
217 Acts::ConstVectorTrackContainer constTrackBackend(std::move(selTrackBackend));
218 Acts::ConstVectorMultiTrajectory constTrackStateBackend(std::move(trackStateBackend));
219 std::unique_ptr<ActsTrk::TrackContainer> constTracksContainer
220 = std::make_unique<ActsTrk::TrackContainer>(std::move(constTrackBackend), std::move(constTrackStateBackend) );
221
222 ACTS_DEBUG("Storing track collection with key '" << m_trackContainerKey.key() << "'");
224 ATH_CHECK(trackContainerHandle.record(std::move(constTracksContainer)));
225
226 return StatusCode::SUCCESS;
227}
228} // namespace ActsTrk
#define ATH_CHECK
Evaluate an expression and check for errors.
Exception-safe IChronoSvc caller.
static Double_t sp
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
Definition Logger.cxx:64
Gaudi::Property< bool > m_relaxCentralHoleSel
std::unique_ptr< const Acts::Logger > m_logger
logging instance
detail::OnTrackCalibrator< MutableTrackStateBackend > m_uncalibMeasCalibrator
Acts::TrackSelector::EtaBinnedConfig m_trackSelectorConfig
ToolHandle< ITrackParamsEstimationTool > m_paramEstimationTool
virtual StatusCode initialize() override
Gaudi::Property< bool > m_relaxMeasurementSel
SG::ReadHandleKey< xAOD::SpacePointContainer > m_xaodStripSpacePointOverlapContainerKey
Gaudi::Property< bool > m_offlineZ0Sel
virtual StatusCode execute(const EventContext &ctx) const override
SG::ReadHandleKey< xAOD::SpacePointContainer > m_xaodPixelSpacePointContainerKey
TrackFindingGNNAlg(const std::string &name, ISvcLocator *pSvcLocator)
ServiceHandle< ActsTrk::ITrackingGeometrySvc > m_trackingGeometrySvc
SG::WriteHandleKey< TrackContainer > m_trackContainerKey
ContextUtility m_ctxProvider
Utility to fetch the geometry, magnetic field and calibration context in the event.
ServiceHandle< IChronoStatSvc > m_chronoSvc
SG::ReadHandleKey< xAOD::SpacePointContainer > m_xaodStripSpacePointContainerKey
detail::xAODUncalibMeasSurfAcc m_uncalibMeasSurfAccessor
ToolHandle< ActsTrk::IGnnPipelineTool > m_gnnPipelineTool
ToolHandle< IFitterTool > m_fitterTool
static OnTrackCalibrator NoCalibration(const ActsTrk::ITrackingGeometrySvc *trackGeoSvc)
Constructs a calibrator which copies the local position & covariance of the ITk measurements onto the...
Helper class to access the Acts::surface associated with an Uncalibrated xAOD measurement.
An algorithm that can be simultaneously executed in multiple threads.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Acts::TrackContainer< Acts::VectorTrackContainer, Acts::VectorMultiTrajectory > RecoTrackContainer
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
Acts::GeometryIdentifier getSurfaceGeometryIdOfMeasurement(const DetectorElementToActsGeometryIdMap &detector_element_to_geoid, const xAOD::UncalibratedMeasurement &measurement)
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.
std::size_t size() const noexcept
static void addFitterTypeProperty(track_container_t &tracksContainer)
add fitter column to the track container