49 template <
typename outlier_finder_t = Vo
idOutlierFinder>
68 std::reference_wrapper<const MagneticFieldContext> mctx,
69 std::reference_wrapper<const CalibrationContext> cctx,
71 const Surface* rSurface =
nullptr,
72 bool mScattering =
true,
bool eLoss =
true,
73 bool bwdFiltering =
false)
77 outlierFinder(outlierFinder),
84 std::reference_wrapper<const GeometryContext>
geoContext;
106 template <
typename source_link_t>
182 template <
typename propagator_t,
typename updater_t = VoidKalmanUpdater,
183 typename smoother_t = VoidKalmanSmoother,
184 typename outlier_finder_t = VoidOutlierFinder,
185 typename calibrator_t = VoidMeasurementCalibrator,
186 typename input_converter_t = VoidKalmanComponents,
187 typename output_converter_t = VoidKalmanComponents>
204 std::unique_ptr<const Logger>
logger =
206 input_converter_t pInputCnv = input_converter_t(),
207 output_converter_t pOutputCnv = output_converter_t())
236 template <
typename source_link_t,
typename parameters_t>
242 Actor(updater_t pUpdater = updater_t(), smoother_t pSmoother = smoother_t(),
243 outlier_finder_t pOutlierFinder = outlier_finder_t(),
244 calibrator_t pCalibrator = calibrator_t())
276 template <
typename propagator_state_t,
typename stepper_t>
293 auto surface = state.navigation.currentSurface;
307 ACTS_ERROR(
"Error in forward filter: " << res.error());
308 result.
result = res.error();
310 }
else if (state.stepping.navDir ==
backward) {
314 ACTS_ERROR(
"Error in backward filter: " << res.error());
315 result.
result = res.error();
324 if (state.stepping.navDir ==
forward) {
327 state.navigation.navigationBreak)) {
335 reverse(state, stepper, result);
341 auto res =
finalize(state, stepper, result);
343 ACTS_ERROR(
"Error in finalize: " << res.error());
344 result.
result = res.error();
357 auto fittedState = stepper.boundState(state.stepping, *
targetSurface);
361 state.navigation.navigationBreak =
true;
366 auto fSurface = &state.referenceSurface();
367 auto surface_it = std::find_if(
389 template <
typename propagator_state_t,
typename stepper_t>
401 template <
typename propagator_state_t,
typename stepper_t>
406 state.options.maxStepSize = -1.0 * state.options.maxStepSize;
408 state.options.pathLimit = -1.0 * state.options.pathLimit;
412 state.navigation =
typename propagator_t::NavigatorState();
414 if (st.hasUncalibrated()) {
416 state.navigation.startSurface = &st.referenceSurface();
417 state.navigation.startLayer =
418 state.navigation.startSurface->associatedLayer();
419 state.navigation.startVolume =
420 state.navigation.startLayer->trackingVolume();
421 state.navigation.targetSurface = targetSurface;
422 state.navigation.currentSurface = state.navigation.startSurface;
423 state.navigation.currentVolume = state.navigation.startVolume;
426 stepper.update(state.stepping,
427 st.filteredParameters(state.options.geoContext));
431 state.stepping.pathAccumulated = 0.;
433 st.referenceSurface().initJacobianToGlobal(
434 state.options.geoContext, state.stepping.jacToGlobal,
435 state.stepping.pos, state.stepping.dir,
436 st.filteredParameters(state.options.geoContext).parameters());
437 state.stepping.jacobian = BoundMatrix::Identity();
438 state.stepping.jacTransport = FreeMatrix::Identity();
439 state.stepping.derivative = FreeVector::Zero();
442 st.smoothed() = st.filtered();
443 st.smoothedCovariance() = st.filteredCovariance();
448 materialInteractor(state.navigation.currentSurface, state, stepper);
465 template <
typename propagator_state_t,
typename stepper_t>
469 auto sourcelink_it = inputMeasurements.find(surface);
470 if (sourcelink_it != inputMeasurements.end()) {
476 materialInteractor(surface, state, stepper,
preUpdate);
479 auto [boundParams, jacobian, pathLength] =
480 stepper.boundState(state.stepping, *surface);
488 auto trackStateProxy =
492 trackStateProxy.uncalibrated() = sourcelink_it->second;
495 trackStateProxy.predicted() = boundParams.parameters();
496 trackStateProxy.predictedCovariance() = *boundParams.covariance();
497 trackStateProxy.jacobian() = jacobian;
498 trackStateProxy.pathLength() = pathLength;
503 [&](
const auto& calibrated) {
504 trackStateProxy.setCalibrated(calibrated);
506 m_calibrator(trackStateProxy.uncalibrated(),
507 trackStateProxy.predicted()));
510 auto& typeFlags = trackStateProxy.typeFlags();
515 auto updateRes = m_updater(state.geoContext, trackStateProxy,
forward);
516 if (!updateRes.ok()) {
517 ACTS_ERROR(
"Update step failed: " << updateRes.error());
518 return updateRes.error();
520 if (not m_outlierFinder(trackStateProxy)) {
525 "Filtering step successful, updated parameters are : \n"
526 << trackStateProxy.filtered().transpose());
530 stepper.update(state.stepping, trackStateProxy.filteredParameters(
531 state.options.geoContext));
536 "Filtering step successful. But measurement is deterimined to "
537 "be an outlier. Stepping state is not updated.")
543 materialInteractor(surface, state, stepper,
postUpdate);
560 auto trackStateProxy =
564 trackStateProxy.setReferenceSurface(surface->
getSharedPtr());
567 auto& typeFlags = trackStateProxy.typeFlags();
580 auto [boundParams, jacobian, pathLength] =
581 stepper.boundState(state.stepping, *surface);
584 trackStateProxy.predicted() = boundParams.parameters();
585 trackStateProxy.predictedCovariance() = *boundParams.covariance();
586 trackStateProxy.jacobian() = jacobian;
587 trackStateProxy.pathLength() = pathLength;
592 auto [curvilinearParams, jacobian, pathLength] =
593 stepper.curvilinearState(state.stepping);
596 trackStateProxy.predicted() = curvilinearParams.parameters();
597 trackStateProxy.predictedCovariance() =
598 *curvilinearParams.covariance();
599 trackStateProxy.jacobian() = jacobian;
600 trackStateProxy.pathLength() = pathLength;
605 trackStateProxy.data().ifiltered = trackStateProxy.data().ipredicted;
612 materialInteractor(surface, state, stepper,
fullUpdate);
626 template <
typename propagator_state_t,
typename stepper_t>
628 propagator_state_t& state,
632 auto sourcelink_it = inputMeasurements.find(surface);
633 if (sourcelink_it != inputMeasurements.end()) {
637 <<
" detected in backward propagation.");
641 if (state.stepping.navDir ==
backward and
642 surface == state.navigation.startSurface) {
643 materialInteractor(surface, state, stepper);
648 materialInteractor(surface, state, stepper,
preUpdate);
651 auto [boundParams, jacobian, pathLength] =
652 stepper.boundState(state.stepping, *surface);
659 auto trackStateProxy = result.
fittedStates.getTrackState(tempTrackTip);
662 trackStateProxy.uncalibrated() = sourcelink_it->second;
665 trackStateProxy.predicted() = boundParams.parameters();
666 trackStateProxy.predictedCovariance() = *boundParams.covariance();
667 trackStateProxy.jacobian() = jacobian;
668 trackStateProxy.pathLength() = pathLength;
673 [&](
const auto& calibrated) {
674 trackStateProxy.setCalibrated(calibrated);
676 m_calibrator(trackStateProxy.uncalibrated(),
677 trackStateProxy.predicted()));
680 auto updateRes = m_updater(state.geoContext, trackStateProxy,
backward);
681 if (!updateRes.ok()) {
682 ACTS_ERROR(
"Backward update step failed: " << updateRes.error());
683 return updateRes.error();
687 "Backward Filtering step successful, updated parameters are : \n"
688 << trackStateProxy.filtered().transpose());
692 auto fSurface = &state.referenceSurface();
693 if (fSurface == surface) {
695 state.smoothed() = trackStateProxy.filtered();
696 state.smoothedCovariance() = trackStateProxy.filteredCovariance();
705 stepper.update(state.stepping, trackStateProxy.filteredParameters(
706 state.options.geoContext));
709 materialInteractor(surface, state, stepper,
postUpdate);
711 }
else if (
surface->surfaceMaterial() !=
nullptr) {
713 if (
surface->associatedDetectorElement() !=
nullptr) {
715 <<
" in backward filtering");
716 if (state.stepping.covTransport) {
721 <<
surface->geoID() <<
" in backward filtering");
722 if (state.stepping.covTransport) {
723 stepper.covarianceTransport(state.stepping);
728 state.stepping.jacobian = BoundMatrix::Identity();
734 return Result<void>::success();
747 template <
typename propagator_state_t,
typename stepper_t>
748 void materialInteractor(
752 bool hasMaterial =
false;
770 <<
" at update stage: " << updateStage <<
" are :");
772 << interaction.
Eloss <<
", "
773 <<
"variancePhi = " << interaction.
variancePhi <<
", "
783 if (not hasMaterial) {
786 <<
" at update stage: "
799 template <
typename propagator_state_t,
typename stepper_t>
806 std::vector<size_t> measurementIndices;
814 measurementIndices.emplace_back(st.index());
815 }
else if (measurementIndices.empty()) {
818 st.data().ismoothed = detail_lt::IndexData::kInvalid;
821 if (not measurementIndices.empty()) {
827 if (measurementIndices.empty()) {
828 ACTS_ERROR(
"Smoothing for a track without measurements.");
829 return KalmanFitterError::SmoothFailed;
834 <<
" filtered track states.");
837 auto smoothRes = m_smoother(state.geoContext, result.fittedStates,
838 measurementIndices.front());
840 if (!smoothRes.ok()) {
841 ACTS_ERROR(
"Smoothing step failed: " << smoothRes.error());
842 return smoothRes.error();
845 auto firstMeasurement =
846 result.fittedStates.getTrackState(measurementIndices.back());
847 parameters_t smoothedPars =
848 firstMeasurement.smoothedParameters(state.options.geoContext);
852 "Smoothing successful, updating stepping state, "
853 "set target surface.");
854 stepper.update(state.stepping, smoothedPars);
856 state.stepping.stepSize =
857 ConstrainedStep(-1. * state.options.maxStepSize);
860 state.stepping.pathAccumulated = 0.;
864 return Result<void>::success();
889 template <
typename source_link_t,
typename parameters_t>
895 template <
typename propagator_state_t,
typename stepper_t,
897 bool operator()(propagator_state_t& ,
const stepper_t& ,
898 const result_t& result)
const {
899 if (!result.result.ok()) {
924 template <
typename source_link_t,
typename start_parameters_t,
925 typename kalman_fitter_options_t,
928 auto fit(
const std::vector<source_link_t>& sourcelinks,
929 const start_parameters_t& sParameters,
930 const kalman_fitter_options_t& kfOptions)
const
931 -> std::enable_if_t<!isDirectNavigator, result_t> {
932 static_assert(SourceLinkConcept<source_link_t>,
933 "Source link does not fulfill SourceLinkConcept");
936 std::is_same<outlier_finder_t,
937 typename kalman_fitter_options_t::OutlierFinder>::
value,
938 "Inconsistent type of outlier finder between kalman fitter and "
939 "kalman fitter options");
943 ACTS_VERBOSE(
"Preparing " << sourcelinks.size() <<
" input measurements");
944 std::map<const Surface*, source_link_t> inputMeasurements;
945 for (
const auto& sl : sourcelinks) {
946 const Surface* srf = &sl.referenceSurface();
947 inputMeasurements.emplace(srf, sl);
953 using KalmanResult =
typename KalmanActor::result_type;
959 kfOptions.geoContext, kfOptions.magFieldContext);
962 auto& kalmanActor = kalmanOptions.
actionList.template get<KalmanActor>();
963 kalmanActor.m_logger = m_logger.get();
964 kalmanActor.inputMeasurements = std::move(inputMeasurements);
965 kalmanActor.targetSurface = kfOptions.referenceSurface;
966 kalmanActor.multipleScattering = kfOptions.multipleScattering;
967 kalmanActor.energyLoss = kfOptions.energyLoss;
968 kalmanActor.backwardFiltering = kfOptions.backwardFiltering;
971 kalmanActor.m_outlierFinder = kfOptions.outlierFinder;
974 kalmanActor.m_updater.m_logger = m_logger;
975 kalmanActor.m_smoother.m_logger = m_logger;
978 auto result = m_propagator.template propagate(sParameters, kalmanOptions);
981 ACTS_ERROR(
"Propapation failed: " << result.error());
982 return result.error();
985 const auto& propRes = *result;
988 auto kalmanResult = propRes.template get<KalmanResult>();
992 if (kalmanResult.result.ok() and not kalmanResult.processedStates) {
993 kalmanResult.result =
Result<void>(KalmanFitterError::PropagationInVain);
996 if (!kalmanResult.result.ok()) {
997 ACTS_ERROR(
"KalmanFilter failed: " << kalmanResult.result.error());
998 return kalmanResult.result.error();
1002 return m_outputConverter(std::move(kalmanResult));
1023 template <
typename source_link_t,
typename start_parameters_t,
1024 typename kalman_fitter_options_t,
1027 auto fit(
const std::vector<source_link_t>& sourcelinks,
1028 const start_parameters_t& sParameters,
1029 const kalman_fitter_options_t& kfOptions,
1030 const std::vector<const Surface*>& sSequence)
const
1031 -> std::enable_if_t<isDirectNavigator, result_t> {
1032 static_assert(SourceLinkConcept<source_link_t>,
1033 "Source link does not fulfill SourceLinkConcept");
1036 std::is_same<outlier_finder_t,
1037 typename kalman_fitter_options_t::OutlierFinder>::
value,
1038 "Inconsistent type of outlier finder between kalman fitter and "
1039 "kalman fitter options");
1043 ACTS_VERBOSE(
"Preparing " << sourcelinks.size() <<
" input measurements");
1044 std::map<const Surface*, source_link_t> inputMeasurements;
1045 for (
const auto& sl : sourcelinks) {
1046 const Surface* srf = &sl.referenceSurface();
1047 inputMeasurements.emplace(srf, sl);
1053 using KalmanResult =
typename KalmanActor::result_type;
1059 kfOptions.geoContext, kfOptions.magFieldContext);
1062 auto& kalmanActor = kalmanOptions.
actionList.template get<KalmanActor>();
1063 kalmanActor.m_logger = m_logger.get();
1064 kalmanActor.inputMeasurements = std::move(inputMeasurements);
1065 kalmanActor.targetSurface = kfOptions.referenceSurface;
1066 kalmanActor.multipleScattering = kfOptions.multipleScattering;
1067 kalmanActor.energyLoss = kfOptions.energyLoss;
1068 kalmanActor.backwardFiltering = kfOptions.backwardFiltering;
1071 kalmanActor.m_outlierFinder.m_config = kfOptions.outlierFinderConfig;
1074 kalmanActor.m_updater.m_logger = m_logger;
1075 kalmanActor.m_smoother.m_logger = m_logger;
1078 auto& dInitializer =
1079 kalmanOptions.
actionList.template get<DirectNavigator::Initializer>();
1080 dInitializer.surfaceSequence = sSequence;
1083 auto result = m_propagator.template propagate(sParameters, kalmanOptions);
1086 ACTS_ERROR(
"Propapation failed: " << result.error());
1087 return result.error();
1090 const auto& propRes = *result;
1093 auto kalmanResult = propRes.template get<KalmanResult>();
1097 if (kalmanResult.result.ok() and not kalmanResult.processedStates) {
1098 kalmanResult.result =
Result<void>(KalmanFitterError::PropagationInVain);
1101 if (!kalmanResult.result.ok()) {
1102 ACTS_ERROR(
"KalmanFilter failed: " << kalmanResult.result.error());
1103 return kalmanResult.result.error();
1107 return m_outputConverter(std::move(kalmanResult));