Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-17 08:31:30

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 #pragma once
0010 
0011 // Non-template part of the GX2F: equation system, scattering properties and
0012 // the backend functions. Kept apart from GlobalChiSquareFitter.hpp so the
0013 // backend translation units do not include the full fitter.
0014 
0015 #include "Acts/Definitions/Algebra.hpp"
0016 #include "Acts/Definitions/TrackParametrization.hpp"
0017 #include "Acts/EventData/BoundTrackParameters.hpp"
0018 #include "Acts/EventData/TrackStatePropMask.hpp"
0019 #include "Acts/Geometry/GeometryIdentifier.hpp"
0020 #include "Acts/Utilities/Logger.hpp"
0021 
0022 #include <cstddef>
0023 #include <string_view>
0024 #include <unordered_map>
0025 #include <vector>
0026 
0027 namespace Acts::Experimental {
0028 
0029 /// @addtogroup track_fitting
0030 /// @{
0031 
0032 namespace Gx2fConstants {
0033 constexpr std::string_view gx2fnUpdateColumn = "Gx2fnUpdateColumn";
0034 
0035 // Mask for the track states. We don't need Predicted and Filtered
0036 constexpr TrackStatePropMask trackStateMask = TrackStatePropMask::Smoothed |
0037                                               TrackStatePropMask::Jacobian |
0038                                               TrackStatePropMask::Calibrated;
0039 
0040 // A projector used for scattering. By using Jacobian * phiThetaProjector one
0041 // gets only the derivatives for the variables phi and theta.
0042 const Eigen::Matrix<double, eBoundSize, 2> phiThetaProjector = [] {
0043   Eigen::Matrix<double, eBoundSize, 2> m =
0044       Eigen::Matrix<double, eBoundSize, 2>::Zero();
0045   m(eBoundPhi, 0) = 1.0;
0046   m(eBoundTheta, 1) = 1.0;
0047   return m;
0048 }();
0049 }  // namespace Gx2fConstants
0050 
0051 /// @brief A container to store scattering properties for each material surface
0052 ///
0053 /// This struct holds the scattering angles, the inverse covariance of the
0054 /// material, and a validity flag indicating whether the material is valid for
0055 /// the scattering process.
0056 struct ScatteringProperties {
0057  public:
0058   /// @brief Constructor to initialize scattering properties.
0059   ///
0060   /// @param scatteringAngles_ The vector of scattering angles.
0061   /// @param invCovarianceMaterial_ The inverse covariance of the material.
0062   /// @param materialIsValid_ A boolean flag indicating whether the material is valid.
0063   ScatteringProperties(const BoundVector& scatteringAngles_,
0064                        const double invCovarianceMaterial_,
0065                        const bool materialIsValid_)
0066       : m_scatteringAngles(scatteringAngles_),
0067         m_invCovarianceMaterial(invCovarianceMaterial_),
0068         m_materialIsValid(materialIsValid_) {}
0069 
0070   /// @brief Accessor for the scattering angles (const version)
0071   /// @return Const reference to the vector of scattering angles
0072   const BoundVector& scatteringAngles() const { return m_scatteringAngles; }
0073 
0074   /// @brief Accessor for the scattering angles (mutable version)
0075   /// @return Mutable reference to the vector of scattering angles for modification
0076   BoundVector& scatteringAngles() { return m_scatteringAngles; }
0077 
0078   /// @brief Accessor for the inverse covariance of the material
0079   /// @return Inverse covariance value computed from material properties (e.g., Highland formula)
0080   double invCovarianceMaterial() const { return m_invCovarianceMaterial; }
0081 
0082   /// @brief Accessor for the material validity flag
0083   /// @return True if material is valid for scattering calculations, false for vacuum or zero thickness
0084   bool materialIsValid() const { return m_materialIsValid; }
0085 
0086  private:
0087   /// Vector of scattering angles. The vector is usually all zeros except for
0088   /// eBoundPhi and eBoundTheta.
0089   BoundVector m_scatteringAngles;
0090 
0091   /// Inverse covariance of the material. Compute with e.g. the Highland
0092   /// formula.
0093   double m_invCovarianceMaterial;
0094 
0095   /// Flag indicating whether the material is valid. Commonly vacuum and zero
0096   /// thickness material will be ignored.
0097   bool m_materialIsValid;
0098 };
0099 
0100 /// @brief A container to manage all properties of a gx2f system
0101 ///
0102 /// This struct manages the mathematical infrastructure for the gx2f. It
0103 /// initializes and maintains the extended aMatrix and extended bVector.
0104 struct Gx2fSystem {
0105  public:
0106   /// @brief Constructor to initialize matrices and vectors to zero based on specified dimensions.
0107   ///
0108   /// @param nDims Number of dimensions for the extended matrix and vector.
0109   explicit Gx2fSystem(std::size_t nDims)
0110       : m_nDims{nDims},
0111         m_aMatrix{Eigen::MatrixXd::Zero(nDims, nDims)},
0112         m_bVector{Eigen::VectorXd::Zero(nDims)} {}
0113 
0114   /// @brief Accessor for the number of dimensions of the extended system
0115   /// @return Number of dimensions for the aMatrix and bVector (bound parameters + scattering angles)
0116   std::size_t nDims() const { return m_nDims; }
0117 
0118   /// @brief Accessor for the accumulated chi-squared value (const version)
0119   /// @return Current sum of chi-squared contributions from measurements and material
0120   double chi2() const { return m_chi2; }
0121 
0122   /// @brief Accessor for the accumulated chi-squared value (mutable version)
0123   /// @return Mutable reference to chi-squared sum for modification during fitting
0124   double& chi2() { return m_chi2; }
0125 
0126   /// @brief Accessor for the extended system matrix (const version)
0127   /// @return Const reference to the aMatrix containing measurement and material contributions
0128   const Eigen::MatrixXd& aMatrix() const { return m_aMatrix; }
0129 
0130   /// @brief Accessor for the extended system matrix (mutable version)
0131   /// @return Mutable reference to the aMatrix for adding measurement and material contributions
0132   Eigen::MatrixXd& aMatrix() { return m_aMatrix; }
0133 
0134   /// @brief Accessor for the extended system vector (const version)
0135   /// @return Const reference to the bVector containing measurement and material contributions
0136   const Eigen::VectorXd& bVector() const { return m_bVector; }
0137 
0138   /// @brief Accessor for the extended system vector (mutable version)
0139   /// @return Mutable reference to the bVector for adding measurement and material contributions
0140   Eigen::VectorXd& bVector() { return m_bVector; }
0141 
0142   /// @brief Accessor for the number of degrees of freedom (const version)
0143   /// @return Current number of degrees of freedom from processed measurements
0144   std::size_t ndf() const { return m_ndf; }
0145 
0146   /// @brief Accessor for the number of degrees of freedom (mutable version)
0147   /// @return Mutable reference to NDF counter for incrementing during measurement processing
0148   std::size_t& ndf() { return m_ndf; }
0149 
0150   /// @brief Determines the minimum number of degrees of freedom required for the fit
0151   ///
0152   /// Automatically deduces the required NDF based on the system configuration.
0153   /// We have only 3 cases, because we always have l0, l1, phi, theta:
0154   /// - 4: no magnetic field -> q/p is empty
0155   /// - 5: no time measurement -> time is not fittable
0156   /// - 6: full fit with all parameters
0157   ///
0158   /// @return Required NDF based on which parameters can be fitted
0159   std::size_t findRequiredNdf() {
0160     std::size_t ndfSystem = 0;
0161     if (m_aMatrix(4, 4) == 0) {
0162       ndfSystem = 4;
0163     } else if (m_aMatrix(5, 5) == 0) {
0164       ndfSystem = 5;
0165     } else {
0166       ndfSystem = 6;
0167     }
0168 
0169     return ndfSystem;
0170   }
0171 
0172   /// @brief Checks if the system has sufficient degrees of freedom for fitting
0173   /// @return True if NDF exceeds the minimum required for the parameter configuration
0174   bool isWellDefined() { return m_ndf > findRequiredNdf(); }
0175 
0176  private:
0177   /// Number of dimensions of the (extended) system
0178   std::size_t m_nDims;
0179 
0180   /// Sum of chi-squared values.
0181   double m_chi2 = 0.;
0182 
0183   /// Extended matrix for accumulation.
0184   Eigen::MatrixXd m_aMatrix;
0185 
0186   /// Extended vector for accumulation.
0187   Eigen::VectorXd m_bVector;
0188 
0189   /// Number of degrees of freedom of the system
0190   std::size_t m_ndf = 0u;
0191 };
0192 
0193 /// @brief Adds a measurement to the GX2F equation system in a modular backend function.
0194 ///
0195 /// This function processes measurement data and integrates it into the GX2F
0196 /// system.
0197 ///
0198 /// @param extendedSystem All parameters of the current equation system to update.
0199 /// @param jacobianFromStart The Jacobian matrix from the start to the current state.
0200 /// @param covarianceMeasurement The covariance matrix of the measurement.
0201 /// @param predicted The predicted state vector based on the track state.
0202 /// @param measurement The measurement vector.
0203 /// @param projector The projection matrix.
0204 /// @param logger A logger instance.
0205 ///
0206 /// @note The dynamic Eigen matrices are suboptimal. We could think of
0207 /// templating again in the future on kMeasDims. We currently use dynamic
0208 /// matrices to reduce the memory during compile time.
0209 void addMeasurementToGx2fSumsBackend(
0210     Gx2fSystem& extendedSystem,
0211     const std::vector<BoundMatrix>& jacobianFromStart,
0212     const Eigen::MatrixXd& covarianceMeasurement, const BoundVector& predicted,
0213     const Eigen::VectorXd& measurement, const Eigen::MatrixXd& projector,
0214     const Logger& logger);
0215 
0216 /// @brief Solve the gx2f system to get the delta parameters for the update
0217 ///
0218 /// This function computes the delta parameters for the GX2F Actor fitting
0219 /// process by solving the linear equation system [a] * delta = b. It uses the
0220 /// column-pivoting Householder QR decomposition for numerical stability.
0221 ///
0222 /// @param extendedSystem All parameters of the current equation system
0223 /// @return Delta parameters for the GX2F update
0224 Eigen::VectorXd computeGx2fDeltaParams(const Gx2fSystem& extendedSystem);
0225 
0226 /// @brief Update parameters (and scattering angles if applicable)
0227 ///
0228 /// @param params Parameters to be updated
0229 /// @param deltaParamsExtended Delta parameters for bound parameter and scattering angles
0230 /// @param nMaterialSurfaces Number of material surfaces in the track
0231 /// @param scatteringMap Map of geometry identifiers to scattering properties,
0232 ///        containing all scattering angles and covariances
0233 /// @param geoIdVector Vector of geometry identifiers corresponding to material surfaces
0234 void updateGx2fParams(
0235     BoundTrackParameters& params, const Eigen::VectorXd& deltaParamsExtended,
0236     const std::size_t nMaterialSurfaces,
0237     std::unordered_map<GeometryIdentifier, ScatteringProperties>& scatteringMap,
0238     const std::vector<GeometryIdentifier>& geoIdVector);
0239 
0240 /// @brief Calculate and update the covariance of the fitted parameters
0241 ///
0242 /// This function calculates the covariance of the fitted parameters using
0243 /// cov = inv([a])
0244 /// It then updates the first square block of size ndfSystem. This ensures,
0245 /// that we only update the covariance for fitted parameters. (In case of
0246 /// no qop/time fit)
0247 ///
0248 /// @param fullCovariancePredicted The covariance matrix to update
0249 /// @param extendedSystem All parameters of the current equation system
0250 void updateGx2fCovarianceParams(BoundMatrix& fullCovariancePredicted,
0251                                 Gx2fSystem& extendedSystem);
0252 
0253 /// @}
0254 
0255 }  // namespace Acts::Experimental