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