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/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/EventData/AnyTrackProxy.hpp"
0014 #include "Acts/EventData/MultiTrajectory.hpp"
0015 #include "Acts/EventData/ProxyAccessor.hpp"
0016 #include "Acts/EventData/TrackContainer.hpp"
0017 #include "Acts/EventData/TrackProxy.hpp"
0018 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0019 #include "Acts/EventData/VectorTrackContainer.hpp"
0020 #include "Acts/Geometry/GeometryContext.hpp"
0021 #include "Acts/Surfaces/PerigeeSurface.hpp"
0022 #include "Acts/Utilities/HashedString.hpp"
0023 #include "Acts/Utilities/Holders.hpp"
0024 
0025 #include <memory>
0026 #include <vector>
0027 
0028 namespace {
0029 
0030 using namespace Acts::UnitLiterals;
0031 using namespace Acts;
0032 using namespace Acts::HashedStringLiteral;
0033 
0034 const auto gctx = GeometryContext::dangerouslyDefaultConstruct();
0035 
0036 // Helper to create a test track with some data
0037 template <typename track_container_t>
0038 void fillTestTrack(typename track_container_t::TrackProxy track) {
0039   auto surface = Acts::Surface::makeShared<PerigeeSurface>(Vector3::Zero());
0040 
0041   // Set reference surface
0042   track.setReferenceSurface(surface);
0043 
0044   // Set parameters
0045   auto params = track.parameters();
0046   params[eBoundLoc0] = 1.0;
0047   params[eBoundLoc1] = 2.0;
0048   params[eBoundTime] = 3.0;
0049   params[eBoundPhi] = 0.5;
0050   params[eBoundTheta] = std::numbers::pi / 4.0;
0051   params[eBoundQOverP] = 0.1;
0052 
0053   // Set covariance
0054   auto cov = track.covariance();
0055   cov.setIdentity();
0056   cov(eBoundLoc0, eBoundLoc0) = 0.01;
0057   cov(eBoundQOverP, eBoundQOverP) = 0.0001;
0058 
0059   // Set statistics
0060   track.chi2() = 12.5f;
0061   track.nDoF() = 10u;
0062   track.nMeasurements() = 8u;
0063   track.nHoles() = 1u;
0064   track.nOutliers() = 0u;
0065   track.nSharedHits() = 2u;
0066 
0067   // Set particle hypothesis
0068   track.setParticleHypothesis(ParticleHypothesis::pion());
0069 }
0070 
0071 }  // namespace
0072 
0073 BOOST_AUTO_TEST_SUITE(EventDataAnyTrack)
0074 
0075 BOOST_AUTO_TEST_CASE(ConstructFromTrackProxy_ValueHolder) {
0076   TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0077 
0078   auto track = tc.makeTrack();
0079   fillTestTrack<decltype(tc)>(track);
0080 
0081   // Construct from track proxy
0082   AnyMutableTrackProxy anyTrack(track);
0083 
0084   // Verify index
0085   BOOST_CHECK_EQUAL(anyTrack.index(), track.index());
0086 }
0087 
0088 BOOST_AUTO_TEST_CASE(ConstructFromTrackProxy_SharedPtr) {
0089   auto vtc = std::make_shared<VectorTrackContainer>();
0090   auto mtj = std::make_shared<VectorMultiTrajectory>();
0091   TrackContainer tc{vtc, mtj};
0092 
0093   auto track = tc.makeTrack();
0094   fillTestTrack<decltype(tc)>(track);
0095 
0096   // Construct from track proxy
0097   AnyMutableTrackProxy anyTrack(track);
0098 
0099   // Verify index
0100   BOOST_CHECK_EQUAL(anyTrack.index(), track.index());
0101 }
0102 
0103 BOOST_AUTO_TEST_CASE(ConstructFromConstTrackProxy) {
0104   VectorTrackContainer vtc;
0105   VectorMultiTrajectory mtj;
0106   TrackContainer tc{vtc, mtj};
0107 
0108   auto track = tc.makeTrack();
0109   fillTestTrack<decltype(tc)>(track);
0110 
0111   // Get const track proxy
0112   auto constTrack = tc.getTrack(track.index());
0113 
0114   // Construct from const track proxy
0115   AnyConstTrackProxy anyTrack(constTrack);
0116 
0117   BOOST_CHECK_EQUAL(anyTrack.index(), track.index());
0118 }
0119 
0120 BOOST_AUTO_TEST_CASE(ConstructFromReadOnlyTrackContainer) {
0121   VectorTrackContainer vtc;
0122   VectorMultiTrajectory mtj;
0123   TrackContainer tc{vtc, mtj};
0124 
0125   auto track = tc.makeTrack();
0126   fillTestTrack<decltype(tc)>(track);
0127 
0128   TrackContainer constTc{ConstVectorTrackContainer{vtc},
0129                          ConstVectorMultiTrajectory{mtj}};
0130   auto constTrack = constTc.getTrack(track.index());
0131 
0132   AnyConstTrackProxy anyTrack(constTrack);
0133 
0134   BOOST_CHECK_EQUAL(anyTrack.index(), track.index());
0135   BOOST_CHECK_CLOSE(anyTrack.parameter(eBoundLoc0), 1.0, 1e-6);
0136 }
0137 
0138 BOOST_AUTO_TEST_CASE(AccessIndices) {
0139   VectorTrackContainer vtc;
0140   VectorMultiTrajectory mtj;
0141   TrackContainer tc{vtc, mtj};
0142 
0143   auto track = tc.makeTrack();
0144   fillTestTrack<decltype(tc)>(track);
0145 
0146   track.tipIndex() = 42;
0147   track.stemIndex() = 7;
0148 
0149   AnyMutableTrackProxy anyTrack(track);
0150 
0151   BOOST_CHECK_EQUAL(anyTrack.tipIndex(), 42u);
0152   BOOST_CHECK_EQUAL(anyTrack.stemIndex(), 7u);
0153   BOOST_CHECK_EQUAL(anyTrack.index(), track.index());
0154 }
0155 
0156 BOOST_AUTO_TEST_CASE(AccessReferenceSurface) {
0157   VectorTrackContainer vtc;
0158   VectorMultiTrajectory mtj;
0159   TrackContainer tc{vtc, mtj};
0160 
0161   auto track = tc.makeTrack();
0162   auto surface = Acts::Surface::makeShared<PerigeeSurface>(Vector3::Zero());
0163   track.setReferenceSurface(surface);
0164 
0165   AnyMutableTrackProxy anyTrack(track);
0166 
0167   BOOST_CHECK(anyTrack.hasReferenceSurface());
0168   BOOST_CHECK_EQUAL(&anyTrack.referenceSurface(), surface.get());
0169 }
0170 
0171 BOOST_AUTO_TEST_CASE(AccessParameters) {
0172   VectorTrackContainer vtc;
0173   VectorMultiTrajectory mtj;
0174   TrackContainer tc{vtc, mtj};
0175 
0176   auto track = tc.makeTrack();
0177   fillTestTrack<decltype(tc)>(track);
0178 
0179   AnyMutableTrackProxy anyTrack(track);
0180 
0181   // Check individual parameters
0182   BOOST_CHECK_CLOSE(anyTrack.parameter(eBoundLoc0), 1.0, 1e-6);
0183   BOOST_CHECK_CLOSE(anyTrack.parameter(eBoundLoc1), 2.0, 1e-6);
0184   BOOST_CHECK_CLOSE(anyTrack.parameter(eBoundTime), 3.0, 1e-6);
0185   BOOST_CHECK_CLOSE(anyTrack.parameter(eBoundPhi), 0.5, 1e-6);
0186   BOOST_CHECK_CLOSE(anyTrack.parameter(eBoundTheta), std::numbers::pi / 4.0,
0187                     1e-6);
0188   BOOST_CHECK_CLOSE(anyTrack.parameter(eBoundQOverP), 0.1, 1e-6);
0189 
0190   // Check convenience accessors
0191   BOOST_CHECK_CLOSE(anyTrack.phi(), 0.5, 1e-6);
0192   BOOST_CHECK_CLOSE(anyTrack.theta(), std::numbers::pi / 4.0, 1e-6);
0193   BOOST_CHECK_CLOSE(anyTrack.qOverP(), 0.1, 1e-6);
0194 
0195   // Verify parameters() map provides reference semantics
0196   auto paramsView = anyTrack.parameters();
0197   paramsView[eBoundLoc0] = 9.0;
0198   BOOST_CHECK_CLOSE(track.parameters()[eBoundLoc0], 9.0, 1e-6);
0199 
0200   AnyConstTrackProxy constTrack(track);
0201   auto constParamsView = constTrack.parameters();
0202   BOOST_CHECK_CLOSE(constParamsView[eBoundLoc0], 9.0, 1e-6);
0203 }
0204 
0205 BOOST_AUTO_TEST_CASE(AccessCovariance) {
0206   VectorTrackContainer vtc;
0207   VectorMultiTrajectory mtj;
0208   TrackContainer tc{vtc, mtj};
0209 
0210   auto track = tc.makeTrack();
0211   fillTestTrack<decltype(tc)>(track);
0212 
0213   AnyMutableTrackProxy anyTrack(track);
0214 
0215   // Check covariance elements
0216   BOOST_CHECK_CLOSE(anyTrack.covariance(eBoundLoc0, eBoundLoc0), 0.01, 1e-6);
0217   BOOST_CHECK_CLOSE(anyTrack.covariance(eBoundQOverP, eBoundQOverP), 0.0001,
0218                     1e-6);
0219   BOOST_CHECK_CLOSE(anyTrack.covariance(eBoundLoc0, eBoundLoc1), 0.0, 1e-6);
0220 
0221   // Verify covariance() map provides reference semantics
0222   auto covView = anyTrack.covariance();
0223   covView(eBoundLoc0, eBoundLoc1) = 0.5;
0224   BOOST_CHECK_CLOSE(track.covariance()(eBoundLoc0, eBoundLoc1), 0.5, 1e-6);
0225 
0226   AnyConstTrackProxy constTrack(track);
0227   auto constCovView = constTrack.covariance();
0228   BOOST_CHECK_CLOSE(constCovView(eBoundLoc0, eBoundLoc1), 0.5, 1e-6);
0229 }
0230 
0231 BOOST_AUTO_TEST_CASE(AccessParticleHypothesis) {
0232   VectorTrackContainer vtc;
0233   VectorMultiTrajectory mtj;
0234   TrackContainer tc{vtc, mtj};
0235 
0236   auto track = tc.makeTrack();
0237   fillTestTrack<decltype(tc)>(track);
0238 
0239   AnyMutableTrackProxy anyTrack(track);
0240 
0241   auto ph = anyTrack.particleHypothesis();
0242   BOOST_CHECK_EQUAL(ph, ParticleHypothesis::pion());
0243 }
0244 
0245 BOOST_AUTO_TEST_CASE(AccessDerivedQuantities) {
0246   VectorTrackContainer vtc;
0247   VectorMultiTrajectory mtj;
0248   TrackContainer tc{vtc, mtj};
0249 
0250   auto track = tc.makeTrack();
0251   fillTestTrack<decltype(tc)>(track);
0252 
0253   AnyMutableTrackProxy anyTrack(track);
0254 
0255   // Check charge
0256   double expectedCharge =
0257       ParticleHypothesis::pion().extractCharge(track.qOverP());
0258   BOOST_CHECK_CLOSE(anyTrack.charge(), expectedCharge, 1e-6);
0259 
0260   // Check momentum
0261   double expectedMomentum =
0262       ParticleHypothesis::pion().extractMomentum(track.qOverP());
0263   BOOST_CHECK_CLOSE(anyTrack.absoluteMomentum(), expectedMomentum, 1e-6);
0264 
0265   // Check transverse momentum
0266   double expectedPt = std::sin(track.theta()) * expectedMomentum;
0267   BOOST_CHECK_CLOSE(anyTrack.transverseMomentum(), expectedPt, 1e-6);
0268 }
0269 
0270 BOOST_AUTO_TEST_CASE(AccessStatistics) {
0271   VectorTrackContainer vtc;
0272   VectorMultiTrajectory mtj;
0273   TrackContainer tc{vtc, mtj};
0274 
0275   auto track = tc.makeTrack();
0276   fillTestTrack<decltype(tc)>(track);
0277 
0278   AnyMutableTrackProxy anyTrack(track);
0279 
0280   BOOST_CHECK_EQUAL(anyTrack.chi2(), 12.5f);
0281   BOOST_CHECK_EQUAL(anyTrack.nDoF(), 10u);
0282   BOOST_CHECK_EQUAL(anyTrack.nMeasurements(), 8u);
0283   BOOST_CHECK_EQUAL(anyTrack.nHoles(), 1u);
0284   BOOST_CHECK_EQUAL(anyTrack.nOutliers(), 0u);
0285   BOOST_CHECK_EQUAL(anyTrack.nSharedHits(), 2u);
0286 }
0287 
0288 BOOST_AUTO_TEST_CASE(AccessTrackStates) {
0289   VectorTrackContainer vtc;
0290   VectorMultiTrajectory mtj;
0291   TrackContainer tc{vtc, mtj};
0292 
0293   auto track = tc.makeTrack();
0294   fillTestTrack<decltype(tc)>(track);
0295 
0296   // Add some track states
0297   auto ts1 = tc.trackStateContainer().makeTrackState();
0298   auto ts2 = tc.trackStateContainer().makeTrackState();
0299   ts2.previous() = ts1.index();
0300   auto ts3 = tc.trackStateContainer().makeTrackState();
0301   ts3.previous() = ts2.index();
0302 
0303   track.tipIndex() = ts3.index();
0304 
0305   AnyMutableTrackProxy anyTrack(track);
0306 
0307   BOOST_CHECK_EQUAL(anyTrack.nTrackStates(), 3u);
0308 }
0309 
0310 BOOST_AUTO_TEST_CASE(AccessDynamicColumns) {
0311   VectorTrackContainer vtc;
0312   VectorMultiTrajectory mtj;
0313   TrackContainer tc{vtc, mtj};
0314 
0315   // Add a dynamic column
0316   tc.addColumn<int>("customInt");
0317   tc.addColumn<float>("customFloat");
0318 
0319   auto track = tc.makeTrack();
0320   fillTestTrack<decltype(tc)>(track);
0321 
0322   track.template component<int>("customInt") = 42;
0323   track.template component<float>("customFloat") = 3.14f;
0324 
0325   AnyMutableTrackProxy anyTrack(track);
0326 
0327   // Check column existence
0328   BOOST_CHECK(anyTrack.hasColumn("customInt"_hash));
0329   BOOST_CHECK(anyTrack.hasColumn("customFloat"_hash));
0330   BOOST_CHECK(!anyTrack.hasColumn("nonExistent"_hash));
0331 
0332   // Access dynamic components using template
0333   BOOST_CHECK_EQUAL(anyTrack.component<int>("customInt"_hash), 42);
0334   BOOST_CHECK_CLOSE(anyTrack.component<float>("customFloat"_hash), 3.14f, 1e-6);
0335 
0336   // Also test with compile-time key
0337   BOOST_CHECK_EQUAL((anyTrack.component<int, "customInt"_hash>()), 42);
0338   BOOST_CHECK_CLOSE((anyTrack.component<float, "customFloat"_hash>()), 3.14f,
0339                     1e-6);
0340 
0341   // Mutate via AnyTrack and observe through const handle
0342   anyTrack.component<int>("customInt"_hash) = 7;
0343   BOOST_CHECK_EQUAL(anyTrack.component<int>("customInt"_hash), 7);
0344   AnyConstTrackProxy constTrack(track);
0345   BOOST_CHECK_EQUAL(constTrack.component<int>("customInt"_hash), 7);
0346 }
0347 
0348 BOOST_AUTO_TEST_CASE(ProxyAccessorWithAnyTrack) {
0349   VectorTrackContainer vtc;
0350   VectorMultiTrajectory mtj;
0351   TrackContainer tc{vtc, mtj};
0352 
0353   tc.addColumn<float>("customFloat");
0354   auto track = tc.makeTrack();
0355   fillTestTrack<decltype(tc)>(track);
0356   track.template component<float>("customFloat"_hash) = 1.5f;
0357 
0358   ProxyAccessor<float> mutableAccessor("customFloat");
0359   ConstProxyAccessor<float> constAccessor("customFloat");
0360 
0361   AnyMutableTrackProxy anyTrack(track);
0362   BOOST_CHECK_CLOSE(mutableAccessor(anyTrack), 1.5f, 1e-6);
0363   mutableAccessor(anyTrack) = 2.25f;
0364   BOOST_CHECK_CLOSE(track.template component<float>("customFloat"_hash), 2.25f,
0365                     1e-6);
0366 
0367   AnyConstTrackProxy constTrack(track);
0368   BOOST_CHECK_CLOSE(constAccessor(constTrack), 2.25f, 1e-6);
0369   BOOST_CHECK(constAccessor.hasColumn(constTrack));
0370 }
0371 
0372 BOOST_AUTO_TEST_CASE(TypeErasureHeterogeneousStorage) {
0373   // Create tracks with different holder types
0374   VectorTrackContainer vtc1;
0375   VectorMultiTrajectory mtj1;
0376   TrackContainer tc1{vtc1, mtj1};
0377 
0378   TrackContainer tc2{VectorTrackContainer{}, VectorMultiTrajectory{}};
0379 
0380   auto vtc3 = std::make_shared<VectorTrackContainer>();
0381   auto mtj3 = std::make_shared<VectorMultiTrajectory>();
0382   TrackContainer tc3{vtc3, mtj3};
0383 
0384   auto track1 = tc1.makeTrack();
0385   auto track2 = tc2.makeTrack();
0386   auto track3 = tc3.makeTrack();
0387 
0388   fillTestTrack<decltype(tc1)>(track1);
0389   fillTestTrack<decltype(tc2)>(track2);
0390   fillTestTrack<decltype(tc3)>(track3);
0391 
0392   track1.chi2() = 10.0f;
0393   track2.chi2() = 20.0f;
0394   track3.chi2() = 30.0f;
0395 
0396   // Store in a vector - all have the same type!
0397   std::vector<AnyMutableTrackProxy> anyTracks;
0398   anyTracks.emplace_back(track1);
0399   anyTracks.emplace_back(track2);
0400   anyTracks.emplace_back(track3);
0401 
0402   BOOST_CHECK_EQUAL(anyTracks.size(), 3u);
0403   BOOST_CHECK_EQUAL(anyTracks[0].chi2(), 10.0f);
0404   BOOST_CHECK_EQUAL(anyTracks[1].chi2(), 20.0f);
0405   BOOST_CHECK_EQUAL(anyTracks[2].chi2(), 30.0f);
0406 }
0407 
0408 BOOST_AUTO_TEST_CASE(MemoryFootprint) {
0409   // Verify that AnyTrack is three pointers (container, handler, index)
0410   // index is TrackIndexType (std::uint32_t), so on 64-bit it's 2 pointers + 4
0411   // bytes which gets padded to 3 pointers
0412   BOOST_CHECK_EQUAL(sizeof(AnyMutableTrackProxy), 3 * sizeof(void*));
0413   BOOST_CHECK_EQUAL(sizeof(AnyConstTrackProxy), 3 * sizeof(void*));
0414 }
0415 
0416 BOOST_AUTO_TEST_CASE(CrossTalkWithTrackProxy) {
0417   // Test that modifications made through TrackProxy are visible in AnyTrack
0418   // and vice versa (both reference the same underlying data)
0419   VectorTrackContainer vtc;
0420   VectorMultiTrajectory mtj;
0421   TrackContainer tc{vtc, mtj};
0422 
0423   auto track = tc.makeTrack();
0424   fillTestTrack<decltype(tc)>(track);
0425 
0426   // Create AnyTrack from TrackProxy
0427   AnyMutableTrackProxy anyTrack(track);
0428 
0429   // Initial values should match
0430   BOOST_CHECK_EQUAL(track.chi2(), 12.5f);
0431   BOOST_CHECK_EQUAL(anyTrack.chi2(), 12.5f);
0432 
0433   // Modify through TrackProxy
0434   track.chi2() = 42.0f;
0435   track.nMeasurements() = 15u;
0436   track.tipIndex() = 99;
0437 
0438   // Changes should be visible in AnyTrack (reads from same container)
0439   BOOST_CHECK_EQUAL(anyTrack.chi2(), 42.0f);
0440   BOOST_CHECK_EQUAL(anyTrack.nMeasurements(), 15u);
0441   BOOST_CHECK_EQUAL(anyTrack.tipIndex(), 99u);
0442 
0443   // Get another TrackProxy to the same track
0444   auto track2 = tc.getTrack(track.index());
0445 
0446   // Verify both proxies see the same data
0447   BOOST_CHECK_EQUAL(track2.chi2(), 42.0f);
0448   BOOST_CHECK_EQUAL(track2.nMeasurements(), 15u);
0449   BOOST_CHECK_EQUAL(track2.tipIndex(), 99u);
0450 
0451   // Modify through AnyTrack and verify TrackProxy observes the changes
0452   anyTrack.chi2() = 7.5f;
0453   anyTrack.nMeasurements() = 5u;
0454   anyTrack.tipIndex() = 123u;
0455   anyTrack.parameter(eBoundLoc0) = 5.5;
0456   anyTrack.covariance(eBoundLoc0, eBoundLoc0) = 0.2;
0457 
0458   BOOST_CHECK_EQUAL(track.chi2(), 7.5f);
0459   BOOST_CHECK_EQUAL(track.nMeasurements(), 5u);
0460   BOOST_CHECK_EQUAL(track.tipIndex(), 123u);
0461   BOOST_CHECK_CLOSE(track.parameters()[eBoundLoc0], 5.5, 1e-6);
0462   BOOST_CHECK_CLOSE(track.covariance()(eBoundLoc0, eBoundLoc0), 0.2, 1e-6);
0463 
0464   BOOST_CHECK_EQUAL(track2.chi2(), 7.5f);
0465   BOOST_CHECK_EQUAL(track2.nMeasurements(), 5u);
0466   BOOST_CHECK_EQUAL(track2.tipIndex(), 123u);
0467   BOOST_CHECK_CLOSE(track2.parameters()[eBoundLoc0], 5.5, 1e-6);
0468   BOOST_CHECK_CLOSE(track2.covariance()(eBoundLoc0, eBoundLoc0), 0.2, 1e-6);
0469 
0470   // Modify through the second proxy
0471   track2.chi2() = 100.0f;
0472 
0473   // Changes should be visible everywhere
0474   BOOST_CHECK_EQUAL(track.chi2(), 100.0f);
0475   BOOST_CHECK_EQUAL(anyTrack.chi2(), 100.0f);
0476 }
0477 
0478 BOOST_AUTO_TEST_CASE(ConstCorrectnessCrossTalk) {
0479   // Test that const AnyTrack can be created from mutable TrackProxy
0480   // and both see the same data
0481   VectorTrackContainer vtc;
0482   VectorMultiTrajectory mtj;
0483   TrackContainer tc{vtc, mtj};
0484 
0485   auto track = tc.makeTrack();
0486   fillTestTrack<decltype(tc)>(track);
0487   track.chi2() = 25.0f;
0488 
0489   // Create const AnyTrack from mutable TrackProxy
0490   AnyConstTrackProxy constAnyTrack(track);
0491 
0492   // Both should see the same data
0493   BOOST_CHECK_EQUAL(track.chi2(), 25.0f);
0494   BOOST_CHECK_EQUAL(constAnyTrack.chi2(), 25.0f);
0495 
0496   // Modify through mutable proxy
0497   track.chi2() = 50.0f;
0498 
0499   // Const AnyTrack should see the change
0500   BOOST_CHECK_EQUAL(constAnyTrack.chi2(), 50.0f);
0501 }
0502 
0503 BOOST_AUTO_TEST_CASE(ConstCorrectnessRestrictions) {
0504   // Test const-correctness restrictions on constructor
0505   VectorTrackContainer vtc;
0506   VectorMultiTrajectory mtj;
0507   TrackContainer tc{vtc, mtj};
0508 
0509   auto mutableTrack = tc.makeTrack();
0510   fillTestTrack<decltype(tc)>(mutableTrack);
0511 
0512   auto constTrack = tc.getTrack(mutableTrack.index());
0513 
0514   // These should compile:
0515   // 1. AnyMutableTrackProxy from mutable track proxy
0516   AnyMutableTrackProxy anyMutable1(mutableTrack);
0517 
0518   // 2. AnyConstTrackProxy from mutable track proxy
0519   AnyConstTrackProxy anyConst1(mutableTrack);
0520 
0521   // 3. AnyConstTrackProxy from const track proxy
0522   AnyConstTrackProxy anyConst2(constTrack);
0523 
0524   // The following should NOT compile (uncomment to test):
0525   // AnyMutableTrackProxy anyMutable2(constTrack);  // Error: cannot create
0526   // mutable from const
0527 
0528   // Verify all see the same data
0529   mutableTrack.chi2() = 77.0f;
0530   BOOST_CHECK_EQUAL(anyMutable1.chi2(), 77.0f);
0531   BOOST_CHECK_EQUAL(anyConst1.chi2(), 77.0f);
0532   BOOST_CHECK_EQUAL(anyConst2.chi2(), 77.0f);
0533 }
0534 
0535 BOOST_AUTO_TEST_SUITE_END()