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