Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:13:54

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 BOOST_AUTO_TEST_SUITE(EventDataTrack)
0119 
0120 BOOST_AUTO_TEST_CASE_TEMPLATE(TrackStateAccess, factory_t, holder_types) {
0121   factory_t factory;
0122   auto& tc = factory.trackContainer();
0123 
0124   VectorMultiTrajectory& traj = factory.trackStateContainer();
0125 
0126   auto mkts = [&](auto prev) {
0127     if constexpr (std::is_same_v<decltype(prev), IndexType>) {
0128       auto ts = traj.makeTrackState(TrackStatePropMask::All, prev);
0129       TestTrackState pc(rng, 2u);
0130       fillTrackState<VectorMultiTrajectory>(pc, TrackStatePropMask::All, ts);
0131       return ts;
0132     } else {
0133       auto ts = traj.makeTrackState(TrackStatePropMask::All, prev.index());
0134       TestTrackState pc(rng, 2u);
0135       fillTrackState<VectorMultiTrajectory>(pc, TrackStatePropMask::All, ts);
0136       return ts;
0137     }
0138   };
0139 
0140   auto ts1 = mkts(MultiTrajectoryTraits::kInvalid);
0141   auto ts2 = mkts(ts1);
0142   auto ts3 = mkts(ts2);
0143   auto ts4 = mkts(ts3);
0144   auto ts5 = mkts(ts4);
0145 
0146   auto t = tc.makeTrack();
0147   t.tipIndex() = ts5.index();
0148 
0149   std::vector<IndexType> act;
0150   for (const auto& ts : t.trackStatesReversed()) {
0151     act.push_back(ts.index());
0152   }
0153 
0154   std::vector<IndexType> exp;
0155   exp.resize(5);
0156   std::iota(exp.rbegin(), exp.rend(), 0);
0157   BOOST_CHECK_EQUAL_COLLECTIONS(act.begin(), act.end(), exp.begin(), exp.end());
0158 
0159   const auto& ct = t;
0160 
0161   for (const auto& ts : ct.trackStatesReversed()) {
0162     (void)ts;
0163   }
0164 
0165   BOOST_CHECK_EQUAL(t.nTrackStates(), 5);
0166 
0167   auto tNone = tc.makeTrack();
0168   BOOST_CHECK_EQUAL(tNone.nTrackStates(), 0);
0169 
0170   auto tsRange = tNone.trackStatesReversed();
0171   BOOST_CHECK(tsRange.begin() == tsRange.end());
0172 
0173   std::size_t i = 0;
0174   for (const auto& state : tNone.trackStatesReversed()) {
0175     (void)state;
0176     i++;
0177   }
0178   BOOST_CHECK_EQUAL(i, 0);
0179 }
0180 
0181 BOOST_AUTO_TEST_CASE_TEMPLATE(TrackIterator, factory_t, holder_types) {
0182   factory_t factory;
0183   auto& tc = factory.trackContainer();
0184 
0185   for (unsigned int i = 0; i < 10; i++) {
0186     auto t = tc.makeTrack();
0187     t.tipIndex() = i;
0188   }
0189   BOOST_CHECK_EQUAL(tc.size(), 10);
0190 
0191   unsigned int i = 0;
0192   for (auto track : tc) {
0193     BOOST_CHECK_EQUAL(i, track.tipIndex());
0194     track.parameters().setRandom();
0195     i++;
0196   }
0197 
0198   BOOST_CHECK_EQUAL(std::distance(tc.begin(), tc.end()), tc.size());
0199 }
0200 
0201 BOOST_AUTO_TEST_CASE(IteratorConcept) {
0202   VectorTrackContainer vtc;
0203   VectorMultiTrajectory mtj;
0204   TrackContainer tc{vtc, mtj};
0205 
0206   for (unsigned int i = 0; i < 10; i++) {
0207     auto t = tc.makeTrack();
0208     t.tipIndex() = i;
0209   }
0210   BOOST_CHECK_EQUAL(tc.size(), 10);
0211   BOOST_CHECK_EQUAL(std::distance(tc.begin(), tc.end()), tc.size());
0212 
0213   {
0214     auto it = tc.begin();
0215     BOOST_CHECK(*it == tc.getTrack(0));
0216     ++it;
0217     BOOST_CHECK(*it == tc.getTrack(1));
0218     it += 1;
0219     BOOST_CHECK(*it == tc.getTrack(2));
0220     it -= 1;
0221     BOOST_CHECK(*it == tc.getTrack(1));
0222     ++it;
0223     ++it;
0224     --it;
0225     BOOST_CHECK(*it == tc.getTrack(2));
0226   }
0227   {
0228     auto it = tc.begin();
0229     BOOST_CHECK(*it == tc.getTrack(0));
0230     std::advance(it, 4);
0231     BOOST_CHECK(*it == tc.getTrack(4));
0232     BOOST_CHECK(*(it + (-1)) == tc.getTrack(3));
0233     BOOST_CHECK(*(it + 0) == tc.getTrack(4));
0234     BOOST_CHECK(*(it + 1) == tc.getTrack(5));
0235     BOOST_CHECK(*(it - 2) == tc.getTrack(2));
0236   }
0237 
0238   {
0239     auto it = tc.begin();
0240     auto it4 = it + 4;
0241     auto it5 = it + 5;
0242     auto it6 = it + 6;
0243 
0244     BOOST_CHECK(it4 < it5);
0245     BOOST_CHECK(it5 < it6);
0246     BOOST_CHECK(it4 < it6);
0247 
0248     BOOST_CHECK(it6 > it5);
0249     BOOST_CHECK(it5 > it4);
0250     BOOST_CHECK(it6 > it4);
0251 
0252     BOOST_CHECK(it4 <= it4);
0253     BOOST_CHECK(it4 <= it5);
0254     BOOST_CHECK(it5 <= it5);
0255     BOOST_CHECK(it5 <= it6);
0256 
0257     BOOST_CHECK(it6 >= it6);
0258     BOOST_CHECK(it6 >= it5);
0259   }
0260 }
0261 
0262 BOOST_AUTO_TEST_CASE(ConstCorrectness) {
0263   VectorTrackContainer vtc;
0264   VectorMultiTrajectory mtj;
0265   {
0266     TrackContainer tc{vtc, mtj};
0267 
0268     for (unsigned int i = 0; i < 10; i++) {
0269       auto t = tc.makeTrack();
0270       t.tipIndex() = i;
0271     }
0272 
0273     unsigned int i = 0;
0274     for (auto track : tc) {
0275       BOOST_CHECK_EQUAL(i, track.tipIndex());
0276       track.parameters().setRandom();
0277       i++;
0278     }
0279 
0280     for (const auto track : tc) {
0281       (void)track;
0282       // does not compile
0283       // track.parameters().setRandom();
0284     }
0285   }
0286 
0287   ConstVectorTrackContainer cvtc{std::move(vtc)};
0288   ConstVectorMultiTrajectory cmtj{std::move(mtj)};
0289   {
0290     TrackContainer tc{cvtc, cmtj};
0291 
0292     unsigned int i = 0;
0293     for (auto track : tc) {
0294       BOOST_CHECK_EQUAL(i, track.tipIndex());
0295       i++;
0296       // does not compile
0297       // track.parameters().setRandom();
0298     }
0299   }
0300 }
0301 
0302 BOOST_AUTO_TEST_CASE(BuildFromConstRef) {
0303   VectorTrackContainer mutVtc;
0304   VectorMultiTrajectory mutMtj;
0305 
0306   TrackContainer mutTc{mutVtc, mutMtj};
0307   static_assert(!mutTc.ReadOnly, "Unexpectedly read only");
0308 
0309   auto t = mutTc.makeTrack();
0310   t.appendTrackState();
0311   t.appendTrackState();
0312   t.appendTrackState();
0313   t = mutTc.makeTrack();
0314   t.appendTrackState();
0315 
0316   BOOST_CHECK_EQUAL(mutTc.size(), 2);
0317   BOOST_CHECK_EQUAL(mutMtj.size(), 4);
0318 
0319   ConstVectorTrackContainer vtc{std::move(mutVtc)};
0320   ConstVectorMultiTrajectory mtj{std::move(mutMtj)};
0321 
0322   // moved from
0323   BOOST_CHECK_EQUAL(mutTc.size(), 0);
0324   BOOST_CHECK_EQUAL(mutMtj.size(), 0);
0325 
0326   TrackContainer ctc{vtc, mtj};
0327   static_assert(ctc.ReadOnly, "Unexpectedly not read only");
0328 
0329   // Does not compile:
0330   // ctc.addTrack();
0331 
0332   BOOST_CHECK_EQUAL(ctc.size(), 2);
0333   BOOST_CHECK_EQUAL(mtj.size(), 4);
0334 
0335   const auto& cvtc = vtc;
0336   const auto& cmtj = mtj;
0337 
0338   TrackContainer crtc{cvtc, cmtj};
0339 
0340   BOOST_CHECK_EQUAL(crtc.size(), 2);
0341   BOOST_CHECK_EQUAL(cmtj.size(), 4);
0342 
0343   // Does not compile: holder deduced to ConstRefHolder, but is not RO
0344   // const auto& mrvtc = mutVtc;
0345   // const auto& mrmtj = mutMtj;
0346   // TrackContainer mrtc{mrvtc, mrmtj};
0347   // static_assert(ctc.ReadOnly, "Unexpectedly not read only");
0348   // mrtc.addTrack();
0349 }
0350 
0351 BOOST_AUTO_TEST_CASE_TEMPLATE(BuildReadOnly, factory_t, const_holder_types) {
0352   factory_t factory;
0353   auto& tc = factory.trackContainer();
0354 
0355   static_assert(std::is_same_v<std::decay_t<decltype(tc)>,
0356                                typename factory_t::track_container_type>,
0357                 "Incorrect deduction");
0358 
0359   static_assert(std::decay_t<decltype(tc)>::ReadOnly, "Should be read only");
0360   BOOST_CHECK(tc.ReadOnly);
0361 }
0362 
0363 BOOST_AUTO_TEST_CASE_TEMPLATE(DynamicColumns, factory_t, holder_types) {
0364   factory_t factory;
0365   auto& tc = factory.trackContainer();
0366 
0367   BOOST_CHECK(!tc.hasColumn("col_a"_hash));
0368   tc.template addColumn<float>("col_a");
0369   BOOST_CHECK(tc.hasColumn("col_a"_hash));
0370 
0371   auto t = tc.makeTrack();
0372   t.template component<float>("col_a") = 5.6f;
0373   BOOST_CHECK_EQUAL((t.template component<float, "col_a"_hash>()), 5.6f);
0374 }
0375 
0376 BOOST_AUTO_TEST_CASE(EnsureDynamicColumns) {
0377   TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0378   tc.addColumn<std::size_t>("counter");
0379   tc.addColumn<bool>("odd");
0380 
0381   BOOST_CHECK(tc.hasColumn("counter"));
0382   BOOST_CHECK(tc.hasColumn("odd"));
0383 
0384   TrackContainer tc2{VectorTrackContainer{}, VectorMultiTrajectory{}};
0385 
0386   BOOST_CHECK(!tc2.hasColumn("counter"));
0387   BOOST_CHECK(!tc2.hasColumn("odd"));
0388 
0389   tc2.ensureDynamicColumns(tc);
0390 
0391   BOOST_CHECK(tc2.hasColumn("counter"));
0392   BOOST_CHECK(tc2.hasColumn("odd"));
0393 }
0394 
0395 BOOST_AUTO_TEST_CASE(AppendTrackState) {
0396   TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0397   auto t = tc.makeTrack();
0398 
0399   std::vector<VectorMultiTrajectory::TrackStateProxy> trackStates;
0400   trackStates.push_back(t.appendTrackState());
0401   trackStates.push_back(t.appendTrackState());
0402   trackStates.push_back(t.appendTrackState());
0403   trackStates.push_back(t.appendTrackState());
0404   trackStates.push_back(t.appendTrackState());
0405   trackStates.push_back(t.appendTrackState());
0406 
0407   BOOST_CHECK_EQUAL(trackStates.size(), t.nTrackStates());
0408 
0409   for (std::size_t i = trackStates.size() - 1; i > 0; i--) {
0410     BOOST_CHECK_EQUAL(trackStates.at(i).index(), i);
0411   }
0412 }
0413 
0414 BOOST_AUTO_TEST_CASE(ForwardIteration) {
0415   TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0416   {
0417     // let's create an unrelated track first
0418     auto t = tc.makeTrack();
0419     for (std::size_t i = 0; i < 10; i++) {
0420       t.appendTrackState();
0421     }
0422   }
0423 
0424   auto t = tc.makeTrack();
0425 
0426   auto stem = t.appendTrackState();
0427   t.appendTrackState();
0428   t.appendTrackState();
0429   t.appendTrackState();
0430   t.appendTrackState();
0431 
0432   BOOST_CHECK_THROW(t.trackStates(), std::invalid_argument);
0433   BOOST_CHECK(!t.innermostTrackState().has_value());
0434 
0435   t.linkForward();
0436 
0437   BOOST_CHECK_EQUAL(t.stemIndex(), stem.index());
0438   BOOST_CHECK_EQUAL(t.innermostTrackState().value().index(), stem.index());
0439   t.innermostTrackState()->predicted().setRandom();
0440 
0441   std::vector<IndexType> indices;
0442   for (const auto& ts : t.trackStatesReversed()) {
0443     indices.push_back(ts.index());
0444   }
0445 
0446   std::ranges::reverse(indices);
0447 
0448   std::vector<IndexType> act;
0449   for (auto ts : t.trackStates()) {
0450     act.push_back(ts.index());
0451     ts.predicted().setRandom();
0452   }
0453 
0454   BOOST_CHECK_EQUAL_COLLECTIONS(indices.begin(), indices.end(), act.begin(),
0455                                 act.end());
0456 
0457   t.reverseTrackStates();
0458   BOOST_CHECK_EQUAL(t.innermostTrackState().value().index(), indices.back());
0459   t.innermostTrackState()->predicted().setRandom();
0460 
0461   act.clear();
0462   for (const auto& ts : t.trackStates()) {
0463     act.push_back(ts.index());
0464   }
0465 
0466   BOOST_CHECK_EQUAL_COLLECTIONS(indices.rbegin(), indices.rend(), act.begin(),
0467                                 act.end());
0468 }
0469 
0470 BOOST_AUTO_TEST_CASE(ShallowCopy) {
0471   TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0472   auto t = tc.makeTrack();
0473 
0474   auto perigee =
0475       Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3::Zero());
0476 
0477   t.parameters().setRandom();
0478   t.covariance().setRandom();
0479   t.particleHypothesis() = Acts::ParticleHypothesis::pion();
0480   t.setReferenceSurface(perigee);
0481 
0482   auto ts1 = t.appendTrackState();
0483   ts1.predicted().setRandom();
0484   auto ts2 = t.appendTrackState();
0485   ts2.predicted().setRandom();
0486   auto ts3 = t.appendTrackState();
0487   ts3.predicted().setRandom();
0488 
0489   auto t2 = tc.makeTrack();
0490   t2.copyFromShallow(t);
0491 
0492   BOOST_CHECK_NE(t.index(), t2.index());
0493   BOOST_CHECK_EQUAL(t.nTrackStates(), t2.nTrackStates());
0494 
0495   BOOST_CHECK_EQUAL(t.particleHypothesis(), t2.particleHypothesis());
0496   BOOST_CHECK_EQUAL(t.parameters(), t2.parameters());
0497   BOOST_CHECK_EQUAL(t.covariance(), t2.covariance());
0498 
0499   BOOST_CHECK_EQUAL(t.referenceSurface().getSharedPtr(),
0500                     t2.referenceSurface().getSharedPtr());
0501   BOOST_CHECK_EQUAL(t.tipIndex(), t2.tipIndex());
0502 
0503   std::vector<decltype(tc)::TrackStateProxy> trackStates;
0504   for (const auto& ts : t.trackStatesReversed()) {
0505     trackStates.insert(trackStates.begin(), ts);
0506   }
0507 
0508   auto t2_ts1 = trackStates.at(0);
0509   auto t2_ts2 = trackStates.at(1);
0510   auto t2_ts3 = trackStates.at(2);
0511 
0512   BOOST_CHECK_EQUAL(t2_ts1.predicted(), ts1.predicted());
0513   BOOST_CHECK_EQUAL(t2_ts1.index(), ts1.index());
0514   BOOST_CHECK_EQUAL(t2_ts2.predicted(), ts2.predicted());
0515   BOOST_CHECK_EQUAL(t2_ts2.index(), ts2.index());
0516   BOOST_CHECK_EQUAL(t2_ts3.predicted(), ts3.predicted());
0517   BOOST_CHECK_EQUAL(t2_ts3.index(), ts3.index());
0518 }
0519 
0520 BOOST_AUTO_TEST_SUITE_END()