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