ATLAS Offline Software
Loading...
Searching...
No Matches
ExtrapolationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
8// ATHENA
9#include "GaudiKernel/IInterface.h"
10
11// PACKAGE
13#include "ActsInterop/Logger.h"
14
15// ACTS
16#include "Acts/Propagator/Navigator.hpp"
17#include "Acts/Propagator/EigenStepper.hpp"
18#include "Acts/Propagator/Propagator.hpp"
19#include "Acts/Propagator/ActorList.hpp"
20#include <Acts/Propagator/StraightLineStepper.hpp>
21#include "Acts/Propagator/EigenStepperDefaultExtension.hpp"
22
23#include "Acts/Utilities/Logger.hpp"
24
25// BOOST
26#include <boost/variant/variant.hpp>
27#include <boost/variant/apply_visitor.hpp>
28#include <boost/variant/static_visitor.hpp>
29
30// STL
31#include <iostream>
32#include <memory>
33
34namespace {
35 using SteppingLogger = Acts::detail::SteppingLogger;
36 using EndOfWorld = Acts::EndOfWorldReached;
37
38 using CurvedStepper_t = Acts::EigenStepper<Acts::EigenStepperDefaultExtension>;
39 using CurvedPropagator_t = Acts::Propagator<CurvedStepper_t, Acts::Navigator>;
40 using StraightStepper_t = Acts::StraightLineStepper;
41 using StraightPropagator_t = Acts::Propagator<StraightStepper_t, Acts::Navigator>;
42}
43
45 using VariantPropagatorBase = boost::variant<CurvedPropagator_t, StraightPropagator_t>;
46
48 {
49 public:
50 using VariantPropagatorBase::VariantPropagatorBase;
51 };
52}
53
55
56namespace ActsTrk{
57
58
60 const std::string& name,
61 const IInterface* parent):
62 base_class{type,name, parent} {}
63
65
66StatusCode
68{
69
70
71 ATH_MSG_INFO("Initializing ACTS extrapolation");
72
73 m_logger = makeActsAthenaLogger(this, name());
74
76
77 Acts::Navigator::Config navConfig{m_trackingGeometryTool->trackingGeometry()};
78 Acts::Navigator navigator{std::move(navConfig), logger().clone()};
79
81 if (m_fieldMode == "ATLAS") {
82 ATH_MSG_INFO("Using ATLAS magnetic field service");
83
84 auto bField = std::make_shared<ATLASMagneticFieldWrapper>();
85
86 CurvedStepper_t stepper{std::move(bField)};
87 CurvedPropagator_t propagator{std::move(stepper), std::move(navigator),
88 logger().clone()};
89 m_varProp = std::make_unique<VariantPropagator>(propagator);
90 }
91 else if (m_fieldMode == "Constant") {
92 if (m_constantFieldVector.value().size() != 3)
93 {
94 ATH_MSG_ERROR("Incorrect field vector size. Using empty field.");
95 return StatusCode::FAILURE;
96 }
97
98 Acts::Vector3 constantFieldVector = Acts::Vector3(m_constantFieldVector[0],
101
102 ATH_MSG_INFO("Using constant magnetic field: (Bx, By, Bz) = "
103 <<Amg::toString(constantFieldVector));
104
105 auto bField = std::make_shared<Acts::ConstantBField>(constantFieldVector);
106 CurvedStepper_t stepper{std::move(bField)};
107 CurvedPropagator_t propagator{std::move(stepper), std::move(navigator), logger().clone()};
108 m_varProp = std::make_unique<VariantPropagator>(propagator);
109 } else if (m_fieldMode == "StraightLine") {
110 Acts::StraightLineStepper stepper{};
111 StraightPropagator_t propagator{stepper, std::move(navigator), logger().clone()};
112 m_varProp = std::make_unique<VariantPropagator>(propagator);
113 } else {
114 ATH_MSG_FATAL("Invalid mode provided "<<m_fieldMode<<". Allowed : \"ATLAS\", \"Constant\", \"StraightLine\".");
115 return StatusCode::FAILURE;
116 }
117
118 ATH_MSG_INFO("ACTS extrapolation successfully initialized");
119 return StatusCode::SUCCESS;
120}
121
122
123Acts::Result<ExtrapolationTool::PropagationOutput>
125 const Acts::BoundTrackParameters& startParameters,
126 Acts::Direction navDir /*= Acts::Direction::Forward()*/,
127 double pathLimit /*= std::numeric_limits<double>::max()*/) const
128{
129
130 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
131
132 Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
133 const GeometryContext& geo_ctx
134 = m_trackingGeometryTool->getGeometryContext(ctx);
135 auto anygctx = geo_ctx.context();
136
137 PropagationOutput output;
138
139 auto res = boost::apply_visitor([&](const auto& propagator) -> Acts::Result<ExtrapolationTool::PropagationOutput> {
140 using Propagator = std::decay_t<decltype(propagator)>;
141
142 // Action list and abort list
143 using ActorList =
144 Acts::ActorList<SteppingLogger, Acts::MaterialInteractor, EndOfWorld>;
145 using Options = typename Propagator::template Options<ActorList>;
146
147 Options options = prepareOptions<Options>(anygctx, mctx, startParameters, navDir, pathLimit);
148
149 auto result = propagator.propagate(startParameters, options);
150 if (!result.ok()) {
151 return result.error();
152 }
153 auto& propRes = *result;
154
155 auto steppingResults = propRes.template get<SteppingLogger::result_type>();
156 auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
157 output.first = std::move(steppingResults.steps);
158 output.second = std::move(materialResult);
159 // try to force return value optimization, not sure this is necessary
160 return std::move(output);
161 }, *m_varProp);
162
163 if (!res.ok()) {
164 ATH_MSG_DEBUG("Got error during propagation: "
165 << res.error() << " " << res.error().message()
166 << ". Returning empty step vector.");
167 return res.error();
168 }
169 output = std::move(*res);
170
171 ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
172 if(output.first.size() == 0) {
173 ATH_MSG_WARNING("ZERO steps returned by stepper, that is not typically a good sign");
174 }
175
176 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
177
178 return output;
179}
180
181
182
183Acts::Result<Acts::BoundTrackParameters>
184ExtrapolationTool::propagate(const EventContext& ctx,
185 const Acts::BoundTrackParameters& startParameters,
186 Acts::Direction navDir /*= Acts::Direction::Forward()*/,
187 double pathLimit /*= std::numeric_limits<double>::max()*/) const
188{
189 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
190
191 Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
192 const GeometryContext& geo_ctx
193 = m_trackingGeometryTool->getGeometryContext(ctx);
194 auto anygctx = geo_ctx.context();
195
196 auto parameters = boost::apply_visitor([&](const auto& propagator) -> Acts::Result<Acts::BoundTrackParameters> {
197 using Propagator = std::decay_t<decltype(propagator)>;
198
199 // Action list and abort list
200 using ActorList =
201 Acts::ActorList<Acts::MaterialInteractor, EndOfWorld>;
202 using Options = typename Propagator::template Options<ActorList>;
203
204 Options options = prepareOptions<Options>(anygctx, mctx, startParameters, navDir, pathLimit);
205
206
207 auto result = propagator.propagate(startParameters, options);
208 if (!result.ok()) {
209 ATH_MSG_DEBUG("Got error during propagation:" << result.error());
210 return result.error();
211 }
212 if (!result.value().endParameters.has_value()) {
213 ATH_MSG_DEBUG("Propagation did not result in valid end parameters.");
214 return Acts::PropagatorError::Failure;
215 }
216 return result.value().endParameters.value();
217 }, *m_varProp);
218
219 return parameters;
220}
221
222Acts::Result<ExtrapolationTool::PropagationOutput>
224 const Acts::BoundTrackParameters& startParameters,
225 const Acts::Surface& target,
226 Acts::Direction navDir /*= Acts::Direction::Forward()*/,
227 double pathLimit /*= std::numeric_limits<double>::max()*/) const
228{
229 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
230
231 PropagationOutput output;
232
233 Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
234 const GeometryContext& geo_ctx
235 = m_trackingGeometryTool->getGeometryContext(ctx);
236 auto anygctx = geo_ctx.context();
237
238 auto res = boost::apply_visitor([&](const auto& propagator) -> Acts::Result<ExtrapolationTool::PropagationOutput> {
239 using Propagator = std::decay_t<decltype(propagator)>;
240
241 // Action list and abort list
242 using ActorList =
243 Acts::ActorList<SteppingLogger, Acts::MaterialInteractor>;
244 using Options = typename Propagator::template Options<ActorList>;
245
246 Options options = prepareOptions<Options>(anygctx, mctx, startParameters, navDir, pathLimit);
247 auto result = target.type() == Acts::Surface::Perigee ?
248 propagator.template propagate<Options, Acts::ForcedSurfaceReached, Acts::PathLimitReached>(startParameters, target, options) :
249 propagator.template propagate<Options, Acts::SurfaceReached, Acts::PathLimitReached>(startParameters, target, options);
250
251
252 if (!result.ok()) {
253 return result.error();
254 }
255 auto& propRes = *result;
256
257 auto steppingResults = propRes.template get<SteppingLogger::result_type>();
258 auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
259 output.first = std::move(steppingResults.steps);
260 output.second = std::move(materialResult);
261 return std::move(output);
262 }, *m_varProp);
263
264 if (!res.ok()) {
265 ATH_MSG_DEBUG("Got error during propagation:" << res.error()
266 << ". Returning empty step vector.");
267 return res.error();
268 }
269 output = std::move(*res);
270
271 ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
272 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
273
274 return output;
275}
276
277Acts::Result<Acts::BoundTrackParameters>
278ExtrapolationTool::propagate(const EventContext& ctx,
279 const Acts::BoundTrackParameters& startParameters,
280 const Acts::Surface& target,
281 Acts::Direction navDir /*= Acts::Direction::Forward()*/,
282 double pathLimit /*= std::numeric_limits<double>::max()*/) const
283{
284
285 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
286
287 Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
288 const GeometryContext& geo_ctx
289 = m_trackingGeometryTool->getGeometryContext(ctx);
290 auto anygctx = geo_ctx.context();
291
292 auto parameters = boost::apply_visitor([&](const auto& propagator) -> Acts::Result<Acts::BoundTrackParameters> {
293 using Propagator = std::decay_t<decltype(propagator)>;
294
295 // Action list and abort list
296 using ActorList =
297 Acts::ActorList<Acts::MaterialInteractor>;
298 using Options = typename Propagator::template Options<ActorList>;
299
300 Options options = prepareOptions<Options>(anygctx, mctx, startParameters, navDir, pathLimit);
301 auto result = target.type() == Acts::Surface::Perigee ?
302 propagator.template propagate<Options, Acts::ForcedSurfaceReached, Acts::PathLimitReached>(startParameters, target, options) :
303 propagator.template propagate<Options, Acts::SurfaceReached, Acts::PathLimitReached>(startParameters, target, options);
304 if (!result.ok()) {
305 ATH_MSG_DEBUG("Got error during propagation: " << result.error());
306 return result.error();
307 }
308 if (!result.value().endParameters.has_value()) {
309 ATH_MSG_DEBUG("Propagation did not result in valid end parameters.");
310 return Acts::PropagatorError::Failure;
311 }
312 return result.value().endParameters.value();
313 }, *m_varProp);
314
315 return parameters;
316}
317
318Acts::MagneticFieldContext ExtrapolationTool::getMagneticFieldContext(const EventContext& ctx) const {
319 const AtlasFieldCacheCondObj* fieldCondObj{nullptr};
320 if (!SG::get(fieldCondObj,m_fieldCacheCondObjInputKey, ctx).isSuccess()) {
321 throw std::runtime_error("Failed to retrieve conditions data from "+m_fieldCacheCondObjInputKey.key() + ".");
322 }
323 return Acts::MagneticFieldContext{fieldCondObj};
324}
325
326template<typename OptionsType>
327OptionsType ExtrapolationTool::prepareOptions(const Acts::GeometryContext& gctx,
328 const Acts::MagneticFieldContext& mctx,
329 const Acts::BoundTrackParameters& startParameters,
330 Acts::Direction navDir,
331 double pathLimit) const {
332 using namespace Acts::UnitLiterals;
333 OptionsType options(gctx, mctx);
334
335 options.pathLimit = pathLimit;
336 options.loopProtection
337 = (Acts::VectorHelpers::perp(startParameters.momentum())
338 < m_ptLoopers * 1_MeV);
339 options.maxSteps = m_maxStep;
340 options.direction = navDir;
341 options.stepping.maxStepSize = m_maxStepSize * 1_m;
342 options.maxTargetSkipping = m_maxSurfSkip;
343 options.surfaceTolerance = m_surfTolerance;
344 options.pathLimit = m_pathLimit * 1_m;
345 auto& mInteractor = options.actorList.template get<Acts::MaterialInteractor>();
346 mInteractor.multipleScattering = m_interactionMultiScatering;
347 mInteractor.energyLoss = m_interactionEloss;
348 mInteractor.recordInteractions = m_interactionRecord;
349 return options;
350}
351}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::pair< std::vector< unsigned int >, bool > res
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
std::unique_ptr< const Acts::Logger > m_logger
Gaudi::Property< unsigned > m_maxSurfSkip
Gaudi::Property< std::vector< double > > m_constantFieldVector
Gaudi::Property< unsigned > m_pathLimit
const Acts::Logger & logger() const
ExtrapolationTool(const std::string &type, const std::string &name, const IInterface *parent)
std::unique_ptr< const ActsExtrapolationDetail::VariantPropagator > m_varProp
Gaudi::Property< bool > m_interactionRecord
OptionsType prepareOptions(const Acts::GeometryContext &gctx, const Acts::MagneticFieldContext &mctx, const Acts::BoundTrackParameters &startParameters, Acts::Direction navDir, double pathLimit) const
Gaudi::Property< double > m_ptLoopers
Gaudi::Property< std::string > m_fieldMode
virtual Acts::Result< Acts::BoundTrackParameters > propagate(const EventContext &ctx, const Acts::BoundTrackParameters &startParameters, Acts::Direction navDir=Acts::Direction::Forward(), double pathLimit=std::numeric_limits< double >::max()) const override
Gaudi::Property< bool > m_interactionMultiScatering
virtual Acts::Result< PropagationOutput > propagationSteps(const EventContext &ctx, const Acts::BoundTrackParameters &startParameters, Acts::Direction navDir=Acts::Direction::Forward(), double pathLimit=std::numeric_limits< double >::max()) const override
Gaudi::Property< double > m_maxStepSize
Gaudi::Property< double > m_surfTolerance
Gaudi::Property< bool > m_interactionEloss
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
Gaudi::Property< unsigned > m_maxStep
virtual StatusCode initialize() override
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
virtual Acts::MagneticFieldContext getMagneticFieldContext(const EventContext &ctx) const override
Acts::GeometryContext context() const
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
boost::variant< CurvedPropagator_t, StraightPropagator_t > VariantPropagatorBase
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.