From 0c41dedd3686733ae3cc4fa2b988b840864220cc Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Mon, 25 Jul 2022 20:11:08 +0200 Subject: [PATCH] L1: CAMergeClones routine was incapsulated into L1ClonesMerger class --- reco/L1/CMakeLists.txt | 3 +- reco/L1/L1Algo/L1Algo.cxx | 4 +- reco/L1/L1Algo/L1Algo.h | 54 +- reco/L1/L1Algo/L1Assert.h | 8 +- reco/L1/L1Algo/L1CATrackFinder.cxx | 12 +- ...L1CAMergeClones.cxx => L1ClonesMerger.cxx} | 591 +++++++++--------- reco/L1/L1Algo/L1ClonesMerger.h | 119 ++++ reco/L1/L1Algo/L1Track.h | 32 +- reco/L1/L1Algo/L1Utils.h | 74 +-- 9 files changed, 472 insertions(+), 425 deletions(-) rename reco/L1/L1Algo/{L1CAMergeClones.cxx => L1ClonesMerger.cxx} (62%) create mode 100644 reco/L1/L1Algo/L1ClonesMerger.h diff --git a/reco/L1/CMakeLists.txt b/reco/L1/CMakeLists.txt index 25d1c057ec..53f1bba9bd 100644 --- a/reco/L1/CMakeLists.txt +++ b/reco/L1/CMakeLists.txt @@ -129,7 +129,6 @@ L1Algo/L1Algo.cxx L1Algo/L1CATrackFinder.cxx L1Algo/L1TrackExtender.cxx L1Algo/L1TrackFitter.cxx -L1Algo/L1CAMergeClones.cxx L1Algo/L1HitsSortHelper.cxx L1Algo/L1Grid.cxx CbmL1Performance.cxx @@ -149,6 +148,7 @@ L1Algo/L1CAIteration.cxx L1Algo/L1BaseStationInfo.cxx L1Algo/L1InitManager.cxx L1Algo/L1Parameters.cxx +L1Algo/L1ClonesMerger.cxx L1Algo/L1ConfigRW.cxx L1Algo/utils/L1AlgoDraw.cxx L1Algo/utils/L1AlgoEfficiencyPerformance.cxx @@ -286,6 +286,7 @@ Install(FILES CbmL1Counters.h L1Algo/L1InitManager.h L1Algo/L1CAIteration.h L1Algo/L1Parameters.h + L1Algo/L1ClonesMerger.h L1Algo/L1ConfigRW.h L1Algo/L1Constants.h L1Algo/L1Utils.h diff --git a/reco/L1/L1Algo/L1Algo.cxx b/reco/L1/L1Algo/L1Algo.cxx index 5a27570b36..a934089cbc 100644 --- a/reco/L1/L1Algo/L1Algo.cxx +++ b/reco/L1/L1Algo/L1Algo.cxx @@ -93,7 +93,7 @@ void L1Algo::Init(const bool UseHitErrors, const TrackingMode mode, const bool M LOG(info) << fParameters.ToString(3); // Get number of station - fNstations = fInitManager.GetNstationsActive(); + fNstations = fParameters.GetNstationsActive(); fTrackingLevel = fInitManager.GetTrackingLevel(); fGhostSuppression = fInitManager.GetGhostSuppression(); @@ -116,7 +116,7 @@ void L1Algo::SetData(L1Vector<L1Hit>& Hits_, int nStrips_, L1Vector<unsigned cha int nHits = vHits->size(); - NHitsIsecAll = nHits; + NHitsIsecAll = nHits; // TODO: Is it needed? vNotUsedHits_A.reset(nHits); vNotUsedHits_B.reset(nHits); diff --git a/reco/L1/L1Algo/L1Algo.h b/reco/L1/L1Algo/L1Algo.h index ebb8d3bc47..b1f51f0d06 100644 --- a/reco/L1/L1Algo/L1Algo.h +++ b/reco/L1/L1Algo/L1Algo.h @@ -43,6 +43,7 @@ class L1AlgoDraw; #include <map> #include "L1Branch.h" +#include "L1ClonesMerger.h" #include "L1Field.h" #include "L1Grid.h" #include "L1Hit.h" @@ -166,39 +167,6 @@ public: Tindex fDupletPortionStopIndex[L1Constants::size::kMaxNstations] {0}; // end of the duplet portions for the station L1Vector<Tindex> fDupletPortionSize {"L1Algo::fDupletPortionSize"}; // N duplets in a portion - /********************************************************************************************/ /** - * Temporary vectors used by the clone merger - * TODO: Probably, the subclass L1TrackMerger for clones merger would help to improve - * readability (S.Zharko) - ***********************************************************************************************/ - - // - // Vectors that are parallel to fTracks - // - /// First station of a track - L1Vector<unsigned short> fMergerTrackFirstStation {"L1Algo::fMergerTrackFirstStation"}; - /// Last station of a track - L1Vector<unsigned short> fMergerTrackLastStation {"L1Algo::fMergerTrackLastStation"}; - /// Index of the first hit of a track - L1Vector<L1HitIndex_t> fMergerTrackFirstHit {"L1Algo::fMergerTrackFirstHit"}; - /// Index of the last hit of a track - L1Vector<L1HitIndex_t> fMergerTrackLastHit {"L1Algo::fMergerTrackLastHit"}; - /// Index (TODO:??) of a track that can be merge with the given track - L1Vector<unsigned short> fMergerTrackNeighbour {"L1Algo::fMergerTrackNeighbour"}; - /// Chi2 value of the track merging procedure - L1Vector<float> fMergerTrackChi2 {"L1Algo::fMergerTrackChi2"}; - /// Flag: is the given track already stored to the output - L1Vector<char> fMergerTrackIsStored {"L1Algo::fMergerTrackIsStored"}; - /// Flag: is the track a downstream neighbour of another track - L1Vector<char> fMergerTrackIsDownstreamNeighbour {"L1Algo::fMergerTrackIsDownstreamNeighbour"}; - // - // Utility vectors - // - /// Tracks after the merging procedure - L1Vector<L1Track> fMergerTracksNew {"L1Algo::fMergerTracksNew"}; // vector of tracks after the merge - L1Vector<L1HitIndex_t> fMergerRecoHitsNew {"L1Algo::fMergerRecoHitsNew"}; // vector of track hits after the merge - - #ifdef DRAW L1AlgoDraw* draw {nullptr}; void DrawRecoTracksTime(const L1Vector<CbmL1Track>& tracks); @@ -261,7 +229,7 @@ public: public: int fNstrips {0}; ///< number of strips L1Vector<L1Hit>* vHits {nullptr}; ///< hits as a combination of front and back strips and z-position - L1Grid vGrid[L1Constants::size::kMaxNstations]; ///< hits as a combination of front and back strips and z-position + L1Grid vGrid[L1Constants::size::kMaxNstations]; ///< L1Grid vGridTime[L1Constants::size::kMaxNstations]; ///< L1Vector<unsigned char>* fStripFlag {nullptr}; // information of hits station & using hits in tracks; @@ -386,15 +354,15 @@ public: // TODO: remove it (S.Zharko) /// Gets a pointer to the L1Algo parameters object - const L1Parameters* GetParameters() { return &fParameters; } + const L1Parameters* GetParameters() const { return &fParameters; } /// Gets a pointer to the L1Algo initialization object L1InitManager* GetInitManager() { return &fInitManager; } private: - L1Parameters fParameters {}; ///< Object of L1Algo parameters class - L1InitManager fInitManager {}; ///< Object of L1Algo initialization manager class - + L1Parameters fParameters {}; ///< Object of L1Algo parameters class + L1InitManager fInitManager {}; ///< Object of L1Algo initialization manager class + L1ClonesMerger fClonesMerger {*this}; ///< Object of L1Algo clones merger algorithm /*********************************************************************************************/ /** * ------ FUNCTIONAL PART ------ @@ -436,16 +404,6 @@ private: /// \return chi2 fscal BranchExtender(L1Branch& t); - /// ----- Subroutines used by L1Algo::CAMergeClones() ------ - void InvertCholetsky(fvec a[15]); - void MultiplySS(fvec const C[15], fvec const V[15], fvec K[5][5]); - void MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15]); - void MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[5]); - void FilterTracks(fvec const r[5], fvec const C[15], fvec const m[5], fvec const V[15], fvec R[5], fvec W[15], - fvec* chi2); - /// - void CAMergeClones(); - inline __attribute__((always_inline)) void PackLocation(unsigned int& location, unsigned int& triplet, unsigned int iStation, unsigned int& thread) { diff --git a/reco/L1/L1Algo/L1Assert.h b/reco/L1/L1Algo/L1Assert.h index 9b3dc67257..a5e03567c5 100644 --- a/reco/L1/L1Algo/L1Assert.h +++ b/reco/L1/L1Algo/L1Assert.h @@ -38,7 +38,7 @@ namespace L1Assert /// Basic template function. Usage: place "level <= L1Assert::kAssertionLevel" as a template parameter template<bool IsAsserted> - int DoAssertion(int level, bool condition, const char* msg, const char* fileName, int lineNo) + void DoAssertion(int level, bool condition, const char* msg, const char* fileName, int lineNo) { if (!condition) { LOG(fatal) << '\n' @@ -48,15 +48,13 @@ namespace L1Assert << " ***** line: " << lineNo; std::abort(); // keep it here, because sometimes LOG(fatal) does not work (for example, in your unit testes) } - return 1; } /// Specialization in case of IsAsserted = false, i.e. the assertion is not made template<> - inline __attribute__((always_inline)) int DoAssertion<false>(int /*level*/, bool /*condition*/, const char* /*msg*/, - const char* /*fileName*/, int /*lineNo*/) + inline __attribute__((always_inline)) void DoAssertion<false>(int /*level*/, bool /*condition*/, const char* /*msg*/, + const char* /*fileName*/, int /*lineNo*/) { - return 0; } }; // namespace L1Assert diff --git a/reco/L1/L1Algo/L1CATrackFinder.cxx b/reco/L1/L1Algo/L1CATrackFinder.cxx index 1f34006ce5..1efe5236e2 100644 --- a/reco/L1/L1Algo/L1CATrackFinder.cxx +++ b/reco/L1/L1Algo/L1CATrackFinder.cxx @@ -754,6 +754,7 @@ inline void L1Algo::findTripletsStep0( // input } else if (kGlobal == fTrackingMode) { fit.L1AddMaterial(T2, fParameters.GetMaterialThickness(istam, T2.x, T2.y), fMaxInvMom, 1); + } else { fit.L1AddMaterial(T2, fParameters.GetMaterialThickness(istam, T2.x, T2.y), T2.qp, 1); } @@ -827,6 +828,8 @@ inline void L1Algo::findTripletsStep0( // input int indR = HitsUnusedStartIndex[iStaR] + irh; if (GetMcTrackIdForUnusedHit(indM) != GetMcTrackIdForUnusedHit(indR)) { continue; } } + +#ifdef USE_EVENT_NUMBER // NOTE: if ((T2.n[i2_4] != hitr.n)) continue; #endif // USE_EVENT_NUMBER const fscal zr = hitr.Z(); @@ -2634,7 +2637,14 @@ void L1Algo::CATrackFinder() c_timerG.Start(); #endif - if constexpr (L1Constants::control::kIfMergeClones) { CAMergeClones(); } + if constexpr (L1Constants::control::kIfMergeClones) { + //CAMergeClones(); + // Fit tracks + this->L1KFTrackFitter(); + + // Merge clones + fClonesMerger.Exec(fTracks, fRecoHits); + } #ifdef XXX c_timerG.Stop(); diff --git a/reco/L1/L1Algo/L1CAMergeClones.cxx b/reco/L1/L1Algo/L1ClonesMerger.cxx similarity index 62% rename from reco/L1/L1Algo/L1CAMergeClones.cxx rename to reco/L1/L1Algo/L1ClonesMerger.cxx index a5476902ae..26d1b3f94f 100644 --- a/reco/L1/L1Algo/L1CAMergeClones.cxx +++ b/reco/L1/L1Algo/L1ClonesMerger.cxx @@ -1,228 +1,52 @@ -/* Copyright (C) 2010-2018 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt +/* Copyright (C) 2010-2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt SPDX-License-Identifier: GPL-3.0-only - Authors: Maksym Zyzak [committer] */ - -/* - *===================================================== - * - * CBM Level 1 Reconstruction - * - * Authors: M.Zyzak - * - * e-mail : - * - *===================================================== - * - * Merge Clones - * - */ + Authors: Sergei Zharko, Maksym Zyzak [committer]*/ + +/// \file L1ClonesMerger.h +/// \authors S.Zharko <s.zharko@gsi.de> (interface), M.Zyzak (original algorithm) +/// \brief A class wrapper over clones merger algorithm for the L1 track finder (implementation) +/// \since 22.07.2022 (second version) + +#include "L1ClonesMerger.h" #include <iostream> #include "L1Algo.h" #include "L1Extrapolation.h" +#include "L1Parameters.h" +#include "L1Track.h" -// using namespace std; -using std::cout; -using std::endl; - -void L1Algo::InvertCholetsky(fvec a[15]) -{ - fvec d[5], uud, u[5][5]; - for (int i = 0; i < 5; i++) { - d[i] = 0.f; - for (int j = 0; j < 5; j++) - u[i][j] = 0.f; - } - - for (int i = 0; i < 5; i++) { - uud = 0.f; - for (int j = 0; j < i; j++) - uud += u[j][i] * u[j][i] * d[j]; - uud = a[i * (i + 3) / 2] - uud; - - fvec smallval = 1.e-12; - fvec initialised = fvec(uud < smallval); - uud = ((!initialised) & uud) + (smallval & initialised); - - d[i] = uud / fabs(uud); - u[i][i] = sqrt(fabs(uud)); - - for (int j = i + 1; j < 5; j++) { - uud = 0.f; - for (int k = 0; k < i; k++) - uud += u[k][i] * u[k][j] * d[k]; - uud = a[j * (j + 1) / 2 + i] /*a[i][j]*/ - uud; - u[i][j] = d[i] / u[i][i] * uud; - } - } - - fvec u1[5]; - - for (int i = 0; i < 5; i++) { - u1[i] = u[i][i]; - u[i][i] = 1.f / u[i][i]; - } - for (int i = 0; i < 4; i++) { - u[i][i + 1] = -u[i][i + 1] * u[i][i] * u[i + 1][i + 1]; - } - for (int i = 0; i < 3; i++) { - u[i][i + 2] = u[i][i + 1] * u1[i + 1] * u[i + 1][i + 2] - u[i][i + 2] * u[i][i] * u[i + 2][i + 2]; - } - for (int i = 0; i < 2; i++) { - u[i][i + 3] = u[i][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i][i + 3] * u[i][i] * u[i + 3][i + 3]; - u[i][i + 3] -= u[i][i + 1] * u1[i + 1] * (u[i + 1][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i + 1][i + 3]); - } - u[0][4] = u[0][2] * u1[2] * u[2][4] - u[0][4] * u[0][0] * u[4][4]; - u[0][4] += u[0][1] * u1[1] * (u[1][4] - u[1][3] * u1[3] * u[3][4] - u[1][2] * u1[2] * u[2][4]); - u[0][4] += u[3][4] * u1[3] * (u[0][3] - u1[2] * u[2][3] * (u[0][2] - u[0][1] * u1[1] * u[1][2])); - - for (int i = 0; i < 5; i++) - a[i + 10] = u[i][4] * d[4] * u[4][4]; - for (int i = 0; i < 4; i++) - a[i + 6] = u[i][3] * u[3][3] * d[3] + u[i][4] * u[3][4] * d[4]; - for (int i = 0; i < 3; i++) - a[i + 3] = u[i][2] * u[2][2] * d[2] + u[i][3] * u[2][3] * d[3] + u[i][4] * u[2][4] * d[4]; - for (int i = 0; i < 2; i++) - a[i + 1] = - u[i][1] * u[1][1] * d[1] + u[i][2] * u[1][2] * d[2] + u[i][3] * u[1][3] * d[3] + u[i][4] * u[1][4] * d[4]; - a[0] = u[0][0] * u[0][0] * d[0] + u[0][1] * u[0][1] * d[1] + u[0][2] * u[0][2] * d[2] + u[0][3] * u[0][3] * d[3] - + u[0][4] * u[0][4] * d[4]; -} - -void L1Algo::MultiplySS(fvec const C[15], fvec const V[15], fvec K[5][5]) -{ - K[0][0] = C[0] * V[0] + C[1] * V[1] + C[3] * V[3] + C[6] * V[6] + C[10] * V[10]; - K[0][1] = C[0] * V[1] + C[1] * V[2] + C[3] * V[4] + C[6] * V[7] + C[10] * V[11]; - K[0][2] = C[0] * V[3] + C[1] * V[4] + C[3] * V[5] + C[6] * V[8] + C[10] * V[12]; - K[0][3] = C[0] * V[6] + C[1] * V[7] + C[3] * V[8] + C[6] * V[9] + C[10] * V[13]; - K[0][4] = C[0] * V[10] + C[1] * V[11] + C[3] * V[12] + C[6] * V[13] + C[10] * V[14]; - - K[1][0] = C[1] * V[0] + C[2] * V[1] + C[4] * V[3] + C[7] * V[6] + C[11] * V[10]; - K[1][1] = C[1] * V[1] + C[2] * V[2] + C[4] * V[4] + C[7] * V[7] + C[11] * V[11]; - K[1][2] = C[1] * V[3] + C[2] * V[4] + C[4] * V[5] + C[7] * V[8] + C[11] * V[12]; - K[1][3] = C[1] * V[6] + C[2] * V[7] + C[4] * V[8] + C[7] * V[9] + C[11] * V[13]; - K[1][4] = C[1] * V[10] + C[2] * V[11] + C[4] * V[12] + C[7] * V[13] + C[11] * V[14]; - - K[2][0] = C[3] * V[0] + C[4] * V[1] + C[5] * V[3] + C[8] * V[6] + C[12] * V[10]; - K[2][1] = C[3] * V[1] + C[4] * V[2] + C[5] * V[4] + C[8] * V[7] + C[12] * V[11]; - K[2][2] = C[3] * V[3] + C[4] * V[4] + C[5] * V[5] + C[8] * V[8] + C[12] * V[12]; - K[2][3] = C[3] * V[6] + C[4] * V[7] + C[5] * V[8] + C[8] * V[9] + C[12] * V[13]; - K[2][4] = C[3] * V[10] + C[4] * V[11] + C[5] * V[12] + C[8] * V[13] + C[12] * V[14]; +// --------------------------------------------------------------------------------------------------------------------- +// +L1ClonesMerger::L1ClonesMerger(const L1Algo& algo) : frAlgo(algo) {} - K[3][0] = C[6] * V[0] + C[7] * V[1] + C[8] * V[3] + C[9] * V[6] + C[13] * V[10]; - K[3][1] = C[6] * V[1] + C[7] * V[2] + C[8] * V[4] + C[9] * V[7] + C[13] * V[11]; - K[3][2] = C[6] * V[3] + C[7] * V[4] + C[8] * V[5] + C[9] * V[8] + C[13] * V[12]; - K[3][3] = C[6] * V[6] + C[7] * V[7] + C[8] * V[8] + C[9] * V[9] + C[13] * V[13]; - K[3][4] = C[6] * V[10] + C[7] * V[11] + C[8] * V[12] + C[9] * V[13] + C[13] * V[14]; - - K[4][0] = C[10] * V[0] + C[11] * V[1] + C[12] * V[3] + C[13] * V[6] + C[14] * V[10]; - K[4][1] = C[10] * V[1] + C[11] * V[2] + C[12] * V[4] + C[13] * V[7] + C[14] * V[11]; - K[4][2] = C[10] * V[3] + C[11] * V[4] + C[12] * V[5] + C[13] * V[8] + C[14] * V[12]; - K[4][3] = C[10] * V[6] + C[11] * V[7] + C[12] * V[8] + C[13] * V[9] + C[14] * V[13]; - K[4][4] = C[10] * V[10] + C[11] * V[11] + C[12] * V[12] + C[13] * V[13] + C[14] * V[14]; -} - -void L1Algo::MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15]) -{ - K[0] = C[0][0] * V[0] + C[0][1] * V[1] + C[0][2] * V[3] + C[0][3] * V[6] + C[0][4] * V[10]; - - K[1] = C[1][0] * V[0] + C[1][1] * V[1] + C[1][2] * V[3] + C[1][3] * V[6] + C[1][4] * V[10]; - K[2] = C[1][0] * V[1] + C[1][1] * V[2] + C[1][2] * V[4] + C[1][3] * V[7] + C[1][4] * V[11]; - - K[3] = C[2][0] * V[0] + C[2][1] * V[1] + C[2][2] * V[3] + C[2][3] * V[6] + C[2][4] * V[10]; - K[4] = C[2][0] * V[1] + C[2][1] * V[2] + C[2][2] * V[4] + C[2][3] * V[7] + C[2][4] * V[11]; - K[5] = C[2][0] * V[3] + C[2][1] * V[4] + C[2][2] * V[5] + C[2][3] * V[8] + C[2][4] * V[12]; - - K[6] = C[3][0] * V[0] + C[3][1] * V[1] + C[3][2] * V[3] + C[3][3] * V[6] + C[3][4] * V[10]; - K[7] = C[3][0] * V[1] + C[3][1] * V[2] + C[3][2] * V[4] + C[3][3] * V[7] + C[3][4] * V[11]; - K[8] = C[3][0] * V[3] + C[3][1] * V[4] + C[3][2] * V[5] + C[3][3] * V[8] + C[3][4] * V[12]; - K[9] = C[3][0] * V[6] + C[3][1] * V[7] + C[3][2] * V[8] + C[3][3] * V[9] + C[3][4] * V[13]; - - K[10] = C[4][0] * V[0] + C[4][1] * V[1] + C[4][2] * V[3] + C[4][3] * V[6] + C[4][4] * V[10]; - K[11] = C[4][0] * V[1] + C[4][1] * V[2] + C[4][2] * V[4] + C[4][3] * V[7] + C[4][4] * V[11]; - K[12] = C[4][0] * V[3] + C[4][1] * V[4] + C[4][2] * V[5] + C[4][3] * V[8] + C[4][4] * V[12]; - K[13] = C[4][0] * V[6] + C[4][1] * V[7] + C[4][2] * V[8] + C[4][3] * V[9] + C[4][4] * V[13]; - K[14] = C[4][0] * V[10] + C[4][1] * V[11] + C[4][2] * V[12] + C[4][3] * V[13] + C[4][4] * V[14]; -} - -void L1Algo::MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[5]) -{ - r_out[0] = r_in[0] * C[0] + r_in[1] * C[1] + r_in[2] * C[3] + r_in[3] * C[6] + r_in[4] * C[10]; - r_out[1] = r_in[0] * C[1] + r_in[1] * C[2] + r_in[2] * C[4] + r_in[3] * C[7] + r_in[4] * C[11]; - r_out[2] = r_in[0] * C[3] + r_in[1] * C[4] + r_in[2] * C[5] + r_in[3] * C[8] + r_in[4] * C[12]; - r_out[3] = r_in[0] * C[6] + r_in[1] * C[7] + r_in[2] * C[8] + r_in[3] * C[9] + r_in[4] * C[13]; - r_out[4] = r_in[0] * C[10] + r_in[1] * C[11] + r_in[2] * C[12] + r_in[3] * C[13] + r_in[4] * C[14]; -} - -void L1Algo::FilterTracks(fvec const r[5], fvec const C[15], fvec const m[5], fvec const V[15], fvec R[5], fvec W[15], - fvec* chi2) -{ - fvec S[15]; - for (int i = 0; i < 15; i++) { - if (W) W[i] = C[i]; - S[i] = C[i] + V[i]; - } - - InvertCholetsky(S); - - fvec dzeta[5]; - - for (int i = 0; i < 5; i++) - dzeta[i] = m[i] - r[i]; - - if (W && R) { - for (int i = 0; i < 5; i++) - R[i] = r[i]; - - fvec K[5][5]; - MultiplySS(C, S, K); - - fvec KC[15]; - MultiplyMS(K, C, KC); - for (int i = 0; i < 15; i++) - W[i] -= KC[i]; - - fvec kd; - for (int i = 0; i < 5; i++) { - kd = 0.f; - for (int j = 0; j < 5; j++) - kd += K[i][j] * dzeta[j]; - R[i] += kd; - } - } - if (chi2) { - fvec S_dzeta[5]; - MultiplySR(S, dzeta, S_dzeta); - *chi2 = dzeta[0] * S_dzeta[0] + dzeta[1] * S_dzeta[1] + dzeta[2] * S_dzeta[2] + dzeta[3] * S_dzeta[3] - + dzeta[4] * S_dzeta[4]; - } -} +// --------------------------------------------------------------------------------------------------------------------- +// +L1ClonesMerger::~L1ClonesMerger() {} -void L1Algo::CAMergeClones() +// --------------------------------------------------------------------------------------------------------------------- +// +void L1ClonesMerger::Exec(L1Vector<L1Track>& extTracks, L1Vector<L1HitIndex_t>& extRecoHits) { + L1Vector<unsigned short>& firstStation = fTrackFirstStation; + L1Vector<unsigned short>& lastStation = fTrackLastStation; + L1Vector<L1HitIndex_t>& firstHit = fTrackFirstHit; + L1Vector<L1HitIndex_t>& lastHit = fTrackLastHit; + L1Vector<unsigned short>& neighbour = fTrackNeighbour; + L1Vector<float>& trackChi2 = fTrackChi2; + L1Vector<char>& isStored = fTrackIsStored; + L1Vector<char>& isDownstreamNeighbour = fTrackIsDownstreamNeighbour; - L1Vector<unsigned short>& firstStation = fMergerTrackFirstStation; - L1Vector<unsigned short>& lastStation = fMergerTrackLastStation; - L1Vector<L1HitIndex_t>& firstHit = fMergerTrackFirstHit; - L1Vector<L1HitIndex_t>& lastHit = fMergerTrackLastHit; - L1Vector<unsigned short>& neighbour = fMergerTrackNeighbour; - L1Vector<float>& trackChi2 = fMergerTrackChi2; - L1Vector<char>& isStored = fMergerTrackIsStored; - L1Vector<char>& isDownstreamNeighbour = fMergerTrackIsDownstreamNeighbour; - - int nTracks = fTracks.size(); + int nTracks = extTracks.size(); assert(nTracks < std::numeric_limits<unsigned short>::max()); constexpr unsigned short kNoNeighbour = std::numeric_limits<unsigned short>::max(); - // vector< L1Track > vTracksNew; - fMergerTracksNew.clear(); - fMergerTracksNew.reserve(nTracks); - // vector< L1HitIndex_t > fRecoHitsNew; - fMergerRecoHitsNew.clear(); - fMergerRecoHitsNew.reserve(fRecoHits.size()); + fTracksNew.clear(); + fTracksNew.reserve(nTracks); + fRecoHitsNew.clear(); + fRecoHitsNew.reserve(extRecoHits.size()); firstStation.reset(nTracks); lastStation.reset(nTracks); @@ -240,10 +64,10 @@ void L1Algo::CAMergeClones() #endif for (int iTr = 0; iTr < nTracks; iTr++) { firstHit[iTr] = start_hit; - firstStation[iTr] = (*fStripFlag)[(*vHits)[fRecoHits[start_hit]].f] / 4; - start_hit += fTracks[iTr].NHits - 1; + firstStation[iTr] = (*frAlgo.fStripFlag)[(*frAlgo.vHits)[extRecoHits[start_hit]].f] / 4; + start_hit += extTracks[iTr].NHits - 1; lastHit[iTr] = start_hit; - lastStation[iTr] = (*fStripFlag)[(*vHits)[fRecoHits[start_hit]].f] / 4; + lastStation[iTr] = (*frAlgo.fStripFlag)[(*frAlgo.vHits)[extRecoHits[start_hit]].f] / 4; start_hit++; isStored[iTr] = false; @@ -252,103 +76,92 @@ void L1Algo::CAMergeClones() isDownstreamNeighbour[iTr] = false; } - L1KFTrackFitter(); - //KFTrackFitter_simple(); - L1TrackPar Tb; L1TrackPar Tf; L1FieldValue fBm, fBb, fBf _fvecalignment; L1FieldRegion fld _fvecalignment; - unsigned char maxLengthForMerge = static_cast<unsigned char>(fNstations - 3); // max length for merge + // Max length for merging + unsigned char maxLengthForMerge = static_cast<unsigned char>(frAlgo.GetParameters()->GetNstationsActive() - 3); #ifdef OMP #pragma omp parallel for #endif for (int iTr = 0; iTr < nTracks; iTr++) { - if (fTracks[iTr].NHits > maxLengthForMerge) continue; + if (extTracks[iTr].NHits > maxLengthForMerge) continue; for (int jTr = 0; jTr < nTracks; jTr++) { - if (fTracks[jTr].NHits > maxLengthForMerge) continue; + if (extTracks[jTr].NHits > maxLengthForMerge) continue; if (iTr == jTr) continue; if (firstStation[iTr] <= lastStation[jTr]) continue; - // if(vTracks[iTr].n != vTracks[jTr].n) continue; - // if (fabs(vTracks[iTr].fTrackTime - vTracks[jTr].fTrackTime) > 3) continue; - - //if((vTracks[iTr].TFirst[4] - vTracks[jTr].TFirst[4])*(vTracks[iTr].TFirst[4] - vTracks[jTr].TFirst[4]) - // > 9*(vTracks[iTr].CFirst[14]+vTracks[jTr].CFirst[14]) ) continue; - unsigned short stab = firstStation[iTr]; - Tb.x = fTracks[iTr].TFirst[0]; - Tb.y = fTracks[iTr].TFirst[1]; - Tb.tx = fTracks[iTr].TFirst[2]; - Tb.ty = fTracks[iTr].TFirst[3]; - Tb.qp = fTracks[iTr].TFirst[4]; - Tb.z = fTracks[iTr].TFirst[5]; - Tb.t = fTracks[iTr].TFirst[6]; - Tb.C00 = fTracks[iTr].CFirst[0]; - Tb.C10 = fTracks[iTr].CFirst[1]; - Tb.C11 = fTracks[iTr].CFirst[2]; - Tb.C20 = fTracks[iTr].CFirst[3]; - Tb.C21 = fTracks[iTr].CFirst[4]; - Tb.C22 = fTracks[iTr].CFirst[5]; - Tb.C30 = fTracks[iTr].CFirst[6]; - Tb.C31 = fTracks[iTr].CFirst[7]; - Tb.C32 = fTracks[iTr].CFirst[8]; - Tb.C33 = fTracks[iTr].CFirst[9]; - Tb.C40 = fTracks[iTr].CFirst[10]; - Tb.C41 = fTracks[iTr].CFirst[11]; - Tb.C42 = fTracks[iTr].CFirst[12]; - Tb.C43 = fTracks[iTr].CFirst[13]; - Tb.C44 = fTracks[iTr].CFirst[14]; - Tb.C50 = fTracks[iTr].CFirst[15]; - Tb.C51 = fTracks[iTr].CFirst[16]; - Tb.C52 = fTracks[iTr].CFirst[17]; - Tb.C53 = fTracks[iTr].CFirst[18]; - Tb.C54 = fTracks[iTr].CFirst[19]; - Tb.C55 = fTracks[iTr].CFirst[20]; + Tb.x = extTracks[iTr].TFirst[0]; + Tb.y = extTracks[iTr].TFirst[1]; + Tb.tx = extTracks[iTr].TFirst[2]; + Tb.ty = extTracks[iTr].TFirst[3]; + Tb.qp = extTracks[iTr].TFirst[4]; + Tb.z = extTracks[iTr].TFirst[5]; + Tb.t = extTracks[iTr].TFirst[6]; + Tb.C00 = extTracks[iTr].CFirst[0]; + Tb.C10 = extTracks[iTr].CFirst[1]; + Tb.C11 = extTracks[iTr].CFirst[2]; + Tb.C20 = extTracks[iTr].CFirst[3]; + Tb.C21 = extTracks[iTr].CFirst[4]; + Tb.C22 = extTracks[iTr].CFirst[5]; + Tb.C30 = extTracks[iTr].CFirst[6]; + Tb.C31 = extTracks[iTr].CFirst[7]; + Tb.C32 = extTracks[iTr].CFirst[8]; + Tb.C33 = extTracks[iTr].CFirst[9]; + Tb.C40 = extTracks[iTr].CFirst[10]; + Tb.C41 = extTracks[iTr].CFirst[11]; + Tb.C42 = extTracks[iTr].CFirst[12]; + Tb.C43 = extTracks[iTr].CFirst[13]; + Tb.C44 = extTracks[iTr].CFirst[14]; + Tb.C50 = extTracks[iTr].CFirst[15]; + Tb.C51 = extTracks[iTr].CFirst[16]; + Tb.C52 = extTracks[iTr].CFirst[17]; + Tb.C53 = extTracks[iTr].CFirst[18]; + Tb.C54 = extTracks[iTr].CFirst[19]; + Tb.C55 = extTracks[iTr].CFirst[20]; unsigned short staf = lastStation[jTr]; - Tf.x = fTracks[jTr].TLast[0]; - Tf.y = fTracks[jTr].TLast[1]; - Tf.tx = fTracks[jTr].TLast[2]; - Tf.ty = fTracks[jTr].TLast[3]; - Tf.qp = fTracks[jTr].TLast[4]; - Tf.z = fTracks[jTr].TLast[5]; - Tf.t = fTracks[jTr].TLast[6]; - Tf.C00 = fTracks[jTr].CLast[0]; - Tf.C10 = fTracks[jTr].CLast[1]; - Tf.C11 = fTracks[jTr].CLast[2]; - Tf.C20 = fTracks[jTr].CLast[3]; - Tf.C21 = fTracks[jTr].CLast[4]; - Tf.C22 = fTracks[jTr].CLast[5]; - Tf.C30 = fTracks[jTr].CLast[6]; - Tf.C31 = fTracks[jTr].CLast[7]; - Tf.C32 = fTracks[jTr].CLast[8]; - Tf.C33 = fTracks[jTr].CLast[9]; - Tf.C40 = fTracks[jTr].CLast[10]; - Tf.C41 = fTracks[jTr].CLast[11]; - Tf.C42 = fTracks[jTr].CLast[12]; - Tf.C43 = fTracks[jTr].CLast[13]; - Tf.C44 = fTracks[jTr].CLast[14]; - Tf.C50 = fTracks[jTr].CLast[15]; - Tf.C51 = fTracks[jTr].CLast[16]; - Tf.C52 = fTracks[jTr].CLast[17]; - Tf.C53 = fTracks[jTr].CLast[18]; - Tf.C54 = fTracks[jTr].CLast[19]; - Tf.C55 = fTracks[jTr].CLast[20]; - - //std::cout << "!!!!!!! Chi2 !!!!!! "<<fTracks[iTr].TFirst[0]<<" "<<fTracks[jTr].TLast[0]<<std::endl; - - //if(((Tf.qp - Tb.qp)*(Tf.qp - Tb.qp)/(Tb.C44+Tf.C44))[0] > 25*10*7) continue; + Tf.x = extTracks[jTr].TLast[0]; + Tf.y = extTracks[jTr].TLast[1]; + Tf.tx = extTracks[jTr].TLast[2]; + Tf.ty = extTracks[jTr].TLast[3]; + Tf.qp = extTracks[jTr].TLast[4]; + Tf.z = extTracks[jTr].TLast[5]; + Tf.t = extTracks[jTr].TLast[6]; + Tf.C00 = extTracks[jTr].CLast[0]; + Tf.C10 = extTracks[jTr].CLast[1]; + Tf.C11 = extTracks[jTr].CLast[2]; + Tf.C20 = extTracks[jTr].CLast[3]; + Tf.C21 = extTracks[jTr].CLast[4]; + Tf.C22 = extTracks[jTr].CLast[5]; + Tf.C30 = extTracks[jTr].CLast[6]; + Tf.C31 = extTracks[jTr].CLast[7]; + Tf.C32 = extTracks[jTr].CLast[8]; + Tf.C33 = extTracks[jTr].CLast[9]; + Tf.C40 = extTracks[jTr].CLast[10]; + Tf.C41 = extTracks[jTr].CLast[11]; + Tf.C42 = extTracks[jTr].CLast[12]; + Tf.C43 = extTracks[jTr].CLast[13]; + Tf.C44 = extTracks[jTr].CLast[14]; + Tf.C50 = extTracks[jTr].CLast[15]; + Tf.C51 = extTracks[jTr].CLast[16]; + Tf.C52 = extTracks[jTr].CLast[17]; + Tf.C53 = extTracks[jTr].CLast[18]; + Tf.C54 = extTracks[jTr].CLast[19]; + Tf.C55 = extTracks[jTr].CLast[20]; + + if (fabs(Tf.t[0] - Tb.t[0]) > 3 * sqrt(Tf.C55[0] + Tb.C55[0])) continue; - // if (fabs (Tf.time[0] - Tb.time[0]) > 500000) continue; unsigned short stam; - fParameters.GetStation(staf).fieldSlice.GetFieldValue(Tf.x, Tf.y, fBf); - fParameters.GetStation(stab).fieldSlice.GetFieldValue(Tb.x, Tb.y, fBb); + frAlgo.GetParameters()->GetStation(staf).fieldSlice.GetFieldValue(Tf.x, Tf.y, fBf); + frAlgo.GetParameters()->GetStation(stab).fieldSlice.GetFieldValue(Tb.x, Tb.y, fBb); unsigned short dist = firstStation[iTr] - lastStation[jTr]; @@ -356,10 +169,10 @@ void L1Algo::CAMergeClones() else stam = staf - 1; - fvec zm = fParameters.GetStation(stam).z; + fvec zm = frAlgo.GetParameters()->GetStation(stam).z; fvec xm = 0.5 * (Tf.x + Tf.tx * (zm - Tf.z) + Tb.x + Tb.tx * (zm - Tb.z)); fvec ym = 0.5 * (Tf.y + Tf.ty * (zm - Tf.z) + Tb.y + Tb.ty * (zm - Tb.z)); - fParameters.GetStation(stam).fieldSlice.GetFieldValue(xm, ym, fBm); + frAlgo.GetParameters()->GetStation(stam).fieldSlice.GetFieldValue(xm, ym, fBm); fld.Set(fBb, Tb.z, fBm, zm, fBf, Tf.z); fvec zMiddle = 0.5 * (Tb.z + Tf.z); @@ -395,39 +208,211 @@ void L1Algo::CAMergeClones() for (int iTr = 0; iTr < nTracks; iTr++) { if (isStored[iTr]) continue; - fMergerTracksNew.push_back(fTracks[iTr]); + fTracksNew.push_back(extTracks[iTr]); if (!isDownstreamNeighbour[iTr]) { for (L1HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) { - fMergerRecoHitsNew.push_back(fRecoHits[HI]); + fRecoHitsNew.push_back(extRecoHits[HI]); } } if (neighbour[iTr] < kNoNeighbour) { isStored[neighbour[iTr]] = true; - fMergerTracksNew.back().NHits += fTracks[neighbour[iTr]].NHits; + fTracksNew.back().NHits += extTracks[neighbour[iTr]].NHits; for (L1HitIndex_t HI = firstHit[neighbour[iTr]]; HI <= lastHit[neighbour[iTr]]; HI++) - fMergerRecoHitsNew.push_back(fRecoHits[HI]); + fRecoHitsNew.push_back(extRecoHits[HI]); } if (isDownstreamNeighbour[iTr]) { for (L1HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) { - fMergerRecoHitsNew.push_back(fRecoHits[HI]); + fRecoHitsNew.push_back(extRecoHits[HI]); } } } - fTracks.reset(fMergerTracksNew.size()); - for (unsigned int iTr = 0; iTr < fMergerTracksNew.size(); iTr++) { - fTracks[iTr] = fMergerTracksNew[iTr]; + // Save the merging results into external vectors + extTracks = std::move(fTracksNew); + extRecoHits = std::move(fRecoHitsNew); +} + +// --------------------------------------------------------------------------------------------------------------------- +// +void L1ClonesMerger::FilterTracks(fvec const r[5], fvec const C[15], fvec const m[5], fvec const V[15], fvec R[5], + fvec W[15], fvec* chi2) +{ + fvec S[15]; + for (int i = 0; i < 15; i++) { + if (W) W[i] = C[i]; + S[i] = C[i] + V[i]; + } + + InvertCholesky(S); + + fvec dzeta[5]; + + for (int i = 0; i < 5; i++) + dzeta[i] = m[i] - r[i]; + + if (W && R) { + for (int i = 0; i < 5; i++) + R[i] = r[i]; + + fvec K[5][5]; + MultiplySS(C, S, K); + + fvec KC[15]; + MultiplyMS(K, C, KC); + for (int i = 0; i < 15; i++) + W[i] -= KC[i]; + + fvec kd; + for (int i = 0; i < 5; i++) { + kd = 0.f; + for (int j = 0; j < 5; j++) + kd += K[i][j] * dzeta[j]; + R[i] += kd; + } + } + if (chi2) { + fvec S_dzeta[5]; + MultiplySR(S, dzeta, S_dzeta); + *chi2 = dzeta[0] * S_dzeta[0] + dzeta[1] * S_dzeta[1] + dzeta[2] * S_dzeta[2] + dzeta[3] * S_dzeta[3] + + dzeta[4] * S_dzeta[4]; + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// +void L1ClonesMerger::InvertCholesky(fvec a[15]) +{ + fvec d[5], uud, u[5][5]; + for (int i = 0; i < 5; i++) { + d[i] = 0.f; + for (int j = 0; j < 5; j++) + u[i][j] = 0.f; } - assert(fRecoHits.size() == fMergerRecoHitsNew.size()); - fRecoHits.reset(fMergerRecoHitsNew.size()); - for (L1HitIndex_t iHi = 0; iHi < fMergerRecoHitsNew.size(); iHi++) { - fRecoHits[iHi] = fMergerRecoHitsNew[iHi]; + for (int i = 0; i < 5; i++) { + uud = 0.f; + for (int j = 0; j < i; j++) + uud += u[j][i] * u[j][i] * d[j]; + uud = a[i * (i + 3) / 2] - uud; + + fvec smallval = 1.e-12; + fvec initialised = fvec(uud < smallval); + uud = ((!initialised) & uud) + (smallval & initialised); + + d[i] = uud / fabs(uud); + u[i][i] = sqrt(fabs(uud)); + + for (int j = i + 1; j < 5; j++) { + uud = 0.f; + for (int k = 0; k < i; k++) + uud += u[k][i] * u[k][j] * d[k]; + uud = a[j * (j + 1) / 2 + i] /*a[i][j]*/ - uud; + u[i][j] = d[i] / u[i][i] * uud; + } } - NHitsIsecAll = fMergerRecoHitsNew.size(); + fvec u1[5]; - //std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!! new "<<vTracksNew.size()<<" old "<< vTracks.size()<<std::endl; + for (int i = 0; i < 5; i++) { + u1[i] = u[i][i]; + u[i][i] = 1.f / u[i][i]; + } + for (int i = 0; i < 4; i++) { + u[i][i + 1] = -u[i][i + 1] * u[i][i] * u[i + 1][i + 1]; + } + for (int i = 0; i < 3; i++) { + u[i][i + 2] = u[i][i + 1] * u1[i + 1] * u[i + 1][i + 2] - u[i][i + 2] * u[i][i] * u[i + 2][i + 2]; + } + for (int i = 0; i < 2; i++) { + u[i][i + 3] = u[i][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i][i + 3] * u[i][i] * u[i + 3][i + 3]; + u[i][i + 3] -= u[i][i + 1] * u1[i + 1] * (u[i + 1][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i + 1][i + 3]); + } + u[0][4] = u[0][2] * u1[2] * u[2][4] - u[0][4] * u[0][0] * u[4][4]; + u[0][4] += u[0][1] * u1[1] * (u[1][4] - u[1][3] * u1[3] * u[3][4] - u[1][2] * u1[2] * u[2][4]); + u[0][4] += u[3][4] * u1[3] * (u[0][3] - u1[2] * u[2][3] * (u[0][2] - u[0][1] * u1[1] * u[1][2])); + + for (int i = 0; i < 5; i++) + a[i + 10] = u[i][4] * d[4] * u[4][4]; + for (int i = 0; i < 4; i++) + a[i + 6] = u[i][3] * u[3][3] * d[3] + u[i][4] * u[3][4] * d[4]; + for (int i = 0; i < 3; i++) + a[i + 3] = u[i][2] * u[2][2] * d[2] + u[i][3] * u[2][3] * d[3] + u[i][4] * u[2][4] * d[4]; + for (int i = 0; i < 2; i++) + a[i + 1] = + u[i][1] * u[1][1] * d[1] + u[i][2] * u[1][2] * d[2] + u[i][3] * u[1][3] * d[3] + u[i][4] * u[1][4] * d[4]; + a[0] = u[0][0] * u[0][0] * d[0] + u[0][1] * u[0][1] * d[1] + u[0][2] * u[0][2] * d[2] + u[0][3] * u[0][3] * d[3] + + u[0][4] * u[0][4] * d[4]; +} + +// --------------------------------------------------------------------------------------------------------------------- +// +void L1ClonesMerger::MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15]) +{ + K[0] = C[0][0] * V[0] + C[0][1] * V[1] + C[0][2] * V[3] + C[0][3] * V[6] + C[0][4] * V[10]; + + K[1] = C[1][0] * V[0] + C[1][1] * V[1] + C[1][2] * V[3] + C[1][3] * V[6] + C[1][4] * V[10]; + K[2] = C[1][0] * V[1] + C[1][1] * V[2] + C[1][2] * V[4] + C[1][3] * V[7] + C[1][4] * V[11]; + + K[3] = C[2][0] * V[0] + C[2][1] * V[1] + C[2][2] * V[3] + C[2][3] * V[6] + C[2][4] * V[10]; + K[4] = C[2][0] * V[1] + C[2][1] * V[2] + C[2][2] * V[4] + C[2][3] * V[7] + C[2][4] * V[11]; + K[5] = C[2][0] * V[3] + C[2][1] * V[4] + C[2][2] * V[5] + C[2][3] * V[8] + C[2][4] * V[12]; + + K[6] = C[3][0] * V[0] + C[3][1] * V[1] + C[3][2] * V[3] + C[3][3] * V[6] + C[3][4] * V[10]; + K[7] = C[3][0] * V[1] + C[3][1] * V[2] + C[3][2] * V[4] + C[3][3] * V[7] + C[3][4] * V[11]; + K[8] = C[3][0] * V[3] + C[3][1] * V[4] + C[3][2] * V[5] + C[3][3] * V[8] + C[3][4] * V[12]; + K[9] = C[3][0] * V[6] + C[3][1] * V[7] + C[3][2] * V[8] + C[3][3] * V[9] + C[3][4] * V[13]; + + K[10] = C[4][0] * V[0] + C[4][1] * V[1] + C[4][2] * V[3] + C[4][3] * V[6] + C[4][4] * V[10]; + K[11] = C[4][0] * V[1] + C[4][1] * V[2] + C[4][2] * V[4] + C[4][3] * V[7] + C[4][4] * V[11]; + K[12] = C[4][0] * V[3] + C[4][1] * V[4] + C[4][2] * V[5] + C[4][3] * V[8] + C[4][4] * V[12]; + K[13] = C[4][0] * V[6] + C[4][1] * V[7] + C[4][2] * V[8] + C[4][3] * V[9] + C[4][4] * V[13]; + K[14] = C[4][0] * V[10] + C[4][1] * V[11] + C[4][2] * V[12] + C[4][3] * V[13] + C[4][4] * V[14]; +} + +// --------------------------------------------------------------------------------------------------------------------- +// +void L1ClonesMerger::MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[5]) +{ + r_out[0] = r_in[0] * C[0] + r_in[1] * C[1] + r_in[2] * C[3] + r_in[3] * C[6] + r_in[4] * C[10]; + r_out[1] = r_in[0] * C[1] + r_in[1] * C[2] + r_in[2] * C[4] + r_in[3] * C[7] + r_in[4] * C[11]; + r_out[2] = r_in[0] * C[3] + r_in[1] * C[4] + r_in[2] * C[5] + r_in[3] * C[8] + r_in[4] * C[12]; + r_out[3] = r_in[0] * C[6] + r_in[1] * C[7] + r_in[2] * C[8] + r_in[3] * C[9] + r_in[4] * C[13]; + r_out[4] = r_in[0] * C[10] + r_in[1] * C[11] + r_in[2] * C[12] + r_in[3] * C[13] + r_in[4] * C[14]; +} + +// --------------------------------------------------------------------------------------------------------------------- +// +void L1ClonesMerger::MultiplySS(fvec const C[15], fvec const V[15], fvec K[5][5]) +{ + K[0][0] = C[0] * V[0] + C[1] * V[1] + C[3] * V[3] + C[6] * V[6] + C[10] * V[10]; + K[0][1] = C[0] * V[1] + C[1] * V[2] + C[3] * V[4] + C[6] * V[7] + C[10] * V[11]; + K[0][2] = C[0] * V[3] + C[1] * V[4] + C[3] * V[5] + C[6] * V[8] + C[10] * V[12]; + K[0][3] = C[0] * V[6] + C[1] * V[7] + C[3] * V[8] + C[6] * V[9] + C[10] * V[13]; + K[0][4] = C[0] * V[10] + C[1] * V[11] + C[3] * V[12] + C[6] * V[13] + C[10] * V[14]; + + K[1][0] = C[1] * V[0] + C[2] * V[1] + C[4] * V[3] + C[7] * V[6] + C[11] * V[10]; + K[1][1] = C[1] * V[1] + C[2] * V[2] + C[4] * V[4] + C[7] * V[7] + C[11] * V[11]; + K[1][2] = C[1] * V[3] + C[2] * V[4] + C[4] * V[5] + C[7] * V[8] + C[11] * V[12]; + K[1][3] = C[1] * V[6] + C[2] * V[7] + C[4] * V[8] + C[7] * V[9] + C[11] * V[13]; + K[1][4] = C[1] * V[10] + C[2] * V[11] + C[4] * V[12] + C[7] * V[13] + C[11] * V[14]; + + K[2][0] = C[3] * V[0] + C[4] * V[1] + C[5] * V[3] + C[8] * V[6] + C[12] * V[10]; + K[2][1] = C[3] * V[1] + C[4] * V[2] + C[5] * V[4] + C[8] * V[7] + C[12] * V[11]; + K[2][2] = C[3] * V[3] + C[4] * V[4] + C[5] * V[5] + C[8] * V[8] + C[12] * V[12]; + K[2][3] = C[3] * V[6] + C[4] * V[7] + C[5] * V[8] + C[8] * V[9] + C[12] * V[13]; + K[2][4] = C[3] * V[10] + C[4] * V[11] + C[5] * V[12] + C[8] * V[13] + C[12] * V[14]; + + K[3][0] = C[6] * V[0] + C[7] * V[1] + C[8] * V[3] + C[9] * V[6] + C[13] * V[10]; + K[3][1] = C[6] * V[1] + C[7] * V[2] + C[8] * V[4] + C[9] * V[7] + C[13] * V[11]; + K[3][2] = C[6] * V[3] + C[7] * V[4] + C[8] * V[5] + C[9] * V[8] + C[13] * V[12]; + K[3][3] = C[6] * V[6] + C[7] * V[7] + C[8] * V[8] + C[9] * V[9] + C[13] * V[13]; + K[3][4] = C[6] * V[10] + C[7] * V[11] + C[8] * V[12] + C[9] * V[13] + C[13] * V[14]; + + K[4][0] = C[10] * V[0] + C[11] * V[1] + C[12] * V[3] + C[13] * V[6] + C[14] * V[10]; + K[4][1] = C[10] * V[1] + C[11] * V[2] + C[12] * V[4] + C[13] * V[7] + C[14] * V[11]; + K[4][2] = C[10] * V[3] + C[11] * V[4] + C[12] * V[5] + C[13] * V[8] + C[14] * V[12]; + K[4][3] = C[10] * V[6] + C[11] * V[7] + C[12] * V[8] + C[13] * V[9] + C[14] * V[13]; + K[4][4] = C[10] * V[10] + C[11] * V[11] + C[12] * V[12] + C[13] * V[13] + C[14] * V[14]; } diff --git a/reco/L1/L1Algo/L1ClonesMerger.h b/reco/L1/L1Algo/L1ClonesMerger.h new file mode 100644 index 0000000000..9b76aefdfa --- /dev/null +++ b/reco/L1/L1Algo/L1ClonesMerger.h @@ -0,0 +1,119 @@ +/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer], Maksym Zyzak */ + +/// \file L1ClonesMerger.h +/// \authors S.Zharko <s.zharko@gsi.de> (interface), M.Zyzak (original algorithm) +/// \brief A class wrapper over clones merger algorithm for the L1 track finder (declaration) +/// \since 22.07.2022 + +#ifndef L1ClonesMerger_h +#define L1ClonesMerger_h 1 + +#include "L1Hit.h" // For L1HitIndex_t +#include "L1Vector.h" +#include "vectors/P4_F32vec4.h" + +class L1Track; +class L1Algo; + +/// Class implements a clones merger algorithm for the CA (L1) track finder +/// +class L1ClonesMerger { +public: + /// Default constructor + L1ClonesMerger(const L1Algo& algo); + + /// Destructor + ~L1ClonesMerger(); + + /// Copy constructor + L1ClonesMerger(const L1ClonesMerger&) = delete; + + /// Move constructor + L1ClonesMerger(L1ClonesMerger&&) = delete; + + /// Copy assignment operator + L1ClonesMerger& operator=(const L1ClonesMerger&) = delete; + + /// Move assignment operator + L1ClonesMerger& operator=(L1ClonesMerger&&) = delete; + + /// Registers + + /// Executes track clones merging algorithm and updates input containers + /// \param extTracks Reference to the external container of reconstructed tracks + /// \param extRecoHits Reference to the external container of reconstructed hit indexes + void Exec(L1Vector<L1Track>& extTracks, L1Vector<L1HitIndex_t>&); + +private: + // *************** + // ** Functions ** + // *************** + + /// + static void InvertCholesky(fvec a[15]); + + /// Multiplication of two symmetric matryces 5x5 + /// \param C Left matrix: + /// C[0] C[1] C[3] C[6] C[10] + /// C[1] C[2] C[4] C[7] C[11] + /// C = C[3] C[4] C[5] C[8] C[12] + /// C[6] C[7] C[8] C[9] C[13] + /// C[10] C[11] C[12] C[13] C[14] + /// \param V Right matrix: + /// V[0] V[1] V[3] V[6] V[10] + /// V[1] V[2] V[4] V[7] V[11] + /// V = V[3] V[4] V[5] V[8] V[12] + /// V[6] V[7] V[8] V[9] V[13] + /// V[10] V[11] V[12] V[13] V[14] + /// \param K Output: K = C * V + static void MultiplySS(fvec const C[15], fvec const V[15], fvec K[5][5]); + + /// + static void MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15]); + + /// + static void MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[5]); + + /// + static void FilterTracks(fvec const r[5], fvec const C[15], fvec const m[5], fvec const V[15], fvec R[5], fvec W[15], + fvec* chi2); + + + // *************** + // ** Variables ** + // *************** + + /// First station of a track + L1Vector<unsigned short> fTrackFirstStation {"L1ClonesMerger::fTrackFirstStation"}; + + /// Last station of a track + L1Vector<unsigned short> fTrackLastStation {"L1ClonesMerger::fTrackLastStation"}; + + /// Index of the first hit of a track + L1Vector<L1HitIndex_t> fTrackFirstHit {"L1ClonesMerger::fTrackFirstHit"}; + + /// Index of the last hit of a track + L1Vector<L1HitIndex_t> fTrackLastHit {"L1ClonesMerger::fTrackLastHit"}; + + /// Index (TODO:??) of a track that can be merge with the given track + L1Vector<unsigned short> fTrackNeighbour {"L1ClonesMerger::fTrackNeighbour"}; + + /// Chi2 value of the track merging procedure + L1Vector<float> fTrackChi2 {"L1ClonesMerger::fTrackChi2"}; + + /// Flag: is the given track already stored to the output + L1Vector<char> fTrackIsStored {"L1ClonesMerger::fTrackIsStored"}; + + /// Flag: is the track a downstream neighbour of another track + L1Vector<char> fTrackIsDownstreamNeighbour {"L1ClonesMerger::fTrackIsDownstreamNeighbour"}; + + L1Vector<L1Track> fTracksNew {"L1CAMergerClones::fTracksNew"}; ///< vector of tracks after the merge + + L1Vector<L1HitIndex_t> fRecoHitsNew {"L1CAMergerClones::fRecoHitsNew"}; ///< vector of track hits after the merge + + const L1Algo& frAlgo; ///< Reference to the main track finder algorithm class +}; + +#endif // L1ClonesMerger_h diff --git a/reco/L1/L1Algo/L1Track.h b/reco/L1/L1Algo/L1Track.h index 584d4b2338..21c4bc93af 100644 --- a/reco/L1/L1Algo/L1Track.h +++ b/reco/L1/L1Algo/L1Track.h @@ -31,24 +31,24 @@ class L1Track { public: static constexpr float kNaN {std::numeric_limits<float>::signaling_NaN()}; - unsigned char NHits; ///> Number of hits in track - unsigned char n; ///> TODO: ?? - float Momentum {kNaN}; ///> TODO: ?? - float fTrackTime {kNaN}; ///> Track time - fscal TFirst[7] {kNaN}; ///> Track parameters on the first station - fscal CFirst[21] {kNaN}; ///> Track parameter covariation matrix elemenst on the first station - fscal TLast[7] {kNaN}; ///> Track parameters on the last station - fscal CLast[21] {kNaN}; ///> Track parameter covatiation matrix elements on the second station - fscal Tpv[7] {kNaN}; ///> Track parameters in the primary vertex - fscal Cpv[21] {kNaN}; ///> Track parameter covariation matrix elements in the primary vertex - fscal chi2 {kNaN}; ///> Track fit chi-square value - short int NDF; ///> Track fit NDF value + unsigned char NHits; ///< Number of hits in track + unsigned char n; ///< TODO: ?? + float Momentum {kNaN}; ///< TODO: ?? + float fTrackTime {kNaN}; ///< Track time + fscal TFirst[7] {kNaN}; ///< Track parameters on the first station + fscal CFirst[21] {kNaN}; ///< Track parameter covariation matrix elemenst on the first station + fscal TLast[7] {kNaN}; ///< Track parameters on the last station + fscal CLast[21] {kNaN}; ///< Track parameter covatiation matrix elements on the second station + fscal Tpv[7] {kNaN}; ///< Track parameters in the primary vertex + fscal Cpv[21] {kNaN}; ///< Track parameter covariation matrix elements in the primary vertex + fscal chi2 {kNaN}; ///< Track fit chi-square value + short int NDF; ///< Track fit NDF value // TODO: shouldn't it be the L1HitIndex_t type instead of int? (S.Zharko) - int FirstHitIndex; ///> Track first hit index in the hits vector - int LastHitIndex; ///> Track last hit index in the hits vector - int index; ///> Index of the track - int ista; ///> TODO: ?? + int FirstHitIndex; ///< Track first hit index in the hits vector + int LastHitIndex; ///< Track last hit index in the hits vector + int index; ///< Index of the track + int ista; ///< TODO: ?? /// Provides comparison of two L1Track objects /// If two tracks have different number of hits, the smallest track has the largest number of hits. diff --git a/reco/L1/L1Algo/L1Utils.h b/reco/L1/L1Algo/L1Utils.h index 5f499b28ba..fdd3ba8f9e 100644 --- a/reco/L1/L1Algo/L1Utils.h +++ b/reco/L1/L1Algo/L1Utils.h @@ -10,13 +10,16 @@ #ifndef L1Utils_h #define L1Utils_h 1 -#include <type_traits> +#include <FairLogger.h> + +#include <chrono> #include <iomanip> #include <limits> #include <map> #include <sstream> #include <string> +#include <type_traits> #include <unordered_map> #include <cmath> @@ -28,24 +31,23 @@ #endif /// Class contains some utility functions for L1Algo -struct L1Utils { - +namespace L1Utils +{ /// NaN value for float - static constexpr float kNaN {std::numeric_limits<float>::signaling_NaN()}; + constexpr float kNaN {std::numeric_limits<float>::signaling_NaN()}; /// Comparison method for floats /// \param lhs Left floating point to compare /// \param rhs Right floating point to compare /// \return Comparison result: true - equals within epsilon template<typename T, typename std::enable_if<std::is_floating_point<T>::value, T>::type* = nullptr> - static bool CmpFloats(T lhs, T rhs) + [[gnu::always_inline]] inline bool CmpFloats(T lhs, T rhs) { return fabs(lhs - rhs) < 2. * std::numeric_limits<T>::epsilon() * fabs(lhs + rhs) || fabs(lhs - rhs) < std::numeric_limits<T>::min(); } - - static __attribute__((always_inline)) void CheckSimdVectorEquality(fvec v, const char* name) + [[gnu::always_inline]] inline void CheckSimdVectorEquality(fvec v, const char* name) { if (!v.IsHorizontallyEqual()) { std::stringstream msg; @@ -63,50 +65,24 @@ struct L1Utils { } }; - /// Template function, which sets a value to an element of the map with a particular key - /// \param key Key of the element to be modified - /// \param value New value of the element under the selected key - /// \param aMap A reference to the map, which element is to be modified - template<class Key, class T, class Hash = std::hash<Key>> - static void SetSingleValueToMap(Key key, T value, std::unordered_map<Key, T, Hash>& aMap) - { - aMap[key] = value; - } - - /// Template function, which sets a value to ALL elements of the map - /// \param value New value of the element under the selected key - /// \param aMap A reference to the map, which element is to be modified - template<class Key, class T, class Hash = std::hash<Key>> - static void SetSameValueToMap(T value, std::unordered_map<Key, T, Hash>& aMap) - { - for (auto it = aMap.begin(); it != aMap.end(); ++it) { - it->second = value; - } - } + /// A time profiler for measuring performace of scopes + class TimeProfiler { + public: + /// Constructor + TimeProfiler(const char* scopeName) : fScopeName(scopeName), fStart(std::chrono::high_resolution_clock::now()) {} - /// Template function, which resets the elements of one map with the values defined in another map - /// \param inMap A constant reference to the map containing new parameters - /// \param aMap A reference to the map, which is going to be modified - template<class Key, class T, class Hash = std::hash<Key>> - static void SetMappedValuesToMap(const std::unordered_map<Key, T, Hash>& inMap, - std::unordered_map<Key, T, Hash>& aMap) - { - for (auto it = aMap.begin(); it != aMap.end(); ++it) { - if (inMap.find(it->first) != inMap.end()) { it->second = inMap.at(it->first); } + /// Destructor + ~TimeProfiler() + { + auto stop = std::chrono::high_resolution_clock::now(); + auto time = std::chrono::duration_cast<std::chrono::nanoseconds>(stop - fStart).count(); + LOG(info) << "Scope \033[1;32m" << fScopeName << "\033[0m was executed in " << time << " ns"; } - } - /// Template function to represent mapped contents into std::string - /// NOTE: operator<< must be defined for value of the map - template<class Key, class T, class Hash = std::hash<Key>> - static std::string RepresentMapWithString(const std::unordered_map<Key, T, Hash>& aMap, int entryWidth = 15) - { - std::stringstream token; - for (auto it = aMap.begin(); it != aMap.end(); ++it) { - token << std::setw(entryWidth) << std::setfill(' ') << it->second << ' '; - } - return token.str(); - } -}; + private: + const char* fScopeName {}; + const std::chrono::high_resolution_clock::time_point fStart {}; + }; +} // namespace L1Utils #endif // L1Utils_h -- GitLab