File indexing completed on 2026-11-12 09:43:57
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Utilities/VectorHelpers.hpp"
0012 #include "ActsExamples/Validation/PatternRecognitionPerformanceCollector.hpp"
0013
0014 #include <array>
0015 #include <cmath>
0016 #include <limits>
0017 #include <memory>
0018 #include <numbers>
0019 #include <random>
0020 #include <vector>
0021
0022 using namespace Acts;
0023 using namespace ActsExamples;
0024
0025 namespace {
0026
0027 void checkAgainstBruteForce(const std::vector<std::array<double, 2>>& points,
0028 double maxDeltaR = 0.3) {
0029 SimParticleContainer particles;
0030 ParticleTrackMatching matching;
0031 TrackParticleMatching trackMatching;
0032 auto trackBackend = std::make_shared<VectorTrackContainer>();
0033 auto stateBackend = std::make_shared<VectorMultiTrajectory>();
0034 ActsExamples::TrackContainer tracks(trackBackend, stateBackend);
0035 for (std::size_t i = 0; i < points.size(); ++i) {
0036 auto barcode = SimBarcode{}.withVertexPrimary(1).withParticle(i + 1);
0037 SimParticle particle(barcode, PdgParticle::eMuon);
0038 const auto [eta, phi] = points[i];
0039 particle.initialState().setDirection(
0040 std::isinf(eta)
0041 ? Vector3(0., 0., std::copysign(1., eta))
0042 : Vector3(std::cos(phi), std::sin(phi), std::sinh(eta)));
0043 particle.initialState().setAbsoluteMomentum(10.);
0044 particles.insert(particle);
0045 if (i % 2 == 0) {
0046 auto track = tracks.makeTrack();
0047 matching[barcode].track = track.index();
0048 trackMatching[track.index()] = {
0049 TrackMatchClassification::Matched, barcode, {}};
0050 }
0051 }
0052 ConstTrackContainer constTracks(
0053 std::make_shared<ConstVectorTrackContainer>(*trackBackend),
0054 std::make_shared<ConstVectorMultiTrajectory>(*stateBackend));
0055 PatternRecognitionPerformanceCollector::Config config;
0056 config.effPlotToolConfig.varBinning["DeltaR"] =
0057 EffPlotTool::BoostRegularAxis(100, 0., maxDeltaR, "deltaR");
0058 PatternRecognitionPerformanceCollector collector(
0059 config, getDefaultLogger("Test", Logging::WARNING));
0060 EffPlotTool reference(config.effPlotToolConfig, Logging::WARNING);
0061 auto gctx = GeometryContext::dangerouslyDefaultConstruct();
0062 collector.fill(gctx, constTracks, particles, trackMatching, matching, {});
0063 for (const auto& particle : particles) {
0064 double nearest = -1.;
0065 for (const auto& other : particles) {
0066 if (particle.particleId() == other.particleId()) {
0067 continue;
0068 }
0069 const double distance =
0070 VectorHelpers::deltaR(particle.direction(), other.direction());
0071 if (nearest == -1. || distance < nearest) {
0072 nearest = distance;
0073 }
0074 }
0075 reference.fill(gctx, particle.initialState(), nearest,
0076 matching.contains(particle.particleId()));
0077 }
0078 for (const auto& [name, expected] : reference.efficiencies1D()) {
0079 BOOST_TEST_CONTEXT(name) {
0080 const auto& actual = collector.effPlotTool().efficiencies1D().at(name);
0081 for (int bin = -1; bin <= expected.totalHistogram().axis(0).size();
0082 ++bin) {
0083 BOOST_CHECK_EQUAL(actual.totalHistogram().at(bin).value(),
0084 expected.totalHistogram().at(bin).value());
0085 BOOST_CHECK_EQUAL(actual.acceptedHistogram().at(bin).value(),
0086 expected.acceptedHistogram().at(bin).value());
0087 }
0088 }
0089 }
0090 }
0091
0092 }
0093
0094 BOOST_AUTO_TEST_CASE(EmptySingletonAndIsolatedParticles) {
0095 checkAgainstBruteForce({});
0096 checkAgainstBruteForce({{0., 0.}});
0097 checkAgainstBruteForce({{-5., -2.}, {0., 0.}, {5., 2.}});
0098 }
0099
0100 BOOST_AUTO_TEST_CASE(PeriodicPhiCoincidenceAndCutoff) {
0101 const double pi = std::numbers::pi;
0102 checkAgainstBruteForce({{0., pi - 0.001},
0103 {0., -pi + 0.001},
0104 {1., 0.},
0105 {1., 0.},
0106 {2., 0.},
0107 {2., 0.3},
0108 {3., 0.},
0109 {3., std::nextafter(0.3, 0.)},
0110 {4., 0.},
0111 {4., std::nextafter(0.3, 1.)}});
0112 }
0113
0114 BOOST_AUTO_TEST_CASE(ConfiguredRangeAndRandomParticles) {
0115 std::mt19937 rng(42);
0116 std::uniform_real_distribution<double> eta(-6., 6.);
0117 std::uniform_real_distribution<double> phi(-std::numbers::pi,
0118 std::numbers::pi);
0119 std::vector<std::array<double, 2>> points;
0120 for (std::size_t i = 0; i < 512; ++i) {
0121 points.push_back({eta(rng), phi(rng)});
0122 }
0123 for (double maxDeltaR : {0.01, 0.3, 1., 10.}) {
0124 BOOST_TEST_CONTEXT(maxDeltaR) {
0125 checkAgainstBruteForce(points, maxDeltaR);
0126 }
0127 }
0128 }
0129
0130 BOOST_AUTO_TEST_CASE(BeamAxisParticles) {
0131 const double infinity = std::numeric_limits<double>::infinity();
0132 checkAgainstBruteForce({{infinity, 0.}, {0., 0.}, {0., 0.1}});
0133 checkAgainstBruteForce({{-infinity, 0.}, {0., 0.}});
0134 }