Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:11:39

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2020 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 http://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 <ostream>
0037 #include <random>
0038 #include <utility>
0039 
0040 namespace {
0041 
0042 namespace bd = boost::unit_test::data;
0043 
0044 using RandomGenerator = std::default_random_engine;
0045 
0046 struct SterileSmearer {
0047   Acts::Result<std::pair<double, double>> operator()(double value,
0048                                                      RandomGenerator& /*rng*/) {
0049     return Acts::Result<std::pair<double, double>>(
0050         std::make_pair<double, double>(value + 0., 0.));
0051   }
0052 };
0053 
0054 struct AddSmearer {
0055   double offset = 1.0;
0056 
0057   Acts::Result<std::pair<double, double>> operator()(double value,
0058                                                      RandomGenerator& /*rng*/) {
0059     return Acts::Result<std::pair<double, double>>(
0060         std::make_pair<double, double>(value + offset, 3.));
0061   }
0062 };
0063 
0064 struct InvalidSmearer {
0065   Acts::Result<std::pair<double, double>> operator()(double /*ignored*/,
0066                                                      RandomGenerator& /*rng*/) {
0067     return Acts::Result<std::pair<double, double>>(
0068         ActsFatras::DigitizationError::SmearingError);
0069   }
0070 };
0071 
0072 struct Fixture {
0073   RandomGenerator 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(uint64_t rngSeed)
0087       : rng(rngSeed),
0088         gid(Acts::GeometryIdentifier().setVolume(1).setLayer(2).setSensitive(
0089             3)),
0090         pid(ActsFatras::Barcode().setVertexPrimary(12).setParticle(23)),
0091         surface(Acts::Surface::makeShared<Acts::PlaneSurface>(
0092             Acts::Transform3(Acts::Translation3(3, 2, 1)))) {
0093     using namespace Acts::UnitLiterals;
0094     using Acts::VectorHelpers::makeVector4;
0095 
0096     surface->assignGeometryId(gid);
0097 
0098     // generate random track parameters
0099     auto [par, cov] =
0100         Acts::detail::Test::generateBoundParametersCovariance(rng);
0101     boundParams = par;
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 f(123);
0139   ActsFatras::BoundParametersSmearer<RandomGenerator, 1u> s;
0140   s.indices = {index};
0141 
0142   // smearing does not do anything
0143   {
0144     s.smearFunctions.fill(SterileSmearer{});
0145     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0146     BOOST_CHECK(ret.ok());
0147     auto [par, cov] = ret.value();
0148     CHECK_CLOSE_REL(par[0], f.boundParams[index], tol);
0149   }
0150   // smearing adds something
0151   {
0152     s.smearFunctions.fill(AddSmearer{-42.0});
0153     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0154     BOOST_CHECK(ret.ok());
0155     auto [par, cov] = ret.value();
0156     CHECK_CLOSE_REL(par[0], f.boundParams[index] - 42.0, tol);
0157   }
0158   // smearing fails
0159   {
0160     s.smearFunctions.fill(InvalidSmearer{});
0161     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0162     BOOST_CHECK(!ret.ok());
0163     BOOST_CHECK(ret.error());
0164   }
0165 }
0166 
0167 BOOST_AUTO_TEST_CASE(BoundAll) {
0168   Fixture f(12356);
0169   // without q/p
0170   ActsFatras::BoundParametersSmearer<RandomGenerator, std::size(boundIndices)>
0171       s;
0172   std::copy(std::begin(boundIndices), std::end(boundIndices),
0173             s.indices.begin());
0174 
0175   // smearing does not do anything
0176   {
0177     s.smearFunctions.fill(SterileSmearer{});
0178     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0179     BOOST_CHECK(ret.ok());
0180     auto [par, cov] = ret.value();
0181     for (std::size_t i = 0; i < s.indices.size(); ++i) {
0182       BOOST_TEST_INFO("Comparing smeared measurement "
0183                       << i << " originating from bound parameter "
0184                       << s.indices[i]);
0185       CHECK_CLOSE_REL(par[i], f.boundParams[s.indices[i]], tol);
0186     }
0187   }
0188   // smearing adds something
0189   {
0190     s.smearFunctions.fill(AddSmearer{-23.0});
0191     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0192     BOOST_CHECK(ret.ok());
0193     auto [par, cov] = ret.value();
0194     for (std::size_t i = 0; i < s.indices.size(); ++i) {
0195       BOOST_TEST_INFO("Comparing smeared measurement "
0196                       << i << " originating from bound parameter "
0197                       << s.indices[i]);
0198       CHECK_CLOSE_REL(par[i], f.boundParams[s.indices[i]] - 23.0, tol);
0199     }
0200   }
0201   // one smearer fails
0202   {
0203     s.smearFunctions.fill(SterileSmearer{});
0204     s.smearFunctions[3] = InvalidSmearer{};
0205     auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0206     BOOST_CHECK(!ret.ok());
0207     BOOST_CHECK(ret.error());
0208   }
0209 }
0210 
0211 BOOST_DATA_TEST_CASE(Free1, bd::make(freeIndices), index) {
0212   Fixture f(1234);
0213   ActsFatras::FreeParametersSmearer<RandomGenerator, 1u> s;
0214   s.indices = {index};
0215 
0216   // smearing does not do anything
0217   {
0218     s.smearFunctions.fill(SterileSmearer{});
0219     auto ret = s(f.rng, f.hit);
0220     BOOST_CHECK(ret.ok());
0221     auto [par, cov] = ret.value();
0222     CHECK_CLOSE_REL(par[0], f.freeParams[index], tol);
0223   }
0224   // smearing adds something
0225   {
0226     s.smearFunctions.fill(AddSmearer{-42.0});
0227     auto ret = s(f.rng, f.hit);
0228     BOOST_CHECK(ret.ok());
0229     auto [par, cov] = ret.value();
0230     CHECK_CLOSE_REL(par[0], f.freeParams[index] - 42.0, tol);
0231   }
0232   // smearing fails
0233   {
0234     s.smearFunctions.fill(InvalidSmearer{});
0235     auto ret = s(f.rng, f.hit);
0236     BOOST_CHECK(!ret.ok());
0237     BOOST_CHECK(ret.error());
0238   }
0239 }
0240 
0241 BOOST_AUTO_TEST_CASE(FreeAll) {
0242   Fixture f(123567);
0243   // without q/p
0244   ActsFatras::FreeParametersSmearer<RandomGenerator, std::size(freeIndices)> s;
0245   std::copy(std::begin(freeIndices), std::end(freeIndices), s.indices.begin());
0246 
0247   // smearing does not do anything
0248   {
0249     s.smearFunctions.fill(SterileSmearer{});
0250     auto ret = s(f.rng, f.hit);
0251     BOOST_CHECK(ret.ok());
0252     auto [par, cov] = ret.value();
0253     for (std::size_t i = 0; i < s.indices.size(); ++i) {
0254       BOOST_TEST_INFO("Comparing smeared measurement "
0255                       << i << " originating from free parameter "
0256                       << s.indices[i]);
0257       CHECK_CLOSE_REL(par[i], f.freeParams[s.indices[i]], tol);
0258     }
0259   }
0260   // smearing adds something
0261   {
0262     s.smearFunctions.fill(AddSmearer{42.0});
0263     auto ret = s(f.rng, f.hit);
0264     BOOST_CHECK(ret.ok());
0265     auto [par, cov] = ret.value();
0266     for (std::size_t i = 0; i < s.indices.size(); ++i) {
0267       BOOST_TEST_INFO("Comparing smeared measurement "
0268                       << i << " originating from free parameter "
0269                       << s.indices[i]);
0270       CHECK_CLOSE_REL(par[i], f.freeParams[s.indices[i]] + 42.0, tol);
0271     }
0272   }
0273   // one smearer fails
0274   {
0275     s.smearFunctions.fill(SterileSmearer{});
0276     s.smearFunctions[3] = InvalidSmearer{};
0277     auto ret = s(f.rng, f.hit);
0278     BOOST_CHECK(!ret.ok());
0279     BOOST_CHECK(ret.error());
0280   }
0281 }
0282 
0283 BOOST_AUTO_TEST_SUITE_END()