Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-28 07:46:25

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/EventData/AnyTrackStateProxy.hpp"
0012 #include "Acts/EventData/ProxyAccessor.hpp"
0013 #include "Acts/EventData/TrackContainer.hpp"
0014 #include "Acts/EventData/TrackStateProxy.hpp"
0015 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0016 #include "Acts/EventData/VectorTrackContainer.hpp"
0017 #include "Acts/Surfaces/PlaneSurface.hpp"
0018 #include "Acts/Surfaces/RectangleBounds.hpp"
0019 #include "Acts/Utilities/HashedString.hpp"
0020 
0021 namespace {
0022 
0023 using namespace Acts;
0024 using namespace Acts::HashedStringLiteral;
0025 
0026 struct TestTrackStateFixture {
0027   using Trajectory = VectorMultiTrajectory;
0028   using TrackContainerBackend = VectorTrackContainer;
0029   using Container =
0030       TrackContainer<TrackContainerBackend, Trajectory, detail::RefHolder>;
0031 
0032   TestTrackStateFixture() : container(trackContainer, trajectory) {}
0033 
0034   Container container;
0035   TrackContainerBackend trackContainer;
0036   Trajectory trajectory;
0037 };
0038 
0039 }  // namespace
0040 
0041 BOOST_AUTO_TEST_SUITE(EventDataAnyTrackState)
0042 
0043 BOOST_FIXTURE_TEST_CASE(WrapTrackStateProxy, TestTrackStateFixture) {
0044   auto track = container.makeTrack();
0045   auto state = container.trackStateContainer().makeTrackState();
0046   track.tipIndex() = state.index();
0047 
0048   auto proxy = container.trackStateContainer().getTrackState(state.index());
0049   AnyMutableTrackStateProxy anyState(proxy);
0050 
0051   BOOST_CHECK_EQUAL(anyState.index(), proxy.index());
0052 }
0053 
0054 BOOST_FIXTURE_TEST_CASE(ConstructFromReadOnlyTrackStateProxy,
0055                         TestTrackStateFixture) {
0056   auto track = container.makeTrack();
0057   auto state = container.trackStateContainer().makeTrackState();
0058   track.tipIndex() = state.index();
0059   state.predicted() = Vector<eBoundSize>::Ones();
0060 
0061   TrackContainer constContainer{ConstVectorTrackContainer{trackContainer},
0062                                 ConstVectorMultiTrajectory{trajectory}};
0063 
0064   auto constState =
0065       constContainer.trackStateContainer().getTrackState(state.index());
0066   AnyConstTrackStateProxy anyState(constState);
0067 
0068   BOOST_CHECK_EQUAL(anyState.index(), state.index());
0069   BOOST_CHECK_CLOSE(anyState.predicted()[eBoundLoc0], 1.0, 1e-6);
0070 }
0071 
0072 BOOST_FIXTURE_TEST_CASE(AccessFiltered, TestTrackStateFixture) {
0073   auto track = container.makeTrack();
0074   auto state = container.trackStateContainer().makeTrackState();
0075   track.tipIndex() = state.index();
0076 
0077   state.predicted() = Vector<eBoundSize>::Ones();
0078   state.filtered() = 2. * Vector<eBoundSize>::Ones();
0079 
0080   AnyMutableTrackStateProxy anyState(state);
0081 
0082   BOOST_CHECK_EQUAL(anyState.predicted()[eBoundLoc0], 1.);
0083   BOOST_CHECK_EQUAL(anyState.filtered()[eBoundLoc0], 2.);
0084 
0085   auto filtered = anyState.filtered();
0086   filtered[eBoundLoc0] = 3.;
0087   BOOST_CHECK_EQUAL(state.filtered()[eBoundLoc0], 3.);
0088 }
0089 
0090 BOOST_FIXTURE_TEST_CASE(AccessCalibratedFixedSize, TestTrackStateFixture) {
0091   auto track = container.makeTrack();
0092   auto state = container.trackStateContainer().makeTrackState();
0093   track.tipIndex() = state.index();
0094 
0095   state.allocateCalibrated(2);
0096   auto calibrated = state.template calibrated<2>();
0097   calibrated[0] = 1.5;
0098   calibrated[1] = 2.5;
0099   auto calibratedCov = state.template calibratedCovariance<2>();
0100   calibratedCov.setZero();
0101   calibratedCov(0, 0) = 0.1;
0102   calibratedCov(1, 1) = 0.2;
0103 
0104   AnyMutableTrackStateProxy anyState(state);
0105 
0106   auto view = anyState.calibrated<2>();
0107   BOOST_CHECK_CLOSE(view[0], 1.5, 1e-6);
0108   BOOST_CHECK_CLOSE(view[1], 2.5, 1e-6);
0109 
0110   view[0] = 4.5;
0111   BOOST_CHECK_CLOSE(state.calibrated<2>()[0], 4.5, 1e-6);
0112 
0113   auto covView = anyState.calibratedCovariance<2>();
0114   BOOST_CHECK_CLOSE(covView(0, 0), 0.1, 1e-6);
0115   BOOST_CHECK_CLOSE(covView(1, 1), 0.2, 1e-6);
0116   covView(0, 0) = 0.5;
0117   BOOST_CHECK_CLOSE(state.calibratedCovariance<2>()(0, 0), 0.5, 1e-6);
0118 
0119   AnyConstTrackStateProxy constState(state);
0120   auto constView = constState.calibrated<2>();
0121   BOOST_CHECK_CLOSE(constView[0], 4.5, 1e-6);
0122   auto constCov = constState.calibratedCovariance<2>();
0123   BOOST_CHECK_CLOSE(constCov(0, 0), 0.5, 1e-6);
0124 }
0125 
0126 BOOST_FIXTURE_TEST_CASE(AccessEffectiveCalibratedDynamic,
0127                         TestTrackStateFixture) {
0128   auto track = container.makeTrack();
0129   auto state = container.trackStateContainer().makeTrackState();
0130   track.tipIndex() = state.index();
0131 
0132   constexpr std::size_t measdim = 3u;
0133   state.allocateCalibrated(measdim);
0134   {
0135     auto dyn = state.effectiveCalibrated();
0136     for (std::size_t i = 0; i < measdim; ++i) {
0137       dyn[i] = 1. + static_cast<double>(i);
0138     }
0139   }
0140   {
0141     auto dynCov = state.effectiveCalibratedCovariance();
0142     dynCov.setZero();
0143     for (std::size_t i = 0; i < measdim; ++i) {
0144       dynCov(i, i) = 0.1 * static_cast<double>(i + 1);
0145     }
0146   }
0147 
0148   AnyMutableTrackStateProxy anyState(state);
0149   BOOST_CHECK_EQUAL(anyState.calibratedSize(), measdim);
0150   auto eff = anyState.effectiveCalibrated();
0151   BOOST_CHECK_EQUAL(eff.size(), measdim);
0152   BOOST_CHECK_CLOSE(eff[0], 1., 1e-6);
0153   BOOST_CHECK_CLOSE(eff[2], 3., 1e-6);
0154   eff[1] = 5.5;
0155   BOOST_CHECK_CLOSE(state.effectiveCalibrated()[1], 5.5, 1e-6);
0156 
0157   auto effCov = anyState.effectiveCalibratedCovariance();
0158   BOOST_CHECK_EQUAL(effCov.rows(), measdim);
0159   BOOST_CHECK_EQUAL(effCov.cols(), measdim);
0160   BOOST_CHECK_CLOSE(effCov(0, 0), 0.1, 1e-6);
0161   BOOST_CHECK_CLOSE(effCov(2, 2), 0.3, 1e-6);
0162   effCov(1, 1) = 1.7;
0163   BOOST_CHECK_CLOSE(state.effectiveCalibratedCovariance()(1, 1), 1.7, 1e-6);
0164 
0165   AnyConstTrackStateProxy constState(state);
0166   BOOST_CHECK_EQUAL(constState.calibratedSize(), measdim);
0167   auto constEff = constState.effectiveCalibrated();
0168   BOOST_CHECK_EQUAL(constEff.size(), measdim);
0169   BOOST_CHECK_CLOSE(constEff[1], 5.5, 1e-6);
0170   auto constEffCov = constState.effectiveCalibratedCovariance();
0171   BOOST_CHECK_EQUAL(constEffCov.rows(), measdim);
0172   BOOST_CHECK_CLOSE(constEffCov(1, 1), 1.7, 1e-6);
0173 }
0174 
0175 BOOST_FIXTURE_TEST_CASE(ProxyAccessorWithAnyTrackState, TestTrackStateFixture) {
0176   container.trackStateContainer().addColumn<float>("customFloat");
0177 
0178   auto track = container.makeTrack();
0179   auto state = container.trackStateContainer().makeTrackState();
0180   track.tipIndex() = state.index();
0181 
0182   state.template component<float>("customFloat"_hash) = 0.25f;
0183 
0184   ProxyAccessor<float> mutableAccessor("customFloat");
0185   ConstProxyAccessor<float> constAccessor("customFloat");
0186 
0187   AnyMutableTrackStateProxy anyState(state);
0188   BOOST_CHECK_CLOSE(mutableAccessor(anyState), 0.25f, 1e-6);
0189   mutableAccessor(anyState) = 0.75f;
0190   BOOST_CHECK_CLOSE(state.template component<float>("customFloat"_hash), 0.75f,
0191                     1e-6);
0192 
0193   AnyConstTrackStateProxy constState(state);
0194   BOOST_CHECK_CLOSE(constAccessor(constState), 0.75f, 1e-6);
0195   BOOST_CHECK(constAccessor.hasColumn(constState));
0196 }
0197 
0198 BOOST_FIXTURE_TEST_CASE(PreviousAndHasPrevious, TestTrackStateFixture) {
0199   auto track = container.makeTrack();
0200   auto state1 = container.trackStateContainer().makeTrackState();
0201   auto state2 = container.trackStateContainer().makeTrackState();
0202   track.tipIndex() = state2.index();
0203 
0204   // Link state2 -> state1
0205   state2.previous() = state1.index();
0206 
0207   AnyMutableTrackStateProxy anyState1(state1);
0208   AnyMutableTrackStateProxy anyState2(state2);
0209 
0210   // state1 has no previous
0211   BOOST_CHECK(!anyState1.hasPrevious());
0212 
0213   // state2 has previous
0214   BOOST_CHECK(anyState2.hasPrevious());
0215   BOOST_CHECK_EQUAL(anyState2.previous(), state1.index());
0216 
0217   // Test with const proxy
0218   AnyConstTrackStateProxy constState2(state2);
0219   BOOST_CHECK(constState2.hasPrevious());
0220   BOOST_CHECK_EQUAL(constState2.previous(), state1.index());
0221 }
0222 
0223 BOOST_FIXTURE_TEST_CASE(GetMask, TestTrackStateFixture) {
0224   // Test with no components
0225   {
0226     auto state = container.trackStateContainer().makeTrackState(
0227         TrackStatePropMask::None);
0228     AnyMutableTrackStateProxy anyState(state);
0229     auto mask = anyState.getMask();
0230     BOOST_CHECK_EQUAL(mask, TrackStatePropMask::None);
0231   }
0232 
0233   // Test with only predicted
0234   {
0235     auto state = container.trackStateContainer().makeTrackState(
0236         TrackStatePropMask::Predicted);
0237     AnyMutableTrackStateProxy anyState(state);
0238     auto mask = anyState.getMask();
0239     BOOST_CHECK(ACTS_CHECK_BIT(mask, TrackStatePropMask::Predicted));
0240     BOOST_CHECK(!ACTS_CHECK_BIT(mask, TrackStatePropMask::Filtered));
0241     BOOST_CHECK(!ACTS_CHECK_BIT(mask, TrackStatePropMask::Smoothed));
0242   }
0243 
0244   // Test with predicted and filtered
0245   {
0246     auto state = container.trackStateContainer().makeTrackState(
0247         TrackStatePropMask::Predicted | TrackStatePropMask::Filtered);
0248     AnyMutableTrackStateProxy anyState(state);
0249     auto mask = anyState.getMask();
0250     BOOST_CHECK(ACTS_CHECK_BIT(mask, TrackStatePropMask::Predicted));
0251     BOOST_CHECK(ACTS_CHECK_BIT(mask, TrackStatePropMask::Filtered));
0252     BOOST_CHECK(!ACTS_CHECK_BIT(mask, TrackStatePropMask::Smoothed));
0253   }
0254 
0255   // Test with all components
0256   {
0257     auto state =
0258         container.trackStateContainer().makeTrackState(TrackStatePropMask::All);
0259     state.allocateCalibrated(2);
0260     AnyMutableTrackStateProxy anyState(state);
0261     auto mask = anyState.getMask();
0262     BOOST_CHECK(ACTS_CHECK_BIT(mask, TrackStatePropMask::Predicted));
0263     BOOST_CHECK(ACTS_CHECK_BIT(mask, TrackStatePropMask::Filtered));
0264     BOOST_CHECK(ACTS_CHECK_BIT(mask, TrackStatePropMask::Smoothed));
0265     BOOST_CHECK(ACTS_CHECK_BIT(mask, TrackStatePropMask::Jacobian));
0266     BOOST_CHECK(ACTS_CHECK_BIT(mask, TrackStatePropMask::Calibrated));
0267   }
0268 }
0269 
0270 BOOST_FIXTURE_TEST_CASE(AccessSmoothed, TestTrackStateFixture) {
0271   auto track = container.makeTrack();
0272   auto state = container.trackStateContainer().makeTrackState();
0273   track.tipIndex() = state.index();
0274 
0275   // Set smoothed parameters and covariance
0276   state.smoothed() = Vector<eBoundSize>::Constant(5.);
0277   state.smoothedCovariance() = Matrix<eBoundSize, eBoundSize>::Identity();
0278 
0279   AnyMutableTrackStateProxy anyState(state);
0280 
0281   // Check hasSmoothed
0282   BOOST_CHECK(anyState.hasSmoothed());
0283 
0284   // Access smoothed parameters
0285   auto smoothed = anyState.smoothed();
0286   BOOST_CHECK_CLOSE(smoothed[eBoundLoc0], 5., 1e-6);
0287 
0288   // Modify smoothed parameters
0289   smoothed[eBoundLoc0] = 7.;
0290   BOOST_CHECK_CLOSE(state.smoothed()[eBoundLoc0], 7., 1e-6);
0291 
0292   // Access smoothed covariance
0293   auto smoothedCov = anyState.smoothedCovariance();
0294   BOOST_CHECK_CLOSE(smoothedCov(0, 0), 1., 1e-6);
0295   smoothedCov(0, 0) = 2.;
0296   BOOST_CHECK_CLOSE(state.smoothedCovariance()(0, 0), 2., 1e-6);
0297 
0298   // Test const proxy
0299   AnyConstTrackStateProxy constState(state);
0300   BOOST_CHECK(constState.hasSmoothed());
0301   auto constSmoothed = constState.smoothed();
0302   BOOST_CHECK_CLOSE(constSmoothed[eBoundLoc0], 7., 1e-6);
0303 }
0304 
0305 BOOST_FIXTURE_TEST_CASE(AccessJacobian, TestTrackStateFixture) {
0306   auto track = container.makeTrack();
0307   // Create state with jacobian allocated
0308   auto state = container.trackStateContainer().makeTrackState(
0309       TrackStatePropMask::Jacobian);
0310   track.tipIndex() = state.index();
0311 
0312   AnyMutableTrackStateProxy anyState(state);
0313   BOOST_CHECK(anyState.hasJacobian());
0314 
0315   // Set jacobian values
0316   state.jacobian() = Matrix<eBoundSize, eBoundSize>::Identity();
0317   state.jacobian()(0, 1) = 0.5;
0318 
0319   // Access jacobian (mutable)
0320   auto jac = anyState.jacobian();
0321   BOOST_CHECK_CLOSE(jac(0, 0), 1., 1e-6);
0322   BOOST_CHECK_CLOSE(jac(0, 1), 0.5, 1e-6);
0323 
0324   // Modify jacobian
0325   jac(0, 1) = 0.75;
0326   BOOST_CHECK_CLOSE(state.jacobian()(0, 1), 0.75, 1e-6);
0327 
0328   // Test const proxy
0329   AnyConstTrackStateProxy constState(state);
0330   BOOST_CHECK(constState.hasJacobian());
0331   auto constJac = constState.jacobian();
0332   BOOST_CHECK_CLOSE(constJac(0, 1), 0.75, 1e-6);
0333 }
0334 
0335 BOOST_FIXTURE_TEST_CASE(AccessParametersAndCovariance, TestTrackStateFixture) {
0336   auto track = container.makeTrack();
0337   // Allocate predicted parameters
0338   auto state = container.trackStateContainer().makeTrackState(
0339       TrackStatePropMask::Predicted);
0340   track.tipIndex() = state.index();
0341 
0342   // Set predicted parameters and covariance
0343   state.predicted() = Vector<eBoundSize>::Constant(3.);
0344   state.predictedCovariance() = Matrix<eBoundSize, eBoundSize>::Identity();
0345   state.predictedCovariance()(1, 1) = 2.;
0346 
0347   AnyMutableTrackStateProxy anyState(state);
0348 
0349   // Access through parameters() and covariance() directly
0350   auto params = anyState.parameters();
0351   BOOST_CHECK_CLOSE(params[eBoundLoc0], 3., 1e-6);
0352 
0353   auto cov = anyState.covariance();
0354   BOOST_CHECK_CLOSE(cov(0, 0), 1., 1e-6);
0355   BOOST_CHECK_CLOSE(cov(1, 1), 2., 1e-6);
0356 
0357   // Access through predictedCovariance
0358   auto predCov = anyState.predictedCovariance();
0359   BOOST_CHECK_CLOSE(predCov(1, 1), 2., 1e-6);
0360   predCov(1, 1) = 3.;
0361   BOOST_CHECK_CLOSE(state.predictedCovariance()(1, 1), 3., 1e-6);
0362 
0363   // Test const proxy
0364   AnyConstTrackStateProxy constState(state);
0365   auto constParams = constState.parameters();
0366   BOOST_CHECK_CLOSE(constParams[eBoundLoc0], 3., 1e-6);
0367   auto constCov = constState.covariance();
0368   BOOST_CHECK_CLOSE(constCov(1, 1), 3., 1e-6);
0369 }
0370 
0371 BOOST_FIXTURE_TEST_CASE(ReferenceSurface, TestTrackStateFixture) {
0372   auto track = container.makeTrack();
0373   // Create with default mask which includes all components
0374   auto state = container.trackStateContainer().makeTrackState();
0375   track.tipIndex() = state.index();
0376 
0377   // Create and set a reference surface
0378   auto initialSurface = Surface::makeShared<PlaneSurface>(
0379       Transform3::Identity(), std::make_shared<RectangleBounds>(10, 10));
0380   state.setReferenceSurface(initialSurface);
0381 
0382   AnyMutableTrackStateProxy anyState(state);
0383 
0384   // Should now have a reference surface
0385   BOOST_CHECK(anyState.hasReferenceSurface());
0386   const Surface& surf1 = anyState.referenceSurface();
0387   BOOST_CHECK(&surf1 == initialSurface.get());
0388 
0389   // Create a new surface and set it
0390   auto newSurface = Surface::makeShared<PlaneSurface>(
0391       Transform3::Identity(), std::make_shared<RectangleBounds>(10, 10));
0392   anyState.setReferenceSurface(newSurface);
0393 
0394   BOOST_CHECK(anyState.hasReferenceSurface());
0395   const Surface& surf2 = anyState.referenceSurface();
0396   BOOST_CHECK(&surf2 == newSurface.get());
0397 
0398   // Test const proxy
0399   AnyConstTrackStateProxy constState(state);
0400   BOOST_CHECK(constState.hasReferenceSurface());
0401   const Surface& surf3 = constState.referenceSurface();
0402   BOOST_CHECK(&surf3 == newSurface.get());
0403 }
0404 
0405 BOOST_FIXTURE_TEST_CASE(SourceLink, TestTrackStateFixture) {
0406   auto track = container.makeTrack();
0407   auto state = container.trackStateContainer().makeTrackState();
0408   track.tipIndex() = state.index();
0409 
0410   AnyMutableTrackStateProxy anyState(state);
0411 
0412   // Initially should not have source link
0413   BOOST_CHECK(!anyState.hasUncalibratedSourceLink());
0414 
0415   // Set source link
0416   state.setUncalibratedSourceLink(Acts::SourceLink{42});
0417 
0418   // Now should have source link
0419   BOOST_CHECK(anyState.hasUncalibratedSourceLink());
0420 
0421   // Get source link
0422   auto retrievedLink = anyState.getUncalibratedSourceLink();
0423   BOOST_CHECK_EQUAL(retrievedLink.get<int>(), 42);
0424 
0425   // Set new source link through any proxy
0426   Acts::SourceLink newLink{99};
0427   anyState.setUncalibratedSourceLink(std::move(newLink));
0428 
0429   // Should still have source link
0430   BOOST_CHECK(anyState.hasUncalibratedSourceLink());
0431 
0432   auto retrievedLink2 = anyState.getUncalibratedSourceLink();
0433   BOOST_CHECK_EQUAL(retrievedLink2.get<int>(), 99);
0434 
0435   // Test const proxy
0436   AnyConstTrackStateProxy constState(state);
0437   BOOST_CHECK(constState.hasUncalibratedSourceLink());
0438   auto constLink = constState.getUncalibratedSourceLink();
0439   BOOST_CHECK_EQUAL(constLink.get<int>(), 99);
0440 }
0441 
0442 BOOST_FIXTURE_TEST_CASE(ProjectorSubspaceIndices, TestTrackStateFixture) {
0443   auto track = container.makeTrack();
0444   // Create with all components (projector is allocated with calibrated)
0445   auto state = container.trackStateContainer().makeTrackState();
0446   track.tipIndex() = state.index();
0447 
0448   // Allocate calibrated which may also allocate projector
0449   constexpr std::size_t measdim = 2;
0450   state.allocateCalibrated(measdim);
0451 
0452   AnyMutableTrackStateProxy anyState(state);
0453   // Projector is now allocated
0454   BOOST_CHECK(anyState.hasProjector());
0455 
0456   // Set projector subspace indices
0457   BoundSubspaceIndices indices{};
0458   indices[0] = eBoundLoc0;
0459   indices[1] = eBoundLoc1;
0460   state.setProjectorSubspaceIndices(
0461       std::span<std::uint8_t>(indices.begin(), measdim));
0462 
0463   BOOST_CHECK(anyState.hasProjector());
0464 
0465   // Get projector subspace indices
0466   auto retrieved = anyState.projectorSubspaceIndices();
0467   BOOST_CHECK_EQUAL(retrieved[0], eBoundLoc0);
0468   BOOST_CHECK_EQUAL(retrieved[1], eBoundLoc1);
0469 
0470   // Get fixed-size variant
0471   auto fixedIndices = anyState.projectorSubspaceIndices<measdim>();
0472   BOOST_CHECK_EQUAL(fixedIndices[0], eBoundLoc0);
0473   BOOST_CHECK_EQUAL(fixedIndices[1], eBoundLoc1);
0474 
0475   // Test subspace helpers
0476   auto variableHelper = anyState.projectorSubspaceHelper();
0477   BOOST_CHECK_EQUAL(variableHelper.size(), measdim);
0478 
0479   auto fixedHelper = anyState.projectorSubspaceHelper<measdim>();
0480   BOOST_CHECK_EQUAL(fixedHelper.size(), measdim);
0481 
0482   // Test setting through any proxy
0483   BoundSubspaceIndices newIndices{};
0484   newIndices[0] = eBoundPhi;
0485   newIndices[1] = eBoundTheta;
0486   anyState.setProjectorSubspaceIndices(
0487       std::span<std::uint8_t>(newIndices.begin(), measdim));
0488 
0489   auto retrieved2 = anyState.projectorSubspaceIndices();
0490   BOOST_CHECK_EQUAL(retrieved2[0], eBoundPhi);
0491   BOOST_CHECK_EQUAL(retrieved2[1], eBoundTheta);
0492 
0493   // Test const proxy
0494   AnyConstTrackStateProxy constState(state);
0495   BOOST_CHECK(constState.hasProjector());
0496   auto constIndices = constState.projectorSubspaceIndices();
0497   BOOST_CHECK_EQUAL(constIndices[0], eBoundPhi);
0498 }
0499 
0500 BOOST_FIXTURE_TEST_CASE(Chi2AndPathLength, TestTrackStateFixture) {
0501   auto track = container.makeTrack();
0502   auto state = container.trackStateContainer().makeTrackState();
0503   track.tipIndex() = state.index();
0504 
0505   // Set chi2 and pathLength
0506   state.chi2() = 2.5f;
0507   state.pathLength() = 123.456;
0508 
0509   AnyMutableTrackStateProxy anyState(state);
0510 
0511   // Access chi2
0512   BOOST_CHECK_CLOSE(anyState.chi2(), 2.5f, 1e-6);
0513 
0514   // Modify chi2
0515   anyState.chi2() = 3.5f;
0516   BOOST_CHECK_CLOSE(state.chi2(), 3.5f, 1e-6);
0517 
0518   // Access pathLength
0519   BOOST_CHECK_CLOSE(anyState.pathLength(), 123.456, 1e-6);
0520 
0521   // Modify pathLength
0522   anyState.pathLength() = 234.567;
0523   BOOST_CHECK_CLOSE(state.pathLength(), 234.567, 1e-6);
0524 
0525   // Test const proxy
0526   AnyConstTrackStateProxy constState(state);
0527   BOOST_CHECK_CLOSE(constState.chi2(), 3.5f, 1e-6);
0528   BOOST_CHECK_CLOSE(constState.pathLength(), 234.567, 1e-6);
0529 }
0530 
0531 BOOST_FIXTURE_TEST_CASE(TypeFlags, TestTrackStateFixture) {
0532   auto track = container.makeTrack();
0533   auto state = container.trackStateContainer().makeTrackState();
0534   track.tipIndex() = state.index();
0535 
0536   // Initially typeFlags should be accessible (always allocated)
0537   AnyMutableTrackStateProxy anyState(state);
0538 
0539   // Set type flags through the original proxy
0540   state.typeFlags().setIsOutlier();
0541 
0542   // Access typeFlags through AnyTrackStateProxy
0543   auto flags = anyState.typeFlags();
0544   BOOST_CHECK(flags.hasMeasurement());
0545   BOOST_CHECK(!flags.isMeasurement());
0546   BOOST_CHECK(flags.isOutlier());
0547   BOOST_CHECK(!flags.isHole());
0548 
0549   // Modify typeFlags through AnyTrackStateProxy
0550   anyState.typeFlags().setIsHole();
0551 
0552   // Access typeFlags through AnyTrackStateProxy
0553   flags = anyState.typeFlags();
0554   BOOST_CHECK(!flags.hasMeasurement());
0555   BOOST_CHECK(!flags.isMeasurement());
0556   BOOST_CHECK(!flags.isOutlier());
0557   BOOST_CHECK(flags.isHole());
0558 }
0559 
0560 BOOST_FIXTURE_TEST_CASE(ComponentAccessWithStringKeys, TestTrackStateFixture) {
0561   container.trackStateContainer().addColumn<int>("intColumn");
0562   container.trackStateContainer().addColumn<double>("doubleColumn");
0563 
0564   auto track = container.makeTrack();
0565   auto state = container.trackStateContainer().makeTrackState();
0566   track.tipIndex() = state.index();
0567 
0568   state.template component<int>("intColumn"_hash) = 42;
0569   state.template component<double>("doubleColumn"_hash) = 3.14;
0570 
0571   AnyMutableTrackStateProxy anyState(state);
0572 
0573   // Test has() with string_view
0574   BOOST_CHECK(anyState.has("intColumn"));
0575   BOOST_CHECK(anyState.has("doubleColumn"));
0576   BOOST_CHECK(!anyState.has("nonexistent"));
0577 
0578   // Test component() with string_view (const)
0579   const auto& intVal = anyState.component<int>("intColumn");
0580   BOOST_CHECK_EQUAL(intVal, 42);
0581   const auto& doubleVal = anyState.component<double>("doubleColumn");
0582   BOOST_CHECK_CLOSE(doubleVal, 3.14, 1e-6);
0583 
0584   // Test component() with string_view (mutable)
0585   anyState.component<int>("intColumn") = 99;
0586   BOOST_CHECK_EQUAL(state.template component<int>("intColumn"_hash), 99);
0587 
0588   // Test hasColumn() with HashedString and string_view
0589   BOOST_CHECK(anyState.hasColumn("intColumn"_hash));
0590   BOOST_CHECK(anyState.hasColumn("intColumn"));
0591   BOOST_CHECK(!anyState.hasColumn("nonexistent"));
0592 
0593   // Test const proxy
0594   AnyConstTrackStateProxy constState(state);
0595   BOOST_CHECK(constState.has("intColumn"));
0596   const auto& constIntVal = constState.component<int>("intColumn");
0597   BOOST_CHECK_EQUAL(constIntVal, 99);
0598 }
0599 
0600 BOOST_FIXTURE_TEST_CASE(UnsetComponents, TestTrackStateFixture) {
0601   auto track = container.makeTrack();
0602   auto state = container.trackStateContainer().makeTrackState();
0603   track.tipIndex() = state.index();
0604 
0605   // Add various components
0606   state.predicted() = Vector<eBoundSize>::Ones();
0607   state.filtered() = 2. * Vector<eBoundSize>::Ones();
0608   state.smoothed() = 3. * Vector<eBoundSize>::Ones();
0609   state.jacobian() = Matrix<eBoundSize, eBoundSize>::Identity();
0610   state.allocateCalibrated(2);
0611 
0612   AnyMutableTrackStateProxy anyState(state);
0613 
0614   // Verify all components exist
0615   BOOST_CHECK(anyState.hasPredicted());
0616   BOOST_CHECK(anyState.hasFiltered());
0617   BOOST_CHECK(anyState.hasSmoothed());
0618   BOOST_CHECK(anyState.hasJacobian());
0619   BOOST_CHECK(anyState.hasCalibrated());
0620 
0621   state.unset(TrackStatePropMask::Smoothed);
0622 
0623   // Verify through AnyTrackStateProxy that the component was unset
0624   BOOST_CHECK(anyState.hasPredicted());
0625   BOOST_CHECK(anyState.hasFiltered());
0626   BOOST_CHECK(!anyState.hasSmoothed());
0627   BOOST_CHECK(anyState.hasJacobian());
0628   BOOST_CHECK(anyState.hasCalibrated());
0629 
0630   anyState.unset(TrackStatePropMask::Jacobian);
0631   BOOST_CHECK(state.hasPredicted());
0632   BOOST_CHECK(state.hasFiltered());
0633   BOOST_CHECK(!state.hasSmoothed());
0634   BOOST_CHECK(!state.hasJacobian());
0635   BOOST_CHECK(state.hasCalibrated());
0636 
0637   anyState.unset(TrackStatePropMask::Calibrated);
0638   BOOST_CHECK(state.hasPredicted());
0639   BOOST_CHECK(state.hasFiltered());
0640   BOOST_CHECK(!anyState.hasSmoothed());
0641   BOOST_CHECK(!anyState.hasJacobian());
0642   BOOST_CHECK(!anyState.hasCalibrated());
0643 }
0644 
0645 BOOST_FIXTURE_TEST_CASE(AllocateCalibratedWithEigen, TestTrackStateFixture) {
0646   auto track = container.makeTrack();
0647   auto state = container.trackStateContainer().makeTrackState();
0648   track.tipIndex() = state.index();
0649 
0650   AnyMutableTrackStateProxy anyState(state);
0651 
0652   // Allocate with Eigen objects
0653   Vector<2> val;
0654   val << 1.5, 2.5;
0655   SquareMatrix<2> cov;
0656   cov << 0.1, 0.01, 0.01, 0.2;
0657 
0658   anyState.allocateCalibrated(val, cov);
0659 
0660   // Verify allocation
0661   BOOST_CHECK(anyState.hasCalibrated());
0662   BOOST_CHECK_EQUAL(anyState.calibratedSize(), 2);
0663 
0664   // Verify values
0665   auto calibrated = anyState.calibrated<2>();
0666   BOOST_CHECK_CLOSE(calibrated[0], 1.5, 1e-6);
0667   BOOST_CHECK_CLOSE(calibrated[1], 2.5, 1e-6);
0668 
0669   // Verify covariance
0670   auto calibratedCov = anyState.calibratedCovariance<2>();
0671   BOOST_CHECK_CLOSE(calibratedCov(0, 0), 0.1, 1e-6);
0672   BOOST_CHECK_CLOSE(calibratedCov(0, 1), 0.01, 1e-6);
0673   BOOST_CHECK_CLOSE(calibratedCov(1, 0), 0.01, 1e-6);
0674   BOOST_CHECK_CLOSE(calibratedCov(1, 1), 0.2, 1e-6);
0675 }
0676 
0677 BOOST_AUTO_TEST_SUITE_END()