File indexing completed on 2026-05-16 07:37:23
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/EventData/detail/GenerateParameters.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Surfaces/StrawSurface.hpp"
0016 #include "Acts/Utilities/BinUtility.hpp"
0017 #include "Acts/Utilities/BinningType.hpp"
0018 #include "ActsExamples/Digitization/DigitizationConfig.hpp"
0019 #include "ActsExamples/Digitization/Smearers.hpp"
0020 #include "ActsExamples/Io/Json/JsonDigitizationConfig.hpp"
0021 #include "ActsFatras/Digitization/UncorrelatedHitSmearer.hpp"
0022 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0023
0024 #include <cmath>
0025 #include <fstream>
0026 #include <string>
0027 #include <vector>
0028
0029 #include <nlohmann/json.hpp>
0030
0031 using namespace Acts;
0032 using namespace ActsFatras;
0033 using namespace ActsExamples;
0034
0035 namespace {
0036 template <typename generator_t>
0037 struct Fixture {
0038 generator_t rng;
0039
0040 GeometryIdentifier gid;
0041 Barcode pid;
0042
0043 std::shared_ptr<Surface> surface;
0044 GeometryContext geoCtx = GeometryContext::dangerouslyDefaultConstruct();
0045
0046 BoundVector boundParams;
0047 FreeVector freeParams{};
0048
0049 Hit hit;
0050
0051 Fixture(std::uint64_t rngSeed, std::shared_ptr<Surface> surf)
0052 : rng(rngSeed),
0053 gid(GeometryIdentifier().withVolume(1).withLayer(2).withSensitive(3)),
0054 pid(Barcode().withVertexPrimary(12).withParticle(23)),
0055 surface(std::move(surf)) {
0056 using namespace UnitLiterals;
0057 using VectorHelpers::makeVector4;
0058
0059 surface->assignGeometryId(gid);
0060
0061
0062 auto [par, cov] = detail::Test::generateBoundParametersCovariance(rng, {});
0063 boundParams = par;
0064
0065 freeParams = transformBoundToFreeParameters(*surface, geoCtx, boundParams);
0066
0067
0068 Vector4 r4;
0069 r4.segment<3>(ePos0) = freeParams.segment<3>(eFreePos0);
0070 r4[eTime] = freeParams[eFreeTime];
0071
0072 Vector4 p4;
0073 p4.segment<3>(eMom0) = freeParams.segment<3>(eFreeDir0).normalized();
0074 p4[eEnergy] = 1;
0075 p4 *= std::abs(1_e / freeParams[eFreeQOverP]);
0076
0077 hit = Hit(gid, pid, r4, p4, p4, 13);
0078 }
0079 };
0080 }
0081
0082 namespace ActsTests {
0083
0084 BOOST_AUTO_TEST_SUITE(JsonSuite)
0085
0086 BOOST_AUTO_TEST_CASE(GaussianSmearing) {
0087 nlohmann::json djson = nlohmann::json::parse(R"(
0088 {
0089 "acts-geometry-hierarchy-map" : {
0090 "format-version" : 0,
0091 "value-identifier" : "digitization-configuration"
0092 },
0093
0094 "entries"
0095 : [
0096 {
0097 "volume" : 1,
0098 "value" : {
0099 "smearing" : [
0100 {"index" : 0, "mean" : 0.0, "stddev" : 0.05, "type" : "Gauss", "forcePositiveValues" : true}
0101
0102
0103 ]
0104 }
0105 }
0106 ]
0107 })");
0108 double radius = 5.;
0109 double halfZ = 8.;
0110 Fixture<RandomEngine> f(
0111 123567, Surface::makeShared<StrawSurface>(
0112 Transform3(Translation3(0., 0., 0.)), radius, halfZ));
0113
0114
0115 auto digiConfig =
0116 DigiConfigConverter("digitization-configuration").fromJson(djson);
0117 BoundParametersSmearer<RandomEngine, 1u> s;
0118
0119 for (auto& el : digiConfig) {
0120 for (auto& smearing : el.smearingDigiConfig.params) {
0121
0122 BOOST_CHECK(smearing.forcePositiveValues);
0123 const auto* gauss =
0124 smearing.smearFunction.target<const Digitization::Gauss>();
0125 BOOST_REQUIRE(gauss != nullptr);
0126 CHECK_CLOSE_REL(gauss->sigma, 0.05, 1e-12);
0127 std::fill(std::begin(s.indices), std::end(s.indices),
0128 static_cast<BoundIndices>(smearing.index));
0129 std::fill(std::begin(s.smearFunctions), std::end(s.smearFunctions),
0130 smearing.smearFunction);
0131 std::fill(std::begin(s.forcePositive), std::end(s.forcePositive),
0132 smearing.forcePositiveValues);
0133 }
0134 }
0135
0136 auto ret = s(f.rng, f.hit, *f.surface, f.geoCtx);
0137
0138 BOOST_CHECK(ret.ok());
0139 auto [par, cov] = ret.value();
0140 for (std::size_t i = 0; i < s.indices.size(); i++) {
0141 BOOST_TEST_INFO("Checking smeared measurement "
0142 << i << " originating from bound parameter "
0143 << s.indices[i]);
0144 BOOST_CHECK(std::isfinite(par[i]));
0145 BOOST_CHECK_GE(par[i], 0.);
0146 CHECK_CLOSE_REL(cov(i, i), 0.05 * 0.05, 1e-12);
0147 }
0148 }
0149
0150 BOOST_AUTO_TEST_CASE(DigitizationConfigRoundTrip) {
0151 std::ofstream out;
0152
0153
0154
0155
0156 DigiComponentsConfig dcf;
0157
0158 GeometricConfig gdc;
0159
0160 BinUtility segmentation;
0161 segmentation += BinUtility(336, -8.4, 8.4, open, AxisDirection::AxisX);
0162 segmentation += BinUtility(1280, -36, 36, open, AxisDirection::AxisY);
0163
0164 gdc.segmentation = segmentation;
0165 gdc.threshold = 0.01;
0166 gdc.thickness = 0.15;
0167 gdc.indices = {eBoundLoc0, eBoundLoc1};
0168 gdc.chargeSmearer = Digitization::Gauss(1.0);
0169
0170 DigiComponentsConfig dcRef;
0171 dcRef.geometricDigiConfig = gdc;
0172
0173 nlohmann::json dcJsonOut(dcRef);
0174 out.open("DigiComponentsConfig.json");
0175 out << dcJsonOut.dump(2);
0176 out.close();
0177
0178 auto in = std::ifstream("DigiComponentsConfig.json",
0179 std::ifstream::in | std::ifstream::binary);
0180 BOOST_CHECK(in.good());
0181 nlohmann::json dcJsonIn;
0182 in >> dcJsonIn;
0183 in.close();
0184
0185 DigiComponentsConfig dcTest(dcJsonIn);
0186 BOOST_CHECK(dcTest.geometricDigiConfig.indices ==
0187 dcRef.geometricDigiConfig.indices);
0188 BOOST_CHECK_EQUAL(dcTest.geometricDigiConfig.segmentation.dimensions(),
0189 dcRef.geometricDigiConfig.segmentation.dimensions());
0190 }
0191
0192 BOOST_AUTO_TEST_SUITE_END()
0193
0194 }