41 #include <unordered_map>
73 template <
typename source_link_selector_t>
99 std::reference_wrapper<const GeometryContext>
gctx,
100 std::reference_wrapper<const MagneticFieldContext> mctx,
101 std::reference_wrapper<const CalibrationContext> cctx,
104 bool mScattering =
true,
bool eLoss =
true,
bool rSmoothing =
true)
145 template <
typename source_link_t>
157 std::vector<std::pair<size_t, CombinatorialKalmanFilterTipState>>
activeTips;
160 std::unordered_map<const Surface*, std::unordered_map<size_t, size_t>>
220 template <
typename propagator_t,
typename updater_t = VoidKalmanUpdater,
221 typename smoother_t = VoidKalmanSmoother,
222 typename source_link_selector_t = CKFSourceLinkSelector,
223 typename branch_stopper_t = VoidBranchStopper,
224 typename calibrator_t = VoidMeasurementCalibrator>
250 template <
typename source_link_t,
typename parameters_t>
254 using BoundState = std::tuple<BoundTrackParameters, BoundMatrix, double>;
256 std::tuple<CurvilinearTrackParameters, BoundMatrix, double>;
264 std::unordered_map<const Surface*, std::vector<source_link_t>>
284 template <
typename propagator_state_t,
typename stepper_t>
287 const auto& logger = state.options.logger;
304 if (result.
reset and state.navigation.navSurfaceIter ==
305 state.navigation.navSurfaces.end()) {
307 state.navigation.navigationStage = KalmanNavigator::Stage::layerTarget;
309 result.
reset =
false;
314 auto surface = state.navigation.currentSurface;
332 ACTS_ERROR(
"Error in filter: " << res.error());
333 result.
result = res.error();
346 const auto& lastActiveTip = result.
activeTips.back().first;
348 const auto& iprevious =
349 result.
fittedStates.getTrackState(lastActiveTip).previous();
353 const auto& [currentTip, tipState] = result.
activeTips.back();
354 if (result.
fittedStates.getTrackState(currentTip).previous() !=
359 if (tipState.nMeasurements > 0) {
361 << currentTip <<
" and there are nMeasurements = "
362 << tipState.nMeasurements
363 <<
", nOutliers = " << tipState.nOutliers
364 <<
", nHoles = " << tipState.nHoles <<
" on track");
365 result.
trackTips.emplace_back(currentTip);
375 << result.
trackTips.size() <<
" tracks");
380 reset(state, stepper, result);
389 Result<void>(CombinatorialKalmanFilterError::NoTrackFound);
402 "Finalize/run smoothing for track with entry index = "
408 auto res =
finalize(state, stepper, result);
410 ACTS_ERROR(
"Error in finalize: " << res.error());
411 result.
result = res.error();
427 std::get<BoundTrackParameters>(fittedState));
433 state.navigation.targetReached =
false;
437 state.stepping.stepSize =
440 state.stepping.navDir =
forward;
443 "Finish forward Kalman filtering and backward smoothing");
461 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.resetState(state.stepping, currentState.filtered(),
484 currentState.filteredCovariance(),
485 currentState.referenceSurface(), state.stepping.navDir,
486 state.options.maxStepSize);
505 template <
typename propagator_state_t,
typename stepper_t>
508 const auto& logger = state.options.logger;
510 size_t nBranchesOnSurface = 0;
519 ACTS_VERBOSE(
"No source link on surface. Skipping filtering");
527 auto boundState = stepper.boundState(state.stepping, *surface);
528 auto boundParams = std::get<BoundTrackParameters>(
boundState);
534 auto& sourcelinks = sourcelink_it->second;
540 bool isOutlier =
false;
544 if (!sourcelinkSelectionRes.ok()) {
545 ACTS_ERROR(
"Selection of source links failed: "
546 << sourcelinkSelectionRes.error());
547 return sourcelinkSelectionRes.error();
552 size_t prevTip = SIZE_MAX;
556 prevTipState = result.
activeTips.back().second;
562 size_t neighborTip = SIZE_MAX;
567 bool isPredictedShared = (neighborTip != SIZE_MAX);
571 bool isSourcelinkShared =
false;
572 size_t sharedTip = SIZE_MAX;
575 auto& sourcelinkTipsOnSurface = sourcelinkTips_it->second;
576 auto index_it = sourcelinkTipsOnSurface.find(index);
577 if (index_it != sourcelinkTipsOnSurface.end()) {
578 isSourcelinkShared =
true;
579 sharedTip = index_it->second;
590 : TrackStatePropMask::All) &
591 (isSourcelinkShared ? ~TrackStatePropMask::Uncalibrated
592 : TrackStatePropMask::All) &
594 : TrackStatePropMask::All);
599 isOutlier, result, state.geoContext, prevTip,
600 prevTipState, neighborTip, sharedTip, logger);
601 if (addStateRes.ok()) {
602 const auto& [currentTip, tipState] = addStateRes.value();
604 if (not isSourcelinkShared) {
605 auto& sourcelinkTipsOnSurface = result.sourcelinkTips[
surface];
606 sourcelinkTipsOnSurface.emplace(index, currentTip);
609 neighborTip = currentTip;
614 result.activeTips.emplace_back(std::move(currentTip),
615 std::move(tipState));
617 nBranchesOnSurface++;
622 if (nBranchesOnSurface > 0 and not isOutlier) {
624 ACTS_VERBOSE(
"Filtering step successful with " << nBranchesOnSurface
630 stepper.update(state.stepping,
632 state.options.geoContext, ts),
633 ts.filteredCovariance());
634 ACTS_VERBOSE(
"Stepping state is updated with filtered parameter: \n"
635 << ts.filtered().transpose()
636 <<
" of track state with tip = "
644 nBranchesOnSurface = 1;
647 size_t prevTip = SIZE_MAX;
656 std::string type = isSensitive ?
"sensitive" :
"passive";
667 (isSensitive or (not isSensitive and
smoothing))) {
675 ~(TrackStatePropMask::Uncalibrated |
676 TrackStatePropMask::Calibrated | TrackStatePropMask::Filtered);
680 size_t currentTip = SIZE_MAX;
683 auto boundState = stepper.boundState(state.stepping, *surface);
700 result.
activeTips.emplace_back(std::move(currentTip),
701 std::move(tipState));
704 nBranchesOnSurface = 0;
712 nBranchesOnSurface = 1;
716 if (nBranchesOnSurface == 0) {
722 reset(state, stepper, result);
725 << result.
trackTips.size() <<
" found tracks");
750 const source_link_t& sourcelink,
bool isOutlier,
result_type& result,
751 std::reference_wrapper<const GeometryContext>
geoContext,
752 const size_t& prevTip,
const TipState& prevTipState,
753 size_t neighborTip = SIZE_MAX,
size_t sharedTip = SIZE_MAX,
759 auto currentTip = result.
fittedStates.addTrackState(stateMask, prevTip);
762 auto trackStateProxy = result.
fittedStates.getTrackState(currentTip);
767 if ((not
ACTS_CHECK_BIT(stateMask, TrackStatePropMask::Predicted)) and
768 neighborTip != SIZE_MAX) {
770 auto neighborState = result.
fittedStates.getTrackState(neighborTip);
771 trackStateProxy.data().ipredicted = neighborState.data().ipredicted;
773 trackStateProxy.predicted() = boundParams.parameters();
774 trackStateProxy.predictedCovariance() = *boundParams.covariance();
776 trackStateProxy.jacobian() = jacobian;
781 if ((not
ACTS_CHECK_BIT(stateMask, TrackStatePropMask::Uncalibrated)) and
782 sharedTip != SIZE_MAX) {
785 auto shared = result.
fittedStates.getTrackState(sharedTip);
786 trackStateProxy.data().iuncalibrated = shared.data().iuncalibrated;
788 trackStateProxy.uncalibrated() = sourcelink;
791 [&](
const auto& calibrated) {
792 trackStateProxy.setCalibrated(calibrated);
795 trackStateProxy.predicted()));
798 auto& typeFlags = trackStateProxy.typeFlags();
807 ACTS_VERBOSE(
"Creating outlier track state with tip = " << currentTip);
815 trackStateProxy.data().ifiltered = trackStateProxy.data().ipredicted;
818 auto updateRes =
m_updater(geoContext, trackStateProxy);
819 if (!updateRes.ok()) {
820 ACTS_ERROR(
"Update step failed: " << updateRes.error());
821 return updateRes.error();
824 "Creating measurement track state with tip = " << currentTip);
830 return std::make_pair(std::move(currentTip), std::move(tipState));
844 size_t prevTip = SIZE_MAX,
847 auto currentTip = result.
fittedStates.addTrackState(stateMask, prevTip);
848 ACTS_VERBOSE(
"Creating Hole track state with tip = " << currentTip);
851 auto trackStateProxy = result.
fittedStates.getTrackState(currentTip);
854 auto& typeFlags = trackStateProxy.typeFlags();
861 trackStateProxy.predicted() = boundParams.parameters();
862 trackStateProxy.predictedCovariance() = *boundParams.covariance();
863 trackStateProxy.jacobian() = jacobian;
866 trackStateProxy.setReferenceSurface(
867 boundParams.referenceSurface().getSharedPtr());
870 trackStateProxy.data().ifiltered = trackStateProxy.data().ipredicted;
891 auto currentTip = result.
fittedStates.addTrackState(stateMask, prevTip);
893 "Creating track state on in-sensitive material surface with tip = "
897 auto trackStateProxy = result.
fittedStates.getTrackState(currentTip);
900 auto& typeFlags = trackStateProxy.typeFlags();
906 trackStateProxy.predicted() = curvilinearParams.parameters();
907 trackStateProxy.predictedCovariance() = *curvilinearParams.covariance();
908 trackStateProxy.jacobian() = jacobian;
911 trackStateProxy.setReferenceSurface(
912 curvilinearParams.referenceSurface().getSharedPtr());
915 trackStateProxy.data().ifiltered = trackStateProxy.data().ipredicted;
930 template <
typename propagator_state_t,
typename stepper_t>
934 const auto& logger = state.options.logger;
936 bool hasMaterial =
false;
954 <<
" at update stage: " << updateStage <<
" are :");
956 << interaction.
Eloss <<
", "
957 <<
"variancePhi = " << interaction.
variancePhi <<
", "
967 if (not hasMaterial) {
970 <<
" at update stage: "
983 template <
typename propagator_state_t,
typename stepper_t>
986 const auto& logger = state.options.logger;
991 std::vector<size_t> measurementIndices;
994 result.
fittedStates.applyBackwards(currentTip, [&](
auto st) {
998 measurementIndices.emplace_back(st.index());
999 }
else if (measurementIndices.empty()) {
1005 if (not measurementIndices.empty()) {
1011 if (measurementIndices.empty()) {
1012 ACTS_ERROR(
"Smoothing for a track without measurements.");
1013 return CombinatorialKalmanFilterError::SmoothFailed;
1017 <<
" filtered track states.");
1020 measurementIndices.front());
1021 if (!smoothRes.ok()) {
1022 ACTS_ERROR(
"Smoothing step failed: " << smoothRes.error());
1023 return smoothRes.error();
1026 auto firstMeasurement =
1027 result.
fittedStates.getTrackState(measurementIndices.back());
1031 "Smoothing successful, updating stepping state, "
1032 "set target surface.");
1033 stepper.update(state.stepping,
1035 state.options.geoContext, firstMeasurement),
1036 firstMeasurement.smoothedCovariance());
1038 state.stepping.stepSize =
1042 state.stepping.pathAccumulated = 0.;
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() or result.finished) {
1101 template <
typename source_link_container_t,
typename start_parameters_t,
1106 const start_parameters_t& sParameters,
1109 const auto& logger = tfOptions.
logger;
1111 static_assert(SourceLinkConcept<SourceLink>,
1112 "Source link does not fulfill SourceLinkConcept");
1116 ACTS_VERBOSE(
"Preparing " << sourcelinks.size() <<
" input measurements");
1117 std::unordered_map<const Surface*, std::vector<SourceLink>>
1119 for (
const auto& sl : sourcelinks) {
1120 const Surface* srf = &sl.referenceSurface();
1122 inputMeasurements[srf].emplace_back(sl);
1129 typename CombinatorialKalmanFilterActor::result_type;
1141 auto& combKalmanActor =
1142 propOptions.
actionList.template get<CombinatorialKalmanFilterActor>();
1143 combKalmanActor.inputMeasurements = std::move(inputMeasurements);
1146 combKalmanActor.energyLoss = tfOptions.
energyLoss;
1147 combKalmanActor.smoothing = tfOptions.
smoothing;
1150 combKalmanActor.m_sourcelinkSelector.m_config =
1154 auto result =
m_propagator.template propagate(sParameters, propOptions);
1157 ACTS_ERROR(
"Propapation failed: " << result.error());
1158 return result.error();
1161 const auto& propRes = *result;
1164 auto combKalmanResult =
1165 propRes.template get<CombinatorialKalmanFilterResult>();
1172 if (combKalmanResult.result.ok() and not combKalmanResult.finished) {
1174 CombinatorialKalmanFilterError::PropagationReachesMaxSteps);
1177 if (!combKalmanResult.result.ok()) {
1178 ACTS_ERROR(
"CombinatorialKalmanFilter failed: "
1179 << combKalmanResult.result.error());
1180 return combKalmanResult.result.error();
1184 return combKalmanResult;