ECCE @ 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 
15 #include <bitset>
16 #include <cmath>
17 #include <cstdlib>
18 #include <iomanip>
19 #include <iostream>
20 #include <memory>
21 #include <string>
22 #include <vector>
23 
28 
29 #define ACTS_CHECK_BIT(value, mask) ((value & mask) == mask)
30 
34 namespace Acts {
35 
50 namespace VectorHelpers {
51 namespace detail {
52 template <class T>
53 using phi_method_t = decltype(std::declval<const T>().phi());
54 
55 template <class T>
57 
58 } // namespace detail
59 
66 template <typename Derived>
67 double phi(const Eigen::MatrixBase<Derived>& v) noexcept {
68  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
69  if constexpr (rows != -1) {
70  // static size, do compile time check
71  static_assert(rows >= 2,
72  "Phi function not valid for vectors not at least 2D");
73  } else {
74  // dynamic size
75  if (v.rows() < 2) {
76  std::cerr << "Phi function not valid for vectors not at least 2D"
77  << std::endl;
78  std::abort();
79  }
80  }
81 
82  return std::atan2(v[1], v[0]);
83 }
84 
90 template <typename T,
92 double phi(const T& v) noexcept {
93  return v.phi();
94 }
95 
102 template <typename Derived>
103 double perp(const Eigen::MatrixBase<Derived>& v) noexcept {
104  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
105  if constexpr (rows != -1) {
106  // static size, do compile time check
107  static_assert(rows >= 2,
108  "Perp function not valid for vectors not at least 2D");
109  } else {
110  // dynamic size
111  if (v.rows() < 2) {
112  std::cerr << "Perp function not valid for vectors not at least 2D"
113  << std::endl;
114  std::abort();
115  }
116  }
117  return std::sqrt(v[0] * v[0] + v[1] * v[1]);
118 }
119 
126 template <typename Derived>
127 double theta(const Eigen::MatrixBase<Derived>& v) noexcept {
128  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
129  if constexpr (rows != -1) {
130  // static size, do compile time check
131  static_assert(rows >= 3, "Theta function not valid for non-3D vectors.");
132  } else {
133  // dynamic size
134  if (v.rows() < 3) {
135  std::cerr << "Theta function not valid for non-3D vectors." << std::endl;
136  std::abort();
137  }
138  }
139 
140  return std::atan2(std::sqrt(v[0] * v[0] + v[1] * v[1]), v[2]);
141 }
142 
149 template <typename Derived>
150 double eta(const Eigen::MatrixBase<Derived>& v) noexcept {
151  constexpr int rows = Eigen::MatrixBase<Derived>::RowsAtCompileTime;
152  if constexpr (rows != -1) {
153  // static size, do compile time check
154  static_assert(rows >= 3, "Eta function not valid for non-3D vectors.");
155  } else {
156  // dynamic size
157  if (v.rows() < 3) {
158  std::cerr << "Eta function not valid for non-3D vectors." << std::endl;
159  std::abort();
160  }
161  }
162 
163  return std::atanh(v[2] / v.norm());
164 }
165 
171 static double cast(const Vector3D& position, BinningValue bval) {
172  if (bval < 3)
173  return position[bval];
174  switch (bval) {
175  case binR:
176  return perp(position);
177  break;
178  case binPhi:
179  return phi(position);
180  break;
181  case binH:
182  return theta(position);
183  break;
184  case binEta:
185  return eta(position);
186  break;
187  case binMag:
188  return position.norm();
189  break;
190  }
191  return 0.;
192 }
193 
202  r.col(0) = m.col(0).cross(v);
203  r.col(1) = m.col(1).cross(v);
204  r.col(2) = m.col(2).cross(v);
205 
206  return r;
207 }
208 
213 inline ParValue_t& time(SpacePointVector& spacePointVec) {
214  return spacePointVec[3];
215 }
216 
222 inline const ParValue_t& time(const SpacePointVector& spacePointVec) {
223  return spacePointVec[3];
224 }
225 
230 inline ParValue_t& time(BoundVector& boundVec) {
231  return boundVec[eT];
232 }
233 
239 inline const ParValue_t& time(const BoundVector& boundVec) {
240  return boundVec[eT];
241 }
242 
247 inline ParValue_t& time(FreeVector& freeVec) {
248  return freeVec[7];
249 }
250 
256 inline const ParValue_t& time(const FreeVector& freeVec) {
257  return freeVec[7];
258 }
259 
264 inline auto position(SpacePointVector& spacePointVec) {
265  return spacePointVec.head<3>();
266 }
267 
273 inline auto position(const SpacePointVector& spacePointVec) {
274  return spacePointVec.head<3>();
275 }
276 
282 inline auto position(FreeVector& freeVec) {
283  return freeVec.head<3>();
284 }
285 
291 inline auto position(const FreeVector& freeVec) {
292  return freeVec.head<3>();
293 }
294 
295 } // namespace VectorHelpers
296 
297 namespace detail {
298 
299 inline double roundWithPrecision(double val, int precision) {
300  if (val < 0 && std::abs(val) * std::pow(10, precision) < 1.) {
301  return -val;
302  }
303  return val;
304 }
305 } // namespace detail
306 
312 inline std::string toString(const ActsMatrixXd& matrix, int precision = 4,
313  const std::string& offset = "") {
314  std::ostringstream sout;
315 
316  sout << std::setiosflags(std::ios::fixed) << std::setprecision(precision);
317  if (matrix.cols() == 1) {
318  sout << "(";
319  for (int i = 0; i < matrix.rows(); ++i) {
320  double val = detail::roundWithPrecision(matrix(i, 0), precision);
321  sout << val;
322  if (i != matrix.rows() - 1) {
323  sout << ", ";
324  }
325  }
326  sout << ")";
327  } else {
328  for (int i = 0; i < matrix.rows(); ++i) {
329  for (int j = 0; j < matrix.cols(); ++j) {
330  if (j == 0) {
331  sout << "(";
332  }
333  double val = detail::roundWithPrecision(matrix(i, j), precision);
334  sout << val;
335  if (j == matrix.cols() - 1) {
336  sout << ")";
337  } else {
338  sout << ", ";
339  }
340  }
341  if (i != matrix.rows() -
342  1) { // make the end line and the offset in the next line
343  sout << std::endl;
344  sout << offset;
345  }
346  }
347  }
348  return sout.str();
349 }
350 
355 inline std::string toString(const Acts::Translation3D& translation,
356  int precision = 4) {
357  Acts::Vector3D trans;
358  trans[0] = translation.x();
359  trans[1] = translation.y();
360  trans[2] = translation.z();
361  return toString(trans, precision);
362 }
363 
369 inline std::string toString(const Acts::Transform3D& transform,
370  int precision = 4, const std::string& offset = "") {
371  std::ostringstream sout;
372  sout << "Translation : " << toString(transform.translation(), precision)
373  << std::endl;
374  std::string rotationOffset = offset + " ";
375  sout << offset << "Rotation : "
376  << toString(transform.rotation(), precision + 2, rotationOffset);
377  return sout.str();
378 }
379 
385 template <typename T>
386 std::vector<T*> unpack_shared_vector(
387  const std::vector<std::shared_ptr<T>>& items) {
388  std::vector<T*> rawPtrs;
389  rawPtrs.reserve(items.size());
390  for (const std::shared_ptr<T>& item : items) {
391  rawPtrs.push_back(item.get());
392  }
393  return rawPtrs;
394 }
395 
401 template <typename T>
402 std::vector<const T*> unpack_shared_vector(
403  const std::vector<std::shared_ptr<const T>>& items) {
404  std::vector<const T*> rawPtrs;
405  rawPtrs.reserve(items.size());
406  for (const std::shared_ptr<const T>& item : items) {
407  rawPtrs.push_back(item.get());
408  }
409  return rawPtrs;
410 }
411 
429 template <template <size_t> class Callable, size_t N, size_t NMAX,
430  typename... Args>
431 decltype(Callable<N>::invoke(std::declval<Args>()...)) template_switch(
432  size_t v, Args&&... args) {
433  if (v == N) {
434  return Callable<N>::invoke(std::forward<Args>(args)...);
435  }
436  if constexpr (N < NMAX) {
437  return template_switch<Callable, N + 1, NMAX>(v,
438  std::forward<Args>(args)...);
439  }
440  std::cerr << "template_switch<Fn, " << N << ", " << NMAX << ">(v=" << v
441  << ") is not valid (v > NMAX)" << std::endl;
442  std::abort();
443 }
444 
452 template <typename MatrixType>
453 MatrixType bitsetToMatrix(const std::bitset<MatrixType::RowsAtCompileTime *
454  MatrixType::ColsAtCompileTime>
455  bs) {
456  constexpr int rows = MatrixType::RowsAtCompileTime;
457  constexpr int cols = MatrixType::ColsAtCompileTime;
458 
459  static_assert(rows != -1 && cols != -1,
460  "bitsetToMatrix does not support dynamic matrices");
461 
462  MatrixType m;
463  auto* p = m.data();
464  for (size_t i = 0; i < rows * cols; i++) {
465  p[i] = bs[rows * cols - 1 - i];
466  }
467  return m;
468 }
469 
476 template <typename Derived>
477 auto matrixToBitset(const Eigen::PlainObjectBase<Derived>& m) {
478  using MatrixType = Eigen::PlainObjectBase<Derived>;
479  constexpr size_t rows = MatrixType::RowsAtCompileTime;
480  constexpr size_t cols = MatrixType::ColsAtCompileTime;
481 
482  std::bitset<rows * cols> res;
483 
484  auto* p = m.data();
485  for (size_t i = 0; i < rows * cols; i++) {
486  res[rows * cols - 1 - i] = p[i];
487  }
488 
489  return res;
490 }
491 
492 } // namespace Acts