File indexing completed on 2025-08-05 08:09:30
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/Utilities/BinningType.hpp"
0015 #include "Acts/Utilities/TypeTraits.hpp"
0016
0017 #include <array>
0018 #include <limits>
0019
0020 #include "Eigen/Dense"
0021
0022 namespace Acts::VectorHelpers {
0023
0024 namespace detail {
0025 template <class T>
0026 using phi_method_t = decltype(std::declval<const T>().phi());
0027
0028 template <class T>
0029 using has_phi_method = Concepts::is_detected<phi_method_t, T>;
0030 }
0031
0032
0033
0034
0035
0036
0037
0038 template <typename Derived>
0039 double phi(const Eigen::MatrixBase<Derived>& v) noexcept {
0040 constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
0041 if constexpr (rows != -1) {
0042
0043 static_assert(rows >= 2,
0044 "Phi function not valid for vectors not at least 2D");
0045 } else {
0046
0047 assert(v.rows() >= 2 &&
0048 "Phi function not valid for vectors not at least 2D");
0049 }
0050 return std::atan2(v[1], v[0]);
0051 }
0052
0053
0054
0055
0056
0057
0058 template <typename T,
0059 std::enable_if_t<detail::has_phi_method<T>::value, int> = 0>
0060 double phi(const T& v) noexcept {
0061 return v.phi();
0062 }
0063
0064
0065
0066
0067
0068
0069
0070 template <typename Derived>
0071 double perp(const Eigen::MatrixBase<Derived>& v) noexcept {
0072 constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
0073 if constexpr (rows != -1) {
0074
0075 static_assert(rows >= 2,
0076 "Perp function not valid for vectors not at least 2D");
0077 } else {
0078
0079 assert(v.rows() >= 2 &&
0080 "Perp function not valid for vectors not at least 2D");
0081 }
0082 return std::hypot(v[0], v[1]);
0083 }
0084
0085
0086
0087
0088
0089
0090
0091 template <typename Derived>
0092 double theta(const Eigen::MatrixBase<Derived>& v) noexcept {
0093 constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
0094 if constexpr (rows != -1) {
0095
0096 static_assert(rows == 3, "Theta function not valid for non-3D vectors.");
0097 } else {
0098
0099 assert(v.rows() == 3 && "Theta function not valid for non-3D vectors.");
0100 }
0101
0102 return std::atan2(perp(v), v[2]);
0103 }
0104
0105
0106
0107
0108
0109
0110
0111 template <typename Derived>
0112 double eta(const Eigen::MatrixBase<Derived>& v) noexcept {
0113 constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
0114 if constexpr (rows != -1) {
0115
0116 static_assert(rows == 3, "Eta function not valid for non-3D vectors.");
0117 } else {
0118
0119 assert(v.rows() == 3 && "Eta function not valid for non-3D vectors.");
0120 }
0121
0122 if (v[0] == 0. && v[1] == 0.) {
0123 return std::copysign(std::numeric_limits<double>::infinity(), v[2]);
0124 } else {
0125 return std::asinh(v[2] / perp(v));
0126 }
0127 }
0128
0129
0130
0131
0132
0133
0134 inline std::array<ActsScalar, 4> evaluateTrigonomics(const Vector3& direction) {
0135 const ActsScalar x = direction(0);
0136 const ActsScalar y = direction(1);
0137 const ActsScalar z = direction(2);
0138
0139 const ActsScalar cosTheta = z;
0140 const ActsScalar sinTheta = std::sqrt(1 - z * z);
0141 assert(sinTheta != 0 &&
0142 "VectorHelpers: Vector is parallel to the z-axis "
0143 "which leads to division by zero");
0144 const ActsScalar invSinTheta = 1. / sinTheta;
0145 const ActsScalar cosPhi = x * invSinTheta;
0146 const ActsScalar sinPhi = y * invSinTheta;
0147
0148 return {cosPhi, sinPhi, cosTheta, sinTheta};
0149 }
0150
0151
0152
0153
0154
0155 inline double cast(const Vector3& position, BinningValue bval) {
0156 switch (bval) {
0157 case binX:
0158 return position[0];
0159 case binY:
0160 return position[1];
0161 case binZ:
0162 return position[2];
0163 case binR:
0164 return perp(position);
0165 case binPhi:
0166 return phi(position);
0167 case binRPhi:
0168 return perp(position) * phi(position);
0169 case binH:
0170 return theta(position);
0171 case binEta:
0172 return eta(position);
0173 case binMag:
0174 return position.norm();
0175 default:
0176 assert(false && "Invalid BinningValue enum value");
0177 return std::numeric_limits<double>::quiet_NaN();
0178 }
0179 }
0180
0181
0182
0183
0184
0185
0186
0187 inline ActsMatrix<3, 3> cross(const ActsMatrix<3, 3>& m, const Vector3& v) {
0188 ActsMatrix<3, 3> r;
0189 r.col(0) = m.col(0).cross(v);
0190 r.col(1) = m.col(1).cross(v);
0191 r.col(2) = m.col(2).cross(v);
0192
0193 return r;
0194 }
0195
0196
0197 inline auto position(const Vector4& pos4) {
0198 return pos4.segment<3>(ePos0);
0199 }
0200
0201
0202 inline auto position(const FreeVector& params) {
0203 return params.segment<3>(eFreePos0);
0204 }
0205
0206
0207 template <typename vector3_t>
0208 inline auto makeVector4(const Eigen::MatrixBase<vector3_t>& vec3,
0209 typename vector3_t::Scalar w)
0210 -> Eigen::Matrix<typename vector3_t::Scalar, 4, 1> {
0211 EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(vector3_t, 3);
0212
0213 Eigen::Matrix<typename vector3_t::Scalar, 4, 1> vec4;
0214 vec4[ePos0] = vec3[ePos0];
0215 vec4[ePos1] = vec3[ePos1];
0216 vec4[ePos2] = vec3[ePos2];
0217 vec4[eTime] = w;
0218 return vec4;
0219 }
0220
0221
0222
0223
0224
0225
0226 inline std::pair<double, double> incidentAngles(
0227 const Acts::Vector3& direction,
0228 const Acts::RotationMatrix3& globalToLocal) {
0229 Acts::Vector3 trfDir = globalToLocal * direction;
0230
0231
0232 double phi = std::atan2(trfDir[2], trfDir[0]);
0233 double theta = std::atan2(trfDir[2], trfDir[1]);
0234 return {phi, theta};
0235 }
0236
0237 }