Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
VectorHelpers.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file VectorHelpers.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-2023 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
16 
17 #include <array>
18 #include <limits>
19 
20 #include "Eigen/Dense"
21 
22 namespace Acts {
23 namespace VectorHelpers {
24 
25 namespace detail {
26 template <class T>
27 using phi_method_t = decltype(std::declval<const T>().phi());
28 
29 template <class T>
31 } // namespace detail
32 
39 template <typename Derived>
40 double phi(const Eigen::MatrixBase<Derived>& v) noexcept {
41  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
42  if constexpr (rows != -1) {
43  // static size, do compile time check
44  static_assert(rows >= 2,
45  "Phi function not valid for vectors not at least 2D");
46  } else {
47  // dynamic size
48  assert(v.rows() >= 2 &&
49  "Phi function not valid for vectors not at least 2D");
50  }
51  return std::atan2(v[1], v[0]);
52 }
53 
59 template <typename T,
61 double phi(const T& v) noexcept {
62  return v.phi();
63 }
64 
71 template <typename Derived>
72 double perp(const Eigen::MatrixBase<Derived>& v) noexcept {
73  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
74  if constexpr (rows != -1) {
75  // static size, do compile time check
76  static_assert(rows >= 2,
77  "Perp function not valid for vectors not at least 2D");
78  } else {
79  // dynamic size
80  assert(v.rows() >= 2 &&
81  "Perp function not valid for vectors not at least 2D");
82  }
83  return std::hypot(v[0], v[1]);
84 }
85 
92 template <typename Derived>
93 double theta(const Eigen::MatrixBase<Derived>& v) noexcept {
94  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
95  if constexpr (rows != -1) {
96  // static size, do compile time check
97  static_assert(rows == 3, "Theta function not valid for non-3D vectors.");
98  } else {
99  // dynamic size
100  assert(v.rows() == 3 && "Theta function not valid for non-3D vectors.");
101  }
102 
103  return std::atan2(perp(v), v[2]);
104 }
105 
112 template <typename Derived>
113 double eta(const Eigen::MatrixBase<Derived>& v) noexcept {
114  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
115  if constexpr (rows != -1) {
116  // static size, do compile time check
117  static_assert(rows == 3, "Eta function not valid for non-3D vectors.");
118  } else {
119  // dynamic size
120  assert(v.rows() == 3 && "Eta function not valid for non-3D vectors.");
121  }
122 
123  if (v[0] == 0. && v[1] == 0.) {
124  return std::copysign(std::numeric_limits<double>::infinity(), v[2]);
125  } else {
126  return std::asinh(v[2] / perp(v));
127  }
128 }
129 
135 inline std::array<ActsScalar, 5> evaluateTrigonomics(const Vector3& direction) {
136  const ActsScalar x = direction(0); // == cos(phi) * sin(theta)
137  const ActsScalar y = direction(1); // == sin(phi) * sin(theta)
138  const ActsScalar z = direction(2); // == cos(theta)
139  // can be turned into cosine/sine
140  const ActsScalar cosTheta = z;
141  const ActsScalar sinTheta = std::hypot(x, y);
142  const ActsScalar invSinTheta = 1. / sinTheta;
143  const ActsScalar cosPhi = x * invSinTheta;
144  const ActsScalar sinPhi = y * invSinTheta;
145 
146  return {cosPhi, sinPhi, cosTheta, sinTheta, invSinTheta};
147 }
148 
153 inline double cast(const Vector3& position, BinningValue bval) {
154  switch (bval) {
155  case binX:
156  return position[0];
157  case binY:
158  return position[1];
159  case binZ:
160  return position[2];
161  case binR:
162  return perp(position);
163  case binPhi:
164  return phi(position);
165  case binRPhi:
166  return perp(position) * phi(position);
167  case binH:
168  return theta(position);
169  case binEta:
170  return eta(position);
171  case binMag:
172  return position.norm();
173  default:
174  assert(false and "Invalid BinningValue enum value");
175  return std::numeric_limits<double>::quiet_NaN();
176  }
177 }
178 
187  r.col(0) = m.col(0).cross(v);
188  r.col(1) = m.col(1).cross(v);
189  r.col(2) = m.col(2).cross(v);
190 
191  return r;
192 }
193 
195 inline auto position(const Vector4& pos4) {
196  return pos4.segment<3>(ePos0);
197 }
198 
200 inline auto position(const FreeVector& params) {
201  return params.segment<3>(eFreePos0);
202 }
203 
205 template <typename vector3_t>
206 inline auto makeVector4(const Eigen::MatrixBase<vector3_t>& vec3,
207  typename vector3_t::Scalar w)
208  -> Eigen::Matrix<typename vector3_t::Scalar, 4, 1> {
209  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(vector3_t, 3);
210 
211  Eigen::Matrix<typename vector3_t::Scalar, 4, 1> vec4;
212  vec4[ePos0] = vec3[ePos0];
213  vec4[ePos1] = vec3[ePos1];
214  vec4[ePos2] = vec3[ePos2];
215  vec4[eTime] = w;
216  return vec4;
217 }
218 
224 inline std::pair<double, double> incidentAngles(
225  const Acts::Vector3& direction,
226  const Acts::RotationMatrix3& globalToLocal) {
227  Acts::Vector3 trfDir = globalToLocal * direction;
228  // The angles are defined with respect to the measurement axis
229  // i.e. "head-on" == pi/2, parallel = 0
230  double phi = std::atan2(trfDir[2], trfDir[0]);
231  double theta = std::atan2(trfDir[2], trfDir[1]);
232  return {phi, theta};
233 }
234 
235 } // namespace VectorHelpers
236 } // namespace Acts