ATLAS Offline Software
ActsExtrapolationTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 // ATHENA
8 #include "GaudiKernel/IInterface.h"
9 
10 // PACKAGE
14 #include "ActsInterop/Logger.h"
15 
16 // ACTS
17 #include "Acts/Propagator/Navigator.hpp"
18 #include "Acts/Propagator/EigenStepper.hpp"
19 #include "Acts/Propagator/Propagator.hpp"
20 #include "Acts/Propagator/AbortList.hpp"
21 #include "Acts/Propagator/ActionList.hpp"
22 #include <Acts/Propagator/StraightLineStepper.hpp>
23 
24 #include "Acts/Surfaces/BoundaryCheck.hpp"
25 #include "Acts/Utilities/Logger.hpp"
26 
27 #include "Acts/Propagator/DefaultExtension.hpp"
28 #include "Acts/Propagator/DenseEnvironmentExtension.hpp"
29 
30 
31 // BOOST
32 #include <boost/variant/variant.hpp>
33 #include <boost/variant/apply_visitor.hpp>
34 #include <boost/variant/static_visitor.hpp>
35 
36 // STL
37 #include <iostream>
38 #include <memory>
39 
40 namespace ActsExtrapolationDetail {
41 
42 
43  using VariantPropagatorBase = boost::variant<
44  Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension,
45  Acts::DenseEnvironmentExtension>,
46  Acts::detail::HighestValidAuctioneer>,
47  Acts::Navigator>,
48  Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension,
49  Acts::DenseEnvironmentExtension>,
50  Acts::detail::HighestValidAuctioneer>,
51  Acts::Navigator> > ;
52 
54  {
55  public:
57  };
58 
59 }
60 
62 
63 
64 ActsExtrapolationTool::ActsExtrapolationTool(const std::string& type, const std::string& name,
65  const IInterface* parent)
66  : base_class(type, name, parent)
67 {
68 }
69 
70 
72 {
73 }
74 
75 
78 {
79  using namespace std::literals::string_literals;
80  m_logger = makeActsAthenaLogger(this, std::string("ActsExtrapTool"), std::string("Prop"));
81 
82  ATH_MSG_INFO("Initializing ACTS extrapolation");
83 
84  m_logger = makeActsAthenaLogger(this, std::string("Prop"), std::string("ActsExtrapTool"));
85 
86  ATH_CHECK( m_trackingGeometryTool.retrieve() );
87  std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry
88  = m_trackingGeometryTool->trackingGeometry();
89 
90  Acts::Navigator navigator( Acts::Navigator::Config{ trackingGeometry } );
91 
92  if (m_fieldMode == "ATLAS"s) {
93  ATH_MSG_INFO("Using ATLAS magnetic field service");
94  using Stepper = Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension,
95  Acts::DenseEnvironmentExtension>,
96  Acts::detail::HighestValidAuctioneer>;
97 
99  auto bField = std::make_shared<ATLASMagneticFieldWrapper>();
100 
101  auto stepper = Stepper(std::move(bField));
102  auto propagator = Acts::Propagator<Stepper, Acts::Navigator>(std::move(stepper),
103  std::move(navigator),
104  logger().cloneWithSuffix("Prop"));
105  m_varProp = std::make_unique<VariantPropagator>(propagator);
106  }
107  else if (m_fieldMode == "Constant") {
108  if (m_constantFieldVector.value().size() != 3)
109  {
110  ATH_MSG_ERROR("Incorrect field vector size. Using empty field.");
111  return StatusCode::FAILURE;
112  }
113 
114  Acts::Vector3 constantFieldVector = Acts::Vector3(m_constantFieldVector[0],
117 
118  ATH_MSG_INFO("Using constant magnetic field: (Bx, By, Bz) = (" << m_constantFieldVector[0] << ", "
119  << m_constantFieldVector[1] << ", "
120  << m_constantFieldVector[2] << ")");
121 
122  using Stepper = Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension,
123  Acts::DenseEnvironmentExtension>,
124  Acts::detail::HighestValidAuctioneer>;
125 
126  auto bField = std::make_shared<Acts::ConstantBField>(constantFieldVector);
127  auto stepper = Stepper(std::move(bField));
128  auto propagator = Acts::Propagator<Stepper, Acts::Navigator>(std::move(stepper),
129  std::move(navigator));
130  m_varProp = std::make_unique<VariantPropagator>(propagator);
131  }
132 
133  ATH_MSG_INFO("ACTS extrapolation successfully initialized");
134  return StatusCode::SUCCESS;
135 }
136 
137 
140  const Acts::BoundTrackParameters& startParameters,
141  Acts::Direction navDir /*= Acts::Direction::Forward*/,
142  double pathLimit /*= std::numeric_limits<double>::max()*/) const
143 {
144  using namespace Acts::UnitLiterals;
145  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
146 
147  Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
148  const ActsGeometryContext& gctx
149  = m_trackingGeometryTool->getGeometryContext(ctx);
150 
151  auto anygctx = gctx.context();
152 
153  // Action list and abort list
154  using ActionList =
155  Acts::ActionList<SteppingLogger, Acts::MaterialInteractor>;
156  using AbortConditions = Acts::AbortList<EndOfWorld>;
157 
158  using Options = Acts::DenseStepperPropagatorOptions<ActionList, AbortConditions>;
159 
160  Options options(anygctx, mctx);
161  options.pathLimit = pathLimit;
162 
163  options.loopProtection
164  = (Acts::VectorHelpers::perp(startParameters.momentum())
165  < m_ptLoopers * 1_MeV);
166  options.maxStepSize = m_maxStepSize * 1_m;
167  options.maxSteps = m_maxStep;
168  options.direction = navDir;
169 
170  auto &mInteractor = options.actionList.get<Acts::MaterialInteractor>();
171  mInteractor.multipleScattering = m_interactionMultiScatering;
172  mInteractor.energyLoss = m_interactionEloss;
173  mInteractor.recordInteractions = m_interactionRecord;
174 
176 
177  auto res = boost::apply_visitor([&](const auto& propagator) -> ResultType {
178  auto result = propagator.propagate(startParameters, options);
179  if (!result.ok()) {
180  return result.error();
181  }
182  auto& propRes = *result;
183 
184  auto steppingResults = propRes.template get<SteppingLogger::result_type>();
185  auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
186  output.first = std::move(steppingResults.steps);
187  output.second = std::move(materialResult);
188  // try to force return value optimization, not sure this is necessary
189  return std::move(output);
190  }, *m_varProp);
191 
192  if (!res.ok()) {
193  ATH_MSG_ERROR("Got error during propagation: "
194  << res.error() << " " << res.error().message()
195  << ". Returning empty step vector.");
196  return {};
197  }
198  output = std::move(*res);
199 
200  ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
201  if(output.first.size() == 0) {
202  ATH_MSG_WARNING("ZERO steps returned by stepper, that is not typically a good sign");
203  }
204 
205  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
206 
207  return output;
208 }
209 
210 
211 
212 std::optional<const Acts::CurvilinearTrackParameters>
213 ActsExtrapolationTool::propagate(const EventContext& ctx,
214  const Acts::BoundTrackParameters& startParameters,
215  Acts::Direction navDir /*= Acts::Direction::Forward*/,
216  double pathLimit /*= std::numeric_limits<double>::max()*/) const
217 {
218  using namespace Acts::UnitLiterals;
219  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
220 
221  Acts::MagneticFieldContext mctx;
222  const ActsGeometryContext& gctx
223  = m_trackingGeometryTool->getGeometryContext(ctx);
224 
225  auto anygctx = gctx.context();
226 
227  // Action list and abort list
228  using ActionList =
229  Acts::ActionList<Acts::MaterialInteractor>;
230  using AbortConditions = Acts::AbortList<EndOfWorld>;
231  using Options = Acts::DenseStepperPropagatorOptions<ActionList, AbortConditions>;
232 
233  Options options(anygctx, mctx);
234  options.pathLimit = pathLimit;
235 
236  options.loopProtection
237  = (Acts::VectorHelpers::perp(startParameters.momentum())
238  < m_ptLoopers * 1_MeV);
239  options.maxStepSize = m_maxStepSize * 1_m;
240  options.maxSteps = m_maxStep;
241  options.direction = navDir;
242 
243  auto& mInteractor = options.actionList.get<Acts::MaterialInteractor>();
244  mInteractor.multipleScattering = m_interactionMultiScatering;
245  mInteractor.energyLoss = m_interactionEloss;
246  mInteractor.recordInteractions = m_interactionRecord;
247 
248  auto parameters = boost::apply_visitor([&](const auto& propagator) -> std::optional<const Acts::CurvilinearTrackParameters> {
249  auto result = propagator.propagate(startParameters, options);
250  if (!result.ok()) {
251  ATH_MSG_ERROR("Got error during propagation:" << result.error()
252  << ". Returning empty parameters.");
253  return std::nullopt;
254  }
255  return result.value().endParameters;
256  }, *m_varProp);
257 
258  return parameters;
259 }
260 
263  const Acts::BoundTrackParameters& startParameters,
264  const Acts::Surface& target,
265  Acts::Direction navDir /*= Acts::Direction::Forward*/,
266  double pathLimit /*= std::numeric_limits<double>::max()*/) const
267 {
268  using namespace Acts::UnitLiterals;
269  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
270 
271  Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);;
272  const ActsGeometryContext& gctx
273  = m_trackingGeometryTool->getGeometryContext(ctx);
274 
275  auto anygctx = gctx.context();
276 
277  // Action list and abort list
278  using ActionList =
279  Acts::ActionList<SteppingLogger, Acts::MaterialInteractor>;
280  using AbortConditions = Acts::AbortList<EndOfWorld>;
281  using Options = Acts::DenseStepperPropagatorOptions<ActionList, AbortConditions>;
282 
283  Options options(anygctx, mctx);
284  options.pathLimit = pathLimit;
285 
286  options.loopProtection
287  = (Acts::VectorHelpers::perp(startParameters.momentum())
288  < m_ptLoopers * 1_MeV);
289  options.maxStepSize = m_maxStepSize * 1_m;
290  options.maxSteps = m_maxStep;
291  options.direction = navDir;
292 
293  auto& mInteractor = options.actionList.get<Acts::MaterialInteractor>();
294  mInteractor.multipleScattering = m_interactionMultiScatering;
295  mInteractor.energyLoss = m_interactionEloss;
296  mInteractor.recordInteractions = m_interactionRecord;
297 
299 
300  auto res = boost::apply_visitor([&](const auto& propagator) -> ResultType {
301  auto result = propagator.propagate(startParameters, target, options);
302  if (!result.ok()) {
303  return result.error();
304  }
305  auto& propRes = *result;
306 
307  auto steppingResults = propRes.template get<SteppingLogger::result_type>();
308  auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
309  output.first = std::move(steppingResults.steps);
310  output.second = std::move(materialResult);
311  return std::move(output);
312  }, *m_varProp);
313 
314  if (!res.ok()) {
315  ATH_MSG_ERROR("Got error during propagation:" << res.error()
316  << ". Returning empty step vector.");
317  return {};
318  }
319  output = std::move(*res);
320 
321  ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
322  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
323 
324  return output;
325 }
326 
327 std::optional<const Acts::BoundTrackParameters>
328 ActsExtrapolationTool::propagate(const EventContext& ctx,
329  const Acts::BoundTrackParameters& startParameters,
330  const Acts::Surface& target,
331  Acts::Direction navDir /*= Acts::Direction::Forward*/,
332  double pathLimit /*= std::numeric_limits<double>::max()*/) const
333 {
334  using namespace Acts::UnitLiterals;
335  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
336 
337  Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
338  const ActsGeometryContext& gctx
339  = m_trackingGeometryTool->getGeometryContext(ctx);
340 
341  auto anygctx = gctx.context();
342 
343  // Action list and abort list
344  using ActionList =
345  Acts::ActionList<Acts::MaterialInteractor>;
346  using AbortConditions = Acts::AbortList<EndOfWorld>;
347  using Options = Acts::DenseStepperPropagatorOptions<ActionList, AbortConditions>;
348 
349  Options options(anygctx, mctx);
350  options.pathLimit = pathLimit;
351 
352  options.loopProtection
353  = (Acts::VectorHelpers::perp(startParameters.momentum())
354  < m_ptLoopers * 1_MeV);
355  options.maxStepSize = m_maxStepSize * 1_m;
356  options.maxSteps = m_maxStep;
357  options.direction = navDir;
358 
359  auto& mInteractor = options.actionList.get<Acts::MaterialInteractor>();
360  mInteractor.multipleScattering = m_interactionMultiScatering;
361  mInteractor.energyLoss = m_interactionEloss;
362  mInteractor.recordInteractions = m_interactionRecord;
363 
364  auto parameters = boost::apply_visitor([&](const auto& propagator) -> std::optional<const Acts::BoundTrackParameters> {
365  auto result = propagator.propagate(startParameters, target, options);
366  if (!result.ok()) {
367  ATH_MSG_ERROR("Got error during propagation: " << result.error()
368  << ". Returning empty parameters.");
369  return std::nullopt;
370  }
371  return result.value().endParameters;
372  }, *m_varProp);
373 
374  return parameters;
375 }
376 
377 Acts::MagneticFieldContext ActsExtrapolationTool::getMagneticFieldContext(const EventContext& ctx) const {
379  if (!readHandle.isValid()) {
380  std::stringstream msg;
381  msg << "Failed to retrieve magnetic field condition data " << m_fieldCacheCondObjInputKey.key() << ".";
382  throw std::runtime_error(msg.str());
383  }
384  const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
385 
386  return Acts::MagneticFieldContext(fieldCondObj);
387 }
ActsExtrapolationTool::propagate
virtual std::optional< const Acts::CurvilinearTrackParameters > propagate(const EventContext &ctx, const Acts::BoundTrackParameters &startParameters, Acts::Direction navDir=Acts::Direction::Forward, double pathLimit=std::numeric_limits< double >::max()) const override
Definition: ActsExtrapolationTool.cxx:213
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
get_generator_info.result
result
Definition: get_generator_info.py:21
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
AtlasFieldCacheCondObj
Definition: AtlasFieldCacheCondObj.h:19
ActsExtrapolationTool::ActsExtrapolationTool
ActsExtrapolationTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: ActsExtrapolationTool.cxx:64
ActsGeometryContext.h
perp
Scalar perp() const
perp method - perpenticular length
Definition: AmgMatrixBasePlugin.h:35
ActsExtrapolationTool::getMagneticFieldContext
virtual Acts::MagneticFieldContext getMagneticFieldContext(const EventContext &ctx) const override
Definition: ActsExtrapolationTool.cxx:377
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
ActsExtrapolationTool::ResultType
Acts::Result< ActsPropagationOutput > ResultType
Definition: ActsExtrapolationTool.h:67
ActsExtrapolationTool::propagationSteps
virtual ActsPropagationOutput propagationSteps(const EventContext &ctx, const Acts::BoundTrackParameters &startParameters, Acts::Direction navDir=Acts::Direction::Forward, double pathLimit=std::numeric_limits< double >::max()) const override
Definition: ActsExtrapolationTool.cxx:139
ActsExtrapolationTool.h
makeActsAthenaLogger
std::unique_ptr< const Acts::Logger > makeActsAthenaLogger(IMessageSvc *svc, const std::string &name, int level, std::optional< std::string > parent_name)
Definition: Tracking/Acts/ActsInterop/src/Logger.cxx:64
ActsGeometryContext::context
Acts::GeometryContext context() const
Definition: ActsGeometryContext.h:46
ActsExtrapolationTool::logger
const Acts::Logger & logger() const
Definition: ActsExtrapolationTool.h:114
ActsExtrapolationTool::m_maxStep
Gaudi::Property< double > m_maxStep
Definition: ActsExtrapolationTool.h:129
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ActsExtrapolationTool::~ActsExtrapolationTool
~ActsExtrapolationTool()
Definition: ActsExtrapolationTool.cxx:71
ActsTrackingGeometryTool.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ActsExtrapolationTool::m_ptLoopers
Gaudi::Property< double > m_ptLoopers
Definition: ActsExtrapolationTool.h:127
res
std::pair< std::vector< unsigned int >, bool > res
Definition: JetGroupProductTest.cxx:14
test_pyathena.parent
parent
Definition: test_pyathena.py:15
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
python.AtlRunQueryLib.options
options
Definition: AtlRunQueryLib.py:379
ActsExtrapolationTool::m_trackingGeometryTool
ToolHandle< IActsTrackingGeometryTool > m_trackingGeometryTool
Definition: ActsExtrapolationTool.h:122
ActsExtrapolationTool::m_interactionMultiScatering
Gaudi::Property< bool > m_interactionMultiScatering
Definition: ActsExtrapolationTool.h:132
ActsExtrapolationTool::initialize
virtual StatusCode initialize() override
Definition: ActsExtrapolationTool.cxx:77
ActsExtrapolationDetail
Definition: ActsExtrapolationTool.h:48
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:28
ActsExtrapolationDetail::VariantPropagator
Definition: ActsExtrapolationTool.cxx:54
merge.output
output
Definition: merge.py:17
ActsExtrapolationTool::m_interactionRecord
Gaudi::Property< bool > m_interactionRecord
Definition: ActsExtrapolationTool.h:134
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
ActsExtrapolationTool::m_fieldCacheCondObjInputKey
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCacheCondObjInputKey
Definition: ActsExtrapolationTool.h:120
checkNSWValTree.Options
Options
Definition: checkNSWValTree.py:15
ActsExtrapolationTool::m_interactionEloss
Gaudi::Property< bool > m_interactionEloss
Definition: ActsExtrapolationTool.h:133
ActsExtrapolationTool::m_fieldMode
Gaudi::Property< std::string > m_fieldMode
Definition: ActsExtrapolationTool.h:124
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
ActsExtrapolationTool::m_varProp
std::unique_ptr< const ActsExtrapolationDetail::VariantPropagator > m_varProp
Definition: ActsExtrapolationTool.h:117
ActsExtrapolationTool::m_maxStepSize
Gaudi::Property< double > m_maxStepSize
Definition: ActsExtrapolationTool.h:128
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
ActsExtrapolationTool::m_logger
std::unique_ptr< const Acts::Logger > m_logger
Definition: ActsExtrapolationTool.h:118
physics_parameters.parameters
parameters
Definition: physics_parameters.py:144
ActsExtrapolationTool::m_constantFieldVector
Gaudi::Property< std::vector< double > > m_constantFieldVector
Definition: ActsExtrapolationTool.h:125
COOLRates.target
target
Definition: COOLRates.py:1106
Logger.h
ActsTrackingGeometrySvc.h
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
ActsPropagationOutput
std::pair< std::vector< Acts::detail::Step >, ActsRecordedMaterial > ActsPropagationOutput
Finally the output of the propagation test.
Definition: IActsExtrapolationTool.h:25
ActsExtrapolationDetail::VariantPropagatorBase
boost::variant< Acts::Propagator< Acts::EigenStepper< Acts::StepperExtensionList< Acts::DefaultExtension, Acts::DenseEnvironmentExtension >, Acts::detail::HighestValidAuctioneer >, Acts::Navigator >, Acts::Propagator< Acts::EigenStepper< Acts::StepperExtensionList< Acts::DefaultExtension, Acts::DenseEnvironmentExtension >, Acts::detail::HighestValidAuctioneer >, Acts::Navigator > > VariantPropagatorBase
Definition: ActsExtrapolationTool.cxx:51