Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:05

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