Skip to content

Commit

Permalink
feat!: Kf reverse filtering option (#1021)
Browse files Browse the repository at this point in the history
This PR allow add an extra template parameter to the Kalman Fitter Options. This will allow us to specify a function to determine if a given track should be smoothed using reverse filtering or not. This also had some relevant unit test.

While testing the KF with ATLAS I noticed the KF smoothing performed poorly at low pT (<1GeV), especially concerny the Z0 resolution. In that case switching to the reverse filtering solved the issue. Eith this PR we will be able to switch between notmal smoothing and reverse filtering on a per track basis depending on the filtered parameters.
  • Loading branch information
Corentin-Allaire committed Oct 5, 2021
1 parent bcb3eed commit 849e792
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 66 deletions.
81 changes: 52 additions & 29 deletions Core/include/Acts/TrackFitting/KalmanFitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,14 @@ namespace Acts {
/// Combined options for the Kalman fitter.
///
/// @tparam calibrator_t Source link type, should be semiregular.
/// @tparam outlier_finder_t Outlier finder type, shoule be semiregular.
template <typename calibrator_t, typename outlier_finder_t>
/// @tparam outlier_finder_t Outlier finder type, should be semiregular.
/// @tparam reverse_filtering_logic_t type deciding whether to run filtering in reversed direction as smoothing, should be semiregular.
template <typename calibrator_t, typename outlier_finder_t,
typename reverse_filtering_logic_t>
struct KalmanFitterOptions {
using Calibrator = calibrator_t;
using OutlierFinder = outlier_finder_t;
using ReverseFilteringLogic = reverse_filtering_logic_t;

/// PropagatorOptions with context.
///
Expand All @@ -56,27 +59,27 @@ struct KalmanFitterOptions {
/// @param cctx The calibration context for this fit
/// @param calibrator_ The source link calibrator
/// @param outlierFinder_ The outlier finder
/// @param reverseFilteringLogic_ The smoothing logic
/// @param logger_ The logger wrapper
/// @param pOptions The plain propagator options
/// @param rSurface The reference surface for the fit to be expressed at
/// @param mScattering Whether to include multiple scattering
/// @param eLoss Whether to include energy loss
/// @param rFiltering Whether to run filtering in reversed direction as
/// smoothing
KalmanFitterOptions(const GeometryContext& gctx,
const MagneticFieldContext& mctx,
std::reference_wrapper<const CalibrationContext> cctx,
Calibrator calibrator_, OutlierFinder outlierFinder_,
LoggerWrapper logger_,
const PropagatorPlainOptions& pOptions,
const Surface* rSurface = nullptr,
bool mScattering = true, bool eLoss = true,
bool rFiltering = false)
KalmanFitterOptions(
const GeometryContext& gctx, const MagneticFieldContext& mctx,
std::reference_wrapper<const CalibrationContext> cctx,
Calibrator calibrator_, OutlierFinder outlierFinder_,
ReverseFilteringLogic reverseFilteringLogic_, LoggerWrapper logger_,
const PropagatorPlainOptions& pOptions, const Surface* rSurface = nullptr,
bool mScattering = true, bool eLoss = true, bool rFiltering = false)
: geoContext(gctx),
magFieldContext(mctx),
calibrationContext(cctx),
calibrator(std::move(calibrator_)),
outlierFinder(std::move(outlierFinder_)),
reverseFilteringLogic(std::move(reverseFilteringLogic_)),
propagatorPlainOptions(pOptions),
referenceSurface(rSurface),
multipleScattering(mScattering),
Expand All @@ -99,6 +102,9 @@ struct KalmanFitterOptions {
/// The outlier finder.
OutlierFinder outlierFinder;

/// The smoothing logic.
ReverseFilteringLogic reverseFilteringLogic;

/// The trivial propagator options
PropagatorPlainOptions propagatorPlainOptions;

Expand All @@ -111,7 +117,8 @@ struct KalmanFitterOptions {
/// Whether to consider energy loss
bool energyLoss = true;

/// Whether to run filtering in reversed direction
/// Whether to run filtering in reversed direction overwrite the
/// ReverseFilteringLogic
bool reversedFiltering = false;

/// Logger
Expand Down Expand Up @@ -218,7 +225,8 @@ class KalmanFitter {
/// The KalmanActor does not rely on the measurements to be
/// sorted along the track.
template <typename source_link_t, typename parameters_t,
typename calibrator_t, typename outlier_finder_t>
typename calibrator_t, typename outlier_finder_t,
typename reverse_filtering_logic_t>
class Actor {
public:
/// Broadcast the result_type
Expand Down Expand Up @@ -313,7 +321,10 @@ class KalmanFitter {
state.navigation.navigationBreak)) {
// Remove the missing surfaces that occur after the last measurement
result.missedActiveSurfaces.resize(result.measurementHoles);
if (reversedFiltering) {
// now get track state proxy for the smoothing logic
auto trackStateProxy =
result.fittedStates.getTrackState(result.lastMeasurementIndex);
if (reversedFiltering || m_reverseFilteringLogic(trackStateProxy)) {
// Start to run reversed filtering:
// Reverse navigation direction and reset navigation and stepping
// state to last measurement
Expand Down Expand Up @@ -346,7 +357,7 @@ class KalmanFitter {
// If no target surface provided:
// -> Return an error when using reversed filtering mode
// -> Fitting is finished here
if (reversedFiltering) {
if (result.reversed) {
ACTS_ERROR(
"The target surface needed for aborting reversed propagation "
"is not provided");
Expand All @@ -373,7 +384,7 @@ class KalmanFitter {
result.fittedParameters = std::get<BoundTrackParameters>(fittedState);

// Reset smoothed status of states missed in reversed filtering
if (reversedFiltering) {
if (result.reversed) {
result.fittedStates.applyBackwards(
result.lastMeasurementIndex, [&](auto trackState) {
auto fSurface = &trackState.referenceSurface();
Expand Down Expand Up @@ -981,17 +992,21 @@ class KalmanFitter {
/// The outlier finder
outlier_finder_t m_outlierFinder;

/// The smoothing logic
reverse_filtering_logic_t m_reverseFilteringLogic;

/// The Surface beeing
SurfaceReached targetReached;
};

template <typename source_link_t, typename parameters_t,
typename calibrator_t, typename outlier_finder_t>
typename calibrator_t, typename outlier_finder_t,
typename reverse_filtering_logic_t>
class Aborter {
public:
/// Broadcast the result_type
using action_type =
Actor<source_link_t, parameters_t, calibrator_t, outlier_finder_t>;
using action_type = Actor<source_link_t, parameters_t, calibrator_t,
outlier_finder_t, reverse_filtering_logic_t>;

template <typename propagator_state_t, typename stepper_t,
typename result_t>
Expand All @@ -1012,6 +1027,7 @@ class KalmanFitter {
/// @tparam start_parameters_t Type of the initial parameters
/// @tparam calibrator_t Type of the source link calibrator
/// @tparam outlier_finder_t Type of the outlier finder
/// @tparam reverse_filtering_logic_t Type of the smoothing logic
/// @tparam parameters_t Type of parameters used for local parameters
///
/// @param sourcelinks The fittable uncalibrated measurements
Expand All @@ -1025,10 +1041,12 @@ class KalmanFitter {
/// @return the output as an output track
template <typename source_link_t, typename start_parameters_t,
typename calibrator_t, typename outlier_finder_t,
typename reverse_filtering_logic_t,
typename parameters_t = BoundTrackParameters>
auto fit(const std::vector<source_link_t>& sourcelinks,
const start_parameters_t& sParameters,
const KalmanFitterOptions<calibrator_t, outlier_finder_t>& kfOptions)
const KalmanFitterOptions<calibrator_t, outlier_finder_t,
reverse_filtering_logic_t>& kfOptions)
const -> std::enable_if_t<!isDirectNavigator,
Result<KalmanFitterResult<source_link_t>>> {
const auto& logger = kfOptions.logger;
Expand All @@ -1045,10 +1063,10 @@ class KalmanFitter {
}

// Create the ActionList and AbortList
using KalmanAborter =
Aborter<source_link_t, parameters_t, calibrator_t, outlier_finder_t>;
using KalmanActor =
Actor<source_link_t, parameters_t, calibrator_t, outlier_finder_t>;
using KalmanAborter = Aborter<source_link_t, parameters_t, calibrator_t,
outlier_finder_t, reverse_filtering_logic_t>;
using KalmanActor = Actor<source_link_t, parameters_t, calibrator_t,
outlier_finder_t, reverse_filtering_logic_t>;
using KalmanResult = typename KalmanActor::result_type;
using Actors = ActionList<KalmanActor>;
using Aborters = AbortList<KalmanAborter>;
Expand All @@ -1069,6 +1087,7 @@ class KalmanFitter {
kalmanActor.reversedFiltering = kfOptions.reversedFiltering;
kalmanActor.m_calibrator = kfOptions.calibrator;
kalmanActor.m_outlierFinder = kfOptions.outlierFinder;
kalmanActor.m_reverseFilteringLogic = kfOptions.reverseFilteringLogic;

// Run the fitter
auto result = m_propagator.template propagate(sParameters, kalmanOptions);
Expand Down Expand Up @@ -1107,6 +1126,7 @@ class KalmanFitter {
/// @tparam start_parameters_t Type of the initial parameters
/// @tparam calibrator_t Type of the source link calibrator
/// @tparam outlier_finder_t Type of the outlier finder
/// @tparam reverse_filtering_logic_t Type of the smoothing logic
/// @tparam parameters_t Type of parameters used for local parameters
///
/// @param sourcelinks The fittable uncalibrated measurements
Expand All @@ -1121,10 +1141,12 @@ class KalmanFitter {
/// @return the output as an output track
template <typename source_link_t, typename start_parameters_t,
typename calibrator_t, typename outlier_finder_t,
typename reverse_filtering_logic_t,
typename parameters_t = BoundTrackParameters>
auto fit(const std::vector<source_link_t>& sourcelinks,
const start_parameters_t& sParameters,
const KalmanFitterOptions<calibrator_t, outlier_finder_t>& kfOptions,
const KalmanFitterOptions<calibrator_t, outlier_finder_t,
reverse_filtering_logic_t>& kfOptions,
const std::vector<const Surface*>& sSequence) const
-> std::enable_if_t<isDirectNavigator,
Result<KalmanFitterResult<source_link_t>>> {
Expand All @@ -1141,10 +1163,10 @@ class KalmanFitter {
}

// Create the ActionList and AbortList
using KalmanAborter =
Aborter<source_link_t, parameters_t, calibrator_t, outlier_finder_t>;
using KalmanActor =
Actor<source_link_t, parameters_t, calibrator_t, outlier_finder_t>;
using KalmanAborter = Aborter<source_link_t, parameters_t, calibrator_t,
outlier_finder_t, reverse_filtering_logic_t>;
using KalmanActor = Actor<source_link_t, parameters_t, calibrator_t,
outlier_finder_t, reverse_filtering_logic_t>;
using KalmanResult = typename KalmanActor::result_type;
using Actors = ActionList<DirectNavigator::Initializer, KalmanActor>;
using Aborters = AbortList<KalmanAborter>;
Expand All @@ -1166,6 +1188,7 @@ class KalmanFitter {
kalmanActor.m_calibrator = kfOptions.calibrator;
// Set config for outlier finder
kalmanActor.m_outlierFinder = kfOptions.outlierFinder;
kalmanActor.m_reverseFilteringLogic = kfOptions.reverseFilteringLogic;

// Set the surface sequence
auto& dInitializer =
Expand Down
16 changes: 16 additions & 0 deletions Core/include/Acts/TrackFitting/detail/VoidKalmanComponents.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,20 @@ struct VoidOutlierFinder {
}
};

/// @brief void smoothing logic
struct VoidReverseFilteringLogic {
/// @brief Public call mimicking an outlier finder
///
/// @tparam track_state_t Type of the track state
///
/// @param trackState The trackState of the last measurement
///
/// @return Whether to run filtering in reversed direction as smoothing or not
template <typename track_state_t>
constexpr bool operator()(const track_state_t& trackState) const {
(void)trackState;
return false;
}
};

} // namespace Acts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class AlignmentAlgorithm final : public BareAlgorithm {
/// trackstate and alignment options and returns some alignment-specific
/// result.
using TrackFitterOptions =
Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder>;
Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder,
Acts::VoidReverseFilteringLogic>;

/// Alignment function that takes the above parameters and runs alignment
/// @note This is separated into a virtual interface to keep compilation units
Expand Down
4 changes: 2 additions & 2 deletions Examples/Algorithms/Alignment/src/AlignmentAlgorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ ActsExamples::ProcessCode ActsExamples::AlignmentAlgorithm::execute(
TrackFitterOptions kfOptions(
ctx.geoContext, ctx.magFieldContext, ctx.calibContext,
MeasurementCalibrator(measurements), Acts::VoidOutlierFinder(),
Acts::LoggerWrapper{logger()}, Acts::PropagatorPlainOptions(),
&(*pSurface));
Acts::VoidReverseFilteringLogic(), Acts::LoggerWrapper{logger()},
Acts::PropagatorPlainOptions(), &(*pSurface));

// Set the alignment options
ActsAlignment::AlignmentOptions<TrackFitterOptions> alignOptions(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class TrackFittingAlgorithm final : public BareAlgorithm {
/// Track fitter function that takes input measurements, initial trackstate
/// and fitter options and returns some track-fitter-specific result.
using TrackFitterOptions =
Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder>;
Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder,
Acts::VoidReverseFilteringLogic>;
using TrackFitterResult =
Acts::Result<Acts::KalmanFitterResult<IndexSourceLink>>;

Expand Down Expand Up @@ -128,7 +129,8 @@ ActsExamples::TrackFittingAlgorithm::fitTrack(
const std::vector<ActsExamples::IndexSourceLink>& sourceLinks,
const ActsExamples::TrackParameters& initialParameters,
const Acts::KalmanFitterOptions<MeasurementCalibrator,
Acts::VoidOutlierFinder>& options,
Acts::VoidOutlierFinder,
Acts::VoidReverseFilteringLogic>& options,
const std::vector<const Acts::Surface*>& surfSequence) const {
if (m_cfg.directNavigation) {
return (*m_cfg.dFit)(sourceLinks, initialParameters, options, surfSequence);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,11 @@ ActsExamples::ProcessCode ActsExamples::TrackFittingAlgorithm::execute(
Acts::Vector3{0., 0., 0.});

// Set the KalmanFitter options
Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder>
Acts::KalmanFitterOptions<MeasurementCalibrator, Acts::VoidOutlierFinder,
Acts::VoidReverseFilteringLogic>
kfOptions(ctx.geoContext, ctx.magFieldContext, ctx.calibContext,
MeasurementCalibrator(measurements), Acts::VoidOutlierFinder(),
Acts::VoidReverseFilteringLogic(),
Acts::LoggerWrapper{logger()}, Acts::PropagatorPlainOptions(),
&(*pSurface));

Expand Down
11 changes: 7 additions & 4 deletions Tests/UnitTests/Alignment/Kernel/AlignmentTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,11 @@ BOOST_AUTO_TEST_CASE(ZeroFieldKalmanAlignment) {
const auto& trajectories = createTrajectories(geometry, 10);

// Construct the KalmanFitter options
KalmanFitterOptions<TestSourceLinkCalibrator, VoidOutlierFinder> kfOptions(
geoCtx, magCtx, calCtx, TestSourceLinkCalibrator(), VoidOutlierFinder(),
LoggerWrapper{*kfLogger}, PropagatorPlainOptions());
KalmanFitterOptions<TestSourceLinkCalibrator, VoidOutlierFinder,
Acts::VoidReverseFilteringLogic>
kfOptions(geoCtx, magCtx, calCtx, TestSourceLinkCalibrator(),
VoidOutlierFinder(), Acts::VoidReverseFilteringLogic(),
LoggerWrapper{*kfLogger}, PropagatorPlainOptions());

// Construct an non-updating alignment updater
AlignedTransformUpdater voidAlignUpdater =
Expand All @@ -287,7 +289,8 @@ BOOST_AUTO_TEST_CASE(ZeroFieldKalmanAlignment) {

// Construct the alignment options
AlignmentOptions<
KalmanFitterOptions<TestSourceLinkCalibrator, VoidOutlierFinder>>
KalmanFitterOptions<TestSourceLinkCalibrator, VoidOutlierFinder,
Acts::VoidReverseFilteringLogic>>
alignOptions(kfOptions, voidAlignUpdater, LoggerWrapper{*alignLogger});
alignOptions.maxIterations = 1;

Expand Down

0 comments on commit 849e792

Please sign in to comment.