|
11 | 11 |
|
12 | 12 | #include "ReconstructionDataFormats/TrackFwd.h" |
13 | 13 | #include "Math/MatrixFunctions.h" |
| 14 | +#include <GPUCommonLogger.h> |
14 | 15 |
|
15 | 16 | namespace o2 |
16 | 17 | { |
@@ -503,5 +504,73 @@ bool TrackParCovFwd::getCovXYZPxPyPzGlo(std::array<float, 21>& cv) const |
503 | 504 | return true; |
504 | 505 | } |
505 | 506 |
|
| 507 | +//________________________________________________________________ |
| 508 | + |
| 509 | +void TrackParCovFwd::propagateToDCAhelix(double zField, const std::array<double, 3>& p, std::array<double, 3>& dca) |
| 510 | +{ |
| 511 | + // Computing DCA of fwd track w.r.t vertex in helix track model, using Newton-Raphson minimization |
| 512 | + |
| 513 | + auto x0 = mParameters(0); |
| 514 | + auto y0 = mParameters(1); |
| 515 | + auto z0 = mZ; |
| 516 | + auto phi0 = mParameters(2); |
| 517 | + auto tanl = mParameters(3); |
| 518 | + auto qOverPt = mParameters(4); |
| 519 | + auto k = TMath::Abs(o2::constants::math::B2C * zField); |
| 520 | + auto qpt = 1.0 / qOverPt; |
| 521 | + auto qR = qpt / std::fabs(k); |
| 522 | + auto invtanl = 1.0 / tanl; |
| 523 | + auto Hz = std::copysign(1, zField); |
| 524 | + |
| 525 | + auto xPV = p[0]; |
| 526 | + auto yPV = p[1]; |
| 527 | + auto zPV = p[2]; |
| 528 | + |
| 529 | + auto qRtanl = qR * tanl; |
| 530 | + auto invqRtanl = 1.0 / qRtanl; |
| 531 | + auto [sinp, cosp] = o2::math_utils::sincosd(phi0); |
| 532 | + |
| 533 | + auto z = zPV; |
| 534 | + double tol = 1e-4; |
| 535 | + int max_iter = 10; |
| 536 | + int iter = 0; |
| 537 | + |
| 538 | + while (iter++ < max_iter) { |
| 539 | + double theta = (z0 - z) * invqRtanl; |
| 540 | + double phi_theta = phi0 + Hz * theta; |
| 541 | + double sin_phi_theta = sin(phi_theta); |
| 542 | + double cos_phi_theta = cos(phi_theta); |
| 543 | + |
| 544 | + double DX = x0 - Hz * qR * (sin_phi_theta - sinp) - xPV; |
| 545 | + double DY = y0 + Hz * qR * (cos_phi_theta - cosp) - yPV; |
| 546 | + double DZ = z - zPV; |
| 547 | + |
| 548 | + double dD2_dZ = |
| 549 | + 2 * DX * cos_phi_theta * invtanl + |
| 550 | + 2 * DY * sin_phi_theta * invtanl + |
| 551 | + 2 * DZ; |
| 552 | + |
| 553 | + double d2D2_dZ2 = |
| 554 | + 2 * invtanl * invtanl + |
| 555 | + 2 * invtanl * (DX * Hz * sin_phi_theta - DY * Hz * cos_phi_theta) * invqRtanl + |
| 556 | + 2; |
| 557 | + |
| 558 | + double z_new = z - dD2_dZ / d2D2_dZ2; |
| 559 | + |
| 560 | + if (std::abs(z_new - z) < tol) { |
| 561 | + z = z_new; |
| 562 | + this->propagateToZhelix(z, zField); |
| 563 | + dca[0] = this->getX() - xPV; |
| 564 | + dca[1] = this->getY() - yPV; |
| 565 | + dca[2] = this->getZ() - zPV; |
| 566 | + LOG(debug) << "Converged after " << iter << " iterations for vertex X=" << p[0] << ", Y=" << p[1] << ", Z = " << p[2]; |
| 567 | + return; |
| 568 | + } |
| 569 | + z = z_new; |
| 570 | + } |
| 571 | + LOG(debug) << "Failed to converge after " << iter << " iterations for vertex X=" << p[0] << ", Y=" << p[1] << ", Z = " << p[2]; |
| 572 | + return; |
| 573 | +} |
| 574 | + |
506 | 575 | } // namespace track |
507 | 576 | } // namespace o2 |
0 commit comments