File indexing completed on 2025-08-28 08:12:00
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Seeding/detail/FastStrawLineFitter.hpp"
0010
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Utilities/StringHelpers.hpp"
0013 #include "Acts/Utilities/detail/periodic.hpp"
0014
0015 #include <format>
0016
0017 using namespace Acts::UnitLiterals;
0018
0019 namespace {
0020
0021
0022 constexpr double inDeg(const double x) {
0023 return x / 1._degree;
0024 }
0025 std::string printThetaStep(const double theta, const double thetaPrime,
0026 const double thetaTwoPrime) {
0027 return std::format(
0028 "-- theta: {:.3f}, thetaPrime: {:.3f}, thetaTwoPrime: {:.3f} --> "
0029 "step-size: {:.8f}",
0030 inDeg(theta), inDeg(thetaPrime), inDeg(thetaTwoPrime),
0031 inDeg(thetaPrime / thetaTwoPrime));
0032 }
0033 }
0034 namespace Acts::Experimental::detail {
0035
0036 void FastStrawLineFitter::FitAuxiliaries::print(std::ostream& ostr) const {
0037 ostr << std::format("T_zzyy: {:.3f}, ", T_zzyy)
0038 << std::format("T_yz: {:.3f}, ", T_yz)
0039 << std::format("T_rz: {:.3f}, ", T_rz)
0040 << std::format("T_ry: {:.3f}, ", T_ry)
0041 << std::format("centre ( {:.3f}, {:3f}), ", centerY, centerZ)
0042 << std::format("y0: {:.3f}", fitY0)
0043 << std::format(", norm: {:.3f}", covNorm) << ", nDoF: " << nDoF;
0044 }
0045 void FastStrawLineFitter::FitResult::print(std::ostream& ostr) const {
0046 ostr << "# iteration: " << nIter << ", nDoF: " << nDoF << ", chi2: " << chi2
0047 << ", chi2 / nDoF: " << (chi2 / static_cast<double>(nDoF)) << ",\n";
0048 ostr << std::format("theta: {:.3f} pm {:.3f}, ", inDeg(theta), inDeg(dTheta))
0049 << std::format("y0: {:.3f} pm {:.3f}", y0, dY0);
0050 }
0051
0052 using Vector = FastStrawLineFitter::Vector;
0053 const Acts::Logger& FastStrawLineFitter::logger() const {
0054 assert(m_logger != nullptr);
0055 return *m_logger;
0056 }
0057 FastStrawLineFitter::FastStrawLineFitter(const Config& cfg,
0058 std::unique_ptr<const Logger> logger)
0059 : m_cfg{cfg}, m_logger{std::move(logger)} {}
0060
0061 inline void FastStrawLineFitter::calcAngularDerivatives(
0062 const TrigonomHelper& angles, const FitAuxiliaries& fitPars,
0063 double& thetaPrime, double& thetaTwoPrime) const {
0064 thetaPrime = 0.5 * fitPars.T_zzyy * angles.sinTwoTheta -
0065 fitPars.T_yz * angles.cosTwoTheta -
0066 fitPars.T_rz * angles.cosTheta - fitPars.T_ry * angles.sinTheta;
0067 thetaTwoPrime = fitPars.T_zzyy * angles.cosTwoTheta +
0068 2. * fitPars.T_yz * angles.sinTwoTheta +
0069 fitPars.T_rz * angles.sinTheta -
0070 fitPars.T_ry * angles.cosTheta;
0071 }
0072 double FastStrawLineFitter::startTheta(const FitAuxiliaries& fitPars) {
0073 double thetaGuess =
0074 std::atan2(2. * (fitPars.T_yz - fitPars.T_ry), fitPars.T_zzyy) / 2.;
0075 return Acts::detail::wrap_periodic(thetaGuess, 0., std::numbers::pi);
0076 }
0077 void FastStrawLineFitter::completeResult(const FitAuxiliaries& fitPars,
0078 const double thetaTwoPrime,
0079 FitResult& result) const {
0080 result.dTheta = std::sqrt(1. / thetaTwoPrime);
0081 const double tanTheta = std::tan(result.theta);
0082 const double secTheta = 1. / std::cos(result.theta);
0083 result.y0 =
0084 fitPars.centerY - fitPars.centerZ * tanTheta + fitPars.fitY0 * secTheta;
0085 result.dY0 = Acts::fastHypot(-fitPars.centerZ * Acts::square(secTheta) +
0086 fitPars.fitY0 * secTheta * tanTheta,
0087 secTheta);
0088
0089 result.dY0 *= result.dTheta;
0090 ACTS_DEBUG(__func__ << "() - " << __LINE__ << ": Fit succeeded " << result);
0091 }
0092
0093 std::optional<FastStrawLineFitter::FitResult> FastStrawLineFitter::fit(
0094 const FitAuxiliaries& fitPars) const {
0095
0096 if (fitPars.nDoF == 0u) {
0097 return std::nullopt;
0098 }
0099 ACTS_DEBUG(__func__ << "() - " << __LINE__ << ": Input fit parameters "
0100 << fitPars);
0101
0102 const double thetaGuess = startTheta(fitPars);
0103 ACTS_DEBUG(__func__ << "() - " << __LINE__
0104 << ": Start fast fit seed theta: " << inDeg(thetaGuess));
0105
0106 FitResult result{};
0107 result.theta = thetaGuess;
0108 result.nDoF = fitPars.nDoF;
0109
0110 double thetaPrime{0.};
0111 double thetaTwoPrime{0.};
0112 while (result.nIter <= m_cfg.maxIter) {
0113 ++result.nIter;
0114 const TrigonomHelper angles{result.theta};
0115 calcAngularDerivatives(angles, fitPars, thetaPrime, thetaTwoPrime);
0116 const double update = thetaPrime / thetaTwoPrime;
0117 ACTS_VERBOSE(
0118 __func__ << "() - " << __LINE__ << ": Fit iteration #" << result.nIter
0119 << " "
0120 << printThetaStep(result.theta, thetaPrime, thetaTwoPrime));
0121
0122 if (std::abs(update) < m_cfg.precCutOff) {
0123 completeResult(fitPars, thetaTwoPrime, result);
0124 return result;
0125 }
0126 result.theta -= update;
0127 }
0128
0129 ACTS_WARNING(
0130 __func__ << "() - " << __LINE__
0131 << ": The fast straw fit did not converge " << fitPars << ", \n"
0132 << printThetaStep(result.theta, thetaPrime, thetaTwoPrime)
0133 << "\n"
0134 << result);
0135 return std::nullopt;
0136 }
0137
0138 }