15#include "Acts/Geometry/VolumeBounds.hpp"
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"
23#include "Acts/Utilities/Logger.hpp"
31 using SteppingLogger = Acts::detail::SteppingLogger;
32 using EndOfWorld = Acts::EndOfWorldReached;
34 using CurvedStepper_t = Acts::EigenStepper<Acts::EigenStepperDefaultExtension>;
35 using CurvedPropagator_t = Acts::Propagator<CurvedStepper_t, Acts::Navigator>;
36 using StraightStepper_t = Acts::StraightLineStepper;
37 using StraightPropagator_t = Acts::Propagator<StraightStepper_t, Acts::Navigator>;
42 struct PassedVolumeAborter{
44 Acts::GeometryIdentifier targetVolumeId{};
47 VolumeAbort stopVolumeFlag{VolumeAbort::atExit};
50 explicit PassedVolumeAborter() =
default;
53 template <
typename propagator_state_t,
typename stepper_t,
55 bool checkAbort(propagator_state_t& state,
const stepper_t& stepper,
56 const navigator_t& navigator,
const Acts::Logger&
logger)
const {
58 if (targetVolumeId == Acts::GeometryIdentifier{}) {
59 ACTS_WARNING(
"PassedVolume aborter | Target volume not set");
62 const Acts::TrackingVolume* currentVolume = navigator.currentVolume(state.navigation);
63 if (currentVolume ==
nullptr) {
67 const Acts::Surface* surface = navigator.currentSurface(state.navigation);
69 if (surface ==
nullptr || surface->geometryId().boundary() == 0) {
72 ACTS_VERBOSE(
"PassedVolume - Investigate portal surface "<<surface->geometryId());
73 if (surface->geometryId().withBoundary(0) == targetVolumeId) {
74 ACTS_VERBOSE(
"PassedVolume - The outer boundary surface is crossed ");
77 if (stopVolumeFlag == VolumeAbort::atExit) {
81 for (
const Acts::Portal& portal : currentVolume->portals()) {
82 if (portal.surface().geometryId() != surface->geometryId()) {
85 auto res = portal.resolveVolume(state.navigation.options.geoContext,
86 stepper.position(state.stepping),
87 stepper.direction(state.stepping));
89 ACTS_WARNING(
"Failed to resolve volume through portal: "
90 <<
res.error().message());
93 return (*res)->geometryId() == targetVolumeId;
95 ACTS_WARNING(
"PassedVolume - Cannot find portal associated with "<<surface->geometryId());
102 struct PassedSurfaceAborter {
104 const Acts::Surface* targetSurface =
nullptr;
106 double surpassedDistance{0.};
108 explicit PassedSurfaceAborter() =
default;
112 template <
typename propagator_state_t,
typename stepper_t,
113 typename navigator_t>
114 bool checkAbort(propagator_state_t& state,
const stepper_t& stepper,
115 const navigator_t& ,
const Acts::Logger&
logger)
const {
116 if (targetSurface ==
nullptr) {
117 ACTS_WARNING(
"PassedSurfaceAborter aborter | Target surface not set.");
121 const Acts::MultiIntersection3D multiIntersection = targetSurface->intersect(state.geoContext,
122 stepper.position(state.stepping),
123 state.options.direction * stepper.direction(state.stepping),
124 Acts::BoundaryTolerance::Infinite());
126 const Acts::Intersection3D closestIntersection = multiIntersection.closest();
127 ACTS_VERBOSE(
"PassedSurfaceAborter aborter | Propagation is "<<closestIntersection.pathLength()
128 <<
" away from target surface "
129 <<targetSurface->toString(state.geoContext)<<
". Abort if distance is "
130 <<std::copysign(surpassedDistance, -1.)<<
".");
131 return closestIntersection.pathLength() < std::copysign(surpassedDistance, -1.);
145 using VariantPropagatorBase::VariantPropagatorBase;
156 const std::string& name,
157 const IInterface* parent):
158 base_class{
type,name, parent} {}
174 Acts::Navigator navigator{std::move(navConfig),
logger().clone()};
180 auto bField = std::make_shared<ATLASMagneticFieldWrapper>();
182 CurvedStepper_t stepper{std::move(bField)};
183 CurvedPropagator_t propagator{std::move(stepper), std::move(navigator),
185 m_varProp = std::make_unique<VariantPropagator>(propagator);
190 ATH_MSG_ERROR(
"Incorrect field vector size. Using empty field.");
191 return StatusCode::FAILURE;
198 ATH_MSG_INFO(
"Using constant magnetic field: (Bx, By, Bz) = "
201 auto bField = std::make_shared<Acts::ConstantBField>(constantFieldVector);
202 CurvedStepper_t stepper{std::move(bField)};
203 CurvedPropagator_t propagator{std::move(stepper), std::move(navigator),
logger().clone()};
204 m_varProp = std::make_unique<VariantPropagator>(propagator);
206 Acts::StraightLineStepper stepper{};
207 StraightPropagator_t propagator{stepper, std::move(navigator),
logger().clone()};
208 m_varProp = std::make_unique<VariantPropagator>(propagator);
211 return StatusCode::FAILURE;
214 ATH_MSG_INFO(
"ACTS extrapolation successfully initialized");
215 return StatusCode::SUCCESS;
219Acts::Result<ExtrapolationTool::PropagationOutput>
221 const Acts::BoundTrackParameters& startParameters,
222 const Acts::Direction navDir,
223 const double pathLimit)
const {
227 const Acts::MagneticFieldContext mfContext =
m_ctxProvider.getMagneticFieldContext(ctx);
228 const Acts::GeometryContext tgContext =
m_ctxProvider.getGeometryContext(ctx);
230 PropagationOutput output;
232 auto res = std::visit([&](
const auto& propagator) -> Acts::Result<ExtrapolationTool::PropagationOutput> {
233 using Propagator = std::decay_t<
decltype(propagator)>;
237 Acts::ActorList<SteppingLogger, Acts::MaterialInteractor, EndOfWorld>;
238 using Options =
typename Propagator::template Options<ActorList>;
242 auto result = propagator.propagate(startParameters, options);
244 return result.error();
246 auto& propRes = *result;
250 output.first = std::move(steppingResults.steps);
251 output.second = std::move(materialResult);
253 return std::move(output);
258 <<
res.error() <<
" " <<
res.error().message()
259 <<
". Returning empty step vector.");
262 output = std::move(*
res);
265 if(output.first.size() == 0) {
266 ATH_MSG_WARNING(
"ZERO steps returned by stepper, that is not typically a good sign");
276Acts::Result<Acts::BoundTrackParameters>
278 const Acts::BoundTrackParameters& startParameters,
279 const Acts::Direction navDir,
280 const double pathLimit)
const
284 const Acts::MagneticFieldContext mfContext =
m_ctxProvider.getMagneticFieldContext(ctx);
285 const Acts::GeometryContext tgContext =
m_ctxProvider.getGeometryContext(ctx);
287 auto parameters = std::visit([&](
const auto& propagator) -> Acts::Result<Acts::BoundTrackParameters> {
288 using Propagator = std::decay_t<
decltype(propagator)>;
292 Acts::ActorList<Acts::MaterialInteractor, EndOfWorld>;
293 using Options =
typename Propagator::template Options<ActorList>;
298 auto result = propagator.propagate(startParameters, options);
300 ATH_MSG_DEBUG(
"Got error during propagation:" << result.error());
301 return result.error();
303 if (!result.value().endParameters.has_value()) {
304 ATH_MSG_DEBUG(
"Propagation did not result in valid end parameters.");
305 return Acts::PropagatorError::Failure;
307 return result.value().endParameters.value();
313Acts::Result<ExtrapolationTool::PropagationOutput>
315 const Acts::BoundTrackParameters& startParameters,
316 const Acts::Surface& target,
317 const Acts::Direction navDir,
318 const double pathLimit)
const {
321 PropagationOutput output;
323 const Acts::MagneticFieldContext mfContext =
m_ctxProvider.getMagneticFieldContext(ctx);
324 const Acts::GeometryContext tgContext =
m_ctxProvider.getGeometryContext(ctx);
326 auto res = std::visit([&](
const auto& propagator) -> Acts::Result<PropagationOutput> {
327 using Propagator = std::decay_t<
decltype(propagator)>;
331 Acts::ActorList<SteppingLogger, Acts::MaterialInteractor>;
332 using Options =
typename Propagator::template Options<ActorList>;
335 auto result = target.type() == Acts::Surface::Perigee ?
341 return result.error();
343 auto& propRes = *result;
347 output.first = std::move(steppingResults.steps);
348 output.second = std::move(materialResult);
349 return std::move(output);
354 <<
". Returning empty step vector.");
357 output = std::move(*
res);
365Acts::Result<Acts::BoundTrackParameters>
367 const Acts::BoundTrackParameters& startParameters,
368 const Acts::Surface& target,
369 const Acts::Direction navDir,
const double pathLimit)
const
374 const Acts::MagneticFieldContext mfContext =
m_ctxProvider.getMagneticFieldContext(ctx);
375 const Acts::GeometryContext tgContext =
m_ctxProvider.getGeometryContext(ctx);
377 auto parameters = std::visit([&](
const auto& propagator) -> Acts::Result<Acts::BoundTrackParameters> {
378 using Propagator = std::decay_t<
decltype(propagator)>;
382 Acts::ActorList<Acts::MaterialInteractor>;
383 using Options =
typename Propagator::template Options<ActorList>;
386 auto result = target.type() == Acts::Surface::Perigee ?
390 ATH_MSG_DEBUG(
"Got error during propagation: " << result.error());
391 return result.error();
393 if (!result.value().endParameters.has_value()) {
394 ATH_MSG_DEBUG(
"Propagation did not result in valid end parameters.");
395 return Acts::PropagatorError::Failure;
397 return result.value().endParameters.value();
404template<
typename OptionsType>
406 const Acts::MagneticFieldContext& mfContext,
407 const Acts::BoundTrackParameters& startParameters,
408 Acts::Direction navDir,
double pathLimit)
const {
409 using namespace Acts::UnitLiterals;
410 OptionsType options(gctx, mfContext);
412 options.pathLimit = pathLimit;
413 options.loopProtection
414 = (Acts::VectorHelpers::perp(startParameters.momentum())
417 options.direction = navDir;
428Acts::Result<ExtrapolationTool::BoundParamVec_t>
430 const Acts::BoundTrackParameters& startParameters,
431 const SurfaceRecordOptions& recordOpts)
const {
433 const Acts::MagneticFieldContext mfContext =
m_ctxProvider.getMagneticFieldContext(ctx);
434 const Acts::GeometryContext tgContext =
m_ctxProvider.getGeometryContext(ctx);
436 return std::visit([&](
const auto& propagator) -> Acts::Result<BoundParamVec_t> {
437 using Propagator = std::decay_t<
decltype(propagator)>;
440 using ParamRecorder_t = Acts::BoundParameterRecorder<Acts::SurfaceSelector>;
441 return std::visit([&](
const auto target) -> Acts::Result<BoundParamVec_t> {
442 using Target_t = std::decay_t<
decltype(target)>;
444 using TargetAborter_t = std::conditional_t<std::is_same_v<Target_t, const Acts::Surface*>,
445 PassedSurfaceAborter, PassedVolumeAborter>;
447 using ActorList = Acts::ActorList<ParamRecorder_t, Acts::MaterialInteractor,
448 TargetAborter_t, EndOfWorld>;
450 using Options =
typename Propagator::template Options<ActorList>;
453 recordOpts.navDir, recordOpts.pathLimit);
456 surfaceRecorder.selector.selectSensitive = recordOpts.recordSensitive;
457 surfaceRecorder.selector.selectMaterial = recordOpts.recordMaterial;
458 surfaceRecorder.selector.selectPassive = recordOpts.recordPassive;
461 if constexpr(std::is_same_v<Target_t, const Acts::Surface*>) {
462 aborter.targetSurface = target;
463 aborter.surpassedDistance = recordOpts.extraPathLength;
467 aborter.targetVolumeId = target->geometryId();
468 aborter.stopVolumeFlag = recordOpts.stopVolumeFlag;
471 auto propResult = propagator.propagate(startParameters, propOptions);
472 if (!propResult.ok()) {
474 return Acts::Result<BoundParamVec_t>::failure(std::make_error_code(std::errc::invalid_argument));
476 auto& result = *propResult;
477 return Acts::Result<BoundParamVec_t>::success(std::move(result.template
get<BoundParamVec_t>()));
478 }, recordOpts.target);
483 const Acts::BoundTrackParameters& startParameters,
484 const Acts::TrackingVolume& target,
485 const VolumeAbort stopVolumeFlag,
486 const Acts::Direction navDir,
487 const double pathLimit)
const {
488 const Acts::MagneticFieldContext mfContext =
m_ctxProvider.getMagneticFieldContext(ctx);
489 const Acts::GeometryContext tgContext =
m_ctxProvider.getGeometryContext(ctx);
491 return std::visit([&](
const auto& propagator) -> Acts::Result<Acts::BoundTrackParameters> {
492 using Propagator = std::decay_t<
decltype(propagator)>;
493 using ActorList = Acts::ActorList<Acts::MaterialInteractor, PassedVolumeAborter, EndOfWorld>;
495 using Options =
typename Propagator::template Options<ActorList>;
501 aborter.targetVolumeId = target.geometryId();
502 aborter.stopVolumeFlag = stopVolumeFlag;
505 auto propResult = propagator.propagate(startParameters, propOptions);
506 if (!propResult.ok()) {
508 return Acts::PropagatorError::Failure;
510 if (!propResult.ok()) {
511 ATH_MSG_DEBUG(
"Got error during propagation: " << propResult.error());
512 return propResult.error();
514 if (!propResult.value().endParameters.has_value()) {
515 ATH_MSG_DEBUG(
"Propagation did not result in valid end parameters.");
516 return Acts::PropagatorError::Failure;
518 return propResult.value().endParameters.value();
#define ATH_CHECK
Evaluate an expression and check for errors.
#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)
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
static Root::TMsgLogger logger("iLumiCalc")
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.