Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2019 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/tools/output_test_stream.hpp>
0011 #include <boost/test/unit_test.hpp>
0012 
0013 #include "Acts/Definitions/Algebra.hpp"
0014 #include "Acts/Definitions/Direction.hpp"
0015 #include "Acts/Definitions/TrackParametrization.hpp"
0016 #include "Acts/Definitions/Units.hpp"
0017 #include "Acts/EventData/GenericBoundTrackParameters.hpp"
0018 #include "Acts/EventData/TrackParameters.hpp"
0019 #include "Acts/Geometry/GeometryContext.hpp"
0020 #include "Acts/Geometry/GeometryIdentifier.hpp"
0021 #include "Acts/MagneticField/ConstantBField.hpp"
0022 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0023 #include "Acts/Propagator/EigenStepper.hpp"
0024 #include "Acts/Propagator/Propagator.hpp"
0025 #include "Acts/Surfaces/PerigeeSurface.hpp"
0026 #include "Acts/Surfaces/Surface.hpp"
0027 #include "Acts/Utilities/Result.hpp"
0028 #include "Acts/Vertexing/HelicalTrackLinearizer.hpp"
0029 #include "Acts/Vertexing/ImpactPointEstimator.hpp"
0030 #include "Acts/Vertexing/KalmanVertexUpdater.hpp"
0031 #include "Acts/Vertexing/LinearizedTrack.hpp"
0032 #include "Acts/Vertexing/TrackAtVertex.hpp"
0033 #include "Acts/Vertexing/Vertex.hpp"
0034 
0035 #include <algorithm>
0036 #include <array>
0037 #include <cmath>
0038 #include <iostream>
0039 #include <memory>
0040 #include <optional>
0041 #include <random>
0042 #include <tuple>
0043 #include <type_traits>
0044 #include <utility>
0045 #include <vector>
0046 
0047 namespace bdata = boost::unit_test::data;
0048 using namespace Acts::UnitLiterals;
0049 
0050 namespace Acts::Test {
0051 
0052 using Covariance = BoundSquareMatrix;
0053 using Propagator = Acts::Propagator<EigenStepper<>>;
0054 using Linearizer = HelicalTrackLinearizer;
0055 
0056 // Create a test context
0057 GeometryContext geoContext = GeometryContext();
0058 MagneticFieldContext magFieldContext = MagneticFieldContext();
0059 
0060 // Vertex x/y position distribution
0061 std::uniform_real_distribution<double> vXYDist(-0.1_mm, 0.1_mm);
0062 // Vertex z position distribution
0063 std::uniform_real_distribution<double> vZDist(-20_mm, 20_mm);
0064 // Track d0 distribution
0065 std::uniform_real_distribution<double> d0Dist(-0.01_mm, 0.01_mm);
0066 // Track z0 distribution
0067 std::uniform_real_distribution<double> z0Dist(-0.2_mm, 0.2_mm);
0068 // Track pT distribution
0069 std::uniform_real_distribution<double> pTDist(0.4_GeV, 10_GeV);
0070 // Track phi distribution
0071 std::uniform_real_distribution<double> phiDist(-M_PI, M_PI);
0072 // Track theta distribution
0073 std::uniform_real_distribution<double> thetaDist(1.0, M_PI - 1.0);
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 // Number of vertices per test event distribution
0083 
0084 ///
0085 /// @brief Unit test for KalmanVertexUpdater
0086 ///
0087 BOOST_AUTO_TEST_CASE(Kalman_Vertex_Updater) {
0088   bool debug = false;
0089 
0090   // Number of tests
0091   unsigned int nTests = 10;
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   // Linearizer for BoundTrackParameters type test
0107   Linearizer::Config ltConfig;
0108   ltConfig.bField = bField;
0109   ltConfig.propagator = propagator;
0110   Linearizer linearizer(ltConfig);
0111   auto fieldCache = bField->makeCache(magFieldContext);
0112 
0113   // Create perigee surface at origin
0114   std::shared_ptr<PerigeeSurface> perigeeSurface =
0115       Surface::makeShared<PerigeeSurface>(Vector3(0., 0., 0.));
0116 
0117   // Creates a random tracks around origin and a random vertex.
0118   // VertexUpdater adds track to vertex and updates the position
0119   // which should afterwards be closer to the origin/track
0120   for (unsigned int i = 0; i < nTests; ++i) {
0121     if (debug) {
0122       std::cout << "Test " << i + 1 << std::endl;
0123     }
0124     // Construct positive or negative charge randomly
0125     double q = qDist(gen) < 0 ? -1. : 1.;
0126 
0127     // Construct random track parameters around origin
0128     BoundTrackParameters::ParametersVector paramVec;
0129 
0130     paramVec << d0Dist(gen), z0Dist(gen), phiDist(gen), thetaDist(gen),
0131         q / pTDist(gen), 0.;
0132 
0133     if (debug) {
0134       std::cout << "Creating track parameters: " << paramVec << std::endl;
0135     }
0136 
0137     // Fill vector of track objects with simple covariance matrix
0138     Covariance covMat;
0139 
0140     // Resolutions
0141     double res_d0 = resIPDist(gen);
0142     double res_z0 = resIPDist(gen);
0143     double res_ph = resAngDist(gen);
0144     double res_th = resAngDist(gen);
0145     double res_qp = resQoPDist(gen);
0146 
0147     covMat << res_d0 * res_d0, 0., 0., 0., 0., 0., 0., res_z0 * res_z0, 0., 0.,
0148         0., 0., 0., 0., res_ph * res_ph, 0., 0., 0., 0., 0., 0.,
0149         res_th * res_th, 0., 0., 0., 0., 0., 0., res_qp * res_qp, 0., 0., 0.,
0150         0., 0., 0., 1.;
0151     BoundTrackParameters params(perigeeSurface, paramVec, std::move(covMat),
0152                                 ParticleHypothesis::pion());
0153 
0154     std::shared_ptr<PerigeeSurface> perigee =
0155         Surface::makeShared<PerigeeSurface>(Vector3::Zero());
0156 
0157     // Linearized state of the track
0158     LinearizedTrack linTrack =
0159         linearizer
0160             .linearizeTrack(params, 0, *perigee, geoContext, magFieldContext,
0161                             fieldCache)
0162             .value();
0163 
0164     // Create TrackAtVertex
0165     TrackAtVertex trkAtVtx(0., params, InputTrack{&params});
0166 
0167     // Set linearized state of trackAtVertex
0168     trkAtVtx.linearizedState = linTrack;
0169     trkAtVtx.isLinearized = true;
0170 
0171     // Create a vertex
0172     Vector3 vtxPos(vXYDist(gen), vXYDist(gen), vZDist(gen));
0173     Vertex vtx(vtxPos);
0174     vtx.setFullCovariance(SquareMatrix4::Identity() * 0.01);
0175 
0176     // Update trkAtVertex with assumption of originating from vtx
0177     KalmanVertexUpdater::updateVertexWithTrack(vtx, trkAtVtx, 3);
0178 
0179     if (debug) {
0180       std::cout << "Old vertex position: " << vtxPos << std::endl;
0181       std::cout << "New vertex position: " << vtx.position() << std::endl;
0182     }
0183 
0184     double oldDistance = vtxPos.norm();
0185     double newDistance = vtx.position().norm();
0186 
0187     if (debug) {
0188       std::cout << "Old distance: " << oldDistance << std::endl;
0189       std::cout << "New distance: " << newDistance << std::endl;
0190     }
0191 
0192     // After update, vertex should be closer to the track
0193     BOOST_CHECK_LT(newDistance, oldDistance);
0194 
0195     // Note: KalmanVertexUpdater updates the vertex w.r.t. the
0196     // newly given track, but does NOT add the track to the
0197     // TrackAtVertex list. Has to be done manually after calling
0198     // the update method.
0199     BOOST_CHECK(vtx.tracks().empty());
0200 
0201   }  // end for loop
0202 
0203 }  // end test case
0204 
0205 ///
0206 /// @brief Unit test for KalmanVertexTrackUpdater
0207 ///
0208 BOOST_AUTO_TEST_CASE(Kalman_Vertex_TrackUpdater) {
0209   bool debug = true;
0210 
0211   // Number of tests
0212   unsigned int nTests = 10;
0213 
0214   // Set up RNG
0215   int mySeed = 31415;
0216   std::mt19937 gen(mySeed);
0217 
0218   // Set up constant B-Field
0219   auto bField = std::make_shared<ConstantBField>(Vector3{0.0, 0.0, 1_T});
0220 
0221   // Set up Eigenstepper
0222   EigenStepper<> stepper(bField);
0223 
0224   // Set up propagator with void navigator
0225   auto propagator = std::make_shared<Propagator>(stepper);
0226 
0227   // Set up ImpactPointEstimator, used for comparisons later
0228   ImpactPointEstimator::Config ip3dEstConfig(bField, propagator);
0229   ImpactPointEstimator ip3dEst(ip3dEstConfig);
0230   ImpactPointEstimator::State state{bField->makeCache(magFieldContext)};
0231 
0232   // Set up HelicalTrackLinearizer, needed for linearizing the tracks
0233   // Linearizer for BoundTrackParameters type test
0234   Linearizer::Config ltConfig;
0235   ltConfig.bField = bField;
0236   ltConfig.propagator = propagator;
0237   Linearizer linearizer(ltConfig);
0238   auto fieldCache = bField->makeCache(magFieldContext);
0239 
0240   // Create perigee surface at origin
0241   std::shared_ptr<PerigeeSurface> perigeeSurface =
0242       Surface::makeShared<PerigeeSurface>(Vector3(0., 0., 0.));
0243 
0244   // Create random tracks around origin and a random vertex.
0245   // Update tracks with the assumption that they originate from
0246   // the vertex position and check if they are closer to the
0247   // vertex after the update process
0248   for (unsigned int i = 0; i < nTests; ++i) {
0249     // Construct positive or negative charge randomly
0250     double q = qDist(gen) < 0 ? -1. : 1.;
0251 
0252     // Construct random track parameters
0253     BoundTrackParameters::ParametersVector paramVec;
0254 
0255     paramVec << d0Dist(gen), z0Dist(gen), phiDist(gen), thetaDist(gen),
0256         q / pTDist(gen), 0.;
0257 
0258     if (debug) {
0259       std::cout << "Creating track parameters: " << paramVec << std::endl;
0260     }
0261 
0262     // Fill vector of track objects with simple covariance matrix
0263     Covariance covMat;
0264 
0265     // Resolutions
0266     double res_d0 = resIPDist(gen);
0267     double res_z0 = resIPDist(gen);
0268     double res_ph = resAngDist(gen);
0269     double res_th = resAngDist(gen);
0270     double res_qp = resQoPDist(gen);
0271 
0272     covMat << res_d0 * res_d0, 0., 0., 0., 0., 0., 0., res_z0 * res_z0, 0., 0.,
0273         0., 0., 0., 0., res_ph * res_ph, 0., 0., 0., 0., 0., 0.,
0274         res_th * res_th, 0., 0., 0., 0., 0., 0., res_qp * res_qp, 0., 0., 0.,
0275         0., 0., 0., 1.;
0276     BoundTrackParameters params(perigeeSurface, paramVec, std::move(covMat),
0277                                 ParticleHypothesis::pion());
0278 
0279     std::shared_ptr<PerigeeSurface> perigee =
0280         Surface::makeShared<PerigeeSurface>(Vector3::Zero());
0281 
0282     // Linearized state of the track
0283     LinearizedTrack linTrack =
0284         linearizer
0285             .linearizeTrack(params, 0, *perigee, geoContext, magFieldContext,
0286                             fieldCache)
0287             .value();
0288 
0289     // Create TrackAtVertex
0290     TrackAtVertex trkAtVtx(0., params, InputTrack{&params});
0291 
0292     // Set linearized state of trackAtVertex
0293     trkAtVtx.linearizedState = linTrack;
0294     trkAtVtx.isLinearized = true;
0295 
0296     // Copy parameters for later comparison of old and new version
0297     auto fittedParamsCopy = trkAtVtx.fittedParams;
0298 
0299     // Create a vertex
0300     Vector3 vtxPos(vXYDist(gen), vXYDist(gen), vZDist(gen));
0301     Vertex vtx(vtxPos);
0302 
0303     // Update trkAtVertex with assumption of originating from vtx
0304     KalmanVertexUpdater::updateTrackWithVertex(trkAtVtx, vtx, 3);
0305 
0306     // The old distance
0307     double oldDistance =
0308         ip3dEst.calculateDistance(geoContext, fittedParamsCopy, vtxPos, state)
0309             .value();
0310 
0311     // The new distance after update
0312     double newDistance =
0313         ip3dEst
0314             .calculateDistance(geoContext, trkAtVtx.fittedParams, vtxPos, state)
0315             .value();
0316     if (debug) {
0317       std::cout << "Old distance: " << oldDistance << std::endl;
0318       std::cout << "New distance: " << newDistance << std::endl;
0319     }
0320 
0321     // Parameters should have changed
0322     BOOST_CHECK_NE(fittedParamsCopy, trkAtVtx.fittedParams);
0323 
0324     // After update, track should be closer to the vertex
0325     BOOST_CHECK_LT(newDistance, oldDistance);
0326 
0327   }  // end for loop
0328 
0329 }  // end test case
0330 
0331 }  // namespace Acts::Test