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
15#include "ActsInterop/Logger.h"
16
17// ACTS
18#include "Acts/Propagator/Navigator.hpp"
19#include "Acts/Propagator/EigenStepper.hpp"
20#include "Acts/Propagator/Propagator.hpp"
21#include "Acts/Propagator/ActorList.hpp"
22#include <Acts/Propagator/StraightLineStepper.hpp>
23#include "Acts/Propagator/EigenStepperDefaultExtension.hpp"
24
25#include "Acts/Utilities/Logger.hpp"
26
27// BOOST
28#include <boost/variant/variant.hpp>
29#include <boost/variant/apply_visitor.hpp>
30#include <boost/variant/static_visitor.hpp>
31
32// STL
33#include <iostream>
34#include <memory>
35
36namespace {
37 using CurvedStepper_t = Acts::EigenStepper<Acts::EigenStepperDefaultExtension>;
38 using CurvedPropagator_t = Acts::Propagator<CurvedStepper_t, Acts::Navigator>;
39 using StraightStepper_t = Acts::StraightLineStepper;
40 using StraightPropagator_t = Acts::Propagator<StraightStepper_t, Acts::Navigator>;
41}
42
44
45
46
47 using VariantPropagatorBase = boost::variant<CurvedPropagator_t, StraightPropagator_t>;
48
50 {
51 public:
52 using VariantPropagatorBase::VariantPropagatorBase;
53 };
54
55}
56
58
59namespace ActsTrk{
60
61
63 const std::string& name,
64 const IInterface* parent):
65 base_class{type,name, parent} {}
66
68
69StatusCode
71{
72
73
74 ATH_MSG_INFO("Initializing ACTS extrapolation");
75
76 m_logger = makeActsAthenaLogger(this, name());
77
79
80 Acts::Navigator::Config navConfig{m_trackingGeometryTool->trackingGeometry()};
81 Acts::Navigator navigator{std::move(navConfig), logger().clone()};
82
84 if (m_fieldMode == "ATLAS") {
85 ATH_MSG_INFO("Using ATLAS magnetic field service");
86
87 auto bField = std::make_shared<ATLASMagneticFieldWrapper>();
88
89 CurvedStepper_t stepper{std::move(bField)};
90 CurvedPropagator_t propagator{std::move(stepper), std::move(navigator),
91 logger().clone()};
92 m_varProp = std::make_unique<VariantPropagator>(propagator);
93 }
94 else if (m_fieldMode == "Constant") {
95 if (m_constantFieldVector.value().size() != 3)
96 {
97 ATH_MSG_ERROR("Incorrect field vector size. Using empty field.");
98 return StatusCode::FAILURE;
99 }
100
101 Acts::Vector3 constantFieldVector = Acts::Vector3(m_constantFieldVector[0],
104
105 ATH_MSG_INFO("Using constant magnetic field: (Bx, By, Bz) = "
106 <<Amg::toString(constantFieldVector));
107
108 auto bField = std::make_shared<Acts::ConstantBField>(constantFieldVector);
109 CurvedStepper_t stepper{std::move(bField)};
110 CurvedPropagator_t propagator{std::move(stepper), std::move(navigator), logger().clone()};
111 m_varProp = std::make_unique<VariantPropagator>(propagator);
112 } else if (m_fieldMode == "StraightLine") {
113 Acts::StraightLineStepper stepper{};
114 StraightPropagator_t propagator{stepper, std::move(navigator), logger().clone()};
115 m_varProp = std::make_unique<VariantPropagator>(propagator);
116 } else {
117 ATH_MSG_FATAL("Invalid mode provided "<<m_fieldMode<<". Allowed : \"ATLAS\", \"Constant\", \"StraightLine\".");
118 return StatusCode::FAILURE;
119 }
120
121 ATH_MSG_INFO("ACTS extrapolation successfully initialized");
122 return StatusCode::SUCCESS;
123}
124
125
126ExtrapolationTool::PropagationOutput
128 const Acts::BoundTrackParameters& startParameters,
129 Acts::Direction navDir /*= Acts::Direction::Forward()*/,
130 double pathLimit /*= std::numeric_limits<double>::max()*/) const
131{
132
133 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
134
135 Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
136 const GeometryContext& geo_ctx
137 = m_trackingGeometryTool->getGeometryContext(ctx);
138 auto anygctx = geo_ctx.context();
139
140 PropagationOutput output;
141
142 auto res = boost::apply_visitor([&](const auto& propagator) -> ResultType {
143 using Propagator = std::decay_t<decltype(propagator)>;
144
145 // Action list and abort list
146 using ActorList =
147 Acts::ActorList<SteppingLogger, Acts::MaterialInteractor, EndOfWorld>;
148 using Options = typename Propagator::template Options<ActorList>;
149
150 Options options = prepareOptions<Options>(anygctx, mctx, startParameters, navDir, pathLimit);
151
152 auto result = propagator.propagate(startParameters, options);
153 if (!result.ok()) {
154 return result.error();
155 }
156 auto& propRes = *result;
157
158 auto steppingResults = propRes.template get<SteppingLogger::result_type>();
159 auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
160 output.first = std::move(steppingResults.steps);
161 output.second = std::move(materialResult);
162 // try to force return value optimization, not sure this is necessary
163 return std::move(output);
164 }, *m_varProp);
165
166 if (!res.ok()) {
167 ATH_MSG_ERROR("Got error during propagation: "
168 << res.error() << " " << res.error().message()
169 << ". Returning empty step vector.");
170 return {};
171 }
172 output = std::move(*res);
173
174 ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
175 if(output.first.size() == 0) {
176 ATH_MSG_WARNING("ZERO steps returned by stepper, that is not typically a good sign");
177 }
178
179 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
180
181 return output;
182}
183
184
185
186std::optional<Acts::BoundTrackParameters>
187ExtrapolationTool::propagate(const EventContext& ctx,
188 const Acts::BoundTrackParameters& startParameters,
189 Acts::Direction navDir /*= Acts::Direction::Forward()*/,
190 double pathLimit /*= std::numeric_limits<double>::max()*/) const
191{
192 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
193
194 Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
195 const GeometryContext& geo_ctx
196 = m_trackingGeometryTool->getGeometryContext(ctx);
197 auto anygctx = geo_ctx.context();
198
199 auto parameters = boost::apply_visitor([&](const auto& propagator) -> std::optional<const Acts::BoundTrackParameters> {
200 using Propagator = std::decay_t<decltype(propagator)>;
201
202 // Action list and abort list
203 using ActorList =
204 Acts::ActorList<Acts::MaterialInteractor, EndOfWorld>;
205 using Options = typename Propagator::template Options<ActorList>;
206
207 Options options = prepareOptions<Options>(anygctx, mctx, startParameters, navDir, pathLimit);
208
209
210 auto result = propagator.propagate(startParameters, options);
211 if (!result.ok()) {
212 ATH_MSG_ERROR("Got error during propagation:" << result.error()
213 << ". Returning empty parameters.");
214 return std::nullopt;
215 }
216 return result.value().endParameters;
217 }, *m_varProp);
218
219 return parameters;
220}
221
222ExtrapolationTool::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) -> ResultType {
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<Acts::BoundTrackParameters, Options,
249 Acts::ForcedSurfaceReached, Acts::PathLimitReached>(startParameters, target, options) :
250 propagator.template propagate<Acts::BoundTrackParameters, Options,
251 Acts::SurfaceReached, Acts::PathLimitReached>(startParameters, target, options);
252
253
254 if (!result.ok()) {
255 return result.error();
256 }
257 auto& propRes = *result;
258
259 auto steppingResults = propRes.template get<SteppingLogger::result_type>();
260 auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
261 output.first = std::move(steppingResults.steps);
262 output.second = std::move(materialResult);
263 return std::move(output);
264 }, *m_varProp);
265
266 if (!res.ok()) {
267 ATH_MSG_ERROR("Got error during propagation:" << res.error()
268 << ". Returning empty step vector.");
269 return {};
270 }
271 output = std::move(*res);
272
273 ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
274 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
275
276 return output;
277}
278
279std::optional<Acts::BoundTrackParameters>
280ExtrapolationTool::propagate(const EventContext& ctx,
281 const Acts::BoundTrackParameters& startParameters,
282 const Acts::Surface& target,
283 Acts::Direction navDir /*= Acts::Direction::Forward()*/,
284 double pathLimit /*= std::numeric_limits<double>::max()*/) const
285{
286
287 ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
288
289 Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
290 const GeometryContext& geo_ctx
291 = m_trackingGeometryTool->getGeometryContext(ctx);
292 auto anygctx = geo_ctx.context();
293
294 auto parameters = boost::apply_visitor([&](const auto& propagator) -> std::optional<const Acts::BoundTrackParameters> {
295 using Propagator = std::decay_t<decltype(propagator)>;
296
297 // Action list and abort list
298 using ActorList =
299 Acts::ActorList<Acts::MaterialInteractor>;
300 using Options = typename Propagator::template Options<ActorList>;
301
302 Options options = prepareOptions<Options>(anygctx, mctx, startParameters, navDir, pathLimit);
303 auto result = target.type() == Acts::Surface::Perigee ?
304 propagator.template propagate<Acts::BoundTrackParameters, Options,
305 Acts::ForcedSurfaceReached, Acts::PathLimitReached>(startParameters, target, options) :
306 propagator.template propagate<Acts::BoundTrackParameters, Options,
307 Acts::SurfaceReached, Acts::PathLimitReached>(startParameters, target, options);
308 if (!result.ok()) {
309 ATH_MSG_ERROR("Got error during propagation: " << result.error()
310 << ". Returning empty parameters.");
311 return std::nullopt;
312 }
313 return result.value().endParameters;
314 }, *m_varProp);
315
316 return parameters;
317}
318
319Acts::MagneticFieldContext ExtrapolationTool::getMagneticFieldContext(const EventContext& ctx) const {
320 const AtlasFieldCacheCondObj* fieldCondObj{nullptr};
321 if (!SG::get(fieldCondObj,m_fieldCacheCondObjInputKey, ctx).isSuccess()) {
322 throw std::runtime_error("Failed to retrieve conditions data from "+m_fieldCacheCondObjInputKey.key() + ".");
323 }
324 return Acts::MagneticFieldContext{fieldCondObj};
325}
326
327template<typename OptionsType>
328OptionsType ExtrapolationTool::prepareOptions(const Acts::GeometryContext& gctx,
329 const Acts::MagneticFieldContext& mctx,
330 const Acts::BoundTrackParameters& startParameters,
331 Acts::Direction navDir,
332 double pathLimit) const {
333 using namespace Acts::UnitLiterals;
334 OptionsType options(gctx, mctx);
335
336 options.pathLimit = pathLimit;
337 options.loopProtection
338 = (Acts::VectorHelpers::perp(startParameters.momentum())
339 < m_ptLoopers * 1_MeV);
340 options.maxSteps = m_maxStep;
341 options.direction = navDir;
342 options.stepping.maxStepSize = m_maxStepSize * 1_m;
343 options.maxTargetSkipping = m_maxSurfSkip;
344 options.surfaceTolerance = m_surfTolerance;
345 options.pathLimit = m_pathLimit * 1_m;
346 auto& mInteractor = options.actorList.template get<Acts::MaterialInteractor>();
347 mInteractor.multipleScattering = m_interactionMultiScatering;
348 mInteractor.energyLoss = m_interactionEloss;
349 mInteractor.recordInteractions = m_interactionRecord;
350 return options;
351}
352}
#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)
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
virtual std::optional< 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
const Acts::Logger & logger() const
virtual PropagationOutput propagationSteps(const EventContext &ctx, const Acts::BoundTrackParameters &startParameters, Acts::Direction navDir=Acts::Direction::Forward(), double pathLimit=std::numeric_limits< double >::max()) const override
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
Gaudi::Property< bool > m_interactionMultiScatering
Gaudi::Property< double > m_maxStepSize
Acts::Result< PropagationOutput > ResultType
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:130
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.