Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:35

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/Units.hpp"
0012 #include "Acts/EventData/ProxyAccessor.hpp"
0013 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0014 #include "Acts/EventData/VectorTrackContainer.hpp"
0015 #include "Acts/Surfaces/CurvilinearSurface.hpp"
0016 #include "Acts/Surfaces/PlaneSurface.hpp"
0017 #include "Acts/Utilities/Zip.hpp"
0018 
0019 #include <algorithm>
0020 #include <numeric>
0021 
0022 using namespace Acts;
0023 using namespace Acts::HashedStringLiteral;
0024 using MultiTrajectoryTraits::IndexType;
0025 using namespace Acts::UnitLiterals;
0026 
0027 template <typename track_container_t, typename traj_t,
0028           template <typename> class holder_t>
0029 struct Factory {};
0030 
0031 template <typename track_container_t, typename traj_t>
0032 struct Factory<track_container_t, traj_t, detail::RefHolder> {
0033   using track_container_type =
0034       TrackContainer<track_container_t, traj_t, detail::RefHolder>;
0035 
0036   track_container_t vtc;
0037   traj_t mtj;
0038   track_container_type tc{vtc, mtj};
0039 
0040   auto& trackContainer() { return tc; }
0041   auto& trackStateContainer() { return mtj; }
0042   auto& backend() { return vtc; }
0043 };
0044 
0045 template <typename track_container_t, typename traj_t>
0046 struct Factory<track_container_t, traj_t, detail::ValueHolder> {
0047   using track_container_type =
0048       TrackContainer<track_container_t, traj_t, detail::ValueHolder>;
0049 
0050   track_container_type tc{track_container_t{}, traj_t{}};
0051 
0052   auto& trackContainer() { return tc; }
0053   auto& trackStateContainer() { return tc.trackStateContainer(); }
0054   auto& backend() { return tc.container(); }
0055 };
0056 
0057 template <typename track_container_t, typename traj_t>
0058 struct Factory<track_container_t, traj_t, std::shared_ptr> {
0059   using track_container_type =
0060       TrackContainer<track_container_t, traj_t, std::shared_ptr>;
0061 
0062   std::shared_ptr<track_container_t> vtc{std::make_shared<track_container_t>()};
0063   std::shared_ptr<traj_t> mtj{std::make_shared<traj_t>()};
0064   track_container_type tc{vtc, mtj};
0065 
0066   auto& trackContainer() { return tc; }
0067   auto& trackStateContainer() { return *mtj; }
0068   auto& backend() { return *vtc; }
0069 };
0070 
0071 template <typename track_container_t, typename traj_t,
0072           template <typename> class... holders>
0073 using holder_types_t =
0074     std::tuple<Factory<track_container_t, traj_t, holders>...>;
0075 
0076 using holder_types = holder_types_t<VectorTrackContainer, VectorMultiTrajectory,
0077                                     // detail_tc::ValueHolder,
0078                                     // detail_tc::RefHolder,
0079                                     std::shared_ptr>;
0080 
0081 using const_holder_types =
0082     holder_types_t<ConstVectorTrackContainer, ConstVectorMultiTrajectory,
0083                    detail::ValueHolder, detail::RefHolder, std::shared_ptr>;
0084 
0085 BOOST_AUTO_TEST_SUITE(EventDataTrack)
0086 
0087 BOOST_AUTO_TEST_CASE(BuildDefaultHolder) {
0088   VectorMultiTrajectory mtj{};
0089   VectorTrackContainer vtc{};
0090   TrackContainer tc{vtc, mtj};
0091 
0092   static_assert(
0093       std::is_same_v<decltype(tc),
0094                      TrackContainer<VectorTrackContainer, VectorMultiTrajectory,
0095                                     detail::RefHolder>>,
0096       "Incorrect deduced type");
0097   BOOST_CHECK_EQUAL(&mtj, &tc.trackStateContainer());
0098   BOOST_CHECK_EQUAL(&vtc, &tc.container());
0099   tc.addTrack();
0100 
0101   std::decay_t<decltype(tc)> copy = tc;
0102   BOOST_CHECK_EQUAL(&mtj, &copy.trackStateContainer());
0103   BOOST_CHECK_EQUAL(&vtc, &copy.container());
0104 }
0105 
0106 BOOST_AUTO_TEST_CASE(BuildValueHolder) {
0107   {
0108     VectorMultiTrajectory mtj{};
0109     VectorTrackContainer vtc{};
0110     TrackContainer tc{std::move(vtc), std::move(mtj)};
0111     static_assert(
0112         std::is_same_v<decltype(tc), TrackContainer<VectorTrackContainer,
0113                                                     VectorMultiTrajectory,
0114                                                     detail::ValueHolder>>,
0115         "Incorrect deduced type");
0116     std::decay_t<decltype(tc)> copy = tc;
0117     BOOST_CHECK_NE(&tc.trackStateContainer(), &copy.trackStateContainer());
0118     BOOST_CHECK_NE(&tc.container(), &copy.container());
0119   }
0120   {
0121     TrackContainer tc{VectorTrackContainer{}, VectorMultiTrajectory{}};
0122 
0123     static_assert(
0124         std::is_same_v<decltype(tc), TrackContainer<VectorTrackContainer,
0125                                                     VectorMultiTrajectory,
0126                                                     detail::ValueHolder>>,
0127         "Incorrect deduced type");
0128     tc.addTrack();
0129     std::decay_t<decltype(tc)> copy = tc;
0130     BOOST_CHECK_NE(&tc.trackStateContainer(), &copy.trackStateContainer());
0131     BOOST_CHECK_NE(&tc.container(), &copy.container());
0132   }
0133 }
0134 
0135 BOOST_AUTO_TEST_CASE(BuildRefHolder) {
0136   VectorMultiTrajectory mtj{};
0137   VectorTrackContainer vtc{};
0138   TrackContainer<VectorTrackContainer, VectorMultiTrajectory, detail::RefHolder>
0139       tc{vtc, mtj};
0140 
0141   static_assert(
0142       std::is_same_v<decltype(tc),
0143                      TrackContainer<VectorTrackContainer, VectorMultiTrajectory,
0144                                     detail::RefHolder>>,
0145       "Incorrect deduced type");
0146   BOOST_CHECK_EQUAL(&mtj, &tc.trackStateContainer());
0147   BOOST_CHECK_EQUAL(&vtc, &tc.container());
0148   tc.addTrack();
0149   std::decay_t<decltype(tc)> copy = tc;
0150   BOOST_CHECK_EQUAL(&mtj, &copy.trackStateContainer());
0151   BOOST_CHECK_EQUAL(&vtc, &copy.container());
0152 }
0153 
0154 BOOST_AUTO_TEST_CASE(BuildSharedPtr) {
0155   auto mtj = std::make_shared<VectorMultiTrajectory>();
0156   auto vtc = std::make_shared<VectorTrackContainer>();
0157   TrackContainer<VectorTrackContainer, VectorMultiTrajectory, std::shared_ptr>
0158       tc{vtc, mtj};
0159 
0160   static_assert(
0161       std::is_same_v<decltype(tc),
0162                      TrackContainer<VectorTrackContainer, VectorMultiTrajectory,
0163                                     std::shared_ptr>>,
0164       "Incorrect deduced type");
0165   BOOST_CHECK_EQUAL(mtj.get(), &tc.trackStateContainer());
0166   BOOST_CHECK_EQUAL(vtc.get(), &tc.container());
0167   tc.addTrack();
0168   std::decay_t<decltype(tc)> copy = tc;
0169   BOOST_CHECK_EQUAL(mtj.get(), &copy.trackStateContainer());
0170   BOOST_CHECK_EQUAL(vtc.get(), &copy.container());
0171 }
0172 
0173 BOOST_AUTO_TEST_CASE(BuildConvenience) {
0174   VectorMultiTrajectory mtj{};
0175   VectorTrackContainer vtc{};
0176   TrackContainer tc{vtc, mtj};
0177 
0178   BOOST_CHECK_EQUAL(tc.size(), 0);
0179   auto track1 = tc.makeTrack();
0180   BOOST_CHECK_EQUAL(tc.size(), 1);
0181   auto track2 = tc.makeTrack();
0182   BOOST_CHECK_EQUAL(tc.size(), 2);
0183 
0184   BOOST_CHECK_EQUAL(track1.index(), 0);
0185   BOOST_CHECK_EQUAL(track2.index(), 1);
0186 }
0187 
0188 BOOST_AUTO_TEST_CASE_TEMPLATE(Build, factory_t, holder_types) {
0189   factory_t factory;
0190 
0191   auto& tc = factory.trackContainer();
0192 
0193   static_assert(std::is_same_v<std::decay_t<decltype(tc)>,
0194                                typename factory_t::track_container_type>,
0195                 "Incorrect deduction");
0196 
0197   static_assert(!std::decay_t<decltype(tc)>::ReadOnly,
0198                 "Should not be read only");
0199   BOOST_CHECK(!tc.ReadOnly);
0200 
0201   auto idx = tc.addTrack();
0202   auto t = tc.getTrack(idx);
0203   auto t2 = tc.getTrack(idx);
0204   t.template component<IndexType, "tipIndex"_hash>() = 5;
0205 
0206   BOOST_CHECK_EQUAL((t.template component<IndexType, "tipIndex"_hash>()), 5);
0207   BOOST_CHECK_EQUAL(t.tipIndex(), 5);
0208   t.tipIndex() = 6;
0209   BOOST_CHECK_EQUAL(t.tipIndex(), 6);
0210 
0211   BoundVector pars;
0212   pars.setRandom();
0213   t.parameters() = pars;
0214   BOOST_CHECK_EQUAL(t.parameters(), pars);
0215 
0216   BoundMatrix cov;
0217   cov.setRandom();
0218   t.covariance() = cov;
0219   BOOST_CHECK_EQUAL(t.covariance(), cov);
0220 
0221   auto surface =
0222       CurvilinearSurface(Acts::Vector3{-3_m, 0., 0.}, Acts::Vector3{1., 0., 0})
0223           .planeSurface();
0224 
0225   t.setReferenceSurface(surface);
0226   BOOST_CHECK_EQUAL(surface.get(), &t.referenceSurface());
0227 
0228   ProxyAccessor<unsigned int> accNMeasuements("nMeasurements");
0229   ConstProxyAccessor<unsigned int> caccNMeasuements("nMeasurements");
0230 
0231   t.nMeasurements() = 42;
0232   BOOST_CHECK_EQUAL(t2.nMeasurements(), 42);
0233   BOOST_CHECK_EQUAL(accNMeasuements(t), 42);
0234   accNMeasuements(t) = 89;
0235   BOOST_CHECK_EQUAL(t2.nMeasurements(), 89);
0236   BOOST_CHECK_EQUAL(caccNMeasuements(t), 89);
0237 
0238   // does not compile
0239   // caccNMeasuements(t) = 66;
0240 
0241   t2.nHoles() = 67;
0242   BOOST_CHECK_EQUAL(t.nHoles(), 67);
0243 
0244   t2.nOutliers() = 68;
0245   BOOST_CHECK_EQUAL(t.nOutliers(), 68);
0246 
0247   t2.nSharedHits() = 69;
0248   BOOST_CHECK_EQUAL(t.nSharedHits(), 69);
0249 
0250   t2.chi2() = 555.0;
0251   BOOST_CHECK_EQUAL(t2.chi2(), 555.0);
0252 
0253   t2.nDoF() = 123;
0254   BOOST_CHECK_EQUAL(t2.nDoF(), 123);
0255 
0256   // const checks: should not compile
0257   // const auto& ctc = tc;
0258   // ctc.getTrack(idx).covariance().setRandom();
0259   // const auto& ctp = t;
0260   // ctp.covariance().setRandom();
0261 }
0262 
0263 BOOST_AUTO_TEST_CASE(CopyTracksIncludingDynamicColumns) {
0264   // mutable source
0265   VectorTrackContainer vtc{};
0266   VectorMultiTrajectory mtj{};
0267   TrackContainer tc{vtc, mtj};
0268   tc.addColumn<std::size_t>("counter");
0269   tc.addColumn<bool>("odd");
0270   mtj.addColumn<std::size_t>("ts_counter");
0271   mtj.addColumn<bool>("ts_odd");
0272 
0273   TrackContainer tc2{VectorTrackContainer{}, VectorMultiTrajectory{}};
0274   // doesn't have the dynamic column
0275 
0276   VectorTrackContainer vtc3{};
0277   VectorMultiTrajectory mtj3{};
0278   mtj3.addColumn<std::size_t>("ts_counter");
0279   mtj3.addColumn<bool>("ts_odd");
0280 
0281   TrackContainer tc3{vtc3, mtj3};
0282 
0283   tc3.addColumn<std::size_t>("counter");
0284   tc3.addColumn<bool>("odd");
0285 
0286   for (std::size_t i = 0; i < 10; i++) {
0287     auto t = tc.makeTrack();
0288     auto ts = t.appendTrackState();
0289     ts.predicted() = BoundVector::Ones();
0290     ts.component<std::size_t, "ts_counter"_hash>() = i;
0291 
0292     ts = t.appendTrackState();
0293     ts.predicted().setOnes();
0294     ts.predicted() *= 2;
0295     ts.component<std::size_t, "ts_counter"_hash>() = i + 1;
0296 
0297     ts = t.appendTrackState();
0298     ts.predicted().setOnes();
0299     ts.predicted() *= 3;
0300     ts.component<std::size_t, "ts_counter"_hash>() = i + 2;
0301 
0302     t.template component<std::size_t>("counter") = i;
0303     t.template component<bool>("odd") = i % 2 == 0;
0304 
0305     auto t2 = tc2.makeTrack();
0306     BOOST_CHECK_THROW(t2.copyFrom(t),
0307                       std::invalid_argument);  // this should fail
0308 
0309     auto t3 = tc3.makeTrack();
0310     t3.copyFrom(t);  // this should work
0311 
0312     BOOST_CHECK_NE(t3.tipIndex(), MultiTrajectoryTraits::kInvalid);
0313     BOOST_CHECK_GT(t3.nTrackStates(), 0);
0314     BOOST_REQUIRE_EQUAL(t.nTrackStates(), t3.nTrackStates());
0315 
0316     for (auto [tsa, tsb] :
0317          zip(t.trackStatesReversed(), t3.trackStatesReversed())) {
0318       BOOST_CHECK_EQUAL(tsa.predicted(), tsb.predicted());
0319 
0320       BOOST_CHECK_EQUAL(
0321           (tsa.template component<std::size_t, "ts_counter"_hash>()),
0322           (tsb.template component<std::size_t, "ts_counter"_hash>()));
0323 
0324       BOOST_CHECK_EQUAL((tsa.template component<bool, "ts_odd"_hash>()),
0325                         (tsb.template component<bool, "ts_odd"_hash>()));
0326     }
0327 
0328     BOOST_CHECK_EQUAL(t.template component<std::size_t>("counter"),
0329                       t3.template component<std::size_t>("counter"));
0330     BOOST_CHECK_EQUAL(t.template component<bool>("odd"),
0331                       t3.template component<bool>("odd"));
0332   }
0333 
0334   std::size_t before = mtj.size();
0335   TrackContainer tc4{ConstVectorTrackContainer{vtc},
0336                      ConstVectorMultiTrajectory{mtj}};
0337 
0338   BOOST_REQUIRE_EQUAL(tc4.trackStateContainer().size(), before);
0339 
0340   VectorTrackContainer vtc5{};
0341   VectorMultiTrajectory mtj5{};
0342   mtj5.addColumn<std::size_t>("ts_counter");
0343   mtj5.addColumn<bool>("ts_odd");
0344 
0345   TrackContainer tc5{vtc5, mtj5};
0346   tc5.addColumn<std::size_t>("counter");
0347   tc5.addColumn<bool>("odd");
0348 
0349   for (std::size_t i = 0; i < 10; i++) {
0350     auto t4 = tc4.getTrack(i);  // const source!
0351     BOOST_CHECK_NE(t4.nTrackStates(), 0);
0352 
0353     auto t5 = tc5.makeTrack();
0354     t5.copyFrom(t4);  // this should work
0355 
0356     BOOST_CHECK_NE(t5.tipIndex(), MultiTrajectoryTraits::kInvalid);
0357     BOOST_CHECK_GT(t5.nTrackStates(), 0);
0358     BOOST_REQUIRE_EQUAL(t4.nTrackStates(), t5.nTrackStates());
0359 
0360     for (auto [tsa, tsb] :
0361          zip(t4.trackStatesReversed(), t5.trackStatesReversed())) {
0362       BOOST_CHECK_EQUAL(tsa.predicted(), tsb.predicted());
0363     }
0364 
0365     BOOST_CHECK_EQUAL(t4.template component<std::size_t>("counter"),
0366                       t5.template component<std::size_t>("counter"));
0367     BOOST_CHECK_EQUAL(t4.template component<bool>("odd"),
0368                       t5.template component<bool>("odd"));
0369   }
0370 }
0371 
0372 BOOST_AUTO_TEST_CASE(ReverseTrackStates) {
0373   VectorTrackContainer vtc{};
0374   VectorMultiTrajectory mtj{};
0375   TrackContainer tc{vtc, mtj};
0376 
0377   auto t = tc.makeTrack();
0378 
0379   for (std::size_t i = 0; i < 4; i++) {
0380     auto ts = t.appendTrackState();
0381     ts.jacobian() = Acts::BoundMatrix::Identity() * i;
0382   }
0383 
0384   std::vector<IndexType> exp;
0385   exp.resize(t.nTrackStates());
0386   std::iota(exp.rbegin(), exp.rend(), 0);
0387   std::vector<IndexType> act;
0388   std::transform(t.trackStatesReversed().begin(), t.trackStatesReversed().end(),
0389                  std::back_inserter(act),
0390                  [](const auto& ts) { return ts.index(); });
0391 
0392   // jacobians count up
0393   for (const auto [e, ts] : zip(exp, t.trackStatesReversed())) {
0394     BOOST_CHECK_EQUAL(ts.jacobian(), Acts::BoundMatrix::Identity() * e);
0395   }
0396 
0397   BOOST_CHECK_EQUAL_COLLECTIONS(exp.begin(), exp.end(), act.begin(), act.end());
0398 
0399   // reverse!
0400   t.reverseTrackStates();
0401 
0402   std::iota(exp.begin(), exp.end(), 0);
0403   act.clear();
0404   std::transform(t.trackStatesReversed().begin(), t.trackStatesReversed().end(),
0405                  std::back_inserter(act),
0406                  [](const auto& ts) { return ts.index(); });
0407   BOOST_CHECK_EQUAL_COLLECTIONS(exp.begin(), exp.end(), act.begin(), act.end());
0408 
0409   // jacobians stay with their track states
0410   for (const auto [e, ts] : zip(exp, t.trackStatesReversed())) {
0411     BOOST_CHECK_EQUAL(ts.jacobian(), Acts::BoundMatrix::Identity() * e);
0412   }
0413 
0414   // back to original!
0415   t.reverseTrackStates();
0416 
0417   // jacobians stay with their track states
0418   for (const auto [e, ts] : zip(exp, t.trackStates())) {
0419     BOOST_CHECK_EQUAL(ts.jacobian(), Acts::BoundMatrix::Identity() * e);
0420   }
0421 
0422   // reverse with jacobians
0423   t.reverseTrackStates(true);
0424 
0425   std::ranges::reverse(exp);
0426   std::rotate(exp.rbegin(), std::next(exp.rbegin()), exp.rend());
0427 
0428   for (const auto [e, ts] : zip(exp, t.trackStates())) {
0429     Acts::BoundMatrix expJac;
0430     if (e == 0) {
0431       expJac = Acts::BoundMatrix::Zero();
0432     } else {
0433       expJac = (Acts::BoundMatrix::Identity() * e).inverse();
0434     }
0435 
0436     BOOST_CHECK_EQUAL(ts.jacobian(), expJac);
0437   }
0438 
0439   // now back to original order, revert jacobians again
0440   t.reverseTrackStates(true);
0441 
0442   // reset exp to range(0, N)
0443   std::iota(exp.begin(), exp.end(), 0);
0444 
0445   for (const auto [e, ts] : zip(exp, t.trackStates())) {
0446     BOOST_CHECK_EQUAL(ts.jacobian(), Acts::BoundMatrix::Identity() * e);
0447   }
0448 }
0449 
0450 BOOST_AUTO_TEST_CASE(CopyTrackProxyCalibrated) {
0451   VectorTrackContainer vtc{};
0452   VectorMultiTrajectory mtj{};
0453   TrackContainer tc{vtc, mtj};
0454 
0455   constexpr static std::size_t kMeasurementSize = 3;
0456 
0457   auto track1 = tc.makeTrack();
0458   auto ts = track1.appendTrackState(TrackStatePropMask::Calibrated);
0459   ts.allocateCalibrated(kMeasurementSize);
0460   ts.setProjectorSubspaceIndices(BoundSubspaceIndices{});
0461 
0462   auto tsCopy = track1.appendTrackState(TrackStatePropMask::Calibrated);
0463   tsCopy.copyFrom(ts, TrackStatePropMask::Calibrated, false);
0464 
0465   BOOST_CHECK_EQUAL(ts.calibratedSize(), tsCopy.calibratedSize());
0466 }
0467 
0468 BOOST_AUTO_TEST_SUITE_END()