Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:13:02

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/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Definitions/Direction.hpp"
0014 #include "Acts/Definitions/TrackParametrization.hpp"
0015 #include "Acts/Definitions/Units.hpp"
0016 #include "Acts/EventData/TrackParameters.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Geometry/GeometryIdentifier.hpp"
0019 #include "Acts/MagneticField/ConstantBField.hpp"
0020 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0021 #include "Acts/Propagator/EigenStepper.hpp"
0022 #include "Acts/Propagator/Propagator.hpp"
0023 #include "Acts/Surfaces/PerigeeSurface.hpp"
0024 #include "Acts/Surfaces/Surface.hpp"
0025 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0026 #include "Acts/Utilities/Result.hpp"
0027 #include "Acts/Vertexing/FullBilloirVertexFitter.hpp"
0028 #include "Acts/Vertexing/HelicalTrackLinearizer.hpp"
0029 #include "Acts/Vertexing/ImpactPointEstimator.hpp"
0030 #include "Acts/Vertexing/VertexingOptions.hpp"
0031 #include "Acts/Vertexing/ZScanVertexFinder.hpp"
0032 
0033 #include <algorithm>
0034 #include <array>
0035 #include <cmath>
0036 #include <functional>
0037 #include <iostream>
0038 #include <memory>
0039 #include <numbers>
0040 #include <random>
0041 #include <string>
0042 #include <system_error>
0043 #include <tuple>
0044 #include <type_traits>
0045 #include <utility>
0046 #include <vector>
0047 
0048 using namespace Acts::UnitLiterals;
0049 
0050 namespace Acts::Test {
0051 
0052 using Covariance = BoundSquareMatrix;
0053 using Propagator = Acts::Propagator<EigenStepper<>>;
0054 
0055 // Create a test context
0056 GeometryContext geoContext = GeometryContext();
0057 MagneticFieldContext magFieldContext = MagneticFieldContext();
0058 
0059 // Vertex x/y position distribution
0060 std::uniform_real_distribution<double> vXYDist(-0.1_mm, 0.1_mm);
0061 // Vertex z position distribution
0062 std::uniform_real_distribution<double> vZDist(-20_mm, 20_mm);
0063 // Track d0 distribution
0064 std::uniform_real_distribution<double> d0Dist(-0.01_mm, 0.01_mm);
0065 // Track z0 distribution
0066 std::uniform_real_distribution<double> z0Dist(-0.2_mm, 0.2_mm);
0067 // Track pT distribution
0068 std::uniform_real_distribution<double> pTDist(0.4_GeV, 10_GeV);
0069 // Track phi distribution
0070 std::uniform_real_distribution<double> phiDist(-std::numbers::pi,
0071                                                std::numbers::pi);
0072 // Track theta distribution
0073 std::uniform_real_distribution<double> thetaDist(1., std::numbers::pi - 1.);
0074 // Track charge helper distribution
0075 std::uniform_real_distribution<double> qDist(-1, 1);
0076 // Track IP resolution distribution
0077 std::uniform_real_distribution<double> resIPDist(0., 100_um);
0078 // Track angular distribution
0079 std::uniform_real_distribution<double> resAngDist(0., 0.1);
0080 // Track q/p resolution distribution
0081 std::uniform_real_distribution<double> resQoPDist(-0.01, 0.01);
0082 
0083 ///
0084 /// @brief Unit test for ZScanVertexFinder
0085 ///
0086 BOOST_AUTO_TEST_CASE(zscan_finder_test) {
0087   unsigned int nTests = 50;
0088 
0089   for (unsigned int iTest = 0; iTest < nTests; ++iTest) {
0090     // Number of tracks
0091     unsigned int nTracks = 30;
0092 
0093     // Set up RNG
0094     int mySeed = 31415;
0095     std::mt19937 gen(mySeed);
0096 
0097     // Set up constant B-Field
0098     auto bField = std::make_shared<ConstantBField>(Vector3{0.0, 0.0, 1_T});
0099 
0100     // Set up Eigenstepper
0101     EigenStepper<> stepper(bField);
0102 
0103     // Set up propagator with void navigator
0104     auto propagator = std::make_shared<Propagator>(stepper);
0105 
0106     // Create perigee surface
0107     std::shared_ptr<PerigeeSurface> perigeeSurface =
0108         Surface::makeShared<PerigeeSurface>(Vector3(0., 0., 0.));
0109 
0110     // Create position of vertex and perigee surface
0111     double x = vXYDist(gen);
0112     double y = vXYDist(gen);
0113     double z = vZDist(gen);
0114 
0115     // Calculate d0 and z0 corresponding to vertex position
0116     double d0_v = std::hypot(x, y);
0117     double z0_v = z;
0118 
0119     // Start constructing nTracks tracks in the following
0120     std::vector<BoundTrackParameters> tracks;
0121 
0122     // Construct random track emerging from vicinity of vertex position
0123     // Vector to store track objects used for vertex fit
0124     for (unsigned int iTrack = 0; iTrack < nTracks; iTrack++) {
0125       // Construct positive or negative charge randomly
0126       double q = qDist(gen) < 0 ? -1. : 1.;
0127 
0128       // Construct random track parameters
0129       BoundVector paramVec = BoundVector::Zero();
0130       paramVec[eBoundLoc0] = d0_v + d0Dist(gen);
0131       paramVec[eBoundLoc1] = z0_v + z0Dist(gen);
0132       paramVec[eBoundPhi] = phiDist(gen);
0133       paramVec[eBoundTheta] = thetaDist(gen);
0134       paramVec[eBoundQOverP] = q / pTDist(gen);
0135 
0136       // Resolutions
0137       double resD0 = resIPDist(gen);
0138       double resZ0 = resIPDist(gen);
0139       double resPh = resAngDist(gen);
0140       double resTh = resAngDist(gen);
0141       double resQp = resQoPDist(gen);
0142 
0143       // Fill vector of track objects with simple covariance matrix
0144       Covariance covMat;
0145 
0146       covMat << resD0 * resD0, 0., 0., 0., 0., 0., 0., resZ0 * resZ0, 0., 0.,
0147           0., 0., 0., 0., resPh * resPh, 0., 0., 0., 0., 0., 0., resTh * resTh,
0148           0., 0., 0., 0., 0., 0., resQp * resQp, 0., 0., 0., 0., 0., 0., 1.;
0149 
0150       tracks.emplace_back(perigeeSurface, paramVec, std::move(covMat),
0151                           ParticleHypothesis::pion());
0152     }
0153 
0154     std::vector<InputTrack> inputTracks;
0155     for (const auto& trk : tracks) {
0156       inputTracks.emplace_back(&trk);
0157     }
0158 
0159     using VertexFinder = ZScanVertexFinder;
0160 
0161     ImpactPointEstimator::Config ipEstimatorCfg(bField, propagator);
0162     ImpactPointEstimator ipEstimator(ipEstimatorCfg);
0163 
0164     VertexFinder::Config cfg(ipEstimator);
0165     cfg.extractParameters.connect<&InputTrack::extractParameters>();
0166 
0167     VertexFinder finder(cfg);
0168 
0169     VertexingOptions vertexingOptions(geoContext, magFieldContext);
0170 
0171     auto state = finder.makeState(magFieldContext);
0172     auto res = finder.find(inputTracks, vertexingOptions, state);
0173 
0174     BOOST_CHECK(res.ok());
0175 
0176     if (!res.ok()) {
0177       std::cout << res.error().message() << std::endl;
0178     }
0179 
0180     if (res.ok()) {
0181       BOOST_CHECK(!(*res).empty());
0182       Vector3 result = (*res).back().position();
0183       CHECK_CLOSE_ABS(result[eZ], z, 1_mm);
0184     }
0185   }
0186 }
0187 
0188 // Dummy user-defined InputTrackStub type
0189 struct InputTrackStub {
0190   explicit InputTrackStub(const BoundTrackParameters& params)
0191       : m_parameters(params) {}
0192 
0193   const BoundTrackParameters& parameters() const { return m_parameters; }
0194 
0195   // store e.g. link to original objects here
0196 
0197  private:
0198   BoundTrackParameters m_parameters;
0199 };
0200 
0201 ///
0202 /// @brief Unit test for ZScanVertexFinder with user-defined input track type
0203 ///
0204 BOOST_AUTO_TEST_CASE(zscan_finder_usertrack_test) {
0205   unsigned int nTests = 50;
0206 
0207   for (unsigned int iTest = 0; iTest < nTests; ++iTest) {
0208     // Number of tracks
0209     unsigned int nTracks = 30;
0210 
0211     // Set up RNG
0212     int mySeed = 31415;
0213     std::mt19937 gen(mySeed);
0214 
0215     // Set up constant B-Field
0216     auto bField = std::make_shared<ConstantBField>(Vector3{0.0, 0.0, 1_T});
0217 
0218     // Set up Eigenstepper
0219     EigenStepper<> stepper(bField);
0220 
0221     // Set up propagator with void navigator
0222     auto propagator = std::make_shared<Propagator>(stepper);
0223 
0224     // Create perigee surface
0225     std::shared_ptr<PerigeeSurface> perigeeSurface =
0226         Surface::makeShared<PerigeeSurface>(Vector3(0., 0., 0.));
0227 
0228     // Create position of vertex and perigee surface
0229     double x = vXYDist(gen);
0230     double y = vXYDist(gen);
0231     double z = vZDist(gen);
0232 
0233     // Calculate d0 and z0 corresponding to vertex position
0234     double d0_v = std::hypot(x, y);
0235     double z0_v = z;
0236 
0237     // Start constructing nTracks tracks in the following
0238     std::vector<InputTrackStub> tracks;
0239 
0240     // Construct random track emerging from vicinity of vertex position
0241     // Vector to store track objects used for vertex fit
0242     for (unsigned int iTrack = 0; iTrack < nTracks; iTrack++) {
0243       // Construct positive or negative charge randomly
0244       double q = qDist(gen) < 0 ? -1. : 1.;
0245 
0246       // Construct random track parameters
0247       BoundVector paramVec;
0248       double z0track = z0_v + z0Dist(gen);
0249       paramVec << d0_v + d0Dist(gen), z0track, phiDist(gen), thetaDist(gen),
0250           q / pTDist(gen), 0.;
0251 
0252       // Resolutions
0253       double resD0 = resIPDist(gen);
0254       double resZ0 = resIPDist(gen);
0255       double resPh = resAngDist(gen);
0256       double resTh = resAngDist(gen);
0257       double resQp = resQoPDist(gen);
0258 
0259       // Fill vector of track objects with simple covariance matrix
0260       Covariance covMat;
0261 
0262       covMat << resD0 * resD0, 0., 0., 0., 0., 0., 0., resZ0 * resZ0, 0., 0.,
0263           0., 0., 0., 0., resPh * resPh, 0., 0., 0., 0., 0., 0., resTh * resTh,
0264           0., 0., 0., 0., 0., 0., resQp * resQp, 0., 0., 0., 0., 0., 0., 1.;
0265 
0266       tracks.emplace_back(BoundTrackParameters(perigeeSurface, paramVec,
0267                                                std::move(covMat),
0268                                                ParticleHypothesis::pion()));
0269     }
0270 
0271     std::vector<InputTrack> inputTracks;
0272     for (const auto& trk : tracks) {
0273       inputTracks.emplace_back(&trk);
0274     }
0275 
0276     using VertexFinder = ZScanVertexFinder;
0277 
0278     ImpactPointEstimator::Config ipEstimatorCfg(bField, propagator);
0279     ImpactPointEstimator ipEstimator(ipEstimatorCfg);
0280 
0281     VertexFinder::Config cfg(ipEstimator);
0282 
0283     // Create a custom std::function to extract BoundTrackParameters from
0284     // user-defined InputTrackStub
0285     auto extractParameters = [](const InputTrack& params) {
0286       return params.as<InputTrackStub>()->parameters();
0287     };
0288 
0289     cfg.extractParameters.connect(extractParameters);
0290     VertexFinder finder(cfg);
0291     auto state = finder.makeState(magFieldContext);
0292 
0293     VertexingOptions vertexingOptions(geoContext, magFieldContext);
0294 
0295     auto res = finder.find(inputTracks, vertexingOptions, state);
0296 
0297     BOOST_CHECK(res.ok());
0298 
0299     if (!res.ok()) {
0300       std::cout << res.error().message() << std::endl;
0301     }
0302 
0303     if (res.ok()) {
0304       BOOST_CHECK(!(*res).empty());
0305       Vector3 result = (*res).back().position();
0306       CHECK_CLOSE_ABS(result[eZ], z, 1_mm);
0307     }
0308   }
0309 }
0310 
0311 }  // namespace Acts::Test