Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-09 09:26:55

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/Definitions/Units.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/TrackStatePropMask.hpp"
0019 #include "Acts/EventData/Types.hpp"
0020 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0021 #include "Acts/EventData/VectorTrackContainer.hpp"
0022 #include "Acts/EventData/detail/GenerateParameters.hpp"
0023 #include "Acts/EventData/detail/TestTrackState.hpp"
0024 #include "Acts/Geometry/GeometryContext.hpp"
0025 #include "Acts/Surfaces/PerigeeSurface.hpp"
0026 #include "Acts/Utilities/HashedString.hpp"
0027 #include "Acts/Utilities/Holders.hpp"
0028 
0029 #include <algorithm>
0030 #include <cstddef>
0031 #include <iterator>
0032 #include <memory>
0033 #include <numeric>
0034 #include <random>
0035 #include <stdexcept>
0036 #include <tuple>
0037 #include <type_traits>
0038 #include <utility>
0039 #include <vector>
0040 
0041 namespace {
0042 
0043 using namespace Acts::UnitLiterals;
0044 
0045 using namespace Acts;
0046 using namespace Acts::HashedStringLiteral;
0047 using namespace Acts::detail::Test;
0048 
0049 using IndexType = TrackIndexType;
0050 
0051 const GeometryContext gctx;
0052 // fixed seed for reproducible tests
0053 std::default_random_engine rng(31415);
0054 
0055 // template <template <typename> class holder_t>
0056 // using track_container_t =
0057 // TrackContainer<VectorTrackContainer, VectorMultiTrajectory, holder_t>;
0058 
0059 template <typename track_container_t, typename traj_t,
0060           template <typename> class holder_t>
0061 struct Factory {};
0062 
0063 template <typename track_container_t, typename traj_t>
0064 struct Factory<track_container_t, traj_t, detail::RefHolder> {
0065   using track_container_type =
0066       TrackContainer<track_container_t, traj_t, detail::RefHolder>;
0067 
0068   track_container_t vtc;
0069   traj_t mtj;
0070   track_container_type tc{vtc, mtj};
0071 
0072   auto& trackContainer() { return tc; }
0073   auto& trackStateContainer() { return mtj; }
0074   auto& backend() { return vtc; }
0075 };
0076 
0077 template <typename track_container_t, typename traj_t>
0078 struct Factory<track_container_t, traj_t, detail::ValueHolder> {
0079   using track_container_type =
0080       TrackContainer<track_container_t, traj_t, detail::ValueHolder>;
0081 
0082   track_container_type tc{track_container_t{}, traj_t{}};
0083 
0084   auto& trackContainer() { return tc; }
0085   auto& trackStateContainer() { return tc.trackStateContainer(); }
0086   auto& backend() { return tc.container(); }
0087 };
0088 
0089 template <typename track_container_t, typename traj_t>
0090 struct Factory<track_container_t, traj_t, std::shared_ptr> {
0091   using track_container_type =
0092       TrackContainer<track_container_t, traj_t, std::shared_ptr>;
0093 
0094   std::shared_ptr<track_container_t> vtc{std::make_shared<track_container_t>()};
0095   std::shared_ptr<traj_t> mtj{std::make_shared<traj_t>()};
0096   track_container_type tc{vtc, mtj};
0097 
0098   auto& trackContainer() { return tc; }
0099   auto& trackStateContainer() { return *mtj; }
0100   auto& backend() { return *vtc; }
0101 };
0102 
0103 template <typename track_container_t, typename traj_t,
0104           template <typename> class... holders>
0105 using holder_types_t =
0106     std::tuple<Factory<track_container_t, traj_t, holders>...>;
0107 
0108 using holder_types = holder_types_t<VectorTrackContainer, VectorMultiTrajectory,
0109                                     // detail_tc::ValueHolder,
0110                                     // detail_tc::RefHolder,
0111                                     std::shared_ptr>;
0112 
0113 using const_holder_types =
0114     holder_types_t<ConstVectorTrackContainer, ConstVectorMultiTrajectory,
0115                    detail::ValueHolder, detail::RefHolder, std::shared_ptr>;
0116 
0117 }  // namespace
0118 
0119 namespace ActsTests {
0120 
0121 // Static assert ensuring concept conformity where we have relevant types
0122 // available
0123 static_assert(
0124     ConstTrackProxyConcept<TrackProxy<
0125         VectorTrackContainer, VectorMultiTrajectory, detail::RefHolder, true>>);
0126 static_assert(ConstTrackProxyConcept<
0127               TrackProxy<VectorTrackContainer, VectorMultiTrajectory,
0128                          detail::RefHolder, false>>);
0129 static_assert(MutableTrackProxyConcept<
0130               TrackProxy<VectorTrackContainer, VectorMultiTrajectory,
0131                          detail::RefHolder, false>>);
0132 static_assert(
0133     !MutableTrackProxyConcept<TrackProxy<
0134         VectorTrackContainer, VectorMultiTrajectory, detail::RefHolder, true>>);
0135 
0136 static_assert(ConstTrackStateProxyConcept<
0137               TrackStateProxy<VectorMultiTrajectory, eBoundSize, true>>);
0138 static_assert(!ConstTrackStateProxyConcept<
0139               TrackStateProxy<VectorMultiTrajectory, eBoundSize, false>>);
0140 static_assert(MutableTrackStateProxyConcept<
0141               TrackStateProxy<VectorMultiTrajectory, eBoundSize, false>>);
0142 static_assert(!MutableTrackStateProxyConcept<
0143               TrackStateProxy<VectorMultiTrajectory, eBoundSize, true>>);
0144 
0145 BOOST_AUTO_TEST_SUITE(EventDataSuite)
0146 
0147 BOOST_AUTO_TEST_CASE_TEMPLATE(TrackStateAccess, factory_t, holder_types) {
0148   factory_t factory;
0149   auto& tc = factory.trackContainer();
0150 
0151   VectorMultiTrajectory& traj = factory.trackStateContainer();
0152 
0153   auto mkts = [&](auto prev) {
0154     if constexpr (std::is_same_v<decltype(prev), IndexType>) {
0155       auto ts = traj.makeTrackState(TrackStatePropMask::All, prev);
0156       TestTrackState pc(rng, 2u);
0157       fillTrackState<VectorMultiTrajectory>(pc, TrackStatePropMask::All, ts);
0158       return ts;
0159     } else {
0160       auto ts = traj.makeTrackState(TrackStatePropMask::All, prev.index());
0161       TestTrackState pc(rng, 2u);
0162       fillTrackState<VectorMultiTrajectory>(pc, TrackStatePropMask::All, ts);
0163       return ts;
0164     }
0165   };
0166 
0167   auto ts1 = mkts(kTrackIndexInvalid);
0168   auto ts2 = mkts(ts1);
0169   auto ts3 = mkts(ts2);
0170   auto ts4 = mkts(ts3);
0171   auto ts5 = mkts(ts4);
0172 
0173   auto t = tc.makeTrack();
0174   t.tipIndex() = ts5.index();
0175 
0176   std::vector<IndexType> act;
0177   for (const auto& ts : t.trackStatesReversed()) {
0178     act.push_back(ts.index());
0179   }
0180 
0181   std::vector<IndexType> exp;
0182   exp.resize(5);
0183   std::iota(exp.rbegin(), exp.rend(), 0);
0184   BOOST_CHECK_EQUAL_COLLECTIONS(act.begin(), act.end(), exp.begin(), exp.end());
0185 
0186   const auto& ct = t;
0187 
0188   for (const auto& ts : ct.trackStatesReversed()) {
0189     (void)ts;
0190   }
0191 
0192   BOOST_CHECK_EQUAL(t.nTrackStates(), 5);
0193 
0194   auto tNone = tc.makeTrack();
0195   BOOST_CHECK_EQUAL(tNone.nTrackStates(), 0);
0196 
0197   auto tsRange = tNone.trackStatesReversed();
0198   BOOST_CHECK(tsRange.begin() == tsRange.end());
0199 
0200   std::size_t i = 0;
0201   for (const auto& state : tNone.trackStatesReversed()) {
0202     (void)state;
0203     i++;
0204   }
0205   BOOST_CHECK_EQUAL(i, 0);
0206 }
0207 
0208 BOOST_AUTO_TEST_CASE_TEMPLATE(TrackIterator, factory_t, holder_types) {
0209   factory_t factory;
0210   auto& tc = factory.trackContainer();
0211 
0212   for (unsigned int i = 0; i < 10; i++) {
0213     auto t = tc.makeTrack();
0214     t.tipIndex() = i;
0215   }
0216   BOOST_CHECK_EQUAL(tc.size(), 10);
0217 
0218   unsigned int i = 0;
0219   for (auto track : tc) {
0220     BOOST_CHECK_EQUAL(i, track.tipIndex());
0221     track.parameters().setRandom();
0222     i++;
0223   }
0224 
0225   BOOST_CHECK_EQUAL(std::distance(tc.begin(), tc.end()), tc.size());
0226 }
0227 
0228 BOOST_AUTO_TEST_CASE(IteratorConcept) {
0229   VectorTrackContainer vtc;
0230   VectorMultiTrajectory mtj;
0231   TrackContainer tc{vtc, mtj};
0232 
0233   for (unsigned int i = 0; i < 10; i++) {
0234     auto t = tc.makeTrack();
0235     t.tipIndex() = i;
0236   }
0237   BOOST_CHECK_EQUAL(tc.size(), 10);
0238   BOOST_CHECK_EQUAL(std::distance(tc.begin(), tc.end()), tc.size());
0239 
0240   {
0241     auto it = tc.begin();
0242     BOOST_CHECK(*it == tc.getTrack(0));
0243     ++it;
0244     BOOST_CHECK(*it == tc.getTrack(1));
0245     it += 1;
0246     BOOST_CHECK(*it == tc.getTrack(2));
0247     it -= 1;
0248     BOOST_CHECK(*it == tc.getTrack(1));
0249     ++it;
0250     ++it;
0251     --it;
0252     BOOST_CHECK(*it == tc.getTrack(2));
0253   }
0254   {
0255     auto it = tc.begin();
0256     BOOST_CHECK(*it == tc.getTrack(0));
0257     std::advance(it, 4);
0258     BOOST_CHECK(*it == tc.getTrack(4));
0259     BOOST_CHECK(*(it + (-1)) == tc.getTrack(3));
0260     BOOST_CHECK(*(it + 0) == tc.getTrack(4));
0261     BOOST_CHECK(*(it + 1) == tc.getTrack(5));
0262     BOOST_CHECK(*(it - 2) == tc.getTrack(2));
0263   }
0264 
0265   {
0266     auto it = tc.begin();
0267     auto it4 = it + 4;
0268     auto it5 = it + 5;
0269     auto it6 = it + 6;
0270 
0271     BOOST_CHECK(it4 < it5);
0272     BOOST_CHECK(it5 < it6);
0273     BOOST_CHECK(it4 < it6);
0274 
0275     BOOST_CHECK(it6 > it5);
0276     BOOST_CHECK(it5 > it4);
0277     BOOST_CHECK(it6 > it4);
0278 
0279     BOOST_CHECK(it4 <= it4);
0280     BOOST_CHECK(it4 <= it5);
0281     BOOST_CHECK(it5 <= it5);
0282     BOOST_CHECK(it5 <= it6);
0283 
0284     BOOST_CHECK(it6 >= it6);
0285     BOOST_CHECK(it6 >= it5);
0286   }
0287 }
0288 
0289 BOOST_AUTO_TEST_CASE(ConstCorrectness) {
0290   VectorTrackContainer vtc;
0291   VectorMultiTrajectory mtj;
0292   {
0293     TrackContainer tc{vtc, mtj};
0294 
0295     for (unsigned int i = 0; i < 10; i++) {
0296       auto t = tc.makeTrack();
0297       t.tipIndex() = i;
0298     }
0299 
0300     unsigned int i = 0;
0301     for (auto track : tc) {
0302       BOOST_CHECK_EQUAL(i, track.tipIndex());
0303       track.parameters().setRandom();
0304       i++;
0305     }
0306 
0307     for (const auto track : tc) {
0308       (void)track;
0309       // does not compile
0310       // track.parameters().setRandom();
0311     }
0312   }
0313 
0314   ConstVectorTrackContainer cvtc{std::move(vtc)};
0315   ConstVectorMultiTrajectory cmtj{std::move(mtj)};
0316   {
0317     TrackContainer tc{cvtc, cmtj};
0318 
0319     unsigned int i = 0;
0320     for (auto track : tc) {
0321       BOOST_CHECK_EQUAL(i, track.tipIndex());
0322       i++;
0323       // does not compile
0324       // track.parameters().setRandom();
0325     }
0326   }
0327 }
0328 
0329 BOOST_AUTO_TEST_CASE(BuildFromConstRef) {
0330   VectorTrackContainer mutVtc;
0331   VectorMultiTrajectory mutMtj;
0332 
0333   TrackContainer mutTc{mutVtc, mutMtj};
0334   static_assert(!mutTc.ReadOnly, "Unexpectedly read only");
0335 
0336   auto t = mutTc.makeTrack();
0337   t.appendTrackState();
0338   t.appendTrackState();
0339   t.appendTrackState();
0340   t = mutTc.makeTrack();
0341   t.appendTrackState();
0342   std::cout << "New track with l0: " << t.loc0() << ", l1: " << t.loc1()
0343             << ", phi: " << t.phi() << ", theta: " << t.theta()
0344             << ", q/p: " << t.qOverP() << ", q: " << t.charge()
0345             << ", P: " << t.absoluteMomentum()
0346             << ", pT: " << t.transverseMomentum()
0347             << ", direction: " << t.direction().transpose()
0348             << ", mom: " << t.momentum().transpose()
0349             << ", p4: " << t.fourMomentum() << ", nStates: " << t.nTrackStates()
0350             << ", nMeasurements: " << t.nMeasurements()
0351             << ", nHoles: " << t.nHoles() << ", nOutlier: " << t.nOutliers()
0352             << ", nShared: " << t.nSharedHits() << ", chi2: " << t.chi2()
0353             << ", nDoF: " << t.nDoF() << std::endl;
0354 
0355   BOOST_CHECK_EQUAL(mutTc.size(), 2);
0356   BOOST_CHECK_EQUAL(mutMtj.size(), 4);
0357 
0358   ConstVectorTrackContainer vtc{std::move(mutVtc)};
0359   ConstVectorMultiTrajectory mtj{std::move(mutMtj)};
0360 
0361   // moved from
0362   BOOST_CHECK_EQUAL(mutTc.size(), 0);
0363   BOOST_CHECK_EQUAL(mutMtj.size(), 0);
0364 
0365   TrackContainer ctc{vtc, mtj};
0366   static_assert(ctc.ReadOnly, "Unexpectedly not read only");
0367 
0368   // Does not compile:
0369   // ctc.addTrack();
0370 
0371   BOOST_CHECK_EQUAL(ctc.size(), 2);
0372   BOOST_CHECK_EQUAL(mtj.size(), 4);
0373 
0374   const auto& cvtc = vtc;
0375   const auto& cmtj = mtj;
0376 
0377   TrackContainer crtc{cvtc, cmtj};
0378 
0379   BOOST_CHECK_EQUAL(crtc.size(), 2);
0380   BOOST_CHECK_EQUAL(cmtj.size(), 4);
0381 
0382   // Does not compile: holder deduced to ConstRefHolder, but is not RO
0383   // const auto& mrvtc = mutVtc;
0384   // const auto& mrmtj = mutMtj;
0385   // TrackContainer mrtc{mrvtc, mrmtj};
0386   // static_assert(ctc.ReadOnly, "Unexpectedly not read only");
0387   // mrtc.addTrack();
0388 }
0389 
0390 BOOST_AUTO_TEST_CASE_TEMPLATE(BuildReadOnly, factory_t, const_holder_types) {
0391   factory_t factory;
0392   auto& tc = factory.trackContainer();
0393 
0394   static_assert(std::is_same_v<std::decay_t<decltype(tc)>,
0395                                typename factory_t::track_container_type>,
0396                 "Incorrect deduction");
0397 
0398   static_assert(std::decay_t<decltype(tc)>::ReadOnly, "Should be read only");
0399   BOOST_CHECK(tc.ReadOnly);
0400 }
0401 
0402 BOOST_AUTO_TEST_CASE_TEMPLATE(DynamicColumns, factory_t, holder_types) {
0403   factory_t factory;
0404   auto& tc = factory.trackContainer();
0405 
0406   BOOST_CHECK(!tc.hasColumn("col_a"_hash));
0407   tc.template addColumn<float>("col_a");
0408   BOOST_CHECK(tc.hasColumn("col_a"_hash));
0409 
0410   auto t = tc.makeTrack();
0411   t.template component<float>("col_a") = 5.6f;
0412   BOOST_CHECK_EQUAL((t.template component<float, "col_a"_hash>()), 5.6f);
0413 }
0414 
0415 BOOST_AUTO_TEST_CASE(EnsureDynamicColumns) {
0416   TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0417   tc.addColumn<std::size_t>("counter");
0418   tc.addColumn<bool>("odd");
0419 
0420   BOOST_CHECK(tc.hasColumn("counter"));
0421   BOOST_CHECK(tc.hasColumn("odd"));
0422 
0423   TrackContainer tc2{VectorTrackContainer{}, VectorMultiTrajectory{}};
0424 
0425   BOOST_CHECK(!tc2.hasColumn("counter"));
0426   BOOST_CHECK(!tc2.hasColumn("odd"));
0427 
0428   tc2.ensureDynamicColumns(tc);
0429 
0430   BOOST_CHECK(tc2.hasColumn("counter"));
0431   BOOST_CHECK(tc2.hasColumn("odd"));
0432 }
0433 
0434 BOOST_AUTO_TEST_CASE(AppendTrackState) {
0435   TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0436   auto t = tc.makeTrack();
0437 
0438   std::vector<VectorMultiTrajectory::TrackStateProxy> trackStates;
0439   trackStates.push_back(t.appendTrackState());
0440   trackStates.push_back(t.appendTrackState());
0441   trackStates.push_back(t.appendTrackState());
0442   trackStates.push_back(t.appendTrackState());
0443   trackStates.push_back(t.appendTrackState());
0444   trackStates.push_back(t.appendTrackState());
0445 
0446   BOOST_CHECK_EQUAL(trackStates.size(), t.nTrackStates());
0447 
0448   for (std::size_t i = trackStates.size() - 1; i > 0; i--) {
0449     BOOST_CHECK_EQUAL(trackStates.at(i).index(), i);
0450   }
0451 }
0452 
0453 BOOST_AUTO_TEST_CASE(ForwardIteration) {
0454   TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0455   {
0456     // let's create an unrelated track first
0457     auto t = tc.makeTrack();
0458     for (std::size_t i = 0; i < 10; i++) {
0459       t.appendTrackState();
0460     }
0461   }
0462 
0463   auto t = tc.makeTrack();
0464 
0465   auto stem = t.appendTrackState();
0466   t.appendTrackState();
0467   t.appendTrackState();
0468   t.appendTrackState();
0469   t.appendTrackState();
0470 
0471   BOOST_CHECK_THROW(t.trackStates(), std::invalid_argument);
0472   BOOST_CHECK(!t.innermostTrackState().has_value());
0473 
0474   t.linkForward();
0475 
0476   BOOST_CHECK_EQUAL(t.stemIndex(), stem.index());
0477   BOOST_CHECK_EQUAL(t.innermostTrackState().value().index(), stem.index());
0478   t.innermostTrackState()->predicted().setRandom();
0479 
0480   std::vector<IndexType> indices;
0481   for (const auto& ts : t.trackStatesReversed()) {
0482     indices.push_back(ts.index());
0483   }
0484 
0485   std::ranges::reverse(indices);
0486 
0487   std::vector<IndexType> act;
0488   for (auto ts : t.trackStates()) {
0489     act.push_back(ts.index());
0490     ts.predicted().setRandom();
0491   }
0492 
0493   BOOST_CHECK_EQUAL_COLLECTIONS(indices.begin(), indices.end(), act.begin(),
0494                                 act.end());
0495 
0496   t.reverseTrackStates();
0497   BOOST_CHECK_EQUAL(t.innermostTrackState().value().index(), indices.back());
0498   t.innermostTrackState()->predicted().setRandom();
0499 
0500   act.clear();
0501   for (const auto& ts : t.trackStates()) {
0502     act.push_back(ts.index());
0503   }
0504 
0505   BOOST_CHECK_EQUAL_COLLECTIONS(indices.rbegin(), indices.rend(), act.begin(),
0506                                 act.end());
0507 }
0508 
0509 BOOST_AUTO_TEST_CASE(ShallowCopy) {
0510   TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0511   auto t = tc.makeTrack();
0512 
0513   auto perigee =
0514       Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3::Zero());
0515 
0516   t.parameters().setRandom();
0517   t.covariance().setRandom();
0518   t.particleHypothesis() = Acts::ParticleHypothesis::pion();
0519   t.setReferenceSurface(perigee);
0520 
0521   auto ts1 = t.appendTrackState();
0522   ts1.predicted().setRandom();
0523   auto ts2 = t.appendTrackState();
0524   ts2.predicted().setRandom();
0525   auto ts3 = t.appendTrackState();
0526   ts3.predicted().setRandom();
0527 
0528   auto t2 = tc.makeTrack();
0529   t2.copyFromShallow(t);
0530 
0531   BOOST_CHECK_NE(t.index(), t2.index());
0532   BOOST_CHECK_EQUAL(t.nTrackStates(), t2.nTrackStates());
0533 
0534   BOOST_CHECK_EQUAL(t.particleHypothesis(), t2.particleHypothesis());
0535   BOOST_CHECK_EQUAL(t.parameters(), t2.parameters());
0536   BOOST_CHECK_EQUAL(t.covariance(), t2.covariance());
0537 
0538   BOOST_CHECK_EQUAL(t.referenceSurface().getSharedPtr(),
0539                     t2.referenceSurface().getSharedPtr());
0540   BOOST_CHECK_EQUAL(t.tipIndex(), t2.tipIndex());
0541 
0542   std::vector<decltype(tc)::TrackStateProxy> trackStates;
0543   for (const auto& ts : t.trackStatesReversed()) {
0544     trackStates.insert(trackStates.begin(), ts);
0545   }
0546 
0547   auto t2_ts1 = trackStates.at(0);
0548   auto t2_ts2 = trackStates.at(1);
0549   auto t2_ts3 = trackStates.at(2);
0550 
0551   BOOST_CHECK_EQUAL(t2_ts1.predicted(), ts1.predicted());
0552   BOOST_CHECK_EQUAL(t2_ts1.index(), ts1.index());
0553   BOOST_CHECK_EQUAL(t2_ts2.predicted(), ts2.predicted());
0554   BOOST_CHECK_EQUAL(t2_ts2.index(), ts2.index());
0555   BOOST_CHECK_EQUAL(t2_ts3.predicted(), ts3.predicted());
0556   BOOST_CHECK_EQUAL(t2_ts3.index(), ts3.index());
0557 }
0558 
0559 BOOST_AUTO_TEST_SUITE_END()
0560 
0561 }  // namespace ActsTests