EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Helpers.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Helpers.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-2018 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 
10 // AlgebraHelper.h, Acts project
12 
13 #pragma once
14 
19 
20 #include <bitset>
21 #include <cassert>
22 #include <cmath>
23 #include <cstdlib>
24 #include <iomanip>
25 #include <iostream>
26 #include <memory>
27 #include <string>
28 #include <vector>
29 
30 #define ACTS_CHECK_BIT(value, mask) ((value & mask) == mask)
31 
32 namespace Acts {
33 
34 namespace VectorHelpers {
35 namespace detail {
36 template <class T>
37 using phi_method_t = decltype(std::declval<const T>().phi());
38 
39 template <class T>
41 
42 } // namespace detail
43 
50 template <typename Derived>
51 double phi(const Eigen::MatrixBase<Derived>& v) noexcept {
52  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
53  if constexpr (rows != -1) {
54  // static size, do compile time check
55  static_assert(rows >= 2,
56  "Phi function not valid for vectors not at least 2D");
57  } else {
58  // dynamic size
59  if (v.rows() < 2) {
60  std::cerr << "Phi function not valid for vectors not at least 2D"
61  << std::endl;
62  std::abort();
63  }
64  }
65 
66  return std::atan2(v[1], v[0]);
67 }
68 
74 template <typename T,
76 double phi(const T& v) noexcept {
77  return v.phi();
78 }
79 
86 template <typename Derived>
87 double perp(const Eigen::MatrixBase<Derived>& v) noexcept {
88  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
89  if constexpr (rows != -1) {
90  // static size, do compile time check
91  static_assert(rows >= 2,
92  "Perp function not valid for vectors not at least 2D");
93  } else {
94  // dynamic size
95  if (v.rows() < 2) {
96  std::cerr << "Perp function not valid for vectors not at least 2D"
97  << std::endl;
98  std::abort();
99  }
100  }
101  return std::sqrt(v[0] * v[0] + v[1] * v[1]);
102 }
103 
110 template <typename Derived>
111 double theta(const Eigen::MatrixBase<Derived>& v) noexcept {
112  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
113  if constexpr (rows != -1) {
114  // static size, do compile time check
115  static_assert(rows >= 3, "Theta function not valid for non-3D vectors.");
116  } else {
117  // dynamic size
118  if (v.rows() < 3) {
119  std::cerr << "Theta function not valid for non-3D vectors." << std::endl;
120  std::abort();
121  }
122  }
123 
124  return std::atan2(std::sqrt(v[0] * v[0] + v[1] * v[1]), v[2]);
125 }
126 
133 template <typename Derived>
134 double eta(const Eigen::MatrixBase<Derived>& v) noexcept {
135  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
136  if constexpr (rows != -1) {
137  // static size, do compile time check
138  static_assert(rows >= 3, "Eta function not valid for non-3D vectors.");
139  } else {
140  // dynamic size
141  if (v.rows() < 3) {
142  std::cerr << "Eta function not valid for non-3D vectors." << std::endl;
143  std::abort();
144  }
145  }
146 
147  return std::atanh(v[2] / v.norm());
148 }
149 
154 inline double cast(const Vector3D& position, BinningValue bval) {
155  switch (bval) {
156  case binX:
157  return position[0];
158  case binY:
159  return position[1];
160  case binZ:
161  return position[2];
162  case binR:
163  return perp(position);
164  case binPhi:
165  return phi(position);
166  case binRPhi:
167  return perp(position) * phi(position);
168  case binH:
169  return theta(position);
170  case binEta:
171  return eta(position);
172  case binMag:
173  return position.norm();
174  default:
175  assert(false and "Invalid BinningValue enum value");
176  return std::numeric_limits<double>::quiet_NaN();
177  }
178 }
179 
188  r.col(0) = m.col(0).cross(v);
189  r.col(1) = m.col(1).cross(v);
190  r.col(2) = m.col(2).cross(v);
191 
192  return r;
193 }
194 
196 inline auto position(const Vector4D& pos4) {
197  return pos4.segment<3>(ePos0);
198 }
199 
201 inline auto position(const FreeVector& params) {
202  return params.segment<3>(eFreePos0);
203 }
204 
206 template <typename vector3_t>
207 inline auto makeVector4(const Eigen::MatrixBase<vector3_t>& vec3,
208  typename vector3_t::Scalar w)
209  -> Eigen::Matrix<typename vector3_t::Scalar, 4, 1> {
210  EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(vector3_t, 3);
211 
212  Eigen::Matrix<typename vector3_t::Scalar, 4, 1> vec4;
213  vec4[ePos0] = vec3[ePos0];
214  vec4[ePos1] = vec3[ePos1];
215  vec4[ePos2] = vec3[ePos2];
216  vec4[eTime] = w;
217  return vec4;
218 }
219 
220 } // namespace VectorHelpers
221 
222 namespace detail {
223 
224 inline double roundWithPrecision(double val, int precision) {
225  if (val < 0 && std::abs(val) * std::pow(10, precision) < 1.) {
226  return -val;
227  }
228  return val;
229 }
230 } // namespace detail
231 
237 inline std::string toString(const ActsMatrixXd& matrix, int precision = 4,
238  const std::string& offset = "") {
239  std::ostringstream sout;
240 
241  sout << std::setiosflags(std::ios::fixed) << std::setprecision(precision);
242  if (matrix.cols() == 1) {
243  sout << "(";
244  for (int i = 0; i < matrix.rows(); ++i) {
245  double val = detail::roundWithPrecision(matrix(i, 0), precision);
246  sout << val;
247  if (i != matrix.rows() - 1) {
248  sout << ", ";
249  }
250  }
251  sout << ")";
252  } else {
253  for (int i = 0; i < matrix.rows(); ++i) {
254  for (int j = 0; j < matrix.cols(); ++j) {
255  if (j == 0) {
256  sout << "(";
257  }
258  double val = detail::roundWithPrecision(matrix(i, j), precision);
259  sout << val;
260  if (j == matrix.cols() - 1) {
261  sout << ")";
262  } else {
263  sout << ", ";
264  }
265  }
266  if (i != matrix.rows() -
267  1) { // make the end line and the offset in the next line
268  sout << std::endl;
269  sout << offset;
270  }
271  }
272  }
273  return sout.str();
274 }
275 
280 inline std::string toString(const Acts::Translation3D& translation,
281  int precision = 4) {
282  Acts::Vector3D trans;
283  trans[0] = translation.x();
284  trans[1] = translation.y();
285  trans[2] = translation.z();
286  return toString(trans, precision);
287 }
288 
294 inline std::string toString(const Acts::Transform3D& transform,
295  int precision = 4, const std::string& offset = "") {
296  std::ostringstream sout;
297  sout << "Translation : " << toString(transform.translation(), precision)
298  << std::endl;
299  std::string rotationOffset = offset + " ";
300  sout << offset << "Rotation : "
301  << toString(transform.rotation(), precision + 2, rotationOffset);
302  return sout.str();
303 }
304 
310 template <typename T>
311 std::vector<T*> unpack_shared_vector(
312  const std::vector<std::shared_ptr<T>>& items) {
313  std::vector<T*> rawPtrs;
314  rawPtrs.reserve(items.size());
315  for (const std::shared_ptr<T>& item : items) {
316  rawPtrs.push_back(item.get());
317  }
318  return rawPtrs;
319 }
320 
326 template <typename T>
327 std::vector<const T*> unpack_shared_vector(
328  const std::vector<std::shared_ptr<const T>>& items) {
329  std::vector<const T*> rawPtrs;
330  rawPtrs.reserve(items.size());
331  for (const std::shared_ptr<const T>& item : items) {
332  rawPtrs.push_back(item.get());
333  }
334  return rawPtrs;
335 }
336 
354 template <template <size_t> class Callable, size_t N, size_t NMAX,
355  typename... Args>
356 decltype(Callable<N>::invoke(std::declval<Args>()...)) template_switch(
357  size_t v, Args&&... args) {
358  if (v == N) {
359  return Callable<N>::invoke(std::forward<Args>(args)...);
360  }
361  if constexpr (N < NMAX) {
362  return template_switch<Callable, N + 1, NMAX>(v,
363  std::forward<Args>(args)...);
364  }
365  std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
366  << ") is not valid (v > NMAX)" << std::endl;
367  std::abort();
368 }
369 
377 template <typename MatrixType>
378 MatrixType bitsetToMatrix(const std::bitset<MatrixType::RowsAtCompileTime *
379  MatrixType::ColsAtCompileTime>
380  bs) {
381  constexpr int rows = MatrixType::RowsAtCompileTime;
382  constexpr int cols = MatrixType::ColsAtCompileTime;
383 
384  static_assert(rows != -1 && cols != -1,
385  "bitsetToMatrix does not support dynamic matrices");
386 
387  MatrixType m;
388  auto* p = m.data();
389  for (size_t i = 0; i < rows * cols; i++) {
390  p[i] = bs[rows * cols - 1 - i];
391  }
392  return m;
393 }
394 
401 template <typename Derived>
402 auto matrixToBitset(const Eigen::PlainObjectBase<Derived>& m) {
403  using MatrixType = Eigen::PlainObjectBase<Derived>;
404  constexpr size_t rows = MatrixType::RowsAtCompileTime;
405  constexpr size_t cols = MatrixType::ColsAtCompileTime;
406 
407  std::bitset<rows * cols> res;
408 
409  auto* p = m.data();
410  for (size_t i = 0; i < rows * cols; i++) {
411  res[rows * cols - 1 - i] = p[i];
412  }
413 
414  return res;
415 }
416 
417 } // namespace Acts