ATLAS Offline Software
ActsExtrapolationTool.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 
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/ActorList.hpp"
21 #include <Acts/Propagator/StraightLineStepper.hpp>
22 #include "Acts/Propagator/EigenStepperDefaultExtension.hpp"
23 
24 #include "Acts/Utilities/Logger.hpp"
25 
26 // BOOST
27 #include <boost/variant/variant.hpp>
28 #include <boost/variant/apply_visitor.hpp>
29 #include <boost/variant/static_visitor.hpp>
30 
31 // STL
32 #include <iostream>
33 #include <memory>
34 
35 namespace ActsExtrapolationDetail {
36 
37 
38  using VariantPropagatorBase = boost::variant<
39  Acts::Propagator<Acts::EigenStepper<Acts::EigenStepperDefaultExtension>, Acts::Navigator>>;
40 
42  {
43  public:
45  };
46 
47 }
48 
50 
51 
52 ActsExtrapolationTool::ActsExtrapolationTool(const std::string& type, const std::string& name,
53  const IInterface* parent)
54  : base_class(type, name, parent)
55 {
56 }
57 
58 
60 {
61 }
62 
63 
66 {
67  using namespace std::literals::string_literals;
68  m_logger = makeActsAthenaLogger(this, std::string("ActsExtrapTool"), std::string("Prop"));
69 
70  ATH_MSG_INFO("Initializing ACTS extrapolation");
71 
72  m_logger = makeActsAthenaLogger(this, std::string("Prop"), std::string("ActsExtrapTool"));
73 
74  ATH_CHECK( m_trackingGeometryTool.retrieve() );
75  std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry
76  = m_trackingGeometryTool->trackingGeometry();
77 
78  Acts::Navigator navigator( Acts::Navigator::Config{ trackingGeometry } );
79 
80  if (m_fieldMode == "ATLAS"s) {
81  ATH_MSG_INFO("Using ATLAS magnetic field service");
82  using Stepper = Acts::EigenStepper<Acts::EigenStepperDefaultExtension>;
83 
85  auto bField = std::make_shared<ATLASMagneticFieldWrapper>();
86 
87  auto stepper = Stepper(std::move(bField));
88  auto propagator = Acts::Propagator<Stepper, Acts::Navigator>(std::move(stepper),
89  std::move(navigator),
90  logger().cloneWithSuffix("Prop"));
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) = (" << m_constantFieldVector[0] << ", "
105  << m_constantFieldVector[1] << ", "
106  << m_constantFieldVector[2] << ")");
107 
108  using Stepper = Acts::EigenStepper<Acts::EigenStepperDefaultExtension>;
109 
110  auto bField = std::make_shared<Acts::ConstantBField>(constantFieldVector);
111  auto stepper = Stepper(std::move(bField));
112  auto propagator = Acts::Propagator<Stepper, Acts::Navigator>(std::move(stepper),
113  std::move(navigator));
114  m_varProp = std::make_unique<VariantPropagator>(propagator);
115  }
116 
117  ATH_MSG_INFO("ACTS extrapolation successfully initialized");
118  return StatusCode::SUCCESS;
119 }
120 
121 
124  const Acts::BoundTrackParameters& startParameters,
125  Acts::Direction navDir /*= Acts::Direction::Forward*/,
126  double pathLimit /*= std::numeric_limits<double>::max()*/) const
127 {
128  using namespace Acts::UnitLiterals;
129  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
130 
131  Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
132  const ActsGeometryContext& gctx
133  = m_trackingGeometryTool->getGeometryContext(ctx);
134 
135  auto anygctx = gctx.context();
136 
138 
139  auto res = boost::apply_visitor([&](const auto& propagator) -> ResultType {
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 
146  using Options = typename Propagator::template Options<ActorList>;
147 
148  Options options(anygctx, mctx);
149  options.pathLimit = pathLimit;
150  options.loopProtection
151  = (Acts::VectorHelpers::perp(startParameters.momentum())
152  < m_ptLoopers * 1_MeV);
153  options.maxSteps = m_maxStep;
154  options.direction = navDir;
155  options.stepping.maxStepSize = m_maxStepSize * 1_m;
156 
157  auto &mInteractor = options.actorList.template get<Acts::MaterialInteractor>();
158  mInteractor.multipleScattering = m_interactionMultiScatering;
159  mInteractor.energyLoss = m_interactionEloss;
160  mInteractor.recordInteractions = m_interactionRecord;
161 
162  auto result = propagator.propagate(startParameters, options);
163  if (!result.ok()) {
164  return result.error();
165  }
166  auto& propRes = *result;
167 
168  auto steppingResults = propRes.template get<SteppingLogger::result_type>();
169  auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
170  output.first = std::move(steppingResults.steps);
171  output.second = std::move(materialResult);
172  // try to force return value optimization, not sure this is necessary
173  return std::move(output);
174  }, *m_varProp);
175 
176  if (!res.ok()) {
177  ATH_MSG_ERROR("Got error during propagation: "
178  << res.error() << " " << res.error().message()
179  << ". Returning empty step vector.");
180  return {};
181  }
182  output = std::move(*res);
183 
184  ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
185  if(output.first.size() == 0) {
186  ATH_MSG_WARNING("ZERO steps returned by stepper, that is not typically a good sign");
187  }
188 
189  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
190 
191  return output;
192 }
193 
194 
195 
196 std::optional<const Acts::CurvilinearTrackParameters>
197 ActsExtrapolationTool::propagate(const EventContext& ctx,
198  const Acts::BoundTrackParameters& startParameters,
199  Acts::Direction navDir /*= Acts::Direction::Forward*/,
200  double pathLimit /*= std::numeric_limits<double>::max()*/) const
201 {
202  using namespace Acts::UnitLiterals;
203  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
204 
205  Acts::MagneticFieldContext mctx;
206  const ActsGeometryContext& gctx
207  = m_trackingGeometryTool->getGeometryContext(ctx);
208 
209  auto anygctx = gctx.context();
210 
211  auto parameters = boost::apply_visitor([&](const auto& propagator) -> std::optional<const Acts::CurvilinearTrackParameters> {
212  using Propagator = std::decay_t<decltype(propagator)>;
213 
214  // Action list and abort list
215  using ActorList =
216  Acts::ActorList<Acts::MaterialInteractor, EndOfWorld>;
217  using Options = typename Propagator::template Options<ActorList>;
218 
219  Options options(anygctx, mctx);
220  options.pathLimit = pathLimit;
221  options.loopProtection
222  = (Acts::VectorHelpers::perp(startParameters.momentum())
223  < m_ptLoopers * 1_MeV);
224  options.maxSteps = m_maxStep;
225  options.direction = navDir;
226  options.stepping.maxStepSize = m_maxStepSize * 1_m;
227 
228  auto& mInteractor = options.actorList.template get<Acts::MaterialInteractor>();
229  mInteractor.multipleScattering = m_interactionMultiScatering;
230  mInteractor.energyLoss = m_interactionEloss;
231  mInteractor.recordInteractions = m_interactionRecord;
232 
233  auto result = propagator.propagate(startParameters, options);
234  if (!result.ok()) {
235  ATH_MSG_ERROR("Got error during propagation:" << result.error()
236  << ". Returning empty parameters.");
237  return std::nullopt;
238  }
239  return result.value().endParameters;
240  }, *m_varProp);
241 
242  return parameters;
243 }
244 
247  const Acts::BoundTrackParameters& startParameters,
248  const Acts::Surface& target,
249  Acts::Direction navDir /*= Acts::Direction::Forward*/,
250  double pathLimit /*= std::numeric_limits<double>::max()*/) const
251 {
252  using namespace Acts::UnitLiterals;
253  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
254 
255  Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);;
256  const ActsGeometryContext& gctx
257  = m_trackingGeometryTool->getGeometryContext(ctx);
258 
259  auto anygctx = gctx.context();
260 
262 
263  auto res = boost::apply_visitor([&](const auto& propagator) -> ResultType {
264  using Propagator = std::decay_t<decltype(propagator)>;
265 
266  // Action list and abort list
267  using ActorList =
268  Acts::ActorList<SteppingLogger, Acts::MaterialInteractor>;
269  using Options = typename Propagator::template Options<ActorList>;
270 
271  Options options(anygctx, mctx);
272  options.pathLimit = pathLimit;
273  options.loopProtection
274  = (Acts::VectorHelpers::perp(startParameters.momentum())
275  < m_ptLoopers * 1_MeV);
276  options.maxSteps = m_maxStep;
277  options.direction = navDir;
278  options.stepping.maxStepSize = m_maxStepSize * 1_m;
279 
280  auto& mInteractor = options.actorList.template get<Acts::MaterialInteractor>();
281  mInteractor.multipleScattering = m_interactionMultiScatering;
282  mInteractor.energyLoss = m_interactionEloss;
283  mInteractor.recordInteractions = m_interactionRecord;
284 
285  auto result = propagator.propagate(startParameters, target, options);
286  if (!result.ok()) {
287  return result.error();
288  }
289  auto& propRes = *result;
290 
291  auto steppingResults = propRes.template get<SteppingLogger::result_type>();
292  auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
293  output.first = std::move(steppingResults.steps);
294  output.second = std::move(materialResult);
295  return std::move(output);
296  }, *m_varProp);
297 
298  if (!res.ok()) {
299  ATH_MSG_ERROR("Got error during propagation:" << res.error()
300  << ". Returning empty step vector.");
301  return {};
302  }
303  output = std::move(*res);
304 
305  ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
306  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
307 
308  return output;
309 }
310 
311 std::optional<const Acts::BoundTrackParameters>
312 ActsExtrapolationTool::propagate(const EventContext& ctx,
313  const Acts::BoundTrackParameters& startParameters,
314  const Acts::Surface& target,
315  Acts::Direction navDir /*= Acts::Direction::Forward*/,
316  double pathLimit /*= std::numeric_limits<double>::max()*/) const
317 {
318  using namespace Acts::UnitLiterals;
319  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
320 
321  Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
322  const ActsGeometryContext& gctx
323  = m_trackingGeometryTool->getGeometryContext(ctx);
324 
325  auto anygctx = gctx.context();
326 
327  auto parameters = boost::apply_visitor([&](const auto& propagator) -> std::optional<const Acts::BoundTrackParameters> {
328  using Propagator = std::decay_t<decltype(propagator)>;
329 
330  // Action list and abort list
331  using ActorList =
332  Acts::ActorList<Acts::MaterialInteractor>;
333  using Options = typename Propagator::template Options<ActorList>;
334 
335  Options options(anygctx, mctx);
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 
344  auto& mInteractor = options.actorList.template get<Acts::MaterialInteractor>();
345  mInteractor.multipleScattering = m_interactionMultiScatering;
346  mInteractor.energyLoss = m_interactionEloss;
347  mInteractor.recordInteractions = m_interactionRecord;
348 
349  auto result = propagator.propagate(startParameters, target, options);
350  if (!result.ok()) {
351  ATH_MSG_ERROR("Got error during propagation: " << result.error()
352  << ". Returning empty parameters.");
353  return std::nullopt;
354  }
355  return result.value().endParameters;
356  }, *m_varProp);
357 
358  return parameters;
359 }
360 
361 Acts::MagneticFieldContext ActsExtrapolationTool::getMagneticFieldContext(const EventContext& ctx) const {
363  if (!readHandle.isValid()) {
364  std::stringstream msg;
365  msg << "Failed to retrieve magnetic field condition data " << m_fieldCacheCondObjInputKey.key() << ".";
366  throw std::runtime_error(msg.str());
367  }
368  const AtlasFieldCacheCondObj* fieldCondObj{*readHandle};
369 
370  return Acts::MagneticFieldContext(fieldCondObj);
371 }
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:197
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:52
ActsGeometryContext.h
perp
Scalar perp() const
perp method - perpenticular length
Definition: AmgMatrixBasePlugin.h:44
ActsTrk::detail::Navigator
Acts::Navigator Navigator
Definition: Tracking/Acts/ActsTrackReconstruction/src/detail/Definitions.h:31
ActsExtrapolationTool::getMagneticFieldContext
virtual Acts::MagneticFieldContext getMagneticFieldContext(const EventContext &ctx) const override
Definition: ActsExtrapolationTool.cxx:361
taskman.template
dictionary template
Definition: taskman.py:317
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
ActsExtrapolationDetail::VariantPropagatorBase
boost::variant< Acts::Propagator< Acts::EigenStepper< Acts::EigenStepperDefaultExtension >, Acts::Navigator > > VariantPropagatorBase
Definition: ActsExtrapolationTool.cxx:39
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:123
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:45
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:59
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:65
ActsExtrapolationDetail
Definition: ActsExtrapolationTool.h:48
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
ActsExtrapolationDetail::VariantPropagator
Definition: ActsExtrapolationTool.cxx:42
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:221
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
ActsTrk::detail::Stepper
Acts::SympyStepper Stepper
Adapted from Acts Examples/Algorithms/TrackFinding/src/TrackFindingAlgorithmFunction....
Definition: Tracking/Acts/ActsTrackReconstruction/src/detail/Definitions.h:30
ActsTrk::detail::Propagator
Acts::Propagator< Stepper, Navigator > Propagator
Definition: Tracking/Acts/ActsTrackReconstruction/src/detail/Definitions.h:32
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
copySelective.target
string target
Definition: copySelective.py:37
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
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