File indexing completed on 2025-09-18 08:13:54
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 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
0283
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
0297
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
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
0330
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
0344
0345
0346
0347
0348
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
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()