38 #include <unordered_map>
70 template <
typename source_link_selector_t>
94 std::reference_wrapper<const GeometryContext>
gctx,
95 std::reference_wrapper<const MagneticFieldContext> mctx,
96 std::reference_wrapper<const CalibrationContext> cctx,
98 bool mScattering =
true,
bool eLoss =
true,
bool rSmoothing =
true)
131 template <
typename source_link_t>
143 std::vector<std::pair<size_t, CombinatorialKalmanFilterTipState>>
activeTips;
146 std::unordered_map<const Surface*, std::unordered_map<size_t, size_t>>
211 template <
typename propagator_t,
typename updater_t = VoidKalmanUpdater,
212 typename smoother_t = VoidKalmanSmoother,
213 typename source_link_selector_t = CKFSourceLinkSelector,
214 typename branch_stopper_t = VoidBranchStopper,
215 typename calibrator_t = VoidMeasurementCalibrator,
216 typename input_converter_t = VoidKalmanComponents,
217 typename output_converter_t = VoidKalmanComponents>
229 std::unique_ptr<const Logger>
logger =
231 input_converter_t pInputCnv = input_converter_t(),
232 output_converter_t pOutputCnv = output_converter_t())
261 template <
typename source_link_t,
typename parameters_t>
266 using BoundState = std::tuple<BoundParameters, BoundMatrix, double>;
268 std::tuple<CurvilinearParameters, BoundMatrix, double>;
273 Actor(updater_t pUpdater = updater_t(), smoother_t pSmoother = smoother_t(),
274 source_link_selector_t pSourceLinkSelector = source_link_selector_t(),
275 branch_stopper_t pBranchStopper = branch_stopper_t(),
276 calibrator_t pCalibrator = calibrator_t())
285 std::unordered_map<const Surface*, std::vector<source_link_t>>
305 template <
typename propagator_state_t,
typename stepper_t>
319 auto surface = state.navigation.currentSurface;
337 ACTS_ERROR(
"Error in filter: " << res.error());
338 result.
result = res.error();
351 const auto& lastActiveTip = result.
activeTips.back().first;
353 const auto& iprevious =
354 result.
fittedStates.getTrackState(lastActiveTip).previous();
358 const auto& [currentTip, tipState] = result.
activeTips.back();
359 if (result.
fittedStates.getTrackState(currentTip).previous() !=
364 if (tipState.nMeasurements > 0) {
366 << currentTip <<
" and there are nMeasurements = "
367 << tipState.nMeasurements
368 <<
", nOutliers = " << tipState.nOutliers
369 <<
", nHoles = " << tipState.nHoles <<
" on track");
370 result.
trackTips.emplace_back(currentTip);
380 << result.
trackTips.size() <<
" tracks");
385 reset(state, stepper, result);
394 Result<void>(CombinatorialKalmanFilterError::NoTracksFound);
399 state.navigation.targetReached =
true;
407 "Finalize/run smoothing for track with entry index = "
413 auto res =
finalize(state, stepper, result);
415 ACTS_ERROR(
"Error in finalize: " << res.error());
416 result.
result = res.error();
432 std::get<BoundParameters>(fittedState));
438 state.navigation.targetReached =
false;
442 state.stepping.stepSize =
445 state.stepping.navDir =
forward;
448 "Finish forward Kalman filtering and backward smoothing");
464 template <
typename propagator_state_t,
typename stepper_t>
470 state.navigation =
typename propagator_t::NavigatorState();
471 state.navigation.startSurface = ¤tState.referenceSurface();
472 if (state.navigation.startSurface->associatedLayer() !=
nullptr) {
473 state.navigation.startLayer =
474 state.navigation.startSurface->associatedLayer();
476 state.navigation.startVolume =
477 state.navigation.startLayer->trackingVolume();
479 state.navigation.currentSurface = state.navigation.startSurface;
480 state.navigation.currentVolume = state.navigation.startVolume;
483 stepper.update(state.stepping,
484 currentState.filteredParameters(state.options.geoContext));
487 state.options.geoContext, state.stepping.jacToGlobal,
488 state.stepping.pos, state.stepping.dir,
489 currentState.filteredParameters(state.options.geoContext)
491 state.stepping.jacobian = BoundMatrix::Identity();
492 state.stepping.jacTransport = FreeMatrix::Identity();
493 state.stepping.derivative = FreeVector::Zero();
496 state.stepping.pathAccumulated = currentState.pathLength();
515 template <
typename propagator_state_t,
typename stepper_t>
519 size_t nBranchesOnSurface = 0;
532 auto boundState = stepper.boundState(state.stepping, *surface);
533 auto boundParams = std::get<BoundParameters>(
boundState);
536 auto& sourcelinks = sourcelink_it->second;
542 bool isOutlier =
false;
546 if (!sourcelinkSelectionRes.ok()) {
547 ACTS_ERROR(
"Selection of source links failed: "
548 << sourcelinkSelectionRes.error());
549 return sourcelinkSelectionRes.error();
554 size_t prevTip = SIZE_MAX;
558 prevTipState = result.
activeTips.back().second;
564 size_t neighborTip = SIZE_MAX;
569 bool isPredictedShared = (neighborTip != SIZE_MAX);
573 bool isSourcelinkShared =
false;
574 size_t sharedTip = SIZE_MAX;
577 auto& sourcelinkTipsOnSurface = sourcelinkTips_it->second;
578 auto index_it = sourcelinkTipsOnSurface.find(index);
579 if (index_it != sourcelinkTipsOnSurface.end()) {
580 isSourcelinkShared =
true;
581 sharedTip = index_it->second;
591 (isPredictedShared ? ~TrackStatePropMask
::Predicted
600 stateMask,
boundState, sourcelinks.at(index), isOutlier, result,
601 state.geoContext, prevTip, prevTipState, neighborTip, sharedTip);
602 if (addStateRes.ok()) {
603 const auto& [currentTip, tipState] = addStateRes.value();
605 if (not isSourcelinkShared) {
606 auto& sourcelinkTipsOnSurface = result.sourcelinkTips[
surface];
607 sourcelinkTipsOnSurface.emplace(index, currentTip);
610 neighborTip = currentTip;
615 result.activeTips.emplace_back(std::move(currentTip),
616 std::move(tipState));
618 nBranchesOnSurface++;
623 if (nBranchesOnSurface > 0 and not isOutlier) {
625 ACTS_VERBOSE(
"Filtering step successful with " << nBranchesOnSurface
629 auto filteredParams =
631 .filteredParameters(state.options.geoContext);
632 stepper.update(state.stepping, filteredParams);
633 ACTS_VERBOSE(
"Stepping state is updated with filtered parameter: \n"
634 << filteredParams.parameters().transpose()
635 <<
" of track state with tip = "
643 nBranchesOnSurface = 1;
646 size_t prevTip = SIZE_MAX;
655 std::string type = isSensitive ?
"sensitive" :
"passive";
665 (isSensitive or (not isSensitive and
smoothing))) {
678 size_t currentTip = SIZE_MAX;
681 auto boundState = stepper.boundState(state.stepping, *surface);
697 result.
activeTips.emplace_back(std::move(currentTip),
698 std::move(tipState));
701 nBranchesOnSurface = 0;
709 nBranchesOnSurface = 1;
713 if (nBranchesOnSurface == 0) {
718 reset(state, stepper, result);
721 << result.
trackTips.size() <<
" found tracks");
746 const source_link_t& sourcelink,
bool isOutlier,
result_type& result,
747 std::reference_wrapper<const GeometryContext>
geoContext,
748 const size_t& prevTip,
const TipState& prevTipState,
749 size_t neighborTip = SIZE_MAX,
size_t sharedTip = SIZE_MAX)
const {
754 auto currentTip = result.
fittedStates.addTrackState(stateMask, prevTip);
757 auto trackStateProxy = result.
fittedStates.getTrackState(currentTip);
759 auto [boundParams, jacobian, pathLength] =
boundState;
763 neighborTip != SIZE_MAX) {
765 auto neighborState = result.
fittedStates.getTrackState(neighborTip);
766 trackStateProxy.data().ipredicted = neighborState.data().ipredicted;
768 trackStateProxy.predicted() = boundParams.parameters();
769 trackStateProxy.predictedCovariance() = *boundParams.covariance();
771 trackStateProxy.jacobian() = jacobian;
772 trackStateProxy.pathLength() = pathLength;
777 sharedTip != SIZE_MAX) {
780 auto shared = result.
fittedStates.getTrackState(sharedTip);
781 trackStateProxy.data().iuncalibrated = shared.data().iuncalibrated;
783 trackStateProxy.uncalibrated() = sourcelink;
786 [&](
const auto& calibrated) {
787 trackStateProxy.setCalibrated(calibrated);
790 trackStateProxy.predicted()));
793 auto& typeFlags = trackStateProxy.typeFlags();
802 ACTS_VERBOSE(
"Creating outlier track state with tip = " << currentTip);
810 trackStateProxy.data().ifiltered = trackStateProxy.data().ipredicted;
813 auto updateRes =
m_updater(geoContext, trackStateProxy);
814 if (!updateRes.ok()) {
815 ACTS_ERROR(
"Update step failed: " << updateRes.error());
816 return updateRes.error();
819 "Creating measurement track state with tip = " << currentTip);
825 return std::make_pair(std::move(currentTip), std::move(tipState));
839 size_t prevTip = SIZE_MAX)
const {
841 auto currentTip = result.
fittedStates.addTrackState(stateMask, prevTip);
842 ACTS_VERBOSE(
"Creating Hole track state with tip = " << currentTip);
845 auto trackStateProxy = result.
fittedStates.getTrackState(currentTip);
848 auto& typeFlags = trackStateProxy.typeFlags();
853 auto [boundParams, jacobian, pathLength] =
boundState;
855 trackStateProxy.predicted() = boundParams.parameters();
856 trackStateProxy.predictedCovariance() = *boundParams.covariance();
857 trackStateProxy.jacobian() = jacobian;
858 trackStateProxy.pathLength() = pathLength;
860 trackStateProxy.setReferenceSurface(
861 boundParams.referenceSurface().getSharedPtr());
864 trackStateProxy.data().ifiltered = trackStateProxy.data().ipredicted;
883 size_t prevTip = SIZE_MAX)
const {
885 auto currentTip = result.
fittedStates.addTrackState(stateMask, prevTip);
887 "Creating track state on in-sensitive material surface with tip = "
891 auto trackStateProxy = result.
fittedStates.getTrackState(currentTip);
894 auto& typeFlags = trackStateProxy.typeFlags();
900 trackStateProxy.predicted() = curvilinearParams.parameters();
901 trackStateProxy.predictedCovariance() = *curvilinearParams.covariance();
902 trackStateProxy.jacobian() = jacobian;
903 trackStateProxy.pathLength() = pathLength;
905 trackStateProxy.setReferenceSurface(Surface::makeShared<PlaneSurface>(
906 curvilinearParams.position(), curvilinearParams.momentum()));
909 trackStateProxy.data().ifiltered = trackStateProxy.data().ipredicted;
924 template <
typename propagator_state_t,
typename stepper_t>
929 bool hasMaterial =
false;
947 <<
" at update stage: " << updateStage <<
" are :");
949 << interaction.
Eloss <<
", "
950 <<
"variancePhi = " << interaction.
variancePhi <<
", "
960 if (not hasMaterial) {
963 <<
" at update stage: "
976 template <
typename propagator_state_t,
typename stepper_t>
983 std::vector<size_t> measurementIndices;
986 result.
fittedStates.applyBackwards(currentTip, [&](
auto st) {
990 measurementIndices.emplace_back(st.index());
991 }
else if (measurementIndices.empty()) {
997 if (not measurementIndices.empty()) {
1003 if (measurementIndices.empty()) {
1004 ACTS_ERROR(
"Smoothing for a track without measurements.");
1005 return CombinatorialKalmanFilterError::SmoothFailed;
1009 <<
" filtered track states.");
1012 measurementIndices.front());
1013 if (!smoothRes.ok()) {
1014 ACTS_ERROR(
"Smoothing step failed: " << smoothRes.error());
1015 return smoothRes.error();
1018 auto firstMeasurement =
1019 result.
fittedStates.getTrackState(measurementIndices.back());
1020 parameters_t smoothedPars =
1021 firstMeasurement.smoothedParameters(state.options.geoContext);
1025 "Smoothing successful, updating stepping state, "
1026 "set target surface.");
1027 stepper.update(state.stepping, smoothedPars);
1029 state.stepping.stepSize =
1033 state.stepping.pathAccumulated = 0.;
1035 state.options.direction =
backward;
1066 template <
typename source_link_t,
typename parameters_t>
1072 template <
typename propagator_state_t,
typename stepper_t,
1075 const result_t& result)
const {
1076 if (!result.result.ok()) {
1104 template <
typename source_link_t,
typename start_parameters_t,
1105 typename comb_kalman_filter_options_t,
1108 const std::vector<source_link_t>& sourcelinks,
1109 const start_parameters_t& sParameters,
1110 const comb_kalman_filter_options_t& tfOptions)
const {
1111 static_assert(SourceLinkConcept<source_link_t>,
1112 "Source link does not fulfill SourceLinkConcept");
1116 source_link_selector_t,
1117 typename comb_kalman_filter_options_t::SourceLinkSelector>::
value,
1118 "Inconsistent type of source link selector between "
1119 "CombinatorialKalmanFilter and "
1120 " CombinatorialKalmanFilter options");
1124 ACTS_VERBOSE(
"Preparing " << sourcelinks.size() <<
" input measurements");
1125 std::unordered_map<const Surface*, std::vector<source_link_t>>
1127 for (
const auto& sl : sourcelinks) {
1128 const Surface* srf = &sl.referenceSurface();
1129 inputMeasurements[srf].emplace_back(sl);
1133 using CombinatorialKalmanFilterAborter =
1137 typename CombinatorialKalmanFilterActor::result_type;
1143 tfOptions.magFieldContext);
1148 auto& combKalmanActor =
1149 propOptions.
actionList.template get<CombinatorialKalmanFilterActor>();
1150 combKalmanActor.m_logger =
m_logger.get();
1151 combKalmanActor.inputMeasurements = std::move(inputMeasurements);
1152 combKalmanActor.targetSurface = tfOptions.referenceSurface;
1153 combKalmanActor.multipleScattering = tfOptions.multipleScattering;
1154 combKalmanActor.energyLoss = tfOptions.energyLoss;
1155 combKalmanActor.smoothing = tfOptions.smoothing;
1158 combKalmanActor.m_sourcelinkSelector.m_config =
1159 tfOptions.sourcelinkSelectorConfig;
1160 combKalmanActor.m_sourcelinkSelector.m_logger =
m_logger;
1163 combKalmanActor.m_updater.m_logger =
m_logger;
1164 combKalmanActor.m_smoother.m_logger =
m_logger;
1167 auto result =
m_propagator.template propagate(sParameters, propOptions);
1170 ACTS_ERROR(
"Propapation failed: " << result.error());
1171 return result.error();
1174 const auto& propRes = *result;
1177 auto combKalmanResult =
1178 propRes.template get<CombinatorialKalmanFilterResult>();
1182 if (combKalmanResult.result.ok() and not combKalmanResult.forwardFiltered) {
1184 CombinatorialKalmanFilterError::PropagationReachesMaxSteps);
1187 if (!combKalmanResult.result.ok()) {
1188 ACTS_ERROR(
"CombinatorialKalmanFilter failed: "
1189 << combKalmanResult.result.error());
1190 return combKalmanResult.result.error();