File indexing completed on 2025-12-17 09:21:46
0001
0002
0003
0004
0005
0006
0007
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
0052 std::default_random_engine rng(31415);
0053
0054
0055
0056
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
0109
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 }
0117
0118 namespace ActsTests {
0119
0120
0121
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
0309
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
0323
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
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
0368
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
0382
0383
0384
0385
0386
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
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 }