File indexing completed on 2026-09-20 08:23:07
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/Definitions/Units.hpp"
0014 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0015 #include "Acts/EventData/detail/TestSourceLink.hpp"
0016 #include "Acts/Propagator/EigenStepper.hpp"
0017 #include "Acts/Propagator/Navigator.hpp"
0018 #include "Acts/Propagator/Propagator.hpp"
0019 #include "Acts/Propagator/StraightLineStepper.hpp"
0020 #include "Acts/TrackFitting/GainMatrixSmoother.hpp"
0021 #include "Acts/TrackFitting/GainMatrixUpdater.hpp"
0022 #include "Acts/TrackFitting/KalmanFitter.hpp"
0023 #include "Acts/Utilities/Logger.hpp"
0024
0025 #include <functional>
0026 #include <memory>
0027 #include <optional>
0028 #include <random>
0029 #include <utility>
0030
0031 #include "FitterTestsCommon.hpp"
0032
0033 using namespace Acts;
0034 using namespace Acts::detail::Test;
0035 using namespace Acts::UnitLiterals;
0036
0037 namespace ActsTests {
0038
0039 using StraightPropagator =
0040 Acts::Propagator<Acts::StraightLineStepper, Acts::Navigator>;
0041 using ConstantFieldStepper = Acts::EigenStepper<>;
0042 using ConstantFieldPropagator =
0043 Acts::Propagator<ConstantFieldStepper, Acts::Navigator>;
0044
0045 using KalmanUpdater = Acts::GainMatrixUpdater;
0046 using KalmanSmoother = Acts::GainMatrixSmoother;
0047 using KalmanFitter =
0048 Acts::KalmanFitter<ConstantFieldPropagator, VectorMultiTrajectory>;
0049
0050 static const auto pion = Acts::ParticleHypothesis::pion();
0051
0052 KalmanUpdater kfUpdater;
0053 KalmanSmoother kfSmoother;
0054
0055
0056 Acts::BoundTrackParameters makeParameters() {
0057
0058 Acts::BoundVector stddev;
0059 stddev[Acts::eBoundLoc0] = 100_um;
0060 stddev[Acts::eBoundLoc1] = 100_um;
0061 stddev[Acts::eBoundTime] = 25_ns;
0062 stddev[Acts::eBoundPhi] = 2_degree;
0063 stddev[Acts::eBoundTheta] = 2_degree;
0064 stddev[Acts::eBoundQOverP] = 1 / 100_GeV;
0065 Acts::BoundMatrix cov = stddev.cwiseProduct(stddev).asDiagonal();
0066
0067 Acts::Vector4 mPos4(-3_m, 0., 0., 42_ns);
0068 return Acts::BoundTrackParameters::createCurvilinear(
0069 mPos4, 0_degree, 90_degree, 1_e / 1_GeV, cov, pion);
0070 }
0071
0072
0073 const FitterTester tester;
0074
0075
0076 auto kfLogger = getDefaultLogger("KalmanFilter", Logging::INFO);
0077 const auto kfZeroPropagator =
0078 makeConstantFieldPropagator<ConstantFieldStepper>(tester.geometry, 0_T);
0079 const auto kfZero = KalmanFitter(kfZeroPropagator, std::move(kfLogger));
0080
0081 std::default_random_engine rng(42);
0082
0083 auto makeDefaultKalmanFitterOptions() {
0084 KalmanFitterExtensions<VectorMultiTrajectory> extensions;
0085 extensions.calibrator
0086 .connect<&testSourceLinkCalibratorStrict<VectorMultiTrajectory>>();
0087 extensions.updater.connect<&KalmanUpdater::operator()<VectorMultiTrajectory>>(
0088 &kfUpdater);
0089 extensions.smoother
0090 .connect<&KalmanSmoother::operator()<VectorMultiTrajectory>>(&kfSmoother);
0091 extensions.surfaceAccessor.connect<
0092 &Acts::detail::Test::TestSourceLink::SurfaceAccessor::operator()>(
0093 &tester.surfaceAccessor);
0094
0095 return KalmanFitterOptions(
0096 tester.geoCtx, tester.magCtx, tester.calCtx, extensions,
0097 PropagatorPlainOptions(tester.geoCtx, tester.magCtx));
0098 }
0099
0100
0101
0102
0103 struct CalibratorContractChecker {
0104 mutable std::size_t nCalls = 0;
0105
0106 template <typename trajectory_t>
0107 void operator()(const GeometryContext& gctx, const CalibrationContext& cctx,
0108 const SourceLink& sourceLink,
0109 typename trajectory_t::TrackStateProxy trackState) const {
0110
0111
0112 BOOST_CHECK(!trackState.hasFiltered());
0113 BOOST_CHECK(!trackState.hasSmoothed());
0114
0115
0116 BOOST_REQUIRE(trackState.hasPredicted());
0117 BOOST_CHECK_EQUAL(trackState.parameters().data(),
0118 trackState.predicted().data());
0119 BOOST_CHECK_EQUAL(trackState.covariance().data(),
0120 trackState.predictedCovariance().data());
0121 BOOST_CHECK(trackState.parameters().allFinite());
0122 BOOST_CHECK(trackState.covariance().allFinite());
0123
0124 ++nCalls;
0125
0126 testSourceLinkCalibrator<trajectory_t>(gctx, cctx, sourceLink, trackState);
0127 }
0128 };
0129
0130 BOOST_AUTO_TEST_SUITE(TrackFittingSuite)
0131
0132
0133
0134
0135 BOOST_AUTO_TEST_CASE(CalibratorSeesValidParameters) {
0136 auto start = makeParameters();
0137 auto kfOptions = makeDefaultKalmanFitterOptions();
0138
0139 CalibratorContractChecker checker;
0140 kfOptions.extensions.calibrator
0141 .connect<&CalibratorContractChecker::operator()<VectorMultiTrajectory>>(
0142 &checker);
0143
0144 bool expected_reversed = false;
0145 bool expected_smoothed = true;
0146 tester.test_ZeroFieldNoSurfaceForward(kfZero, kfOptions, start, rng,
0147 expected_reversed, expected_smoothed,
0148 true);
0149
0150 BOOST_CHECK_GT(checker.nCalls, 0u);
0151 }
0152
0153 BOOST_AUTO_TEST_CASE(ZeroFieldNoSurfaceForward) {
0154 auto start = makeParameters();
0155 auto kfOptions = makeDefaultKalmanFitterOptions();
0156
0157 bool expected_reversed = false;
0158 bool expected_smoothed = true;
0159 tester.test_ZeroFieldNoSurfaceForward(kfZero, kfOptions, start, rng,
0160 expected_reversed, expected_smoothed,
0161 true);
0162 }
0163
0164 BOOST_AUTO_TEST_CASE(ZeroFieldWithSurfaceForward) {
0165 auto start = makeParameters();
0166 auto kfOptions = makeDefaultKalmanFitterOptions();
0167
0168
0169 kfOptions.reverseFiltering = false;
0170 bool expected_reversed = false;
0171 bool expected_smoothed = true;
0172 tester.test_ZeroFieldWithSurfaceForward(kfZero, kfOptions, start, rng,
0173 expected_reversed, expected_smoothed,
0174 true);
0175
0176
0177 kfOptions.reverseFiltering = true;
0178 kfOptions.reverseFilteringCovarianceScaling = 100.0;
0179 expected_reversed = true;
0180 expected_smoothed = false;
0181 tester.test_ZeroFieldWithSurfaceForward(kfZero, kfOptions, start, rng,
0182 expected_reversed, expected_smoothed,
0183 true);
0184 }
0185
0186 BOOST_AUTO_TEST_CASE(ZeroFieldWithSurfaceBackward) {
0187 auto start = makeParameters();
0188 auto kfOptions = makeDefaultKalmanFitterOptions();
0189
0190
0191 kfOptions.reverseFiltering = false;
0192 bool expected_reversed = false;
0193 bool expected_smoothed = true;
0194 tester.test_ZeroFieldWithSurfaceBackward(kfZero, kfOptions, start, rng,
0195 expected_reversed, expected_smoothed,
0196 true);
0197
0198
0199 kfOptions.reverseFiltering = true;
0200 kfOptions.reverseFilteringCovarianceScaling = 100.0;
0201 expected_reversed = true;
0202 expected_smoothed = false;
0203 tester.test_ZeroFieldWithSurfaceBackward(kfZero, kfOptions, start, rng,
0204 expected_reversed, expected_smoothed,
0205 true);
0206 }
0207
0208 BOOST_AUTO_TEST_CASE(ZeroFieldWithSurfaceAtExit) {
0209 auto start = makeParameters();
0210 auto kfOptions = makeDefaultKalmanFitterOptions();
0211
0212 bool expected_reversed = false;
0213 bool expected_smoothed = true;
0214 tester.test_ZeroFieldWithSurfaceAtExit(kfZero, kfOptions, start, rng,
0215 expected_reversed, expected_smoothed,
0216 true);
0217 }
0218
0219 BOOST_AUTO_TEST_CASE(ZeroFieldShuffled) {
0220 auto start = makeParameters();
0221 auto kfOptions = makeDefaultKalmanFitterOptions();
0222
0223 bool expected_reversed = false;
0224 bool expected_smoothed = true;
0225 tester.test_ZeroFieldShuffled(kfZero, kfOptions, start, rng,
0226 expected_reversed, expected_smoothed, true);
0227 }
0228
0229 BOOST_AUTO_TEST_CASE(ZeroFieldWithHole) {
0230 auto start = makeParameters();
0231 auto kfOptions = makeDefaultKalmanFitterOptions();
0232
0233 bool expected_reversed = false;
0234 bool expected_smoothed = true;
0235 tester.test_ZeroFieldWithHole(kfZero, kfOptions, start, rng,
0236 expected_reversed, expected_smoothed, true);
0237 }
0238
0239 BOOST_AUTO_TEST_CASE(ZeroFieldWithOutliers) {
0240 auto start = makeParameters();
0241
0242
0243
0244 auto kfOptions = makeDefaultKalmanFitterOptions();
0245
0246 TestOutlierFinder tof{5_mm};
0247 kfOptions.extensions.outlierFinder
0248 .connect<&TestOutlierFinder::operator()<VectorMultiTrajectory>>(&tof);
0249
0250 bool expected_reversed = false;
0251 bool expected_smoothed = true;
0252 tester.test_ZeroFieldWithOutliers(kfZero, kfOptions, start, rng,
0253 expected_reversed, expected_smoothed, true);
0254 }
0255
0256 BOOST_AUTO_TEST_CASE(ZeroFieldWithReverseFiltering) {
0257 auto start = makeParameters();
0258
0259 auto test = [&](double threshold, bool reverse, bool expected_reversed,
0260 bool expected_smoothed) {
0261 auto kfOptions = makeDefaultKalmanFitterOptions();
0262
0263 TestReverseFilteringLogic trfl{threshold};
0264 kfOptions.extensions.reverseFilteringLogic
0265 .connect<&TestReverseFilteringLogic::operator()<VectorMultiTrajectory>>(
0266 &trfl);
0267
0268 kfOptions.reverseFiltering = reverse;
0269 kfOptions.reverseFilteringCovarianceScaling = 100.0;
0270
0271 tester.test_ZeroFieldWithReverseFiltering(kfZero, kfOptions, start, rng,
0272 expected_reversed,
0273 expected_smoothed, true);
0274 };
0275
0276
0277
0278 test(0.1_GeV, false, false, true);
0279
0280
0281
0282 test(10._GeV, false, true, false);
0283
0284
0285
0286 test(0.1_GeV, true, true, false);
0287 }
0288
0289
0290
0291 BOOST_AUTO_TEST_CASE(GlobalCovariance) {
0292 auto start = makeParameters();
0293 auto kfOptions = makeDefaultKalmanFitterOptions();
0294
0295 tester.test_GlobalCovariance(kfZero, kfOptions, start, rng);
0296 }
0297
0298 BOOST_AUTO_TEST_SUITE_END()
0299
0300 }