From 1ff4d63b5c0e0c017a0648856c511889012d4cbd Mon Sep 17 00:00:00 2001
From: "se.gorbunov" <se.gorbunov@gsi.de>
Date: Fri, 13 Oct 2023 20:16:03 +0000
Subject: [PATCH] Ca: rewrite L1Branch, move it to /algo

---
 algo/ca/core/CMakeLists.txt             |   1 +
 algo/ca/core/data/CaBranch.h            |  69 ++++++++
 reco/L1/CMakeLists.txt                  |   2 -
 reco/L1/CbmL1.cxx                       |   1 -
 reco/L1/L1Algo/L1Algo.h                 |  17 +-
 reco/L1/L1Algo/L1Branch.h               | 137 ----------------
 reco/L1/L1Algo/L1BranchExtender.cxx     |  34 ++--
 reco/L1/L1Algo/L1CaTrackFinderSlice.cxx | 206 ++++++++++--------------
 8 files changed, 179 insertions(+), 288 deletions(-)
 create mode 100644 algo/ca/core/data/CaBranch.h
 delete mode 100644 reco/L1/L1Algo/L1Branch.h

diff --git a/algo/ca/core/CMakeLists.txt b/algo/ca/core/CMakeLists.txt
index 9af82d63e4..9f0a9e5372 100644
--- a/algo/ca/core/CMakeLists.txt
+++ b/algo/ca/core/CMakeLists.txt
@@ -60,6 +60,7 @@ install(
     data/CaGrid.h
     data/CaGridArea.h
     data/CaTriplet.h
+    data/CaBranch.h
     pars/CaConstants.h
     pars/CaField.h
     pars/CaInitManager.h
diff --git a/algo/ca/core/data/CaBranch.h b/algo/ca/core/data/CaBranch.h
new file mode 100644
index 0000000000..f16537c0df
--- /dev/null
+++ b/algo/ca/core/data/CaBranch.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2007-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Ivan Kisel, Sergey Gorbunov [committer], Maksym Zyzak, Valentina Akishina */
+
+/// @file CaBranch.h
+/// @author Sergey Gorbunov
+
+#pragma once  // include this header only once per compilation unit
+
+#include "CaHit.h"
+#include "CaVector.h"
+
+namespace cbm::algo::ca
+{
+
+  namespace
+  {
+    using namespace cbm::algo;
+  }
+
+  ///  The class describes a combinatorial branch of the CA tracker
+  ///
+  class Branch {
+  public:
+    /// default constructor
+    Branch() { fHits.reserve(25); }
+
+    ///------------------------------
+    /// Setters and getters
+
+    void SetStation(int iStation) { fStation = iStation; }
+    void SetChi2(fscal chi2) { fChi2 = chi2; }
+    void SetId(int Id) { fId = Id; }
+    void SetAlive(bool isAlive) { fIsAlive = isAlive; }
+
+    void AddHit(ca::HitIndex_t hitIndex) { fHits.push_back(hitIndex); }
+    void ResetHits() { fHits.clear(); }
+
+    int NofHits() const { return fHits.size(); }
+    int Station() const { return fStation; }
+    fscal Chi2() const { return fChi2; }
+    int Id() const { return fId; }
+    bool IsAlive() const { return fIsAlive; }
+    const Vector<ca::HitIndex_t>& Hits() const { return fHits; }
+
+    Vector<ca::HitIndex_t>& RefHits() { return fHits; }
+
+    ///------------------------------
+    /// Methods
+
+    bool IsBetterThan(const Branch& b) const
+    {
+      if (NofHits() != b.NofHits()) return (NofHits() > b.NofHits());
+      if (Station() != b.Station()) return (Station() < b.Station());
+      return (Chi2() <= b.Chi2());
+    }
+
+  private:
+    ///------------------------------
+    /// Data members
+
+    int fStation {0};
+    fscal fChi2 {0.};
+    int fId {0};
+    bool fIsAlive {0};
+    Vector<ca::HitIndex_t> fHits {"Branch::fHits"};
+  };
+
+}  // namespace cbm::algo::ca
diff --git a/reco/L1/CMakeLists.txt b/reco/L1/CMakeLists.txt
index 89f6a45074..43ce0dd84b 100644
--- a/reco/L1/CMakeLists.txt
+++ b/reco/L1/CMakeLists.txt
@@ -186,7 +186,6 @@ add_dependencies(G__L1 KFPARTICLE)
 install(FILES CbmL1Counters.h
   L1Algo/L1Assert.h
   L1Algo/L1EventEfficiencies.h
-  L1Algo/L1Branch.h
   L1Algo/L1Event.h
   L1Algo/L1EventMatch.h
   L1Algo/L1Utils.h
@@ -198,6 +197,5 @@ install(FILES CbmL1Counters.h
 )
 
 install(FILES L1Algo/L1Algo.h
-  L1Algo/L1Branch.h
   DESTINATION include/L1Algo
 )
diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx
index 568c19efb8..afbc212022 100644
--- a/reco/L1/CbmL1.cxx
+++ b/reco/L1/CbmL1.cxx
@@ -68,7 +68,6 @@
 #include "CaHit.h"
 #include "L1Algo/L1Algo.h"
 #include "L1Algo/L1Assert.h"
-#include "L1Algo/L1Branch.h"
 #include "L1Event.h"
 
 using namespace cbm::algo;  // TODO: remove this line
diff --git a/reco/L1/L1Algo/L1Algo.h b/reco/L1/L1Algo/L1Algo.h
index bb90ffd735..b3df979331 100644
--- a/reco/L1/L1Algo/L1Algo.h
+++ b/reco/L1/L1Algo/L1Algo.h
@@ -28,6 +28,7 @@ class L1AlgoDraw;
 #include <limits>
 #include <map>
 
+#include "CaBranch.h"
 #include "CaConstants.h"
 #include "CaField.h"
 #include "CaGrid.h"
@@ -40,7 +41,6 @@ class L1AlgoDraw;
 #include "CaTrackParam.h"
 #include "CaTriplet.h"
 #include "CaVector.h"
-#include "L1Branch.h"
 #include "L1CloneMerger.h"
 #include "L1Fit.h"
 #include "L1Utils.h"
@@ -184,9 +184,8 @@ public:
 
   void ReadWindowData();
 
-  void CAFindTrack(int ista, L1Branch& best_tr, unsigned char& best_L, fscal& best_chi2, const ca::Triplet* curr_trip,
-                   L1Branch& curr_tr, unsigned char& curr_L, fscal& curr_chi2, unsigned char min_best_l,
-                   L1Branch* new_tr);
+  void CAFindTrack(int ista, ca::Branch& best_tr, const ca::Triplet* curr_trip, ca::Branch& curr_tr,
+                   unsigned char min_best_l, ca::Branch* new_tr);
 
 
   /// Fits track
@@ -195,7 +194,7 @@ public:
   /// \param dir - false - forward, true - backward
   /// \param qp0 - momentum for extrapolation
   /// \param initParams - should be params ititialized. 1 - yes.
-  void BranchFitterFast(const L1Branch& t, TrackParamV& T, const bool dir, const fvec qp0 = 0.,
+  void BranchFitterFast(const ca::Branch& t, TrackParamV& T, const bool dir, const fvec qp0 = 0.,
                         const bool initParams = true);
 
   /// Fits track. more precise than FitterFast
@@ -204,7 +203,7 @@ public:
   /// \param dir - false - forward, true - backward
   /// \param qp0 - momentum for extrapolation
   /// \param initParams - should be params ititialized. 1 - yes.
-  void BranchFitter(const L1Branch& t, TrackParamV& T, const bool dir, const fvec qp0 = 0.,
+  void BranchFitter(const ca::Branch& t, TrackParamV& T, const bool dir, const fvec qp0 = 0.,
                     const bool initParams = true);
 
   /// Finds additional hits for already found track
@@ -212,11 +211,11 @@ public:
   /// \param T - track params
   /// \param dir - 0 - forward, 1 - backward
   /// \param qp0 - momentum for extrapolation
-  void FindMoreHits(L1Branch& t, TrackParamV& T, const bool dir, const fvec qp0 = 0.0);
+  void FindMoreHits(ca::Branch& t, TrackParamV& T, const bool dir, const fvec qp0 = 0.0);
 
   /// Find additional hits for existing track
   /// \return chi2
-  fscal BranchExtender(L1Branch& t);
+  fscal BranchExtender(ca::Branch& t);
 
 #ifdef DRAW
   L1AlgoDraw* draw {nullptr};
@@ -321,7 +320,7 @@ public:
 
   /// Track candidates created out of adjacent triplets before the final track selection.
   /// The candidates may share any amount of hits.
-  Vector<L1Branch> fTrackCandidates {"L1Algo::fTrackCandidates"};
+  Vector<ca::Branch> fTrackCandidates {"L1Algo::fTrackCandidates"};
 
   ///< indices of the sub-slice hits
   Vector<ca::HitIndex_t> fSliceHitIds[constants::size::MaxNstations] {"L1Algo::fSliceHitIds"};
diff --git a/reco/L1/L1Algo/L1Branch.h b/reco/L1/L1Algo/L1Branch.h
deleted file mode 100644
index fa983e8e3d..0000000000
--- a/reco/L1/L1Algo/L1Branch.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Copyright (C) 2007-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Ivan Kisel, Sergey Gorbunov [committer], Maksym Zyzak, Valentina Akishina */
-
-/// @file L1Branch.h
-/// @author Sergey Gorbunov
-
-#ifndef L1Branch_h
-#define L1Branch_h
-
-#include "CaHit.h"
-#include "CaVector.h"
-#include "L1Def.h"
-
-namespace
-{
-  using namespace cbm::algo::ca;  // TMP!!
-  using namespace cbm::algo;      // TMP!!
-}
-
-///
-/// L1Branch class describes a search branch of the CA tracker
-///
-struct L1Branch {
-  /// default constructor
-  L1Branch() { fHits.reserve(25); }
-
-  unsigned char ista {0};
-  char Momentum {0};
-  char NHits {0};
-  fscal chi2 {0.};
-  int fID {0};
-  bool fIsAlive {0};
-  Vector<ca::HitIndex_t> fHits {"L1Branch::fHits"};
-
-  //     static bool compareCand(const L1Branch *a, const L1Branch *b){
-  //
-  //     if (a->Lengtha != b->Lengtha) return (a->Lengtha > b->Lengtha);
-  //
-  //     if (a->ista != b->ista ) return (a->ista  < b->ista );
-  //
-  //   if (a->chi2  != b->chi2 )return (a->chi2  < b->chi2 );
-  // //return (a->chi2  < b->chi2 );
-  //   //   return (a->CandIndex < b->CandIndex );
-  //        return (a->CandIndex > b->CandIndex );
-  //
-  //   }
-
-  //     inline static  bool compareCand(const L1Branch &a, const L1Branch &b){
-  //
-  //
-  //
-  //     if (a.Lengtha != b.Lengtha) return (a.Lengtha > b.Lengtha);
-  //
-  //
-  //     // if (a.time_dif != b.time_dif) return (a.time_dif < b.time_dif);
-  //
-  //
-  //     if (a.ista != b.ista ) return (a.ista  < b.ista );
-  //
-  //
-  //
-  //     if (a.chi2 != b.chi2 ) return (a.chi2  < b.chi2 );
-  //
-  //       return (a.CandIndex  < b.CandIndex );
-  //     //   return (a->CandIndex < b->CandIndex );
-  //    // return (a.CandIndex < b.CandIndex );
-  //
-  //   }
-
-  inline static bool compareCand(const L1Branch& a, const L1Branch& b)
-  {
-
-    if (a.NHits != b.NHits) return (a.NHits > b.NHits);
-
-    if (a.ista != b.ista) return (a.ista < b.ista);
-
-    return (a.chi2 < b.chi2);
-  }
-
-
-  //    static bool compareChi2(const L1Branch &a, const L1Branch &b){
-  //    return (a.Quality > b.Quality );
-  //  }
-
-  //      static bool compareChi2(const L1Branch &a, const L1Branch &b){
-  //          if (a.Lengtha != b.Lengtha) return (a.Lengtha > b.Lengtha);
-  //
-  //           if (a.chi2  != b.chi2 )return (a.chi2  < b.chi2 );
-  //     //return (a->chi2  < b->chi2 );
-  //     //   return (a->CandIndex < b->CandIndex );
-  //     return (a.CandIndex >= b.CandIndex );
-  //     }
-
-
-  // static bool compareChi2(const L1Branch &a, const L1Branch &b){
-  // return (a.Quality > b.Quality );
-  //}
-
-  void Set(unsigned char iStation, unsigned char Length, float Chi2, float Qp, int ID)
-  {
-    NHits = Length;
-    ista  = iStation;
-    //  iN = ( (static_cast<unsigned char>( Chi2 ))<<3 ) + (Level%8);
-    //unsigned short int ista_l = 16-iStation;
-    // float tmp = sqrt(Chi2) / 3.5 * 255;
-    // if (tmp > 255) tmp = 255;
-    // unsigned short int chi_2 = 255 - static_cast<unsigned char>( tmp );
-    // Quality = (Length<<12) + (ista_l<<8) + chi_2;
-    Momentum = 1.0 / fabs(Qp);
-    //    chi2 = chi_2;
-    chi2 = Chi2;
-    fID      = ID;
-    fIsAlive = true;
-  }
-
-  //   void SetLength( unsigned char Length ){
-  //     Quality += - (Quality*(4096)) + (Length/(4096));
-  //   }
-
-  //  static bool compareChi2Q(const L1Branch &a, const L1Branch &b){
-  ////      return (a.Quality > b.Quality);
-  ////
-  //     if (a.Lengtha != b.Lengtha) return (a.Lengtha > b.Lengtha);
-  //
-  //    if (a.ista != b.ista ) return (a.ista  < b.ista );
-  //
-  //    return (a.chi2 < b.chi2 );
-  //  }
-  //  static bool comparePChi2(const L1Branch *a, const L1Branch *b){
-  //    return compareChi2(*a,*b);
-  //  }
-  static bool compareMomentum(const L1Branch& a, const L1Branch& b) { return (a.Momentum > b.Momentum); }
-  static bool comparePMomentum(const L1Branch* a, const L1Branch* b) { return compareMomentum(*a, *b); }
-};
-
-#endif
diff --git a/reco/L1/L1Algo/L1BranchExtender.cxx b/reco/L1/L1Algo/L1BranchExtender.cxx
index a065721421..2dd7948bc0 100644
--- a/reco/L1/L1Algo/L1BranchExtender.cxx
+++ b/reco/L1/L1Algo/L1BranchExtender.cxx
@@ -4,13 +4,13 @@
 
 #include <iostream>
 
+#include "CaBranch.h"
 #include "CaDefines.h"
 #include "CaGridArea.h"
 #include "CaTrack.h"
 #include "CaTrackParam.h"
 #include "CaVector.h"
 #include "L1Algo.h"
-#include "L1Branch.h"
 
 // using namespace std;
 using cbm::algo::ca::Vector;  // TMP!!
@@ -22,7 +22,7 @@ using std::endl;
 /// T - track params
 /// qp0 - momentum for extrapolation
 /// initialize - should be params ititialized. 1 - yes.
-void L1Algo::BranchFitterFast(const L1Branch& t, TrackParamV& Tout, const bool upstream, const fvec qp0,
+void L1Algo::BranchFitterFast(const ca::Branch& t, TrackParamV& Tout, const bool upstream, const fvec qp0,
                               const bool initParams)
 {
   CBMCA_DEBUG_ASSERT(t.NHits >= 3);
@@ -34,8 +34,8 @@ void L1Algo::BranchFitterFast(const L1Branch& t, TrackParamV& Tout, const bool u
   TrackParamV& T = fit.Tr();
 
   // get hits of current track
-  const Vector<ca::HitIndex_t>& hits = t.fHits;  // array of indeses of hits of current track
-  const int nHits                    = t.NHits;
+  const Vector<ca::HitIndex_t>& hits = t.Hits();  // array of indeses of hits of current track
+  const int nHits                    = t.NofHits();
 
   const signed short int step = -2 * static_cast<int>(upstream) + 1;  // increment for station index
   const int iFirstHit         = (upstream) ? nHits - 1 : 0;
@@ -122,7 +122,8 @@ void L1Algo::BranchFitterFast(const L1Branch& t, TrackParamV& Tout, const bool u
 }  // void L1Algo::BranchFitterFast
 
 /// like BranchFitterFast but more precise
-void L1Algo::BranchFitter(const L1Branch& t, TrackParamV& T, const bool upstream, const fvec qp0, const bool initParams)
+void L1Algo::BranchFitter(const ca::Branch& t, TrackParamV& T, const bool upstream, const fvec qp0,
+                          const bool initParams)
 {
   BranchFitterFast(t, T, upstream, qp0, initParams);
   for (int i = 0; i < 1; i++) {
@@ -136,7 +137,7 @@ void L1Algo::BranchFitter(const L1Branch& t, TrackParamV& T, const bool upstream
 /// T - track params
 /// qp0 - momentum for extrapolation
 /// initialize - should be params ititialized. 1 - yes.
-void L1Algo::FindMoreHits(L1Branch& t, TrackParamV& Tout, const bool upstream, const fvec qp0)
+void L1Algo::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool upstream, const fvec qp0)
 {
   Vector<ca::HitIndex_t> newHits {"L1TrackExtender::newHits"};
   newHits.reserve(fParameters.GetNstationsActive());
@@ -148,12 +149,12 @@ void L1Algo::FindMoreHits(L1Branch& t, TrackParamV& Tout, const bool upstream, c
   fit.SetQp0(qp0);
 
   const signed short int step = -2 * static_cast<int>(upstream) + 1;  // increment for station index
-  const int iFirstHit         = (upstream) ? 2 : t.NHits - 3;
+  const int iFirstHit         = (upstream) ? 2 : t.NofHits() - 3;
   //  int ista = fInputData.GetHit(t.Hits[iFirstHit]).iSt + 2 * step; // current station. set to the end of track
 
-  const ca::Hit& hit0 = fInputData.GetHit(t.fHits[iFirstHit]);  // optimize
-  const ca::Hit& hit1 = fInputData.GetHit(t.fHits[iFirstHit + step]);
-  const ca::Hit& hit2 = fInputData.GetHit(t.fHits[iFirstHit + 2 * step]);
+  const ca::Hit& hit0 = fInputData.GetHit(t.Hits()[iFirstHit]);  // optimize
+  const ca::Hit& hit1 = fInputData.GetHit(t.Hits()[iFirstHit + step]);
+  const ca::Hit& hit2 = fInputData.GetHit(t.Hits()[iFirstHit + 2 * step]);
 
   const int ista0 = hit0.Station();
   const int ista1 = hit1.Station();
@@ -268,22 +269,21 @@ void L1Algo::FindMoreHits(L1Branch& t, TrackParamV& Tout, const bool upstream, c
   }
 
   // save hits
-  const unsigned int NOldHits = t.NHits;
+  const unsigned int NOldHits = t.NofHits();
   const unsigned int NNewHits = newHits.size();
-  t.fHits.enlarge(NNewHits + NOldHits);
-  t.NHits = (NNewHits + NOldHits);
+  t.RefHits().enlarge(NNewHits + NOldHits);
 
   if (upstream) {  // backward
     for (int i = NOldHits - 1; i >= 0; i--) {
-      t.fHits[NNewHits + i] = t.fHits[i];
+      t.RefHits()[NNewHits + i] = t.RefHits()[i];
     }
     for (unsigned int i = 0, ii = NNewHits - 1; i < NNewHits; i++, ii--) {
-      t.fHits[i] = newHits[ii];
+      t.RefHits()[i] = newHits[ii];
     }
   }
   else {  // forward
     for (unsigned int i = 0; i < newHits.size(); i++) {
-      t.fHits[NOldHits + i] = (newHits[i]);
+      t.RefHits()[NOldHits + i] = newHits[i];
     }
   }
 
@@ -292,7 +292,7 @@ void L1Algo::FindMoreHits(L1Branch& t, TrackParamV& Tout, const bool upstream, c
 }  // void L1Algo::FindMoreHits
 
 /// Try to extrapolate and find additional hits on other stations
-fscal L1Algo::BranchExtender(L1Branch& t)  // TODO Simdize
+fscal L1Algo::BranchExtender(ca::Branch& t)  // TODO Simdize
 {
   //   const unsigned int minNHits = 3;
 
diff --git a/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx b/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx
index bfcaedaf6d..27e29a8b2c 100644
--- a/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx
+++ b/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx
@@ -22,13 +22,13 @@
 #include "CbmL1.h"
 #include "CbmL1MCTrack.h"
 
+#include "CaBranch.h"
 #include "CaGrid.h"
 #include "CaGridEntry.h"
 #include "CaTrack.h"
 #include "CaTrackParam.h"
 #include "L1Algo.h"
 #include "L1Assert.h"
-#include "L1Branch.h"
 #include "L1Fit.h"
 #include "L1TripletConstructor.h"
 #ifdef DRAW
@@ -438,16 +438,11 @@ void L1Algo::CaTrackFinderSlice()
     //LOG(FATAL) << "L1CATrackFinder: min_level undefined in " << __FILE__ << " : " << __LINE__;
     if (fpCurrentIteration->GetTrackFromTripletsFlag()) { min_level = 0; }
 
-    L1Branch curr_tr;
-    L1Branch new_tr[constants::size::MaxNstations];
-    L1Branch best_tr;
-    fscal curr_chi2 = 0;
+    ca::Branch curr_tr;
+    ca::Branch new_tr[constants::size::MaxNstations];
+    ca::Branch best_tr;
 
-    fscal best_chi2      = 0;
-    unsigned char best_L = 0;
-
-    unsigned char curr_L = 1;
-    int ndf              = 1;
+    int ndf = 1;
 
 
     // collect consequtive: the longest tracks, shorter, more shorter and so on
@@ -496,60 +491,53 @@ void L1Algo::CaTrackFinderSlice()
           // ghost tracks, but does not affect the efficiency
           if (first_trip.GetLevel() < firstTripletLevel) { continue; }
 
-          //  curr_tr.Momentum = 0.f;
-          curr_tr.chi2 = 0.f;
-          //   curr_tr.Lengtha  = 0;
-          curr_tr.ista = 0;
-          curr_tr.fHits.clear();
-          curr_tr.fHits.push_back(fWindowHits[first_trip.GetLHit()].Id());
-          curr_tr.NHits = 1;
-
-          curr_L    = 1;
-          curr_chi2 = first_trip.GetChi2();
+          curr_tr.SetChi2(0.);
+          curr_tr.SetStation(0);
+          curr_tr.ResetHits();
+          curr_tr.AddHit(fWindowHits[first_trip.GetLHit()].Id());
+          curr_tr.SetChi2(first_trip.GetChi2());
 
-          best_tr   = (curr_tr);
-          best_chi2 = curr_chi2;
-          best_L    = curr_L;
+          best_tr = curr_tr;
 
-          CAFindTrack(istaF, best_tr, best_L, best_chi2, &first_trip, (curr_tr), curr_L, curr_chi2, min_best_l,
+          CAFindTrack(istaF, best_tr, &first_trip, curr_tr, min_best_l,
                       new_tr);  /// reqursive func to build a tree of possible track-candidates and choose the best
 
-          if (best_L < firstTripletLevel + 2) continue;  // loose maximum one hit
+          if (best_tr.NofHits() < firstTripletLevel + 2) continue;  // loose maximum one hit
 
-          if (best_L < min_level + 3) continue;  // should find all hits for min_level
+          if (best_tr.NofHits() < min_level + 3) continue;  // should find all hits for min_level
 
-          ndf = best_L * 2 - 5;
+          ndf = best_tr.NofHits() * 2 - 5;
 
           // TODO: automatize the NDF calculation
 
-          if (kGlobal == fTrackingMode || kMcbm == fTrackingMode) { ndf = best_L * 2 - 4; }
-
-          best_chi2 = best_chi2 / ndf;  //normalize
+          if (kGlobal == fTrackingMode || kMcbm == fTrackingMode) { ndf = best_tr.NofHits() * 2 - 4; }
 
+          best_tr.SetChi2(best_tr.Chi2() / ndf);
           if (fGhostSuppression) {
-            if (3 == best_L) {
+            if (3 == best_tr.NofHits()) {
               if (!fpCurrentIteration->GetPrimaryFlag() && (istaF != 0)) continue;  // too /*short*/ non-MAPS track
-              if (fpCurrentIteration->GetPrimaryFlag() && (best_chi2 > 5.0)) continue;
+              if (fpCurrentIteration->GetPrimaryFlag() && (best_tr.Chi2() > 5.0)) continue;
             }
           }
           fTrackCandidates.push_back(best_tr);
-          L1Branch& tr = fTrackCandidates.back();
-          tr.Set(istaF, best_L, best_chi2, first_trip.GetQp(), fTrackCandidates.size() - 1);
+          ca::Branch& tr = fTrackCandidates.back();
+          tr.SetStation(istaF);
+          tr.SetId(fTrackCandidates.size() - 1);
+          tr.SetAlive(true);
           if (0) {  // debug
-            cout << "track " << fTrackCandidates.size() - 1 << " found, L = " << (int) best_L << " chi2= " << best_chi2
-                 << endl;
+            cout << "track " << fTrackCandidates.size() - 1 << " found, L = " << best_tr.NofHits()
+                 << " chi2= " << best_tr.Chi2() << endl;
             cout << " hits: ";
-            for (unsigned int i = 0; i < tr.fHits.size(); i++) {
-              cout << GetMcTrackIdForCaHit(tr.fHits[i]) << " ";
+            for (auto hitId : tr.Hits()) {
+              cout << GetMcTrackIdForCaHit(hitId) << " ";
             }
             cout << endl;
           }
         }  // itrip
       }    // istaF
 
-      for (Tindex iTrack = 0; iTrack < (Tindex) fTrackCandidates.size(); ++iTrack) {
-        L1Branch& tr = fTrackCandidates[iTrack];
-        tr.fIsAlive  = false;
+      for (ca::Branch& tr : fTrackCandidates) {
+        tr.SetAlive(false);
       }
 
       bool repeatCompetition = true;
@@ -560,63 +548,60 @@ void L1Algo::CaTrackFinderSlice()
 
         repeatCompetition = false;
 
-        for (Tindex iTrack = 0; iTrack < (Tindex) fTrackCandidates.size(); ++iTrack) {
-          L1Branch& tr = fTrackCandidates[iTrack];
-          if (tr.fIsAlive) continue;
-
-          for (int iHit = 0; iHit < (int) tr.fHits.size(); ++iHit) {
-            const ca::Hit& h = fInputData.GetHit(tr.fHits[iHit]);
+        for (ca::Branch& tr : fTrackCandidates) {
+          if (tr.IsAlive()) { continue; }
+          for (auto& hitId : tr.Hits()) {
+            const ca::Hit& h = fInputData.GetHit(hitId);
             bool isAlive     = true;
             {  // front  strip
               auto& stripF = (fStripToTrack)[h.FrontKey()];
-              if ((stripF >= 0) && (stripF != tr.fID)) {  // strip is used by other candidate
+              if ((stripF >= 0) && (stripF != tr.Id())) {  // strip is used by other candidate
                 const auto& other = fTrackCandidates[stripF];
-                if (!other.fIsAlive && L1Branch::compareCand(tr, other)) { stripF = tr.fID; }
+                if (!other.IsAlive() && tr.IsBetterThan(other)) { stripF = tr.Id(); }
                 else {
                   isAlive = false;
                 }
               }
               else {
-                stripF = tr.fID;
+                stripF = tr.Id();
               }
               if (!isAlive) { break; }
             }
 
             {  // back strip
               auto& stripB = (fStripToTrack)[h.BackKey()];
-              if ((stripB >= 0) && (stripB != tr.fID)) {  // strip is used by other candidate
+              if ((stripB >= 0) && (stripB != tr.Id())) {  // strip is used by other candidate
                 const auto& other = fTrackCandidates[stripB];
-                if (!other.fIsAlive && L1Branch::compareCand(tr, other)) { stripB = tr.fID; }
+                if (!other.IsAlive() && tr.IsBetterThan(other)) { stripB = tr.Id(); }
                 else {
                   isAlive = false;
                 }
               }
               else {
-                stripB = tr.fID;
+                stripB = tr.Id();
               }
               if (!isAlive) { break; }
             }
           }  // loop over hits
         }    // itrack
 
-        // == Loop over track candidates and select those that are alive
+        // == Check if some suppressed candidates are still alive
 
-        for (Tindex iTrack = 0; iTrack < (Tindex) fTrackCandidates.size(); ++iTrack) {
-          L1Branch& tr = fTrackCandidates[iTrack];
-          if (tr.fIsAlive) { continue; }
+        for (ca::Branch& tr : fTrackCandidates) {
+          if (tr.IsAlive()) { continue; }
 
-          tr.fIsAlive = true;
-          for (int iHit = 0; tr.fIsAlive && (iHit < (int) tr.fHits.size()); ++iHit) {
-            const ca::Hit& h = fInputData.GetHit(tr.fHits[iHit]);
-            tr.fIsAlive =
-              tr.fIsAlive && ((fStripToTrack)[h.FrontKey()] == tr.fID) && ((fStripToTrack)[h.BackKey()] == tr.fID);
+          tr.SetAlive(true);
+          for (int iHit = 0; tr.IsAlive() && (iHit < (int) tr.Hits().size()); ++iHit) {
+            const ca::Hit& h = fInputData.GetHit(tr.Hits()[iHit]);
+            tr.SetAlive(tr.IsAlive() && ((fStripToTrack)[h.FrontKey()] == tr.Id())
+                        && ((fStripToTrack)[h.BackKey()] == tr.Id()));
           }
 
-          if (!tr.fIsAlive) {  // release strips
-            for (int iHit = 0; (iHit < (int) tr.fHits.size()); ++iHit) {
-              const ca::Hit& h = fInputData.GetHit(tr.fHits[iHit]);
-              if (fStripToTrack[h.FrontKey()] == tr.fID) { fStripToTrack[h.FrontKey()] = -1; }
-              if (fStripToTrack[h.BackKey()] == tr.fID) { fStripToTrack[h.BackKey()] = -1; }
+          if (!tr.IsAlive()) {  // release strips
+            for (auto hitId : tr.Hits()) {
+              const ca::Hit& h = fInputData.GetHit(hitId);
+              if (fStripToTrack[h.FrontKey()] == tr.Id()) { fStripToTrack[h.FrontKey()] = -1; }
+              if (fStripToTrack[h.BackKey()] == tr.Id()) { fStripToTrack[h.BackKey()] = -1; }
             }
           }
           else {
@@ -631,22 +616,22 @@ void L1Algo::CaTrackFinderSlice()
       // ==
 
       for (Tindex iCandidate = 0; iCandidate < (Tindex) fTrackCandidates.size(); ++iCandidate) {
-        L1Branch& tr = fTrackCandidates[iCandidate];
-        if (!tr.fIsAlive) continue;
+        ca::Branch& tr = fTrackCandidates[iCandidate];
+        if (!tr.IsAlive()) continue;
         if (kMcbm == fTrackingMode) {
-          if (tr.NHits <= 3) { continue; }
+          if (tr.NofHits() <= 3) { continue; }
         }
         else if (kGlobal == fTrackingMode) {
-          if (tr.NHits < 3) { continue; }
+          if (tr.NofHits() < 3) { continue; }
         }
         else {
-          if (tr.NHits < 3) { continue; }
+          if (tr.NofHits() < 3) { continue; }
         }
         if (fpCurrentIteration->GetExtendTracksFlag()) {
-          if (tr.NHits != fParameters.GetNstationsActive()) BranchExtender(tr);
+          if (tr.NofHits() < fParameters.GetNstationsActive()) { BranchExtender(tr); }
         }
 
-        for (auto iHit : tr.fHits) {
+        for (auto iHit : tr.Hits()) {
           const ca::Hit& hit = fInputData.GetHit(iHit);
 
           /// used strips are marked
@@ -657,13 +642,13 @@ void L1Algo::CaTrackFinderSlice()
           fSliceRecoHits.push_back(iHit);
         }
         Track t;
-        t.fNofHits = tr.NHits;
+        t.fNofHits = tr.NofHits();
         fSliceRecoTracks.push_back(t);
         if (0) {  // SG debug
-          cout << "store track " << iCandidate << " chi2= " << tr.chi2 << endl;
+          cout << "store track " << iCandidate << " chi2= " << tr.Chi2() << endl;
           cout << " hits: ";
-          for (unsigned int ih = 0; ih < tr.fHits.size(); ih++) {
-            cout << GetMcTrackIdForCaHit(tr.fHits[ih]) << " ";
+          for (unsigned int ih = 0; ih < tr.Hits().size(); ih++) {
+            cout << GetMcTrackIdForCaHit(tr.Hits()[ih]) << " ";
           }
           cout << '\n';
         }
@@ -751,13 +736,13 @@ void L1Algo::CaTrackFinderSlice()
      *                                                              *
      ****************************************************************/
 
-void L1Algo::CAFindTrack(int ista, L1Branch& best_tr, unsigned char& best_L, fscal& best_chi2,
-                         const ca::Triplet* curr_trip, L1Branch& curr_tr, unsigned char& curr_L, fscal& curr_chi2,
-                         unsigned char min_best_l, L1Branch* new_tr)
+void L1Algo::CAFindTrack(int ista, ca::Branch& best_tr, const ca::Triplet* curr_trip, ca::Branch& curr_tr,
+                         unsigned char min_best_l, ca::Branch* new_tr)
 /// recursive search for tracks
-/// input: @ista - station index, @&best_tr - best track for the privious call, @&best_L -
+/// input: @ista - station index, @&best_tr - best track for the privious call
 /// output: @&NCalls - number of function calls
 {
+
   if (curr_trip->GetLevel() == 0)  // the end of the track -> check and store
   {
     // -- finish with current track
@@ -775,11 +760,7 @@ void L1Algo::CAFindTrack(int ista, L1Branch& best_tr, unsigned char& best_L, fsc
 
       //        curr_tr.Hits.push_back(fGridHitIds[ihitm]);
 
-      curr_tr.fHits.push_back(fWindowHits[ihitm].Id());
-
-      curr_tr.NHits++;
-
-      curr_L++;
+      curr_tr.AddHit(fWindowHits[ihitm].Id());
     }
 
     //if (!GetFUsed((*fStripFlag)[fGridHits[ihitr].f] | (*fStripFlag)[fGridHits[ihitr].b])) {
@@ -790,39 +771,22 @@ void L1Algo::CAFindTrack(int ista, L1Branch& best_tr, unsigned char& best_L, fsc
     if (!(fvHitKeyFlags[fWindowHits[ihitr].FrontKey()] || fvHitKeyFlags[fWindowHits[ihitr].BackKey()])) {
 
       //curr_tr.Hits.push_back(fGridHitIds[ihitr]);
-      curr_tr.fHits.push_back(fWindowHits[ihitr].Id());
-
-      curr_tr.NHits++;
-
-      curr_L++;
+      curr_tr.AddHit(fWindowHits[ihitr].Id());
     }
 
-    //if( curr_L < min_best_l - 1 ) return; // suppouse that only one hit can be added by extender
+    //if( curr_tr.NofHits() < min_best_l - 1 ) return; // suppouse that only one hit can be added by extender
     // TODO: SZh 21.08.2023: Replace hard-coded value with a parameter
-    int ndf = curr_L * 2 - 5;
+    int ndf = curr_tr.NofHits() * 2 - 5;
 
-    if (kGlobal == fTrackingMode || kMcbm == fTrackingMode) { ndf = curr_L * 2 - 4; }
+    if (kGlobal == fTrackingMode || kMcbm == fTrackingMode) { ndf = curr_tr.NofHits() * 2 - 4; }
 
-    if (curr_chi2 > fTrackChi2Cut * ndf) { return; }
+    if (curr_tr.Chi2() > fTrackChi2Cut * ndf) { return; }
 
-    // TODO: SZh 04.10.2022: Does one should delete this code?
-    //       // try to find more hits
-    // if (fpCurrentIteration->GetExtendTracksFlag()) {
-    //     // if( curr_L < min_best_l )
-    //     if (!fpCurrentIteration->GetJumpedFlag() && curr_L >= 3){
-    //       //curr_chi2 = BranchExtender(curr_tr);
-    //       BranchExtender(curr_tr);
-    //       curr_L = curr_tr.Hits.size();
-    //         //      if( 2*curr_chi2 > (2*(curr_L*2-5) + 1) * 4*4 ) return;
-    //     }
-    // }
 
     // -- select the best
-    if ((curr_L > best_L) || ((curr_L == best_L) && (curr_chi2 < best_chi2))) {
-
-      best_tr   = curr_tr;
-      best_chi2 = curr_chi2;
-      best_L    = curr_L;
+    if ((curr_tr.NofHits() > best_tr.NofHits())
+        || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
+      best_tr = curr_tr;
     }
 
     return;
@@ -846,17 +810,15 @@ void L1Algo::CAFindTrack(int ista, L1Branch& best_tr, unsigned char& best_L, fsc
       if (fvHitKeyFlags[fWindowHits[new_trip.GetLHit()].FrontKey()]
           || fvHitKeyFlags[fWindowHits[new_trip.GetLHit()].BackKey()]) {  //hits are used
         //  no used hits allowed -> compare and store track
-        if ((curr_L > best_L) || ((curr_L == best_L) && (curr_chi2 < best_chi2))) {
+        if ((curr_tr.NofHits() > best_tr.NofHits())
+            || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
           best_tr = curr_tr;
-
-          best_chi2 = curr_chi2;
-          best_L    = curr_L;
         }
       }
       else {  // hit is not used: add the left hit from the new triplet to the current track
 
-        unsigned char new_L = curr_L + 1;
-        fscal new_chi2      = curr_chi2 + dchi2;
+        unsigned char new_L = curr_tr.NofHits() + 1;
+        fscal new_chi2      = curr_tr.Chi2() + dchi2;
 
 
         if (0) {  //SGtrd2d debug!!
@@ -868,7 +830,7 @@ void L1Algo::CAFindTrack(int ista, L1Branch& best_tr, unsigned char& best_L, fsc
           int mc13 = GetMcTrackIdForWindowHit(new_trip.GetRHit());
           if ((mc01 == mc02) && (mc02 == mc03)) {
             cout << " sta " << ista << " mc0 " << mc01 << " " << mc02 << " " << mc03 << " mc1 " << mc11 << " " << mc12
-                 << " " << mc13 << " chi2 " << curr_chi2 / (2 * (curr_L + 2) - 4) << " new "
+                 << " " << mc13 << " chi2 " << curr_tr.Chi2() / (2 * (curr_tr.NofHits() + 2) - 4) << " new "
                  << new_chi2 / (2 * (new_L + 2) - 4) << endl;
             cout << "   hits " << curr_trip->GetLHit() << " " << curr_trip->GetMHit() << " " << curr_trip->GetRHit()
                  << " " << new_trip.GetLHit() << endl;
@@ -891,12 +853,12 @@ void L1Algo::CAFindTrack(int ista, L1Branch& best_tr, unsigned char& best_L, fsc
 
         // add new hit
         new_tr[ista] = curr_tr;
-        new_tr[ista].fHits.push_back(fWindowHits[new_trip.GetLHit()].Id());
-        new_tr[ista].NHits++;
+        new_tr[ista].AddHit(fWindowHits[new_trip.GetLHit()].Id());
 
         const int new_ista = ista + new_trip.GetMSta() - new_trip.GetLSta();
+        new_tr[ista].SetChi2(new_chi2);
 
-        CAFindTrack(new_ista, best_tr, best_L, best_chi2, &new_trip, new_tr[ista], new_L, new_chi2, min_best_l, new_tr);
+        CAFindTrack(new_ista, best_tr, &new_trip, new_tr[ista], min_best_l, new_tr);
       }  // add triplet to track
     }    // for neighbours
   }      // level = 0
-- 
GitLab