Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-02 08:54:45

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/data/test_case.hpp>
0010 #include <boost/test/unit_test.hpp>
0011 
0012 #include "Acts/Definitions/Algebra.hpp"
0013 #include "Acts/Definitions/Common.hpp"
0014 #include "Acts/Definitions/TrackParametrization.hpp"
0015 #include "Acts/Definitions/Units.hpp"
0016 #include "Acts/EventData/TransformationHelpers.hpp"
0017 #include "Acts/EventData/detail/GenerateParameters.hpp"
0018 #include "Acts/Geometry/GeometryContext.hpp"
0019 #include "Acts/Geometry/GeometryIdentifier.hpp"
0020 #include "Acts/Surfaces/PlaneSurface.hpp"
0021 #include "Acts/Surfaces/Surface.hpp"
0022 #include "Acts/Utilities/Result.hpp"
0023 #include "ActsFatras/Digitization/DigitizationError.hpp"
0024 #include "ActsFatras/Digitization/UncorrelatedHitSmearer.hpp"
0025 #include "ActsFatras/EventData/Barcode.hpp"
0026 #include "ActsFatras/EventData/Hit.hpp"
0027 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0028 
0029 #include <algorithm>
0030 #include <array>
0031 #include <cstddef>
0032 #include <cstdint>
0033 #include <iterator>
0034 #include <limits>
0035 #include <memory>
0036 #include <random>
0037 #include <utility>
0038 
0039 using namespace Acts;
0040 using namespace ActsFatras;
0041 
0042 namespace ActsTests {
0043 
0044 namespace bd = boost::unit_test::data;
0045 
0046 using RandomGenerator = std::default_random_engine;
0047 
0048 struct SterileSmearer {
0049   Result<std::pair<double, double>> operator()(double value,
0050                                                RandomGenerator& /*rng*/) {
0051     return Result<std::pair<double, double>>(
0052         std::make_pair<double, double>(value + 0., 0.));
0053   }
0054 };
0055 
0056 struct AddSmearer {
0057   double offset = 1.0;
0058 
0059   Result<std::pair<double, double>> operator()(double value,
0060                                                RandomGenerator& /*rng*/) {
0061     return Result<std::pair<double, double>>(
0062         std::make_pair<double, double>(value + offset, 3.));
0063   }
0064 };
0065 
0066 struct InvalidSmearer {
0067   Result<std::pair<double, double>> operator()(double /*ignored*/,
0068                                                RandomGenerator& /*rng*/) {
0069     return Result<std::pair<double, double>>(DigitizationError::SmearingError);
0070   }
0071 };
0072 
0073 template <typename generator_t>
0074 struct Fixture {
0075   generator_t rng;
0076   // identifiers
0077   GeometryIdentifier gid;
0078   Barcode pid;
0079   // geometry information
0080   std::shared_ptr<Surface> surface;
0081   GeometryContext geoCtx;
0082   // local and global track parameters
0083   BoundVector boundParams;
0084   FreeVector freeParams;
0085   // hit information
0086   Hit hit;
0087 
0088   Fixture(std::uint64_t rngSeed, std::shared_ptr<Surface> surf)
0089       : rng(rngSeed),
0090         gid(GeometryIdentifier().withVolume(1).withLayer(2).withSensitive(3)),
0091         pid(Barcode().withVertexPrimary(12).withParticle(23)),
0092         surface(std::move(surf)) {
0093     using namespace UnitLiterals;
0094     using VectorHelpers::makeVector4;
0095 
0096     surface->assignGeometryId(gid);
0097 
0098     // generate random track parameters
0099     auto [par, cov] = detail::Test::generateBoundParametersCovariance(rng, {});
0100     boundParams = par;
0101 
0102     freeParams = transformBoundToFreeParameters(*surface, geoCtx, boundParams);
0103 
0104     // construct hit from free parameters
0105     Vector4 r4;
0106     r4.segment<3>(ePos0) = freeParams.segment<3>(eFreePos0);
0107     r4[eTime] = freeParams[eFreeTime];
0108     // construct 4-momentum vector assuming m=0
0109     Vector4 p4;
0110     p4.segment<3>(eMom0) = freeParams.segment<3>(eFreeDir0).normalized();
0111     p4[eEnergy] = 1;
0112     p4 *= std::abs(1_e / freeParams[eFreeQOverP]);
0113     // same 4-momentum before/after hit
0114     hit = Hit(gid, pid, r4, p4, p4, 13);
0115   }
0116 };
0117 
0118 // track parameter indices to test smearing with. q/p smearing is not supported
0119 // in either case.
0120 const BoundIndices boundIndices[] = {
0121     eBoundLoc0, eBoundLoc1, eBoundTime, eBoundPhi, eBoundTheta,
0122 };
0123 const FreeIndices freeIndices[] = {
0124     eFreePos0, eFreePos1, eFreePos2, eFreeTime, eFreeDir0, eFreeDir1, eFreeDir2,
0125 };
0126 
0127 constexpr auto tol = 128 * std::numeric_limits<double>::epsilon();
0128 
0129 BOOST_AUTO_TEST_SUITE(DigitizationSuite)
0130 
0131 BOOST_DATA_TEST_CASE(Bound1, bd::make(boundIndices), index) {
0132   Fixture<RandomGenerator> f(123, Surface::makeShared<PlaneSurface>(
0133                                       Transform3(Translation3(3, 2, 1))));
0134   BoundParametersSmearer<RandomGenerator, 1u> s;
0135   s.indices = {index};
0136 
0137   // smearing does not do anything
0138   {
0139     s.smearFunctions.fill(SterileSmearer{});
0140     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0141     BOOST_CHECK(ret.ok());
0142     auto [par, cov] = ret.value();
0143     CHECK_CLOSE_REL(par[0], f.boundParams[index], tol);
0144   }
0145   // smearing adds something
0146   {
0147     s.smearFunctions.fill(AddSmearer{-42.0});
0148     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0149     BOOST_CHECK(ret.ok());
0150     auto [par, cov] = ret.value();
0151     CHECK_CLOSE_REL(par[0], f.boundParams[index] - 42.0, tol);
0152   }
0153   // smearing fails
0154   {
0155     s.smearFunctions.fill(InvalidSmearer{});
0156     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0157     BOOST_CHECK(!ret.ok());
0158     BOOST_CHECK(ret.error());
0159   }
0160 }
0161 
0162 BOOST_AUTO_TEST_CASE(BoundAll) {
0163   Fixture<RandomGenerator> f(12356, Surface::makeShared<PlaneSurface>(
0164                                         Transform3(Translation3(3, 2, 1))));
0165   // without q/p
0166   BoundParametersSmearer<RandomGenerator, std::size(boundIndices)> s;
0167   std::copy(std::begin(boundIndices), std::end(boundIndices),
0168             s.indices.begin());
0169 
0170   // smearing does not do anything
0171   {
0172     s.smearFunctions.fill(SterileSmearer{});
0173     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0174     BOOST_CHECK(ret.ok());
0175     auto [par, cov] = ret.value();
0176     for (std::size_t i = 0; i < s.indices.size(); ++i) {
0177       BOOST_TEST_INFO("Comparing smeared measurement "
0178                       << i << " originating from bound parameter "
0179                       << s.indices[i]);
0180       CHECK_CLOSE_REL(par[i], f.boundParams[s.indices[i]], tol);
0181     }
0182   }
0183   // smearing adds something
0184   {
0185     s.smearFunctions.fill(AddSmearer{-23.0});
0186     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0187     BOOST_CHECK(ret.ok());
0188     auto [par, cov] = ret.value();
0189     for (std::size_t i = 0; i < s.indices.size(); ++i) {
0190       BOOST_TEST_INFO("Comparing smeared measurement "
0191                       << i << " originating from bound parameter "
0192                       << s.indices[i]);
0193       CHECK_CLOSE_REL(par[i], f.boundParams[s.indices[i]] - 23.0, tol);
0194     }
0195   }
0196   // one smearer fails
0197   {
0198     s.smearFunctions.fill(SterileSmearer{});
0199     s.smearFunctions[3] = InvalidSmearer{};
0200     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0201     BOOST_CHECK(!ret.ok());
0202     BOOST_CHECK(ret.error());
0203   }
0204 }
0205 
0206 BOOST_DATA_TEST_CASE(Free1, bd::make(freeIndices), index) {
0207   Fixture<RandomGenerator> f(1234, Surface::makeShared<PlaneSurface>(
0208                                        Transform3(Translation3(3, 2, 1))));
0209   FreeParametersSmearer<RandomGenerator, 1u> s;
0210   s.indices = {index};
0211 
0212   // smearing does not do anything
0213   {
0214     s.smearFunctions.fill(SterileSmearer{});
0215     auto ret = s(f.rng, f.hit);
0216     BOOST_CHECK(ret.ok());
0217     auto [par, cov] = ret.value();
0218     CHECK_CLOSE_REL(par[0], f.freeParams[index], tol);
0219   }
0220   // smearing adds something
0221   {
0222     s.smearFunctions.fill(AddSmearer{-42.0});
0223     auto ret = s(f.rng, f.hit);
0224     BOOST_CHECK(ret.ok());
0225     auto [par, cov] = ret.value();
0226     CHECK_CLOSE_REL(par[0], f.freeParams[index] - 42.0, tol);
0227   }
0228   // smearing fails
0229   {
0230     s.smearFunctions.fill(InvalidSmearer{});
0231     auto ret = s(f.rng, f.hit);
0232     BOOST_CHECK(!ret.ok());
0233     BOOST_CHECK(ret.error());
0234   }
0235 }
0236 
0237 BOOST_AUTO_TEST_CASE(FreeAll) {
0238   Fixture<RandomGenerator> f(123567, Surface::makeShared<PlaneSurface>(
0239                                          Transform3(Translation3(3, 2, 1))));
0240   // without q/p
0241   FreeParametersSmearer<RandomGenerator, std::size(freeIndices)> s;
0242   std::copy(std::begin(freeIndices), std::end(freeIndices), s.indices.begin());
0243 
0244   // smearing does not do anything
0245   {
0246     s.smearFunctions.fill(SterileSmearer{});
0247     auto ret = s(f.rng, f.hit);
0248     BOOST_CHECK(ret.ok());
0249     auto [par, cov] = ret.value();
0250     for (std::size_t i = 0; i < s.indices.size(); ++i) {
0251       BOOST_TEST_INFO("Comparing smeared measurement "
0252                       << i << " originating from free parameter "
0253                       << s.indices[i]);
0254       CHECK_CLOSE_REL(par[i], f.freeParams[s.indices[i]], tol);
0255     }
0256   }
0257   // smearing adds something
0258   {
0259     s.smearFunctions.fill(AddSmearer{42.0});
0260     auto ret = s(f.rng, f.hit);
0261     BOOST_CHECK(ret.ok());
0262     auto [par, cov] = ret.value();
0263     for (std::size_t i = 0; i < s.indices.size(); ++i) {
0264       BOOST_TEST_INFO("Comparing smeared measurement "
0265                       << i << " originating from free parameter "
0266                       << s.indices[i]);
0267       CHECK_CLOSE_REL(par[i], f.freeParams[s.indices[i]] + 42.0, tol);
0268     }
0269   }
0270   // one smearer fails
0271   {
0272     s.smearFunctions.fill(SterileSmearer{});
0273     s.smearFunctions[3] = InvalidSmearer{};
0274     auto ret = s(f.rng, f.hit);
0275     BOOST_CHECK(!ret.ok());
0276     BOOST_CHECK(ret.error());
0277   }
0278 }
0279 
0280 BOOST_AUTO_TEST_SUITE_END()
0281 
0282 }  // namespace ActsTests