File indexing completed on 2025-08-05 08:09:35
0001
0002
0003
0004
0005
0006
0007
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
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
0068
0069
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
0078 std::size_t sampleSize = 2 * eFreeSize + 1;
0079
0080
0081 std::vector<std::tuple<FreeVector, ActsScalar, ActsScalar>> sampledFreeParams;
0082 sampledFreeParams.reserve(sampleSize);
0083
0084
0085 FreeSquareMatrix covSqrt = FreeSquareMatrix::Zero();
0086
0087 Eigen::JacobiSVD<FreeSquareMatrix> svd(
0088 freeCovariance, Eigen::ComputeFullU | Eigen::ComputeFullV);
0089 auto S = svd.singularValues();
0090 FreeMatrix U = svd.matrixU();
0091
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
0099 covSqrt = U * D;
0100
0101
0102 ActsScalar kappa = m_alpha * m_alpha * static_cast<double>(eFreeSize);
0103
0104 ActsScalar lambda = kappa - static_cast<double>(eFreeSize);
0105
0106 ActsScalar gamma = std::sqrt(kappa);
0107
0108
0109
0110 sampledFreeParams.push_back(
0111 {freeParams, lambda / kappa,
0112 lambda / kappa + (1.0 - m_alpha * m_alpha + m_beta)});
0113
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
0122 BoundVector bpMean = BoundVector::Zero();
0123
0124 BoundSquareMatrix bv = BoundSquareMatrix::Zero();
0125
0126
0127
0128 std::vector<std::pair<BoundVector, ActsScalar>> transformedBoundParams;
0129
0130
0131
0132
0133 const auto& [paramsNom, mweightNom, cweightNom] = sampledFreeParams[0];
0134
0135 auto nominalRes =
0136 transformFreeToBoundParameters(paramsNom, surface, geoContext);
0137
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
0148
0149 for (unsigned i = 1; i < sampledFreeParams.size(); ++i) {
0150 const auto& [params, mweight, cweight] = sampledFreeParams[i];
0151 FreeVector correctedFreeParams = params;
0152
0153
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
0163 auto result = transformFreeToBoundParameters(correctedFreeParams, surface,
0164 geoContext);
0165
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
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 }