Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-17 09:21:46

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