17#ifndef _ALICEO2_DCA_FWDFITTERN_
18#define _ALICEO2_DCA_FWDFITTERN_
43 float detXY = cxx * cyy - cxy * cxy;
45 auto detXYI = 1. / detXY;
51 throw std::runtime_error(
"invalid track covariance");
64 float snp = trc.
getSnp(), csp = std::sqrt((1. - snp) * (1. + snp)), cspI = 1. / csp, crv2c = trc.
getCurvature(bz), tgl = trc.
getTanl(), tglI = 1. / tgl;
66 crv2c = (trc.
getCharge()) * 0.3 * bz * (-1e-3);
71 d2xdz2 = crv2c * snp * tglI * tglI;
72 d2ydz2 = -crv2c * csp * tglI * tglI;
76template <
int N,
typename... Args>
79 static constexpr double NMin = 2;
80 static constexpr double NMax = 4;
81 static constexpr double NInv = 1. / N;
82 static constexpr int MAXHYP = 2;
83 static constexpr float ZerrFactor = 5.;
95 using ArrTrack = std::array<Track, N>;
96 using ArrTrackCovI = std::array<FwdTrackCovI, N>;
97 using ArrTrCoef = std::array<TrackCoefVtx, N>;
98 using ArrTrDer = std::array<FwdTrackDeriv, N>;
99 using ArrTrPos = std::array<Vec3D, N>;
105 FwdDCAFitterN(
float bz,
bool useAbsDCA,
bool prop2DCA) : mBz(bz), mUseAbsDCA(useAbsDCA), mPropagateToPCA(prop2DCA)
107 static_assert(N >= NMin && N <= NMax,
"N prongs outside of allowed range");
115 const auto& vd = mPCA[mOrder[cand]];
116 return std::array<float, 3>{float(vd[0]), float(vd[1]), float(vd[2])};
133 if (!mTrPropDone[mOrder[cand]]) {
134 throw std::runtime_error(
"propagateTracksToVertex was not called yet");
136 return mCandTr[mOrder[cand]][
i];
147 return {float(
m(0, 0)), float(
m(1, 0)), float(
m(1, 1)), float(
m(2, 0)), float(
m(2, 1)), float(
m(2, 2))};
166 mUseMatBudget =
true;
173 float getMaxR()
const {
return std::sqrt(mMaxR2); }
179 double getHz(
double b)
const {
return std::copysign(1,
b); }
185 template <
class... Tr>
186 int process(
const Tr&... args);
233 const auto& trc = mCandTr[mOrder[cand]][
i];
235 mat(0, 0) = trc.getSigma2X();
236 mat(1, 1) = trc.getSigma2Y();
237 mat(1, 0) = trc.getSigmaXY();
238 mat(2, 2) = trc.getSigma2Y() * ZerrFactor;
243 template <
class T,
class... Tr>
244 void assign(
int i,
const T& t,
const Tr&... args)
246 static_assert(std::is_convertible<T, Track>(),
"Wrong track type");
254 mAllowAltPreference =
true;
266 std::array<std::array<Vec3D, N>, N> mDResidDz;
268 std::array<std::array<Vec3D, N>, N> mD2ResidDz2;
272 std::array<const Track*, N> mOrigTrPtr;
273 std::array<TrackAuxPar, N> mTrAux;
274 CrossInfo mCrossings;
276 std::array<ArrTrackCovI, MAXHYP> mTrcEInv;
277 std::array<ArrTrack, MAXHYP> mCandTr;
278 std::array<ArrTrCoef, MAXHYP> mTrCFVT;
279 std::array<ArrTrDer, MAXHYP> mTrDer;
280 std::array<ArrTrPos, MAXHYP> mTrPos;
281 std::array<ArrTrPos, MAXHYP> mTrRes;
282 std::array<Vec3D, MAXHYP> mPCA;
283 std::array<float, MAXHYP> mChi2 = {0};
284 std::array<int, MAXHYP> mNIters;
285 std::array<bool, MAXHYP> mTrPropDone;
287 std::array<int, MAXHYP> mOrder{0};
290 int mCrossIDAlt = -1;
291 bool mAllowAltPreference =
true;
292 bool mUseAbsDCA =
false;
293 bool mPropagateToPCA =
true;
294 bool mUseMatBudget =
false;
295 bool mTGeoFallBackAllowed =
true;
298 float mMaxR2 = 200. * 200.;
299 float mMaxDXIni = 4.;
300 float mMinParamChange = 1e-5;
301 float mMinRelChi2Change = 0.98;
302 float mMaxChi2 = 100;
303 float mMaxDist2ToMergeSeeds = 1.;
310template <
int N,
typename... Args>
311template <
class... Tr>
315 static_assert(
sizeof...(args) == N,
"incorrect number of input tracks");
319 for (
int i = 0;
i < N;
i++) {
320 mTrAux[
i].set(*mOrigTrPtr[
i], mBz);
323 if (!mCrossings.set(mTrAux[0], *mOrigTrPtr[0], mTrAux[1], *mOrigTrPtr[1])) {
327 if (mCrossings.nDCA == MAXHYP) {
328 auto dst2 = (mCrossings.xDCA[0] - mCrossings.xDCA[1]) * (mCrossings.xDCA[0] - mCrossings.xDCA[1]) +
329 (mCrossings.yDCA[0] - mCrossings.yDCA[1]) * (mCrossings.yDCA[0] - mCrossings.yDCA[1]);
331 if (dst2 < mMaxDist2ToMergeSeeds) {
333 mCrossings.xDCA[0] = 0.5 * (mCrossings.xDCA[0] + mCrossings.xDCA[1]);
334 mCrossings.yDCA[0] = 0.5 * (mCrossings.yDCA[0] + mCrossings.yDCA[1]);
339 for (
int ic = 0; ic < mCrossings.nDCA; ic++) {
341 if (mCrossings.xDCA[ic] * mCrossings.xDCA[ic] + mCrossings.yDCA[ic] * mCrossings.yDCA[ic] > mMaxR2) {
346 mCrossIDAlt = (mCrossings.nDCA == 2 && mAllowAltPreference) ? 1 - ic : -1;
347 mNIters[mCurHyp] = 0;
348 mTrPropDone[mCurHyp] =
false;
349 mChi2[mCurHyp] = -1.;
351 findZatXY_mid(mCurHyp);
353 if (mUseAbsDCA ? minimizeChi2NoErr() : minimizeChi2()) {
354 mOrder[mCurHyp] = mCurHyp;
355 if (mPropagateToPCA && !FwdpropagateTracksToVertex(mCurHyp)) {
362 for (
int i = mCurHyp;
i--;) {
363 for (
int j =
i;
j--;) {
364 if (mChi2[mOrder[
i]] < mChi2[mOrder[
j]]) {
365 std::swap(mOrder[
i], mOrder[
j]);
374template <
int N,
typename... Args>
378 if (!FwdcalcInverseWeight()) {
381 for (
int i = N;
i--;) {
382 const auto& tcov = mTrcEInv[mCurHyp][
i];
385 miei[0][0] = tcov.sxx;
386 miei[0][1] = tcov.sxy;
387 miei[1][0] = tcov.sxy;
388 miei[1][1] = tcov.syy;
389 miei[2][2] = tcov.szz;
391 mTrCFVT[mCurHyp][
i] = mWeightInv * miei;
397template <
int N,
typename... Args>
401 auto* arrmat = mWeightInv.Array();
402 memset(arrmat, 0,
sizeof(mWeightInv));
409 for (
int i = N;
i--;) {
410 const auto& tcov = mTrcEInv[mCurHyp][
i];
411 arrmat[XX] += tcov.sxx;
412 arrmat[XY] += tcov.sxy;
414 arrmat[YY] += tcov.syy;
416 arrmat[ZZ] += tcov.szz;
420 return mWeightInv.Invert();
424template <
int N,
typename... Args>
429 for (
int i = N;
i--;) {
431 for (
int j = N;
j--;) {
432 const auto& matT = mTrCFVT[mCurHyp][
j];
433 const auto& trDz = mTrDer[mCurHyp][
j];
434 auto& dr1 = mDResidDz[
i][
j];
435 auto& dr2 = mD2ResidDz2[
i][
j];
437 matMT[0][0] = matT[0][0];
438 matMT[0][1] = matT[0][1];
439 matMT[0][2] = matT[0][2];
440 matMT[1][0] = matT[1][0];
441 matMT[1][1] = matT[1][1];
442 matMT[1][2] = matT[1][2];
443 matMT[2][0] = matT[2][0];
444 matMT[2][1] = matT[2][1];
445 matMT[2][2] = matT[2][2];
448 dr1[0] = -(matMT[0][0] * trDz.dxdz + matMT[0][1] * trDz.dydz + matMT[0][2]);
449 dr1[1] = -(matMT[1][0] * trDz.dxdz + matMT[1][1] * trDz.dydz + matMT[1][2]);
450 dr1[2] = -(matMT[2][0] * trDz.dxdz + matMT[2][1] * trDz.dydz + matMT[2][2]);
453 dr2[0] = -(matMT[0][1] * trDz.d2ydz2 + matMT[0][0] * trDz.d2xdz2);
454 dr2[1] = -(matMT[1][1] * trDz.d2ydz2 + matMT[1][0] * trDz.d2xdz2);
455 dr2[2] = -(matMT[2][1] * trDz.d2ydz2 + matMT[2][0] * trDz.d2xdz2);
462 dr2[0] += trDz.d2xdz2;
463 dr2[1] += trDz.d2ydz2;
470template <
int N,
typename... Args>
474 constexpr double NInv1 = 1. - NInv;
475 for (
int i = N;
i--;) {
476 const auto& trDzi = mTrDer[mCurHyp][
i];
477 auto& dr1ii = mDResidDz[
i][
i];
478 auto& dr2ii = mD2ResidDz2[
i][
i];
480 dr1ii[0] = NInv1 * trDzi.dxdz;
481 dr1ii[1] = NInv1 * trDzi.dydz;
484 dr2ii[0] = NInv1 * trDzi.d2xdz2;
485 dr2ii[1] = NInv1 * trDzi.d2ydz2;
488 for (
int j =
i;
j--;) {
489 auto& dr1ij = mDResidDz[
i][
j];
490 auto& dr1ji = mDResidDz[
j][
i];
491 const auto& trDzj = mTrDer[mCurHyp][
j];
494 dr1ij[0] = -trDzj.dxdz * NInv;
495 dr1ij[1] = -trDzj.dydz * NInv;
496 dr1ij[2] = -1 * NInv;
499 dr1ji[0] = -trDzi.dxdz * NInv;
500 dr1ji[1] = -trDzi.dydz * NInv;
501 dr1ji[2] = -1 * NInv;
503 auto& dr2ij = mD2ResidDz2[
i][
j];
504 auto& dr2ji = mD2ResidDz2[
j][
i];
507 dr2ij[0] = -trDzj.d2xdz2 * NInv;
508 dr2ij[1] = -trDzj.d2ydz2 * NInv;
512 dr2ji[0] = -trDzi.d2xdz2 * NInv;
513 dr2ji[1] = -trDzi.d2ydz2 * NInv;
521template <
int N,
typename... Args>
525 std::array<std::array<Vec3D, N>, N> covIDrDz;
528 for (
int i = N;
i--;) {
529 auto& dchi1 = mDChi2Dz[
i];
531 for (
int j = N;
j--;) {
532 const auto&
res = mTrRes[mCurHyp][
j];
533 const auto& covI = mTrcEInv[mCurHyp][
j];
534 const auto& dr1 = mDResidDz[
j][
i];
535 auto& cidr = covIDrDz[
i][
j];
536 cidr[0] = covI.sxx * dr1[0] + covI.sxy * dr1[1];
537 cidr[1] = covI.sxy * dr1[0] + covI.syy * dr1[1];
538 cidr[2] = covI.szz * dr1[2];
540 dchi1 += ROOT::Math::Dot(
res, cidr);
545 for (
int i = N;
i--;) {
546 for (
int j =
i + 1;
j--;) {
547 auto& dchi2 = mD2Chi2Dz2[
i][
j];
549 for (
int k = N; k--;) {
550 const auto& dr1j = mDResidDz[k][
j];
551 const auto& cidrkj = covIDrDz[
i][k];
552 dchi2 += ROOT::Math::Dot(dr1j, cidrkj);
554 const auto&
res = mTrRes[mCurHyp][k];
555 const auto& covI = mTrcEInv[mCurHyp][k];
556 const auto& dr2ij = mD2ResidDz2[k][
j];
557 dchi2 +=
res[0] * (covI.sxx * dr2ij[0] + covI.sxy * dr2ij[1]) +
res[1] * (covI.sxy * dr2ij[0] + covI.syy * dr2ij[1]) +
res[2] * covI.szz * dr2ij[2];
565template <
int N,
typename... Args>
569 for (
int i = N;
i--;) {
570 auto& dchi1 = mDChi2Dz[
i];
572 for (
int j = N;
j--;) {
573 const auto&
res = mTrRes[mCurHyp][
j];
574 const auto& dr1 = mDResidDz[
j][
i];
575 dchi1 += ROOT::Math::Dot(
res, dr1);
578 auto& dchi2 = mD2Chi2Dz2[
i][
j];
579 dchi2 = ROOT::Math::Dot(mTrRes[mCurHyp][
i], mD2ResidDz2[
i][
j]);
580 for (
int k = N; k--;) {
581 dchi2 += ROOT::Math::Dot(mDResidDz[k][
i], mDResidDz[k][
j]);
589template <
int N,
typename... Args>
594 mPCA[mCurHyp] = mTrCFVT[mCurHyp][N - 1] * mTrPos[mCurHyp][N - 1];
595 for (
int i = N - 1;
i--;) {
596 mPCA[mCurHyp] += mTrCFVT[mCurHyp][
i] * mTrPos[mCurHyp][
i];
601template <
int N,
typename... Args>
605 auto& pca = mPCA[mCurHyp];
607 pca[0] = mTrPos[mCurHyp][N - 1][0];
608 pca[1] = mTrPos[mCurHyp][N - 1][1];
609 pca[2] = mTrPos[mCurHyp][N - 1][2];
611 for (
int i = N - 1;
i--;) {
612 pca[0] += mTrPos[mCurHyp][
i][0];
613 pca[1] += mTrPos[mCurHyp][
i][1];
614 pca[2] += mTrPos[mCurHyp][
i][2];
622template <
int N,
typename... Args>
627 for (
int i = N;
i--;) {
628 covm += ROOT::Math::Similarity(mUseAbsDCA ? getTrackRotMatrix(
i) : mTrCFVT[mOrder[cand]][
i], getTrackCovMatrix(
i, cand));
634template <
int N,
typename... Args>
639 for (
int i = N;
i--;) {
640 mTrRes[mCurHyp][
i] = mTrPos[mCurHyp][
i];
641 vtxLoc = mPCA[mCurHyp];
642 mTrRes[mCurHyp][
i] -= vtxLoc;
647template <
int N,
typename... Args>
651 for (
int i = N;
i--;) {
652 mTrDer[mCurHyp][
i].set(mCandTr[mCurHyp][
i], mBz);
657template <
int N,
typename... Args>
662 for (
int i = N;
i--;) {
663 const auto&
res = mTrRes[mCurHyp][
i];
664 const auto& covI = mTrcEInv[mCurHyp][
i];
665 chi2 +=
res[0] *
res[0] * covI.sxx +
res[1] *
res[1] * covI.syy +
res[2] *
res[2] * covI.szz + 2. *
res[0] *
res[1] * covI.sxy;
671template <
int N,
typename... Args>
676 for (
int i = N;
i--;) {
677 const auto&
res = mTrRes[mCurHyp][
i];
684template <
int N,
typename... Args>
688 for (
int i = N;
i--;) {
689 const auto& trDer = mTrDer[mCurHyp][
i];
690 auto dz2h = 0.5 * corrZ[
i] * corrZ[
i];
691 mTrPos[mCurHyp][
i][0] -= trDer.dxdz * corrZ[
i] - dz2h * trDer.d2xdz2;
692 mTrPos[mCurHyp][
i][1] -= trDer.dydz * corrZ[
i] - dz2h * trDer.d2ydz2;
693 mTrPos[mCurHyp][
i][2] -= corrZ[
i];
700template <
int N,
typename... Args>
704 int ord = mOrder[icand];
705 if (mTrPropDone[ord]) {
708 const Vec3D& pca = mPCA[ord];
709 std::array<float, 6> covMatrixPCA = calcPCACovMatrixFlat(ord);
710 std::array<float, 2> cov = {covMatrixPCA[0], covMatrixPCA[2]};
711 for (
int i = N;
i--;) {
712 mCandTr[ord][
i] = *mOrigTrPtr[
i];
713 auto& trc = mCandTr[ord][
i];
714 const std::array<float, 3> p = {(float)pca[0], (
float)pca[1], (float)pca[2]};
715 if (!propagateToVtx(trc, p, cov)) {
720 mTrPropDone[ord] =
true;
725template <
int N,
typename... Args>
730 double startPoint = 20.;
732 double z[2] = {startPoint, startPoint};
733 double newX[2], newY[2];
735 double X = mPCA[mCurHyp][0];
736 double Y = mPCA[mCurHyp][1];
738 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
739 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
741 double dstXY[2][3] = {{999., 999., 999.}, {999., 999., 999.}};
748 for (
int i = 0;
i < 2;
i++) {
752 mCandTr[mCurHyp][
i].propagateParamToZquadratic(
z[
i], mBz);
753 newX[
i] = mCandTr[mCurHyp][
i].getX();
754 newY[
i] = mCandTr[mCurHyp][
i].getY();
756 newDstXY = std::sqrt((newX[
i] - X) * (newX[
i] - X) +
757 (newY[
i] - Y) * (newY[
i] - Y));
760 dstXY[
i][0] = dstXY[
i][1];
761 dstXY[
i][1] = dstXY[
i][2];
762 dstXY[
i][2] = newDstXY;
764 if (dstXY[
i][2] > dstXY[
i][1] && dstXY[
i][1] < dstXY[
i][0]) {
765 finalZ[
i] =
z[
i] + step;
773 float rez = 0.5 * (finalZ[0] + finalZ[1]);
778template <
int N,
typename... Args>
783 double startPoint = -40.;
784 double endPoint = 50.;
785 double midPoint = 0.5 * (startPoint + endPoint);
787 double z[2][2] = {{startPoint, endPoint}, {startPoint, endPoint}};
789 double DeltaZ = std::abs(endPoint - startPoint);
794 double epsilon = 0.0001;
796 double X = mPCA[mCurHyp][0];
797 double Y = mPCA[mCurHyp][1];
799 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
800 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
806 while (DeltaZ > epsilon) {
808 midPoint = 0.5 * (startPoint + endPoint);
810 for (
int i = 0;
i < 2;
i++) {
811 mCandTr[mCurHyp][
i].propagateParamToZquadratic(startPoint, mBz);
812 newX[
i][0] = mCandTr[mCurHyp][
i].getX();
813 newY[
i][0] = mCandTr[mCurHyp][
i].getY();
815 mCandTr[mCurHyp][
i].propagateParamToZquadratic(endPoint, mBz);
816 newX[
i][1] = mCandTr[mCurHyp][
i].getX();
817 newY[
i][1] = mCandTr[mCurHyp][
i].getY();
820 dstXY[0] = (newX[0][0] - newX[1][0]) * (newX[0][0] - newX[1][0]) +
821 (newY[0][0] - newY[1][0]) * (newY[0][0] - newY[1][0]);
823 dstXY[1] = (newX[0][1] - newX[1][1]) * (newX[0][1] - newX[1][1]) +
824 (newY[0][1] - newY[1][1]) * (newY[0][1] - newY[1][1]);
826 DeltaZ = std::abs(endPoint - startPoint);
828 if (DeltaZ < epsilon) {
829 finalZ = 0.5 * (startPoint + endPoint);
834 if (dstXY[1] > dstXY[0]) {
837 startPoint = midPoint;
841 mPCA[mCurHyp][2] = finalZ;
845template <
int N,
typename... Args>
850 double startPoint = 1.;
851 double endPoint = 50.;
853 double X = mPCA[mCurHyp][0];
854 double Y = mPCA[mCurHyp][1];
856 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
857 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
872 for (
int i = 0;
i < 2;
i++) {
874 mCandTr[mCurHyp][
i].propagateToZquadratic(startPoint, mBz);
876 z[
i][0] = startPoint;
877 y[
i][0] = mCandTr[mCurHyp][
i].getY();
878 x[
i][0] = mCandTr[mCurHyp][
i].getX();
880 mCandTr[mCurHyp][
i].propagateToZquadratic(endPoint, mBz);
883 y[
i][1] = mCandTr[mCurHyp][
i].getY();
884 x[
i][1] = mCandTr[mCurHyp][
i].getX();
886 bYZ[
i] = (
y[
i][1] -
y[
i][0] *
z[
i][1] /
z[
i][0]) / (1 -
z[
i][1] /
z[
i][0]);
887 aYZ[
i] = (
y[
i][0] - bYZ[
i]) /
z[
i][0];
889 bXZ[
i] = (
x[
i][1] -
x[
i][0] *
z[
i][1] /
z[
i][0]) / (1 -
z[
i][1] /
z[
i][0]);
890 aXZ[
i] = (
x[
i][0] - bXZ[
i]) /
z[
i][0];
894 finalZ = 0.5 * ((bYZ[0] - bYZ[1]) / (aYZ[1] - aYZ[0]) + (bXZ[0] - bXZ[1]) / (aXZ[1] - aXZ[0]));
896 mPCA[mCurHyp][2] = finalZ;
900template <
int N,
typename... Args>
903 double startPoint = 0.;
904 double endPoint = 40.;
906 double X = mPCA[mCurHyp][0];
907 double Y = mPCA[mCurHyp][1];
909 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
910 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
922 double Ax[2], Bx[2], Cx[2];
923 double Ay[2], By[2], Cy[2];
925 double deltaX[2], deltaY[2];
927 bool posX[2], nulX[2], negX[2];
928 double z1X[2], z2X[2], z12X[2];
930 bool posY[2], nulY[2], negY[2];
931 double z1Y[2], z2Y[2], z12Y[2];
939 for (
int i = 0;
i < 2;
i++) {
940 mCandTr[mCurHyp][
i].propagateToZquadratic(startPoint, mBz);
941 x[
i] = mCandTr[mCurHyp][
i].getX();
942 y[
i] = mCandTr[mCurHyp][
i].getY();
943 sinPhi0[
i] = mCandTr[mCurHyp][
i].getSnp();
944 cosPhi0[
i] = std::sqrt((1. - sinPhi0[
i]) * (1. + sinPhi0[
i]));
945 tanL0[
i] = mCandTr[mCurHyp][
i].getTanl();
946 qpt0[
i] = mCandTr[mCurHyp][
i].getInvQPt();
950 Ax[
i] = qpt0[
i] * Hz[
i] * k[
i] * sinPhi0[
i] / (2 * tanL0[
i] * tanL0[
i]);
951 Bx[
i] = cosPhi0[
i] / tanL0[
i];
954 Ay[
i] = -qpt0[
i] * Hz[
i] * k[
i] * cosPhi0[
i] / (2 * tanL0[
i] * tanL0[
i]);
955 By[
i] = sinPhi0[
i] / tanL0[
i];
958 deltaX[
i] = Bx[
i] * Bx[
i] - 4 * Ax[
i] * Cx[
i];
959 deltaY[
i] = By[
i] * By[
i] - 4 * Ay[
i] * Cy[
i];
963 z1X[
i] = (-Bx[
i] - std::sqrt(deltaX[
i])) / (2 * Ax[
i]);
964 z2X[
i] = (-Bx[
i] + std::sqrt(deltaX[
i])) / (2 * Ax[
i]);
965 }
else if (deltaX[
i] == 0) {
967 z12X[
i] = -Bx[
i] / (2 * Ax[
i]);
975 z1Y[
i] = (-By[
i] - std::sqrt(deltaY[
i])) / (2 * Ay[
i]);
976 z2Y[
i] = (-By[
i] + std::sqrt(deltaY[
i])) / (2 * Ay[
i]);
977 }
else if (deltaX[
i] == 0) {
979 z12Y[
i] = -By[
i] / (2 * Ay[
i]);
987 if (z1X[
i] < endPoint && z1X[
i] > startPoint) {
995 if (z1Y[
i] < endPoint && z1Y[
i] > startPoint) {
1002 finalZ[
i] = 0.5 * (z12X[
i] + z12Y[
i]);
1005 mPCA[mCurHyp][2] = 0.5 * (finalZ[0] + finalZ[1]);
1009template <
int N,
typename... Args>
1013 double startPoint = 0.;
1015 double X = mPCA[mCurHyp][0];
1016 double Y = mPCA[mCurHyp][1];
1018 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
1019 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
1027 double Ax[2], Bx[2];
1028 double Ay[2], By[2];
1039 for (
int i = 0;
i < 2;
i++) {
1040 mCandTr[mCurHyp][
i].propagateToZlinear(startPoint);
1041 x[
i] = mCandTr[mCurHyp][
i].getX();
1042 y[
i] = mCandTr[mCurHyp][
i].getY();
1043 sinPhi0[
i] = mCandTr[mCurHyp][
i].getSnp();
1044 cosPhi0[
i] = std::sqrt((1. - sinPhi0[
i]) * (1. + sinPhi0[
i]));
1045 tanL0[
i] = mCandTr[mCurHyp][
i].getTanl();
1047 Ax[
i] = cosPhi0[
i] / tanL0[
i];
1050 Ay[
i] = sinPhi0[
i] / tanL0[
i];
1053 z12X[
i] = -Bx[
i] / Ax[
i];
1054 z12Y[
i] = -By[
i] / Ay[
i];
1056 finalZ[
i] = 0.5 * (z12X[
i] + z12Y[
i]);
1059 mPCA[mCurHyp][2] = 0.5 * (finalZ[0] + finalZ[1]);
1063template <
int N,
typename... Args>
1067 int ord = mOrder[icand];
1069 if (!mTrPropDone[ord]) {
1070 auto z = mPCA[ord][2];
1078template <
int N,
typename... Args>
1082 for (
int i = N;
i--;) {
1083 auto vai = std::abs(
v[
i]);
1092template <
int N,
typename... Args>
1100 for (
int i = N;
i--;) {
1101 mCandTr[mCurHyp][
i] = *mOrigTrPtr[
i];
1102 auto z = mPCA[mCurHyp][2];
1104 mCandTr[mCurHyp][
i].propagateToZquadratic(
z, mBz);
1106 x[
i] = mCandTr[mCurHyp][
i].getX();
1107 y[
i] = mCandTr[mCurHyp][
i].getY();
1109 setTrackPos(mTrPos[mCurHyp][
i], mCandTr[mCurHyp][
i]);
1110 mTrcEInv[mCurHyp][
i].set(mCandTr[mCurHyp][
i], ZerrFactor);
1116 mPCA[mCurHyp][0] = sumX / N;
1117 mPCA[mCurHyp][1] = sumY / N;
1119 if (mMaxDXIni > 0 && !roughDXCut()) {
1123 if (!FwdcalcPCACoefs()) {
1127 FwdcalcTrackResiduals();
1128 float chi2Upd, chi2 = FwdcalcChi2();
1130 calcTrackDerivatives();
1131 FwdcalcResidDerivatives();
1132 FwdcalcChi2Derivatives();
1135 if (!mD2Chi2Dz2.Invert()) {
1139 VecND dz = mD2Chi2Dz2 * mDChi2Dz;
1141 if (!FwdcorrectTracks(dz)) {
1146 if (mCrossIDAlt >= 0 && closerToAlternative()) {
1147 mAllowAltPreference =
false;
1151 FwdcalcTrackResiduals();
1152 chi2Upd = FwdcalcChi2();
1154 if (getAbsMax(dz) < mMinParamChange || chi2Upd > chi2 * mMinRelChi2Change) {
1160 }
while (++mNIters[mCurHyp] < mMaxIter);
1162 mChi2[mCurHyp] = chi2 * NInv;
1163 return mChi2[mCurHyp] < mMaxChi2;
1167template <
int N,
typename... Args>
1175 for (
int i = N;
i--;) {
1177 mCandTr[mCurHyp][
i] = *mOrigTrPtr[
i];
1179 auto z = mPCA[mCurHyp][2];
1180 mCandTr[mCurHyp][
i].propagateParamToZquadratic(
z, mBz);
1182 x[
i] = mCandTr[mCurHyp][
i].getX();
1183 y[
i] = mCandTr[mCurHyp][
i].getY();
1185 mPCA[mCurHyp][2] =
z;
1187 setTrackPos(mTrPos[mCurHyp][
i], mCandTr[mCurHyp][
i]);
1193 mPCA[mCurHyp][0] = sumX / N;
1194 mPCA[mCurHyp][1] = sumY / N;
1196 if (mMaxDXIni > 0 && !roughDXCut()) {
1201 FwdcalcTrackResiduals();
1202 float chi2Upd, chi2 = FwdcalcChi2NoErr();
1204 calcTrackDerivatives();
1205 FwdcalcResidDerivativesNoErr();
1206 FwdcalcChi2DerivativesNoErr();
1209 if (!mD2Chi2Dz2.Invert()) {
1212 VecND dz = mD2Chi2Dz2 * mDChi2Dz;
1214 if (!FwdcorrectTracks(dz)) {
1218 if (mCrossIDAlt >= 0 && closerToAlternative()) {
1219 mAllowAltPreference =
false;
1222 FwdcalcTrackResiduals();
1223 chi2Upd = FwdcalcChi2NoErr();
1224 if (getAbsMax(dz) < mMinParamChange || chi2Upd > chi2 * mMinRelChi2Change) {
1229 }
while (++mNIters[mCurHyp] < mMaxIter);
1231 mChi2[mCurHyp] = chi2 * NInv;
1232 return mChi2[mCurHyp] < mMaxChi2;
1236template <
int N,
typename... Args>
1242 for (
int i = N; accept &&
i--;) {
1243 for (
int j =
i;
j--;) {
1244 if (std::abs(mCandTr[mCurHyp][
i].getX() - mCandTr[mCurHyp][
j].getX()) > mMaxDXIni) {
1254template <
int N,
typename... Args>
1258 auto dxCur = mPCA[mCurHyp][0] - mCrossings.xDCA[mCrossIDCur], dyCur = mPCA[mCurHyp][1] - mCrossings.yDCA[mCrossIDCur];
1259 auto dxAlt = mPCA[mCurHyp][0] - mCrossings.xDCA[mCrossIDAlt], dyAlt = mPCA[mCurHyp][1] - mCrossings.yDCA[mCrossIDAlt];
1260 return dxCur * dxCur + dyCur * dyCur > dxAlt * dxAlt + dyAlt * dyAlt;
1264template <
int N,
typename... Args>
1267 LOG(info) << N <<
"-prong vertex fitter in " << (mUseAbsDCA ?
"abs." :
"weighted") <<
" distance minimization mode";
1268 LOG(info) <<
"Bz: " << mBz <<
" MaxIter: " << mMaxIter <<
" MaxChi2: " << mMaxChi2;
1269 LOG(info) <<
"Stopping condition: Max.param change < " << mMinParamChange <<
" Rel.Chi2 change > " << mMinRelChi2Change;
1270 LOG(info) <<
"Discard candidates for : Rvtx > " << getMaxR() <<
" DZ between tracks > " << mMaxDXIni;
1273template <
int N,
typename... Args>
1278 if (mUseMatBudget) {
1279 auto mb = mMatLUT->getMatBudget(t.
getX(), t.
getY(), t.
getZ(), p[0], p[1], p[2]);
1280 x2x0 = (float)mb.meanX2X0;
1282 }
else if (mTGeoFallBackAllowed) {
1284 x2x0 = (float)geoMan.meanX2X0;
Helper classes for helical tracks manipulations.
Definition of the GeometryManager class.
Base forward track model, params only, w/o covariance.
static o2::base::MatBudget meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1)
bool propagateToVtxhelixWithMCS(double z, const std::array< float, 2 > &p, const std::array< float, 2 > &cov, double field, double x_over_X0)
Double_t getSigma2Y() const
void propagateToZhelix(double zEnd, double zField)
Double_t getSigmaXY() const
Double_t getSigma2X() const
void propagateParamToZquadratic(double zEnd, double zField)
Double_t getZ() const
return Z coordinate (cm)
Double_t getCurvature(double b) const
Double_t getCharge() const
return the charge (assumed forward motion)
void FwdcalcChi2Derivatives()
MatStd3D getTrackRotMatrix(int i) const
void setMinParamChange(float x=1e-3)
void FwdcalcTrackResiduals()
float getChi2AtPCACandidate(int cand=0) const
int process(const Tr &... args)
void findZatXY_mid(int cand=0)
void setMinRelChi2Change(float r=0.9)
FwdDCAFitterN(float bz, bool useAbsDCA, bool prop2DCA)
bool isPropagateTracksToVertexDone(int cand=0) const
void setUseAbsDCA(bool v)
void setPropagateToPCA(bool v=true)
int getNIterations(int cand=0) const
void findZatXY_linear(int cand=0)
void FwdcalcResidDerivativesNoErr()
bool propagateToVtx(o2::track::TrackParCovFwd &t, const std::array< float, 3 > &p, const std::array< float, 2 > &cov) const
track param positions at V0 candidate (no check for the candidate validity)
const Vec3D & getTrackPos(int i, int cand=0) const
track Z-param at V0 candidate (no check for the candidate validity)
bool closerToAlternative() const
void assign(int i, const T &t, const Tr &... args)
std::array< float, 6 > calcPCACovMatrixFlat(int cand=0) const
float findZatXY(int cand=0)
void setMatLUT(const o2::base::MatLayerCylSet *m)
void setMaxDXIni(float d=4.)
void FwdcalcResidDerivatives()
void findZatXY_lineApprox(int cand=0)
int getNCandidates() const
void calcTrackDerivatives()
static constexpr int getNProngs()
void setMaxIter(int n=60)
float getMinParamChange() const
float getMaxDistance2ToMerge() const
double getK(double b) const
double getHz(double b) const
void FwdcalcChi2DerivativesNoErr()
float getTrackZ(int i, int cand=0) const
const Track * getOrigTrackPtr(int i) const
return number of iterations during minimization (no check for its validity)
double FwdcalcChi2() const
double FwdcalcChi2NoErr() const
const auto getPCACandidatePos(int cand=0) const
return Chi2 at PCA candidate (no check for its validity)
bool getUseAbsDCA() const
void setMaxR(float r=200.)
static double getAbsMax(const VecND &v)
bool getPropagateToPCA() const
void setMaxChi2(float chi2=999.)
static void setTrackPos(Vec3D &pnt, const Track &tr)
const Vec3D & getPCACandidate(int cand=0) const
< return PCA candidate, by default best on is provided (no check for the index validity)
void findZatXY_quad(int cand=0)
Track & getTrack(int i, int cand=0)
calculate on the fly track param (no cov mat) at candidate
MatSym3D getTrackCovMatrix(int i, int cand=0) const
void setTGeoMat(bool v=true)
bool FwdcorrectTracks(const VecND &corrZ)
bool FwdpropagateTracksToVertex(int cand=0)
check if propagation of tracks to candidate vertex was done
bool FwdcalcInverseWeight()
o2::track::TrackParFwd FwdgetTrackParamAtPCA(int i, int cand=0) const
float getMaxDXIni() const
MatSym3D calcPCACovMatrix(int cand=0) const
void setMaxDistance2ToMerge(float v)
GLboolean GLboolean GLboolean b
GLdouble GLdouble GLdouble z
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
void set(const o2::track::TrackParCovFwd &trc, float zerrFactor=1)
FwdTrackCovI(const o2::track::TrackParCovFwd &trc, float zerrFactor=1.)
void set(const o2::track::TrackParFwd &trc, float bz)
FwdTrackDeriv(const o2::track::TrackParFwd &trc, float bz)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"