File indexing completed on 2025-08-06 08:11:44
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/data/test_case.hpp>
0010 #include <boost/test/tools/old/interface.hpp>
0011 #include <boost/test/unit_test.hpp>
0012 #include <boost/test/unit_test_suite.hpp>
0013
0014 #include "Acts/Definitions/Algebra.hpp"
0015 #include "Acts/Definitions/TrackParametrization.hpp"
0016 #include "Acts/Definitions/Units.hpp"
0017 #include "Acts/EventData/MultiTrajectory.hpp"
0018 #include "Acts/EventData/ParticleHypothesis.hpp"
0019 #include "Acts/EventData/VectorMultiTrajectory.hpp"
0020 #include "Acts/EventData/VectorTrackContainer.hpp"
0021 #include "Acts/Geometry/GeometryContext.hpp"
0022 #include "Acts/Plugins/Podio/PodioTrackContainer.hpp"
0023 #include "Acts/Plugins/Podio/PodioTrackStateContainer.hpp"
0024 #include "Acts/Plugins/Podio/PodioUtil.hpp"
0025 #include "Acts/Surfaces/AnnulusBounds.hpp"
0026 #include "Acts/Surfaces/ConeSurface.hpp"
0027 #include "Acts/Surfaces/ConvexPolygonBounds.hpp"
0028 #include "Acts/Surfaces/CylinderBounds.hpp"
0029 #include "Acts/Surfaces/CylinderSurface.hpp"
0030 #include "Acts/Surfaces/DiamondBounds.hpp"
0031 #include "Acts/Surfaces/DiscBounds.hpp"
0032 #include "Acts/Surfaces/DiscSurface.hpp"
0033 #include "Acts/Surfaces/DiscTrapezoidBounds.hpp"
0034 #include "Acts/Surfaces/EllipseBounds.hpp"
0035 #include "Acts/Surfaces/PerigeeSurface.hpp"
0036 #include "Acts/Surfaces/PlanarBounds.hpp"
0037 #include "Acts/Surfaces/PlaneSurface.hpp"
0038 #include "Acts/Surfaces/RadialBounds.hpp"
0039 #include "Acts/Surfaces/RectangleBounds.hpp"
0040 #include "Acts/Surfaces/StrawSurface.hpp"
0041 #include "Acts/Surfaces/SurfaceBounds.hpp"
0042 #include "Acts/Utilities/Helpers.hpp"
0043 #include "Acts/Utilities/Zip.hpp"
0044 #include "ActsPodioEdm/Surface.h"
0045 #include <ActsPodioEdm/TrackCollection.h>
0046
0047 #include <algorithm>
0048 #include <iterator>
0049 #include <memory>
0050 #include <random>
0051 #include <stdexcept>
0052
0053 using namespace Acts;
0054 using namespace Acts::UnitLiterals;
0055 using namespace Acts::HashedStringLiteral;
0056 BOOST_AUTO_TEST_SUITE(PodioTrackContainerTest)
0057
0058 class NullHelper : public PodioUtil::ConversionHelper {
0059 public:
0060 std::optional<PodioUtil::Identifier> surfaceToIdentifier(
0061 const Surface& ) const override {
0062 return {};
0063 }
0064 const Surface* identifierToSurface(
0065 PodioUtil::Identifier ) const override {
0066 return nullptr;
0067 }
0068
0069 SourceLink identifierToSourceLink(
0070 PodioUtil::Identifier ) const override {
0071 return SourceLink{0};
0072 }
0073
0074 PodioUtil::Identifier sourceLinkToIdentifier(
0075 const SourceLink& ) override {
0076 return 0;
0077 }
0078 };
0079
0080 struct MapHelper : public NullHelper {
0081 std::optional<PodioUtil::Identifier> surfaceToIdentifier(
0082 const Surface& surface) const override {
0083 for (auto&& [id, srf] : surfaces) {
0084 if (srf == &surface) {
0085 return id;
0086 }
0087 }
0088 return {};
0089 }
0090 const Surface* identifierToSurface(PodioUtil::Identifier id) const override {
0091 auto it = surfaces.find(id);
0092 if (it == surfaces.end()) {
0093 return nullptr;
0094 }
0095
0096 return it->second;
0097 }
0098
0099 std::unordered_map<PodioUtil::Identifier, const Surface*> surfaces;
0100 };
0101
0102 BOOST_AUTO_TEST_CASE(ConvertSurface) {
0103 auto rBounds = std::make_shared<RectangleBounds>(15, 20);
0104
0105 auto trf = Transform3::Identity();
0106 trf.translation().setRandom();
0107
0108 auto free = Acts::Surface::makeShared<PlaneSurface>(trf, rBounds);
0109
0110 NullHelper helper;
0111 auto surface = PodioUtil::convertSurfaceToPodio(helper, *free);
0112
0113 auto free2 = PodioUtil::convertSurfaceFromPodio(helper, surface);
0114
0115 Acts::GeometryContext gctx;
0116
0117 BOOST_REQUIRE(free2);
0118 BOOST_CHECK_EQUAL(free->type(), free2->type());
0119 BOOST_CHECK_EQUAL(free->bounds().type(), free2->bounds().type());
0120 BOOST_CHECK_EQUAL(free->center(gctx), free2->center(gctx));
0121
0122 const auto* rBounds2 = dynamic_cast<const RectangleBounds*>(&free2->bounds());
0123 BOOST_REQUIRE_NE(rBounds2, nullptr);
0124
0125 BOOST_CHECK_EQUAL(rBounds2->halfLengthX(), rBounds->halfLengthX());
0126 BOOST_CHECK_EQUAL(rBounds2->halfLengthY(), rBounds->halfLengthY());
0127
0128
0129 }
0130
0131 BOOST_AUTO_TEST_CASE(ConvertTrack) {
0132 auto rBounds = std::make_shared<RectangleBounds>(15, 20);
0133 auto trf = Transform3::Identity();
0134 trf.translation().setRandom();
0135 auto free = Acts::Surface::makeShared<PlaneSurface>(trf, rBounds);
0136
0137 MapHelper helper;
0138
0139 auto refCov = BoundMatrix::Random().eval();
0140
0141 podio::Frame frame;
0142
0143 ParticleHypothesis pHypo = ParticleHypothesis::pion();
0144
0145 {
0146 Acts::MutablePodioTrackStateContainer tsc{helper};
0147 Acts::MutablePodioTrackContainer ptc{helper};
0148 ActsPodioEdm::TrackCollection& tracks = ptc.trackCollection();
0149
0150 Acts::TrackContainer tc{ptc, tsc};
0151
0152 BOOST_CHECK(!tc.hasColumn("int_column"_hash));
0153 BOOST_CHECK(!tc.hasColumn("float_column"_hash));
0154 tc.addColumn<int32_t>("int_column");
0155 tc.addColumn<float>("float_column");
0156 BOOST_CHECK(tc.hasColumn("int_column"_hash));
0157 BOOST_CHECK(tc.hasColumn("float_column"_hash));
0158
0159 BOOST_CHECK_EQUAL(tc.size(), 0);
0160
0161 auto t = tc.makeTrack();
0162 BOOST_CHECK_EQUAL(t.tipIndex(), MultiTrajectoryTraits::kInvalid);
0163
0164 t.setParticleHypothesis(pHypo);
0165 BOOST_CHECK_EQUAL(t.particleHypothesis(), pHypo);
0166
0167 BOOST_CHECK_EQUAL(tsc.size(), 0);
0168 auto ts1 = t.appendTrackState();
0169 auto ts2 = t.appendTrackState();
0170 auto ts3 = t.appendTrackState();
0171 BOOST_CHECK_EQUAL(tsc.size(), 3);
0172 BOOST_CHECK_EQUAL(ts1.index(), 0);
0173 BOOST_CHECK_EQUAL(ts2.index(), 1);
0174 BOOST_CHECK_EQUAL(ts3.index(), 2);
0175
0176 BOOST_CHECK_EQUAL(t.nTrackStates(), 3);
0177 BOOST_CHECK_EQUAL(t.tipIndex(), 2);
0178
0179 BOOST_CHECK_EQUAL(tc.size(), 1);
0180
0181 auto pTrack = tracks.at(0);
0182 BOOST_CHECK_EQUAL(pTrack.data().tipIndex, 2);
0183
0184 t.parameters() << 1, 2, 3, 4, 5, 6;
0185 Eigen::Map<BoundVector> pars{pTrack.data().parameters.data()};
0186 BoundVector bv;
0187 bv << 1, 2, 3, 4, 5, 6;
0188 BOOST_CHECK_EQUAL(pars, bv);
0189
0190 t.covariance() = refCov;
0191
0192 Eigen::Map<const BoundMatrix> cov{pTrack.data().covariance.data()};
0193 BOOST_CHECK_EQUAL(refCov, cov);
0194
0195 t.nMeasurements() = 17;
0196 BOOST_CHECK_EQUAL(pTrack.data().nMeasurements, 17);
0197
0198 t.nHoles() = 34;
0199 BOOST_CHECK_EQUAL(pTrack.data().nHoles, 34);
0200
0201 t.chi2() = 882.3f;
0202 BOOST_CHECK_EQUAL(pTrack.data().chi2, 882.3f);
0203
0204 t.nDoF() = 9;
0205 BOOST_CHECK_EQUAL(pTrack.data().ndf, 9);
0206
0207 t.nOutliers() = 77;
0208 BOOST_CHECK_EQUAL(pTrack.data().nOutliers, 77);
0209
0210 t.nSharedHits() = 99;
0211 BOOST_CHECK_EQUAL(pTrack.data().nSharedHits, 99);
0212
0213 Acts::GeometryContext gctx;
0214 t.setReferenceSurface(free);
0215 const auto& free2 = t.referenceSurface();
0216 BOOST_CHECK_EQUAL(free->center(gctx), free2.center(gctx));
0217
0218 const auto* rBounds2 =
0219 dynamic_cast<const RectangleBounds*>(&free2.bounds());
0220 BOOST_REQUIRE_NE(rBounds2, nullptr);
0221
0222 BOOST_CHECK_EQUAL(rBounds2->halfLengthX(), rBounds->halfLengthX());
0223 BOOST_CHECK_EQUAL(rBounds2->halfLengthY(), rBounds->halfLengthY());
0224
0225 BOOST_CHECK_EQUAL(pTrack.getReferenceSurface().identifier,
0226 PodioUtil::kNoIdentifier);
0227
0228 auto t2 = tc.makeTrack();
0229 auto t3 = tc.makeTrack();
0230 BOOST_CHECK_EQUAL(tc.size(), 3);
0231
0232
0233 helper.surfaces[666] = free.get();
0234 t2.setReferenceSurface(free);
0235 auto pTrack2 = tracks.at(1);
0236 BOOST_CHECK_EQUAL(pTrack2.getReferenceSurface().identifier, 666);
0237
0238 t.component<int32_t, "int_column"_hash>() = -11;
0239 t2.component<int32_t, "int_column"_hash>() = 42;
0240 t3.component<int32_t, "int_column"_hash>() = -98;
0241
0242 t.component<float, "float_column"_hash>() = -11.2f;
0243 t2.component<float, "float_column"_hash>() = 42.4f;
0244 t3.component<float, "float_column"_hash>() = -98.9f;
0245
0246 ptc.releaseInto(frame);
0247 tsc.releaseInto(frame);
0248
0249 BOOST_REQUIRE_NE(frame.get("tracks"), nullptr);
0250 BOOST_CHECK_EQUAL(frame.get("tracks")->size(), 3);
0251 BOOST_REQUIRE_NE(frame.get("tracks_extra__int_column"), nullptr);
0252 BOOST_REQUIRE_NE(frame.get("tracks_extra__float_column"), nullptr);
0253
0254 BOOST_REQUIRE_NE(frame.get("trackStates"), nullptr);
0255 BOOST_CHECK_EQUAL(frame.get("trackStates")->size(), 3);
0256 }
0257
0258 {
0259 Acts::ConstPodioTrackStateContainer tsc{helper, frame};
0260 Acts::ConstPodioTrackContainer ptc{helper, frame};
0261
0262
0263 Acts::TrackContainer tc{ptc, tsc};
0264
0265 BOOST_CHECK(tc.hasColumn("int_column"_hash));
0266 BOOST_CHECK(tc.hasColumn("float_column"_hash));
0267
0268 BOOST_CHECK_EQUAL(tc.size(), 3);
0269
0270 auto t = tc.getTrack(0);
0271 const auto& freeRecreated = t.referenceSurface();
0272
0273 BOOST_CHECK_NE(free.get(), &freeRecreated);
0274
0275 BOOST_CHECK_EQUAL(t.particleHypothesis(), pHypo);
0276
0277 BOOST_CHECK_EQUAL(t.nMeasurements(), 17);
0278
0279 BOOST_CHECK_EQUAL(t.nHoles(), 34);
0280
0281 BOOST_CHECK_EQUAL(t.chi2(), 882.3f);
0282
0283 BOOST_CHECK_EQUAL(t.nDoF(), 9);
0284
0285 BOOST_CHECK_EQUAL(t.nOutliers(), 77);
0286
0287 BOOST_CHECK_EQUAL(t.nSharedHits(), 99);
0288
0289 BOOST_CHECK_EQUAL(t.tipIndex(), 2);
0290 BOOST_CHECK_EQUAL(t.nTrackStates(), 3);
0291
0292 auto t2 = tc.getTrack(1);
0293
0294 BOOST_CHECK_EQUAL(free.get(), &t2.referenceSurface());
0295 BoundVector bv;
0296 bv << 1, 2, 3, 4, 5, 6;
0297 BOOST_CHECK_EQUAL(t.parameters(), bv);
0298
0299 BOOST_CHECK_EQUAL(t.covariance(), refCov);
0300
0301 auto t3 = tc.getTrack(2);
0302 BOOST_CHECK(!t3.hasReferenceSurface());
0303
0304 BOOST_CHECK_EQUAL((t.component<int32_t, "int_column"_hash>()), -11);
0305 BOOST_CHECK_EQUAL((t2.component<int32_t, "int_column"_hash>()), 42);
0306 BOOST_CHECK_EQUAL((t3.component<int32_t, "int_column"_hash>()), -98);
0307
0308 BOOST_CHECK_EQUAL((t.component<float, "float_column"_hash>()), -11.2f);
0309 BOOST_CHECK_EQUAL((t2.component<float, "float_column"_hash>()), 42.4f);
0310 BOOST_CHECK_EQUAL((t3.component<float, "float_column"_hash>()), -98.9f);
0311 }
0312 }
0313
0314 BOOST_AUTO_TEST_CASE(CopyTracksIncludingDynamicColumnsDifferentBackends) {
0315 MapHelper helper;
0316
0317 podio::Frame frame;
0318
0319
0320 VectorTrackContainer vtc{};
0321 VectorMultiTrajectory mtj{};
0322 TrackContainer tc{vtc, mtj};
0323 tc.addColumn<uint64_t>("counter");
0324 tc.addColumn<uint8_t>("odd");
0325 mtj.addColumn<uint64_t>("ts_counter");
0326 mtj.addColumn<uint8_t>("ts_odd");
0327
0328 Acts::MutablePodioTrackStateContainer tsc2{helper};
0329 Acts::MutablePodioTrackContainer ptc2{helper};
0330 Acts::TrackContainer tc2{ptc2, tsc2};
0331
0332
0333 Acts::MutablePodioTrackStateContainer tsc3{helper};
0334 Acts::MutablePodioTrackContainer ptc3{helper};
0335 Acts::TrackContainer tc3{ptc3, tsc3};
0336
0337 tc3.addColumn<uint64_t>("counter");
0338 tc3.addColumn<uint8_t>("odd");
0339 tsc3.addColumn<uint64_t>("ts_counter");
0340 tsc3.addColumn<uint8_t>("ts_odd");
0341
0342 for (std::size_t i = 0; i < 10; i++) {
0343 auto t = tc.makeTrack();
0344 auto ts = t.appendTrackState();
0345 ts.predicted() = BoundVector::Ones();
0346 ts.component<uint64_t, "ts_counter"_hash>() = i;
0347
0348 ts = t.appendTrackState();
0349 ts.predicted().setOnes();
0350 ts.predicted() *= 2;
0351 ts.component<uint64_t, "ts_counter"_hash>() = i + 1;
0352
0353 ts = t.appendTrackState();
0354 ts.predicted().setOnes();
0355 ts.predicted() *= 3;
0356 ts.component<uint64_t, "ts_counter"_hash>() = i + 2;
0357
0358 t.template component<uint64_t>("counter") = i;
0359 t.template component<uint8_t>("odd") = static_cast<uint8_t>(i % 2 == 0);
0360
0361 auto t2 = tc2.makeTrack();
0362 BOOST_CHECK_THROW(t2.copyFrom(t),
0363 std::invalid_argument);
0364
0365 auto t3 = tc3.makeTrack();
0366 t3.copyFrom(t);
0367
0368 BOOST_CHECK_NE(t3.tipIndex(), MultiTrajectoryTraits::kInvalid);
0369 BOOST_CHECK_GT(t3.nTrackStates(), 0);
0370 BOOST_REQUIRE_EQUAL(t.nTrackStates(), t3.nTrackStates());
0371
0372 for (auto [tsa, tsb] :
0373 zip(t.trackStatesReversed(), t3.trackStatesReversed())) {
0374 BOOST_CHECK_EQUAL(tsa.predicted(), tsb.predicted());
0375
0376 BOOST_CHECK_EQUAL(
0377 (tsa.template component<uint64_t, "ts_counter"_hash>()),
0378 (tsb.template component<uint64_t, "ts_counter"_hash>()));
0379
0380 BOOST_CHECK_EQUAL((tsa.template component<uint8_t, "ts_odd"_hash>()),
0381 (tsb.template component<uint8_t, "ts_odd"_hash>()));
0382 }
0383
0384 BOOST_CHECK_EQUAL(t.template component<uint64_t>("counter"),
0385 t3.template component<uint64_t>("counter"));
0386 BOOST_CHECK_EQUAL(t.template component<uint8_t>("odd"),
0387 t3.template component<uint8_t>("odd"));
0388 }
0389 }
0390
0391 BOOST_AUTO_TEST_SUITE_END()