60 template <
typename traj_t>
104 calibrator.template connect<&detail::voidFitterCalibrator<traj_t>>();
105 updater.template connect<&detail::voidFitterUpdater<traj_t>>();
106 smoother.template connect<&detail::voidFitterSmoother<traj_t>>();
107 outlierFinder.template connect<&detail::voidOutlierFinder<traj_t>>();
109 .template connect<&detail::voidReverseFilteringLogic<traj_t>>();
116 template <
typename traj_t>
133 std::reference_wrapper<const CalibrationContext> cctx,
136 const Surface* rSurface =
nullptr,
137 bool mScattering =
true,
bool eLoss =
true,
138 bool rFiltering =
false,
double rfScaling = 1.0,
172 KalmanFitterTargetSurfaceStrategy::firstOrLast;
195 template <
typename traj_t>
266 template <
typename propagator_t,
typename traj_t>
277 std::unique_ptr<const Logger> _logger =
279 : m_propagator(std::
move(pPropagator)),
301 template <
typename parameters_t>
312 KalmanFitterTargetSurfaceStrategy::firstOrLast;
360 template <
typename propagator_state_t,
typename stepper_t,
361 typename navigator_t>
372 << stepper.position(state.stepping).transpose()
373 <<
" dir: " << stepper.direction(state.stepping).transpose()
375 << stepper.absoluteMomentum(state.stepping));
383 navigator.insertExternalSurface(state.navigation,
384 measurementIt->first);
391 auto surface = navigator.currentSurface(state.navigation);
392 std::string direction = state.options.direction.toString();
402 ACTS_VERBOSE(
"Perform " << direction <<
" filter step");
403 auto res =
filter(
surface, state, stepper, navigator, result);
405 ACTS_ERROR(
"Error in " << direction <<
" filter: " << res.error());
406 result.
result = res.error();
410 ACTS_VERBOSE(
"Perform " << direction <<
" filter step");
413 ACTS_ERROR(
"Error in " << direction <<
" filter: " << res.error());
414 result.
result = res.error();
426 navigator.navigationBreak(state.navigation))) {
430 auto trackStateProxy =
433 extensions.reverseFilteringLogic(trackStateProxy)) {
438 auto res =
reverse(state, stepper, navigator, result);
440 ACTS_ERROR(
"Error in reversing navigation: " << res.error());
441 result.
result = res.error();
449 auto res =
finalize(state, stepper, navigator, result);
451 ACTS_ERROR(
"Error in finalize: " << res.error());
452 result.
result = res.error();
467 MaterialUpdateStage::FullUpdate);
476 "The target surface needed for aborting reversed propagation "
482 "No target surface set. Completing without fitted track "
491 auto res = stepper.boundState(state.stepping, *
targetSurface,
true,
494 ACTS_ERROR(
"Error in " << direction <<
" filter: " << res.error());
495 result.
result = res.error();
498 auto& fittedState = *res;
506 auto fSurface = &trackState.referenceSurface();
507 auto surface_it = std::find_if(
510 [=](
const Surface*
s) {
return s == fSurface; });
514 trackState.unset(TrackStatePropMask::Smoothed);
535 template <
typename propagator_state_t,
typename stepper_t,
536 typename navigator_t>
542 ACTS_ERROR(
"No point to reverse for a track without measurements.");
543 return KalmanFitterError::ReverseNavigationFailed;
550 state.options.direction = state.options.direction.invert();
554 state.options.pathLimit =
555 state.options.direction * std::abs(state.options.pathLimit);
563 state.stepping, st.filtered(),
564 reversedFilteringCovarianceScaling * st.filteredCovariance(),
565 st.referenceSurface(), state.options.maxStepSize);
568 st.smoothed() = st.filtered();
569 st.smoothedCovariance() = st.filteredCovariance();
575 navigator.resetState(
576 state.navigation, state.geoContext, stepper.position(state.stepping),
577 state.options.direction * stepper.direction(state.stepping),
578 &st.referenceSurface(),
nullptr);
582 materialInteractor(navigator.currentSurface(state.navigation),
state,
599 template <
typename propagator_state_t,
typename stepper_t,
600 typename navigator_t>
605 auto sourcelink_it = inputMeasurements->find(surface->
geometryId());
606 if (sourcelink_it != inputMeasurements->end()) {
611 stepper.transportCovarianceToBound(state.stepping, *surface,
612 freeToBoundCorrection);
615 materialInteractor(surface, state, stepper, navigator,
616 MaterialUpdateStage::PreUpdate);
621 *calibrationContext, state, stepper,
extensions, *surface,
625 if (!trackStateProxyRes.ok()) {
626 return trackStateProxyRes.error();
629 const auto& trackStateProxy = *trackStateProxyRes;
633 if (trackStateProxy.typeFlags().test(
636 ACTS_VERBOSE(
"Filtering step successful, updated parameters are:\n"
637 << trackStateProxy.filtered().transpose());
639 stepper.update(state.stepping,
641 state.options.geoContext, trackStateProxy),
642 trackStateProxy.filtered(),
643 trackStateProxy.filteredCovariance(), *
surface);
649 materialInteractor(surface, state, stepper, navigator,
650 MaterialUpdateStage::PostUpdate);
671 if (!trackStateProxyRes.ok()) {
672 return trackStateProxyRes.error();
675 const auto& trackStateProxy = *trackStateProxyRes;
687 materialInteractor(surface, state, stepper, navigator,
688 MaterialUpdateStage::FullUpdate);
705 template <
typename propagator_state_t,
typename stepper_t,
706 typename navigator_t>
708 propagator_state_t&
state,
713 auto sourcelink_it = inputMeasurements->find(surface->
geometryId());
714 if (sourcelink_it != inputMeasurements->end()) {
718 <<
" detected in reversed propagation.");
723 surface == navigator.startSurface(state.navigation)) {
724 materialInteractor(surface, state, stepper, navigator,
725 MaterialUpdateStage::FullUpdate);
730 stepper.transportCovarianceToBound(state.stepping, *surface,
731 freeToBoundCorrection);
734 materialInteractor(surface, state, stepper, navigator,
735 MaterialUpdateStage::PreUpdate);
742 const size_t currentTrackIndex = fittedStates.addTrackState(
746 typename traj_t::TrackStateProxy trackStateProxy =
747 fittedStates.getTrackState(currentTrackIndex);
752 trackStateProxy.setReferenceSurface(surface->
getSharedPtr());
754 auto res = stepper.boundState(state.stepping, *surface,
false,
755 freeToBoundCorrection);
759 auto& [boundParams, jacobian,
pathLength] = *res;
762 trackStateProxy.predicted() =
std::move(boundParams.parameters());
763 if (boundParams.covariance().has_value()) {
764 trackStateProxy.predictedCovariance() =
768 trackStateProxy.jacobian() =
std::move(jacobian);
774 extensions.calibrator(state.geoContext, *calibrationContext,
775 sourcelink_it->second, trackStateProxy);
778 auto updateRes =
extensions.updater(state.geoContext, trackStateProxy,
779 state.options.direction,
logger());
780 if (!updateRes.ok()) {
781 ACTS_ERROR(
"Backward update step failed: " << updateRes.error());
782 return updateRes.error();
786 "Backward filtering step successful, updated parameters are:\n"
787 << trackStateProxy.filtered().transpose());
792 auto fSurface = &trackState.referenceSurface();
793 if (fSurface == surface) {
795 trackState.smoothed() = trackStateProxy.filtered();
796 trackState.smoothedCovariance() =
797 trackStateProxy.filteredCovariance();
806 stepper.update(state.stepping,
808 state.options.geoContext, trackStateProxy),
809 trackStateProxy.filtered(),
810 trackStateProxy.filteredCovariance(), *
surface);
813 materialInteractor(surface, state, stepper, navigator,
814 MaterialUpdateStage::PostUpdate);
816 }
else if (
surface->associatedDetectorElement() !=
nullptr ||
817 surface->surfaceMaterial() !=
nullptr) {
819 if (
surface->associatedDetectorElement() !=
nullptr) {
821 <<
" in reversed filtering");
822 if (
state.stepping.covTransport) {
825 }
else if (
surface->surfaceMaterial() !=
nullptr) {
827 <<
surface->geometryId() <<
" in reversed filtering");
828 if (
state.stepping.covTransport) {
829 stepper.transportCovarianceToCurvilinear(
state.stepping);
835 if (
surface->surfaceMaterial() !=
nullptr) {
838 MaterialUpdateStage::FullUpdate);
842 return Result<void>::success();
857 template <
typename propagator_state_t,
typename stepper_t,
858 typename navigator_t>
864 bool hasMaterial =
false;
882 <<
" at update stage: " << updateStage <<
" are :");
884 << interaction.
Eloss <<
", "
885 <<
"variancePhi = " << interaction.
variancePhi <<
", "
895 if (not hasMaterial) {
898 <<
" at update stage: "
913 template <
typename propagator_state_t,
typename stepper_t,
914 typename navigator_t>
934 if (isMeasurement && !isOutlier) {
935 firstStateIndex = st.index();
942 ACTS_ERROR(
"Smoothing for a track without measurements.");
943 return KalmanFitterError::SmoothFailed;
947 <<
" filtered track states.");
952 result.lastMeasurementIndex,
logger());
953 if (!smoothRes.ok()) {
954 ACTS_ERROR(
"Smoothing step failed: " << smoothRes.error());
955 return smoothRes.error();
959 if (targetSurface ==
nullptr) {
960 return Result<void>::success();
964 auto firstCreatedState =
965 result.fittedStates->getTrackState(firstStateIndex);
966 auto lastCreatedMeasurement =
967 result.fittedStates->getTrackState(result.lastMeasurementIndex);
975 true,
state.options.targetTolerance)
982 state.options.geoContext, firstCreatedState);
984 state.options.geoContext, lastCreatedMeasurement);
987 const auto firstIntersection =
target(firstParams);
988 const auto lastIntersection =
target(lastParams);
998 bool useFirstTrackState =
true;
999 switch (targetSurfaceStrategy) {
1000 case KalmanFitterTargetSurfaceStrategy::first:
1001 useFirstTrackState =
true;
1003 case KalmanFitterTargetSurfaceStrategy::last:
1004 useFirstTrackState =
false;
1006 case KalmanFitterTargetSurfaceStrategy::firstOrLast:
1007 useFirstTrackState = std::abs(firstIntersection.pathLength()) <=
1008 std::abs(lastIntersection.pathLength());
1011 ACTS_ERROR(
"Unknown target surface strategy");
1012 return KalmanFitterError::SmoothFailed;
1014 bool reverseDirection =
false;
1015 if (useFirstTrackState) {
1016 stepper.resetState(
state.stepping, firstCreatedState.smoothed(),
1017 firstCreatedState.smoothedCovariance(),
1018 firstCreatedState.referenceSurface(),
1019 state.options.maxStepSize);
1020 reverseDirection = firstIntersection.pathLength() < 0;
1022 stepper.resetState(
state.stepping, lastCreatedMeasurement.smoothed(),
1023 lastCreatedMeasurement.smoothedCovariance(),
1024 lastCreatedMeasurement.referenceSurface(),
1025 state.options.maxStepSize);
1026 reverseDirection = lastIntersection.pathLength() < 0;
1029 if (reverseDirection) {
1031 "Reverse navigation direction after smoothing for reaching the "
1033 state.options.direction =
state.options.direction.invert();
1035 const auto&
surface = useFirstTrackState
1036 ? firstCreatedState.referenceSurface()
1037 : lastCreatedMeasurement.referenceSurface();
1040 "Smoothing successful, updating stepping state to smoothed "
1041 "parameters at surface "
1042 <<
surface.geometryId() <<
". Prepared to reach the target surface.");
1052 return Result<void>::success();
1056 template <
typename parameters_t>
1062 template <
typename propagator_state_t,
typename stepper_t,
1063 typename navigator_t,
typename result_t>
1064 bool operator()(propagator_state_t& ,
const stepper_t& ,
1065 const navigator_t& ,
const result_t& result,
1067 if (!result.result.ok() or result.finished) {
1094 template <
typename source_link_iterator_t,
typename start_parameters_t,
1096 typename track_container_t,
template <
typename>
class holder_t,
1097 bool _isdn = isDirectNavigator>
1098 auto fit(source_link_iterator_t
it, source_link_iterator_t
end,
1099 const start_parameters_t& sParameters,
1102 const -> std::enable_if_t<
1108 <<
" input measurements");
1109 std::map<GeometryIdentifier, SourceLink> inputMeasurements;
1113 const Surface*
surface = kfOptions.extensions.surfaceAccessor(sl);
1116 inputMeasurements.emplace(geoId,
std::move(sl));
1123 using KalmanResult =
typename KalmanActor::result_type;
1124 using Actors = ActionList<KalmanActor>;
1125 using Aborters = AbortList<KalmanAborter>;
1129 kfOptions.geoContext, kfOptions.magFieldContext);
1135 auto& kalmanActor = kalmanOptions.
actionList.template get<KalmanActor>();
1136 kalmanActor.inputMeasurements = &inputMeasurements;
1137 kalmanActor.targetSurface = kfOptions.referenceSurface;
1138 kalmanActor.multipleScattering = kfOptions.multipleScattering;
1139 kalmanActor.energyLoss = kfOptions.energyLoss;
1140 kalmanActor.reversedFiltering = kfOptions.reversedFiltering;
1141 kalmanActor.reversedFilteringCovarianceScaling =
1142 kfOptions.reversedFilteringCovarianceScaling;
1143 kalmanActor.freeToBoundCorrection = kfOptions.freeToBoundCorrection;
1144 kalmanActor.calibrationContext = &kfOptions.calibrationContext.get();
1145 kalmanActor.extensions = kfOptions.extensions;
1146 kalmanActor.actorLogger = m_actorLogger.get();
1148 typename propagator_t::template action_list_t_result_t<
1152 auto&
r = inputResult.template get<KalmanFitterResult<traj_t>>();
1154 r.fittedStates = &trackContainer.trackStateContainer();
1157 auto result = m_propagator.template propagate(
1158 sParameters, kalmanOptions,
false,
std::move(inputResult));
1161 ACTS_ERROR(
"Propagation failed: " << result.error());
1162 return result.error();
1165 auto& propRes = *result;
1168 auto kalmanResult =
std::move(propRes.template get<KalmanResult>());
1172 if (kalmanResult.result.ok() and not kalmanResult.measurementStates) {
1173 kalmanResult.result =
Result<void>(KalmanFitterError::NoMeasurementFound);
1176 if (!kalmanResult.result.ok()) {
1178 << kalmanResult.result.error() <<
", "
1179 << kalmanResult.result.error().message());
1180 return kalmanResult.result.error();
1183 auto track = trackContainer.getTrack(trackContainer.addTrack());
1184 track.tipIndex() = kalmanResult.lastMeasurementIndex;
1185 if (kalmanResult.fittedParameters) {
1186 const auto& params = kalmanResult.fittedParameters.value();
1187 track.parameters() = params.parameters();
1188 track.covariance() = params.covariance().value();
1189 track.setReferenceSurface(params.referenceSurface().getSharedPtr());
1194 if (trackContainer.hasColumn(
hashString(
"smoothed"))) {
1195 track.template component<bool,
hashString(
"smoothed")>() =
1196 kalmanResult.smoothed;
1198 if (trackContainer.hasColumn(
hashString(
"reversed"))) {
1199 track.template component<bool,
hashString(
"reversed")>() =
1200 kalmanResult.reversed;
1228 template <
typename source_link_iterator_t,
typename start_parameters_t,
1230 typename track_container_t,
template <
typename>
class holder_t,
1231 bool _isdn = isDirectNavigator>
1232 auto fit(source_link_iterator_t
it, source_link_iterator_t
end,
1233 const start_parameters_t& sParameters,
1235 const std::vector<const Surface*>& sSequence,
1237 const -> std::enable_if_t<
1243 <<
" input measurements");
1244 std::map<GeometryIdentifier, SourceLink> inputMeasurements;
1247 const Surface*
surface = kfOptions.extensions.surfaceAccessor(sl);
1250 inputMeasurements.emplace(geoId, sl);
1257 using KalmanResult =
typename KalmanActor::result_type;
1258 using Actors = ActionList<DirectNavigator::Initializer, KalmanActor>;
1259 using Aborters = AbortList<KalmanAborter>;
1263 kfOptions.geoContext, kfOptions.magFieldContext);
1269 auto& kalmanActor = kalmanOptions.
actionList.template get<KalmanActor>();
1270 kalmanActor.inputMeasurements = &inputMeasurements;
1271 kalmanActor.targetSurface = kfOptions.referenceSurface;
1272 kalmanActor.targetSurfaceStrategy = kfOptions.referenceSurfaceStrategy;
1273 kalmanActor.multipleScattering = kfOptions.multipleScattering;
1274 kalmanActor.energyLoss = kfOptions.energyLoss;
1275 kalmanActor.reversedFiltering = kfOptions.reversedFiltering;
1276 kalmanActor.reversedFilteringCovarianceScaling =
1277 kfOptions.reversedFilteringCovarianceScaling;
1278 kalmanActor.extensions = kfOptions.extensions;
1279 kalmanActor.actorLogger = m_actorLogger.get();
1282 auto& dInitializer =
1283 kalmanOptions.
actionList.template get<DirectNavigator::Initializer>();
1284 dInitializer.navSurfaces = sSequence;
1286 typename propagator_t::template action_list_t_result_t<
1290 auto&
r = inputResult.template get<KalmanFitterResult<traj_t>>();
1292 r.fittedStates = &trackContainer.trackStateContainer();
1295 auto result = m_propagator.template propagate(
1296 sParameters, kalmanOptions,
false,
std::move(inputResult));
1299 ACTS_ERROR(
"Propagation failed: " << result.error());
1300 return result.error();
1303 const auto& propRes = *result;
1306 auto kalmanResult = propRes.template get<KalmanResult>();
1310 if (kalmanResult.result.ok() and not kalmanResult.measurementStates) {
1311 kalmanResult.result =
Result<void>(KalmanFitterError::NoMeasurementFound);
1314 if (!kalmanResult.result.ok()) {
1316 << kalmanResult.result.error() <<
", "
1317 << kalmanResult.result.error().message());
1318 return kalmanResult.result.error();
1321 auto track = trackContainer.getTrack(trackContainer.addTrack());
1322 track.tipIndex() = kalmanResult.lastMeasurementIndex;
1323 if (kalmanResult.fittedParameters) {
1324 const auto& params = kalmanResult.fittedParameters.value();
1325 track.parameters() = params.parameters();
1326 track.covariance() = params.covariance().value();
1327 track.setReferenceSurface(params.referenceSurface().getSharedPtr());
1332 if (trackContainer.hasColumn(
hashString(
"smoothed"))) {
1333 track.template component<bool,
hashString(
"smoothed")>() =
1334 kalmanResult.smoothed;
1336 if (trackContainer.hasColumn(
hashString(
"reversed"))) {
1337 track.template component<bool,
hashString(
"reversed")>() =
1338 kalmanResult.reversed;