File indexing completed on 2025-01-18 09:11:19
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_, double alpha_,
0029 double beta_)
0030 : apply(apply_), alpha(alpha_), beta(beta_) {}
0031
0032 Acts::FreeToBoundCorrection::FreeToBoundCorrection(bool apply_)
0033 : apply(apply_) {}
0034
0035 Acts::FreeToBoundCorrection::operator bool() const {
0036 return apply;
0037 }
0038
0039 Acts::detail::CorrectedFreeToBoundTransformer::CorrectedFreeToBoundTransformer(
0040 double alpha, double beta, double cosIncidentAngleMinCutoff,
0041 double cosIncidentAngleMaxCutoff)
0042 : m_alpha(alpha),
0043 m_beta(beta),
0044 m_cosIncidentAngleMinCutoff(cosIncidentAngleMinCutoff),
0045 m_cosIncidentAngleMaxCutoff(cosIncidentAngleMaxCutoff) {}
0046
0047 Acts::detail::CorrectedFreeToBoundTransformer::CorrectedFreeToBoundTransformer(
0048 const FreeToBoundCorrection& freeToBoundCorrection) {
0049 m_alpha = freeToBoundCorrection.alpha;
0050 m_beta = freeToBoundCorrection.beta;
0051 m_cosIncidentAngleMinCutoff = freeToBoundCorrection.cosIncidentAngleMinCutoff;
0052 m_cosIncidentAngleMaxCutoff = freeToBoundCorrection.cosIncidentAngleMaxCutoff;
0053 }
0054
0055 std::optional<std::tuple<Acts::BoundVector, Acts::BoundSquareMatrix>>
0056 Acts::detail::CorrectedFreeToBoundTransformer::operator()(
0057 const Acts::FreeVector& freeParams,
0058 const Acts::FreeSquareMatrix& freeCovariance, const Acts::Surface& surface,
0059 const Acts::GeometryContext& geoContext, Direction navDir,
0060 const Logger& logger) const {
0061
0062 Vector3 dir = freeParams.segment<3>(eFreeDir0);
0063 Vector3 normal =
0064 surface.normal(geoContext, freeParams.segment<3>(eFreePos0), dir);
0065 double absCosIncidenceAng = std::abs(dir.dot(normal));
0066
0067
0068
0069 if (absCosIncidenceAng < m_cosIncidentAngleMinCutoff ||
0070 absCosIncidenceAng > m_cosIncidentAngleMaxCutoff) {
0071 ACTS_VERBOSE("Incident angle: " << std::acos(absCosIncidenceAng)
0072 << " is out of range for correction");
0073 return std::nullopt;
0074 }
0075
0076
0077 std::size_t sampleSize = 2 * eFreeSize + 1;
0078
0079
0080 std::vector<std::tuple<FreeVector, double, double>> sampledFreeParams;
0081 sampledFreeParams.reserve(sampleSize);
0082
0083
0084 FreeSquareMatrix covSqrt = FreeSquareMatrix::Zero();
0085
0086 Eigen::JacobiSVD<FreeSquareMatrix> svd(
0087 freeCovariance, Eigen::ComputeFullU | Eigen::ComputeFullV);
0088 auto S = svd.singularValues();
0089 FreeMatrix U = svd.matrixU();
0090
0091 FreeMatrix D = FreeMatrix::Zero();
0092 for (unsigned i = 0; i < eFreeSize; ++i) {
0093 if (S(i) > 0) {
0094 D(i, i) = std::sqrt(S(i));
0095 }
0096 }
0097
0098 covSqrt = U * D;
0099
0100
0101 double kappa = m_alpha * m_alpha * static_cast<double>(eFreeSize);
0102
0103 double lambda = kappa - static_cast<double>(eFreeSize);
0104
0105 double gamma = std::sqrt(kappa);
0106
0107
0108
0109 sampledFreeParams.push_back(
0110 {freeParams, lambda / kappa,
0111 lambda / kappa + (1.0 - m_alpha * m_alpha + m_beta)});
0112
0113 for (unsigned i = 0; i < eFreeSize; ++i) {
0114 sampledFreeParams.push_back(
0115 {freeParams + covSqrt.col(i) * gamma, 0.5 / kappa, 0.5 / kappa});
0116 sampledFreeParams.push_back(
0117 {freeParams - covSqrt.col(i) * gamma, 0.5 / kappa, 0.5 / kappa});
0118 }
0119
0120
0121 BoundVector bpMean = BoundVector::Zero();
0122
0123 BoundSquareMatrix bv = BoundSquareMatrix::Zero();
0124
0125
0126
0127 std::vector<std::pair<BoundVector, double>> transformedBoundParams;
0128
0129
0130
0131
0132 const auto& [paramsNom, mweightNom, cweightNom] = sampledFreeParams[0];
0133
0134 auto nominalRes =
0135 transformFreeToBoundParameters(paramsNom, surface, geoContext);
0136
0137 if (!nominalRes.ok()) {
0138 ACTS_WARNING(
0139 "Free to bound transformation for nominal free parameters failed.");
0140 return std::nullopt;
0141 }
0142 auto nominalBound = nominalRes.value();
0143 transformedBoundParams.push_back({nominalBound, cweightNom});
0144 bpMean = bpMean + mweightNom * nominalBound;
0145
0146
0147
0148 for (unsigned i = 1; i < sampledFreeParams.size(); ++i) {
0149 const auto& [params, mweight, cweight] = sampledFreeParams[i];
0150 FreeVector correctedFreeParams = params;
0151
0152
0153 SurfaceIntersection intersection =
0154 surface
0155 .intersect(geoContext, params.segment<3>(eFreePos0),
0156 navDir * params.segment<3>(eFreeDir0),
0157 BoundaryTolerance::Infinite())
0158 .closest();
0159 correctedFreeParams.segment<3>(eFreePos0) = intersection.position();
0160
0161
0162 auto result = transformFreeToBoundParameters(correctedFreeParams, surface,
0163 geoContext);
0164
0165 if (!result.ok()) {
0166 ACTS_WARNING(
0167 "Free to bound transformation for sampled free parameters: \n"
0168 << correctedFreeParams << " failed.");
0169 return std::nullopt;
0170 }
0171
0172 auto bp = result.value();
0173 transformedBoundParams.push_back({bp, cweight});
0174 bpMean = bpMean + mweight * bp;
0175 }
0176
0177
0178 for (unsigned isample = 0; isample < sampleSize; ++isample) {
0179 BoundVector bSigma = transformedBoundParams[isample].first - bpMean;
0180
0181 bv = bv +
0182 transformedBoundParams[isample].second * bSigma * bSigma.transpose();
0183 }
0184
0185 return std::make_tuple(bpMean, bv);
0186 }