File indexing completed on 2024-04-06 12:28:38
0001 #ifndef RecoTracker_PixelTrackFitting_RiemannFit_h
0002 #define RecoTracker_PixelTrackFitting_RiemannFit_h
0003
0004 #include <Eigen/Core>
0005 #include <Eigen/Eigenvalues>
0006
0007 #include "RecoTracker/PixelTrackFitting/interface/FitUtils.h"
0008
0009 namespace riemannFit {
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 template <typename VNd1, typename VNd2>
0034 __host__ __device__ inline void computeRadLenUniformMaterial(const VNd1& length_values, VNd2& rad_lengths) {
0035
0036
0037 constexpr double xx_0_inv = 0.06 / 16.;
0038 uint n = length_values.rows();
0039 rad_lengths(0) = length_values(0) * xx_0_inv;
0040 for (uint j = 1; j < n; ++j) {
0041 rad_lengths(j) = std::abs(length_values(j) - length_values(j - 1)) * xx_0_inv;
0042 }
0043 }
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 template <typename V4, typename VNd1, typename VNd2, int N>
0065 __host__ __device__ inline auto scatterCovLine(Matrix2d const* cov_sz,
0066 const V4& fast_fit,
0067 VNd1 const& s_arcs,
0068 VNd2 const& z_values,
0069 const double theta,
0070 const double bField,
0071 MatrixNd<N>& ret) {
0072 #ifdef RFIT_DEBUG
0073 riemannFit::printIt(&s_arcs, "Scatter_cov_line - s_arcs: ");
0074 #endif
0075 constexpr uint n = N;
0076 double p_t = std::min(20., fast_fit(2) * bField);
0077 double p_2 = p_t * p_t * (1. + 1. / sqr(fast_fit(3)));
0078 VectorNd<N> rad_lengths_S;
0079
0080
0081
0082 VectorNd<N> s_values = s_arcs.array() * s_arcs.array() + z_values.array() * z_values.array();
0083 s_values = s_values.array().sqrt();
0084 computeRadLenUniformMaterial(s_values, rad_lengths_S);
0085 VectorNd<N> sig2_S;
0086 sig2_S = .000225 / p_2 * (1. + 0.038 * rad_lengths_S.array().log()).abs2() * rad_lengths_S.array();
0087 #ifdef RFIT_DEBUG
0088 riemannFit::printIt(cov_sz, "Scatter_cov_line - cov_sz: ");
0089 #endif
0090 Matrix2Nd<N> tmp = Matrix2Nd<N>::Zero();
0091 for (uint k = 0; k < n; ++k) {
0092 tmp(k, k) = cov_sz[k](0, 0);
0093 tmp(k + n, k + n) = cov_sz[k](1, 1);
0094 tmp(k, k + n) = tmp(k + n, k) = cov_sz[k](0, 1);
0095 }
0096 for (uint k = 0; k < n; ++k) {
0097 for (uint l = k; l < n; ++l) {
0098 for (uint i = 0; i < std::min(k, l); ++i) {
0099 tmp(k + n, l + n) += std::abs(s_values(k) - s_values(i)) * std::abs(s_values(l) - s_values(i)) * sig2_S(i);
0100 }
0101 tmp(l + n, k + n) = tmp(k + n, l + n);
0102 }
0103 }
0104
0105
0106 #ifdef RFIT_DEBUG
0107 riemannFit::printIt(&tmp, "Scatter_cov_line - tmp: ");
0108 #endif
0109 ret = tmp.block(n, n, n, n);
0110 }
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125 template <typename M2xN, typename V4, int N>
0126 __host__ __device__ inline MatrixNd<N> scatter_cov_rad(const M2xN& p2D,
0127 const V4& fast_fit,
0128 VectorNd<N> const& rad,
0129 double B) {
0130 constexpr uint n = N;
0131 double p_t = std::min(20., fast_fit(2) * B);
0132 double p_2 = p_t * p_t * (1. + 1. / sqr(fast_fit(3)));
0133 double theta = atan(fast_fit(3));
0134 theta = theta < 0. ? theta + M_PI : theta;
0135 VectorNd<N> s_values;
0136 VectorNd<N> rad_lengths;
0137 const Vector2d oVec(fast_fit(0), fast_fit(1));
0138
0139
0140 for (uint i = 0; i < n; ++i) {
0141 Vector2d pVec = p2D.block(0, i, 2, 1) - oVec;
0142 const double cross = cross2D(-oVec, pVec);
0143 const double dot = (-oVec).dot(pVec);
0144 const double tempAtan2 = atan2(cross, dot);
0145 s_values(i) = std::abs(tempAtan2 * fast_fit(2));
0146 }
0147 computeRadLenUniformMaterial(s_values * sqrt(1. + 1. / sqr(fast_fit(3))), rad_lengths);
0148 MatrixNd<N> scatter_cov_rad = MatrixNd<N>::Zero();
0149 VectorNd<N> sig2 = (1. + 0.038 * rad_lengths.array().log()).abs2() * rad_lengths.array();
0150 sig2 *= 0.000225 / (p_2 * sqr(sin(theta)));
0151 for (uint k = 0; k < n; ++k) {
0152 for (uint l = k; l < n; ++l) {
0153 for (uint i = 0; i < std::min(k, l); ++i) {
0154 scatter_cov_rad(k, l) += (rad(k) - rad(i)) * (rad(l) - rad(i)) * sig2(i);
0155 }
0156 scatter_cov_rad(l, k) = scatter_cov_rad(k, l);
0157 }
0158 }
0159 #ifdef RFIT_DEBUG
0160 riemannFit::printIt(&scatter_cov_rad, "Scatter_cov_rad - scatter_cov_rad: ");
0161 #endif
0162 return scatter_cov_rad;
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 template <typename M2xN, int N>
0174 __host__ __device__ inline Matrix2Nd<N> cov_radtocart(const M2xN& p2D,
0175 const MatrixNd<N>& cov_rad,
0176 const VectorNd<N>& rad) {
0177 #ifdef RFIT_DEBUG
0178 printf("Address of p2D: %p\n", &p2D);
0179 #endif
0180 printIt(&p2D, "cov_radtocart - p2D:");
0181 constexpr uint n = N;
0182 Matrix2Nd<N> cov_cart = Matrix2Nd<N>::Zero();
0183 VectorNd<N> rad_inv = rad.cwiseInverse();
0184 printIt(&rad_inv, "cov_radtocart - rad_inv:");
0185 for (uint i = 0; i < n; ++i) {
0186 for (uint j = i; j < n; ++j) {
0187 cov_cart(i, j) = cov_rad(i, j) * p2D(1, i) * rad_inv(i) * p2D(1, j) * rad_inv(j);
0188 cov_cart(i + n, j + n) = cov_rad(i, j) * p2D(0, i) * rad_inv(i) * p2D(0, j) * rad_inv(j);
0189 cov_cart(i, j + n) = -cov_rad(i, j) * p2D(1, i) * rad_inv(i) * p2D(0, j) * rad_inv(j);
0190 cov_cart(i + n, j) = -cov_rad(i, j) * p2D(0, i) * rad_inv(i) * p2D(1, j) * rad_inv(j);
0191 cov_cart(j, i) = cov_cart(i, j);
0192 cov_cart(j + n, i + n) = cov_cart(i + n, j + n);
0193 cov_cart(j + n, i) = cov_cart(i, j + n);
0194 cov_cart(j, i + n) = cov_cart(i + n, j);
0195 }
0196 }
0197 return cov_cart;
0198 }
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 template <typename M2xN, int N>
0211 __host__ __device__ inline VectorNd<N> cov_carttorad(const M2xN& p2D,
0212 const Matrix2Nd<N>& cov_cart,
0213 const VectorNd<N>& rad) {
0214 constexpr uint n = N;
0215 VectorNd<N> cov_rad;
0216 const VectorNd<N> rad_inv2 = rad.cwiseInverse().array().square();
0217 for (uint i = 0; i < n; ++i) {
0218
0219 if (rad(i) < 1.e-4)
0220 cov_rad(i) = cov_cart(i, i);
0221 else {
0222 cov_rad(i) = rad_inv2(i) * (cov_cart(i, i) * sqr(p2D(1, i)) + cov_cart(i + n, i + n) * sqr(p2D(0, i)) -
0223 2. * cov_cart(i, i + n) * p2D(0, i) * p2D(1, i));
0224 }
0225 }
0226 return cov_rad;
0227 }
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 template <typename M2xN, typename V4, int N>
0242 __host__ __device__ inline VectorNd<N> cov_carttorad_prefit(const M2xN& p2D,
0243 const Matrix2Nd<N>& cov_cart,
0244 V4& fast_fit,
0245 const VectorNd<N>& rad) {
0246 constexpr uint n = N;
0247 VectorNd<N> cov_rad;
0248 for (uint i = 0; i < n; ++i) {
0249
0250 if (rad(i) < 1.e-4)
0251 cov_rad(i) = cov_cart(i, i);
0252 else {
0253 Vector2d a = p2D.col(i);
0254 Vector2d b = p2D.col(i) - fast_fit.head(2);
0255 const double x2 = a.dot(b);
0256 const double y2 = cross2D(a, b);
0257 const double tan_c = -y2 / x2;
0258 const double tan_c2 = sqr(tan_c);
0259 cov_rad(i) =
0260 1. / (1. + tan_c2) * (cov_cart(i, i) + cov_cart(i + n, i + n) * tan_c2 + 2 * cov_cart(i, i + n) * tan_c);
0261 }
0262 }
0263 return cov_rad;
0264 }
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277 template <int N>
0278 __host__ __device__ inline VectorNd<N> weightCircle(const MatrixNd<N>& cov_rad_inv) {
0279 return cov_rad_inv.colwise().sum().transpose();
0280 }
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290 template <typename M2xN>
0291 __host__ __device__ inline int32_t charge(const M2xN& p2D, const Vector3d& par_uvr) {
0292 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)) >
0293 0)
0294 ? -1
0295 : 1;
0296 }
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313 __host__ __device__ inline Vector3d min_eigen3D(const Matrix3d& A, double& chi2) {
0314 #ifdef RFIT_DEBUG
0315 printf("min_eigen3D - enter\n");
0316 #endif
0317 Eigen::SelfAdjointEigenSolver<Matrix3d> solver(3);
0318 solver.computeDirect(A);
0319 int min_index;
0320 chi2 = solver.eigenvalues().minCoeff(&min_index);
0321 #ifdef RFIT_DEBUG
0322 printf("min_eigen3D - exit\n");
0323 #endif
0324 return solver.eigenvectors().col(min_index);
0325 }
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338 __host__ __device__ inline Vector3d min_eigen3D_fast(const Matrix3d& A) {
0339 Eigen::SelfAdjointEigenSolver<Matrix3f> solver(3);
0340 solver.computeDirect(A.cast<float>());
0341 int min_index;
0342 solver.eigenvalues().minCoeff(&min_index);
0343 return solver.eigenvectors().col(min_index).cast<double>();
0344 }
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 __host__ __device__ inline Vector2d min_eigen2D(const Matrix2d& aMat, double& chi2) {
0357 Eigen::SelfAdjointEigenSolver<Matrix2d> solver(2);
0358 solver.computeDirect(aMat);
0359 int min_index;
0360 chi2 = solver.eigenvalues().minCoeff(&min_index);
0361 return solver.eigenvectors().col(min_index);
0362 }
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377 template <typename M3xN, typename V4>
0378 __host__ __device__ inline void fastFit(const M3xN& hits, V4& result) {
0379 constexpr uint32_t N = M3xN::ColsAtCompileTime;
0380 constexpr auto n = N;
0381 printIt(&hits, "Fast_fit - hits: ");
0382
0383
0384
0385 const Vector2d bVec = hits.block(0, n / 2, 2, 1) - hits.block(0, 0, 2, 1);
0386 const Vector2d cVec = hits.block(0, n - 1, 2, 1) - hits.block(0, 0, 2, 1);
0387 printIt(&bVec, "Fast_fit - b: ");
0388 printIt(&cVec, "Fast_fit - c: ");
0389
0390 auto b2 = bVec.squaredNorm();
0391 auto c2 = cVec.squaredNorm();
0392
0393
0394
0395
0396
0397
0398 bool flip = abs(bVec.x()) < abs(bVec.y());
0399 auto bx = flip ? bVec.y() : bVec.x();
0400 auto by = flip ? bVec.x() : bVec.y();
0401 auto cx = flip ? cVec.y() : cVec.x();
0402 auto cy = flip ? cVec.x() : cVec.y();
0403
0404 auto div = 2. * (cx * by - bx * cy);
0405
0406 auto y0 = (cx * b2 - bx * c2) / div;
0407 auto x0 = (0.5 * b2 - y0 * by) / bx;
0408 result(0) = hits(0, 0) + (flip ? y0 : x0);
0409 result(1) = hits(1, 0) + (flip ? x0 : y0);
0410 result(2) = sqrt(sqr(x0) + sqr(y0));
0411 printIt(&result, "Fast_fit - result: ");
0412
0413
0414 const Vector2d dVec = hits.block(0, 0, 2, 1) - result.head(2);
0415 const Vector2d eVec = hits.block(0, n - 1, 2, 1) - result.head(2);
0416 printIt(&eVec, "Fast_fit - e: ");
0417 printIt(&dVec, "Fast_fit - d: ");
0418
0419 auto dr = result(2) * atan2(cross2D(dVec, eVec), dVec.dot(eVec));
0420
0421 auto dz = hits(2, n - 1) - hits(2, 0);
0422
0423 result(3) = (dr / dz);
0424
0425 #ifdef RFIT_DEBUG
0426 printf("Fast_fit: [%f, %f, %f, %f]\n", result(0), result(1), result(2), result(3));
0427 #endif
0428 }
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457 template <typename M2xN, typename V4, int N>
0458 __host__ __device__ inline CircleFit circleFit(const M2xN& hits2D,
0459 const Matrix2Nd<N>& hits_cov2D,
0460 const V4& fast_fit,
0461 const VectorNd<N>& rad,
0462 const double bField,
0463 const bool error) {
0464 #ifdef RFIT_DEBUG
0465 printf("circle_fit - enter\n");
0466 #endif
0467
0468 Matrix2Nd<N> vMat = hits_cov2D;
0469 constexpr uint n = N;
0470 printIt(&hits2D, "circle_fit - hits2D:");
0471 printIt(&hits_cov2D, "circle_fit - hits_cov2D:");
0472
0473 #ifdef RFIT_DEBUG
0474 printf("circle_fit - WEIGHT COMPUTATION\n");
0475 #endif
0476
0477 VectorNd<N> weight;
0478 MatrixNd<N> gMat;
0479 double renorm;
0480 {
0481 MatrixNd<N> cov_rad = cov_carttorad_prefit(hits2D, vMat, fast_fit, rad).asDiagonal();
0482 MatrixNd<N> scatterCovRadMat = scatter_cov_rad(hits2D, fast_fit, rad, bField);
0483 printIt(&scatterCovRadMat, "circle_fit - scatter_cov_rad:");
0484 printIt(&hits2D, "circle_fit - hits2D bis:");
0485 #ifdef RFIT_DEBUG
0486 printf("Address of hits2D: a) %p\n", &hits2D);
0487 #endif
0488 vMat += cov_radtocart(hits2D, scatterCovRadMat, rad);
0489 printIt(&vMat, "circle_fit - V:");
0490 cov_rad += scatterCovRadMat;
0491 printIt(&cov_rad, "circle_fit - cov_rad:");
0492 math::cholesky::invert(cov_rad, gMat);
0493
0494 renorm = gMat.sum();
0495 gMat *= 1. / renorm;
0496 weight = weightCircle(gMat);
0497 }
0498 printIt(&weight, "circle_fit - weight:");
0499
0500
0501 #ifdef RFIT_DEBUG
0502 printf("circle_fit - SPACE TRANSFORMATION\n");
0503 #endif
0504
0505
0506 #ifdef RFIT_DEBUG
0507 printf("Address of hits2D: b) %p\n", &hits2D);
0508 #endif
0509 const Vector2d hCentroid = hits2D.rowwise().mean();
0510 printIt(&hCentroid, "circle_fit - h_:");
0511 Matrix3xNd<N> p3D;
0512 p3D.block(0, 0, 2, n) = hits2D.colwise() - hCentroid;
0513 printIt(&p3D, "circle_fit - p3D: a)");
0514 Vector2Nd<N> mc;
0515 mc << p3D.row(0).transpose(), p3D.row(1).transpose();
0516 printIt(&mc, "circle_fit - mc(centered hits):");
0517
0518
0519 const double tempQ = mc.squaredNorm();
0520 const double tempS = sqrt(n * 1. / tempQ);
0521 p3D.block(0, 0, 2, n) *= tempS;
0522
0523
0524 p3D.row(2) = p3D.block(0, 0, 2, n).colwise().squaredNorm();
0525 printIt(&p3D, "circle_fit - p3D: b)");
0526
0527 #ifdef RFIT_DEBUG
0528 printf("circle_fit - COST FUNCTION\n");
0529 #endif
0530
0531
0532
0533 Vector3d r0;
0534 r0.noalias() = p3D * weight;
0535 const Matrix3xNd<N> xMat = p3D.colwise() - r0;
0536 Matrix3d aMat = xMat * gMat * xMat.transpose();
0537 printIt(&aMat, "circle_fit - A:");
0538
0539 #ifdef RFIT_DEBUG
0540 printf("circle_fit - MINIMIZE\n");
0541 #endif
0542
0543 double chi2;
0544 Vector3d vVec = min_eigen3D(aMat, chi2);
0545 #ifdef RFIT_DEBUG
0546 printf("circle_fit - AFTER MIN_EIGEN\n");
0547 #endif
0548 printIt(&vVec, "v BEFORE INVERSION");
0549 vVec *= (vVec(2) > 0) ? 1 : -1;
0550 printIt(&vVec, "v AFTER INVERSION");
0551
0552
0553 #ifdef RFIT_DEBUG
0554 printf("circle_fit - AFTER MIN_EIGEN 1\n");
0555 #endif
0556 Eigen::Matrix<double, 1, 1> cm;
0557 #ifdef RFIT_DEBUG
0558 printf("circle_fit - AFTER MIN_EIGEN 2\n");
0559 #endif
0560 cm = -vVec.transpose() * r0;
0561 #ifdef RFIT_DEBUG
0562 printf("circle_fit - AFTER MIN_EIGEN 3\n");
0563 #endif
0564 const double tempC = cm(0, 0);
0565
0566 #ifdef RFIT_DEBUG
0567 printf("circle_fit - COMPUTE CIRCLE PARAMETER\n");
0568 #endif
0569
0570
0571
0572 const double tempH = sqrt(1. - sqr(vVec(2)) - 4. * tempC * vVec(2));
0573 const double v2x2_inv = 1. / (2. * vVec(2));
0574 const double s_inv = 1. / tempS;
0575 Vector3d par_uvr;
0576 par_uvr << -vVec(0) * v2x2_inv, -vVec(1) * v2x2_inv, tempH * v2x2_inv;
0577
0578 CircleFit circle;
0579 circle.par << par_uvr(0) * s_inv + hCentroid(0), par_uvr(1) * s_inv + hCentroid(1), par_uvr(2) * s_inv;
0580 circle.qCharge = charge(hits2D, circle.par);
0581 circle.chi2 = abs(chi2) * renorm / sqr(2 * vVec(2) * par_uvr(2) * tempS);
0582 printIt(&circle.par, "circle_fit - CIRCLE PARAMETERS:");
0583 printIt(&circle.cov, "circle_fit - CIRCLE COVARIANCE:");
0584 #ifdef RFIT_DEBUG
0585 printf("circle_fit - CIRCLE CHARGE: %d\n", circle.qCharge);
0586 #endif
0587
0588 #ifdef RFIT_DEBUG
0589 printf("circle_fit - ERROR PROPAGATION\n");
0590 #endif
0591
0592 if (error) {
0593 #ifdef RFIT_DEBUG
0594 printf("circle_fit - ERROR PRPAGATION ACTIVATED\n");
0595 #endif
0596 ArrayNd<N> vcsMat[2][2];
0597 MatrixNd<N> cMat[3][3];
0598 #ifdef RFIT_DEBUG
0599 printf("circle_fit - ERROR PRPAGATION ACTIVATED 2\n");
0600 #endif
0601 {
0602 Eigen::Matrix<double, 1, 1> cm;
0603 Eigen::Matrix<double, 1, 1> cm2;
0604 cm = mc.transpose() * vMat * mc;
0605 const double tempC2 = cm(0, 0);
0606 Matrix2Nd<N> tempVcsMat;
0607 tempVcsMat.template triangularView<Eigen::Upper>() =
0608 (sqr(tempS) * vMat + sqr(sqr(tempS)) * 1. / (4. * tempQ * n) *
0609 (2. * vMat.squaredNorm() + 4. * tempC2) *
0610 (mc * mc.transpose()));
0611
0612 printIt(&tempVcsMat, "circle_fit - Vcs:");
0613 cMat[0][0] = tempVcsMat.block(0, 0, n, n).template selfadjointView<Eigen::Upper>();
0614 vcsMat[0][1] = tempVcsMat.block(0, n, n, n);
0615 cMat[1][1] = tempVcsMat.block(n, n, n, n).template selfadjointView<Eigen::Upper>();
0616 vcsMat[1][0] = vcsMat[0][1].transpose();
0617 printIt(&tempVcsMat, "circle_fit - Vcs:");
0618 }
0619
0620 {
0621 const ArrayNd<N> t0 = (VectorXd::Constant(n, 1.) * p3D.row(0));
0622 const ArrayNd<N> t1 = (VectorXd::Constant(n, 1.) * p3D.row(1));
0623 const ArrayNd<N> t00 = p3D.row(0).transpose() * p3D.row(0);
0624 const ArrayNd<N> t01 = p3D.row(0).transpose() * p3D.row(1);
0625 const ArrayNd<N> t11 = p3D.row(1).transpose() * p3D.row(1);
0626 const ArrayNd<N> t10 = t01.transpose();
0627 vcsMat[0][0] = cMat[0][0];
0628 cMat[0][1] = vcsMat[0][1];
0629 cMat[0][2] = 2. * (vcsMat[0][0] * t0 + vcsMat[0][1] * t1);
0630 vcsMat[1][1] = cMat[1][1];
0631 cMat[1][2] = 2. * (vcsMat[1][0] * t0 + vcsMat[1][1] * t1);
0632 MatrixNd<N> tmp;
0633 tmp.template triangularView<Eigen::Upper>() =
0634 (2. * (vcsMat[0][0] * vcsMat[0][0] + vcsMat[0][0] * vcsMat[0][1] + vcsMat[1][1] * vcsMat[1][0] +
0635 vcsMat[1][1] * vcsMat[1][1]) +
0636 4. * (vcsMat[0][0] * t00 + vcsMat[0][1] * t01 + vcsMat[1][0] * t10 + vcsMat[1][1] * t11))
0637 .matrix();
0638 cMat[2][2] = tmp.template selfadjointView<Eigen::Upper>();
0639 }
0640 printIt(&cMat[0][0], "circle_fit - C[0][0]:");
0641
0642 Matrix3d c0Mat;
0643 for (uint i = 0; i < 3; ++i) {
0644 for (uint j = i; j < 3; ++j) {
0645 Eigen::Matrix<double, 1, 1> tmp;
0646 tmp = weight.transpose() * cMat[i][j] * weight;
0647
0648 const double tempC = tmp(0, 0);
0649 c0Mat(i, j) = tempC;
0650 c0Mat(j, i) = c0Mat(i, j);
0651 }
0652 }
0653 printIt(&c0Mat, "circle_fit - C0:");
0654
0655 const MatrixNd<N> wMat = weight * weight.transpose();
0656 const MatrixNd<N> hMat = MatrixNd<N>::Identity().rowwise() - weight.transpose();
0657 const MatrixNx3d<N> s_v = hMat * p3D.transpose();
0658 printIt(&wMat, "circle_fit - W:");
0659 printIt(&hMat, "circle_fit - H:");
0660 printIt(&s_v, "circle_fit - s_v:");
0661
0662 MatrixNd<N> dMat[3][3];
0663 dMat[0][0] = (hMat * cMat[0][0] * hMat.transpose()).cwiseProduct(wMat);
0664 dMat[0][1] = (hMat * cMat[0][1] * hMat.transpose()).cwiseProduct(wMat);
0665 dMat[0][2] = (hMat * cMat[0][2] * hMat.transpose()).cwiseProduct(wMat);
0666 dMat[1][1] = (hMat * cMat[1][1] * hMat.transpose()).cwiseProduct(wMat);
0667 dMat[1][2] = (hMat * cMat[1][2] * hMat.transpose()).cwiseProduct(wMat);
0668 dMat[2][2] = (hMat * cMat[2][2] * hMat.transpose()).cwiseProduct(wMat);
0669 dMat[1][0] = dMat[0][1].transpose();
0670 dMat[2][0] = dMat[0][2].transpose();
0671 dMat[2][1] = dMat[1][2].transpose();
0672 printIt(&dMat[0][0], "circle_fit - D_[0][0]:");
0673
0674 constexpr uint nu[6][2] = {{0, 0}, {0, 1}, {0, 2}, {1, 1}, {1, 2}, {2, 2}};
0675
0676 Matrix6d eMat;
0677 for (uint a = 0; a < 6; ++a) {
0678 const uint i = nu[a][0], j = nu[a][1];
0679 for (uint b = a; b < 6; ++b) {
0680 const uint k = nu[b][0], l = nu[b][1];
0681 VectorNd<N> t0(n);
0682 VectorNd<N> t1(n);
0683 if (l == k) {
0684 t0 = 2. * dMat[j][l] * s_v.col(l);
0685 if (i == j)
0686 t1 = t0;
0687 else
0688 t1 = 2. * dMat[i][l] * s_v.col(l);
0689 } else {
0690 t0 = dMat[j][l] * s_v.col(k) + dMat[j][k] * s_v.col(l);
0691 if (i == j)
0692 t1 = t0;
0693 else
0694 t1 = dMat[i][l] * s_v.col(k) + dMat[i][k] * s_v.col(l);
0695 }
0696
0697 if (i == j) {
0698 Eigen::Matrix<double, 1, 1> cm;
0699 cm = s_v.col(i).transpose() * (t0 + t1);
0700
0701 const double tempC = cm(0, 0);
0702 eMat(a, b) = 0. + tempC;
0703 } else {
0704 Eigen::Matrix<double, 1, 1> cm;
0705 cm = (s_v.col(i).transpose() * t0) + (s_v.col(j).transpose() * t1);
0706
0707 const double tempC = cm(0, 0);
0708 eMat(a, b) = 0. + tempC;
0709 }
0710 if (b != a)
0711 eMat(b, a) = eMat(a, b);
0712 }
0713 }
0714 printIt(&eMat, "circle_fit - E:");
0715
0716 Eigen::Matrix<double, 3, 6> j2Mat;
0717 for (uint a = 0; a < 6; ++a) {
0718 const uint i = nu[a][0], j = nu[a][1];
0719 Matrix3d delta = Matrix3d::Zero();
0720 delta(i, j) = delta(j, i) = abs(aMat(i, j) * epsilon);
0721 j2Mat.col(a) = min_eigen3D_fast(aMat + delta);
0722 const int sign = (j2Mat.col(a)(2) > 0) ? 1 : -1;
0723 j2Mat.col(a) = (j2Mat.col(a) * sign - vVec) / delta(i, j);
0724 }
0725 printIt(&j2Mat, "circle_fit - J2:");
0726
0727 Matrix4d cvcMat;
0728 {
0729 Matrix3d t0 = j2Mat * eMat * j2Mat.transpose();
0730 Vector3d t1 = -t0 * r0;
0731 cvcMat.block(0, 0, 3, 3) = t0;
0732 cvcMat.block(0, 3, 3, 1) = t1;
0733 cvcMat.block(3, 0, 1, 3) = t1.transpose();
0734 Eigen::Matrix<double, 1, 1> cm1;
0735 Eigen::Matrix<double, 1, 1> cm3;
0736 cm1 = (vVec.transpose() * c0Mat * vVec);
0737
0738 cm3 = (r0.transpose() * t0 * r0);
0739
0740 const double tempC = cm1(0, 0) + (c0Mat.cwiseProduct(t0)).sum() + cm3(0, 0);
0741 cvcMat(3, 3) = tempC;
0742
0743 }
0744 printIt(&cvcMat, "circle_fit - Cvc:");
0745
0746 Eigen::Matrix<double, 3, 4> j3Mat;
0747 {
0748 const double t = 1. / tempH;
0749 j3Mat << -v2x2_inv, 0, vVec(0) * sqr(v2x2_inv) * 2., 0, 0, -v2x2_inv, vVec(1) * sqr(v2x2_inv) * 2., 0,
0750 vVec(0) * v2x2_inv * t, vVec(1) * v2x2_inv * t,
0751 -tempH * sqr(v2x2_inv) * 2. - (2. * tempC + vVec(2)) * v2x2_inv * t, -t;
0752 }
0753 printIt(&j3Mat, "circle_fit - J3:");
0754
0755 const RowVector2Nd<N> Jq = mc.transpose() * tempS * 1. / n;
0756 printIt(&Jq, "circle_fit - Jq:");
0757
0758 Matrix3d cov_uvr = j3Mat * cvcMat * j3Mat.transpose() * sqr(s_inv)
0759 + (par_uvr * par_uvr.transpose()) * (Jq * vMat * Jq.transpose());
0760
0761 circle.cov = cov_uvr;
0762 }
0763
0764 printIt(&circle.cov, "Circle cov:");
0765 #ifdef RFIT_DEBUG
0766 printf("circle_fit - exit\n");
0767 #endif
0768 return circle;
0769 }
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787 template <typename M3xN, typename M6xN, typename V4>
0788 __host__ __device__ inline LineFit lineFit(const M3xN& hits,
0789 const M6xN& hits_ge,
0790 const CircleFit& circle,
0791 const V4& fast_fit,
0792 const double bField,
0793 const bool error) {
0794 constexpr uint32_t N = M3xN::ColsAtCompileTime;
0795 constexpr auto n = N;
0796 double theta = -circle.qCharge * atan(fast_fit(3));
0797 theta = theta < 0. ? theta + M_PI : theta;
0798
0799
0800 Eigen::Matrix<double, 2, 2> rot;
0801 rot << sin(theta), cos(theta), -cos(theta), sin(theta);
0802
0803
0804
0805
0806
0807
0808
0809
0810
0811 Matrix2xNd<N> p2D = Matrix2xNd<N>::Zero();
0812 Eigen::Matrix<double, 2, 6> jxMat;
0813
0814 #ifdef RFIT_DEBUG
0815 printf("Line_fit - B: %g\n", bField);
0816 printIt(&hits, "Line_fit points: ");
0817 printIt(&hits_ge, "Line_fit covs: ");
0818 printIt(&rot, "Line_fit rot: ");
0819 #endif
0820
0821
0822
0823
0824
0825 const Vector2d oVec(circle.par(0), circle.par(1));
0826
0827
0828 Matrix6d covMat = Matrix6d::Zero();
0829 Matrix2d cov_sz[N];
0830 for (uint i = 0; i < n; ++i) {
0831 Vector2d pVec = hits.block(0, i, 2, 1) - oVec;
0832 const double cross = cross2D(-oVec, pVec);
0833 const double dot = (-oVec).dot(pVec);
0834
0835
0836 const double tempQAtan2 = -circle.qCharge * atan2(cross, dot);
0837
0838 p2D(0, i) = tempQAtan2 * circle.par(2);
0839
0840
0841 const double temp0 = -circle.qCharge * circle.par(2) * 1. / (sqr(dot) + sqr(cross));
0842 double d_X0 = 0., d_Y0 = 0., d_R = 0.;
0843 if (error) {
0844 d_X0 = -temp0 * ((pVec(1) + oVec(1)) * dot - (pVec(0) - oVec(0)) * cross);
0845 d_Y0 = temp0 * ((pVec(0) + oVec(0)) * dot - (oVec(1) - pVec(1)) * cross);
0846 d_R = tempQAtan2;
0847 }
0848 const double d_x = temp0 * (oVec(1) * dot + oVec(0) * cross);
0849 const double d_y = temp0 * (-oVec(0) * dot + oVec(1) * cross);
0850 jxMat << d_X0, d_Y0, d_R, d_x, d_y, 0., 0., 0., 0., 0., 0., 1.;
0851
0852 covMat.block(0, 0, 3, 3) = circle.cov;
0853 covMat(3, 3) = hits_ge.col(i)[0];
0854 covMat(4, 4) = hits_ge.col(i)[2];
0855 covMat(5, 5) = hits_ge.col(i)[5];
0856 covMat(3, 4) = covMat(4, 3) = hits_ge.col(i)[1];
0857 covMat(3, 5) = covMat(5, 3) = hits_ge.col(i)[3];
0858 covMat(4, 5) = covMat(5, 4) = hits_ge.col(i)[4];
0859 Matrix2d tmp = jxMat * covMat * jxMat.transpose();
0860 cov_sz[i].noalias() = rot * tmp * rot.transpose();
0861 }
0862
0863 p2D.row(1) = hits.row(2);
0864
0865
0866
0867 MatrixNd<N> cov_with_ms;
0868 scatterCovLine(cov_sz, fast_fit, p2D.row(0), p2D.row(1), theta, bField, cov_with_ms);
0869 #ifdef RFIT_DEBUG
0870 printIt(cov_sz, "line_fit - cov_sz:");
0871 printIt(&cov_with_ms, "line_fit - cov_with_ms: ");
0872 #endif
0873
0874
0875 Matrix2xNd<N> p2D_rot = rot * p2D;
0876
0877 #ifdef RFIT_DEBUG
0878 printf("Fast fit Tan(theta): %g\n", fast_fit(3));
0879 printf("Rotation angle: %g\n", theta);
0880 printIt(&rot, "Rotation Matrix:");
0881 printIt(&p2D, "Original Hits(s,z):");
0882 printIt(&p2D_rot, "Rotated hits(S3D, Z'):");
0883 printIt(&rot, "Rotation Matrix:");
0884 #endif
0885
0886
0887 Matrix2xNd<N> aMat;
0888 aMat << MatrixXd::Ones(1, n), p2D_rot.row(0);
0889
0890 #ifdef RFIT_DEBUG
0891 printIt(&aMat, "A Matrix:");
0892 #endif
0893
0894
0895 MatrixNd<N> vyInvMat;
0896 math::cholesky::invert(cov_with_ms, vyInvMat);
0897
0898 Eigen::Matrix<double, 2, 2> covParamsMat = aMat * vyInvMat * aMat.transpose();
0899
0900 math::cholesky::invert(covParamsMat, covParamsMat);
0901
0902
0903
0904
0905 Eigen::Matrix<double, 2, 1> sol = covParamsMat * aMat * vyInvMat * p2D_rot.row(1).transpose();
0906
0907 #ifdef RFIT_DEBUG
0908 printIt(&sol, "Rotated solutions:");
0909 #endif
0910
0911
0912 const auto sinTheta = sin(theta);
0913 const auto cosTheta = cos(theta);
0914 auto common_factor = 1. / (sinTheta - sol(1, 0) * cosTheta);
0915 Eigen::Matrix<double, 2, 2> jMat;
0916 jMat << 0., common_factor * common_factor, common_factor, sol(0, 0) * cosTheta * common_factor * common_factor;
0917
0918 double tempM = common_factor * (sol(1, 0) * sinTheta + cosTheta);
0919 double tempQ = common_factor * sol(0, 0);
0920 auto cov_mq = jMat * covParamsMat * jMat.transpose();
0921
0922 VectorNd<N> res = p2D_rot.row(1).transpose() - aMat.transpose() * sol;
0923 double chi2 = res.transpose() * vyInvMat * res;
0924
0925 LineFit line;
0926 line.par << tempM, tempQ;
0927 line.cov << cov_mq;
0928 line.chi2 = chi2;
0929
0930 #ifdef RFIT_DEBUG
0931 printf("Common_factor: %g\n", common_factor);
0932 printIt(&jMat, "Jacobian:");
0933 printIt(&sol, "Rotated solutions:");
0934 printIt(&covParamsMat, "Cov_params:");
0935 printIt(&cov_mq, "Rotated Covariance Matrix:");
0936 printIt(&(line.par), "Real Parameters:");
0937 printIt(&(line.cov), "Real Covariance Matrix:");
0938 printf("Chi2: %g\n", chi2);
0939 #endif
0940
0941 return line;
0942 }
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977 template <int N>
0978 inline HelixFit helixFit(const Matrix3xNd<N>& hits,
0979 const Eigen::Matrix<float, 6, N>& hits_ge,
0980 const double bField,
0981 const bool error) {
0982 constexpr uint n = N;
0983 VectorNd<4> rad = (hits.block(0, 0, 2, n).colwise().norm());
0984
0985
0986 Vector4d fast_fit;
0987 fastFit(hits, fast_fit);
0988 riemannFit::Matrix2Nd<N> hits_cov = MatrixXd::Zero(2 * n, 2 * n);
0989 riemannFit::loadCovariance2D(hits_ge, hits_cov);
0990 CircleFit circle = circleFit(hits.block(0, 0, 2, n), hits_cov, fast_fit, rad, bField, error);
0991 LineFit line = lineFit(hits, hits_ge, circle, fast_fit, bField, error);
0992
0993 par_uvrtopak(circle, bField, error);
0994
0995 HelixFit helix;
0996 helix.par << circle.par, line.par;
0997 if (error) {
0998 helix.cov = MatrixXd::Zero(5, 5);
0999 helix.cov.block(0, 0, 3, 3) = circle.cov;
1000 helix.cov.block(3, 3, 2, 2) = line.cov;
1001 }
1002 helix.qCharge = circle.qCharge;
1003 helix.chi2_circle = circle.chi2;
1004 helix.chi2_line = line.chi2;
1005
1006 return helix;
1007 }
1008
1009 }
1010
1011 #endif