Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-03 08:59:18

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 #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& /*surface*/) const override {
0064     return {};
0065   }
0066   const Surface* identifierToSurface(
0067       PodioUtil::Identifier /*identifier*/) const override {
0068     return nullptr;
0069   }
0070 
0071   SourceLink identifierToSourceLink(
0072       PodioUtil::Identifier /*identifier*/) const override {
0073     return SourceLink{0};
0074   }
0075 
0076   PodioUtil::Identifier sourceLinkToIdentifier(
0077       const SourceLink& /*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   // this could probably use some more complete checks
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     // Register surface "with the detector"
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     // const ActsPodioEdm::TrackCollection& tracks = ptc.trackCollection();
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     // Not the exact same surface, it's recreated from values
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     // Is the exact same surface, because it's looked up in the "detector"
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   // mutable source
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   // doesn't have the dynamic column
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);  // this should fail
0367 
0368     auto t3 = tc3.makeTrack();
0369     t3.copyFrom(t);  // this should work
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 }  // namespace ActsTests