File indexing completed on 2025-11-02 08:54:45
0001
0002
0003
0004
0005
0006
0007
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& ) {
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& ) {
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 ,
0068 RandomGenerator& ) {
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
0077 GeometryIdentifier gid;
0078 Barcode pid;
0079
0080 std::shared_ptr<Surface> surface;
0081 GeometryContext geoCtx;
0082
0083 BoundVector boundParams;
0084 FreeVector freeParams;
0085
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
0099 auto [par, cov] = detail::Test::generateBoundParametersCovariance(rng, {});
0100 boundParams = par;
0101
0102 freeParams = transformBoundToFreeParameters(*surface, geoCtx, boundParams);
0103
0104
0105 Vector4 r4;
0106 r4.segment<3>(ePos0) = freeParams.segment<3>(eFreePos0);
0107 r4[eTime] = freeParams[eFreeTime];
0108
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
0114 hit = Hit(gid, pid, r4, p4, p4, 13);
0115 }
0116 };
0117
0118
0119
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
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
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
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
0166 BoundParametersSmearer<RandomGenerator, std::size(boundIndices)> s;
0167 std::copy(std::begin(boundIndices), std::end(boundIndices),
0168 s.indices.begin());
0169
0170
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
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
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
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
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
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
0241 FreeParametersSmearer<RandomGenerator, std::size(freeIndices)> s;
0242 std::copy(std::begin(freeIndices), std::end(freeIndices), s.indices.begin());
0243
0244
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
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
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 }