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