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