Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:35

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2021-2022 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 "Acts/EventData/detail/CorrectedTransformationFreeToBound.hpp"
0010 
0011 #include "Acts/Definitions/TrackParametrization.hpp"
0012 #include "Acts/EventData/TransformationHelpers.hpp"
0013 #include "Acts/Surfaces/RegularSurface.hpp"
0014 #include "Acts/Surfaces/Surface.hpp"
0015 #include "Acts/Utilities/Intersection.hpp"
0016 #include "Acts/Utilities/Result.hpp"
0017 #include "Acts/Utilities/ThrowAssert.hpp"
0018 
0019 #include <algorithm>
0020 #include <cmath>
0021 #include <cstddef>
0022 #include <memory>
0023 #include <ostream>
0024 #include <type_traits>
0025 #include <utility>
0026 #include <vector>
0027 
0028 Acts::FreeToBoundCorrection::FreeToBoundCorrection(bool apply_,
0029                                                    ActsScalar alpha_,
0030                                                    ActsScalar beta_)
0031     : apply(apply_), alpha(alpha_), beta(beta_) {}
0032 
0033 Acts::FreeToBoundCorrection::FreeToBoundCorrection(bool apply_)
0034     : apply(apply_) {}
0035 
0036 Acts::FreeToBoundCorrection::operator bool() const {
0037   return apply;
0038 }
0039 
0040 Acts::detail::CorrectedFreeToBoundTransformer::CorrectedFreeToBoundTransformer(
0041     ActsScalar alpha, ActsScalar beta, ActsScalar cosIncidentAngleMinCutoff,
0042     ActsScalar cosIncidentAngleMaxCutoff)
0043     : m_alpha(alpha),
0044       m_beta(beta),
0045       m_cosIncidentAngleMinCutoff(cosIncidentAngleMinCutoff),
0046       m_cosIncidentAngleMaxCutoff(cosIncidentAngleMaxCutoff) {}
0047 
0048 Acts::detail::CorrectedFreeToBoundTransformer::CorrectedFreeToBoundTransformer(
0049     const FreeToBoundCorrection& freeToBoundCorrection) {
0050   m_alpha = freeToBoundCorrection.alpha;
0051   m_beta = freeToBoundCorrection.beta;
0052   m_cosIncidentAngleMinCutoff = freeToBoundCorrection.cosIncidentAngleMinCutoff;
0053   m_cosIncidentAngleMaxCutoff = freeToBoundCorrection.cosIncidentAngleMaxCutoff;
0054 }
0055 
0056 std::optional<std::tuple<Acts::BoundVector, Acts::BoundSquareMatrix>>
0057 Acts::detail::CorrectedFreeToBoundTransformer::operator()(
0058     const Acts::FreeVector& freeParams,
0059     const Acts::FreeSquareMatrix& freeCovariance, const Acts::Surface& surface,
0060     const Acts::GeometryContext& geoContext, Direction navDir,
0061     const Logger& logger) const {
0062   // Get the incidence angle
0063   Vector3 dir = freeParams.segment<3>(eFreeDir0);
0064   Vector3 normal =
0065       surface.normal(geoContext, freeParams.segment<3>(eFreePos0), dir);
0066   ActsScalar absCosIncidenceAng = std::abs(dir.dot(normal));
0067   // No correction if the incidentAngle is small enough (not necessary ) or too
0068   // large (correction could be invalid). Fall back to nominal free to bound
0069   // transformation
0070   if (absCosIncidenceAng < m_cosIncidentAngleMinCutoff ||
0071       absCosIncidenceAng > m_cosIncidentAngleMaxCutoff) {
0072     ACTS_VERBOSE("Incident angle: " << std::acos(absCosIncidenceAng)
0073                                     << " is out of range for correction");
0074     return std::nullopt;
0075   }
0076 
0077   // The number of sigma points
0078   std::size_t sampleSize = 2 * eFreeSize + 1;
0079   // The sampled free parameters, the weight for measurement W_m and weight for
0080   // covariance, W_c
0081   std::vector<std::tuple<FreeVector, ActsScalar, ActsScalar>> sampledFreeParams;
0082   sampledFreeParams.reserve(sampleSize);
0083 
0084   // Initialize the covariance sqrt root matrix
0085   FreeSquareMatrix covSqrt = FreeSquareMatrix::Zero();
0086   // SVD decomposition: freeCovariance = U*S*U^T here
0087   Eigen::JacobiSVD<FreeSquareMatrix> svd(
0088       freeCovariance, Eigen::ComputeFullU | Eigen::ComputeFullV);
0089   auto S = svd.singularValues();
0090   FreeMatrix U = svd.matrixU();
0091   // Get the sqrt root matrix of S
0092   FreeMatrix D = FreeMatrix::Zero();
0093   for (unsigned i = 0; i < eFreeSize; ++i) {
0094     if (S(i) > 0) {
0095       D(i, i) = std::sqrt(S(i));
0096     }
0097   }
0098   // Get the covariance sqrt root matrix
0099   covSqrt = U * D;
0100 
0101   // Define kappa = alpha*alpha*N
0102   ActsScalar kappa = m_alpha * m_alpha * static_cast<double>(eFreeSize);
0103   // lambda = alpha*alpha*N - N
0104   ActsScalar lambda = kappa - static_cast<double>(eFreeSize);
0105   // gamma = sqrt(labmda + N)
0106   ActsScalar gamma = std::sqrt(kappa);
0107 
0108   // Sample the free parameters
0109   // 1. the nominal parameter
0110   sampledFreeParams.push_back(
0111       {freeParams, lambda / kappa,
0112        lambda / kappa + (1.0 - m_alpha * m_alpha + m_beta)});
0113   // 2. the shifted parameters
0114   for (unsigned i = 0; i < eFreeSize; ++i) {
0115     sampledFreeParams.push_back(
0116         {freeParams + covSqrt.col(i) * gamma, 0.5 / kappa, 0.5 / kappa});
0117     sampledFreeParams.push_back(
0118         {freeParams - covSqrt.col(i) * gamma, 0.5 / kappa, 0.5 / kappa});
0119   }
0120 
0121   // Initialize the mean of the bound parameters
0122   BoundVector bpMean = BoundVector::Zero();
0123   // Initialize the bound covariance
0124   BoundSquareMatrix bv = BoundSquareMatrix::Zero();
0125 
0126   // The transformed bound parameters and weight for each sampled free
0127   // parameters
0128   std::vector<std::pair<BoundVector, ActsScalar>> transformedBoundParams;
0129 
0130   // 1. The nominal one
0131   // The sampled free parameters, the weight for measurement W_m and weight for
0132   // covariance, W_c
0133   const auto& [paramsNom, mweightNom, cweightNom] = sampledFreeParams[0];
0134   // Transform the free to bound
0135   auto nominalRes =
0136       transformFreeToBoundParameters(paramsNom, surface, geoContext);
0137   // Not successful, fall back to nominal free to bound transformation
0138   if (!nominalRes.ok()) {
0139     ACTS_WARNING(
0140         "Free to bound transformation for nominal free parameters failed.");
0141     return std::nullopt;
0142   }
0143   auto nominalBound = nominalRes.value();
0144   transformedBoundParams.push_back({nominalBound, cweightNom});
0145   bpMean = bpMean + mweightNom * nominalBound;
0146 
0147   // 2. Loop over the rest sample points of the free parameters to get the
0148   // corrected bound parameters
0149   for (unsigned i = 1; i < sampledFreeParams.size(); ++i) {
0150     const auto& [params, mweight, cweight] = sampledFreeParams[i];
0151     FreeVector correctedFreeParams = params;
0152 
0153     // Reintersect to get the corrected free params without boundary check
0154     SurfaceIntersection intersection =
0155         surface
0156             .intersect(geoContext, params.segment<3>(eFreePos0),
0157                        navDir * params.segment<3>(eFreeDir0),
0158                        BoundaryCheck(false))
0159             .closest();
0160     correctedFreeParams.segment<3>(eFreePos0) = intersection.position();
0161 
0162     // Transform the free to bound
0163     auto result = transformFreeToBoundParameters(correctedFreeParams, surface,
0164                                                  geoContext);
0165     // Not successful, fall back to nominal free to bound transformation
0166     if (!result.ok()) {
0167       ACTS_WARNING(
0168           "Free to bound transformation for sampled free parameters: \n"
0169           << correctedFreeParams << " failed.");
0170       return std::nullopt;
0171     }
0172 
0173     auto bp = result.value();
0174     transformedBoundParams.push_back({bp, cweight});
0175     bpMean = bpMean + mweight * bp;
0176   }
0177 
0178   // Get the corrected bound covariance
0179   for (unsigned isample = 0; isample < sampleSize; ++isample) {
0180     BoundVector bSigma = transformedBoundParams[isample].first - bpMean;
0181 
0182     bv = bv +
0183          transformedBoundParams[isample].second * bSigma * bSigma.transpose();
0184   }
0185 
0186   return std::make_tuple(bpMean, bv);
0187 }