Project
Loading...
Searching...
No Matches
FwdDCAFitterN.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
17#ifndef _ALICEO2_DCA_FWDFITTERN_
18#define _ALICEO2_DCA_FWDFITTERN_
19#include <TMath.h>
20#include "MathUtils/Cartesian.h"
24#include <TRandom.h>
27
28namespace o2
29{
30namespace vertexing
31{
32
36 float sxx, syy, sxy, szz;
37
38 FwdTrackCovI(const o2::track::TrackParCovFwd& trc, float zerrFactor = 1.) { set(trc, zerrFactor); }
39 FwdTrackCovI() = default;
40 void set(const o2::track::TrackParCovFwd& trc, float zerrFactor = 1)
41 {
42 float cxx = trc.getSigma2X(), cyy = trc.getSigma2Y(), cxy = trc.getSigmaXY(), czz = cyy * zerrFactor;
43 float detXY = cxx * cyy - cxy * cxy;
44 if (detXY > 0.) {
45 auto detXYI = 1. / detXY;
46 sxx = cyy * detXYI;
47 syy = cxx * detXYI;
48 sxy = -cxy * detXYI;
49 szz = 1. / czz;
50 } else {
51 throw std::runtime_error("invalid track covariance");
52 }
53 }
54};
55
60 FwdTrackDeriv() = default;
61 FwdTrackDeriv(const o2::track::TrackParFwd& trc, float bz) { set(trc, bz); }
62 void set(const o2::track::TrackParFwd& trc, float bz)
63 {
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;
65 if (crv2c == 0.) {
66 crv2c = (trc.getCharge()) * 0.3 * bz * (-1e-3);
67 }
68
69 dxdz = csp * tglI;
70 dydz = snp * tglI;
71 d2xdz2 = crv2c * snp * tglI * tglI;
72 d2ydz2 = -crv2c * csp * tglI * tglI;
73 }
74};
75
76template <int N, typename... Args>
78{
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.; // factor for conversion of track covXX to dummy covZZ
94 using TrackCoefVtx = MatStd3D;
95 using ArrTrack = std::array<Track, N>; // container for prongs (tracks) at single vertex cand.
96 using ArrTrackCovI = std::array<FwdTrackCovI, N>; // container for inv.cov.matrices at single vertex cand.
97 using ArrTrCoef = std::array<TrackCoefVtx, N>; // container of TrackCoefVtx coefficients at single vertex cand.
98 using ArrTrDer = std::array<FwdTrackDeriv, N>; // container of Track 1st and 2nd derivative over their Z param
99 using ArrTrPos = std::array<Vec3D, N>; // container of Track positions
100
101 public:
102 static constexpr int getNProngs() { return N; }
103
104 FwdDCAFitterN() = default;
105 FwdDCAFitterN(float bz, bool useAbsDCA, bool prop2DCA) : mBz(bz), mUseAbsDCA(useAbsDCA), mPropagateToPCA(prop2DCA)
106 {
107 static_assert(N >= NMin && N <= NMax, "N prongs outside of allowed range");
108 }
109
110 //=========================================================================
112 const Vec3D& getPCACandidate(int cand = 0) const { return mPCA[mOrder[cand]]; }
113 const auto getPCACandidatePos(int cand = 0) const
114 {
115 const auto& vd = mPCA[mOrder[cand]];
116 return std::array<float, 3>{float(vd[0]), float(vd[1]), float(vd[2])};
117 }
118
120 float getChi2AtPCACandidate(int cand = 0) const { return mChi2[mOrder[cand]]; }
121
124 bool FwdpropagateTracksToVertex(int cand = 0);
125
127 bool isPropagateTracksToVertexDone(int cand = 0) const { return mTrPropDone[mOrder[cand]]; }
128
131 Track& getTrack(int i, int cand = 0)
132 {
133 if (!mTrPropDone[mOrder[cand]]) {
134 throw std::runtime_error("propagateTracksToVertex was not called yet");
135 }
136 return mCandTr[mOrder[cand]][i];
137 }
138
140 o2::track::TrackParFwd FwdgetTrackParamAtPCA(int i, int cand = 0) const;
141
142 MatSym3D calcPCACovMatrix(int cand = 0) const;
143
144 std::array<float, 6> calcPCACovMatrixFlat(int cand = 0) const
145 {
146 auto m = calcPCACovMatrix(cand);
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))};
148 }
149
150 const Track* getOrigTrackPtr(int i) const { return mOrigTrPtr[i]; }
151
153 int getNIterations(int cand = 0) const { return mNIters[mOrder[cand]]; }
154 void setPropagateToPCA(bool v = true) { mPropagateToPCA = v; }
155 void setMaxIter(int n = 60) { mMaxIter = n > 2 ? n : 2; }
156 void setMaxR(float r = 200.) { mMaxR2 = r * r; }
157 void setMaxDXIni(float d = 4.) { mMaxDXIni = d; }
158 void setMaxChi2(float chi2 = 999.) { mMaxChi2 = chi2; }
159 void setBz(float bz) { mBz = std::abs(bz) > o2::constants::math::Almost0 ? bz : 0.f; }
160 void setMinParamChange(float x = 1e-3) { mMinParamChange = x > 1e-4 ? x : 1.e-4; }
161 void setMinRelChi2Change(float r = 0.9) { mMinRelChi2Change = r > 0.1 ? r : 999.; }
162 void setUseAbsDCA(bool v) { mUseAbsDCA = v; }
164 {
165 mMatLUT = m;
166 mUseMatBudget = true;
167 }
168 void setTGeoMat(bool v = true) { mTGeoFallBackAllowed = v; }
169 void setMaxDistance2ToMerge(float v) { mMaxDist2ToMergeSeeds = v; }
170
171 int getNCandidates() const { return mCurHyp; }
172 int getMaxIter() const { return mMaxIter; }
173 float getMaxR() const { return std::sqrt(mMaxR2); }
174 float getMaxDXIni() const { return mMaxDXIni; }
175 float getMaxChi2() const { return mMaxChi2; }
176 float getMinParamChange() const { return mMinParamChange; }
177 float getBz() const { return mBz; }
178 double getK(double b) const { return std::abs(o2::constants::math::B2C * b); }
179 double getHz(double b) const { return std::copysign(1, b); }
180
181 float getMaxDistance2ToMerge() const { return mMaxDist2ToMergeSeeds; }
182 bool getUseAbsDCA() const { return mUseAbsDCA; }
183 bool getPropagateToPCA() const { return mPropagateToPCA; }
184
185 template <class... Tr>
186 int process(const Tr&... args);
187 void print() const;
188
189 protected:
190 bool FwdcalcPCACoefs();
196 void FwdcalcPCA();
197 void FwdcalcPCANoErr();
200 float findZatXY(int cand = 0);
201 void findZatXY_mid(int cand = 0);
202 void findZatXY_lineApprox(int cand = 0);
203 void findZatXY_quad(int cand = 0);
204 void findZatXY_linear(int cand = 0);
205 double FwdcalcChi2() const;
206 double FwdcalcChi2NoErr() const;
207 bool FwdcorrectTracks(const VecND& corrZ);
208 bool minimizeChi2();
209 bool minimizeChi2NoErr();
210 bool roughDXCut() const;
211 bool closerToAlternative() const;
212 static double getAbsMax(const VecND& v);
213 bool propagateToVtx(o2::track::TrackParCovFwd& t, const std::array<float, 3>& p, const std::array<float, 2>& cov) const;
214
216 const Vec3D& getTrackPos(int i, int cand = 0) const { return mTrPos[mOrder[cand]][i]; }
217
219 float getTrackZ(int i, int cand = 0) const { return getTrackPos(i, cand)[2]; }
220
221 MatStd3D getTrackRotMatrix(int i) const // generate 3D matrix for track rotation to global frame
222 // no rotation for fwd: mat=I
223 {
224 MatStd3D mat;
225 mat(0, 0) = 1;
226 mat(1, 1) = 1;
227 mat(2, 2) = 1;
228 return mat;
229 }
230
231 MatSym3D getTrackCovMatrix(int i, int cand = 0) const // generate covariance matrix of track position, adding fake Z error
232 {
233 const auto& trc = mCandTr[mOrder[cand]][i];
234 MatSym3D mat;
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;
239 return mat;
240 }
241
242 void assign(int) {}
243 template <class T, class... Tr>
244 void assign(int i, const T& t, const Tr&... args)
245 {
246 static_assert(std::is_convertible<T, Track>(), "Wrong track type");
247 mOrigTrPtr[i] = &t;
248 assign(i + 1, args...);
249 }
250
251 void clear()
252 {
253 mCurHyp = 0;
254 mAllowAltPreference = true;
255 }
256
257 static void setTrackPos(Vec3D& pnt, const Track& tr)
258 {
259 pnt[0] = tr.getX();
260 pnt[1] = tr.getY();
261 pnt[2] = tr.getZ();
262 }
263
264 private:
265 // vectors of 1st derivatives of track local residuals over Z parameters
266 std::array<std::array<Vec3D, N>, N> mDResidDz;
267 // vectors of 1nd derivatives of track local residuals over Z parameters
268 std::array<std::array<Vec3D, N>, N> mD2ResidDz2;
269 VecND mDChi2Dz; // 1st derivatives of chi2 over tracks Z params
270 MatSymND mD2Chi2Dz2; // 2nd derivatives of chi2 over tracks Z params (symmetric matrix)
271
272 std::array<const Track*, N> mOrigTrPtr;
273 std::array<TrackAuxPar, N> mTrAux; // Aux track info for each track at each cand. vertex
274 CrossInfo mCrossings; // info on track crossing
275
276 std::array<ArrTrackCovI, MAXHYP> mTrcEInv; // errors for each track at each cand. vertex
277 std::array<ArrTrack, MAXHYP> mCandTr; // tracks at each cond. vertex (Note: Errors are at seed XY point)
278 std::array<ArrTrCoef, MAXHYP> mTrCFVT; // TrackCoefVtx for each track at each cand. vertex
279 std::array<ArrTrDer, MAXHYP> mTrDer; // Track derivativse
280 std::array<ArrTrPos, MAXHYP> mTrPos; // Track positions
281 std::array<ArrTrPos, MAXHYP> mTrRes; // Track residuals
282 std::array<Vec3D, MAXHYP> mPCA; // PCA for each vertex candidate
283 std::array<float, MAXHYP> mChi2 = {0}; // Chi2 at PCA candidate
284 std::array<int, MAXHYP> mNIters; // number of iterations for each seed
285 std::array<bool, MAXHYP> mTrPropDone; // Flag that the tracks are fully propagated to PCA
286 MatSym3D mWeightInv; // inverse weight of single track, [sum{M^T E M}]^-1 in EQ.T
287 std::array<int, MAXHYP> mOrder{0};
288 int mCurHyp = 0;
289 int mCrossIDCur = 0;
290 int mCrossIDAlt = -1;
291 bool mAllowAltPreference = true; // if the fit converges to alternative PCA seed, abandon the current one
292 bool mUseAbsDCA = false; // use abs. distance minimization rather than chi2
293 bool mPropagateToPCA = true; // create tracks version propagated to PCA
294 bool mUseMatBudget = false; // include MCS effects in track propagation
295 bool mTGeoFallBackAllowed = true; // use TGeo for precise estimate of mat. budget
296 int mMaxIter = 60; // max number of iterations
297 float mBz = 0; // bz field, to be set by user
298 float mMaxR2 = 200. * 200.; // reject PCA's above this radius
299 float mMaxDXIni = 4.; // reject (if>0) PCA candidate if tracks DZ exceeds threshold
300 float mMinParamChange = 1e-5; // stop iterations if largest change of any X is smaller than this
301 float mMinRelChi2Change = 0.98; // stop iterations is chi2/chi2old > this
302 float mMaxChi2 = 100; // abs cut on chi2 or abs distance
303 float mMaxDist2ToMergeSeeds = 1.; // merge 2 seeds to their average if their distance^2 is below the threshold
304 const o2::base::MatLayerCylSet* mMatLUT = nullptr; // use to compute material budget to include MCS effects
305
306 ClassDefNV(FwdDCAFitterN, 1);
307};
308
310template <int N, typename... Args>
311template <class... Tr>
313{
314
315 static_assert(sizeof...(args) == N, "incorrect number of input tracks");
316 assign(0, args...);
317 clear();
318
319 for (int i = 0; i < N; i++) {
320 mTrAux[i].set(*mOrigTrPtr[i], mBz);
321 }
322
323 if (!mCrossings.set(mTrAux[0], *mOrigTrPtr[0], mTrAux[1], *mOrigTrPtr[1])) { // even for N>2 it should be enough to test just 1 loop
324 return 0; // no crossing
325 }
326
327 if (mCrossings.nDCA == MAXHYP) { // if there are 2 candidates
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]);
330
331 if (dst2 < mMaxDist2ToMergeSeeds) {
332 mCrossings.nDCA = 1;
333 mCrossings.xDCA[0] = 0.5 * (mCrossings.xDCA[0] + mCrossings.xDCA[1]);
334 mCrossings.yDCA[0] = 0.5 * (mCrossings.yDCA[0] + mCrossings.yDCA[1]);
335 }
336 }
337
338 // check all crossings
339 for (int ic = 0; ic < mCrossings.nDCA; ic++) {
340 // check if radius is acceptable
341 if (mCrossings.xDCA[ic] * mCrossings.xDCA[ic] + mCrossings.yDCA[ic] * mCrossings.yDCA[ic] > mMaxR2) {
342 continue;
343 }
344
345 mCrossIDCur = ic;
346 mCrossIDAlt = (mCrossings.nDCA == 2 && mAllowAltPreference) ? 1 - ic : -1; // works for max 2 crossings
347 mNIters[mCurHyp] = 0;
348 mTrPropDone[mCurHyp] = false;
349 mChi2[mCurHyp] = -1.;
350
351 findZatXY_mid(mCurHyp);
352
353 if (mUseAbsDCA ? minimizeChi2NoErr() : minimizeChi2()) {
354 mOrder[mCurHyp] = mCurHyp;
355 if (mPropagateToPCA && !FwdpropagateTracksToVertex(mCurHyp)) {
356 continue;
357 }
358 mCurHyp++;
359 }
360 }
361
362 for (int i = mCurHyp; i--;) { // order in quality
363 for (int j = i; j--;) {
364 if (mChi2[mOrder[i]] < mChi2[mOrder[j]]) {
365 std::swap(mOrder[i], mOrder[j]);
366 }
367 }
368 }
369
370 return mCurHyp;
371}
372
373//__________________________________________________________________________
374template <int N, typename... Args>
376{
377 //< calculate Ti matrices for global vertex decomposition to V = sum_{0<i<N} Ti pi, see EQ.T in the ref
378 if (!FwdcalcInverseWeight()) {
379 return false;
380 }
381 for (int i = N; i--;) { // build Mi*Ei matrix, with Mi = I
382 const auto& tcov = mTrcEInv[mCurHyp][i];
383 MatStd3D miei;
384
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;
390
391 mTrCFVT[mCurHyp][i] = mWeightInv * miei;
392 }
393 return true;
394}
395
396//__________________________________________________________________________
397template <int N, typename... Args>
399{
400 //< calculate [sum_{0<j<N} M_j*E_j*M_j^T]^-1 used for Ti matrices, see EQ.T, with M_i = I
401 auto* arrmat = mWeightInv.Array();
402 memset(arrmat, 0, sizeof(mWeightInv));
403 enum { XX,
404 XY,
405 YY,
406 XZ,
407 YZ,
408 ZZ };
409 for (int i = N; i--;) {
410 const auto& tcov = mTrcEInv[mCurHyp][i];
411 arrmat[XX] += tcov.sxx;
412 arrmat[XY] += tcov.sxy;
413 arrmat[XZ] += 0;
414 arrmat[YY] += tcov.syy;
415 arrmat[YZ] += 0;
416 arrmat[ZZ] += tcov.szz;
417 }
418
419 // invert 3x3 symmetrix matrix
420 return mWeightInv.Invert();
421}
422
423//__________________________________________________________________________
424template <int N, typename... Args>
426{
427 //< calculate matrix of derivatives for weighted chi2: residual i vs parameter Z of track j
428 MatStd3D matMT;
429 for (int i = N; i--;) { // residual being differentiated
430 // const auto& taux = mTrAux[i];
431 for (int j = N; j--;) { // track over which we differentiate
432 const auto& matT = mTrCFVT[mCurHyp][j]; // coefficient matrix for track J
433 const auto& trDz = mTrDer[mCurHyp][j]; // track point derivs over track Z param
434 auto& dr1 = mDResidDz[i][j];
435 auto& dr2 = mD2ResidDz2[i][j];
436 // calculate M_i^transverse * T_j , M_i^transverse=I -> MT=T
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];
446
447 // calculate DResid_i/Dz_j = (delta_ij - M_i^tr * T_j) * DTrack_k/Dz_k
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]);
451
452 // calculate D2Resid_I/(Dz_J Dz_K) = (delta_ijk - M_i^tr * T_j * delta_jk) * D2Track_k/dz_k^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);
456
457 if (i == j) {
458 dr1[0] += trDz.dxdz;
459 dr1[1] += trDz.dydz;
460 dr1[2] += 1.;
461
462 dr2[0] += trDz.d2xdz2;
463 dr2[1] += trDz.d2ydz2;
464 }
465 } // track over which we differentiate
466 } // residual being differentiated
467}
468
469//__________________________________________________________________________
470template <int N, typename... Args>
472{
473 //< calculate matrix of derivatives for absolute distance chi2: residual i vs parameter Z of track j
474 constexpr double NInv1 = 1. - NInv; // profit from Rii = I/Ninv
475 for (int i = N; i--;) { // residual being differentiated
476 const auto& trDzi = mTrDer[mCurHyp][i]; // track point derivs over track Z param
477 auto& dr1ii = mDResidDz[i][i];
478 auto& dr2ii = mD2ResidDz2[i][i];
479
480 dr1ii[0] = NInv1 * trDzi.dxdz;
481 dr1ii[1] = NInv1 * trDzi.dydz;
482 dr1ii[2] = NInv1;
483
484 dr2ii[0] = NInv1 * trDzi.d2xdz2;
485 dr2ii[1] = NInv1 * trDzi.d2ydz2;
486 dr2ii[2] = 0;
487
488 for (int j = i; j--;) { // track over which we differentiate
489 auto& dr1ij = mDResidDz[i][j];
490 auto& dr1ji = mDResidDz[j][i];
491 const auto& trDzj = mTrDer[mCurHyp][j]; // track point derivs over track Z param
492
493 // calculate DResid_i/Dz_j = (delta_ij - R_ij) * DTrack_j/Dz_j for j<i
494 dr1ij[0] = -trDzj.dxdz * NInv;
495 dr1ij[1] = -trDzj.dydz * NInv;
496 dr1ij[2] = -1 * NInv;
497
498 // calculate DResid_j/Dz_i = (delta_ij - R_ji) * DTrack_i/Dz_i for j<i
499 dr1ji[0] = -trDzi.dxdz * NInv;
500 dr1ji[1] = -trDzi.dydz * NInv;
501 dr1ji[2] = -1 * NInv;
502
503 auto& dr2ij = mD2ResidDz2[i][j];
504 auto& dr2ji = mD2ResidDz2[j][i];
505
506 // calculate D2Resid_I/(Dz_J Dz_K) = (delta_ij - Rij) * D2Track_j/dz_j^2 * delta_jk for j<i
507 dr2ij[0] = -trDzj.d2xdz2 * NInv;
508 dr2ij[1] = -trDzj.d2ydz2 * NInv;
509 dr2ij[2] = 0;
510
511 // calculate D2Resid_j/(Dz_i Dz_k) = (delta_ij - Rji) * D2Track_i/dz_i^2 * delta_ik for j<i
512 dr2ji[0] = -trDzi.d2xdz2 * NInv;
513 dr2ji[1] = -trDzi.d2ydz2 * NInv;
514 dr2ji[2] = 0;
515
516 } // track over which we differentiate
517 } // residual being differentiated
518}
519
520//__________________________________________________________________________
521template <int N, typename... Args>
523{
524 //< calculate 1st and 2nd derivatives of wighted DCA (chi2) over track parameters Z
525 std::array<std::array<Vec3D, N>, N> covIDrDz; // tempory vectors of covI_j * dres_j/dz_i
526
527 // chi2 1st derivative
528 for (int i = N; i--;) {
529 auto& dchi1 = mDChi2Dz[i]; // DChi2/Dz_i = sum_j { res_j * covI_j * Dres_j/Dz_i }
530 dchi1 = 0;
531 for (int j = N; j--;) {
532 const auto& res = mTrRes[mCurHyp][j]; // vector of residuals of track j
533 const auto& covI = mTrcEInv[mCurHyp][j]; // inverse cov matrix of track j
534 const auto& dr1 = mDResidDz[j][i]; // vector of j-th residuals 1st derivative over Z param of track i
535 auto& cidr = covIDrDz[i][j]; // vector covI_j * dres_j/dz_i, save for 2nd derivative calculation
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];
539
540 dchi1 += ROOT::Math::Dot(res, cidr);
541 }
542 }
543
544 // chi2 2nd derivative
545 for (int i = N; i--;) {
546 for (int j = i + 1; j--;) { // symmetric matrix
547 auto& dchi2 = mD2Chi2Dz2[i][j]; // D2Chi2/Dz_i/Dz_j = sum_k { Dres_k/Dz_j * covI_k * Dres_k/Dz_i + res_k * covI_k * D2res_k/Dz_i/Dz_j }
548 dchi2 = 0;
549 for (int k = N; k--;) {
550 const auto& dr1j = mDResidDz[k][j]; // vector of k-th residuals 1st derivative over Z param of track j
551 const auto& cidrkj = covIDrDz[i][k]; // vector covI_k * dres_k/dz_i
552 dchi2 += ROOT::Math::Dot(dr1j, cidrkj);
553 if (k == j) {
554 const auto& res = mTrRes[mCurHyp][k]; // vector of residuals of track k
555 const auto& covI = mTrcEInv[mCurHyp][k]; // inverse cov matrix of track k
556 const auto& dr2ij = mD2ResidDz2[k][j]; // vector of k-th residuals 2nd derivative over Z params of track 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];
558 }
559 }
560 }
561 }
562}
563
564//__________________________________________________________________________
565template <int N, typename... Args>
567{
568 //< calculate 1st and 2nd derivatives of abs DCA (chi2) over track parameters Z
569 for (int i = N; i--;) {
570 auto& dchi1 = mDChi2Dz[i]; // DChi2/Dz_i = sum_j { res_j * Dres_j/Dz_i }
571 dchi1 = 0; // chi2 1st derivative
572 for (int j = N; j--;) {
573 const auto& res = mTrRes[mCurHyp][j]; // vector of residuals of track j
574 const auto& dr1 = mDResidDz[j][i]; // vector of j-th residuals 1st derivative over Z param of track i
575 dchi1 += ROOT::Math::Dot(res, dr1);
576 if (i >= j) { // symmetrix matrix
577 // chi2 2nd derivative
578 auto& dchi2 = mD2Chi2Dz2[i][j]; // D2Chi2/Dz_i/Dz_j = sum_k { Dres_k/Dz_j * covI_k * Dres_k/Dz_i + res_k * covI_k * D2res_k/Dz_i/Dz_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]);
582 }
583 }
584 }
585 }
586}
587
588//___________________________________________________________________
589template <int N, typename... Args>
591{
592 // calculate point of closest approach for N prongs
593 // calculating V = sum (Ti*Pi)
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];
597 }
598}
599
600//___________________________________________________________________
601template <int N, typename... Args>
603{
604 // calculate point of closest approach for N prongs w/o errors
605 auto& pca = mPCA[mCurHyp];
606
607 pca[0] = mTrPos[mCurHyp][N - 1][0];
608 pca[1] = mTrPos[mCurHyp][N - 1][1];
609 pca[2] = mTrPos[mCurHyp][N - 1][2];
610
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];
615 }
616 pca[0] *= NInv;
617 pca[1] *= NInv;
618 pca[2] *= NInv;
619}
620
621//___________________________________________________________________
622template <int N, typename... Args>
624{
625 // calculate covariance matrix for the point of closest approach
626 MatSym3D covm;
627 for (int i = N; i--;) {
628 covm += ROOT::Math::Similarity(mUseAbsDCA ? getTrackRotMatrix(i) : mTrCFVT[mOrder[cand]][i], getTrackCovMatrix(i, cand));
629 }
630 return covm;
631}
632
633//___________________________________________________________________
634template <int N, typename... Args>
636{
637 // calculate residuals, res = Pi - V
638 Vec3D vtxLoc;
639 for (int i = N; i--;) {
640 mTrRes[mCurHyp][i] = mTrPos[mCurHyp][i];
641 vtxLoc = mPCA[mCurHyp];
642 mTrRes[mCurHyp][i] -= vtxLoc;
643 }
644}
645
646//___________________________________________________________________
647template <int N, typename... Args>
649{
650 // calculate track derivatives over Z param
651 for (int i = N; i--;) {
652 mTrDer[mCurHyp][i].set(mCandTr[mCurHyp][i], mBz);
653 }
654}
655
656//___________________________________________________________________
657template <int N, typename... Args>
659{
660 // calculate current chi2
661 double chi2 = 0;
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;
666 }
667 return chi2;
668}
669
670//___________________________________________________________________
671template <int N, typename... Args>
673{
674 // calculate current chi2 of abs. distance minimization
675 double chi2 = 0;
676 for (int i = N; i--;) {
677 const auto& res = mTrRes[mCurHyp][i];
678 chi2 += res[0] * res[0] + res[1] * res[1] + res[2] * res[2];
679 }
680 return chi2;
681}
682
683//___________________________________________________________________
684template <int N, typename... Args>
686{
687 // propagate tracks to updated Z
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];
694 }
695
696 return true;
697}
698
699//___________________________________________________________________
700template <int N, typename... Args>
702{
703 // propagate on z axis to vertex
704 int ord = mOrder[icand];
705 if (mTrPropDone[ord]) {
706 return true;
707 }
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]; // fetch the track again, as mCandTr might have been propagated w/o errors
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)) {
716 return false;
717 }
718 }
719
720 mTrPropDone[ord] = true;
721 return true;
722}
723
724//___________________________________________________________________
725template <int N, typename... Args>
726float FwdDCAFitterN<N, Args...>::findZatXY(int mCurHyp) // Between 2 tracks
727{
728
729 double step = 0.001; // initial step
730 double startPoint = 20.; // first MFT disk
731
732 double z[2] = {startPoint, startPoint};
733 double newX[2], newY[2];
734
735 double X = mPCA[mCurHyp][0]; // X seed
736 double Y = mPCA[mCurHyp][1]; // Y seed
737
738 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
739 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
740
741 double dstXY[2][3] = {{999., 999., 999.}, {999., 999., 999.}};
742
743 double Z[2];
744 double finalZ[2];
745
746 double newDstXY;
747
748 for (int i = 0; i < 2; i++) {
749
750 while (z[i] > -10) {
751
752 mCandTr[mCurHyp][i].propagateParamToZquadratic(z[i], mBz);
753 newX[i] = mCandTr[mCurHyp][i].getX();
754 newY[i] = mCandTr[mCurHyp][i].getY();
755
756 newDstXY = std::sqrt((newX[i] - X) * (newX[i] - X) +
757 (newY[i] - Y) * (newY[i] - Y));
758
759 // Update points
760 dstXY[i][0] = dstXY[i][1];
761 dstXY[i][1] = dstXY[i][2];
762 dstXY[i][2] = newDstXY;
763
764 if (dstXY[i][2] > dstXY[i][1] && dstXY[i][1] < dstXY[i][0]) {
765 finalZ[i] = z[i] + step;
766 break;
767 }
768
769 z[i] -= step;
770 }
771 }
772
773 float rez = 0.5 * (finalZ[0] + finalZ[1]);
774 return rez;
775}
776
777//___________________________________________________________________
778template <int N, typename... Args>
780{
781 // look into dXY of T0 - T1 between 2 points(0,40cm); the one with the highest dXY is moved to mid
782
783 double startPoint = -40.;
784 double endPoint = 50.;
785 double midPoint = 0.5 * (startPoint + endPoint);
786
787 double z[2][2] = {{startPoint, endPoint}, {startPoint, endPoint}}; // z for tracks 0/1 on starting poing and endpoint
788
789 double DeltaZ = std::abs(endPoint - startPoint);
790
791 double newX[2][2];
792 double newY[2][2];
793
794 double epsilon = 0.0001;
795
796 double X = mPCA[mCurHyp][0]; // X seed
797 double Y = mPCA[mCurHyp][1]; // Y seed
798
799 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
800 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
801
802 double finalZ;
803
804 double dstXY[2]; // 0 -> distance btwn both tracks at startPoint
805
806 while (DeltaZ > epsilon) {
807
808 midPoint = 0.5 * (startPoint + endPoint);
809
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();
814
815 mCandTr[mCurHyp][i].propagateParamToZquadratic(endPoint, mBz);
816 newX[i][1] = mCandTr[mCurHyp][i].getX();
817 newY[i][1] = mCandTr[mCurHyp][i].getY();
818 }
819
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]);
822
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]);
825
826 DeltaZ = std::abs(endPoint - startPoint);
827
828 if (DeltaZ < epsilon) {
829 finalZ = 0.5 * (startPoint + endPoint);
830 break;
831 }
832
833 // chose new start and end Point according to the smallest D_XY
834 if (dstXY[1] > dstXY[0]) {
835 endPoint = midPoint;
836 } else {
837 startPoint = midPoint;
838 }
839 }
840
841 mPCA[mCurHyp][2] = finalZ;
842}
843
844//___________________________________________________________________
845template <int N, typename... Args>
847{
848 // approx method: z=(b-b')/(a'-a) -> tracks to lines with y0,1=az0,1+b for each track (in YZ and XZ plane)
849
850 double startPoint = 1.;
851 double endPoint = 50.; // first disk
852
853 double X = mPCA[mCurHyp][0]; // X seed
854 double Y = mPCA[mCurHyp][1]; // Y seed
855
856 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
857 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
858
859 double y[2][2]; // Y00: y track 0 at point 0; Y01: y track 0 at point 1
860 double z[2][2];
861 double x[2][2];
862
863 double aYZ[2];
864 double bYZ[2];
865
866 double aXZ[2];
867 double bXZ[2];
868
869 double finalZ;
870
871 // find points of the tracks = 2 straight lines
872 for (int i = 0; i < 2; i++) {
873
874 mCandTr[mCurHyp][i].propagateToZquadratic(startPoint, mBz);
875 // mCandTr[mCurHyp][i].propagateToZlinear(startPoint);
876 z[i][0] = startPoint;
877 y[i][0] = mCandTr[mCurHyp][i].getY();
878 x[i][0] = mCandTr[mCurHyp][i].getX();
879
880 mCandTr[mCurHyp][i].propagateToZquadratic(endPoint, mBz);
881 // mCandTr[mCurHyp][i].propagateToZlinear(endPoint);
882 z[i][1] = endPoint;
883 y[i][1] = mCandTr[mCurHyp][i].getY();
884 x[i][1] = mCandTr[mCurHyp][i].getX();
885
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];
888
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];
891 }
892
893 // z seed: equ. for intersection of these lines
894 finalZ = 0.5 * ((bYZ[0] - bYZ[1]) / (aYZ[1] - aYZ[0]) + (bXZ[0] - bXZ[1]) / (aXZ[1] - aXZ[0]));
895
896 mPCA[mCurHyp][2] = finalZ;
897}
898
899//___________________________________________________________________
900template <int N, typename... Args>
902{
903 double startPoint = 0.;
904 double endPoint = 40.; // first disk
905
906 double X = mPCA[mCurHyp][0]; // X seed
907 double Y = mPCA[mCurHyp][1]; // Y seed
908
909 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
910 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
911
912 double x[2];
913 double y[2];
914 double sinPhi0[2];
915 double cosPhi0[2];
916 double tanL0[2];
917 double qpt0[2];
918
919 double k[2]; // B2C *abs(mBz)
920 double Hz[2]; // mBz/abs(mBz)
921
922 double Ax[2], Bx[2], Cx[2];
923 double Ay[2], By[2], Cy[2];
924
925 double deltaX[2], deltaY[2];
926
927 bool posX[2], nulX[2], negX[2];
928 double z1X[2], z2X[2], z12X[2];
929
930 bool posY[2], nulY[2], negY[2];
931 double z1Y[2], z2Y[2], z12Y[2];
932
933 double finalZ[2];
934
935 // find all variables for 2 tracks at z0 = startPoint
936 // set A, B, C variables for x/y equation for 2 tracks
937 // calculate Deltax/y for both and roots
938
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();
947 k[i] = getK(mBz);
948 Hz[i] = getHz(mBz);
949
950 Ax[i] = qpt0[i] * Hz[i] * k[i] * sinPhi0[i] / (2 * tanL0[i] * tanL0[i]);
951 Bx[i] = cosPhi0[i] / tanL0[i];
952 Cx[i] = x[i] - X;
953
954 Ay[i] = -qpt0[i] * Hz[i] * k[i] * cosPhi0[i] / (2 * tanL0[i] * tanL0[i]);
955 By[i] = sinPhi0[i] / tanL0[i];
956 Cy[i] = y[i] - Y; //
957
958 deltaX[i] = Bx[i] * Bx[i] - 4 * Ax[i] * Cx[i];
959 deltaY[i] = By[i] * By[i] - 4 * Ay[i] * Cy[i];
960
961 if (deltaX[i] > 0) {
962 posX[i] = true;
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) {
966 nulX[i] = true;
967 z12X[i] = -Bx[i] / (2 * Ax[i]);
968 } else {
969 negX[i] = true;
970 z12X[i] = 0;
971 } // discard
972
973 if (deltaY[i] > 0) {
974 posY[i] = true;
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) {
978 nulY[i] = true;
979 z12Y[i] = -By[i] / (2 * Ay[i]);
980 } else {
981 negY[i] = true;
982 z12Y[i] = 0;
983 }
984
985 // find the z located in an acceptable interval
986 if (posX[i]) {
987 if (z1X[i] < endPoint && z1X[i] > startPoint) {
988 z12X[i] = z1X[i];
989 } else {
990 z12X[i] = z2X[i];
991 }
992 }
993
994 if (posY[i]) {
995 if (z1Y[i] < endPoint && z1Y[i] > startPoint) {
996 z12Y[i] = z1Y[i];
997 } else {
998 z12Y[i] = z2Y[i];
999 }
1000 }
1001
1002 finalZ[i] = 0.5 * (z12X[i] + z12Y[i]);
1003 }
1004
1005 mPCA[mCurHyp][2] = 0.5 * (finalZ[0] + finalZ[1]);
1006}
1007
1008//___________________________________________________________________
1009template <int N, typename... Args>
1011{
1012
1013 double startPoint = 0.;
1014
1015 double X = mPCA[mCurHyp][0]; // X seed
1016 double Y = mPCA[mCurHyp][1]; // Y seed
1017
1018 mCandTr[mCurHyp][0] = *mOrigTrPtr[0];
1019 mCandTr[mCurHyp][1] = *mOrigTrPtr[1];
1020
1021 double x[2];
1022 double y[2];
1023 double sinPhi0[2];
1024 double cosPhi0[2];
1025 double tanL0[2];
1026
1027 double Ax[2], Bx[2];
1028 double Ay[2], By[2];
1029
1030 double z12X[2];
1031 double z12Y[2];
1032
1033 double finalZ[2];
1034
1035 // find all variables for 2 tracks at z0 = startPoint
1036 // set A, B variables for x/y equation for 2 tracks
1037 // calculate root
1038
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();
1046
1047 Ax[i] = cosPhi0[i] / tanL0[i];
1048 Bx[i] = x[i] - X;
1049
1050 Ay[i] = sinPhi0[i] / tanL0[i];
1051 By[i] = y[i] - Y;
1052
1053 z12X[i] = -Bx[i] / Ax[i];
1054 z12Y[i] = -By[i] / Ay[i];
1055
1056 finalZ[i] = 0.5 * (z12X[i] + z12Y[i]);
1057 }
1058
1059 mPCA[mCurHyp][2] = 0.5 * (finalZ[0] + finalZ[1]);
1060}
1061
1062//___________________________________________________________________
1063template <int N, typename... Args>
1065{
1066 // propagate tracks param only to current vertex (if not already done)
1067 int ord = mOrder[icand];
1068 o2::track::TrackParFwd trc(mCandTr[ord][i]);
1069 if (!mTrPropDone[ord]) {
1070 auto z = mPCA[ord][2];
1071 trc.propagateParamToZquadratic(z, mBz);
1072 }
1073
1074 return {trc};
1075}
1076
1077//___________________________________________________________________
1078template <int N, typename... Args>
1080{
1081 double mx = -1;
1082 for (int i = N; i--;) {
1083 auto vai = std::abs(v[i]);
1084 if (mx < vai) {
1085 mx = vai;
1086 }
1087 }
1088 return mx;
1089}
1090
1091//___________________________________________________________________
1092template <int N, typename... Args>
1094{
1095 // find best chi2 (weighted DCA) of N tracks in the vicinity of the seed PCA
1096 double x[2], y[2];
1097 double sumX = 0.;
1098 double sumY = 0.;
1099
1100 for (int i = N; i--;) {
1101 mCandTr[mCurHyp][i] = *mOrigTrPtr[i];
1102 auto z = mPCA[mCurHyp][2];
1103
1104 mCandTr[mCurHyp][i].propagateToZquadratic(z, mBz);
1105
1106 x[i] = mCandTr[mCurHyp][i].getX();
1107 y[i] = mCandTr[mCurHyp][i].getY();
1108
1109 setTrackPos(mTrPos[mCurHyp][i], mCandTr[mCurHyp][i]); // prepare positions
1110 mTrcEInv[mCurHyp][i].set(mCandTr[mCurHyp][i], ZerrFactor); // prepare inverse cov.matrices at starting point
1111
1112 sumX = sumX + x[i];
1113 sumY = sumY + y[i];
1114 }
1115
1116 mPCA[mCurHyp][0] = sumX / N;
1117 mPCA[mCurHyp][1] = sumY / N;
1118
1119 if (mMaxDXIni > 0 && !roughDXCut()) { // apply rough cut on tracks X difference
1120 return false;
1121 }
1122
1123 if (!FwdcalcPCACoefs()) { // prepare tracks contribution matrices to the global PCA
1124 return false;
1125 }
1126 FwdcalcPCA(); // current PCA
1127 FwdcalcTrackResiduals(); // current track residuals
1128 float chi2Upd, chi2 = FwdcalcChi2();
1129 do {
1130 calcTrackDerivatives(); // current track derivatives (1st and 2nd)
1131 FwdcalcResidDerivatives(); // current residals derivatives (1st and 2nd)
1132 FwdcalcChi2Derivatives(); // current chi2 derivatives (1st and 2nd) to proceed for dz calculation
1133
1134 // do Newton-Rapson iteration with corrections = - dchi2/d{x0..xN} * [ d^2chi2/d{x0..xN}^2 ]^-1
1135 if (!mD2Chi2Dz2.Invert()) {
1136 return false;
1137 }
1138
1139 VecND dz = mD2Chi2Dz2 * mDChi2Dz;
1140
1141 if (!FwdcorrectTracks(dz)) { // calculate new Pi (mTrPos) following Newton-Rapson iteration
1142 return false;
1143 }
1144
1145 FwdcalcPCA(); // updated mPCA (new V coordinates with new mTrPos (Pi))
1146 if (mCrossIDAlt >= 0 && closerToAlternative()) {
1147 mAllowAltPreference = false;
1148 return false;
1149 }
1150
1151 FwdcalcTrackResiduals(); // updated residuals
1152 chi2Upd = FwdcalcChi2(); // updated chi2
1153
1154 if (getAbsMax(dz) < mMinParamChange || chi2Upd > chi2 * mMinRelChi2Change) {
1155 chi2 = chi2Upd;
1156 break; // converged
1157 }
1158
1159 chi2 = chi2Upd;
1160 } while (++mNIters[mCurHyp] < mMaxIter);
1161
1162 mChi2[mCurHyp] = chi2 * NInv;
1163 return mChi2[mCurHyp] < mMaxChi2;
1164}
1165
1166//___________________________________________________________________
1167template <int N, typename... Args>
1169{
1170 // find best chi2 (absolute DCA) of N tracks in the vicinity of the PCA seed
1171 double x[2], y[2];
1172 double sumX = 0.;
1173 double sumY = 0.;
1174
1175 for (int i = N; i--;) {
1176
1177 mCandTr[mCurHyp][i] = *mOrigTrPtr[i];
1178
1179 auto z = mPCA[mCurHyp][2];
1180 mCandTr[mCurHyp][i].propagateParamToZquadratic(z, mBz);
1181
1182 x[i] = mCandTr[mCurHyp][i].getX();
1183 y[i] = mCandTr[mCurHyp][i].getY();
1184
1185 mPCA[mCurHyp][2] = z;
1186
1187 setTrackPos(mTrPos[mCurHyp][i], mCandTr[mCurHyp][i]); // prepare positions
1188
1189 sumX = sumX + x[i];
1190 sumY = sumY + y[i];
1191 }
1192
1193 mPCA[mCurHyp][0] = sumX / N;
1194 mPCA[mCurHyp][1] = sumY / N;
1195
1196 if (mMaxDXIni > 0 && !roughDXCut()) { // apply rough cut on tracks Z difference
1197 return false;
1198 }
1199
1200 FwdcalcPCANoErr(); // current PCA
1201 FwdcalcTrackResiduals(); // current track residuals
1202 float chi2Upd, chi2 = FwdcalcChi2NoErr();
1203 do {
1204 calcTrackDerivatives(); // current track derivatives (1st and 2nd)
1205 FwdcalcResidDerivativesNoErr(); // current residals derivatives (1st and 2nd)
1206 FwdcalcChi2DerivativesNoErr(); // current chi2 derivatives (1st and 2nd)
1207
1208 // do Newton-Rapson iteration with corrections = - dchi2/d{x0..xN} * [ d^2chi2/d{x0..xN}^2 ]^-1
1209 if (!mD2Chi2Dz2.Invert()) {
1210 return false;
1211 }
1212 VecND dz = mD2Chi2Dz2 * mDChi2Dz;
1213
1214 if (!FwdcorrectTracks(dz)) {
1215 return false;
1216 }
1217 FwdcalcPCANoErr(); // updated PCA
1218 if (mCrossIDAlt >= 0 && closerToAlternative()) {
1219 mAllowAltPreference = false;
1220 return false;
1221 }
1222 FwdcalcTrackResiduals(); // updated residuals
1223 chi2Upd = FwdcalcChi2NoErr(); // updated chi2
1224 if (getAbsMax(dz) < mMinParamChange || chi2Upd > chi2 * mMinRelChi2Change) {
1225 chi2 = chi2Upd;
1226 break; // converged
1227 }
1228 chi2 = chi2Upd;
1229 } while (++mNIters[mCurHyp] < mMaxIter);
1230 //
1231 mChi2[mCurHyp] = chi2 * NInv;
1232 return mChi2[mCurHyp] < mMaxChi2;
1233}
1234
1235//___________________________________________________________________
1236template <int N, typename... Args>
1238{
1239 // apply rough cut on DX between the tracks in the seed point
1240
1241 bool accept = true;
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) {
1245 accept = false;
1246 break;
1247 }
1248 }
1249 }
1250 return accept;
1251}
1252
1253//___________________________________________________________________
1254template <int N, typename... Args>
1256{
1257 // check if the point current PCA point is closer to the seeding XY point being tested or to alternative see (if any)
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;
1261}
1262
1263//___________________________________________________________________
1264template <int N, typename... Args>
1266{
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;
1271}
1272//___________________________________________________________________
1273template <int N, typename... Args>
1274inline bool FwdDCAFitterN<N, Args...>::propagateToVtx(o2::track::TrackParCovFwd& t, const std::array<float, 3>& p, const std::array<float, 2>& cov) const
1275{
1276 // propagate track to vertex including MCS effects if material budget included, simple propagation to Z otherwise
1277 float x2x0 = 0;
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;
1281 return t.propagateToVtxhelixWithMCS(p[2], {p[0], p[1]}, cov, mBz, x2x0);
1282 } else if (mTGeoFallBackAllowed) {
1283 auto geoMan = o2::base::GeometryManager::meanMaterialBudget(t.getX(), t.getY(), t.getZ(), p[0], p[1], p[2]);
1284 x2x0 = (float)geoMan.meanX2X0;
1285 return t.propagateToVtxhelixWithMCS(p[2], {p[0], p[1]}, cov, mBz, x2x0);
1286 } else {
1287 t.propagateToZhelix(p[2], mBz);
1288 return true;
1289 }
1290}
1291
1294
1295} // namespace vertexing
1296} // namespace o2
1297#endif // _ALICEO2_DCA_FWDFITTERN_
Helper classes for helical tracks manipulations.
Base track model for the Barrel, params only, w/o covariance.
Definition of the GeometryManager class.
int32_t i
uint32_t j
Definition RawData.h:0
uint32_t res
Definition RawData.h:0
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)
Definition TrackFwd.cxx:443
Double_t getSigma2Y() const
Definition TrackFwd.h:153
void propagateToZhelix(double zEnd, double zField)
Definition TrackFwd.cxx:188
Double_t getSigmaXY() const
Definition TrackFwd.h:154
Double_t getSigma2X() const
Definition TrackFwd.h:152
void propagateParamToZquadratic(double zEnd, double zField)
Definition TrackFwd.cxx:81
Double_t getTanl() const
Definition TrackFwd.h:72
Double_t getZ() const
return Z coordinate (cm)
Definition TrackFwd.h:46
Double_t getCurvature(double b) const
Definition TrackFwd.h:89
Double_t getY() const
Definition TrackFwd.h:52
Double_t getCharge() const
return the charge (assumed forward motion)
Definition TrackFwd.h:96
Double_t getX() const
Definition TrackFwd.h:49
Double_t getSnp() const
Definition TrackFwd.h:58
MatStd3D getTrackRotMatrix(int i) const
void setMinParamChange(float x=1e-3)
float getChi2AtPCACandidate(int cand=0) const
int process(const Tr &... args)
void setMinRelChi2Change(float r=0.9)
FwdDCAFitterN(float bz, bool useAbsDCA, bool prop2DCA)
bool isPropagateTracksToVertexDone(int cand=0) const
void setPropagateToPCA(bool v=true)
int getNIterations(int cand=0) const
void findZatXY_linear(int cand=0)
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)
void assign(int i, const T &t, const Tr &... args)
std::array< float, 6 > calcPCACovMatrixFlat(int cand=0) const
void setMatLUT(const o2::base::MatLayerCylSet *m)
void findZatXY_lineApprox(int cand=0)
static constexpr int getNProngs()
double getK(double b) const
double getHz(double b) const
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)
const auto getPCACandidatePos(int cand=0) const
return Chi2 at PCA candidate (no check for its validity)
static double getAbsMax(const VecND &v)
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
bool FwdcorrectTracks(const VecND &corrZ)
bool FwdpropagateTracksToVertex(int cand=0)
check if propagation of tracks to candidate vertex was done
o2::track::TrackParFwd FwdgetTrackParamAtPCA(int i, int cand=0) const
MatSym3D calcPCACovMatrix(int cand=0) const
GLdouble n
Definition glcorearb.h:1982
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
const GLdouble * v
Definition glcorearb.h:832
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean r
Definition glcorearb.h:1233
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
constexpr float Almost0
constexpr float B2C
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"
vec clear()