CMS 3D CMS Logo

RiemannFit.h
Go to the documentation of this file.
1 #ifndef RecoTracker_PixelTrackFitting_interface_alpaka_RiemannFit_h
2 #define RecoTracker_PixelTrackFitting_interface_alpaka_RiemannFit_h
3 
4 #include <alpaka/alpaka.hpp>
5 
6 #include <Eigen/Core>
7 #include <Eigen/Eigenvalues>
8 
11 
13  using namespace ::riemannFit;
14 
37  template <typename TAcc, typename VNd1, typename VNd2>
38  ALPAKA_FN_ACC ALPAKA_FN_INLINE void computeRadLenUniformMaterial(const TAcc& acc,
39  const VNd1& length_values,
40  VNd2& rad_lengths) {
41  // Radiation length of the pixel detector in the uniform assumption, with
42  // 0.06 rad_len at 16 cm
43  constexpr double xx_0_inv = 0.06 / 16.;
44  uint n = length_values.rows();
45  rad_lengths(0) = length_values(0) * xx_0_inv;
46  for (uint j = 1; j < n; ++j) {
47  rad_lengths(j) = alpaka::math::abs(acc, length_values(j) - length_values(j - 1)) * xx_0_inv;
48  }
49  }
50 
70  template <typename TAcc, typename V4, typename VNd1, typename VNd2, int N>
71  ALPAKA_FN_ACC ALPAKA_FN_INLINE auto scatterCovLine(const TAcc& acc,
72  Matrix2d const* cov_sz,
73  const V4& fast_fit,
74  VNd1 const& s_arcs,
75  VNd2 const& z_values,
76  const double theta,
77  const double bField,
78  MatrixNd<N>& ret) {
79 #ifdef RFIT_DEBUG
80  riemannFit::printIt(&s_arcs, "Scatter_cov_line - s_arcs: ");
81 #endif
82  constexpr uint n = N;
83  double p_t = alpaka::math::min(acc, 20., fast_fit(2) * bField); // limit pt to avoid too small error!!!
84  double p_2 = p_t * p_t * (1. + 1. / sqr(fast_fit(3)));
85  VectorNd<N> rad_lengths_S;
86  // See documentation at http://eigen.tuxfamily.org/dox/group__TutorialArrayClass.html
87  // Basically, to perform cwise operations on Matrices and Vectors, you need
88  // to transform them into Array-like objects.
89  VectorNd<N> s_values = s_arcs.array() * s_arcs.array() + z_values.array() * z_values.array();
90  s_values = s_values.array().sqrt();
91  computeRadLenUniformMaterial(acc, s_values, rad_lengths_S);
92  VectorNd<N> sig2_S;
93  sig2_S = .000225 / p_2 * (1. + 0.038 * rad_lengths_S.array().log()).abs2() * rad_lengths_S.array();
94 #ifdef RFIT_DEBUG
95  riemannFit::printIt(cov_sz, "Scatter_cov_line - cov_sz: ");
96 #endif
97  Matrix2Nd<N> tmp = Matrix2Nd<N>::Zero();
98  for (uint k = 0; k < n; ++k) {
99  tmp(k, k) = cov_sz[k](0, 0);
100  tmp(k + n, k + n) = cov_sz[k](1, 1);
101  tmp(k, k + n) = tmp(k + n, k) = cov_sz[k](0, 1);
102  }
103  for (uint k = 0; k < n; ++k) {
104  for (uint l = k; l < n; ++l) {
105  for (uint i = 0; i < uint(alpaka::math::min(acc, k, l)); ++i) {
106  tmp(k + n, l + n) += alpaka::math::abs(acc, s_values(k) - s_values(i)) *
107  alpaka::math::abs(acc, s_values(l) - s_values(i)) * sig2_S(i);
108  }
109  tmp(l + n, k + n) = tmp(k + n, l + n);
110  }
111  }
112  // We are interested only in the errors orthogonal to the rotated s-axis
113  // which, in our formalism, are in the lower square matrix.
114 #ifdef RFIT_DEBUG
115  riemannFit::printIt(&tmp, "Scatter_cov_line - tmp: ");
116 #endif
117  ret = tmp.block(n, n, n, n);
118  }
119 
133  template <typename TAcc, typename M2xN, typename V4, int N>
134  ALPAKA_FN_ACC ALPAKA_FN_INLINE MatrixNd<N> scatter_cov_rad(
135  const TAcc& acc, const M2xN& p2D, const V4& fast_fit, VectorNd<N> const& rad, double B) {
136  constexpr uint n = N;
137  double p_t = alpaka::math::min(acc, 20., fast_fit(2) * B); // limit pt to avoid too small error!!!
138  double p_2 = p_t * p_t * (1. + 1. / sqr(fast_fit(3)));
139  double theta = atan(fast_fit(3));
140  theta = theta < 0. ? theta + M_PI : theta;
141  VectorNd<N> s_values;
142  VectorNd<N> rad_lengths;
143  const Vector2d oVec(fast_fit(0), fast_fit(1));
144 
145  // associated Jacobian, used in weights and errors computation
146  for (uint i = 0; i < n; ++i) { // x
147  Vector2d pVec = p2D.block(0, i, 2, 1) - oVec;
148  const double cross = cross2D(acc, -oVec, pVec);
149  const double dot = (-oVec).dot(pVec);
150  const double tempAtan2 = atan2(cross, dot);
151  s_values(i) = alpaka::math::abs(acc, tempAtan2 * fast_fit(2));
152  }
153  computeRadLenUniformMaterial(acc, s_values * sqrt(1. + 1. / sqr(fast_fit(3))), rad_lengths);
154  MatrixNd<N> scatter_cov_rad = MatrixNd<N>::Zero();
155  VectorNd<N> sig2 = (1. + 0.038 * rad_lengths.array().log()).abs2() * rad_lengths.array();
156  sig2 *= 0.000225 / (p_2 * sqr(sin(theta)));
157  for (uint k = 0; k < n; ++k) {
158  for (uint l = k; l < n; ++l) {
159  for (uint i = 0; i < uint(alpaka::math::min(acc, k, l)); ++i) {
160  scatter_cov_rad(k, l) += (rad(k) - rad(i)) * (rad(l) - rad(i)) * sig2(i);
161  }
163  }
164  }
165 #ifdef RFIT_DEBUG
166  riemannFit::printIt(&scatter_cov_rad, "Scatter_cov_rad - scatter_cov_rad: ");
167 #endif
168  return scatter_cov_rad;
169  }
170 
179  template <typename TAcc, typename M2xN, int N>
180  ALPAKA_FN_ACC ALPAKA_FN_INLINE Matrix2Nd<N> cov_radtocart(const TAcc& acc,
181  const M2xN& p2D,
182  const MatrixNd<N>& cov_rad,
183  const VectorNd<N>& rad) {
184 #ifdef RFIT_DEBUG
185  printf("Address of p2D: %p\n", &p2D);
186 #endif
187  printIt(&p2D, "cov_radtocart - p2D:");
188  constexpr uint n = N;
189  Matrix2Nd<N> cov_cart = Matrix2Nd<N>::Zero();
190  VectorNd<N> rad_inv = rad.cwiseInverse();
191  printIt(&rad_inv, "cov_radtocart - rad_inv:");
192  for (uint i = 0; i < n; ++i) {
193  for (uint j = i; j < n; ++j) {
194  cov_cart(i, j) = cov_rad(i, j) * p2D(1, i) * rad_inv(i) * p2D(1, j) * rad_inv(j);
195  cov_cart(i + n, j + n) = cov_rad(i, j) * p2D(0, i) * rad_inv(i) * p2D(0, j) * rad_inv(j);
196  cov_cart(i, j + n) = -cov_rad(i, j) * p2D(1, i) * rad_inv(i) * p2D(0, j) * rad_inv(j);
197  cov_cart(i + n, j) = -cov_rad(i, j) * p2D(0, i) * rad_inv(i) * p2D(1, j) * rad_inv(j);
198  cov_cart(j, i) = cov_cart(i, j);
199  cov_cart(j + n, i + n) = cov_cart(i + n, j + n);
200  cov_cart(j + n, i) = cov_cart(i, j + n);
201  cov_cart(j, i + n) = cov_cart(i + n, j);
202  }
203  }
204  return cov_cart;
205  }
206 
217  template <typename TAcc, typename M2xN, int N>
218  ALPAKA_FN_ACC ALPAKA_FN_INLINE VectorNd<N> cov_carttorad(const TAcc& acc,
219  const M2xN& p2D,
220  const Matrix2Nd<N>& cov_cart,
221  const VectorNd<N>& rad) {
222  constexpr uint n = N;
223  VectorNd<N> cov_rad;
224  const VectorNd<N> rad_inv2 = rad.cwiseInverse().array().square();
225  for (uint i = 0; i < n; ++i) {
227  if (rad(i) < 1.e-4)
228  cov_rad(i) = cov_cart(i, i);
229  else {
230  cov_rad(i) = rad_inv2(i) * (cov_cart(i, i) * sqr(p2D(1, i)) + cov_cart(i + n, i + n) * sqr(p2D(0, i)) -
231  2. * cov_cart(i, i + n) * p2D(0, i) * p2D(1, i));
232  }
233  }
234  return cov_rad;
235  }
236 
249  template <typename TAcc, typename M2xN, typename V4, int N>
250  ALPAKA_FN_ACC ALPAKA_FN_INLINE VectorNd<N> cov_carttorad_prefit(
251  const TAcc& acc, const M2xN& p2D, const Matrix2Nd<N>& cov_cart, V4& fast_fit, const VectorNd<N>& rad) {
252  constexpr uint n = N;
253  VectorNd<N> cov_rad;
254  for (uint i = 0; i < n; ++i) {
256  if (rad(i) < 1.e-4)
257  cov_rad(i) = cov_cart(i, i); // TO FIX
258  else {
259  Vector2d a = p2D.col(i);
260  Vector2d b = p2D.col(i) - fast_fit.head(2);
261  const double x2 = a.dot(b);
262  const double y2 = cross2D(acc, a, b);
263  const double tan_c = -y2 / x2;
264  const double tan_c2 = sqr(tan_c);
265  cov_rad(i) =
266  1. / (1. + tan_c2) * (cov_cart(i, i) + cov_cart(i + n, i + n) * tan_c2 + 2 * cov_cart(i, i + n) * tan_c);
267  }
268  }
269  return cov_rad;
270  }
271 
283  template <typename TAcc, int N>
284  ALPAKA_FN_ACC ALPAKA_FN_INLINE VectorNd<N> weightCircle(const TAcc& acc, const MatrixNd<N>& cov_rad_inv) {
285  return cov_rad_inv.colwise().sum().transpose();
286  }
287 
296  template <typename TAcc, typename M2xN>
297  ALPAKA_FN_ACC ALPAKA_FN_INLINE int32_t charge(const TAcc& acc, const M2xN& p2D, const Vector3d& par_uvr) {
298  return ((p2D(0, 1) - p2D(0, 0)) * (par_uvr.y() - p2D(1, 0)) - (p2D(1, 1) - p2D(1, 0)) * (par_uvr.x() - p2D(0, 0)) >
299  0)
300  ? -1
301  : 1;
302  }
303 
318  template <typename TAcc>
319  ALPAKA_FN_ACC ALPAKA_FN_INLINE Vector3d min_eigen3D(const TAcc& acc, const Matrix3d& A, double& chi2) {
320 #ifdef RFIT_DEBUG
321  printf("min_eigen3D - enter\n");
322 #endif
323  Eigen::SelfAdjointEigenSolver<Matrix3d> solver(3);
324  solver.computeDirect(A);
325  int min_index;
326  chi2 = solver.eigenvalues().minCoeff(&min_index);
327 #ifdef RFIT_DEBUG
328  printf("min_eigen3D - exit\n");
329 #endif
330  return solver.eigenvectors().col(min_index);
331  }
332 
344  template <typename TAcc>
345  ALPAKA_FN_ACC ALPAKA_FN_INLINE Vector3d min_eigen3D_fast(const TAcc& acc, const Matrix3d& A) {
346  Eigen::SelfAdjointEigenSolver<Matrix3f> solver(3);
347  solver.computeDirect(A.cast<float>());
348  int min_index;
349  solver.eigenvalues().minCoeff(&min_index);
350  return solver.eigenvectors().col(min_index).cast<double>();
351  }
352 
362  template <typename TAcc>
363  ALPAKA_FN_ACC ALPAKA_FN_INLINE Vector2d min_eigen2D(const TAcc& acc, const Matrix2d& aMat, double& chi2) {
364  Eigen::SelfAdjointEigenSolver<Matrix2d> solver(2);
365  solver.computeDirect(aMat);
366  int min_index;
367  chi2 = solver.eigenvalues().minCoeff(&min_index);
368  return solver.eigenvectors().col(min_index);
369  }
370 
384  template <typename TAcc, typename M3xN, typename V4>
385  ALPAKA_FN_ACC ALPAKA_FN_INLINE void fastFit(const TAcc& acc, const M3xN& hits, V4& result) {
386  constexpr uint32_t N = M3xN::ColsAtCompileTime;
387  constexpr auto n = N; // get the number of hits
388  printIt(&hits, "Fast_fit - hits: ");
389 
390  // CIRCLE FIT
391  // Make segments between middle-to-first(b) and last-to-first(c) hits
392  const Vector2d bVec = hits.block(0, n / 2, 2, 1) - hits.block(0, 0, 2, 1);
393  const Vector2d cVec = hits.block(0, n - 1, 2, 1) - hits.block(0, 0, 2, 1);
394  printIt(&bVec, "Fast_fit - b: ");
395  printIt(&cVec, "Fast_fit - c: ");
396  // Compute their lengths
397  auto b2 = bVec.squaredNorm();
398  auto c2 = cVec.squaredNorm();
399  // The algebra has been verified (MR). The usual approach has been followed:
400  // * use an orthogonal reference frame passing from the first point.
401  // * build the segments (chords)
402  // * build orthogonal lines through mid points
403  // * make a system and solve for X0 and Y0.
404  // * add the initial point
405  bool flip = abs(bVec.x()) < abs(bVec.y());
406  auto bx = flip ? bVec.y() : bVec.x();
407  auto by = flip ? bVec.x() : bVec.y();
408  auto cx = flip ? cVec.y() : cVec.x();
409  auto cy = flip ? cVec.x() : cVec.y();
411  auto div = 2. * (cx * by - bx * cy);
412  // if aligned TO FIX
413  auto y0 = (cx * b2 - bx * c2) / div;
414  auto x0 = (0.5 * b2 - y0 * by) / bx;
415  result(0) = hits(0, 0) + (flip ? y0 : x0);
416  result(1) = hits(1, 0) + (flip ? x0 : y0);
417  result(2) = sqrt(sqr(x0) + sqr(y0));
418  printIt(&result, "Fast_fit - result: ");
419 
420  // LINE FIT
421  const Vector2d dVec = hits.block(0, 0, 2, 1) - result.head(2);
422  const Vector2d eVec = hits.block(0, n - 1, 2, 1) - result.head(2);
423  printIt(&eVec, "Fast_fit - e: ");
424  printIt(&dVec, "Fast_fit - d: ");
425  // Compute the arc-length between first and last point: L = R * theta = R * atan (tan (Theta) )
426  auto dr = result(2) * atan2(cross2D(acc, dVec, eVec), dVec.dot(eVec));
427  // Simple difference in Z between last and first hit
428  auto dz = hits(2, n - 1) - hits(2, 0);
429 
430  result(3) = (dr / dz);
431 
432 #ifdef RFIT_DEBUG
433  printf("Fast_fit: [%f, %f, %f, %f]\n", result(0), result(1), result(2), result(3));
434 #endif
435  }
436 
464  template <typename TAcc, typename M2xN, typename V4, int N>
465  ALPAKA_FN_ACC ALPAKA_FN_INLINE CircleFit circleFit(const TAcc& acc,
466  const M2xN& hits2D,
467  const Matrix2Nd<N>& hits_cov2D,
468  const V4& fast_fit,
469  const VectorNd<N>& rad,
470  const double bField,
471  const bool error) {
472 #ifdef RFIT_DEBUG
473  printf("circle_fit - enter\n");
474 #endif
475  // INITIALIZATION
476  Matrix2Nd<N> vMat = hits_cov2D;
477  constexpr uint n = N;
478  printIt(&hits2D, "circle_fit - hits2D:");
479  printIt(&hits_cov2D, "circle_fit - hits_cov2D:");
480 
481 #ifdef RFIT_DEBUG
482  printf("circle_fit - WEIGHT COMPUTATION\n");
483 #endif
484  // WEIGHT COMPUTATION
485  VectorNd<N> weight;
486  MatrixNd<N> gMat;
487  double renorm;
488  {
489  MatrixNd<N> cov_rad = cov_carttorad_prefit(acc, hits2D, vMat, fast_fit, rad).asDiagonal();
490  MatrixNd<N> scatterCovRadMat = scatter_cov_rad(acc, hits2D, fast_fit, rad, bField);
491  printIt(&scatterCovRadMat, "circle_fit - scatter_cov_rad:");
492  printIt(&hits2D, "circle_fit - hits2D bis:");
493 #ifdef RFIT_DEBUG
494  printf("Address of hits2D: a) %p\n", &hits2D);
495 #endif
496  vMat += cov_radtocart(acc, hits2D, scatterCovRadMat, rad);
497  printIt(&vMat, "circle_fit - V:");
498  cov_rad += scatterCovRadMat;
499  printIt(&cov_rad, "circle_fit - cov_rad:");
500  math::cholesky::invert(cov_rad, gMat);
501  // gMat = cov_rad.inverse();
502  renorm = gMat.sum();
503  gMat *= 1. / renorm;
504  weight = weightCircle(acc, gMat);
505  }
506  printIt(&weight, "circle_fit - weight:");
507 
508  // SPACE TRANSFORMATION
509 #ifdef RFIT_DEBUG
510  printf("circle_fit - SPACE TRANSFORMATION\n");
511 #endif
512 
513  // center
514 #ifdef RFIT_DEBUG
515  printf("Address of hits2D: b) %p\n", &hits2D);
516 #endif
517  const Vector2d hCentroid = hits2D.rowwise().mean(); // centroid
518  printIt(&hCentroid, "circle_fit - h_:");
519  Matrix3xNd<N> p3D;
520  p3D.block(0, 0, 2, n) = hits2D.colwise() - hCentroid;
521  printIt(&p3D, "circle_fit - p3D: a)");
522  Vector2Nd<N> mc; // centered hits, used in error computation
523  mc << p3D.row(0).transpose(), p3D.row(1).transpose();
524  printIt(&mc, "circle_fit - mc(centered hits):");
525 
526  // scale
527  const double tempQ = mc.squaredNorm();
528  const double tempS = sqrt(n * 1. / tempQ); // scaling factor
529  p3D.block(0, 0, 2, n) *= tempS;
530 
531  // project on paraboloid
532  p3D.row(2) = p3D.block(0, 0, 2, n).colwise().squaredNorm();
533  printIt(&p3D, "circle_fit - p3D: b)");
534 
535 #ifdef RFIT_DEBUG
536  printf("circle_fit - COST FUNCTION\n");
537 #endif
538  // COST FUNCTION
539 
540  // compute
541  Vector3d r0;
542  r0.noalias() = p3D * weight; // center of gravity
543  const Matrix3xNd<N> xMat = p3D.colwise() - r0;
544  Matrix3d aMat = xMat * gMat * xMat.transpose();
545  printIt(&aMat, "circle_fit - A:");
546 
547 #ifdef RFIT_DEBUG
548  printf("circle_fit - MINIMIZE\n");
549 #endif
550  // minimize
551  double chi2;
552  Vector3d vVec = min_eigen3D(acc, aMat, chi2);
553 #ifdef RFIT_DEBUG
554  printf("circle_fit - AFTER MIN_EIGEN\n");
555 #endif
556  printIt(&vVec, "v BEFORE INVERSION");
557  vVec *= (vVec(2) > 0) ? 1 : -1; // TO FIX dovrebbe essere N(3)>0
558  printIt(&vVec, "v AFTER INVERSION");
559  // This hack to be able to run on GPU where the automatic assignment to a
560  // double from the vector multiplication is not working.
561 #ifdef RFIT_DEBUG
562  printf("circle_fit - AFTER MIN_EIGEN 1\n");
563 #endif
564  Eigen::Matrix<double, 1, 1> cm;
565 #ifdef RFIT_DEBUG
566  printf("circle_fit - AFTER MIN_EIGEN 2\n");
567 #endif
568  cm = -vVec.transpose() * r0;
569 #ifdef RFIT_DEBUG
570  printf("circle_fit - AFTER MIN_EIGEN 3\n");
571 #endif
572  const double tempC = cm(0, 0);
573 
574 #ifdef RFIT_DEBUG
575  printf("circle_fit - COMPUTE CIRCLE PARAMETER\n");
576 #endif
577  // COMPUTE CIRCLE PARAMETER
578 
579  // auxiliary quantities
580  const double tempH = sqrt(1. - sqr(vVec(2)) - 4. * tempC * vVec(2));
581  const double v2x2_inv = 1. / (2. * vVec(2));
582  const double s_inv = 1. / tempS;
583  Vector3d par_uvr; // used in error propagation
584  par_uvr << -vVec(0) * v2x2_inv, -vVec(1) * v2x2_inv, tempH * v2x2_inv;
585 
586  CircleFit circle;
587  circle.par << par_uvr(0) * s_inv + hCentroid(0), par_uvr(1) * s_inv + hCentroid(1), par_uvr(2) * s_inv;
588  circle.qCharge = charge(acc, hits2D, circle.par);
589  circle.chi2 = abs(chi2) * renorm / sqr(2 * vVec(2) * par_uvr(2) * tempS);
590  printIt(&circle.par, "circle_fit - CIRCLE PARAMETERS:");
591  printIt(&circle.cov, "circle_fit - CIRCLE COVARIANCE:");
592 #ifdef RFIT_DEBUG
593  printf("circle_fit - CIRCLE CHARGE: %d\n", circle.qCharge);
594 #endif
595 
596 #ifdef RFIT_DEBUG
597  printf("circle_fit - ERROR PROPAGATION\n");
598 #endif
599  // ERROR PROPAGATION
600  if (error) {
601 #ifdef RFIT_DEBUG
602  printf("circle_fit - ERROR PRPAGATION ACTIVATED\n");
603 #endif
604  ArrayNd<N> vcsMat[2][2]; // cov matrix of center & scaled points
605  MatrixNd<N> cMat[3][3]; // cov matrix of 3D transformed points
606 #ifdef RFIT_DEBUG
607  printf("circle_fit - ERROR PRPAGATION ACTIVATED 2\n");
608 #endif
609  {
610  Eigen::Matrix<double, 1, 1> cm;
611  Eigen::Matrix<double, 1, 1> cm2;
612  cm = mc.transpose() * vMat * mc;
613  const double tempC2 = cm(0, 0);
614  Matrix2Nd<N> tempVcsMat;
615  tempVcsMat.template triangularView<Eigen::Upper>() =
616  (sqr(tempS) * vMat + sqr(sqr(tempS)) * 1. / (4. * tempQ * n) *
617  (2. * vMat.squaredNorm() + 4. * tempC2) * // mc.transpose() * V * mc) *
618  (mc * mc.transpose()));
619 
620  printIt(&tempVcsMat, "circle_fit - Vcs:");
621  cMat[0][0] = tempVcsMat.block(0, 0, n, n).template selfadjointView<Eigen::Upper>();
622  vcsMat[0][1] = tempVcsMat.block(0, n, n, n);
623  cMat[1][1] = tempVcsMat.block(n, n, n, n).template selfadjointView<Eigen::Upper>();
624  vcsMat[1][0] = vcsMat[0][1].transpose();
625  printIt(&tempVcsMat, "circle_fit - Vcs:");
626  }
627 
628  {
629  const ArrayNd<N> t0 = (VectorXd::Constant(n, 1.) * p3D.row(0));
630  const ArrayNd<N> t1 = (VectorXd::Constant(n, 1.) * p3D.row(1));
631  const ArrayNd<N> t00 = p3D.row(0).transpose() * p3D.row(0);
632  const ArrayNd<N> t01 = p3D.row(0).transpose() * p3D.row(1);
633  const ArrayNd<N> t11 = p3D.row(1).transpose() * p3D.row(1);
634  const ArrayNd<N> t10 = t01.transpose();
635  vcsMat[0][0] = cMat[0][0];
636  cMat[0][1] = vcsMat[0][1];
637  cMat[0][2] = 2. * (vcsMat[0][0] * t0 + vcsMat[0][1] * t1);
638  vcsMat[1][1] = cMat[1][1];
639  cMat[1][2] = 2. * (vcsMat[1][0] * t0 + vcsMat[1][1] * t1);
640  MatrixNd<N> tmp;
641  tmp.template triangularView<Eigen::Upper>() =
642  (2. * (vcsMat[0][0] * vcsMat[0][0] + vcsMat[0][0] * vcsMat[0][1] + vcsMat[1][1] * vcsMat[1][0] +
643  vcsMat[1][1] * vcsMat[1][1]) +
644  4. * (vcsMat[0][0] * t00 + vcsMat[0][1] * t01 + vcsMat[1][0] * t10 + vcsMat[1][1] * t11))
645  .matrix();
646  cMat[2][2] = tmp.template selfadjointView<Eigen::Upper>();
647  }
648  printIt(&cMat[0][0], "circle_fit - C[0][0]:");
649 
650  Matrix3d c0Mat; // cov matrix of center of gravity (r0.x,r0.y,r0.z)
651  for (uint i = 0; i < 3; ++i) {
652  for (uint j = i; j < 3; ++j) {
653  Eigen::Matrix<double, 1, 1> tmp;
654  tmp = weight.transpose() * cMat[i][j] * weight;
655  // Workaround to get things working in GPU
656  const double tempC = tmp(0, 0);
657  c0Mat(i, j) = tempC; //weight.transpose() * C[i][j] * weight;
658  c0Mat(j, i) = c0Mat(i, j);
659  }
660  }
661  printIt(&c0Mat, "circle_fit - C0:");
662 
663  const MatrixNd<N> wMat = weight * weight.transpose();
664  const MatrixNd<N> hMat = MatrixNd<N>::Identity().rowwise() - weight.transpose();
665  const MatrixNx3d<N> s_v = hMat * p3D.transpose();
666  printIt(&wMat, "circle_fit - W:");
667  printIt(&hMat, "circle_fit - H:");
668  printIt(&s_v, "circle_fit - s_v:");
669 
670  MatrixNd<N> dMat[3][3]; // cov(s_v)
671  dMat[0][0] = (hMat * cMat[0][0] * hMat.transpose()).cwiseProduct(wMat);
672  dMat[0][1] = (hMat * cMat[0][1] * hMat.transpose()).cwiseProduct(wMat);
673  dMat[0][2] = (hMat * cMat[0][2] * hMat.transpose()).cwiseProduct(wMat);
674  dMat[1][1] = (hMat * cMat[1][1] * hMat.transpose()).cwiseProduct(wMat);
675  dMat[1][2] = (hMat * cMat[1][2] * hMat.transpose()).cwiseProduct(wMat);
676  dMat[2][2] = (hMat * cMat[2][2] * hMat.transpose()).cwiseProduct(wMat);
677  dMat[1][0] = dMat[0][1].transpose();
678  dMat[2][0] = dMat[0][2].transpose();
679  dMat[2][1] = dMat[1][2].transpose();
680  printIt(&dMat[0][0], "circle_fit - D_[0][0]:");
681 
682  constexpr uint nu[6][2] = {{0, 0}, {0, 1}, {0, 2}, {1, 1}, {1, 2}, {2, 2}};
683 
684  Matrix6d eMat; // cov matrix of the 6 independent elements of A
685  for (uint a = 0; a < 6; ++a) {
686  const uint i = nu[a][0], j = nu[a][1];
687  for (uint b = a; b < 6; ++b) {
688  const uint k = nu[b][0], l = nu[b][1];
689  VectorNd<N> t0(n);
690  VectorNd<N> t1(n);
691  if (l == k) {
692  t0 = 2. * dMat[j][l] * s_v.col(l);
693  if (i == j)
694  t1 = t0;
695  else
696  t1 = 2. * dMat[i][l] * s_v.col(l);
697  } else {
698  t0 = dMat[j][l] * s_v.col(k) + dMat[j][k] * s_v.col(l);
699  if (i == j)
700  t1 = t0;
701  else
702  t1 = dMat[i][l] * s_v.col(k) + dMat[i][k] * s_v.col(l);
703  }
704 
705  if (i == j) {
706  Eigen::Matrix<double, 1, 1> cm;
707  cm = s_v.col(i).transpose() * (t0 + t1);
708  // Workaround to get things working in GPU
709  const double tempC = cm(0, 0);
710  eMat(a, b) = 0. + tempC;
711  } else {
712  Eigen::Matrix<double, 1, 1> cm;
713  cm = (s_v.col(i).transpose() * t0) + (s_v.col(j).transpose() * t1);
714  // Workaround to get things working in GPU
715  const double tempC = cm(0, 0);
716  eMat(a, b) = 0. + tempC; //(s_v.col(i).transpose() * t0) + (s_v.col(j).transpose() * t1);
717  }
718  if (b != a)
719  eMat(b, a) = eMat(a, b);
720  }
721  }
722  printIt(&eMat, "circle_fit - E:");
723 
724  Eigen::Matrix<double, 3, 6> j2Mat; // Jacobian of min_eigen() (numerically computed)
725  for (uint a = 0; a < 6; ++a) {
726  const uint i = nu[a][0], j = nu[a][1];
727  Matrix3d delta = Matrix3d::Zero();
728  delta(i, j) = delta(j, i) = abs(aMat(i, j) * epsilon);
729  j2Mat.col(a) = min_eigen3D_fast(acc, aMat + delta);
730  const int sign = (j2Mat.col(a)(2) > 0) ? 1 : -1;
731  j2Mat.col(a) = (j2Mat.col(a) * sign - vVec) / delta(i, j);
732  }
733  printIt(&j2Mat, "circle_fit - J2:");
734 
735  Matrix4d cvcMat; // joint cov matrix of (v0,v1,v2,c)
736  {
737  Matrix3d t0 = j2Mat * eMat * j2Mat.transpose();
738  Vector3d t1 = -t0 * r0;
739  cvcMat.block(0, 0, 3, 3) = t0;
740  cvcMat.block(0, 3, 3, 1) = t1;
741  cvcMat.block(3, 0, 1, 3) = t1.transpose();
742  Eigen::Matrix<double, 1, 1> cm1;
743  Eigen::Matrix<double, 1, 1> cm3;
744  cm1 = (vVec.transpose() * c0Mat * vVec);
745  // cm2 = (c0Mat.cwiseProduct(t0)).sum();
746  cm3 = (r0.transpose() * t0 * r0);
747  // Workaround to get things working in GPU
748  const double tempC = cm1(0, 0) + (c0Mat.cwiseProduct(t0)).sum() + cm3(0, 0);
749  cvcMat(3, 3) = tempC;
750  // (v.transpose() * c0Mat * v) + (c0Mat.cwiseProduct(t0)).sum() + (r0.transpose() * t0 * r0);
751  }
752  printIt(&cvcMat, "circle_fit - Cvc:");
753 
754  Eigen::Matrix<double, 3, 4> j3Mat; // Jacobian (v0,v1,v2,c)->(X0,Y0,R)
755  {
756  const double t = 1. / tempH;
757  j3Mat << -v2x2_inv, 0, vVec(0) * sqr(v2x2_inv) * 2., 0, 0, -v2x2_inv, vVec(1) * sqr(v2x2_inv) * 2., 0,
758  vVec(0) * v2x2_inv * t, vVec(1) * v2x2_inv * t,
759  -tempH * sqr(v2x2_inv) * 2. - (2. * tempC + vVec(2)) * v2x2_inv * t, -t;
760  }
761  printIt(&j3Mat, "circle_fit - J3:");
762 
763  const RowVector2Nd<N> Jq = mc.transpose() * tempS * 1. / n; // var(q)
764  printIt(&Jq, "circle_fit - Jq:");
765 
766  Matrix3d cov_uvr = j3Mat * cvcMat * j3Mat.transpose() * sqr(s_inv) // cov(X0,Y0,R)
767  + (par_uvr * par_uvr.transpose()) * (Jq * vMat * Jq.transpose());
768 
769  circle.cov = cov_uvr;
770  }
771 
772  printIt(&circle.cov, "Circle cov:");
773 #ifdef RFIT_DEBUG
774  printf("circle_fit - exit\n");
775 #endif
776  return circle;
777  }
778 
795  template <typename TAcc, typename M3xN, typename M6xN, typename V4>
796  ALPAKA_FN_ACC ALPAKA_FN_INLINE LineFit lineFit(const TAcc& acc,
797  const M3xN& hits,
798  const M6xN& hits_ge,
799  const CircleFit& circle,
800  const V4& fast_fit,
801  const double bField,
802  const bool error) {
803  constexpr uint32_t N = M3xN::ColsAtCompileTime;
804  constexpr auto n = N;
805  double theta = -circle.qCharge * atan(fast_fit(3));
806  theta = theta < 0. ? theta + M_PI : theta;
807 
808  // Prepare the Rotation Matrix to rotate the points
809  Eigen::Matrix<double, 2, 2> rot;
810  rot << sin(theta), cos(theta), -cos(theta), sin(theta);
811 
812  // PROJECTION ON THE CILINDER
813  //
814  // p2D will be:
815  // [s1, s2, s3, ..., sn]
816  // [z1, z2, z3, ..., zn]
817  // s values will be ordinary x-values
818  // z values will be ordinary y-values
819 
820  Matrix2xNd<N> p2D = Matrix2xNd<N>::Zero();
821  Eigen::Matrix<double, 2, 6> jxMat;
822 
823 #ifdef RFIT_DEBUG
824  printf("Line_fit - B: %g\n", bField);
825  printIt(&hits, "Line_fit points: ");
826  printIt(&hits_ge, "Line_fit covs: ");
827  printIt(&rot, "Line_fit rot: ");
828 #endif
829  // x & associated Jacobian
830  // cfr https://indico.cern.ch/event/663159/contributions/2707659/attachments/1517175/2368189/Riemann_fit.pdf
831  // Slide 11
832  // a ==> -o i.e. the origin of the circle in XY plane, negative
833  // b ==> p i.e. distances of the points wrt the origin of the circle.
834  const Vector2d oVec(circle.par(0), circle.par(1));
835 
836  // associated Jacobian, used in weights and errors computation
837  Matrix6d covMat = Matrix6d::Zero();
838  Matrix2d cov_sz[N];
839  for (uint i = 0; i < n; ++i) {
840  Vector2d pVec = hits.block(0, i, 2, 1) - oVec;
841  const double cross = cross2D(acc, -oVec, pVec);
842  const double dot = (-oVec).dot(pVec);
843  // atan2(cross, dot) give back the angle in the transverse plane so tha the
844  // final equation reads: x_i = -q*R*theta (theta = angle returned by atan2)
845  const double tempQAtan2 = -circle.qCharge * atan2(cross, dot);
846  // p2D.coeffRef(1, i) = atan2_ * circle.par(2);
847  p2D(0, i) = tempQAtan2 * circle.par(2);
848 
849  // associated Jacobian, used in weights and errors- computation
850  const double temp0 = -circle.qCharge * circle.par(2) * 1. / (sqr(dot) + sqr(cross));
851  double d_X0 = 0., d_Y0 = 0., d_R = 0.; // good approximation for big pt and eta
852  if (error) {
853  d_X0 = -temp0 * ((pVec(1) + oVec(1)) * dot - (pVec(0) - oVec(0)) * cross);
854  d_Y0 = temp0 * ((pVec(0) + oVec(0)) * dot - (oVec(1) - pVec(1)) * cross);
855  d_R = tempQAtan2;
856  }
857  const double d_x = temp0 * (oVec(1) * dot + oVec(0) * cross);
858  const double d_y = temp0 * (-oVec(0) * dot + oVec(1) * cross);
859  jxMat << d_X0, d_Y0, d_R, d_x, d_y, 0., 0., 0., 0., 0., 0., 1.;
860 
861  covMat.block(0, 0, 3, 3) = circle.cov;
862  covMat(3, 3) = hits_ge.col(i)[0]; // x errors
863  covMat(4, 4) = hits_ge.col(i)[2]; // y errors
864  covMat(5, 5) = hits_ge.col(i)[5]; // z errors
865  covMat(3, 4) = covMat(4, 3) = hits_ge.col(i)[1]; // cov_xy
866  covMat(3, 5) = covMat(5, 3) = hits_ge.col(i)[3]; // cov_xz
867  covMat(4, 5) = covMat(5, 4) = hits_ge.col(i)[4]; // cov_yz
868  Matrix2d tmp = jxMat * covMat * jxMat.transpose();
869  cov_sz[i].noalias() = rot * tmp * rot.transpose();
870  }
871  // Math of d_{X0,Y0,R,x,y} all verified by hand
872  p2D.row(1) = hits.row(2);
873 
874  // The following matrix will contain errors orthogonal to the rotated S
875  // component only, with the Multiple Scattering properly treated!!
876  MatrixNd<N> cov_with_ms;
877  scatterCovLine(acc, cov_sz, fast_fit, p2D.row(0), p2D.row(1), theta, bField, cov_with_ms);
878 #ifdef RFIT_DEBUG
879  printIt(cov_sz, "line_fit - cov_sz:");
880  printIt(&cov_with_ms, "line_fit - cov_with_ms: ");
881 #endif
882 
883  // Rotate Points with the shape [2, n]
884  Matrix2xNd<N> p2D_rot = rot * p2D;
885 
886 #ifdef RFIT_DEBUG
887  printf("Fast fit Tan(theta): %g\n", fast_fit(3));
888  printf("Rotation angle: %g\n", theta);
889  printIt(&rot, "Rotation Matrix:");
890  printIt(&p2D, "Original Hits(s,z):");
891  printIt(&p2D_rot, "Rotated hits(S3D, Z'):");
892  printIt(&rot, "Rotation Matrix:");
893 #endif
894 
895  // Build the A Matrix
896  Matrix2xNd<N> aMat;
897  aMat << MatrixXd::Ones(1, n), p2D_rot.row(0); // rotated s values
898 
899 #ifdef RFIT_DEBUG
900  printIt(&aMat, "A Matrix:");
901 #endif
902 
903  // Build A^T V-1 A, where V-1 is the covariance of only the Y components.
904  MatrixNd<N> vyInvMat;
905  math::cholesky::invert(cov_with_ms, vyInvMat);
906  // MatrixNd<N> vyInvMat = cov_with_ms.inverse();
907  Eigen::Matrix<double, 2, 2> covParamsMat = aMat * vyInvMat * aMat.transpose();
908  // Compute the Covariance Matrix of the fit parameters
909  math::cholesky::invert(covParamsMat, covParamsMat);
910 
911  // Now Compute the Parameters in the form [2,1]
912  // The first component is q.
913  // The second component is m.
914  Eigen::Matrix<double, 2, 1> sol = covParamsMat * aMat * vyInvMat * p2D_rot.row(1).transpose();
915 
916 #ifdef RFIT_DEBUG
917  printIt(&sol, "Rotated solutions:");
918 #endif
919 
920  // We need now to transfer back the results in the original s-z plane
921  const auto sinTheta = sin(theta);
922  const auto cosTheta = cos(theta);
923  auto common_factor = 1. / (sinTheta - sol(1, 0) * cosTheta);
924  Eigen::Matrix<double, 2, 2> jMat;
925  jMat << 0., common_factor * common_factor, common_factor, sol(0, 0) * cosTheta * common_factor * common_factor;
926 
927  double tempM = common_factor * (sol(1, 0) * sinTheta + cosTheta);
928  double tempQ = common_factor * sol(0, 0);
929  auto cov_mq = jMat * covParamsMat * jMat.transpose();
930 
931  VectorNd<N> res = p2D_rot.row(1).transpose() - aMat.transpose() * sol;
932  double chi2 = res.transpose() * vyInvMat * res;
933 
934  LineFit line;
935  line.par << tempM, tempQ;
936  line.cov << cov_mq;
937  line.chi2 = chi2;
938 
939 #ifdef RFIT_DEBUG
940  printf("Common_factor: %g\n", common_factor);
941  printIt(&jMat, "Jacobian:");
942  printIt(&sol, "Rotated solutions:");
943  printIt(&covParamsMat, "Cov_params:");
944  printIt(&cov_mq, "Rotated Covariance Matrix:");
945  printIt(&(line.par), "Real Parameters:");
946  printIt(&(line.cov), "Real Covariance Matrix:");
947  printf("Chi2: %g\n", chi2);
948 #endif
949 
950  return line;
951  }
952 
953 } // namespace ALPAKA_ACCELERATOR_NAMESPACE::riemannFit
954 
955 namespace riemannFit {
989  template <int N>
990  class helixFit {
991  public:
992  template <typename TAcc>
993  ALPAKA_FN_ACC ALPAKA_FN_INLINE void operator()(const TAcc& acc,
994  const Matrix3xNd<N>* hits,
995  const Eigen::Matrix<float, 6, N>* hits_ge,
996  const double bField,
997  const bool error,
998  HelixFit* helix) const {
999  constexpr uint n = N;
1000  VectorNd<4> rad = (hits->block(0, 0, 2, n).colwise().norm());
1001 
1002  // Fast_fit gives back (X0, Y0, R, theta) w/o errors, using only 3 points.
1005  riemannFit::Matrix2Nd<N> hits_cov = MatrixXd::Zero(2 * n, 2 * n);
1008  acc, hits->block(0, 0, 2, n), hits_cov, fast_fit, rad, bField, error);
1009  LineFit line =
1011 
1013 
1014  helix->par << circle.par, line.par;
1015  if (error) {
1016  helix->cov = MatrixXd::Zero(5, 5);
1017  helix->cov.block(0, 0, 3, 3) = circle.cov;
1018  helix->cov.block(3, 3, 2, 2) = line.cov;
1019  }
1020  helix->qCharge = circle.qCharge;
1021  helix->chi2_circle = circle.chi2;
1022  helix->chi2_line = line.chi2;
1023  }
1024  };
1025 
1026 } // namespace riemannFit
1027 
1028 #endif // RecoTracker_PixelTrackFitting_interface_alpaka_RiemannFit_h
Eigen::Vector4d Vector4d
Definition: FitResult.h:12
Eigen::Vector3d Vector3d
Definition: FitResult.h:11
Basic3DVector cross(const Basic3DVector &v) const
Vector product, or "cross" product, with a vector of same type.
Eigen::Matrix3d Matrix3d
Definition: FitResult.h:15
ALPAKA_FN_ACC ALPAKA_FN_INLINE void computeRadLenUniformMaterial(const TAcc &acc, const VNd1 &length_values, VNd2 &rad_lengths)
Definition: RiemannFit.h:38
int32_t qCharge
particle charge
Definition: FitResult.h:31
ALPAKA_FN_ACC ALPAKA_FN_INLINE VectorNd< N > cov_carttorad_prefit(const TAcc &acc, const M2xN &p2D, const Matrix2Nd< N > &cov_cart, V4 &fast_fit, const VectorNd< N > &rad)
Transform covariance matrix from Cartesian coordinates (only transverse plane component) to coordinat...
Definition: RiemannFit.h:250
ALPAKA_FN_ACC ALPAKA_FN_INLINE LineFit lineFit(const TAcc &acc, const M3xN &hits, const M6xN &hits_ge, const CircleFit &circle, const V4 &fast_fit, const double bField, const bool error)
Perform an ordinary least square fit in the s-z plane to compute the parameters cotTheta and Zip...
Definition: RiemannFit.h:796
Definition: APVGainStruct.h:7
ALPAKA_FN_ACC void loadCovariance2D(const TAcc &acc, M6xNf const &ge, M2Nd &hits_cov)
Definition: FitUtils.h:126
ret
prodAgent to be discontinued
Vector5d par
(phi,Tip,pt,cotan(theta)),Zip)
Definition: FitResult.h:46
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
ALPAKA_FN_ACC ALPAKA_FN_INLINE double cross2D(const TAcc &acc, const Vector2d &a, const Vector2d &b)
Compute cross product of two 2D vector (assuming z component 0), returning z component of the result...
Definition: FitUtils.h:117
ALPAKA_FN_ACC ALPAKA_FN_INLINE void par_uvrtopak(const TAcc &acc, CircleFit &circle, const double B, const bool error)
Transform circle parameter from (X0,Y0,R) to (phi,Tip,p_t) and consequently covariance matrix...
Definition: FitUtils.h:212
Definition: weight.py:1
Vector3d par
parameter: (X0,Y0,R)
Definition: FitResult.h:24
constexpr T sqr(const T a)
raise to square.
Definition: FitUtils.h:104
Definition: Electron.h:6
T dot(const Basic3DVector &v) const
Scalar product, or "dot" product, with a vector of same type.
ALPAKA_FN_ACC ALPAKA_FN_INLINE void fastFit(const TAcc &acc, const M3xN &hits, V4 &result)
A very fast helix fit: it fits a circle by three points (first, middle and last point) and a line by ...
Definition: RiemannFit.h:385
Eigen::Matrix< double, 6, 6 > Matrix6d
Definition: FitResult.h:18
ALPAKA_FN_ACC ALPAKA_FN_INLINE VectorNd< N > weightCircle(const TAcc &acc, const MatrixNd< N > &cov_rad_inv)
Compute the points&#39; weights&#39; vector for the circle fit when multiple scattering is managed...
Definition: RiemannFit.h:284
Eigen::Matrix< double, N, 1 > VectorNd
Definition: FitUtils.h:37
int32_t qCharge
particle charge
Definition: FitResult.h:58
T sqrt(T t)
Definition: SSEVec.h:23
Eigen::Matrix2d Matrix2d
Definition: FitResult.h:14
ALPAKA_FN_ACC ALPAKA_FN_INLINE void operator()(const TAcc &acc, const Matrix3xNd< N > *hits, const Eigen::Matrix< float, 6, N > *hits_ge, const double bField, const bool error, HelixFit *helix) const
Definition: RiemannFit.h:993
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
Eigen::Matrix4d Matrix4d
Definition: FitResult.h:16
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
Eigen::Matrix< double, 3, N > Matrix3xNd
Definition: HelixFit.h:30
#define M_PI
bias2_t b2[25]
Definition: b2.h:9
Polynomial< 0 > Constant
Definition: Constant.h:6
ALPAKA_FN_ACC ALPAKA_FN_INLINE MatrixNd< N > scatter_cov_rad(const TAcc &acc, const M2xN &p2D, const V4 &fast_fit, VectorNd< N > const &rad, double B)
Compute the covariance matrix (in radial coordinates) of points in the transverse plane due to multip...
Definition: RiemannFit.h:134
ALPAKA_FN_ACC ALPAKA_FN_INLINE void const M3xN const V4 & fast_fit
Definition: BrokenLine.h:158
Eigen::Matrix< double, 2 *N, 2 *N > Matrix2Nd
Definition: FitUtils.h:25
constexpr float sol
Definition: Config.h:13
ALPAKA_FN_ACC ALPAKA_FN_INLINE int32_t charge(const TAcc &acc, const M2xN &p2D, const Vector3d &par_uvr)
Find particle q considering the sign of cross product between particles velocity (estimated by the fi...
Definition: RiemannFit.h:297
#define N
Definition: blowfish.cc:9
Eigen::Vector2d Vector2d
Definition: FitResult.h:10
ALPAKA_FN_ACC void printIt(const TAcc &acc, C *m, const char *prefix="")
Definition: FitUtils.h:90
double b
Definition: hdecay.h:120
Helix fit by three step: -fast pre-fit (see Fast_fit() for further info); -circle fit of hits proje...
Definition: RiemannFit.h:990
ALPAKA_FN_ACC ALPAKA_FN_INLINE auto scatterCovLine(const TAcc &acc, Matrix2d const *cov_sz, const V4 &fast_fit, VNd1 const &s_arcs, VNd2 const &z_values, const double theta, const double bField, MatrixNd< N > &ret)
Compute the covariance matrix along cartesian S-Z of points due to multiple Coulomb scattering to be ...
Definition: RiemannFit.h:71
ALPAKA_FN_ACC ALPAKA_FN_INLINE Vector3d min_eigen3D(const TAcc &acc, const Matrix3d &A, double &chi2)
Compute the eigenvector associated to the minimum eigenvalue.
Definition: RiemannFit.h:319
double a
Definition: hdecay.h:121
ALPAKA_FN_ACC ALPAKA_FN_INLINE CircleFit circleFit(const TAcc &acc, const M2xN &hits2D, const Matrix2Nd< N > &hits_cov2D, const V4 &fast_fit, const VectorNd< N > &rad, const double bField, const bool error)
Fit a generic number of 2D points with a circle using Riemann-Chernov algorithm. Covariance matrix of...
Definition: RiemannFit.h:465
ALPAKA_FN_ACC ALPAKA_FN_INLINE VectorNd< N > cov_carttorad(const TAcc &acc, const M2xN &p2D, const Matrix2Nd< N > &cov_cart, const VectorNd< N > &rad)
Transform covariance matrix from Cartesian coordinates (only transverse plane component) to radial co...
Definition: RiemannFit.h:218
Definition: APVGainStruct.h:7
tmp
align.sh
Definition: createJobs.py:716
ALPAKA_FN_ACC ALPAKA_FN_INLINE Matrix2Nd< N > cov_radtocart(const TAcc &acc, const M2xN &p2D, const MatrixNd< N > &cov_rad, const VectorNd< N > &rad)
Transform covariance matrix from radial (only tangential component) to Cartesian coordinates (only tr...
Definition: RiemannFit.h:180
Geom::Theta< T > theta() const
ALPAKA_FN_ACC ALPAKA_FN_INLINE Vector2d min_eigen2D(const TAcc &acc, const Matrix2d &aMat, double &chi2)
2D version of min_eigen3D().
Definition: RiemannFit.h:363
ALPAKA_FN_ACC ALPAKA_FN_INLINE Vector3d min_eigen3D_fast(const TAcc &acc, const Matrix3d &A)
A faster version of min_eigen3D() where double precision is not needed.
Definition: RiemannFit.h:345