From eb563b4942b749c0a961f52bc665e2b5929eb258 Mon Sep 17 00:00:00 2001 From: "se.gorbunov" <se.gorbunov@gsi.de> Date: Thu, 18 Aug 2022 16:22:23 +0000 Subject: [PATCH] L1: update of filtration --- reco/L1/CbmL1.cxx | 9 +++ reco/L1/L1Algo/L1CATrackFinder.cxx | 46 +++++++++-- reco/L1/L1Algo/L1Filtration.h | 122 +++++++++++++++-------------- reco/L1/L1Algo/L1TrackPar.h | 111 ++++++++++++++++++-------- 4 files changed, 194 insertions(+), 94 deletions(-) diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx index 08f1d78d78..bbd90eb1ab 100644 --- a/reco/L1/CbmL1.cxx +++ b/reco/L1/CbmL1.cxx @@ -800,7 +800,16 @@ InitStatus CbmL1::Init() trd2dIter2.SetMinLevelTripletStart(1); trd2dIter2.SetPrimaryFlag(true); + // Initialize CA track finder iterations sequence + fpInitManager->SetCAIterationsNumberCrosscheck(1); + /* + fpInitManager->SetCAIterationsNumberCrosscheck(5); + fpInitManager->PushBackCAIteration(trackingIterFastPrim); + fpInitManager->PushBackCAIteration(trackingIterAllPrim); + fpInitManager->PushBackCAIteration(trackingIterAllPrimJump); + fpInitManager->PushBackCAIteration(trackingIterAllSec); + */ fpInitManager->PushBackCAIteration(trd2dIter2); } else { diff --git a/reco/L1/L1Algo/L1CATrackFinder.cxx b/reco/L1/L1Algo/L1CATrackFinder.cxx index 1e69f08ed7..0bd214f415 100644 --- a/reco/L1/L1Algo/L1CATrackFinder.cxx +++ b/reco/L1/L1Algo/L1CATrackFinder.cxx @@ -694,6 +694,8 @@ inline void L1Algo::findTripletsStep0( // input // assert(T2.IsConsistent(true, n2_4)); + // L1TrackPar tStore1 = T2; + L1UMeasurementInfo info = stam.frontInfo; if (fUseHitErrors) info.sigma2 = du2 * du2; @@ -708,7 +710,28 @@ inline void L1Algo::findTripletsStep0( // input L1FilterNoField(T2, info, u_front_2); } - // assert(T2.IsConsistent(true, n2_4)); + // L1TrackPar tStore2 = T2; + + //assert(T2.IsConsistent(true, n2_4)); + + // a good place to debug the fit + + /* + if (tStore1.IsConsistent(false, n2_4) && !tStore2.IsConsistent(false, n2_4)) { + cout << " i2 " << i2 << " dx2 " << dx2 << endl; + cout << "\n\n before filtration: \n\n" << endl; + tStore1.Print(); + tStore1.IsConsistent(true, n2_4); + cout << "\n\n after filtration: \n\n" << endl; + tStore2.Print(); + tStore2.IsConsistent(true, n2_4); + cout << "\n\n " << n2_4 << " vector elements are filled." << endl; + cout << "measurement: cos " << info.cos_phi[0] << " sin " << info.sin_phi[0] << " u " << u_front_2 << " s2 " + << sqrt(info.sigma2) << endl; + cout << "\n\n" << endl; + exit(0); + } + */ info = stam.backInfo; if (fUseHitErrors) info.sigma2 = dv2 * dv2; @@ -946,7 +969,7 @@ inline void L1Algo::findTripletsStep0( // input dv_.resize(n3 / fvecLen); timeR.resize(n3 / fvecLen); timeER.resize(n3 / fvecLen); - cout << "GetMaxTripletPerDoublets==" << fParameters.GetMaxTripletPerDoublets() + cout << "L1: GetMaxTripletPerDoublets==" << fParameters.GetMaxTripletPerDoublets() << " reached in findTripletsStep0()" << endl; //assert(0); break; @@ -1259,13 +1282,17 @@ inline void L1Algo::findTripletsStep3( // input ihitl_prev = 1 + hitsl_3[i3]; #ifdef DO_NOT_SELECT_TRIPLETS - if (isec != TRACKS_FROM_TRIPLETS_ITERATION) + if (isec != TRACKS_FROM_TRIPLETS_ITERATION) { + if (chi2 > fTripletChi2Cut) { continue; } + } +#else + if (chi2 > fTripletChi2Cut) { continue; } #endif // DO_NOT_SELECT_TRIPLETS - // assert(finite(chi2) && chi2 > 0); + // assert(finite(chi2) && chi2 > 0); - if (!finite(chi2) || chi2 < 0) { continue; } - if (chi2 > fTripletChi2Cut) { continue; } + if (!finite(chi2) || chi2 < 0) { continue; } + //if (!T3.IsEntryConsistent(false, i3_4)) { continue; } fscal qp = T3.qp[i3_4]; @@ -2820,6 +2847,13 @@ inline void L1Algo::CAFindTrack(int ista, L1Branch& best_tr, unsigned char& best fscal Cty = curr_trip->GetCty(); Cty += new_trip.GetCty(); + // it shouldn't happen, but happens sometimes + + if (!std::isfinite(dtx)) continue; + if (!std::isfinite(dty)) continue; + if (!std::isfinite(Ctx)) continue; + if (!std::isfinite(Cty)) continue; + assert(std::isfinite(dtx)); assert(std::isfinite(dty)); assert(std::isfinite(Ctx)); diff --git a/reco/L1/L1Algo/L1Filtration.h b/reco/L1/L1Algo/L1Filtration.h index 2310f934fc..6e1a095e47 100644 --- a/reco/L1/L1Algo/L1Filtration.h +++ b/reco/L1/L1Algo/L1Filtration.h @@ -14,42 +14,45 @@ #define cnst const fvec -inline void FilterTime(L1TrackPar& T, fvec t0, fvec dt0, fvec timeInfo = 1., fvec w = 1.) +inline void FilterTime(L1TrackPar& T, fvec t, fvec dt, fvec timeInfo = 1., fvec w = 1.) { - fvec wi, zeta, zetawi, HCH; - fvec F0, F1, F2, F3, F4, F5; - fvec K1, K2, K3, K4, K5; - - zeta = T.t - t0; + // filter track with a time measurement // F = CH' - F0 = T.C50; - F1 = T.C51; + fvec F0 = T.C50; + fvec F1 = T.C51; + fvec F2 = T.C52; + fvec F3 = T.C53; + fvec F4 = T.C54; + fvec F5 = T.C55; - HCH = T.C55; + fvec HCH = T.C55; - F2 = T.C52; - F3 = T.C53; - F4 = T.C54; - F5 = T.C55; + w = w & (timeInfo > 0.f); -#if 1 // use mask - const fvec mask = (timeInfo > 0); - wi = mask & w / (dt0 * dt0 + HCH); - zetawi = zeta * wi; - T.chi2 += mask & (zeta * zetawi); -#else - wi = w / (dt0 * dt0 + HCH); - zetawi = zeta * wi; - T.chi2 += zeta * zetawi; -#endif // 0 + fvec dt2 = dt * dt; + + // when dt0 is much smaller than current time error, + // set track time exactly to the measurement value without filtering + // it helps to keep the initial time errors reasonably small + // the calculations in the covariance matrix are not affected + + const fvec maskDoFilter = (HCH < dt2 * 16.f); + //const fvec maskDoFilter = _f32vec4_true; + + fvec wi = w / (dt2 + 1.0000001f * HCH); + fvec zeta = T.t - t; + fvec zetawi = zeta / ((maskDoFilter & dt2) + HCH); + + //T.chi2 += maskDoFilter & (zeta * zetawi); + T.chi2 += zeta * zeta * wi; T.NDF += w; - K1 = F1 * wi; - K2 = F2 * wi; - K3 = F3 * wi; - K4 = F4 * wi; - K5 = F5 * wi; + fvec K1 = F1 * wi; + fvec K2 = F2 * wi; + fvec K3 = F3 * wi; + fvec K4 = F4 * wi; + fvec K5 = F5 * wi; T.x -= F0 * zetawi; T.y -= F1 * zetawi; @@ -81,42 +84,46 @@ inline void FilterTime(L1TrackPar& T, fvec t0, fvec dt0, fvec timeInfo = 1., fve T.C55 -= K5 * F5; } + inline void L1Filter(L1TrackPar& T, const L1UMeasurementInfo& info, fvec u, fvec w = 1.) { - fvec wi, zeta, zetawi, HCH; - fvec F0, F1, F2, F3, F4, F5; - fvec K1, K2, K3, K4, K5; + // filter the track T with an 1-D measurement u - zeta = info.cos_phi * T.x + info.sin_phi * T.y - u; + fvec zeta = info.cos_phi * T.x + info.sin_phi * T.y - u; // F = CH' - F0 = info.cos_phi * T.C00 + info.sin_phi * T.C10; - F1 = info.cos_phi * T.C10 + info.sin_phi * T.C11; - - HCH = (F0 * info.cos_phi + F1 * info.sin_phi); - - F2 = info.cos_phi * T.C20 + info.sin_phi * T.C21; - F3 = info.cos_phi * T.C30 + info.sin_phi * T.C31; - F4 = info.cos_phi * T.C40 + info.sin_phi * T.C41; - F5 = info.cos_phi * T.C50 + info.sin_phi * T.C51; - -#if 0 // use mask - const fvec mask = (HCH < info.sigma2 * 16.); - wi = w/( (mask & info.sigma2) +HCH ); - zetawi = zeta *wi; - T.chi2 += mask & (zeta * zetawi); -#else - wi = w / (info.sigma2 + HCH); - zetawi = zeta * wi; - T.chi2 += zeta * zetawi; -#endif // 0 + fvec F0 = info.cos_phi * T.C00 + info.sin_phi * T.C10; + fvec F1 = info.cos_phi * T.C10 + info.sin_phi * T.C11; + fvec F2 = info.cos_phi * T.C20 + info.sin_phi * T.C21; + fvec F3 = info.cos_phi * T.C30 + info.sin_phi * T.C31; + fvec F4 = info.cos_phi * T.C40 + info.sin_phi * T.C41; + fvec F5 = info.cos_phi * T.C50 + info.sin_phi * T.C51; + + fvec HCH = (F0 * info.cos_phi + F1 * info.sin_phi); + + // when the measurement error info.sigma2 is much smaller than the current track error HCH, + // move track exactly to the measurement without filtering + // it helps to keep the initial track errors reasonably small + // the calculations in the covariance matrix are not affected + + //const fvec maskDoFilter = (HCH < info.sigma2 * 16.f); + const fvec maskDoFilter = _f32vec4_true; + + // correction to HCH is needed for the case when sigma2 is so small + // with respect to HCH that it disappears due to the roundoff error + // + fvec wi = w / (info.sigma2 + 1.0000001f * HCH); + fvec zetawi = zeta / ((maskDoFilter & info.sigma2) + HCH); + + // T.chi2 += maskDoFilter & (zeta * zetawi); + T.chi2 += zeta * zeta * wi; T.NDF += w; - K1 = F1 * wi; - K2 = F2 * wi; - K3 = F3 * wi; - K4 = F4 * wi; - K5 = F5 * wi; + fvec K1 = F1 * wi; + fvec K2 = F2 * wi; + fvec K3 = F3 * wi; + fvec K4 = F4 * wi; + fvec K5 = F5 * wi; T.x -= F0 * zetawi; T.y -= F1 * zetawi; @@ -148,6 +155,7 @@ inline void L1Filter(L1TrackPar& T, const L1UMeasurementInfo& info, fvec u, fvec T.C55 -= K5 * F5; } + inline void L1FilterNoField(L1TrackPar& T, const L1UMeasurementInfo& info, fvec u, fvec w = 1.) { fvec wi, zeta, zetawi, HCH; diff --git a/reco/L1/L1Algo/L1TrackPar.h b/reco/L1/L1Algo/L1TrackPar.h index 3361d53ae2..687a880c68 100644 --- a/reco/L1/L1Algo/L1TrackPar.h +++ b/reco/L1/L1Algo/L1TrackPar.h @@ -81,6 +81,13 @@ public: void SetOneEntry(const int i0, const L1TrackPar& T1, const int i1); + fvec C(int i, int j) const + { + const fvec* c = &C00; + int ind = (j <= i) ? i * (1 + i) / 2 + j : j * (1 + j) / 2 + i; + return c[ind]; + } + void Print(int i = -1) const; void PrintCorrelations(int i = -1) const; @@ -144,7 +151,10 @@ inline void L1TrackPar::Print(int i) const inline void L1TrackPar::PrintCorrelations(int i) const { + + std::_Ios_Fmtflags flagSafe = std::cout.flags(); // std::cout.setf(std::ios::scientific, std::ios::floatfield); + std::cout << std::setprecision(6); if (i == -1) { fvec s0 = sqrt(C00); @@ -192,6 +202,7 @@ inline void L1TrackPar::PrintCorrelations(int i) const std::cout << " " << C50[i] / s5 / s0 << " " << C51[i] / s5 / s1 << " " << C52[i] / s5 / s2 << " " << C53[i] / s5 / s3 << " " << C54[i] / s5 / s4 << std::endl; } + std::cout.flags(flagSafe); } inline void L1TrackPar::SetOneEntry(const int i0, const L1TrackPar& T1, const int i1) @@ -229,48 +240,86 @@ inline void L1TrackPar::SetOneEntry(const int i0, const L1TrackPar& T1, const in NDF[i0] = T1.NDF[i1]; } // SetOneEntry -inline bool L1TrackPar::IsEntryConsistent(bool printWhenWrong, int i) const +inline bool L1TrackPar::IsEntryConsistent(bool printWhenWrong, int k) const { bool ok = true; - const fvec* v = &x; - const fvec* v1 = &NDF; - for (; v < v1; v++) { - ok = ok && std::isfinite((*v)[i]); + // verify that all the numbers in the object are valid floats + const fvec* memberFirst = &x; + const fvec* memberLast = &NDF; + for (int i = 0; i < &memberLast - &memberFirst + 1; i++) { + if (!std::isfinite(memberFirst[i][k])) { + ok = false; + if (printWhenWrong) { + std::cout << " L1TrackPar member N " << i << ", vector entry " << k + << " is not a number: " << memberFirst[i][k]; + } + } } - // verify diagonal elements - - ok = ok && (C00[i] > 0.f); - ok = ok && (C11[i] > 0.f); - ok = ok && (C22[i] > 0.f); - ok = ok && (C33[i] > 0.f); - ok = ok && (C44[i] > 0.f); - ok = ok && (C55[i] > 0.f); - - // verify non-diagonal elements - ok = ok && (C10[i] * C10[i] <= C11[i] * C00[i]); - ok = ok && (C20[i] * C20[i] <= C22[i] * C00[i]); - ok = ok && (C21[i] * C21[i] <= C22[i] * C11[i]); + // verify diagonal elements. + // Cii is a squared dispersion of i-th parameter, it must be positive - ok = ok && (C30[i] * C30[i] <= C33[i] * C00[i]); - ok = ok && (C31[i] * C31[i] <= C33[i] * C11[i]); - ok = ok && (C32[i] * C32[i] <= C33[i] * C22[i]); + for (int i = 0; i < 6; i++) { + if (C(i, i)[k] <= 0.f) { + ok = false; + if (printWhenWrong) { + std::cout << " L1TrackPar: C[" << i << "," << i << "], vec entry " << k << " is not positive: " << C(i, i)[k] + << std::endl; + } + } + } - ok = ok && (C40[i] * C40[i] <= C44[i] * C00[i]); - ok = ok && (C41[i] * C41[i] <= C44[i] * C11[i]); - ok = ok && (C42[i] * C42[i] <= C44[i] * C22[i]); - ok = ok && (C43[i] * C43[i] <= C44[i] * C33[i]); + // verify non-diagonal elements. + // Cij/sqrt(Cii*Cjj) is a correlation between i-th and j-th parameter, + // it must belong to [-1,1] + + for (int i = 1; i < 6; i++) { + for (int j = 0; j < i; j++) { + double tolerance = 1.0; + if (C(i, j)[k] * C(i, j)[k] > tolerance * (C(i, i)[k] * C(j, j)[k])) { + ok = false; + if (printWhenWrong) { + std::cout << " L1TrackPar: correlation [" << i << "," << j << "], vec entry " << k + << " is too large: " << C(i, i)[k] / sqrt(C(i, i)[k] * C(j, j)[k]) << std::endl; + } + } + } + } - ok = ok && (C50[i] * C50[i] <= C55[i] * C00[i]); - ok = ok && (C51[i] * C51[i] <= C55[i] * C11[i]); - ok = ok && (C52[i] * C52[i] <= C55[i] * C22[i]); - ok = ok && (C53[i] * C53[i] <= C55[i] * C33[i]); - ok = ok && (C54[i] * C54[i] <= C55[i] * C44[i]); + // verify triplets of correlations + // Kxy * Kxy + Kxz * Kxz + Kyz * Kyz <= 1 + 2 * Kxy * Kxz * Kyz + + for (int i = 2; i < 6; i++) { + for (int j = 1; j < i; j++) { + for (int m = 0; m < j; m++) { + double tolerance = 1.0; + double Cxx = C(i, i)[k]; + double Cyy = C(j, j)[k]; + double Czz = C(m, m)[k]; + double Cxy = C(i, j)[k]; + double Cxz = C(i, m)[k]; + double Cyz = C(j, m)[k]; + if (Cxx * Cyz * Cyz + Cyy * Cxz * Cxz + Czz * Cxy * Cxy + > tolerance * (Cxx * Cyy * Czz + 2. * Cxy * Cyz * Cxz)) { + ok = false; + if (printWhenWrong) { + double Kxy = Cxy / sqrt(Cxx * Cyy); + double Kxz = Cxz / sqrt(Cxx * Czz); + double Kyz = Cyz / sqrt(Cyy * Czz); + std::cout << " L1TrackPar: correlations between parametetrs " << i << ", " << j << ", " << m + << ", vec entry " << k << " are wrong: " << Kxy << " " << Kxz << " " << Kyz << std::endl; + std::cout << " inequation: " << Kxy * Kxy + Kxz * Kxz + Kyz * Kyz << " > " << 1 + 2 * Kxy * Kxz * Kyz + << std::endl; + } + } + } + } + } if (!ok && printWhenWrong) { std::cout << "L1TrackPar parameters are not consistent: " << std::endl; - Print(i); + Print(k); } return ok; } -- GitLab