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