File indexing completed on 2025-07-03 07:53:42
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <boost/test/unit_test.hpp>
0012
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/Definitions/Units.hpp"
0015 #include "Acts/EventData/MultiTrajectory.hpp"
0016 #include "Acts/EventData/ProxyAccessor.hpp"
0017 #include "Acts/EventData/SourceLink.hpp"
0018 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0019 #include "Acts/EventData/VectorTrackContainer.hpp"
0020 #include "Acts/EventData/detail/TestSourceLink.hpp"
0021 #include "Acts/Geometry/TrackingGeometry.hpp"
0022 #include "Acts/MagneticField/ConstantBField.hpp"
0023 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0024 #include "Acts/Propagator/Navigator.hpp"
0025 #include "Acts/Propagator/Propagator.hpp"
0026 #include "Acts/Propagator/StraightLineStepper.hpp"
0027 #include "Acts/Surfaces/CurvilinearSurface.hpp"
0028 #include "Acts/Tests/CommonHelpers/CubicTrackingGeometry.hpp"
0029 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0030 #include "Acts/Tests/CommonHelpers/MeasurementsCreator.hpp"
0031 #include "Acts/TrackFitting/detail/KalmanGlobalCovariance.hpp"
0032 #include "Acts/Utilities/CalibrationContext.hpp"
0033 #include "Acts/Utilities/Logger.hpp"
0034
0035 #include <iterator>
0036
0037 using namespace Acts::UnitLiterals;
0038 using namespace Acts::Test;
0039
0040
0041
0042
0043
0044
0045
0046 struct TestOutlierFinder {
0047 double distanceMax = std::numeric_limits<double>::max();
0048
0049
0050
0051
0052
0053
0054
0055 template <typename traj_t>
0056 bool operator()(typename traj_t::ConstTrackStateProxy state) const {
0057
0058 if (!state.hasCalibrated() || !state.hasPredicted()) {
0059 return false;
0060 }
0061 auto subspaceHelper = state.projectorSubspaceHelper();
0062 auto projector =
0063 subspaceHelper.fullProjector()
0064 .topLeftCorner(state.calibratedSize(), Acts::eBoundSize)
0065 .eval();
0066 auto residuals =
0067 (state.effectiveCalibrated() - projector * state.predicted()).eval();
0068 auto distance = residuals.norm();
0069 return (distanceMax <= distance);
0070 }
0071 };
0072
0073
0074
0075 struct TestReverseFilteringLogic {
0076 double momentumMax = std::numeric_limits<double>::max();
0077
0078
0079
0080
0081
0082
0083 template <typename traj_t>
0084 bool operator()(typename traj_t::ConstTrackStateProxy state) const {
0085
0086 auto momentum = std::abs(1 / state.filtered()[Acts::eBoundQOverP]);
0087 std::cout << "momentum : " << momentum << std::endl;
0088 return (momentum <= momentumMax);
0089 }
0090 };
0091
0092
0093 auto makeStraightPropagator(std::shared_ptr<const Acts::TrackingGeometry> geo) {
0094 Acts::Navigator::Config cfg{std::move(geo)};
0095 cfg.resolvePassive = false;
0096 cfg.resolveMaterial = true;
0097 cfg.resolveSensitive = true;
0098 Acts::Navigator navigator(
0099 cfg, Acts::getDefaultLogger("Navigator", Acts::Logging::INFO));
0100 Acts::StraightLineStepper stepper;
0101 return Acts::Propagator<Acts::StraightLineStepper, Acts::Navigator>(
0102 stepper, std::move(navigator));
0103 }
0104
0105
0106 template <typename stepper_t>
0107 auto makeConstantFieldPropagator(
0108 std::shared_ptr<const Acts::TrackingGeometry> geo, double bz) {
0109 Acts::Navigator::Config cfg{std::move(geo)};
0110 cfg.resolvePassive = false;
0111 cfg.resolveMaterial = true;
0112 cfg.resolveSensitive = true;
0113 Acts::Navigator navigator(
0114 cfg, Acts::getDefaultLogger("Navigator", Acts::Logging::INFO));
0115 auto field =
0116 std::make_shared<Acts::ConstantBField>(Acts::Vector3(0.0, 0.0, bz));
0117 stepper_t stepper(std::move(field));
0118 return Acts::Propagator<decltype(stepper), Acts::Navigator>(
0119 std::move(stepper), std::move(navigator));
0120 }
0121
0122
0123
0124 struct FitterTester {
0125 using Rng = std::default_random_engine;
0126
0127
0128 Acts::GeometryContext geoCtx;
0129 Acts::MagneticFieldContext magCtx;
0130 Acts::CalibrationContext calCtx;
0131
0132
0133 CubicTrackingGeometry geometryStore{geoCtx};
0134 std::shared_ptr<const Acts::TrackingGeometry> geometry = geometryStore();
0135
0136 Acts::detail::Test::TestSourceLink::SurfaceAccessor surfaceAccessor{
0137 *geometry};
0138
0139
0140 constexpr static std::size_t nMeasurements = 6u;
0141
0142
0143 MeasurementResolution resPixel = {MeasurementType::eLoc01, {25_um, 50_um}};
0144 MeasurementResolution resStrip0 = {MeasurementType::eLoc0, {100_um}};
0145 MeasurementResolution resStrip1 = {MeasurementType::eLoc1, {150_um}};
0146 MeasurementResolutionMap resolutions = {
0147 {Acts::GeometryIdentifier().withVolume(2), resPixel},
0148 {Acts::GeometryIdentifier().withVolume(3).withLayer(2), resStrip0},
0149 {Acts::GeometryIdentifier().withVolume(3).withLayer(4), resStrip1},
0150 {Acts::GeometryIdentifier().withVolume(3).withLayer(6), resStrip0},
0151 {Acts::GeometryIdentifier().withVolume(3).withLayer(8), resStrip1},
0152 };
0153
0154
0155 Acts::Propagator<Acts::StraightLineStepper, Acts::Navigator> simPropagator =
0156 makeStraightPropagator(geometry);
0157
0158 static std::vector<Acts::SourceLink> prepareSourceLinks(
0159 const std::vector<Acts::detail::Test::TestSourceLink>& sourceLinks) {
0160 std::vector<Acts::SourceLink> result;
0161 std::transform(sourceLinks.begin(), sourceLinks.end(),
0162 std::back_inserter(result),
0163 [](const auto& sl) { return Acts::SourceLink{sl}; });
0164 return result;
0165 }
0166
0167
0168
0169
0170
0171 template <typename fitter_t, typename fitter_options_t, typename parameters_t>
0172 void test_ZeroFieldNoSurfaceForward(const fitter_t& fitter,
0173 fitter_options_t options,
0174 const parameters_t& start, Rng& rng,
0175 const bool expected_reversed,
0176 const bool expected_smoothed,
0177 const bool doDiag) const {
0178 auto measurements = createMeasurements(simPropagator, geoCtx, magCtx, start,
0179 resolutions, rng);
0180
0181 auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
0182 BOOST_REQUIRE_EQUAL(sourceLinks.size(), nMeasurements);
0183
0184
0185 options.referenceSurface = nullptr;
0186
0187 Acts::ConstProxyAccessor<bool> reversed{"reversed"};
0188 Acts::ConstProxyAccessor<bool> smoothed{"smoothed"};
0189
0190 auto doTest = [&](bool diag) {
0191 Acts::TrackContainer tracks{Acts::VectorTrackContainer{},
0192 Acts::VectorMultiTrajectory{}};
0193 if (diag) {
0194 tracks.addColumn<bool>("reversed");
0195 tracks.addColumn<bool>("smoothed");
0196
0197 BOOST_CHECK(tracks.hasColumn("reversed"));
0198 BOOST_CHECK(tracks.hasColumn("smoothed"));
0199 }
0200
0201 auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(), start,
0202 options, tracks);
0203 BOOST_REQUIRE(res.ok());
0204
0205 const auto track = res.value();
0206 BOOST_CHECK_NE(track.tipIndex(), Acts::MultiTrajectoryTraits::kInvalid);
0207 BOOST_CHECK(!track.hasReferenceSurface());
0208 BOOST_CHECK_EQUAL(track.nMeasurements(), sourceLinks.size());
0209 BOOST_CHECK_EQUAL(track.nHoles(), 0u);
0210
0211 if (diag) {
0212
0213 BOOST_CHECK_EQUAL(reversed(track), expected_reversed);
0214 BOOST_CHECK_EQUAL(smoothed(track), expected_smoothed);
0215 }
0216 };
0217
0218 if (doDiag) {
0219 doTest(true);
0220 }
0221 doTest(false);
0222 }
0223
0224 template <typename fitter_t, typename fitter_options_t, typename parameters_t>
0225 void test_ZeroFieldWithSurfaceForward(const fitter_t& fitter,
0226 fitter_options_t options,
0227 const parameters_t& start, Rng& rng,
0228 const bool expected_reversed,
0229 const bool expected_smoothed,
0230 const bool doDiag) const {
0231 auto measurements = createMeasurements(simPropagator, geoCtx, magCtx, start,
0232 resolutions, rng);
0233 auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
0234 BOOST_REQUIRE_EQUAL(sourceLinks.size(), nMeasurements);
0235
0236
0237
0238 options.referenceSurface = &start.referenceSurface();
0239
0240 options.propagatorPlainOptions.direction = Acts::Direction::Forward();
0241
0242 Acts::TrackContainer tracks{Acts::VectorTrackContainer{},
0243 Acts::VectorMultiTrajectory{}};
0244 tracks.addColumn<bool>("reversed");
0245 tracks.addColumn<bool>("smoothed");
0246
0247 auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(), start,
0248 options, tracks);
0249 BOOST_REQUIRE(res.ok());
0250
0251 const auto& track = res.value();
0252 BOOST_CHECK_NE(track.tipIndex(), Acts::MultiTrajectoryTraits::kInvalid);
0253 BOOST_CHECK(track.hasReferenceSurface());
0254 BOOST_CHECK_EQUAL(track.nMeasurements(), sourceLinks.size());
0255 BOOST_CHECK_EQUAL(track.nHoles(), 0u);
0256
0257 BOOST_CHECK(tracks.hasColumn("reversed"));
0258 BOOST_CHECK(tracks.hasColumn("smoothed"));
0259
0260 Acts::ConstProxyAccessor<bool> reversed{"reversed"};
0261 Acts::ConstProxyAccessor<bool> smoothed{"smoothed"};
0262
0263
0264 if (doDiag) {
0265 BOOST_CHECK_EQUAL(smoothed(track), expected_smoothed);
0266 BOOST_CHECK_EQUAL(reversed(track), expected_reversed);
0267 }
0268
0269
0270 if (expected_reversed && expected_smoothed) {
0271 std::size_t nSmoothed = 0;
0272 for (const auto ts : track.trackStatesReversed()) {
0273 nSmoothed += ts.hasSmoothed();
0274 }
0275 BOOST_CHECK_EQUAL(nSmoothed, sourceLinks.size());
0276 }
0277 }
0278
0279 template <typename fitter_t, typename fitter_options_t, typename parameters_t>
0280 void test_ZeroFieldWithSurfaceBackward(const fitter_t& fitter,
0281 fitter_options_t options,
0282 const parameters_t& start, Rng& rng,
0283 const bool expected_reversed,
0284 const bool expected_smoothed,
0285 const bool doDiag) const {
0286 auto measurements = createMeasurements(simPropagator, geoCtx, magCtx, start,
0287 resolutions, rng);
0288 auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
0289 BOOST_REQUIRE_EQUAL(sourceLinks.size(), nMeasurements);
0290
0291
0292 Acts::Vector4 posOuter = start.fourPosition(geoCtx);
0293 posOuter[Acts::ePos0] = 3_m;
0294 Acts::BoundTrackParameters startOuter =
0295 Acts::BoundTrackParameters::createCurvilinear(
0296 posOuter, start.direction(), start.qOverP(), start.covariance(),
0297 Acts::ParticleHypothesis::pion());
0298
0299 options.referenceSurface = &startOuter.referenceSurface();
0300 options.propagatorPlainOptions.direction = Acts::Direction::Backward();
0301
0302 Acts::TrackContainer tracks{Acts::VectorTrackContainer{},
0303 Acts::VectorMultiTrajectory{}};
0304 tracks.addColumn<bool>("reversed");
0305 tracks.addColumn<bool>("smoothed");
0306
0307 auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(), startOuter,
0308 options, tracks);
0309 BOOST_CHECK(res.ok());
0310
0311 const auto& track = res.value();
0312 BOOST_CHECK_NE(track.tipIndex(), Acts::MultiTrajectoryTraits::kInvalid);
0313 BOOST_CHECK(track.hasReferenceSurface());
0314 BOOST_CHECK_EQUAL(track.nMeasurements(), sourceLinks.size());
0315 BOOST_CHECK_EQUAL(track.nHoles(), 0u);
0316
0317 Acts::ConstProxyAccessor<bool> reversed{"reversed"};
0318 Acts::ConstProxyAccessor<bool> smoothed{"smoothed"};
0319
0320 if (doDiag) {
0321 BOOST_CHECK_EQUAL(smoothed(track), expected_smoothed);
0322 BOOST_CHECK_EQUAL(reversed(track), expected_reversed);
0323 }
0324
0325
0326 if (expected_reversed && expected_smoothed) {
0327 std::size_t nSmoothed = 0;
0328 for (const auto ts : track.trackStatesReversed()) {
0329 nSmoothed += ts.hasSmoothed();
0330 }
0331 BOOST_CHECK_EQUAL(nSmoothed, sourceLinks.size());
0332 }
0333 }
0334
0335 template <typename fitter_t, typename fitter_options_t, typename parameters_t>
0336 void test_ZeroFieldWithSurfaceAtExit(const fitter_t& fitter,
0337 fitter_options_t options,
0338 const parameters_t& start, Rng& rng,
0339 const bool expected_reversed,
0340 const bool expected_smoothed,
0341 const bool doDiag) const {
0342 auto measurements = createMeasurements(simPropagator, geoCtx, magCtx, start,
0343 resolutions, rng);
0344 auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
0345 BOOST_REQUIRE_EQUAL(sourceLinks.size(), nMeasurements);
0346
0347
0348 Acts::Vector3 center(3._m, 0., 0.);
0349 Acts::Vector3 normal(1., 0., 0.);
0350 std::shared_ptr<Acts::PlaneSurface> targetSurface =
0351 Acts::CurvilinearSurface(center, normal).planeSurface();
0352
0353 options.referenceSurface = targetSurface.get();
0354
0355 Acts::TrackContainer tracks{Acts::VectorTrackContainer{},
0356 Acts::VectorMultiTrajectory{}};
0357 tracks.addColumn<bool>("reversed");
0358 tracks.addColumn<bool>("smoothed");
0359
0360 auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(), start,
0361 options, tracks);
0362 BOOST_REQUIRE(res.ok());
0363
0364 const auto& track = res.value();
0365 BOOST_CHECK_NE(track.tipIndex(), Acts::MultiTrajectoryTraits::kInvalid);
0366 BOOST_CHECK(track.hasReferenceSurface());
0367 BOOST_CHECK_EQUAL(track.nMeasurements(), sourceLinks.size());
0368 BOOST_CHECK_EQUAL(track.nHoles(), 0u);
0369
0370 Acts::ConstProxyAccessor<bool> reversed{"reversed"};
0371 Acts::ConstProxyAccessor<bool> smoothed{"smoothed"};
0372
0373
0374 if (doDiag) {
0375 BOOST_CHECK_EQUAL(smoothed(track), expected_smoothed);
0376 BOOST_CHECK_EQUAL(reversed(track), expected_reversed);
0377 }
0378 }
0379
0380 template <typename fitter_t, typename fitter_options_t, typename parameters_t>
0381 void test_ZeroFieldShuffled(const fitter_t& fitter, fitter_options_t options,
0382 const parameters_t& start, Rng& rng,
0383 const bool expected_reversed,
0384 const bool expected_smoothed,
0385 const bool doDiag) const {
0386 auto measurements = createMeasurements(simPropagator, geoCtx, magCtx, start,
0387 resolutions, rng);
0388 auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
0389 BOOST_REQUIRE_EQUAL(sourceLinks.size(), nMeasurements);
0390
0391 options.referenceSurface = &start.referenceSurface();
0392
0393 Acts::BoundVector parameters = Acts::BoundVector::Zero();
0394
0395 Acts::TrackContainer tracks{Acts::VectorTrackContainer{},
0396 Acts::VectorMultiTrajectory{}};
0397 tracks.addColumn<bool>("reversed");
0398 tracks.addColumn<bool>("smoothed");
0399
0400 Acts::ConstProxyAccessor<bool> reversed{"reversed"};
0401 Acts::ConstProxyAccessor<bool> smoothed{"smoothed"};
0402
0403
0404 {
0405 auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(), start,
0406 options, tracks);
0407 BOOST_REQUIRE(res.ok());
0408
0409 const auto& track = res.value();
0410 BOOST_CHECK_NE(track.tipIndex(), Acts::MultiTrajectoryTraits::kInvalid);
0411 BOOST_CHECK_EQUAL(track.nMeasurements(), sourceLinks.size());
0412 BOOST_REQUIRE(track.hasReferenceSurface());
0413 parameters = track.parameters();
0414 BOOST_CHECK_EQUAL(track.nHoles(), 0u);
0415
0416
0417 if (doDiag) {
0418 BOOST_CHECK_EQUAL(smoothed(track), expected_smoothed);
0419 BOOST_CHECK_EQUAL(reversed(track), expected_reversed);
0420 }
0421 }
0422
0423 {
0424 decltype(sourceLinks) shuffledSourceLinks = sourceLinks;
0425 std::shuffle(shuffledSourceLinks.begin(), shuffledSourceLinks.end(), rng);
0426 auto res = fitter.fit(shuffledSourceLinks.begin(),
0427 shuffledSourceLinks.end(), start, options, tracks);
0428 BOOST_REQUIRE(res.ok());
0429
0430 const auto& track = res.value();
0431 BOOST_CHECK_NE(track.tipIndex(), Acts::MultiTrajectoryTraits::kInvalid);
0432 BOOST_REQUIRE(track.hasReferenceSurface());
0433
0434 CHECK_CLOSE_ABS(track.parameters(), parameters, 1e-5);
0435 BOOST_CHECK_EQUAL(track.nMeasurements(), sourceLinks.size());
0436
0437 if (doDiag) {
0438 BOOST_CHECK_EQUAL(smoothed(track), expected_smoothed);
0439 BOOST_CHECK_EQUAL(reversed(track), expected_reversed);
0440 }
0441 }
0442 }
0443
0444 template <typename fitter_t, typename fitter_options_t, typename parameters_t>
0445 void test_ZeroFieldWithHole(const fitter_t& fitter, fitter_options_t options,
0446 const parameters_t& start, Rng& rng,
0447 const bool expected_reversed,
0448 const bool expected_smoothed,
0449 const bool doDiag) const {
0450 auto measurements = createMeasurements(simPropagator, geoCtx, magCtx, start,
0451 resolutions, rng);
0452 auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
0453 BOOST_REQUIRE_EQUAL(sourceLinks.size(), nMeasurements);
0454
0455 Acts::TrackContainer tracks{Acts::VectorTrackContainer{},
0456 Acts::VectorMultiTrajectory{}};
0457 tracks.addColumn<bool>("reversed");
0458 tracks.addColumn<bool>("smoothed");
0459
0460 Acts::ConstProxyAccessor<bool> reversed{"reversed"};
0461 Acts::ConstProxyAccessor<bool> smoothed{"smoothed"};
0462
0463
0464
0465 for (std::size_t i = 1u; (i + 1u) < sourceLinks.size(); ++i) {
0466
0467 auto withHole = sourceLinks;
0468 withHole.erase(std::next(withHole.begin(), i));
0469 BOOST_REQUIRE_EQUAL(withHole.size() + 1u, sourceLinks.size());
0470 BOOST_TEST_INFO("Removed measurement " << i);
0471
0472 auto res =
0473 fitter.fit(withHole.begin(), withHole.end(), start, options, tracks);
0474 BOOST_REQUIRE(res.ok());
0475
0476 const auto& track = res.value();
0477 BOOST_CHECK_NE(track.tipIndex(), Acts::MultiTrajectoryTraits::kInvalid);
0478 BOOST_REQUIRE(!track.hasReferenceSurface());
0479 BOOST_CHECK_EQUAL(track.nMeasurements(), withHole.size());
0480
0481 if (doDiag) {
0482 BOOST_CHECK_EQUAL(smoothed(track), expected_smoothed);
0483 BOOST_CHECK_EQUAL(reversed(track), expected_reversed);
0484 }
0485 BOOST_CHECK_EQUAL(track.nHoles(), 1u);
0486 }
0487 BOOST_CHECK_EQUAL(tracks.size(), sourceLinks.size() - 2);
0488 }
0489
0490 template <typename fitter_t, typename fitter_options_t, typename parameters_t>
0491 void test_ZeroFieldWithOutliers(const fitter_t& fitter,
0492 fitter_options_t options,
0493 const parameters_t& start, Rng& rng,
0494 const bool expected_reversed,
0495 const bool expected_smoothed,
0496 const bool doDiag) const {
0497 auto measurements = createMeasurements(simPropagator, geoCtx, magCtx, start,
0498 resolutions, rng);
0499 auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
0500 auto outlierSourceLinks =
0501 prepareSourceLinks(measurements.outlierSourceLinks);
0502 BOOST_REQUIRE_EQUAL(sourceLinks.size(), nMeasurements);
0503 BOOST_REQUIRE_EQUAL(outlierSourceLinks.size(), nMeasurements);
0504
0505 Acts::TrackContainer tracks{Acts::VectorTrackContainer{},
0506 Acts::VectorMultiTrajectory{}};
0507 tracks.addColumn<bool>("reversed");
0508 tracks.addColumn<bool>("smoothed");
0509
0510 Acts::ConstProxyAccessor<bool> reversed{"reversed"};
0511 Acts::ConstProxyAccessor<bool> smoothed{"smoothed"};
0512
0513 for (std::size_t i = 0; i < sourceLinks.size(); ++i) {
0514
0515 auto withOutlier = sourceLinks;
0516 withOutlier[i] = outlierSourceLinks[i];
0517 BOOST_REQUIRE_EQUAL(withOutlier.size(), sourceLinks.size());
0518 BOOST_TEST_INFO("Replaced measurement " << i << " with outlier");
0519
0520 auto res = fitter.fit(withOutlier.begin(), withOutlier.end(), start,
0521 options, tracks);
0522 BOOST_REQUIRE(res.ok());
0523
0524 const auto& track = res.value();
0525 BOOST_CHECK_NE(track.tipIndex(), Acts::MultiTrajectoryTraits::kInvalid);
0526
0527 std::size_t nOutliers = 0;
0528 for (const auto state : track.trackStatesReversed()) {
0529 nOutliers += state.typeFlags().test(Acts::TrackStateFlag::OutlierFlag);
0530 }
0531 BOOST_CHECK_EQUAL(nOutliers, 1u);
0532 BOOST_REQUIRE(!track.hasReferenceSurface());
0533 BOOST_CHECK_EQUAL(track.nMeasurements(), withOutlier.size() - 1u);
0534
0535 if (doDiag) {
0536 BOOST_CHECK_EQUAL(smoothed(track), expected_smoothed);
0537 BOOST_CHECK_EQUAL(reversed(track), expected_reversed);
0538 }
0539 BOOST_CHECK_EQUAL(track.nHoles(), 0u);
0540 }
0541 BOOST_CHECK_EQUAL(tracks.size(), sourceLinks.size());
0542 }
0543
0544 template <typename fitter_t, typename fitter_options_t, typename parameters_t>
0545 void test_ZeroFieldWithReverseFiltering(const fitter_t& fitter,
0546 fitter_options_t options,
0547 const parameters_t& start, Rng& rng,
0548 const bool expected_reversed,
0549 const bool expected_smoothed,
0550 const bool doDiag) const {
0551 auto measurements = createMeasurements(simPropagator, geoCtx, magCtx, start,
0552 resolutions, rng);
0553
0554 Acts::TrackContainer tracks{Acts::VectorTrackContainer{},
0555 Acts::VectorMultiTrajectory{}};
0556 tracks.addColumn<bool>("reversed");
0557 tracks.addColumn<bool>("smoothed");
0558
0559 Acts::ConstProxyAccessor<bool> reversed{"reversed"};
0560 Acts::ConstProxyAccessor<bool> smoothed{"smoothed"};
0561
0562 auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
0563
0564 const auto& outlierSourceLinks = measurements.outlierSourceLinks;
0565 BOOST_REQUIRE_EQUAL(sourceLinks.size(), nMeasurements);
0566 BOOST_REQUIRE_EQUAL(outlierSourceLinks.size(), nMeasurements);
0567
0568
0569 Acts::Vector3 center(-3._m, 0., 0.);
0570 Acts::Vector3 normal(1., 0., 0.);
0571 std::shared_ptr<Acts::PlaneSurface> targetSurface =
0572 Acts::CurvilinearSurface(center, normal).planeSurface();
0573
0574 options.referenceSurface = targetSurface.get();
0575
0576 auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(), start,
0577 options, tracks);
0578 BOOST_REQUIRE(res.ok());
0579 const auto& track = res.value();
0580
0581
0582
0583 if (doDiag) {
0584 BOOST_CHECK_EQUAL(smoothed(track), expected_smoothed);
0585 BOOST_CHECK_EQUAL(reversed(track), expected_reversed);
0586 }
0587 }
0588
0589
0590
0591 template <typename fitter_t, typename fitter_options_t, typename parameters_t>
0592 void test_GlobalCovariance(const fitter_t& fitter, fitter_options_t options,
0593 const parameters_t& start, Rng& rng) const {
0594 auto measurements = createMeasurements(simPropagator, geoCtx, magCtx, start,
0595 resolutions, rng);
0596 auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
0597 BOOST_REQUIRE_EQUAL(sourceLinks.size(), nMeasurements);
0598
0599 Acts::TrackContainer tracks{Acts::VectorTrackContainer{},
0600 Acts::VectorMultiTrajectory{}};
0601
0602 auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(), start,
0603 options, tracks);
0604 BOOST_REQUIRE(res.ok());
0605
0606
0607 const auto& track = res.value();
0608 auto [trackParamsCov, stateRowIndices] =
0609 Acts::detail::globalTrackParametersCovariance(
0610 tracks.trackStateContainer(), track.tipIndex());
0611 BOOST_CHECK_EQUAL(trackParamsCov.rows(),
0612 sourceLinks.size() * Acts::eBoundSize);
0613 BOOST_CHECK_EQUAL(stateRowIndices.size(), sourceLinks.size());
0614
0615
0616
0617
0618
0619 BOOST_CHECK_EQUAL(stateRowIndices.at(track.tipIndex()),
0620 Acts::eBoundSize * (nMeasurements - 1));
0621 }
0622 };