ATLAS Offline Software
Loading...
Searching...
No Matches
TrackExtensionAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
6#include "Acts/Propagator/PropagatorOptions.hpp"
8
9// Athena
10#include "AsgTools/ToolStore.h"
19
20// ACTS
21#include "Acts/Definitions/Units.hpp"
22#include "Acts/Geometry/TrackingGeometry.hpp"
23#include "Acts/Geometry/GeometryIdentifier.hpp"
24#include "Acts/MagneticField/MagneticFieldProvider.hpp"
25#include "Acts/Surfaces/Surface.hpp"
26#include "Acts/TrackFinding/CombinatorialKalmanFilter.hpp"
27#include "Acts/Surfaces/PerigeeSurface.hpp"
28#include "Acts/Utilities/TrackHelpers.hpp"
29#include "Acts/TrackFinding/TrackStateCreator.hpp"
30
31// ActsTrk
38#include "ActsInterop/Logger.h"
45
46// STL
47#include <initializer_list>
48#include <sstream>
49#include <functional>
50#include <tuple>
51#include <utility>
52#include <algorithm>
53
54
55namespace ActsTrk{
56
58 ATH_CHECK(m_pixelClusters.initialize());
60 ATH_CHECK(m_trackContainerKey.initialize());
64 ATH_CHECK(m_ctxProvider.initialize());
65 ATH_CHECK(m_pixelCalibTool.retrieve(EnableTool{not m_pixelCalibTool.empty()}));
66 ATH_CHECK(m_stripCalibTool.retrieve(EnableTool{not m_stripCalibTool.empty()}));
67 ATH_CHECK(m_hgtdCalibTool.retrieve(EnableTool{not m_hgtdCalibTool.empty()}));
69 ATH_CHECK(m_trackStatePrinter.retrieve(EnableTool{not m_trackStatePrinter.empty()}));
70 ATH_CHECK(m_actsFitter.retrieve());
71 ATH_CHECK(m_beamSpotKey.initialize());
72 m_logger = makeActsAthenaLogger(this, name());
73
74 auto magneticField = std::make_unique<ATLASMagneticFieldWrapper>();
75 std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry = m_trackingGeometrySvc->trackingGeometry();
76
77 detail::Stepper stepper(std::move(magneticField));
78 detail::Navigator::Config cfg{trackingGeometry};
79 cfg.resolvePassive = false;
80 cfg.resolveMaterial = true;
81 cfg.resolveSensitive = true;
82 detail::Navigator navigator(cfg, m_logger->cloneWithSuffix("Navigator"));
83 detail::Propagator propagator(std::move(stepper), std::move(navigator), m_logger->cloneWithSuffix("Prop"));
84
85 // Using the CKF propagator as extrapolator
86 detail::Extrapolator extrapolator = propagator;
87
88
89 // update once shared code for configuring this is available
90 Acts::TrackSelector::EtaBinnedConfig trackSelectorCfg(std::vector<double>({0, 4}));
91 trackSelectorCfg.cutSets[0].ptMin = 1000;
92 trackSelectorCfg.cutSets[0].ptMax = 1000000;
93 trackSelectorCfg.cutSets[0].minMeasurements = 3;
94 trackSelectorCfg.cutSets[0].maxHoles = 1;
95 trackSelectorCfg.cutSets[0].maxOutliers = 1;
96 trackSelectorCfg.cutSets[0].maxSharedHits = 1;
97 trackSelectorCfg.cutSets[0].maxChi2 = 25.;
98
99 detail::CKF_config ckfConfig{
100 std::move(extrapolator),
101 detail::CKF{std::move(propagator), m_logger->cloneWithSuffix("CKF")},
102 {},
103 Acts::TrackSelector{trackSelectorCfg}};
104
105 m_ckfConfig = std::make_unique<detail::CKF_config>(std::move(ckfConfig));
106 return StatusCode::SUCCESS;
107 }
108
109
110
111
112 StatusCode TrackExtensionAlg::execute(const EventContext& context) const {
114 ATH_CHECK(protoTracksHandle.isValid());
115
116 Acts::VectorTrackContainer tback;
117 Acts::VectorMultiTrajectory tsBack;
118 detail::RecoTrackContainer trackContainer(tback, tsBack);
119
120 // track finding goes here
121 Acts::VectorTrackContainer trackBackend;
122 Acts::VectorMultiTrajectory trackStateBackend;
123 detail::RecoTrackContainer tracksContainerTemp(trackBackend, trackStateBackend);
124
125 // Get Beam pos and make pSurface
126 const InDet::BeamSpotData* beamSpotData{};
127 ATH_CHECK(SG::get(beamSpotData, m_beamSpotKey, context));
128
129 // Beam Spot Position
130 Acts::Vector3 beamPos( beamSpotData->beamPos().x() * Acts::UnitConstants::mm,
131 beamSpotData->beamPos().y() * Acts::UnitConstants::mm,
132 0 );
133
134 // Construct a perigee surface as the target surface
135 std::shared_ptr<Acts::PerigeeSurface> perigeeSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(beamPos);
136
137 const Acts::GeometryContext tgContext{m_ctxProvider.getGeometryContext(context)};
138 const Acts::MagneticFieldContext mfContext{m_ctxProvider.getMagneticFieldContext(context)};
139 const Acts::CalibrationContext calContext{m_ctxProvider.getCalibrationContext(context)};
140
142
144 ATH_MSG_DEBUG("Measurements (pixels only) size: " << pixelClustersHandle->size());
145 // potential TODO: filtering only certain layers
146 detail::TrackFindingMeasurements measurements(1ul /* number of measurement containers*/);
147 measurements.addMeasurements(0, *pixelClustersHandle, *m_trackingGeometrySvc->surfaceIdMap());
148 std::optional<detail::MeasurementIndex> measurementIndex;
149
150 if (m_trackStatePrinter.isSet()) {
151 measurementIndex.emplace(1ul);
152 measurementIndex->addMeasurements(*pixelClustersHandle);
153 }
154
155 using DefaultTrackStateCreator = Acts::TrackStateCreator<ActsTrk::detail::UncalibSourceLinkAccessor::Iterator,detail::RecoTrackContainer>;
156
158 DefaultTrackStateCreator::SourceLinkAccessor slAccessorDelegate;
159 slAccessorDelegate.connect<&ActsTrk::detail::UncalibSourceLinkAccessor::range>(&slAccessor);
160
161 Acts::PropagatorPlainOptions plainOptions(tgContext, mfContext);
162 plainOptions.maxSteps = 1000;
163 plainOptions.direction= m_propagateForward ? Acts::Direction::Forward() : Acts::Direction::Backward();
164
165
166
167 TrackExtensionAlg::CKFOptions options(tgContext,
168 mfContext,
169 calContext,
170 m_ckfConfig->ckfExtensions,
171 plainOptions,
172 perigeeSurface.get());
173
174 options.targetSurface = perigeeSurface.get();
175
177 context,
182
183 DefaultTrackStateCreator defaultTrackStateCreator{};
184 defaultTrackStateCreator.sourceLinkAccessor = slAccessorDelegate;
185 defaultTrackStateCreator.calibrator.template connect<&detail::OnTrackCalibrator<detail::RecoTrackStateContainer>::calibrate>(&calibrator);
186
187 options.extensions.createTrackStates.template connect<
188 &DefaultTrackStateCreator
189 ::createTrackStates>(&defaultTrackStateCreator);
190
191 if ( not m_truthParticlesKey.empty() ) {
192 auto truthHandle = SG::ReadHandle(m_truthParticlesKey, context);
193 for ( auto truthParticle: *truthHandle ) {
194 ATH_MSG_DEBUG("truth: eta: " << truthParticle->eta() << " phi: " << truthParticle->phi() << " pt: " << truthParticle->pt());
195 }
196 }
197
198 ATH_MSG_DEBUG("Size of proto tracks collection " << protoTracksHandle->size());
199 for (const ActsTrk::ProtoTrack& protoTrack : *protoTracksHandle) {
200 if(protoTrack.measurements.empty()) continue;
201
202 const Acts::Surface* refSurface = surfAcc.get(protoTrack.measurements[0]);
203
204 auto res = m_actsFitter->fit(protoTrack.measurements, *protoTrack.parameters,
205 tgContext, mfContext, calContext, refSurface);
206 if(!res) continue;
207 if (res->size() == 0 ) continue;
208 ATH_MSG_DEBUG(".......Done fit of track with "<< protoTrack.measurements.size() << " measurements");
209 const auto trackProxy = res->getTrack(0);
210 if (not trackProxy.hasReferenceSurface()) {
211 ATH_MSG_INFO("There is not reference surface for this track");
212 continue;
213 }
214
215 Acts::BoundTrackParameters parametersAtRefSurface( trackProxy.referenceSurface().getSharedPtr(),
216 trackProxy.parameters(),
217 trackProxy.covariance(),
218 trackProxy.particleHypothesis());
219
220
221
222 ATH_MSG_DEBUG("proto track: eta: " << -1 * log(tan( parametersAtRefSurface.theta() * 0.5)) << " phi: " << parametersAtRefSurface.phi() << " pt:" << abs(1./protoTrack.parameters->qOverP() * sin(protoTrack.parameters->theta())));
223 ATH_MSG_DEBUG("Extending proto track of " << protoTrack.measurements.size() << " measurements");
224 auto result = m_ckfConfig->ckf.findTracks(parametersAtRefSurface, options,
225 tracksContainerTemp);
226
227
228 ATH_MSG_DEBUG("Built " << tracksContainerTemp.size() << " tracks from it");
229 for (detail::RecoTrackContainer::TrackProxy tempTrackProxy : tracksContainerTemp) {
230 auto destTrackProxy = trackContainer.makeTrack();
231 ATH_MSG_DEBUG("Reco MTJ size " << trackStateBackend.size() );
232 for ( size_t stateIndex=0; stateIndex < trackStateBackend.size(); ++stateIndex) {
233 auto state = trackStateBackend.getTrackState(stateIndex);
234 if (m_trackStatePrinter.isSet()) m_trackStatePrinter->printTrackState(tgContext, state, *measurementIndex, false);
235 }
236 ATH_MSG_DEBUG("Track has: " << tempTrackProxy.nMeasurements() << " measurements ");
237 ATH_MSG_DEBUG("track: eta: " << -1 * log(tan( tempTrackProxy.theta() * 0.5)) << " phi: " << tempTrackProxy.phi() << " pt:" << abs(1./tempTrackProxy.qOverP() * sin(protoTrack.parameters->theta())));
238
239 destTrackProxy.copyFrom(tempTrackProxy);
240 }
241 }
242
243
244
245 // convert to const version
246 Acts::ConstVectorTrackContainer ctback( std::move(tback) );
247 Acts::ConstVectorMultiTrajectory ctsBack( std::move(tsBack) );
248 std::unique_ptr< ActsTrk::TrackContainer > ctrackContainer = std::make_unique< ActsTrk::TrackContainer >( std::move(ctback), std::move(ctsBack) );
249
251 ATH_CHECK(trackContainerHandle.record(std::move(ctrackContainer)));
252
253 return StatusCode::SUCCESS;
254 }
255
256} // EOF namespace
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
std::pair< std::vector< unsigned int >, bool > res
Header file to be included by clients of the Monitored infrastructure.
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
ToolHandle< ActsTrk::TrackStatePrinterTool > m_trackStatePrinter
virtual StatusCode initialize() override
ToolHandle< ActsTrk::IPixelOnTrackCalibratorTool< detail::RecoTrackStateContainer > > m_pixelCalibTool
SG::ReadHandleKey< xAOD::PixelClusterContainer > m_pixelClusters
ServiceHandle< ActsTrk::ITrackingGeometrySvc > m_trackingGeometrySvc
ActsTrk::MutableTrackContainerHandlesHelper m_tracksBackendHandlesHelper
SG::WriteHandleKey< ActsTrk::TrackContainer > m_trackContainerKey
SG::ReadHandleKey< ActsTrk::ProtoTrackCollection > m_protoTrackCollectionKey
Acts::CombinatorialKalmanFilterOptions< detail::RecoTrackContainer > CKFOptions
std::unique_ptr< detail::CKF_config > m_ckfConfig
ContextUtility m_ctxProvider
Utility to fetch the geometry, magnetic field and calibration context in the event.
virtual StatusCode execute(const EventContext &context) const override
ToolHandle< ActsTrk::IFitterTool > m_actsFitter
std::unique_ptr< const Acts::Logger > m_logger
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticlesKey
ToolHandle< ActsTrk::IHGTDOnTrackCalibratorTool< detail::RecoTrackStateContainer > > m_hgtdCalibTool
Gaudi::Property< bool > m_propagateForward
SG::ReadCondHandleKey< InDet::BeamSpotData > m_beamSpotKey
ToolHandle< ActsTrk::IStripOnTrackCalibratorTool< detail::RecoTrackStateContainer > > m_stripCalibTool
std::pair< Iterator, Iterator > range(const Acts::Surface &surface) const
Inner detector / ITk calibrator implementation used in the KalmanFilterTool.
void addMeasurements(std::size_t typeIndex, const xAOD::UncalibratedMeasurementContainer &clusterContainer, const DetectorElementToActsGeometryIdMap &detectorElementToGeoid, const MeasurementIndex *measurementIndex=nullptr)
const MeasurementRangeList & measurementRanges() const
Helper class to access the Acts::surface associated with an Uncalibrated xAOD measurement.
const Acts::Surface * get(const xAOD::UncalibratedMeasurement *meas) const
Operator.
const Amg::Vector3D & beamPos() const noexcept
virtual bool isValid() override final
Can the handle be successfully dereferenced?
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Acts::SympyStepper Stepper
Adapted from Acts Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction....
GenUncalibSourceLinkAccessor< MeasurementRangeList > UncalibSourceLinkAccessor
Acts::TrackContainer< Acts::VectorTrackContainer, Acts::VectorMultiTrajectory > RecoTrackContainer
Acts::CombinatorialKalmanFilter< Propagator, RecoTrackContainer > CKF
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::string prefixFromTrackContainerName(const std::string &tracks)
Parse TrackContainer name to get the prefix for backends The name has to contain XYZTracks,...
Acts::TrackStateCreator< ActsTrk::detail::UncalibSourceLinkAccessor::Iterator, detail::RecoTrackContainer > DefaultTrackStateCreator
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())