File indexing completed on 2025-01-18 09:11:06
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/TrackParametrization.hpp"
0013 #include "Acts/EventData/MultiComponentTrackParameters.hpp"
0014 #include "Acts/EventData/MultiTrajectory.hpp"
0015 #include "Acts/EventData/TrackParameters.hpp"
0016 #include "Acts/EventData/Types.hpp"
0017 #include "Acts/Utilities/Logger.hpp"
0018
0019 #include <array>
0020 #include <cassert>
0021 #include <cmath>
0022 #include <cstddef>
0023 #include <iomanip>
0024 #include <map>
0025 #include <numeric>
0026 #include <ostream>
0027 #include <tuple>
0028 #include <vector>
0029
0030 namespace Acts {
0031
0032
0033 constexpr static double s_normalizationTolerance = 1.e-4;
0034
0035 namespace detail {
0036
0037 template <typename component_range_t, typename projector_t>
0038 bool weightsAreNormalized(const component_range_t &cmps,
0039 const projector_t &proj,
0040 double tol = s_normalizationTolerance) {
0041 double sumOfWeights = 0.0;
0042
0043 for (auto it = cmps.begin(); it != cmps.end(); ++it) {
0044 sumOfWeights += proj(*it);
0045 }
0046
0047 return std::abs(sumOfWeights - 1.0) < tol;
0048 }
0049
0050 template <typename component_range_t, typename projector_t>
0051 void normalizeWeights(component_range_t &cmps, const projector_t &proj) {
0052 double sumOfWeights = 0.0;
0053
0054
0055
0056 for (auto it = cmps.begin(); it != cmps.end(); ++it) {
0057 decltype(auto) cmp = *it;
0058 assert(std::isfinite(proj(cmp)) && "weight not finite in normalization");
0059 sumOfWeights += proj(cmp);
0060 }
0061
0062 assert(sumOfWeights > 0 && "sum of weights is not > 0");
0063
0064 for (auto it = cmps.begin(); it != cmps.end(); ++it) {
0065 decltype(auto) cmp = *it;
0066 proj(cmp) /= sumOfWeights;
0067 }
0068 }
0069
0070
0071
0072
0073
0074 template <typename propagator_state_t, typename stepper_t, typename navigator_t>
0075 class ScopedGsfInfoPrinterAndChecker {
0076 const propagator_state_t &m_state;
0077 const stepper_t &m_stepper;
0078 const navigator_t &m_navigator;
0079 double m_p_initial;
0080 const Logger &m_logger;
0081
0082 const Logger &logger() const { return m_logger; }
0083
0084 void print_component_stats() const {
0085 std::size_t i = 0;
0086 for (auto cmp : m_stepper.constComponentIterable(m_state.stepping)) {
0087 auto getVector = [&](auto idx) {
0088 return cmp.pars().template segment<3>(idx).transpose();
0089 };
0090 ACTS_VERBOSE(" #" << i++ << " pos: " << getVector(eFreePos0) << ", dir: "
0091 << getVector(eFreeDir0) << ", weight: " << cmp.weight()
0092 << ", status: " << cmp.status()
0093 << ", qop: " << cmp.pars()[eFreeQOverP]
0094 << ", det(cov): " << cmp.cov().determinant());
0095 }
0096 }
0097
0098 void checks(bool onStart) const {
0099 const auto cmps = m_stepper.constComponentIterable(m_state.stepping);
0100 [[maybe_unused]] const bool allFinite =
0101 std::all_of(cmps.begin(), cmps.end(),
0102 [](auto cmp) { return std::isfinite(cmp.weight()); });
0103 [[maybe_unused]] const bool allNormalized = detail::weightsAreNormalized(
0104 cmps, [](const auto &cmp) { return cmp.weight(); });
0105 [[maybe_unused]] const bool zeroComponents =
0106 m_stepper.numberComponents(m_state.stepping) == 0;
0107
0108 if (onStart) {
0109 assert(!zeroComponents && "no cmps at the start");
0110 assert(allFinite && "weights not finite at the start");
0111 assert(allNormalized && "not normalized at the start");
0112 } else {
0113 assert(!zeroComponents && "no cmps at the end");
0114 assert(allFinite && "weights not finite at the end");
0115 assert(allNormalized && "not normalized at the end");
0116 }
0117 }
0118
0119 public:
0120 ScopedGsfInfoPrinterAndChecker(const propagator_state_t &state,
0121 const stepper_t &stepper,
0122 const navigator_t &navigator,
0123 const Logger &logger)
0124 : m_state(state),
0125 m_stepper(stepper),
0126 m_navigator(navigator),
0127 m_p_initial(stepper.absoluteMomentum(state.stepping)),
0128 m_logger{logger} {
0129
0130 checks(true);
0131 ACTS_VERBOSE("Gsf step "
0132 << state.stepping.steps << " at mean position "
0133 << stepper.position(state.stepping).transpose()
0134 << " with direction "
0135 << stepper.direction(state.stepping).transpose()
0136 << " and momentum " << stepper.absoluteMomentum(state.stepping)
0137 << " and charge " << stepper.charge(state.stepping));
0138 ACTS_VERBOSE("Propagation is in " << state.options.direction << " mode");
0139 print_component_stats();
0140 }
0141
0142 ~ScopedGsfInfoPrinterAndChecker() {
0143 if (m_navigator.currentSurface(m_state.navigation)) {
0144 const auto p_final = m_stepper.absoluteMomentum(m_state.stepping);
0145 ACTS_VERBOSE("Component status at end of step:");
0146 print_component_stats();
0147 ACTS_VERBOSE("Delta Momentum = " << std::setprecision(5)
0148 << p_final - m_p_initial);
0149 }
0150 checks(false);
0151 }
0152 };
0153
0154 double calculateDeterminant(
0155 const double *fullCalibratedCovariance,
0156 TrackStateTraits<MultiTrajectoryTraits::MeasurementSizeMax,
0157 true>::Covariance predictedCovariance,
0158 BoundSubspaceIndices projector, unsigned int calibratedSize);
0159
0160
0161
0162
0163
0164 template <typename traj_t>
0165 void computePosteriorWeights(
0166 const traj_t &mt, const std::vector<MultiTrajectoryTraits::IndexType> &tips,
0167 std::map<MultiTrajectoryTraits::IndexType, double> &weights) {
0168
0169
0170
0171
0172 const auto minChi2 =
0173 mt.getTrackState(*std::min_element(tips.begin(), tips.end(),
0174 [&](const auto &a, const auto &b) {
0175 return mt.getTrackState(a).chi2() <
0176 mt.getTrackState(b).chi2();
0177 }))
0178 .chi2();
0179
0180
0181 for (auto tip : tips) {
0182 const auto state = mt.getTrackState(tip);
0183 const double chi2 = state.chi2() - minChi2;
0184 const double detR = calculateDeterminant(
0185
0186
0187
0188 state
0189 .template calibratedCovariance<
0190 MultiTrajectoryTraits::MeasurementSizeMax>()
0191 .data(),
0192 state.predictedCovariance(), state.projectorSubspaceIndices(),
0193 state.calibratedSize());
0194
0195 if (detR <= 0) {
0196
0197 continue;
0198 }
0199
0200 const auto factor = std::sqrt(1. / detR) * safeExp(-0.5 * chi2);
0201
0202 if (!std::isfinite(factor)) {
0203
0204 continue;
0205 }
0206
0207 weights.at(tip) *= factor;
0208 }
0209 }
0210
0211
0212
0213 enum class StatesType { ePredicted, eFiltered, eSmoothed };
0214
0215 inline std::ostream &operator<<(std::ostream &os, StatesType type) {
0216 constexpr static std::array names = {"predicted", "filtered", "smoothed"};
0217 os << names[static_cast<int>(type)];
0218 return os;
0219 }
0220
0221
0222
0223
0224 template <StatesType type, typename traj_t>
0225 struct MultiTrajectoryProjector {
0226 const traj_t &mt;
0227 const std::map<MultiTrajectoryTraits::IndexType, double> &weights;
0228
0229 auto operator()(MultiTrajectoryTraits::IndexType idx) const {
0230 const auto proxy = mt.getTrackState(idx);
0231 switch (type) {
0232 case StatesType::ePredicted:
0233 return std::make_tuple(weights.at(idx), proxy.predicted(),
0234 proxy.predictedCovariance());
0235 case StatesType::eFiltered:
0236 return std::make_tuple(weights.at(idx), proxy.filtered(),
0237 proxy.filteredCovariance());
0238 case StatesType::eSmoothed:
0239 return std::make_tuple(weights.at(idx), proxy.smoothed(),
0240 proxy.smoothedCovariance());
0241 default:
0242 throw std::invalid_argument(
0243 "Incorrect StatesType, should be ePredicted"
0244 ", eFiltered, or eSmoothed.");
0245 }
0246 }
0247 };
0248
0249
0250
0251
0252 template <typename T>
0253 class Updatable {
0254 T m_tmp{};
0255 T m_val{};
0256
0257 public:
0258 Updatable() : m_tmp(0), m_val(0) {}
0259
0260 T &tmp() { return m_tmp; }
0261 void update() { m_val = m_tmp; }
0262
0263 const T &val() const { return m_val; }
0264 };
0265
0266 }
0267 }