From 14f058f8c222106faf1dafb7fc1c1bf53a1743c1 Mon Sep 17 00:00:00 2001
From: "se.gorbunov" <se.gorbunov@gsi.de>
Date: Thu, 19 Oct 2023 21:37:12 +0000
Subject: [PATCH] Ca: move Ca track finder to /algo

---
 algo/ca/core/CMakeLists.txt                   |  16 +
 .../ca/core/tracking/CaCloneMerger.cxx        |  40 +-
 algo/ca/core/tracking/CaCloneMerger.h         | 127 +++
 .../ca/core/tracking/CaFramework.cxx          |  59 +-
 algo/ca/core/tracking/CaFramework.h           | 358 +++++++
 .../ca/core/tracking/CaTrackExtender.cxx      | 136 +--
 algo/ca/core/tracking/CaTrackExtender.h       |  93 ++
 .../ca/core/tracking/CaTrackFinder.cxx        | 150 +--
 algo/ca/core/tracking/CaTrackFinder.h         |  66 ++
 algo/ca/core/tracking/CaTrackFinderWindow.cxx | 771 ++++++++++++++++
 algo/ca/core/tracking/CaTrackFinderWindow.h   |  73 ++
 .../ca/core/tracking/CaTrackFitter.cxx        |  68 +-
 algo/ca/core/tracking/CaTrackFitter.h         |  66 ++
 .../ca/core/tracking/CaTripletConstructor.cxx |  55 +-
 algo/ca/core/tracking/CaTripletConstructor.h  | 122 +++
 reco/KF/ParticleFitter/CbmL1PFFitter.cxx      |  43 +-
 reco/L1/CMakeLists.txt                        |  16 +-
 reco/L1/CbmL1.cxx                             |  72 +-
 reco/L1/CbmL1.h                               |  21 +-
 reco/L1/CbmL1MCTrack.cxx                      |   4 +-
 reco/L1/CbmL1Performance.cxx                  |  61 +-
 reco/L1/CbmL1ReadEvent.cxx                    |  20 +-
 reco/L1/L1Algo/L1Algo.h                       | 435 ---------
 reco/L1/L1Algo/L1CaTrackFinderSlice.cxx       | 871 ------------------
 reco/L1/L1Algo/L1CloneMerger.h                | 133 ---
 reco/L1/L1Algo/L1TripletConstructor.h         | 117 ---
 reco/L1/L1Algo/utils/L1AlgoDraw.cxx           |  11 +-
 reco/L1/L1Algo/utils/L1AlgoDraw.h             |  10 +-
 .../utils/L1AlgoEfficiencyPerformance.h       |   3 +-
 reco/L1/L1Algo/utils/L1AlgoPulls.cxx          |   2 +
 reco/L1/L1Algo/utils/L1AlgoPulls.h            |   5 +-
 .../CbmL1GlobalTrackFinder.cxx                |   1 -
 .../OffLineInterface/CbmL1StsTrackFinder.cxx  |   1 -
 reco/L1/catools/CaToolsDebugger.cxx           |   8 +-
 reco/L1/catools/CaToolsDebugger.h             |   1 +
 35 files changed, 2110 insertions(+), 1925 deletions(-)
 rename reco/L1/L1Algo/L1CloneMerger.cxx => algo/ca/core/tracking/CaCloneMerger.cxx (91%)
 create mode 100644 algo/ca/core/tracking/CaCloneMerger.h
 rename reco/L1/L1Algo/L1Algo.cxx => algo/ca/core/tracking/CaFramework.cxx (76%)
 create mode 100644 algo/ca/core/tracking/CaFramework.h
 rename reco/L1/L1Algo/L1BranchExtender.cxx => algo/ca/core/tracking/CaTrackExtender.cxx (60%)
 create mode 100644 algo/ca/core/tracking/CaTrackExtender.h
 rename reco/L1/L1Algo/L1CaTrackFinder.cxx => algo/ca/core/tracking/CaTrackFinder.cxx (53%)
 create mode 100644 algo/ca/core/tracking/CaTrackFinder.h
 create mode 100644 algo/ca/core/tracking/CaTrackFinderWindow.cxx
 create mode 100644 algo/ca/core/tracking/CaTrackFinderWindow.h
 rename reco/L1/L1Algo/L1TrackFitter.cxx => algo/ca/core/tracking/CaTrackFitter.cxx (81%)
 create mode 100644 algo/ca/core/tracking/CaTrackFitter.h
 rename reco/L1/L1Algo/L1TripletConstructor.cxx => algo/ca/core/tracking/CaTripletConstructor.cxx (93%)
 create mode 100644 algo/ca/core/tracking/CaTripletConstructor.h
 delete mode 100644 reco/L1/L1Algo/L1Algo.h
 delete mode 100644 reco/L1/L1Algo/L1CaTrackFinderSlice.cxx
 delete mode 100644 reco/L1/L1Algo/L1CloneMerger.h
 delete mode 100644 reco/L1/L1Algo/L1TripletConstructor.h

diff --git a/algo/ca/core/CMakeLists.txt b/algo/ca/core/CMakeLists.txt
index da259ab55b..0adcb851a5 100644
--- a/algo/ca/core/CMakeLists.txt
+++ b/algo/ca/core/CMakeLists.txt
@@ -26,9 +26,18 @@ set(SRCS
   ${CMAKE_CURRENT_SOURCE_DIR}/pars/CaSearchWindow.cxx
   ${CMAKE_CURRENT_SOURCE_DIR}/pars/CaStation.cxx
   ${CMAKE_CURRENT_SOURCE_DIR}/pars/CaStationInitializer.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaCloneMerger.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaFramework.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTrackExtender.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTrackFinder.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTrackFinderWindow.cxx
   ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTrackFit.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTrackFitter.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/tracking/CaTripletConstructor.cxx
 )
 
+SET_SOURCE_FILES_PROPERTIES(${SRCS} PROPERTIES COMPILE_FLAGS "-O3")
+
 add_library(CaCore SHARED ${SRCS})
 
 target_include_directories(CaCore
@@ -93,7 +102,14 @@ install(
     utils/CaVector.h
     utils/CaUtils.h
     utils/CaDefines.h
+    tracking/CaCloneMerger.h
+    tracking/CaFramework.h
+    tracking/CaTrackExtender.h
+    tracking/CaTrackFinder.h
+    tracking/CaTrackFinderWindow.h
     tracking/CaTrackFit.h
+    tracking/CaTrackFitter.h
+    tracking/CaTripletConstructor.h   
   DESTINATION
     include/
 )
diff --git a/reco/L1/L1Algo/L1CloneMerger.cxx b/algo/ca/core/tracking/CaCloneMerger.cxx
similarity index 91%
rename from reco/L1/L1Algo/L1CloneMerger.cxx
rename to algo/ca/core/tracking/CaCloneMerger.cxx
index 707d12ba6c..37074f5a88 100644
--- a/reco/L1/L1Algo/L1CloneMerger.cxx
+++ b/algo/ca/core/tracking/CaCloneMerger.cxx
@@ -2,35 +2,35 @@
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Sergei Zharko, Maksym Zyzak [committer]*/
 
-/// \file    L1CloneMerger.h
+/// \file    CloneMerger.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)
+/// \brief   A class wrapper over clones merger algorithm for the Ca track finder (implementation)
 /// \since   22.07.2022 (second version)
 
-#include "L1CloneMerger.h"
+#include "CaCloneMerger.h"
 
 #include <iostream>
 
+#include "CaFramework.h"
 #include "CaParameters.h"
 #include "CaTrack.h"
 #include "CaTrackFit.h"
 #include "CaVector.h"
-#include "L1Algo.h"
 
-using cbm::algo::ca::Track;   // TMP
-using cbm::algo::ca::Vector;  // TMP
+using namespace cbm::algo::ca;
+using namespace cbm::algo;
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-L1CloneMerger::L1CloneMerger(const L1Algo& algo) : frAlgo(algo) {}
+CloneMerger::CloneMerger(const ca::Framework& algo) : frAlgo(algo) {}
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-L1CloneMerger::~L1CloneMerger() {}
+CloneMerger::~CloneMerger() {}
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void L1CloneMerger::Exec(Vector<Track>& extTracks, Vector<ca::HitIndex_t>& extRecoHits)
+void CloneMerger::Exec(Vector<Track>& extTracks, Vector<ca::HitIndex_t>& extRecoHits)
 {
   Vector<unsigned short>& firstStation = fTrackFirstStation;
   Vector<unsigned short>& lastStation  = fTrackLastStation;
@@ -93,7 +93,7 @@ void L1CloneMerger::Exec(Vector<Track>& extTracks, Vector<ca::HitIndex_t>& extRe
   ca::FieldRegion fld _fvecalignment;
 
   // Max length for merging
-  unsigned char maxLengthForMerge = static_cast<unsigned char>(frAlgo.GetParameters()->GetNstationsActive() - 3);
+  unsigned char maxLengthForMerge = static_cast<unsigned char>(frAlgo.GetParameters().GetNstationsActive() - 3);
 
   for (int iTr = 0; iTr < nTracks; iTr++) {
     if (extTracks[iTr].fNofHits > maxLengthForMerge) continue;
@@ -119,8 +119,8 @@ void L1CloneMerger::Exec(Vector<Track>& extTracks, Vector<ca::HitIndex_t>& extRe
 
       unsigned short stam;
 
-      fBf = frAlgo.GetParameters()->GetStation(staf).fieldSlice.GetFieldValue(Tf.X(), Tf.Y());
-      fBb = frAlgo.GetParameters()->GetStation(stab).fieldSlice.GetFieldValue(Tb.X(), Tb.Y());
+      fBf = frAlgo.GetParameters().GetStation(staf).fieldSlice.GetFieldValue(Tf.X(), Tf.Y());
+      fBb = frAlgo.GetParameters().GetStation(stab).fieldSlice.GetFieldValue(Tb.X(), Tb.Y());
 
       unsigned short dist = firstStation[iTr] - lastStation[jTr];
 
@@ -128,10 +128,10 @@ void L1CloneMerger::Exec(Vector<Track>& extTracks, Vector<ca::HitIndex_t>& extRe
       else
         stam = staf - 1;
 
-      fvec zm = frAlgo.GetParameters()->GetStation(stam).fZ;
+      fvec zm = frAlgo.GetParameters().GetStation(stam).fZ;
       fvec xm = fvec(0.5) * (Tf.GetX() + Tf.Tx() * (zm - Tf.Z()) + Tb.GetX() + Tb.Tx() * (zm - Tb.Z()));
       fvec ym = fvec(0.5) * (Tf.Y() + Tf.Ty() * (zm - Tf.Z()) + Tb.Y() + Tb.Ty() * (zm - Tb.Z()));
-      fBm     = frAlgo.GetParameters()->GetStation(stam).fieldSlice.GetFieldValue(xm, ym);
+      fBm     = frAlgo.GetParameters().GetStation(stam).fieldSlice.GetFieldValue(xm, ym);
       fld.Set(fBb, Tb.Z(), fBm, zm, fBf, Tf.Z());
 
       fvec zMiddle = fvec(0.5) * (Tb.Z() + Tf.Z());
@@ -195,8 +195,8 @@ void L1CloneMerger::Exec(Vector<Track>& extTracks, Vector<ca::HitIndex_t>& extRe
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void L1CloneMerger::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 CloneMerger::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++) {
@@ -241,7 +241,7 @@ void L1CloneMerger::FilterTracks(fvec const r[5], fvec const C[15], fvec const m
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void L1CloneMerger::InvertCholesky(fvec a[15])
+void CloneMerger::InvertCholesky(fvec a[15])
 {
   fvec d[5], uud, u[5][5];
   for (int i = 0; i < 5; i++) {
@@ -306,7 +306,7 @@ void L1CloneMerger::InvertCholesky(fvec a[15])
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void L1CloneMerger::MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15])
+void CloneMerger::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];
 
@@ -331,7 +331,7 @@ void L1CloneMerger::MultiplyMS(fvec const C[5][5], fvec const V[15], fvec K[15])
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void L1CloneMerger::MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[5])
+void CloneMerger::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];
@@ -342,7 +342,7 @@ void L1CloneMerger::MultiplySR(fvec const C[15], fvec const r_in[5], fvec r_out[
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void L1CloneMerger::MultiplySS(fvec const C[15], fvec const V[15], fvec K[5][5])
+void CloneMerger::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];
diff --git a/algo/ca/core/tracking/CaCloneMerger.h b/algo/ca/core/tracking/CaCloneMerger.h
new file mode 100644
index 0000000000..8acc9fb88d
--- /dev/null
+++ b/algo/ca/core/tracking/CaCloneMerger.h
@@ -0,0 +1,127 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer], Maksym Zyzak */
+
+/// \file    CloneMerger.h
+/// \authors S.Zharko <s.zharko@gsi.de> (interface), M.Zyzak (original algorithm)
+/// \brief   A class wrapper over clones merger algorithm for the Ca track finder (declaration)
+/// \since   22.07.2022
+
+#pragma once  // include this header only once per compilation unit
+
+#include "CaHit.h"   // For ca::HitIndex_t
+#include "CaSimd.h"  // TEMPORARY FOR fvec, fscal
+#include "CaVector.h"
+
+
+namespace cbm::algo::ca
+{
+  class Track;
+  class Framework;
+
+  namespace
+  {
+    using namespace cbm::algo;  // to keep ca:: prefices in the code
+  }
+
+
+  /// Class implements a clones merger algorithm for the CA track finder
+  ///
+  class CloneMerger {
+  public:
+    /// Default constructor
+    CloneMerger(const ca::Framework& algo);
+
+    /// Destructor
+    ~CloneMerger();
+
+    /// Copy constructor
+    CloneMerger(const CloneMerger&) = delete;
+
+    /// Move constructor
+    CloneMerger(CloneMerger&&) = delete;
+
+    /// Copy assignment operator
+    CloneMerger& operator=(const CloneMerger&) = delete;
+
+    /// Move assignment operator
+    CloneMerger& operator=(CloneMerger&&) = 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(Vector<Track>& extTracks, Vector<ca::HitIndex_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
+    Vector<unsigned short> fTrackFirstStation {"CloneMerger::fTrackFirstStation"};
+
+    /// Last station of a track
+    Vector<unsigned short> fTrackLastStation {"CloneMerger::fTrackLastStation"};
+
+    /// Index of the first hit of a track
+    Vector<ca::HitIndex_t> fTrackFirstHit {"CloneMerger::fTrackFirstHit"};
+
+    /// Index of the last hit of a track
+    Vector<ca::HitIndex_t> fTrackLastHit {"CloneMerger::fTrackLastHit"};
+
+    /// Index (TODO:??) of a track that can be merge with the given track
+    Vector<unsigned short> fTrackNeighbour {"CloneMerger::fTrackNeighbour"};
+
+    /// Chi2 value of the track merging procedure
+    Vector<float> fTrackChi2 {"CloneMerger::fTrackChi2"};
+
+    /// Flag: is the given track already stored to the output
+    Vector<char> fTrackIsStored {"CloneMerger::fTrackIsStored"};
+
+    /// Flag: is the track a downstream neighbour of another track
+    Vector<char> fTrackIsDownstreamNeighbour {"CloneMerger::fTrackIsDownstreamNeighbour"};
+
+    Vector<Track> fTracksNew {"CaCloneMerger::fTracksNew"};  ///< vector of tracks after the merge
+
+    Vector<ca::HitIndex_t> fRecoHitsNew {"CaCloneMerger::fRecoHitsNew"};  ///< vector of track hits after the merge
+
+    const ca::Framework& frAlgo;  ///< Reference to the main track finder algorithm class
+  };
+
+}  // namespace cbm::algo::ca
diff --git a/reco/L1/L1Algo/L1Algo.cxx b/algo/ca/core/tracking/CaFramework.cxx
similarity index 76%
rename from reco/L1/L1Algo/L1Algo.cxx
rename to algo/ca/core/tracking/CaFramework.cxx
index 9b3a9f2e27..539483fe87 100644
--- a/reco/L1/L1Algo/L1Algo.cxx
+++ b/algo/ca/core/tracking/CaFramework.cxx
@@ -2,31 +2,33 @@
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Igor Kulakov [committer], Maksym Zyzak, Valentina Akishina */
 
-#include "L1Algo.h"
-
-#include "CbmL1.h"
+#include "CaFramework.h"
 
 #include "CaGridEntry.h"
-#include "CaToolsDebugger.h"
+// #include "CaToolsDebugger.h"
+
+using namespace cbm::algo::ca;
 
-L1Algo::L1Algo()
+namespace
+{
+  using namespace cbm::algo;  // to keep ca:: prefices in the code
+}
+
+Framework::Framework()
 {
   for (unsigned int i = 0; i < constants::size::MaxNstations; i++) {
-    fTriplets[i].SetName(std::stringstream() << "L1Algo::fTriplets[" << i << "]");
+    fTriplets[i].SetName(std::stringstream() << "Framework::fTriplets[" << i << "]");
   }
 }
 
 using cbm::algo::ca::ECounter;  // monitor counter key type
 using cbm::algo::ca::EDetectorID;
 using cbm::algo::ca::ETimer;  // monitor timer key type
-using cbm::ca::tools::Debugger;
+//using cbm::ca::tools::Debugger;
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void L1Algo::Init(const TrackingMode mode)
+void Framework::Init(const TrackingMode mode)
 {
   fTrackingMode = mode;
-
   // Monitor settings
   fMonitor.SetCounterName(ECounter::RecoTrack, "reco tracks");
   fMonitor.SetCounterName(ECounter::RecoHit, "reco hits");
@@ -42,21 +44,23 @@ void L1Algo::Init(const TrackingMode mode)
   fMonitor.Reset();
 }
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void L1Algo::Finish() { Debugger::Instance().Write(); }
+void Framework::Finish()
+{
+  //Debugger::Instance().Write();
+}
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void L1Algo::ReceiveInputData(InputData&& inputData)
+void Framework::ReceiveInputData(InputData&& inputData)
 {
   // ----- Get input data ----------------------------------------------------------------------------------------------
   fInputData = std::move(inputData);
 }
 
+
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void L1Algo::ReceiveParameters(Parameters&& parameters)
+void Framework::ReceiveParameters(Parameters&& parameters)
 {
   fParameters = std::move(parameters);
 
@@ -76,34 +80,43 @@ void L1Algo::ReceiveParameters(Parameters&& parameters)
   ca::FieldRegion::ForceUseOfOriginalField(fParameters.DevIsUseOfOriginalField());
 }
 
-int L1Algo::GetMcTrackIdForCaHit(int iHit) const
+int Framework::GetMcTrackIdForCaHit(int /*iHit*/) const
 {
+  return -1;
+  /*
   int hitId    = iHit;
   int iMcPoint = CbmL1::Instance()->GetHitBestMcRefs()[hitId];
   if (iMcPoint < 0) return -1;
   return CbmL1::Instance()->GetMcPoints()[iMcPoint].ID;
+  */
 }
 
-int L1Algo::GetMcTrackIdForWindowHit(int iHit) const
+int Framework::GetMcTrackIdForWindowHit(int /*iHit*/) const
 {
+  return -1;
+  /*
   int hitId    = fWindowHits[iHit].Id();
   int iMcPoint = CbmL1::Instance()->GetHitBestMcRefs()[hitId];
   if (iMcPoint < 0) return -1;
   return CbmL1::Instance()->GetMcPoints()[iMcPoint].ID;
+  */
 }
 
-const CbmL1MCTrack* L1Algo::GetMcTrackForWindowHit(int iHit) const
+/*
+const CbmL1MCTrack* Framework::GetMcTrackForWindowHit(int iHit) const
 {
+  return nullptr;
   int id = GetMcTrackIdForWindowHit(iHit);
   if (id < 0) return nullptr;
   return &CbmL1::Instance()->GetMcTracks()[id];
 }
+*/
 
-//   bool L1Algo::SortTrip(TripSort const& a, TripSort const& b) {
+//   bool Framework::SortTrip(TripSort const& a, TripSort const& b) {
 //       return   ( a.trip.GetLevel() >  b.trip.GetLevel() );
 // }
 //
-// bool L1Algo::SortCand(CandSort const& a, CandSort const& b) {
+// bool Framework::SortCand(CandSort const& a, CandSort const& b) {
 //     if (a.cand.Lengtha != b.cand.Lengtha) return (a.cand.Lengtha > b.cand.Lengtha);
 //
 //     if (a.cand.ista != b.cand.ista ) return (a.cand.ista  < b.cand.ista );
@@ -114,8 +127,8 @@ const CbmL1MCTrack* L1Algo::GetMcTrackForWindowHit(int iHit) const
 //    // return (a.cand.CandIndex > b.cand.CandIndex );
 // }
 
-//   inline int L1Algo::PackIndex(const int& a, const int& b, const int& c) {
+//   inline int Framework::PackIndex(const int& a, const int& b, const int& c) {
 //       return   (a) + ((b)*10000) + (c*100000000);
 // }
 //
-//   inline int L1Algo::UnPackIndex(const int& i, int& a, int& b, int& c) {
+//   inline int Framework::UnPackIndex(const int& i, int& a, int& b, int& c) {
diff --git a/algo/ca/core/tracking/CaFramework.h b/algo/ca/core/tracking/CaFramework.h
new file mode 100644
index 0000000000..a279435e0d
--- /dev/null
+++ b/algo/ca/core/tracking/CaFramework.h
@@ -0,0 +1,358 @@
+/* Copyright (C) 2007-2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Maksym Zyzak, Valentina Akishina, Igor Kulakov [committer], Sergei Zharko */
+
+#pragma once  // include this header only once per compilation unit
+
+#include <array>
+#include <iomanip>
+#include <iostream>
+#include <limits>
+#include <map>
+
+#include "CaBranch.h"
+#include "CaCloneMerger.h"
+#include "CaConstants.h"
+#include "CaField.h"
+#include "CaGrid.h"
+#include "CaGridEntry.h"
+#include "CaHit.h"
+#include "CaInputData.h"
+#include "CaMeasurementXy.h"
+#include "CaParameters.h"
+#include "CaStation.h"
+#include "CaTimer.h"
+#include "CaTrack.h"
+#include "CaTrackExtender.h"
+#include "CaTrackFinder.h"
+#include "CaTrackFinderWindow.h"
+#include "CaTrackFitter.h"
+#include "CaTrackParam.h"
+#include "CaTrackingMonitor.h"
+#include "CaTriplet.h"
+#include "CaVector.h"
+
+namespace cbm::algo::ca
+{
+  class TripletConstructor;
+
+
+  namespace
+  {
+    using namespace cbm::algo;  // to keep ca:: prefices in the code
+  }
+
+  //namespace
+  //{
+  //  using cbm::algo::ca::Track;      // TMP
+  //  using cbm::algo::ca::Vector;     // TMP
+  //  using cbm::algo::ca::Iteration;  // TMP
+  //}  // namespace
+
+  // *******************************
+  // ** Types definition (global) **
+  // *******************************
+
+  using CaStationsArray_t = std::array<ca::Station, constants::size::MaxNstations>;
+  using CaMaterialArray_t = std::array<ca::MaterialMap, constants::size::MaxNstations>;
+  using Tindex            = int;  // TODO: Replace with ca::HitIndex_t, if suitable
+
+  struct CaHitTimeInfo {
+    fscal fEventTimeMin {-std::numeric_limits<fscal>::max() / 2.};
+    fscal fEventTimeMax {std::numeric_limits<fscal>::max() / 2.};
+    fscal fMaxTimeBeforeHit {0.};  //< max event time for hits [0 .. hit] in the station hit array
+    fscal fMinTimeAfterHit {0.};   //< min event time for hits [hit ... ] in the station hit array
+  };
+
+  /// Main class of CA track finder algorithm
+  ///
+  class Framework {
+  public:
+    // *************************
+    // ** Friend classes list **
+    // *************************
+
+    friend class ca::TripletConstructor;
+    friend class ca::TrackExtender;
+    friend class ca::TrackFitter;
+    friend class ca::TrackFinderWindow;
+    friend class ca::TrackFinder;
+
+    ///---------------------------
+    /// Internal enumerations
+
+    enum TrackingMode
+    {
+      kSts,
+      kGlobal,
+      kMcbm
+    };
+
+    // **********************************
+    // ** Member functions declaration **
+    // **********************************
+
+    // ** Constructors and destructor
+
+    /// Constructor
+    Framework();
+
+    /// Copy constructor
+    Framework(const Framework&) = delete;
+
+    /// Move constructor
+    Framework(Framework&&) = delete;
+
+    /// Copy assignment operator
+    Framework& operator=(const Framework&) = delete;
+
+    /// Move assignment operator
+    Framework& operator=(Framework&&) = delete;
+
+    /// Destructor
+    ~Framework() = default;
+
+
+    // ** Functions, which pack and unpack indexes of station and triplet **
+
+    // TODO: move to ca::Triplet class (S.Zharko)
+    /// Packs station and triplet indices to an unique triplet ID
+    /// \param  iStation  Index of station in the active stations array
+    /// \param  iTriplet  Index of triplet
+    static unsigned int PackTripletId(unsigned int iStation, unsigned int iTriplet);
+
+    /// Unpacks the triplet ID to its station index
+    /// \param  id  Unique triplet ID
+    static unsigned int TripletId2Station(unsigned int id);
+
+    /// Unpacks the triplet ID to its triplet index
+    /// \param  id  Unique triplet ID
+    static unsigned int TripletId2Triplet(unsigned int id);
+
+
+    /// Sets Framework parameters object
+    /// \param other - reference to the Parameters object
+    void SetParameters(const Parameters& other) { fParameters = other; }
+    // TODO: remove it (S.Zharko)
+
+    /// Gets a pointer to the Framework parameters object
+    const Parameters& GetParameters() const { return fParameters; }
+
+    /// Receives input data
+    void ReceiveInputData(InputData&& inputData);
+
+    /// Receives tracking parameters
+    void ReceiveParameters(Parameters&& parameters);
+
+    /// Gets pointer to input data object for external access
+    const InputData& GetInputData() const { return fInputData; }
+
+    int PackIndex(const int& a, const int& b, const int& c);
+
+    int UnPackIndex(const int& i, int& a, int& b, int& c);
+
+    /// \brief Sets a default particle mass for the track fit
+    ///
+    /// The function is used during the reconstruction in order to estimate the multiple scattering and energy loss
+    /// \param mass Default particle mass
+    void SetDefaultParticleMass(float mass) { fDefaultMass = mass; }
+
+    /// Gets default particle mass
+    /// \return particle mass
+    float GetDefaultParticleMass() const { return fDefaultMass; }
+
+    /// Gets default particle mass squared
+    /// \return particle mass squared
+    float GetDefaultParticleMass2() const { return fDefaultMass * fDefaultMass; }
+
+
+    /*********************************************************************************************/ /**
+   *                             ------  FUNCTIONAL PART ------
+   ************************************************************************************************/
+
+
+    void Init(const TrackingMode mode);
+
+    void Finish();
+
+    void PrintHits();
+
+    float GetMaxInvMom() const { return fMaxInvMom[0]; }
+
+    /// Gets reference to the monitor
+    const TrackingMonitor& GetMonitor() const { return fMonitor; }
+
+  public:
+    /// Gets number of stations before the pipe (MVD stations in CBM)
+    int GetNstationsBeforePipe() const { return fNstationsBeforePipe; }
+
+    /// Gets number of stations situated in field region (MVD + STS in CBM)
+    int GetNfieldStations() const { return fNfieldStations; }
+
+    /// Get mc track ID for a hit (debug tool)
+    int GetMcTrackIdForCaHit(int iHit) const;
+
+    /// Get mc track ID for a hit (debug tool)
+    int GetMcTrackIdForWindowHit(int iGridHit) const;
+
+    // const CbmL1MCTrack* GetMcTrackForWindowHit(int iHit) const;
+
+  private:
+    int fNstationsBeforePipe {0};                    ///< number of stations before pipe (MVD stations in CBM)
+    int fNfieldStations {0};                         ///< number of stations in the field region
+    float fDefaultMass {constants::phys::MuonMass};  ///< mass of the propagated particle [GeV/c2]
+
+
+    // ***************************
+    // ** Member variables list **
+    // ***************************
+
+    Parameters fParameters;  ///< Object of Framework parameters class
+    InputData fInputData;    ///< Tracking input data
+
+    Vector<unsigned char> fvHitKeyFlags {
+      "Framework::fvHitKeyFlags"};  ///< List of key flags: has been this hit or cluster already used
+
+    ca::TrackingMonitor fMonitor {"CA Algo"};  ///< Tracking monitor
+
+  public:
+    Vector<CaHitTimeInfo> fHitTimeInfo;
+
+    ca::Grid vGrid[constants::size::MaxNstations];  ///<
+
+    /// ----- Data used during track finding -----
+    ///
+
+    ///\brief hits of the current time window
+    /// it is a portion of fInputData to process in the current time window
+    /// hit.Id is replaced by the hit index in fInputData
+    Vector<ca::Hit> fWindowHits {"Framework::fWindowHits"};
+
+    Vector<unsigned char> fIsWindowHitSuppressed {"Framework::fIsWindowHitSuppressed"};
+
+    ///\brief first index of the station hits in the time window
+    ca::HitIndex_t fStationHitsStartIndex[constants::size::MaxNstations + 1] {0};
+
+    ///\brief number of station hits in the time window
+    ca::HitIndex_t fStationNhits[constants::size::MaxNstations + 1] {0};
+
+    /// ----------
+
+    double fCaRecoTime {0.};  // time of the track finder + fitter
+
+    Vector<Track> fRecoTracks {"Framework::fRecoTracks"};       ///< reconstructed tracks
+    Vector<ca::HitIndex_t> fRecoHits {"Framework::fRecoHits"};  ///< packed hits of reconstructed tracks
+
+    Vector<Track> fSliceRecoTracks {"Framework::fSliceRecoTracks"};       ///< reconstructed tracks in sub-timeslice
+    Vector<ca::HitIndex_t> fSliceRecoHits {"Framework::fSliceRecoHits"};  ///< packed hits of reconstructed tracks
+
+    /// Created triplets vs station index
+    Vector<ca::Triplet> fTriplets[constants::size::MaxNstations] {{"Framework::fTriplets"}};
+
+    /// Track candidates created out of adjacent triplets before the final track selection.
+    /// The candidates may share any amount of hits.
+    Vector<ca::Branch> fTrackCandidates {"Framework::fTrackCandidates"};
+
+    ///< indices of the sub-slice hits
+    Vector<ca::HitIndex_t> fSliceHitIds[constants::size::MaxNstations] {"Framework::fSliceHitIds"};
+
+    Vector<int> fStripToTrack {"Framework::fStripToTrack"};  // strip to track pointers
+
+    TrackingMode fTrackingMode {kSts};
+
+    fvec EventTime {0.f};
+    fvec Err {0.f};
+
+    /// --- data used during finding iterations
+    unsigned int fCurrentIterationIndex {0};        ///< index of the corrent iteration, needed for debug output
+    const Iteration* fpCurrentIteration = nullptr;  ///< pointer to the current CA track finder iteration
+
+    Vector<int> fHitFirstTriplet {"Framework::fHitFirstTriplet"};  /// link hit -> first triplet { hit, *, *}
+    Vector<int> fHitNtriplets {"Framework::fHitNtriplets"};        /// link hit ->n triplets { hit, *, *}
+
+
+  public:
+    ca::TrackExtender fTrackExtender {*this};          ///< Object of the track extender algorithm
+    ca::CloneMerger fCloneMerger {*this};              ///< Object of  the clone merger algorithm
+    ca::TrackFitter fTrackFitter {*this};              ///< Object of the track extender algorithm
+    ca::TrackFinderWindow fTrackFinderWindow {*this};  ///< Object of the track finder algorithm for the time window
+    ca::TrackFinder fTrackFinder {*this};  ///< Object of the track finder algorithm for the entire time slice
+
+  private:
+    /// =================================  DATA PART  =================================
+
+    /// ----- Different parameters of CATrackFinder -----
+
+    Tindex fFirstCAstation {0};  //first station used in CA
+
+    // fNFindIterations - set number of interation for trackfinding
+    // itetation of finding:
+
+    int fNFindIterations = -1;  // TODO investigate kAllPrimJumpIter & kAllSecJumpIter
+
+    float fTrackChi2Cut {10.f};
+    float fTripletFinalChi2Cut {10.f};
+    float fTripletChi2Cut {5.f};  // cut for selecting triplets before collecting tracks.per one DoF
+    float fDoubletChi2Cut {5.f};
+    float fTimeCut1 {0.f};  // TODO: please, specify "1" and "2" (S.Zharko)
+    float fTimeCut2 {0.f};
+
+    /// correction in order to take into account overlaping and iff z. if sort by y then it is max diff between same station's modules (~0.4cm)
+    fvec fMaxDZ {constants::Undef<fvec>};
+
+    /// parameters which are different for different iterations. Set in the begin of CA Track Finder
+
+    float fPickGather {constants::Undef<fvec>};  ///< same for attaching additional hits to track
+    float fTripletLinkChi2 {
+      constants::Undef<fvec>};                  ///< (dp2/dp_error2 < fTripletLinkChi2)  =>  triplets are neighbours
+    fvec fMaxInvMom {constants::Undef<fvec>};   ///< max considered q/p for tracks
+    fvec fMaxSlopePV {constants::Undef<fvec>};  ///< max slope (tx\ty) in prim vertex
+    float fMaxSlope {constants::Undef<fvec>};   ///< max slope (tx\ty) in 3d hit position of a triplet
+
+    fvec fTargX {constants::Undef<fvec>};  ///< target position x coordinate for the current iteration (modifiable)
+    fvec fTargY {constants::Undef<fvec>};  ///< target position y coordinate for the current iteration (modifiable)
+    fvec fTargZ {constants::Undef<fvec>};  ///< target position z coordinate for the current iteration (modifiable)
+
+    bool fIsTargetField {false};  ///< is the magnetic field present at the target
+
+    ca::FieldValue fTargB _fvecalignment {};  // field in the target point (modifiable, do not touch!!)
+    ca::MeasurementXy<fvec> TargetMeasurement _fvecalignment {};  // target constraint  [cm]
+
+    int fGhostSuppression {1};  // NOTE: Should be equal to 0 in TRACKS_FROM_TRIPLETS mode!
+
+  } _fvecalignment;
+
+
+  // ********************************************
+  // ** Inline member functions implementation **
+  // ********************************************
+
+  // ---------------------------------------------------------------------------------------------------------------------
+  //
+  [[gnu::always_inline]] inline unsigned int Framework::PackTripletId(unsigned int iStation, unsigned int iTriplet)
+  {
+#ifndef FAST_CODE
+    assert(iStation < constants::size::MaxNstations);
+    assert(iTriplet < constants::size::MaxNtriplets);
+#endif
+    constexpr unsigned int kMoveStation = constants::size::TripletBits;
+    return (iStation << kMoveStation) + iTriplet;
+  }
+
+  // ---------------------------------------------------------------------------------------------------------------------
+  //
+  [[gnu::always_inline]] inline unsigned int Framework::TripletId2Station(unsigned int id)
+  {
+    constexpr unsigned int kMoveStation = constants::size::TripletBits;
+    return id >> kMoveStation;
+  }
+
+  // ---------------------------------------------------------------------------------------------------------------------
+  //
+  [[gnu::always_inline]] inline unsigned int Framework::TripletId2Triplet(unsigned int id)
+  {
+    constexpr unsigned int kTripletMask = (1u << constants::size::TripletBits) - 1u;
+    return id & kTripletMask;
+  }
+
+}  // namespace cbm::algo::ca
diff --git a/reco/L1/L1Algo/L1BranchExtender.cxx b/algo/ca/core/tracking/CaTrackExtender.cxx
similarity index 60%
rename from reco/L1/L1Algo/L1BranchExtender.cxx
rename to algo/ca/core/tracking/CaTrackExtender.cxx
index fb0490dd0d..0bfbb98c4f 100644
--- a/reco/L1/L1Algo/L1BranchExtender.cxx
+++ b/algo/ca/core/tracking/CaTrackExtender.cxx
@@ -2,34 +2,45 @@
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Igor Kulakov [committer], Maksym Zyzak, Valentina Akishina */
 
+#include "CaTrackExtender.h"
+
 #include <iostream>
 
 #include "CaBranch.h"
 #include "CaDefines.h"
+#include "CaFramework.h"
 #include "CaGridArea.h"
 #include "CaTrack.h"
 #include "CaTrackFit.h"
 #include "CaTrackParam.h"
 #include "CaVector.h"
-#include "L1Algo.h"
 
 // using namespace std;
 using cbm::algo::ca::Vector;  // TMP!!
 using std::cout;
 using std::endl;
 
-/// Fit track
-/// t - track with hits
-/// T - track params
-/// qp0 - momentum for extrapolation
-/// initialize - should be params ititialized. 1 - yes.
-void L1Algo::BranchFitterFast(const ca::Branch& t, TrackParamV& Tout, const bool upstream, const fvec qp0,
-                              const bool initParams)
+using namespace cbm::algo::ca;
+
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+TrackExtender::TrackExtender(const ca::Framework& algo) : frAlgo(algo) {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+TrackExtender::~TrackExtender() {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+
+void TrackExtender::FitBranchFast(const ca::Branch& t, TrackParamV& Tout, const bool upstream, const fvec qp0,
+                                  const bool initParams)
 {
   CBMCA_DEBUG_ASSERT(t.NHits >= 3);
 
   ca::TrackFit fit;
-  fit.SetParticleMass(GetDefaultParticleMass());
+  fit.SetParticleMass(frAlgo.GetDefaultParticleMass());
   fit.SetMask(fmask::One());
   fit.SetTrack(Tout);
   TrackParamV& T = fit.Tr();
@@ -42,17 +53,17 @@ void L1Algo::BranchFitterFast(const ca::Branch& t, TrackParamV& Tout, const bool
   const int iFirstHit         = (upstream) ? nHits - 1 : 0;
   const int iLastHit          = (upstream) ? 0 : nHits - 1;
 
-  const ca::Hit& hit0 = fInputData.GetHit(hits[iFirstHit]);
-  const ca::Hit& hit1 = fInputData.GetHit(hits[iFirstHit + step]);
-  const ca::Hit& hit2 = fInputData.GetHit(hits[iFirstHit + 2 * step]);
+  const ca::Hit& hit0 = frAlgo.GetInputData().GetHit(hits[iFirstHit]);
+  const ca::Hit& hit1 = frAlgo.GetInputData().GetHit(hits[iFirstHit + step]);
+  const ca::Hit& hit2 = frAlgo.GetInputData().GetHit(hits[iFirstHit + 2 * step]);
 
   int ista0 = hit0.Station();
   int ista1 = hit1.Station();
   int ista2 = hit2.Station();
 
-  const ca::Station& sta0 = fParameters.GetStation(ista0);
-  const ca::Station& sta1 = fParameters.GetStation(ista1);
-  const ca::Station& sta2 = fParameters.GetStation(ista2);
+  const ca::Station& sta0 = frAlgo.GetParameters().GetStation(ista0);
+  const ca::Station& sta1 = frAlgo.GetParameters().GetStation(ista1);
+  const ca::Station& sta2 = frAlgo.GetParameters().GetStation(ista2);
 
   fvec x0 = hit0.X();
   fvec y0 = hit0.Y();
@@ -100,13 +111,13 @@ void L1Algo::BranchFitterFast(const ca::Branch& t, TrackParamV& Tout, const bool
   fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
 
   for (int i = iFirstHit + step; step * i <= step * iLastHit; i += step) {
-    const ca::Hit& hit     = fInputData.GetHit(hits[i]);
+    const ca::Hit& hit     = frAlgo.GetInputData().GetHit(hits[i]);
     int ista               = hit.Station();
-    const ca::Station& sta = fParameters.GetStation(ista);
+    const ca::Station& sta = frAlgo.GetParameters().GetStation(ista);
 
     fit.Extrapolate(hit.Z(), fld);
     fit.FilterHit(sta, hit);
-    auto radThick = fParameters.GetMaterialThickness(ista, T.X(), T.Y());
+    auto radThick = frAlgo.GetParameters().GetMaterialThickness(ista, T.X(), T.Y());
     fit.MultipleScattering(radThick);
     fit.EnergyLossCorrection(radThick, fvec(upstream ? 1. : -1.));
 
@@ -120,50 +131,46 @@ void L1Algo::BranchFitterFast(const ca::Branch& t, TrackParamV& Tout, const bool
   }  // i
 
   Tout = T;
-}  // void L1Algo::BranchFitterFast
+}  // void ca::Framework::BranchFitterFast
 
 /// like BranchFitterFast but more precise
-void L1Algo::BranchFitter(const ca::Branch& t, TrackParamV& T, const bool upstream, const fvec qp0,
-                          const bool initParams)
+void TrackExtender::FitBranch(const ca::Branch& t, TrackParamV& T, const bool upstream, const fvec qp0,
+                              const bool initParams)
 {
-  BranchFitterFast(t, T, upstream, qp0, initParams);
+  FitBranchFast(t, T, upstream, qp0, initParams);
   for (int i = 0; i < 1; i++) {
-    BranchFitterFast(t, T, !upstream, T.Qp(), false);
-    BranchFitterFast(t, T, upstream, T.Qp(), false);
+    FitBranchFast(t, T, !upstream, T.Qp(), false);
+    FitBranchFast(t, T, upstream, T.Qp(), false);
   }
-}  // void L1Algo::BranchFitter
-
-/// Find additional hits for existing track
-/// t - track with hits
-/// T - track params
-/// qp0 - momentum for extrapolation
-/// initialize - should be params ititialized. 1 - yes.
-void L1Algo::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool upstream, const fvec qp0)
+}  // void ca::Framework::BranchFitter
+
+
+void TrackExtender::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool upstream, const fvec qp0)
 {
-  Vector<ca::HitIndex_t> newHits {"L1TrackExtender::newHits"};
-  newHits.reserve(fParameters.GetNstationsActive());
+  Vector<ca::HitIndex_t> newHits {"ca::TrackExtender::newHits"};
+  newHits.reserve(frAlgo.GetParameters().GetNstationsActive());
 
   ca::TrackFit fit;
-  fit.SetParticleMass(GetDefaultParticleMass());
+  fit.SetParticleMass(frAlgo.GetDefaultParticleMass());
   fit.SetMask(fmask::One());
   fit.SetTrack(Tout);
   fit.SetQp0(qp0);
 
   const signed short int step = -2 * static_cast<int>(upstream) + 1;  // increment for station index
   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
+  //  int ista = frAlgo.GetInputData().GetHit(t.Hits[iFirstHit]).iSt + 2 * step; // current station. set to the end of track
 
-  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 ca::Hit& hit0 = frAlgo.GetInputData().GetHit(t.Hits()[iFirstHit]);  // optimize
+  const ca::Hit& hit1 = frAlgo.GetInputData().GetHit(t.Hits()[iFirstHit + step]);
+  const ca::Hit& hit2 = frAlgo.GetInputData().GetHit(t.Hits()[iFirstHit + 2 * step]);
 
   const int ista0 = hit0.Station();
   const int ista1 = hit1.Station();
   const int ista2 = hit2.Station();
 
-  const ca::Station& sta0 = fParameters.GetStation(ista0);
-  const ca::Station& sta1 = fParameters.GetStation(ista1);
-  const ca::Station& sta2 = fParameters.GetStation(ista2);
+  const ca::Station& sta0 = frAlgo.GetParameters().GetStation(ista0);
+  const ca::Station& sta1 = frAlgo.GetParameters().GetStation(ista1);
+  const ca::Station& sta2 = frAlgo.GetParameters().GetStation(ista2);
 
   fvec x0 = hit0.X();
   fvec y0 = hit0.Y();
@@ -187,13 +194,13 @@ void L1Algo::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool upstream,
 
   int ista = ista2 + 2 * step;  // skip one station. if there would be hit it has to be found on previous stap
 
-  if (ista2 == fFirstCAstation) ista = ista2 + step;
+  if (ista2 == frAlgo.fFirstCAstation) ista = ista2 + step;
 
-  const fvec pickGather2 = fPickGather * fPickGather;
+  const fvec pickGather2 = frAlgo.fPickGather * frAlgo.fPickGather;
 
-  for (; (ista < fParameters.GetNstationsActive()) && (ista >= 0); ista += step) {  // CHECKME why ista2?
+  for (; (ista < frAlgo.GetParameters().GetNstationsActive()) && (ista >= 0); ista += step) {  // CHECKME why ista2?
 
-    const ca::Station& sta = fParameters.GetStation(ista);
+    const ca::Station& sta = frAlgo.GetParameters().GetStation(ista);
 
     fit.Extrapolate(sta.fZ, fld);
 
@@ -202,18 +209,19 @@ void L1Algo::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool upstream,
 
     TrackParamV& tr = fit.Tr();
 
-    ca::GridArea area(vGrid[ista], tr.X()[0], tr.Y()[0],
-                      (sqrt(fPickGather * tr.C00()) + vGrid[ista].GetMaxRangeX() + fMaxDZ * abs(tr.Tx()))[0],
-                      (sqrt(fPickGather * tr.C11()) + vGrid[ista].GetMaxRangeY() + fMaxDZ * abs(tr.Ty()))[0]);
+    ca::GridArea area(
+      frAlgo.vGrid[ista], tr.X()[0], tr.Y()[0],
+      (sqrt(frAlgo.fPickGather * tr.C00()) + frAlgo.vGrid[ista].GetMaxRangeX() + frAlgo.fMaxDZ * abs(tr.Tx()))[0],
+      (sqrt(frAlgo.fPickGather * tr.C11()) + frAlgo.vGrid[ista].GetMaxRangeY() + frAlgo.fMaxDZ * abs(tr.Ty()))[0]);
 
-    if (fParameters.DevIsIgnoreHitSearchAreas()) { area.DoLoopOverEntireGrid(); }
+    if (frAlgo.GetParameters().DevIsIgnoreHitSearchAreas()) { area.DoLoopOverEntireGrid(); }
 
     ca::HitIndex_t ih = 0;
 
     while (area.GetNextObjectId(ih)) {  // loop over the hits in the area
 
-      if (fIsWindowHitSuppressed[ih]) { continue; }
-      const ca::Hit& hit = fWindowHits[ih];
+      if (frAlgo.fIsWindowHitSuppressed[ih]) { continue; }
+      const ca::Hit& hit = frAlgo.fWindowHits[ih];
 
       if (sta.timeInfo && tr.NdfTime()[0] > -2.) {
         fscal dt = hit.T() - tr.Time()[0];
@@ -221,10 +229,8 @@ void L1Algo::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool upstream,
       }
 
       //if (GetFUsed((*fStripFlag)[hit.f] | (*fStripFlag)[hit.b])) continue;  // if used
-      //L1_SHOW(fvHitKeyFlags.size());
-      //L1_SHOW(hit.f);
-      //L1_SHOW(hit.b);
-      if (fvHitKeyFlags[hit.FrontKey()] || fvHitKeyFlags[hit.BackKey()]) { continue; }
+
+      if (frAlgo.fvHitKeyFlags[hit.FrontKey()] || frAlgo.fvHitKeyFlags[hit.BackKey()]) { continue; }
 
       auto [y, C11] = fit.ExtrapolateLineYdY2(hit.Z());
 
@@ -239,7 +245,7 @@ void L1Algo::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool upstream,
       fscal d2  = d_x * d_x + d_y * d_y;
       if (d2 > r2_best) continue;
 
-      fscal dxm_est = sqrt(pickGather2 * C00)[0] + vGrid[ista].GetMaxRangeX();
+      fscal dxm_est = sqrt(pickGather2 * C00)[0] + frAlgo.vGrid[ista].GetMaxRangeX();
       if (fabs(d_x) > dxm_est) continue;
 
       r2_best   = d2;
@@ -248,13 +254,13 @@ void L1Algo::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool upstream,
 
     if (iHit_best < 0) break;
 
-    newHits.push_back(fWindowHits[iHit_best].Id());
+    newHits.push_back(frAlgo.fWindowHits[iHit_best].Id());
 
-    const ca::Hit& hit = fWindowHits[iHit_best];
+    const ca::Hit& hit = frAlgo.fWindowHits[iHit_best];
 
     fit.Extrapolate(hit.Z(), fld);
     fit.FilterHit(sta, hit);
-    auto radThick = fParameters.GetMaterialThickness(ista, tr.X(), tr.Y());
+    auto radThick = frAlgo.GetParameters().GetMaterialThickness(ista, tr.X(), tr.Y());
     fit.MultipleScattering(radThick);
     fit.EnergyLossCorrection(radThick, upstream ? fvec(1.f) : fvec(-1.f));
 
@@ -288,10 +294,10 @@ void L1Algo::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const bool upstream,
 
   Tout = fit.Tr();
 
-}  // void L1Algo::FindMoreHits
+}  // void ca::Framework::FindMoreHits
 
 /// Try to extrapolate and find additional hits on other stations
-fscal L1Algo::BranchExtender(ca::Branch& t)  // TODO Simdize
+fscal TrackExtender::ExtendBranch(ca::Branch& t)
 {
   //   const unsigned int minNHits = 3;
 
@@ -300,15 +306,13 @@ fscal L1Algo::BranchExtender(ca::Branch& t)  // TODO Simdize
   // downstream
   bool upstream = 0;
 
-  BranchFitter(t, T, upstream);
-  // BranchFitterFast (t, T, upstream, 0, true);
+  FitBranch(t, T, upstream, 0.0);
 
-  // if (t.NHits < minNHits) return T.chi2[0];
   FindMoreHits(t, T, upstream, T.Qp());
 
   // upstream
   upstream = 1;
-  BranchFitterFast(t, T, upstream, T.Qp(), false);
+  FitBranchFast(t, T, upstream, T.Qp(), false);
 
 
   FindMoreHits(t, T, upstream, T.Qp());
diff --git a/algo/ca/core/tracking/CaTrackExtender.h b/algo/ca/core/tracking/CaTrackExtender.h
new file mode 100644
index 0000000000..3e9ee941d6
--- /dev/null
+++ b/algo/ca/core/tracking/CaTrackExtender.h
@@ -0,0 +1,93 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer], Maksym Zyzak */
+
+/// \file    TrackExtender.h
+/// \authors S.Zharko <s.zharko@gsi.de> (interface), M.Zyzak (original algorithm)
+/// \brief   A class wrapper over clones merger algorithm for the CA track finder (declaration)
+/// \since   22.07.2022
+
+#pragma once  // include this header only once per compilation unit
+
+#include "CaBranch.h"
+#include "CaHit.h"
+#include "CaSimd.h"
+#include "CaTrackParam.h"
+#include "CaVector.h"
+
+
+namespace cbm::algo::ca
+{
+  class Track;
+  class Framework;
+
+  namespace
+  {
+    using namespace cbm::algo;  // to keep ca:: prefices in the code
+  }
+
+
+  /// Class implements a clones merger algorithm for the CA track finder
+  ///
+  class TrackExtender {
+  public:
+    /// Default constructor
+    TrackExtender(const ca::Framework& algo);
+
+    /// Destructor
+    ~TrackExtender();
+
+    /// Copy constructor
+    TrackExtender(const TrackExtender&) = delete;
+
+    /// Move constructor
+    TrackExtender(TrackExtender&&) = delete;
+
+    /// Copy assignment operator
+    TrackExtender& operator=(const TrackExtender&) = delete;
+
+    /// Move assignment operator
+    TrackExtender& operator=(TrackExtender&&) = delete;
+
+
+    /// Find additional hits for existing track both downstream and upstream
+    /// \return chi2
+    fscal ExtendBranch(ca::Branch& t);
+
+  private:
+    ///-------------------------------
+    /// Private methods
+
+    /// Finds additional hits for already found track in the given direction
+    /// \param t - track with hits
+    /// \param T - track params
+    /// \param dir - 0 - forward, 1 - backward
+    /// \param qp0 - momentum value to linearize the extrapolation
+    void FindMoreHits(ca::Branch& t, TrackParamV& T, const bool dir, const fvec qp0);
+
+    /// Fits the branch. Does few passes over the hits.
+    /// \param t - track branch with hits
+    /// \param T - track parameters
+    /// \param dir - false - forward, true - backward
+    /// \param qp0 - momentum value to linearize the extrapolation
+    /// \param initParams - should params be ititialized. 1 - yes.
+    void FitBranch(const ca::Branch& t, TrackParamV& T, const bool dir, const fvec qp0, const bool initParams = true);
+
+
+    /// Fits the branch. Does only one pass over the hits.
+    /// \param t - track branch with hits
+    /// \param T - track parameters
+    /// \param dir - false - forward, true - backward
+    /// \param qp0 - momentum value to linearize the extrapolation
+    /// \param initParams - should params be ititialized. 1 - yes.
+    void FitBranchFast(const ca::Branch& t, TrackParamV& T, const bool dir, const fvec qp0,
+                       const bool initParams = true);
+
+  private:
+    ///-------------------------------
+    /// Data members
+
+    const ca::Framework& frAlgo;  ///< Reference to the main track finder algorithm class
+  };
+
+}  // namespace cbm::algo::ca
diff --git a/reco/L1/L1Algo/L1CaTrackFinder.cxx b/algo/ca/core/tracking/CaTrackFinder.cxx
similarity index 53%
rename from reco/L1/L1Algo/L1CaTrackFinder.cxx
rename to algo/ca/core/tracking/CaTrackFinder.cxx
index fc80be5d5d..5e9732bd68 100644
--- a/reco/L1/L1Algo/L1CaTrackFinder.cxx
+++ b/algo/ca/core/tracking/CaTrackFinder.cxx
@@ -20,14 +20,27 @@
 
 #include <chrono>
 
+#include "CaFramework.h"
 #include "CaTrack.h"
-#include "L1Algo.h"
+
+using namespace cbm::algo::ca;
 
 using cbm::algo::ca::ECounter;
 using cbm::algo::ca::ETimer;
 using cbm::algo::ca::Track;
 
-void L1Algo::CaTrackFinder()
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+TrackFinder::TrackFinder(ca::Framework& algo) : frAlgo(algo) {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+TrackFinder::~TrackFinder() {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TrackFinder::FindTracks()
 {
   //
   // The main CaTrackFinder routine
@@ -36,60 +49,59 @@ void L1Algo::CaTrackFinder()
   //
 
   // Reset monitor
-  fMonitor.Reset();
-  fMonitor.IncrementCounter(ECounter::RecoHit, fInputData.GetNhits());
-  fMonitor.StartTimer(ETimer::Tracking);
+  frAlgo.fMonitor.Reset();
+  frAlgo.fMonitor.IncrementCounter(ECounter::RecoHit, frAlgo.fInputData.GetNhits());
+  frAlgo.fMonitor.StartTimer(ETimer::Tracking);
 
   auto timerStart = std::chrono::high_resolution_clock::now();
 
-
   // ----- Reset data arrays -------------------------------------------------------------------------------------------
-  fvHitKeyFlags.reset(fInputData.GetNhitKeys(), 0);
+  frAlgo.fvHitKeyFlags.reset(frAlgo.fInputData.GetNhitKeys(), 0);
 
-  fRecoTracks.clear();
-  fRecoHits.clear();
-  fRecoHits.reserve(2 * fInputData.GetNhits());
-  fRecoTracks.reserve(2 * fInputData.GetNhits() / fParameters.GetNstationsActive());
+  frAlgo.fRecoTracks.clear();
+  frAlgo.fRecoHits.clear();
+  frAlgo.fRecoHits.reserve(2 * frAlgo.fInputData.GetNhits());
+  frAlgo.fRecoTracks.reserve(2 * frAlgo.fInputData.GetNhits() / frAlgo.GetParameters().GetNstationsActive());
 
-  for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
-    fSliceHitIds[iS].clear();
-    fSliceHitIds[iS].reserve(fInputData.GetNhits());
+  for (int iS = 0; iS < frAlgo.GetParameters().GetNstationsActive(); ++iS) {
+    frAlgo.fSliceHitIds[iS].clear();
+    frAlgo.fSliceHitIds[iS].reserve(frAlgo.fInputData.GetNhits());
   }
 
-  fvHitKeyFlags.reset(fInputData.GetNhitKeys(), 0);
-  fHitTimeInfo.reset(fInputData.GetNhits());
+  frAlgo.fvHitKeyFlags.reset(frAlgo.fInputData.GetNhitKeys(), 0);
+  frAlgo.fHitTimeInfo.reset(frAlgo.fInputData.GetNhits());
 
-  // TODO: move these values to CbmL1Parameters namespace (S.Zharko)
+  // TODO: move these values to Parameters namespace (S.Zharko)
   const fscal tsLength    = 10000;  // length of sub-TS
   const fscal tsOverlap   = 15;     // min length of overlap region
   fscal minProtonMomentum = 0.1;
 
-  fscal targX = fParameters.GetTargetPositionX()[0];
-  fscal targY = fParameters.GetTargetPositionY()[0];
-  fscal targZ = fParameters.GetTargetPositionZ()[0];
+  fscal targX = frAlgo.GetParameters().GetTargetPositionX()[0];
+  fscal targY = frAlgo.GetParameters().GetTargetPositionY()[0];
+  fscal targZ = frAlgo.GetParameters().GetTargetPositionZ()[0];
 
   fscal tsStart = std::numeric_limits<fscal>::max();  // starting time of sub-TS
 
-  // calculate possible event time for the hits (fHitTimeInfo array)
+  // calculate possible event time for the hits (frAlgo.fHitTimeInfo array)
 
-  const int nDataStreams = fInputData.GetNdataStreams();
+  const int nDataStreams = frAlgo.fInputData.GetNdataStreams();
 
   for (int iStream = 0; iStream < nDataStreams; ++iStream) {
 
     fscal maxTimeBeforeHit = std::numeric_limits<fscal>::lowest();
 
-    int nStreamHits = fInputData.GetStreamNhits(iStream);
+    int nStreamHits = frAlgo.fInputData.GetStreamNhits(iStream);
 
     for (int ih = 0; ih < nStreamHits; ++ih) {
 
-      ca::HitIndex_t caHitId = fInputData.GetStreamStartIndex(iStream) + ih;
-      const ca::Hit& h       = fInputData.GetHit(caHitId);
-      const ca::Station& st  = fParameters.GetStation(h.Station());
+      ca::HitIndex_t caHitId = frAlgo.fInputData.GetStreamStartIndex(iStream) + ih;
+      const ca::Hit& h       = frAlgo.fInputData.GetHit(caHitId);
+      const ca::Station& st  = frAlgo.GetParameters().GetStation(h.Station());
 
-      fscal dx    = h.X() - targX;
-      fscal dy    = h.Y() - targY;
-      fscal dz    = h.Z() - targZ;
-      fscal l     = sqrt(dx * dx + dy * dy + dz * dz);
+      fscal dx = h.X() - targX;
+      fscal dy = h.Y() - targY;
+      fscal dz = h.Z() - targZ;
+      fscal l  = sqrt(dx * dx + dy * dy + dz * dz);
 
       fscal timeOfFlightMin = l * constants::phys::SpeedOfLightInv;
       fscal timeOfFlightMax =
@@ -98,7 +110,7 @@ void L1Algo::CaTrackFinder()
         * constants::phys::SpeedOfLightInvD;
       fscal dt = h.RangeT();
 
-      L1HitTimeInfo& info = fHitTimeInfo[caHitId];
+      CaHitTimeInfo& info = frAlgo.fHitTimeInfo[caHitId];
       info.fEventTimeMin  = h.T() - dt - timeOfFlightMax;
       info.fEventTimeMax  = h.T() + dt - timeOfFlightMin;
 
@@ -116,11 +128,11 @@ void L1Algo::CaTrackFinder()
     }
 
     fscal minTimeAfterHit = std::numeric_limits<fscal>::max();
-    // loop in the reverse order to fill L1HitTimeInfo::fMinTimeAfterHit fields
+    // loop in the reverse order to fill CaHitTimeInfo::fMinTimeAfterHit fields
 
     for (int ih = nStreamHits - 1; ih >= 0; --ih) {
-      ca::HitIndex_t caHitId = fInputData.GetStreamStartIndex(iStream) + ih;
-      L1HitTimeInfo& info  = fHitTimeInfo[caHitId];
+      ca::HitIndex_t caHitId = frAlgo.fInputData.GetStreamStartIndex(iStream) + ih;
+      CaHitTimeInfo& info    = frAlgo.fHitTimeInfo[caHitId];
       if (minTimeAfterHit > info.fEventTimeMin) { minTimeAfterHit = info.fEventTimeMin; }
       info.fMinTimeAfterHit = minTimeAfterHit;
     }
@@ -133,15 +145,16 @@ void L1Algo::CaTrackFinder()
   ca::HitIndex_t sliceFirstHit[nDataStreams];
 
   for (int iStream = 0; iStream < nDataStreams; ++iStream) {
-    sliceFirstHit[iStream] = fInputData.GetStreamStartIndex(iStream);
+    sliceFirstHit[iStream] = frAlgo.fInputData.GetStreamStartIndex(iStream);
   }
 
   while (areDataLeft) {
-    fMonitor.IncrementCounter(ECounter::SubTS);
+
+    frAlgo.fMonitor.IncrementCounter(ECounter::SubTS);
 
     // select the sub-slice hits
-    for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
-      fSliceHitIds[iS].clear();
+    for (int iS = 0; iS < frAlgo.GetParameters().GetNstationsActive(); ++iS) {
+      frAlgo.fSliceHitIds[iS].clear();
     }
 
     areDataLeft = false;
@@ -150,11 +163,12 @@ void L1Algo::CaTrackFinder()
 
     for (int iStream = 0; iStream < nDataStreams; ++iStream) {
 
-      for (ca::HitIndex_t caHitId = sliceFirstHit[iStream]; caHitId < fInputData.GetStreamStopIndex(iStream);
+      for (ca::HitIndex_t caHitId = sliceFirstHit[iStream]; caHitId < frAlgo.fInputData.GetStreamStopIndex(iStream);
            ++caHitId) {
-        L1HitTimeInfo& info = fHitTimeInfo[caHitId];
-        const ca::Hit& h    = fInputData.GetHit(caHitId);
-        if (fvHitKeyFlags[h.FrontKey()] || fvHitKeyFlags[h.BackKey()]) {  // the hit is already reconstructed
+        CaHitTimeInfo& info = frAlgo.fHitTimeInfo[caHitId];
+        const ca::Hit& h    = frAlgo.fInputData.GetHit(caHitId);
+        if (frAlgo.fvHitKeyFlags[h.FrontKey()]
+            || frAlgo.fvHitKeyFlags[h.BackKey()]) {  // the hit is already reconstructed
           continue;
         }
         if (info.fEventTimeMin > tsStart + tsLength) {  // the hit is too late for the sub slice
@@ -166,7 +180,7 @@ void L1Algo::CaTrackFinder()
         }
         else {
           if (tsStart <= info.fEventTimeMax) {  // the hit belongs to the sub-slice
-            fSliceHitIds[h.Station()].push_back(caHitId);
+            frAlgo.fSliceHitIds[h.Station()].push_back(caHitId);
             if (info.fMaxTimeBeforeHit < tsStart + tsLength - tsOverlap) {
               // this hit and all hits before are before the overlap
               sliceFirstHit[iStream] = caHitId + 1;
@@ -176,14 +190,13 @@ void L1Algo::CaTrackFinder()
       }
     }
 
-    fMonitor.StartTimer(ETimer::TrackFinder);
-    CaTrackFinderSlice();
-    fMonitor.StopTimer(ETimer::TrackFinder);
-
+    frAlgo.fMonitor.StartTimer(ETimer::TrackFinder);
+    frAlgo.fTrackFinderWindow.CaTrackFinderSlice();
+    frAlgo.fMonitor.StopTimer(ETimer::TrackFinder);
 
-    fMonitor.StartTimer(ETimer::TrackFitter);
-    L1KFTrackFitter();
-    fMonitor.StopTimer(ETimer::TrackFitter);
+    frAlgo.fMonitor.StartTimer(ETimer::TrackFitter);
+    frAlgo.fTrackFitter.FitCaTracks();
+    frAlgo.fMonitor.StopTimer(ETimer::TrackFitter);
 
     // save reconstructed tracks with no hits in the overlap region
 
@@ -194,11 +207,12 @@ void L1Algo::CaTrackFinder()
     // TODO: only add those hits from the region before tsStartNew that belong to the not stored tracks
 
     int trackFirstHit = 0;
-    for (auto it = fSliceRecoTracks.begin(); it != fSliceRecoTracks.end(); trackFirstHit += it->fNofHits, it++) {
+    for (auto it = frAlgo.fSliceRecoTracks.begin(); it != frAlgo.fSliceRecoTracks.end();
+         trackFirstHit += it->fNofHits, it++) {
       bool isTrackCompletelyInOverlap = true;
       for (int ih = 0; ih < it->fNofHits; ih++) {
-        int caHitId         = fSliceRecoHits[trackFirstHit + ih];
-        L1HitTimeInfo& info = fHitTimeInfo[caHitId];
+        int caHitId         = frAlgo.fSliceRecoHits[trackFirstHit + ih];
+        CaHitTimeInfo& info = frAlgo.fHitTimeInfo[caHitId];
         if (info.fEventTimeMax < tsStart) {  // this hit is before the overlap
           isTrackCompletelyInOverlap = false;
           break;
@@ -216,21 +230,21 @@ void L1Algo::CaTrackFinder()
 
         // release the track hits
         for (int i = 0; i < it->fNofHits; i++) {
-          int caHitId        = fSliceRecoHits[trackFirstHit + i];
-          const auto& h      = fInputData.GetHit(caHitId);
-          fvHitKeyFlags[h.FrontKey()] = 0;
-          fvHitKeyFlags[h.BackKey()]  = 0;
+          int caHitId                        = frAlgo.fSliceRecoHits[trackFirstHit + i];
+          const auto& h                      = frAlgo.fInputData.GetHit(caHitId);
+          frAlgo.fvHitKeyFlags[h.FrontKey()] = 0;
+          frAlgo.fvHitKeyFlags[h.BackKey()]  = 0;
         }
       }
       else {  // save the track
-        fRecoTracks.push_back(*it);
+        frAlgo.fRecoTracks.push_back(*it);
         // mark the track hits as used
         for (int i = 0; i < it->fNofHits; i++) {
-          int caHitId        = fSliceRecoHits[trackFirstHit + i];
-          const auto& h      = fInputData.GetHit(caHitId);
-          fvHitKeyFlags[h.FrontKey()] = 1;
-          fvHitKeyFlags[h.BackKey()]  = 1;
-          fRecoHits.push_back(caHitId);
+          int caHitId                        = frAlgo.fSliceRecoHits[trackFirstHit + i];
+          const auto& h                      = frAlgo.fInputData.GetHit(caHitId);
+          frAlgo.fvHitKeyFlags[h.FrontKey()] = 1;
+          frAlgo.fvHitKeyFlags[h.BackKey()]  = 1;
+          frAlgo.fRecoHits.push_back(caHitId);
         }
       }
     }  // sub-timeslice tracks
@@ -238,10 +252,10 @@ void L1Algo::CaTrackFinder()
     tsStart -= 5;  // do 5 ns margin
   }
 
-  auto timerEnd = std::chrono::high_resolution_clock::now();
-  fMonitor.StopTimer(ETimer::Tracking);
-  fMonitor.IncrementCounter(ECounter::RecoTrack, fRecoTracks.size());
-  fMonitor.IncrementCounter(ECounter::RecoHitUsed, fRecoHits.size());
+  frAlgo.fMonitor.StopTimer(ETimer::Tracking);
+  frAlgo.fMonitor.IncrementCounter(ECounter::RecoTrack, frAlgo.fRecoTracks.size());
+  frAlgo.fMonitor.IncrementCounter(ECounter::RecoHitUsed, frAlgo.fRecoHits.size());
 
-  fCaRecoTime   = (double) (std::chrono::duration<double>(timerEnd - timerStart).count());
+  auto timerEnd      = std::chrono::high_resolution_clock::now();
+  frAlgo.fCaRecoTime = (double) (std::chrono::duration<double>(timerEnd - timerStart).count());
 }
diff --git a/algo/ca/core/tracking/CaTrackFinder.h b/algo/ca/core/tracking/CaTrackFinder.h
new file mode 100644
index 0000000000..4e2db5dccc
--- /dev/null
+++ b/algo/ca/core/tracking/CaTrackFinder.h
@@ -0,0 +1,66 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer], Maksym Zyzak */
+
+/// \file    CaTrackFinder.h
+
+#pragma once  // include this header only once per compilation unit
+
+#include "CaBranch.h"
+#include "CaHit.h"
+#include "CaSimd.h"
+#include "CaTrackParam.h"
+#include "CaVector.h"
+
+
+namespace cbm::algo::ca
+{
+
+  class Track;
+  class Triplet;
+  class Framework;
+
+  namespace
+  {
+    using namespace cbm::algo;  // to keep ca:: prefices in the code
+  }
+
+  /// Class implements a clones merger algorithm for the CA track finder
+  ///
+  class TrackFinder {
+  public:
+    /// Default constructor
+    TrackFinder(ca::Framework& algo);
+
+    /// Destructor
+    ~TrackFinder();
+
+    /// Copy constructor
+    TrackFinder(const TrackFinder&) = delete;
+
+    /// Move constructor
+    TrackFinder(TrackFinder&&) = delete;
+
+    /// Copy assignment operator
+    TrackFinder& operator=(const TrackFinder&) = delete;
+
+    /// Move assignment operator
+    TrackFinder& operator=(TrackFinder&&) = delete;
+
+    void FindTracks();
+
+  private:
+    ///-------------------------------
+    /// Private methods
+
+    bool checkTripletMatch(const ca::Triplet& l, const ca::Triplet& r, fscal& dchi2) const;
+
+
+  private:
+    ///-------------------------------
+    /// Data members
+
+    ca::Framework& frAlgo;  ///< Reference to the main track finder algorithm class
+  };
+
+}  // namespace cbm::algo::ca
diff --git a/algo/ca/core/tracking/CaTrackFinderWindow.cxx b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
new file mode 100644
index 0000000000..25b4dcdec6
--- /dev/null
+++ b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
@@ -0,0 +1,771 @@
+/* Copyright (C) 2009-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Valentina Akishina, Ivan Kisel, Sergey Gorbunov [committer], Igor Kulakov, Maksym Zyzak */
+
+/*
+ *=====================================================
+ *
+ *  CBM Level 1 4D Reconstruction
+ *
+ *  Authors: V.Akishina, I.Kisel,  S.Gorbunov, I.Kulakov, M.Zyzak
+ *  Documentation: V.Akishina
+ *
+ *  e-mail : v.akishina@gsi.de
+ *
+ *=====================================================
+ *
+ *  Finds tracks using the Cellular Automaton algorithm
+ *
+ */
+
+
+#include "CaTrackFinderWindow.h"
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <list>
+#include <map>
+
+#include <stdio.h>
+
+#include "CaBranch.h"
+#include "CaFramework.h"
+#include "CaGrid.h"
+#include "CaGridEntry.h"
+#include "CaTrack.h"
+#include "CaTrackParam.h"
+#include "CaTripletConstructor.h"
+
+// #include "CaToolsDebugger.h"
+
+
+// using namespace std;
+using std::cout;
+using std::endl;
+using Track = cbm::algo::ca::Track;
+
+using namespace cbm::algo::ca;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+TrackFinderWindow::TrackFinderWindow(ca::Framework& algo) : frAlgo(algo) {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+TrackFinderWindow::~TrackFinderWindow() {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+
+
+bool TrackFinderWindow::checkTripletMatch(const ca::Triplet& l, const ca::Triplet& r, fscal& dchi2) const
+{
+  dchi2 = 1.e20;
+
+  if (r.GetMHit() != l.GetRHit()) return false;
+  if (r.GetLHit() != l.GetMHit()) return false;
+
+  if (r.GetMSta() != l.GetRSta()) return false;
+  if (r.GetLSta() != l.GetMSta()) return false;
+
+
+  if (r.IsMomentumFitted()) {
+    assert(l.IsMomentumFitted());
+
+    fscal dqp = l.GetQp() - r.GetQp();
+    fscal Cqp = l.GetCqp() + r.GetCqp();
+
+    if (!std::isfinite(dqp)) return false;
+    if (!std::isfinite(Cqp)) return false;
+
+    if (dqp * dqp > frAlgo.fTripletLinkChi2 * Cqp) {
+      return false;  // bad neighbour // CHECKME why do we need recheck it?? (it really change result)
+    }
+    dchi2 = dqp * dqp / Cqp;
+  }
+  else {
+    fscal dtx = l.GetTx() - r.GetTx();
+    fscal Ctx = l.GetCtx() + r.GetCtx();
+
+    fscal dty = l.GetTy() - r.GetTy();
+    fscal Cty = l.GetCty() + r.GetCty();
+
+    // it shouldn't happen, but happens sometimes
+
+    if (!std::isfinite(dtx)) return false;
+    if (!std::isfinite(dty)) return false;
+    if (!std::isfinite(Ctx)) return false;
+    if (!std::isfinite(Cty)) return false;
+
+    if (dty * dty > frAlgo.fTripletLinkChi2 * Cty) return false;
+    if (dtx * dtx > frAlgo.fTripletLinkChi2 * Ctx) return false;
+
+    //dchi2 = 0.5f * (dtx * dtx / Ctx + dty * dty / Cty);
+    dchi2 = 0.;
+  }
+
+  if (!std::isfinite(dchi2)) return false;
+
+  return true;
+}
+
+
+// **************************************************************************************************
+// *                                                                                                *
+// *                            ------ CATrackFinder procedure ------                               *
+// *                                                                                                *
+// **************************************************************************************************
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TrackFinderWindow::ReadWindowData()
+{
+  int nHits = 0;
+  for (int iS = 0; iS < frAlgo.GetParameters().GetNstationsActive(); iS++) {
+    frAlgo.fStationHitsStartIndex[iS] = nHits;
+    frAlgo.fStationNhits[iS]          = frAlgo.fSliceHitIds[iS].size();
+    nHits += frAlgo.fStationNhits[iS];
+  }
+  frAlgo.fStationHitsStartIndex[frAlgo.GetParameters().GetNstationsActive()] = nHits;
+
+  frAlgo.fWindowHits.reset(nHits);
+  frAlgo.fIsWindowHitSuppressed.reset(nHits, 0);
+
+  for (int iS = 0; iS < frAlgo.GetParameters().GetNstationsActive(); iS++) {
+    for (ca::HitIndex_t ih = 0; ih < frAlgo.fSliceHitIds[iS].size(); ++ih) {
+      ca::Hit h = frAlgo.fInputData.GetHit(frAlgo.fSliceHitIds[iS][ih]);
+      h.SetId(frAlgo.fSliceHitIds[iS][ih]);
+
+      frAlgo.fWindowHits[frAlgo.fStationHitsStartIndex[iS] + ih] = h;
+    }
+  }
+
+  frAlgo.fHitFirstTriplet.reset(nHits, 0);
+  frAlgo.fHitNtriplets.reset(nHits, 0);
+
+  // TODO: SG: reduce the array size to the number of keys in subslice
+
+  frAlgo.fStripToTrack.reset(frAlgo.fInputData.GetNhitKeys(), -1);
+
+  frAlgo.fSliceRecoTracks.clear();
+  frAlgo.fSliceRecoTracks.reserve(2 * nHits / frAlgo.GetParameters().GetNstationsActive());
+
+  frAlgo.fSliceRecoHits.clear();
+  frAlgo.fSliceRecoHits.reserve(2 * nHits);
+
+  frAlgo.fTrackCandidates.clear();
+  frAlgo.fTrackCandidates.reserve(nHits / 10);
+  for (unsigned int iS = 0; iS < constants::size::MaxNstations; iS++) {
+    int nHitsStation = frAlgo.fSliceHitIds[iS].size();
+    frAlgo.fTriplets[iS].clear();
+    frAlgo.fTriplets[iS].reserve(2 * nHitsStation);
+  }
+}
+
+void TrackFinderWindow::CaTrackFinderSlice()
+{
+  frAlgo.fNFindIterations = frAlgo.GetParameters().GetNcaIterations();
+
+
+  /********************************/ /**
+   * CATrackFinder routine setting
+   ***********************************/
+
+  ReadWindowData();
+
+  for (int iS = 0; iS < frAlgo.GetParameters().GetNstationsActive(); ++iS) {
+
+    bool timeUninitialised = 1;
+    fscal lasttime         = 0;
+    fscal starttime        = 0;
+
+
+    fscal gridMinX = -0.1;
+    fscal gridMaxX = 0.1;
+    fscal gridMinY = -0.1;
+    fscal gridMaxY = 0.1;
+
+    for (ca::HitIndex_t ih = 0; ih < frAlgo.fSliceHitIds[iS].size(); ++ih) {
+      const ca::Hit& h = frAlgo.fInputData.GetHit(frAlgo.fSliceHitIds[iS][ih]);
+
+      if (h.X() < gridMinX) { gridMinX = h.X(); }
+      if (h.X() > gridMaxX) { gridMaxX = h.X(); }
+      if (h.Y() < gridMinY) { gridMinY = h.Y(); }
+      if (h.Y() > gridMaxY) { gridMaxY = h.Y(); }
+
+      const fscal time = h.T();
+      assert(std::isfinite(time));
+      if (timeUninitialised || lasttime < time) { lasttime = time; }
+      if (timeUninitialised || starttime > time) { starttime = time; }
+      timeUninitialised = false;
+    }
+
+    // TODO: changing the grid also changes the result. Investigate why it happens.
+    // TODO: find the optimal grid size
+
+    int nSliceHits = frAlgo.fSliceHitIds[iS].size();
+    fscal sizeY    = gridMaxY - gridMinY;
+    fscal sizeX    = gridMaxX - gridMinX;
+    int nBins2D    = 1 + nSliceHits;
+    fscal yStep    = sizeY / sqrt(nBins2D);
+    fscal xStep    = sizeX / sqrt(nBins2D);
+
+    fscal scale = frAlgo.GetParameters().GetStation(iS).GetZScal() - frAlgo.GetParameters().GetTargetPositionZ()[0];
+
+    if (yStep > 0.3 * scale) yStep = 0.3 * scale;
+    if (yStep < 0.01 * scale) yStep = 0.01 * scale;
+    if (xStep > 0.3 * scale) xStep = 0.3 * scale;
+    if (xStep < 0.01 * scale) xStep = 0.01 * scale;
+
+    frAlgo.vGrid[iS].BuildBins(gridMinX, gridMaxX, gridMinY, gridMaxY, xStep, yStep);
+    frAlgo.vGrid[iS].StoreHits(frAlgo.fWindowHits, frAlgo.fStationHitsStartIndex[iS], frAlgo.fStationNhits[iS],
+                               frAlgo.fvHitKeyFlags);
+  }
+
+
+  // ---- Loop over Track Finder iterations ----------------------------------------------------------------//
+
+
+  assert(frAlgo.fNFindIterations == (int) frAlgo.GetParameters().GetCAIterations().size());
+
+  for (frAlgo.fCurrentIterationIndex = 0;
+       frAlgo.fCurrentIterationIndex < frAlgo.GetParameters().GetCAIterations().size();
+       ++frAlgo.fCurrentIterationIndex) {
+
+    // current iteration of the CA tracker
+    const auto& caIteration   = frAlgo.GetParameters().GetCAIterations()[frAlgo.fCurrentIterationIndex];
+    frAlgo.fpCurrentIteration = &caIteration;
+
+    if (frAlgo.fCurrentIterationIndex > 0) {
+      for (int ista = 0; ista < frAlgo.GetParameters().GetNstationsActive(); ++ista) {
+        frAlgo.vGrid[ista].RemoveUsedHits(frAlgo.fWindowHits, frAlgo.fvHitKeyFlags);
+      }
+    }
+
+    frAlgo.fIsWindowHitSuppressed.reset(frAlgo.fWindowHits.size(), 0);
+
+    for (int j = 0; j < frAlgo.GetParameters().GetNstationsActive(); j++) {
+      frAlgo.fTriplets[j].clear();
+    }
+
+    frAlgo.fHitFirstTriplet.reset(frAlgo.fWindowHits.size(), 0);
+    frAlgo.fHitNtriplets.reset(frAlgo.fWindowHits.size(), 0);
+
+    {
+      // #pragma omp  task
+      {
+        // --- SET PARAMETERS FOR THE ITERATION ---
+
+        frAlgo.fFirstCAstation      = caIteration.GetFirstStationIndex();
+        frAlgo.fTrackChi2Cut        = caIteration.GetTrackChi2Cut();
+        frAlgo.fDoubletChi2Cut      = caIteration.GetDoubletChi2Cut();  //11.3449 * 2.f / 3.f;  // prob = 0.1
+        frAlgo.fTripletChi2Cut      = caIteration.GetTripletChi2Cut();  //21.1075;  // prob = 0.01%
+        frAlgo.fTripletFinalChi2Cut = caIteration.GetTripletFinalChi2Cut();
+        frAlgo.fPickGather          = caIteration.GetPickGather();       //3.0;
+        frAlgo.fTripletLinkChi2     = caIteration.GetTripletLinkChi2();  //5.0;
+        frAlgo.fMaxInvMom           = caIteration.GetMaxQp();            //1.0 / 0.5;  // max considered q/p
+        frAlgo.fMaxSlopePV          = caIteration.GetMaxSlopePV();       //1.1;
+        frAlgo.fMaxSlope            = caIteration.GetMaxSlope();         //2.748;  // corresponds to 70 grad
+
+        // define the target
+        frAlgo.fTargX = frAlgo.GetParameters().GetTargetPositionX();
+        frAlgo.fTargY = frAlgo.GetParameters().GetTargetPositionY();
+        frAlgo.fTargZ = frAlgo.GetParameters().GetTargetPositionZ();
+
+        fscal SigmaTargetX = caIteration.GetTargetPosSigmaX();
+        fscal SigmaTargetY = caIteration.GetTargetPosSigmaY();  // target constraint [cm]
+
+        // Select magnetic field. For primary tracks - fVtxFieldValue, for secondary tracks - st.fieldSlice
+        if (caIteration.GetPrimaryFlag()) { frAlgo.fTargB = frAlgo.GetParameters().GetVertexFieldValue(); }
+        else {
+          frAlgo.fTargB = frAlgo.GetParameters().GetStation(0).fieldSlice.GetFieldValue(0, 0);
+        }  // NOTE: calculates field frAlgo.fTargB in the center of 0th station
+
+        frAlgo.fIsTargetField = (fabs(frAlgo.fTargB.y[0]) > 0.001);
+
+        frAlgo.TargetMeasurement.SetX(frAlgo.fTargX);
+        frAlgo.TargetMeasurement.SetY(frAlgo.fTargY);
+        frAlgo.TargetMeasurement.SetDx2(SigmaTargetX * SigmaTargetX);
+        frAlgo.TargetMeasurement.SetDxy(0);
+        frAlgo.TargetMeasurement.SetDy2(SigmaTargetY * SigmaTargetY);
+        frAlgo.TargetMeasurement.SetNdfX(1);
+        frAlgo.TargetMeasurement.SetNdfY(1);
+
+        /// Set correction in order to take into account overlaping and iff z.
+        /// The reason is that low momentum tracks are too curved and goes not from target direction. That's why sort by hit_y/hit_z is not work idealy
+        /// If sort by y then it is max diff between same station's modules (~0.4cm)
+        frAlgo.fMaxDZ = caIteration.GetMaxDZ();  //0;
+      }
+    }
+
+
+    ///   stage for triplets creation
+
+    frAlgo.fMonitor.StartTimer(ETimer::TripletConstruction);
+
+    ca::TripletConstructor constructor1(&frAlgo);
+    ca::TripletConstructor constructor2(&frAlgo);
+    ca::TripletConstructor constructor3(&frAlgo);
+
+    for (int istal = frAlgo.GetParameters().GetNstationsActive() - 2; istal >= frAlgo.fFirstCAstation;
+         istal--) {  // start with downstream chambers
+      Tindex nGridEntriesL = frAlgo.vGrid[istal].GetEntries().size();
+
+      for (Tindex iel = 0; iel < nGridEntriesL; ++iel) {
+        ca::HitIndex_t ihitl = frAlgo.vGrid[istal].GetEntries()[iel].GetObjectId();
+        constructor1.CreateTripletsForHit(istal, istal + 1, istal + 2, ihitl);
+
+        if (frAlgo.fpCurrentIteration->GetJumpedFlag()) {
+          constructor2.CreateTripletsForHit(istal, istal + 1, istal + 3, ihitl);
+          constructor3.CreateTripletsForHit(istal, istal + 2, istal + 3, ihitl);
+        }
+
+        auto oldSize = frAlgo.fTriplets[istal].size();
+
+        frAlgo.fTriplets[istal].insert(frAlgo.fTriplets[istal].end(), constructor1.GetTriplets().begin(),
+                                       constructor1.GetTriplets().end());
+        frAlgo.fTriplets[istal].insert(frAlgo.fTriplets[istal].end(), constructor2.GetTriplets().begin(),
+                                       constructor2.GetTriplets().end());
+        frAlgo.fTriplets[istal].insert(frAlgo.fTriplets[istal].end(), constructor3.GetTriplets().begin(),
+                                       constructor3.GetTriplets().end());
+
+        frAlgo.fHitFirstTriplet[ihitl] = frAlgo.PackTripletId(istal, oldSize);
+        frAlgo.fHitNtriplets[ihitl]    = frAlgo.fTriplets[istal].size() - oldSize;
+      }
+    }  // istal
+
+    frAlgo.fMonitor.StopTimer(ETimer::TripletConstruction);
+
+    // search for neighbouring triplets
+    frAlgo.fMonitor.StartTimer(ETimer::NeighboringTripletSearch);
+    for (int istal = frAlgo.GetParameters().GetNstationsActive() - 2; istal >= frAlgo.fFirstCAstation;
+         istal--) {  // start with downstream chambers
+
+      for (unsigned int it = 0; it < frAlgo.fTriplets[istal].size(); ++it) {
+
+        ca::Triplet& tr = frAlgo.fTriplets[istal][it];
+        tr.SetLevel(0);
+        tr.SetFNeighbour(0);
+        tr.SetNNeighbours(0);
+
+        if (istal > (frAlgo.GetParameters().GetNstationsActive() - 4)) break;
+
+        unsigned int nNeighbours = frAlgo.fHitNtriplets[tr.GetMHit()];
+
+        unsigned int neighLocation = frAlgo.fHitFirstTriplet[tr.GetMHit()];
+        unsigned int neighStation  = frAlgo.TripletId2Station(neighLocation);
+        unsigned int neighTriplet  = frAlgo.TripletId2Triplet(neighLocation);
+
+        if (nNeighbours > 0) { assert((int) neighStation == istal + 1 || (int) neighStation == istal + 2); }
+
+        unsigned char level = 0;
+
+        for (unsigned int iN = 0; iN < nNeighbours; ++iN, ++neighTriplet, ++neighLocation) {
+
+          ca::Triplet& neighbour = frAlgo.fTriplets[neighStation][neighTriplet];
+
+          fscal dchi2 = 0.;
+          if (!checkTripletMatch(tr, neighbour, dchi2)) continue;
+
+          if (tr.GetFNeighbour() == 0) { tr.SetFNeighbour(neighLocation); }
+
+          tr.SetNNeighbours(neighLocation - tr.GetFNeighbour() + 1);
+
+          const unsigned char neighbourLevel = neighbour.GetLevel();
+
+          if (level <= neighbourLevel) { level = neighbourLevel + 1; }
+        }
+        tr.SetLevel(level);
+      }  // neighbour search
+
+      frAlgo.fMonitor.IncrementCounter(ECounter::Triplet, frAlgo.fTriplets[istal].size());
+
+    }  // istal
+    frAlgo.fMonitor.StopTimer(ETimer::NeighboringTripletSearch);
+
+
+    ///====================================================================
+    ///=                                                                  =
+    ///=        Collect track candidates. CREATE TRACKS                   =
+    ///=                                                                  =
+    ///====================================================================
+
+    // min level to start triplet. So min track length = min_level+3.
+    int min_level = std::min(caIteration.GetMinNhits(), caIteration.GetMinNhitsStation0()) - 3;
+
+    if (frAlgo.fpCurrentIteration->GetTrackFromTripletsFlag()) { min_level = 0; }
+
+    ca::Branch curr_tr;
+    ca::Branch new_tr[constants::size::MaxNstations];
+    ca::Branch best_tr;
+
+    int ndf = 1;
+
+
+    // collect consequtive: the longest tracks, shorter, more shorter and so on
+    for (int firstTripletLevel = frAlgo.GetParameters().GetNstationsActive() - 3; firstTripletLevel >= min_level;
+         firstTripletLevel--) {
+      // choose length in triplets number - firstTripletLevel - the maximum possible triplet level among all triplets in the searched candidate
+
+      //  how many levels to check
+      int nlevel = (frAlgo.GetParameters().GetNstationsActive() - 2) - firstTripletLevel + 1;
+
+      const unsigned char min_best_l =
+        (firstTripletLevel > min_level) ? firstTripletLevel + 2 : min_level + 3;  // loose maximum
+
+
+      frAlgo.fTrackCandidates.clear();
+
+      frAlgo.fStripToTrack.reset(frAlgo.fInputData.GetNhitKeys(), -1);
+
+      //== Loop over triplets with the required level, find and store track candidates
+
+      for (int istaF = frAlgo.fFirstCAstation;
+           istaF <= frAlgo.GetParameters().GetNstationsActive() - 3 - firstTripletLevel; ++istaF) {
+
+        if (--nlevel == 0) break;  //TODO: SG: this is not needed
+
+        for (Tindex itrip = 0; itrip < (Tindex) frAlgo.fTriplets[istaF].size(); ++itrip) {
+
+          ca::Triplet& first_trip = (frAlgo.fTriplets[istaF][itrip]);
+          if (frAlgo.fvHitKeyFlags[frAlgo.fWindowHits[first_trip.GetLHit()].FrontKey()]
+              || frAlgo.fvHitKeyFlags[frAlgo.fWindowHits[first_trip.GetLHit()].BackKey()]) {
+            continue;
+          }
+          //               ghost suppression !!!
+          //
+
+          if (!frAlgo.fpCurrentIteration->GetTrackFromTripletsFlag()) {  // ghost suppression !!!
+            int nHits = 3 + first_trip.GetLevel();
+            if (frAlgo.fWindowHits[first_trip.GetLHit()].Station() == 0) {
+              if (nHits < frAlgo.fpCurrentIteration->GetMinNhitsStation0()) { continue; }
+            }
+            else {
+              if (nHits < frAlgo.fpCurrentIteration->GetMinNhits()) { continue; }
+            }
+          }
+
+          // Collect triplets, which can start a track with length equal to firstTipletLevel + 3. This cut suppresses
+          // ghost tracks, but does not affect the efficiency
+          if (first_trip.GetLevel() < firstTripletLevel) { continue; }
+
+          curr_tr.SetChi2(0.);
+          curr_tr.SetStation(0);
+          curr_tr.ResetHits();
+          curr_tr.AddHit(frAlgo.fWindowHits[first_trip.GetLHit()].Id());
+          curr_tr.SetChi2(first_trip.GetChi2());
+
+          best_tr = curr_tr;
+
+          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_tr.NofHits() < firstTripletLevel + 2) continue;  // loose maximum one hit
+
+          if (best_tr.NofHits() < min_level + 3) continue;  // should find all hits for min_level
+
+          ndf = best_tr.NofHits() * 2 - 5;
+
+          // TODO: automatize the NDF calculation
+
+          if (ca::Framework::TrackingMode::kGlobal == frAlgo.fTrackingMode
+              || ca::Framework::TrackingMode::kMcbm == frAlgo.fTrackingMode) {
+            ndf = best_tr.NofHits() * 2 - 4;
+          }
+
+          best_tr.SetChi2(best_tr.Chi2() / ndf);
+          if (frAlgo.fGhostSuppression) {
+            if (3 == best_tr.NofHits()) {
+              if (!frAlgo.fpCurrentIteration->GetPrimaryFlag() && (istaF != 0))
+                continue;  // too /*short*/ non-MAPS track
+              if (frAlgo.fpCurrentIteration->GetPrimaryFlag() && (best_tr.Chi2() > 5.0)) continue;
+            }
+          }
+          frAlgo.fTrackCandidates.push_back(best_tr);
+          ca::Branch& tr = frAlgo.fTrackCandidates.back();
+          tr.SetStation(istaF);
+          tr.SetId(frAlgo.fTrackCandidates.size() - 1);
+          tr.SetAlive(true);
+          if (0) {  // debug
+            cout << "track " << frAlgo.fTrackCandidates.size() - 1 << " found, L = " << best_tr.NofHits()
+                 << " chi2= " << best_tr.Chi2() << endl;
+            cout << " hits: ";
+            for (auto hitId : tr.Hits()) {
+              cout << frAlgo.GetMcTrackIdForCaHit(hitId) << " ";
+            }
+            cout << endl;
+          }
+        }  // itrip
+      }    // istaF
+
+      for (ca::Branch& tr : frAlgo.fTrackCandidates) {
+        tr.SetAlive(false);
+      }
+
+      bool repeatCompetition = true;
+      int iComp              = 0;
+      for (iComp = 0; (iComp < 100) && repeatCompetition; ++iComp) {
+
+        // == Loop over track candidates and mark their strips
+
+        repeatCompetition = false;
+
+        for (ca::Branch& tr : frAlgo.fTrackCandidates) {
+          if (tr.IsAlive()) { continue; }
+          for (auto& hitId : tr.Hits()) {
+            const ca::Hit& h = frAlgo.fInputData.GetHit(hitId);
+            bool isAlive     = true;
+            {  // front  strip
+              auto& stripF = (frAlgo.fStripToTrack)[h.FrontKey()];
+              if ((stripF >= 0) && (stripF != tr.Id())) {  // strip is used by other candidate
+                const auto& other = frAlgo.fTrackCandidates[stripF];
+                if (!other.IsAlive() && tr.IsBetterThan(other)) { stripF = tr.Id(); }
+                else {
+                  isAlive = false;
+                }
+              }
+              else {
+                stripF = tr.Id();
+              }
+              if (!isAlive) { break; }
+            }
+
+            {  // back strip
+              auto& stripB = (frAlgo.fStripToTrack)[h.BackKey()];
+              if ((stripB >= 0) && (stripB != tr.Id())) {  // strip is used by other candidate
+                const auto& other = frAlgo.fTrackCandidates[stripB];
+                if (!other.IsAlive() && tr.IsBetterThan(other)) { stripB = tr.Id(); }
+                else {
+                  isAlive = false;
+                }
+              }
+              else {
+                stripB = tr.Id();
+              }
+              if (!isAlive) { break; }
+            }
+          }  // loop over hits
+        }    // itrack
+
+        // == Check if some suppressed candidates are still alive
+
+        for (ca::Branch& tr : frAlgo.fTrackCandidates) {
+          if (tr.IsAlive()) { continue; }
+
+          tr.SetAlive(true);
+          for (int iHit = 0; tr.IsAlive() && (iHit < (int) tr.Hits().size()); ++iHit) {
+            const ca::Hit& h = frAlgo.fInputData.GetHit(tr.Hits()[iHit]);
+            tr.SetAlive(tr.IsAlive() && ((frAlgo.fStripToTrack)[h.FrontKey()] == tr.Id())
+                        && ((frAlgo.fStripToTrack)[h.BackKey()] == tr.Id()));
+          }
+
+          if (!tr.IsAlive()) {  // release strips
+            for (auto hitId : tr.Hits()) {
+              const ca::Hit& h = frAlgo.fInputData.GetHit(hitId);
+              if (frAlgo.fStripToTrack[h.FrontKey()] == tr.Id()) { frAlgo.fStripToTrack[h.FrontKey()] = -1; }
+              if (frAlgo.fStripToTrack[h.BackKey()] == tr.Id()) { frAlgo.fStripToTrack[h.BackKey()] = -1; }
+            }
+          }
+          else {
+            repeatCompetition = true;
+          }
+        }  // itrack
+
+      }  // competitions
+
+      // cout << " N Competitions: " << iComp << endl;
+
+      // ==
+
+      for (Tindex iCandidate = 0; iCandidate < (Tindex) frAlgo.fTrackCandidates.size(); ++iCandidate) {
+        ca::Branch& tr = frAlgo.fTrackCandidates[iCandidate];
+        if (!tr.IsAlive()) continue;
+        if (ca::Framework::TrackingMode::kMcbm == frAlgo.fTrackingMode) {
+          if (tr.NofHits() <= 3) { continue; }
+        }
+        else if (ca::Framework::TrackingMode::kGlobal == frAlgo.fTrackingMode) {
+          if (tr.NofHits() < 3) { continue; }
+        }
+        else {
+          if (tr.NofHits() < 3) { continue; }
+        }
+        if (frAlgo.fpCurrentIteration->GetExtendTracksFlag()) {
+          if (tr.NofHits() < frAlgo.GetParameters().GetNstationsActive()) { frAlgo.fTrackExtender.ExtendBranch(tr); }
+        }
+
+        for (auto iHit : tr.Hits()) {
+          const ca::Hit& hit = frAlgo.fInputData.GetHit(iHit);
+
+          /// used strips are marked
+
+          frAlgo.fvHitKeyFlags[hit.FrontKey()] = 1;
+          frAlgo.fvHitKeyFlags[hit.BackKey()]  = 1;
+
+          frAlgo.fSliceRecoHits.push_back(iHit);
+        }
+        Track t;
+        t.fNofHits = tr.NofHits();
+        frAlgo.fSliceRecoTracks.push_back(t);
+        if (0) {  // SG debug
+          cout << "store track " << iCandidate << " chi2= " << tr.Chi2() << endl;
+          cout << " hits: ";
+          for (unsigned int ih = 0; ih < tr.Hits().size(); ih++) {
+            cout << frAlgo.GetMcTrackIdForCaHit(tr.Hits()[ih]) << " ";
+          }
+          cout << '\n';
+        }
+
+      }  // tracks
+
+    }  // firstTripletLevel
+
+
+    // suppress strips of suppressed hits
+    for (unsigned int ih = 0; ih < frAlgo.fWindowHits.size(); ih++) {
+      if (frAlgo.fIsWindowHitSuppressed[ih]) {
+        const ca::Hit& hit                   = frAlgo.fWindowHits[ih];
+        frAlgo.fvHitKeyFlags[hit.FrontKey()] = 1;
+        frAlgo.fvHitKeyFlags[hit.BackKey()]  = 1;
+      }
+    }
+  }  // ---- Loop over Track Finder iterations: END -----------------------------------------------------------//
+
+  // Fit tracks
+  frAlgo.fTrackFitter.FitCaTracks();
+
+  // Merge clones
+  frAlgo.fCloneMerger.Exec(frAlgo.fSliceRecoTracks, frAlgo.fSliceRecoHits);
+}
+
+
+/** *************************************************************
+     *                                                              *
+     *     The routine performs recursive search for tracks         *
+     *                                                              *
+     *     I. Kisel                                    06.03.05     *
+     *     I.Kulakov                                    2012        *
+     *                                                              *
+     ****************************************************************/
+
+void TrackFinderWindow::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
+/// output: @&NCalls - number of function calls
+{
+
+  if (curr_trip->GetLevel() == 0)  // the end of the track -> check and store
+  {
+    // -- finish with current track
+    // add rest of hits
+    const ca::HitIndex_t& ihitm = curr_trip->GetMHit();
+    const ca::HitIndex_t& ihitr = curr_trip->GetRHit();
+
+    if (!(frAlgo.fvHitKeyFlags[frAlgo.fWindowHits[ihitm].FrontKey()]
+          || frAlgo.fvHitKeyFlags[frAlgo.fWindowHits[ihitm].BackKey()])) {
+
+      //        curr_tr.Hits.push_back(fGridHitIds[ihitm]);
+
+      curr_tr.AddHit(frAlgo.fWindowHits[ihitm].Id());
+    }
+
+    if (!(frAlgo.fvHitKeyFlags[frAlgo.fWindowHits[ihitr].FrontKey()]
+          || frAlgo.fvHitKeyFlags[frAlgo.fWindowHits[ihitr].BackKey()])) {
+
+      //curr_tr.Hits.push_back(fGridHitIds[ihitr]);
+      curr_tr.AddHit(frAlgo.fWindowHits[ihitr].Id());
+    }
+
+    //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_tr.NofHits() * 2 - 5;
+
+    if (ca::Framework::TrackingMode::kGlobal == frAlgo.fTrackingMode
+        || ca::Framework::TrackingMode::kMcbm == frAlgo.fTrackingMode) {
+      ndf = curr_tr.NofHits() * 2 - 4;
+    }
+
+    if (curr_tr.Chi2() > frAlgo.fTrackChi2Cut * ndf) { return; }
+
+
+    // -- select the best
+    if ((curr_tr.NofHits() > best_tr.NofHits())
+        || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
+      best_tr = curr_tr;
+    }
+
+    return;
+  }
+  else  //MEANS level ! = 0
+  {
+    int N_neighbour = (curr_trip->GetNNeighbours());
+
+    for (Tindex in = 0; in < N_neighbour; in++) {
+
+      unsigned int ID = curr_trip->GetFNeighbour() + in;
+
+      unsigned int Station = frAlgo.TripletId2Station(ID);
+      unsigned int Triplet = frAlgo.TripletId2Triplet(ID);
+
+      const ca::Triplet& new_trip = frAlgo.fTriplets[Station][Triplet];
+
+      fscal dchi2 = 0.;
+      if (!checkTripletMatch(*curr_trip, new_trip, dchi2)) continue;
+
+      if (frAlgo.fvHitKeyFlags[frAlgo.fWindowHits[new_trip.GetLHit()].FrontKey()]
+          || frAlgo.fvHitKeyFlags[frAlgo.fWindowHits[new_trip.GetLHit()].BackKey()]) {  //hits are used
+        //  no used hits allowed -> compare and store track
+        if ((curr_tr.NofHits() > best_tr.NofHits())
+            || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
+          best_tr = curr_tr;
+        }
+      }
+      else {  // hit is not used: add the left hit from the new triplet to the current track
+
+        unsigned char new_L = curr_tr.NofHits() + 1;
+        fscal new_chi2      = curr_tr.Chi2() + dchi2;
+
+
+        if (0) {  //SGtrd2d debug!!
+          int mc01 = frAlgo.GetMcTrackIdForWindowHit(curr_trip->GetLHit());
+          int mc02 = frAlgo.GetMcTrackIdForWindowHit(curr_trip->GetMHit());
+          int mc03 = frAlgo.GetMcTrackIdForWindowHit(curr_trip->GetRHit());
+          int mc11 = frAlgo.GetMcTrackIdForWindowHit(new_trip.GetLHit());
+          int mc12 = frAlgo.GetMcTrackIdForWindowHit(new_trip.GetMHit());
+          int mc13 = frAlgo.GetMcTrackIdForWindowHit(new_trip.GetRHit());
+          if ((mc01 == mc02) && (mc02 == mc03)) {
+            cout << " sta " << ista << " mc0 " << mc01 << " " << mc02 << " " << mc03 << " mc1 " << mc11 << " " << mc12
+                 << " " << 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;
+          }
+        }
+
+        int ndf = 2 * (new_L + 2) - 5;
+
+        if (ca::Framework::TrackingMode::kGlobal == frAlgo.fTrackingMode) {  //SGtrd2d!!!
+          ndf = 2 * (new_L + 2) - 4;
+        }
+        else if (ca::Framework::TrackingMode::kMcbm == frAlgo.fTrackingMode) {
+          ndf = 2 * (new_L + 2) - 4;
+        }
+        else {
+          ndf = new_L;  // TODO: SG:  2 * (new_L + 2) - 5
+        }
+
+        if (new_chi2 > frAlgo.fTrackChi2Cut * ndf) continue;
+
+        // add new hit
+        new_tr[ista] = curr_tr;
+        new_tr[ista].AddHit(frAlgo.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, &new_trip, new_tr[ista], min_best_l, new_tr);
+      }  // add triplet to track
+    }    // for neighbours
+  }      // level = 0
+}
diff --git a/algo/ca/core/tracking/CaTrackFinderWindow.h b/algo/ca/core/tracking/CaTrackFinderWindow.h
new file mode 100644
index 0000000000..edf3846447
--- /dev/null
+++ b/algo/ca/core/tracking/CaTrackFinderWindow.h
@@ -0,0 +1,73 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer], Maksym Zyzak */
+
+/// \file    CaTrackFinderWindow.h
+/// \authors S.Zharko <s.zharko@gsi.de> (interface), M.Zyzak (original algorithm)
+/// \brief   A class wrapper over clones merger algorithm for the CA track finder (declaration)
+/// \since   22.07.2022
+
+#pragma once  // include this header only once per compilation unit
+
+#include "CaBranch.h"
+#include "CaHit.h"
+#include "CaSimd.h"
+#include "CaTrackParam.h"
+#include "CaVector.h"
+
+
+namespace cbm::algo::ca
+{
+
+  class Track;
+  class Triplet;
+  class Framework;
+
+  namespace
+  {
+    using namespace cbm::algo;  // to keep ca:: prefices in the code
+  }
+
+  /// Class implements a clones merger algorithm for the CA track finder
+  ///
+  class TrackFinderWindow {
+  public:
+    /// Default constructor
+    TrackFinderWindow(ca::Framework& algo);
+
+    /// Destructor
+    ~TrackFinderWindow();
+
+    /// Copy constructor
+    TrackFinderWindow(const TrackFinderWindow&) = delete;
+
+    /// Move constructor
+    TrackFinderWindow(TrackFinderWindow&&) = delete;
+
+    /// Copy assignment operator
+    TrackFinderWindow& operator=(const TrackFinderWindow&) = delete;
+
+    /// Move assignment operator
+    TrackFinderWindow& operator=(TrackFinderWindow&&) = delete;
+
+    void ReadWindowData();
+    void CaTrackFinderSlice();
+
+    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);
+
+  private:
+    ///-------------------------------
+    /// Private methods
+
+    bool checkTripletMatch(const ca::Triplet& l, const ca::Triplet& r, fscal& dchi2) const;
+
+
+  private:
+    ///-------------------------------
+    /// Data members
+
+    ca::Framework& frAlgo;  ///< Reference to the main track finder algorithm class
+  };
+
+}  // namespace cbm::algo::ca
diff --git a/reco/L1/L1Algo/L1TrackFitter.cxx b/algo/ca/core/tracking/CaTrackFitter.cxx
similarity index 81%
rename from reco/L1/L1Algo/L1TrackFitter.cxx
rename to algo/ca/core/tracking/CaTrackFitter.cxx
index 4d4e762724..b83eba8191 100644
--- a/reco/L1/L1Algo/L1TrackFitter.cxx
+++ b/algo/ca/core/tracking/CaTrackFitter.cxx
@@ -2,29 +2,38 @@
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Ivan Kisel, Sergey Gorbunov, Igor Kulakov [committer], Valentina Akishina, Maksym Zyzak */
 
+#include "CaTrackFitter.h"
+
 #include <iostream>
 #include <vector>
 
+#include "CaFramework.h"
 #include "CaTrackFit.h"
 #include "CaTrackParam.h"
-#include "L1Algo.h"
 
 using std::cout;
 using std::endl;
 using std::vector;
 using Track = cbm::algo::ca::Track;
 
-namespace NS_L1TrackFitter
-{
-  const fvec c_light(0.000299792458), c_light_i(fvec(1.) / c_light);
-}  // namespace NS_L1TrackFitter
-using namespace NS_L1TrackFitter;
+using namespace cbm::algo::ca;
+using namespace cbm::algo;
+
 
+// ---------------------------------------------------------------------------------------------------------------------
+//
+TrackFitter::TrackFitter(ca::Framework& algo) : frAlgo(algo) {}
 
-void L1Algo::L1KFTrackFitter()
+// ---------------------------------------------------------------------------------------------------------------------
+//
+TrackFitter::~TrackFitter() {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TrackFitter::FitCaTracks()
 {
-  //  cout << " Start L1 Track Fitter " << endl;
-  int start_hit = 0;  // for interation in fSliceRecoHits[]
+  //  cout << " Start CA Track Fitter " << endl;
+  int start_hit = 0;  // for interation in frAlgo.fSliceRecoHits[]
 
   //  static ca::FieldValue fldB0, fldB1, fldB2 _fvecalignment;
   //  static ca::FieldRegion fld _fvecalignment;
@@ -35,17 +44,17 @@ void L1Algo::L1KFTrackFitter()
   ca::FieldValue fldB01, fldB11, fldB21 _fvecalignment;
   ca::FieldRegion fld1 _fvecalignment;
 
-  const int nStations = fParameters.GetNstationsActive();
+  const int nStations = frAlgo.GetParameters().GetNstationsActive();
   int nTracks_SIMD    = fvec::size();
 
   ca::TrackFit fit;  // fit parameters coresponding to the current track
   TrackParamV& tr = fit.Tr();
-  fit.SetParticleMass(GetDefaultParticleMass());
+  fit.SetParticleMass(frAlgo.GetDefaultParticleMass());
   fit.SetDoFitVelocity(true);
 
   Track* t[fvec::size()] {nullptr};
 
-  const ca::Station* sta = fParameters.GetStations().begin();
+  const ca::Station* sta = frAlgo.GetParameters().GetStations().begin();
 
   // Spatial-time position of a hit vs. station and track in the portion
 
@@ -95,19 +104,19 @@ void L1Algo::L1KFTrackFitter()
     mxy[ista].SetCov(1., 0., 1.);
   }
 
-  unsigned short N_vTracks = fSliceRecoTracks.size();  // number of tracks processed per one SSE register
+  unsigned short N_vTracks = frAlgo.fSliceRecoTracks.size();  // number of tracks processed per one SSE register
 
   for (unsigned short itrack = 0; itrack < N_vTracks; itrack += fvec::size()) {
 
     if (N_vTracks - itrack < static_cast<unsigned short>(fvec::size())) nTracks_SIMD = N_vTracks - itrack;
 
     for (int i = 0; i < nTracks_SIMD; i++) {
-      t[i] = &fSliceRecoTracks[itrack + i];
+      t[i] = &frAlgo.fSliceRecoTracks[itrack + i];
     }
 
     // fill the rest of the SIMD vectors with something reasonable
     for (uint i = nTracks_SIMD; i < fvec::size(); i++) {
-      t[i] = &fSliceRecoTracks[itrack];
+      t[i] = &frAlgo.fSliceRecoTracks[itrack];
     }
 
     // get hits of current track
@@ -126,7 +135,7 @@ void L1Algo::L1KFTrackFitter()
 
       for (int ih = 0; ih < nHitsTrack; ih++) {
 
-        const ca::Hit& hit = fInputData.GetHit(fSliceRecoHits[start_hit++]);
+        const ca::Hit& hit = frAlgo.GetInputData().GetHit(frAlgo.fSliceRecoHits[start_hit++]);
         const int ista     = hit.Station();
 
         //if (sta[ista].fieldStatus) { isFieldPresent[iVec] = true; }
@@ -187,14 +196,17 @@ void L1Algo::L1KFTrackFitter()
 
       for (int ih = nHitsTrack - 1; ih >= 0; ih--) {
         const int ista        = iSta[ih];
-        const ca::Station& st = fParameters.GetStation(ista);
+        const ca::Station& st = frAlgo.GetParameters().GetStation(ista);
         By[ista][iVec]        = st.fieldSlice.cy[0][0];
       }
     }
 
     fit.GuessTrack(z_end, x, y, z, time, By, w, w_time, nStations);
 
-    if (kGlobal == fTrackingMode || kMcbm == fTrackingMode) { tr.Qp() = fvec(1. / 1.1); }
+    if (ca::Framework::TrackingMode::kGlobal == frAlgo.fTrackingMode
+        || ca::Framework::TrackingMode::kMcbm == frAlgo.fTrackingMode) {
+      tr.Qp() = fvec(1. / 1.1);
+    }
 
     // tr.Qp() = iif(isFieldPresent, tr.Qp(), fvec(1. / 0.25));
 
@@ -245,8 +257,8 @@ void L1Algo::L1KFTrackFitter()
 
         fit.SetMask(initialised);
         fit.Extrapolate(z[ista], fld1);
-        fit.MultipleScattering(fParameters.GetMaterialThickness(ista, tr.X(), tr.Y()));
-        fit.EnergyLossCorrection(fParameters.GetMaterialThickness(ista, tr.X(), tr.Y()), fvec(1.f));
+        fit.MultipleScattering(frAlgo.GetParameters().GetMaterialThickness(ista, tr.X(), tr.Y()));
+        fit.EnergyLossCorrection(frAlgo.GetParameters().GetMaterialThickness(ista, tr.X(), tr.Y()), fvec(1.f));
 
         fit.SetMask(initialised && w[ista]);
         fit.FilterXY(mxy[ista]);
@@ -265,23 +277,23 @@ void L1Algo::L1KFTrackFitter()
       {
         fitpv.SetMask(fmask::One());
 
-        ca::MeasurementXy<fvec> vtxInfo = TargetMeasurement;
+        ca::MeasurementXy<fvec> vtxInfo = frAlgo.TargetMeasurement;
         vtxInfo.SetDx2(1.e-8);
         vtxInfo.SetDxy(0.);
         vtxInfo.SetDy2(1.e-8);
 
-        if (kGlobal == fTrackingMode) {
+        if (ca::Framework::TrackingMode::kGlobal == frAlgo.fTrackingMode) {
           for (int vtxIter = 0; vtxIter < 2; vtxIter++) {
             fitpv.SetQp0(fitpv.Tr().Qp());
             fitpv.Tr()      = fit.Tr();
             fitpv.Tr().Qp() = fitpv.Qp0();
-            fitpv.Extrapolate(fParameters.GetTargetPositionZ(), fld);
+            fitpv.Extrapolate(frAlgo.GetParameters().GetTargetPositionZ(), fld);
             fitpv.FilterXY(vtxInfo);
           }
         }
         else {
           fitpv.SetQp0(fitpv.Tr().Qp());
-          fitpv.Extrapolate(fParameters.GetTargetPositionZ(), fld);
+          fitpv.Extrapolate(frAlgo.GetParameters().GetTargetPositionZ(), fld);
         }
       }
 
@@ -291,7 +303,7 @@ void L1Algo::L1KFTrackFitter()
       //fit.FilterVi(TrackParamV::kClightNsInv);
 
       TrackParamV Tf = fit.Tr();
-      if (kGlobal == fTrackingMode) { Tf.Qp() = fitpv.Tr().Qp(); }
+      if (ca::Framework::TrackingMode::kGlobal == frAlgo.fTrackingMode) { Tf.Qp() = fitpv.Tr().Qp(); }
 
       for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
         t[iVec]->fParFirst.Set(Tf, iVec);
@@ -342,8 +354,8 @@ void L1Algo::L1KFTrackFitter()
 
         fit.SetMask(initialised);
         fit.Extrapolate(z[ista], fld);
-        fit.MultipleScattering(fParameters.GetMaterialThickness(ista, tr.X(), tr.Y()));
-        fit.EnergyLossCorrection(fParameters.GetMaterialThickness(ista, tr.X(), tr.Y()), fvec(-1.f));
+        fit.MultipleScattering(frAlgo.GetParameters().GetMaterialThickness(ista, tr.X(), tr.Y()));
+        fit.EnergyLossCorrection(frAlgo.GetParameters().GetMaterialThickness(ista, tr.X(), tr.Y()), fvec(-1.f));
         fit.SetMask(initialised && w[ista]);
         fit.FilterXY(mxy[ista]);
         fit.FilterTime(time[ista], dt2[ista], sta[ista].timeInfo);
@@ -360,7 +372,7 @@ void L1Algo::L1KFTrackFitter()
       //fit.FilterVi(TrackParamV::kClightNsInv);
 
       TrackParamV Tl = fit.Tr();
-      if (kGlobal == fTrackingMode) { Tl.Qp() = fitpv.Tr().Qp(); }
+      if (ca::Framework::TrackingMode::kGlobal == frAlgo.fTrackingMode) { Tl.Qp() = fitpv.Tr().Qp(); }
 
       for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
         t[iVec]->fParLast.Set(Tl, iVec);
diff --git a/algo/ca/core/tracking/CaTrackFitter.h b/algo/ca/core/tracking/CaTrackFitter.h
new file mode 100644
index 0000000000..130a42903f
--- /dev/null
+++ b/algo/ca/core/tracking/CaTrackFitter.h
@@ -0,0 +1,66 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer], Maksym Zyzak */
+
+/// \file    TrackFitter.h
+/// \brief   A class wrapper over clones merger algorithm for the Ca track finder (declaration)
+/// \since   19.10.2023
+
+#pragma once  // include this header only once per compilation unit
+
+#include "CaBranch.h"
+#include "CaHit.h"
+#include "CaSimd.h"
+#include "CaTrackParam.h"
+#include "CaVector.h"
+
+
+namespace cbm::algo::ca
+{
+  class Track;
+  class Framework;
+
+  namespace
+  {
+    using namespace cbm::algo;  // to keep ca:: prefices in the code
+  }
+
+
+  /// Class implements a track fit the CA track finder
+  ///
+  class TrackFitter {
+  public:
+    /// Default constructor
+    TrackFitter(ca::Framework& algo);
+
+    /// Destructor
+    ~TrackFitter();
+
+    /// Copy constructor
+    TrackFitter(const TrackFitter&) = delete;
+
+    /// Move constructor
+    TrackFitter(TrackFitter&&) = delete;
+
+    /// Copy assignment operator
+    TrackFitter& operator=(const TrackFitter&) = delete;
+
+    /// Move assignment operator
+    TrackFitter& operator=(TrackFitter&&) = delete;
+
+
+    /// Fit tracks, found by the CA tracker
+    void FitCaTracks();
+
+  private:
+    ///-------------------------------
+    /// Private methods
+
+  private:
+    ///-------------------------------
+    /// Data members
+
+    ca::Framework& frAlgo;  ///< Reference to the main track finder algorithm class
+  };
+
+}  // namespace cbm::algo::ca
diff --git a/reco/L1/L1Algo/L1TripletConstructor.cxx b/algo/ca/core/tracking/CaTripletConstructor.cxx
similarity index 93%
rename from reco/L1/L1Algo/L1TripletConstructor.cxx
rename to algo/ca/core/tracking/CaTripletConstructor.cxx
index 4ae4c1debb..2b0e2433f7 100644
--- a/reco/L1/L1Algo/L1TripletConstructor.cxx
+++ b/algo/ca/core/tracking/CaTripletConstructor.cxx
@@ -2,26 +2,25 @@
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Igor Kulakov [committer], Maksym Zyzak, Valentina Akishina */
 
-#include "L1TripletConstructor.h"
-
-#include "CbmL1.h"
-#include "CbmL1MCTrack.h"
+#include "CaTripletConstructor.h"
 
 #include <algorithm>
 #include <iostream>
 
 #include "CaDefines.h"
+#include "CaFramework.h"
 #include "CaGridArea.h"
-#include "CaToolsDebugger.h"
+// #include "CaToolsDebugger.h"
 #include "CaTrackFit.h"
 #include "CaTrackParam.h"
-#include "L1Algo.h"
 
-using cbm::ca::tools::Debugger;
+// using cbm::ca::tools::Debugger;
+
+using namespace cbm::algo::ca;
 
-L1TripletConstructor::L1TripletConstructor(L1Algo* algo) { fAlgo = algo; }
+TripletConstructor::TripletConstructor(ca::Framework* algo) { fAlgo = algo; }
 
-void L1TripletConstructor::InitStations(int istal, int istam, int istar)
+void TripletConstructor::InitStations(int istal, int istam, int istar)
 {
   fIsInitialized = false;
 
@@ -74,7 +73,7 @@ void L1TripletConstructor::InitStations(int istal, int istam, int istar)
 }
 
 
-void L1TripletConstructor::CreateTripletsForHit(int istal, int istam, int istar, ca::HitIndex_t iHitL)
+void TripletConstructor::CreateTripletsForHit(int istal, int istam, int istar, ca::HitIndex_t iHitL)
 {
   InitStations(istal, istam, istar);
 
@@ -169,7 +168,7 @@ void L1TripletConstructor::CreateTripletsForHit(int istal, int istam, int istar,
 }
 
 
-void L1TripletConstructor::FindDoublets()
+void TripletConstructor::FindDoublets()
 {
   /// Find the doublets. Reformat data into portions of doublets.
 
@@ -183,12 +182,12 @@ void L1TripletConstructor::FindDoublets()
 }
 
 
-void L1TripletConstructor::FitDoublets()
+void TripletConstructor::FitDoublets()
 {
 
   // ---- Add the middle hits to parameters estimation ----
 
-  Vector<ca::HitIndex_t> hitsMtmp("L1TripletConstructor::hitsMtmp", fHitsM_2);
+  Vector<ca::HitIndex_t> hitsMtmp("TripletConstructor::hitsMtmp", fHitsM_2);
 
   fHitsM_2.clear();
   fTracks_2.clear();
@@ -227,7 +226,7 @@ void L1TripletConstructor::FitDoublets()
     fFit.SetQp0(fFit.Tr().Qp());
 
     // check if there are other hits close to the doublet on the same station
-    if (L1Algo::kMcbm != fAlgo->fTrackingMode) {
+    if (ca::Framework::kMcbm != fAlgo->fTrackingMode) {
       // TODO: SG: adjust cuts, put them to parameters
 
       fscal tx = T2.Tx()[0];
@@ -268,7 +267,7 @@ void L1TripletConstructor::FitDoublets()
 }
 
 
-void L1TripletConstructor::FindTriplets()
+void TripletConstructor::FindTriplets()
 {
   if (fIstaR >= fAlgo->fParameters.GetNstationsActive()) { return; }
   FindRightHit();
@@ -277,7 +276,7 @@ void L1TripletConstructor::FindTriplets()
 }
 
 
-void L1TripletConstructor::FindRightHit()
+void TripletConstructor::FindRightHit()
 {
 
   /// Add the middle hits to parameters estimation. Propagate to right station.
@@ -324,7 +323,7 @@ void L1TripletConstructor::FindRightHit()
     CollectHits(T2, fIstaR, fAlgo->fTripletChi2Cut, iMC, collectedHits, fAlgo->fParameters.GetMaxTripletPerDoublets());
 
     if (collectedHits.size() >= fAlgo->fParameters.GetMaxTripletPerDoublets()) {
-      LOG(debug) << "L1: GetMaxTripletPerDoublets==" << fAlgo->fParameters.GetMaxTripletPerDoublets()
+      LOG(debug) << "Ca: GetMaxTripletPerDoublets==" << fAlgo->fParameters.GetMaxTripletPerDoublets()
                  << " reached in findTripletsStep0()";
       // reject already created triplets for this doublet
       collectedHits.clear();
@@ -342,7 +341,7 @@ void L1TripletConstructor::FindRightHit()
 }
 
 
-void L1TripletConstructor::FitTriplets()
+void TripletConstructor::FitTriplets()
 {
   constexpr bool dumpTriplets = 0;
 
@@ -356,8 +355,8 @@ void L1TripletConstructor::FitTriplets()
 
   /// Refit Triplets
   if (dumpTriplets) {
-    cbm::ca::tools::Debugger::Instance().AddNtuple(
-      "triplets", "ev:iter:i0:x0:y0:z0:i1:x1:y1:z1:i2:x2:y2:z2:mc:sta:p:vx:vy:vz:chi2:ndf:chi2time:ndfTime");
+    //cbm::ca::tools::Debugger::Instance().AddNtuple(
+    //  "triplets", "ev:iter:i0:x0:y0:z0:i1:x1:y1:z1:i2:x2:y2:z2:mc:sta:p:vx:vy:vz:chi2:ndf:chi2time:ndfTime");
   }
 
   ca::TrackFit fit;
@@ -520,17 +519,17 @@ void L1TripletConstructor::FitTriplets()
       int mc1 = fAlgo->GetMcTrackIdForCaHit(ih0);
       int mc2 = fAlgo->GetMcTrackIdForCaHit(ih1);
       int mc3 = fAlgo->GetMcTrackIdForCaHit(ih2);
-
-      const ca::Hit& h0 = fAlgo->fInputData.GetHit(ih0);
-      const ca::Hit& h1 = fAlgo->fInputData.GetHit(ih1);
-      const ca::Hit& h2 = fAlgo->fInputData.GetHit(ih2);
-
       if ((mc1 >= 0) && (mc1 == mc2) && (mc1 == mc3)) {
+        /*
+        const ca::Hit& h0        = fAlgo->fInputData.GetHit(ih0);
+        const ca::Hit& h1        = fAlgo->fInputData.GetHit(ih1);
+        const ca::Hit& h2        = fAlgo->fInputData.GetHit(ih2);
         const CbmL1MCTrack& mctr = CbmL1::Instance()->GetMcTracks()[mc1];
         cbm::ca::tools::Debugger::Instance().FillNtuple(
           "triplets", mctr.iEvent, fAlgo->fCurrentIterationIndex, ih0, h0.X(), h0.Y(), h0.Z(), ih1, h1.X(), h1.Y(),
           h1.Z(), ih2, h2.X(), h2.Y(), h2.Z(), mc1, fIstaL, mctr.p, mctr.x, mctr.y, mctr.z, (float) T.GetChiSq()[0],
           (float) T.Ndf()[0], (float) T.ChiSqTime()[0], (float) T.NdfTime()[0]);
+        */
       }
     }
   }  //i3
@@ -538,7 +537,7 @@ void L1TripletConstructor::FitTriplets()
 }  // FitTriplets
 
 
-void L1TripletConstructor::StoreTriplets()
+void TripletConstructor::StoreTriplets()
 {
   /// Selects good triplets and saves them into fTriplets.
   /// Finds neighbouring triplets at the next station.
@@ -587,8 +586,8 @@ void L1TripletConstructor::StoreTriplets()
 }
 
 
-void L1TripletConstructor::CollectHits(const TrackParamV& Tr, const int iSta, const double chi2Cut, const int iMC,
-                                       Vector<ca::HitIndex_t>& collectedHits, int maxNhits)
+void TripletConstructor::CollectHits(const TrackParamV& Tr, const int iSta, const double chi2Cut, const int iMC,
+                                     Vector<ca::HitIndex_t>& collectedHits, int maxNhits)
 {
   /// Collect hits on a station
 
diff --git a/algo/ca/core/tracking/CaTripletConstructor.h b/algo/ca/core/tracking/CaTripletConstructor.h
new file mode 100644
index 0000000000..477bee185a
--- /dev/null
+++ b/algo/ca/core/tracking/CaTripletConstructor.h
@@ -0,0 +1,122 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov [committer] */
+
+/// \file CaTripletConstructor.h
+/// \brief Triplet constructor for the CA tracker
+/// \author Sergey Gorbunov
+
+#pragma once  // include this header only once per compilation unit
+
+#include "CaField.h"
+#include "CaFramework.h"
+#include "CaGridEntry.h"
+#include "CaStation.h"
+#include "CaTrackFit.h"
+#include "CaTrackParam.h"
+#include "CaTriplet.h"
+#include "CaVector.h"
+
+namespace cbm::algo::ca
+{
+
+  namespace
+  {
+    using namespace cbm::algo;  // to keep ca:: prefices in the code
+  }
+
+  /// Construction of triplets for the CA tracker
+  ///
+  class TripletConstructor {
+  public:
+    ///                             ------  Constructors and destructor ------
+
+    /// Constructor
+    /// \param nThreads  Number of threads for multi-threaded mode
+    TripletConstructor(ca::Framework* algo);
+
+    /// Copy constructor
+    TripletConstructor(const TripletConstructor&) = delete;
+
+    /// Move constructor
+    TripletConstructor(TripletConstructor&&) = delete;
+
+    /// Copy assignment operator
+    TripletConstructor& operator=(const TripletConstructor&) = delete;
+
+    /// Move assignment operator
+    TripletConstructor& operator=(TripletConstructor&&) = delete;
+
+    /// Destructor
+    ~TripletConstructor() = default;
+
+
+    ///                             ------  FUNCTIONAL PART ------
+
+    void InitStations(int istal, int istam, int istar);
+
+    void CreateTripletsForHit(int istal, int istam, int istar, ca::HitIndex_t ihl);
+
+    const Vector<ca::Triplet>& GetTriplets() const { return fTriplets; }
+
+    /// Find the doublets. Reformat data in the portion of doublets.
+    void FindDoublets();
+    void FitDoublets();
+
+    /// Find triplets on station
+    void FindTriplets();
+
+    /// Add the middle hits to parameters estimation. Propagate to right station.
+    /// Find the triplets (right hit). Reformat data in the portion of triplets.
+    void FindRightHit();
+
+    /// Fit Triplets
+    void FitTriplets();
+
+    /// Select triplets. Save them into vTriplets.
+    void StoreTriplets();
+
+    void CollectHits(const TrackParamV& Tr, const int iSta, const double chi2Cut, const int iMC,
+                     Vector<ca::HitIndex_t>& collectedHits, int maxNhits);
+
+  private:
+    /// left station
+    const ca::Station& staL() { return *fStaL; }
+    /// middle station
+    const ca::Station& staM() { return *fStaM; }
+    /// right station
+    const ca::Station& staR() { return *fStaR; }
+
+  private:
+    bool fIsInitialized {false};     ///< is initialized;
+    ca::Framework* fAlgo {nullptr};  ///< pointer to ca::Framework object
+
+    int fIstaL {-1};  ///< left station index
+    int fIstaM {-1};  ///< middle station index
+    int fIstaR {-1};  ///< right station index
+
+    const ca::Station* fStaL {nullptr};  ///< left station
+    const ca::Station* fStaM {nullptr};  ///< mid station
+    const ca::Station* fStaR {nullptr};  ///< right station
+
+    const ca::Station* fFld0Sta[2];  // two stations for approximating the field between the target and the left hit
+    const ca::Station* fFld1Sta[3];  // three stations for approximating the field between the left and the right hit
+
+    ca::HitIndex_t fIhitL;  ///< index of the left hit in fAlgo->fWindowHits
+    TrackParamV fTrL;
+    ca::FieldRegion fFldL;
+
+    Vector<ca::HitIndex_t> fHitsM_2 {"TripletConstructor::fHitsM_2"};
+    Vector<TrackParamV> fTracks_2 {"TripletConstructor::fTracks_2"};
+
+    Vector<TrackParamV> fTracks_3 {"TripletConstructor::fTracks_3"};
+    Vector<ca::HitIndex_t> fHitsM_3 {"TripletConstructor::fHitsM_3"};
+    Vector<ca::HitIndex_t> fHitsR_3 {"TripletConstructor::fHitsR_3"};
+
+    Vector<ca::Triplet> fTriplets {"TripletConstructor::fTriplets"};
+
+    ca::TrackFit fFit;
+
+  } _fvecalignment;
+
+}  // namespace cbm::algo::ca
diff --git a/reco/KF/ParticleFitter/CbmL1PFFitter.cxx b/reco/KF/ParticleFitter/CbmL1PFFitter.cxx
index b4a6162c7a..1b8b6c60b9 100644
--- a/reco/KF/ParticleFitter/CbmL1PFFitter.cxx
+++ b/reco/KF/ParticleFitter/CbmL1PFFitter.cxx
@@ -27,7 +27,7 @@
 
 #include "TClonesArray.h"
 
-//L1Algo tools
+//ca::Framework tools
 #include "CbmKFVertex.h"
 
 #include "FairRootManager.h"
@@ -35,12 +35,15 @@
 #include "TDatabasePDG.h"
 
 #include "CaField.h"
+#include "CaFramework.h"
+#include "CaSimd.h"
 #include "CaStation.h"
 #include "CaToolsField.h"
 #include "CaTrackFit.h"
 #include "CaTrackParam.h"
 #include "KFParticleDatabase.h"
-#include "L1Algo.h"  // Also defines L1Parameters
+
+using namespace cbm::algo::ca;
 
 //typedef ca::TrackFit1 ca::TrackFit;
 
@@ -111,13 +114,11 @@ inline void CbmL1PFFitter::Initialize()
 
   if (!manager) { LOG(fatal) << "CbmL1PFFitter: no FairRootManager"; }
 
-  if (!CbmL1::Instance() || !CbmL1::Instance()->fpAlgo || !CbmL1::Instance()->fpAlgo->GetParameters()) {
-    LOG(fatal) << "CbmL1PFFitter: no CbmL1 task initialised ";
-  }
+  if (!CbmL1::Instance() || !CbmL1::Instance()->fpAlgo) { LOG(fatal) << "CbmL1PFFitter: no CbmL1 task initialised "; }
 
   using cbm::algo::ca::EDetectorID;
-  fNmvdStationsActive = CbmL1::Instance()->fpAlgo->GetParameters()->GetNstationsActive(EDetectorID::kMvd);
-  fNstsStationsActive = CbmL1::Instance()->fpAlgo->GetParameters()->GetNstationsActive(EDetectorID::kSts);
+  fNmvdStationsActive = CbmL1::Instance()->fpAlgo->GetParameters().GetNstationsActive(EDetectorID::kMvd);
+  fNstsStationsActive = CbmL1::Instance()->fpAlgo->GetParameters().GetNstationsActive(EDetectorID::kSts);
 
   if (fNmvdStationsActive > 0) { fMvdHitArray = static_cast<TClonesArray*>(manager->GetObject("MvdHit")); }
   if (fNstsStationsActive > 0) { fStsHitArray = static_cast<TClonesArray*>(manager->GetObject("StsHit")); }
@@ -130,13 +131,13 @@ inline void CbmL1PFFitter::Initialize()
 inline int CbmL1PFFitter::GetMvdStationIndex(const CbmMvdHit* hit)
 {
   using cbm::algo::ca::EDetectorID;
-  return CbmL1::Instance()->fpAlgo->GetParameters()->GetStationIndexActive(hit->GetStationNr(), EDetectorID::kMvd);
+  return CbmL1::Instance()->fpAlgo->GetParameters().GetStationIndexActive(hit->GetStationNr(), EDetectorID::kMvd);
 }
 
 inline int CbmL1PFFitter::GetStsStationIndex(const CbmStsHit* hit)
 {
   using cbm::algo::ca::EDetectorID;
-  return CbmL1::Instance()->fpAlgo->GetParameters()->GetStationIndexActive(
+  return CbmL1::Instance()->fpAlgo->GetParameters().GetStationIndexActive(
     CbmStsSetup::Instance()->GetStationNumber(hit->GetAddress()), EDetectorID::kSts);
 }
 
@@ -164,7 +165,7 @@ void CbmL1PFFitter::Fit(std::vector<CbmStsTrack>& Tracks, const std::vector<CbmM
   ca::FieldRegion fld _fvecalignment;
   // fld.SetUseOriginalField();
 
-  static int nHits = CbmL1::Instance()->fpAlgo->GetParameters()->GetNstationsActive();
+  static int nHits = CbmL1::Instance()->fpAlgo->GetParameters().GetNstationsActive();
   int nTracks_SIMD = fvec::size();
 
   ca::TrackFit fit;
@@ -175,7 +176,7 @@ void CbmL1PFFitter::Fit(std::vector<CbmStsTrack>& Tracks, const std::vector<CbmM
   CbmStsTrack* tr[fvec::size()] {nullptr};
 
   int ista;
-  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters()->GetStations().begin();
+  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
 
   fvec x[nHits];
   fvec y[nHits];
@@ -355,7 +356,7 @@ void CbmL1PFFitter::Fit(std::vector<CbmStsTrack>& Tracks, const std::vector<CbmM
 
       fit.SetMask(initialised);
       fit.Extrapolate(z[i], fld);
-      auto radThick = CbmL1::Instance()->fpAlgo->GetParameters()->GetMaterialThickness(i, fit.Tr().X(), fit.Tr().Y());
+      auto radThick = CbmL1::Instance()->fpAlgo->GetParameters().GetMaterialThickness(i, fit.Tr().X(), fit.Tr().Y());
       fit.MultipleScattering(radThick);
       fit.EnergyLossCorrection(radThick, -fvec::One());
 
@@ -416,7 +417,7 @@ void CbmL1PFFitter::Fit(std::vector<CbmStsTrack>& Tracks, const std::vector<CbmM
 
       fit.SetMask(initialised);
       fit.Extrapolate(z[i], fld);
-      auto radThick = CbmL1::Instance()->fpAlgo->GetParameters()->GetMaterialThickness(i, fit.Tr().X(), fit.Tr().Y());
+      auto radThick = CbmL1::Instance()->fpAlgo->GetParameters().GetMaterialThickness(i, fit.Tr().X(), fit.Tr().Y());
       fit.MultipleScattering(radThick);
       fit.EnergyLossCorrection(radThick, fvec::One());
 
@@ -493,7 +494,7 @@ void CbmL1PFFitter::GetChiToVertex(vector<CbmStsTrack>& Tracks, vector<PFFieldRe
 
   int nStations = fNmvdStationsActive + fNstsStationsActive;
 
-  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters()->GetStations().begin();
+  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
   fvec* zSta             = new fvec[nStations];
   for (int iSta = 0; iSta < nStations; iSta++) {
     zSta[iSta] = sta[iSta].fZ;
@@ -565,8 +566,8 @@ void CbmL1PFFitter::GetChiToVertex(vector<CbmStsTrack>& Tracks, vector<PFFieldRe
       }
     }
 
-    fB[0]     = CbmL1::Instance()->fpAlgo->GetParameters()->GetVertexFieldValue();
-    zField[0] = CbmL1::Instance()->fpAlgo->GetParameters()->GetTargetPositionZ();
+    fB[0]     = CbmL1::Instance()->fpAlgo->GetParameters().GetVertexFieldValue();
+    zField[0] = CbmL1::Instance()->fpAlgo->GetParameters().GetTargetPositionZ();
     fld.Set(fB[2], zField[2], fB[1], zField[1], fB[0], zField[0]);
     for (int i = 0; i < nTracks_SIMD; i++) {
       field.emplace_back(fld, i);
@@ -577,7 +578,7 @@ void CbmL1PFFitter::GetChiToVertex(vector<CbmStsTrack>& Tracks, vector<PFFieldRe
     for (int iSt = nStations - 4; iSt >= 0; iSt--) {
       fit.SetMask(T.Z() > zSta[iSt] + fvec(2.5));
       fit.Extrapolate(zSta[iSt], fld);
-      auto radThick = CbmL1::Instance()->fpAlgo->GetParameters()->GetMaterialThickness(iSt, fit.Tr().X(), fit.Tr().Y());
+      auto radThick = CbmL1::Instance()->fpAlgo->GetParameters().GetMaterialThickness(iSt, fit.Tr().X(), fit.Tr().Y());
       fit.MultipleScattering(radThick);
       fit.EnergyLossCorrection(radThick, fvec::One());
     }
@@ -645,7 +646,7 @@ void CbmL1PFFitter::CalculateFieldRegion(vector<CbmStsTrack>& Tracks, vector<PFF
   CbmStsTrack* tr[fvec::size()];
 
   int ista;
-  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters()->GetStations().begin();
+  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
   ca::FieldValue fB[3], fB_temp _fvecalignment;
   fvec zField[3];
 
@@ -693,8 +694,8 @@ void CbmL1PFFitter::CalculateFieldRegion(vector<CbmStsTrack>& Tracks, vector<PFF
       }
     }
 
-    fB[0]     = CbmL1::Instance()->fpAlgo->GetParameters()->GetVertexFieldValue();
-    zField[0] = CbmL1::Instance()->fpAlgo->GetParameters()->GetTargetPositionZ();
+    fB[0]     = CbmL1::Instance()->fpAlgo->GetParameters().GetVertexFieldValue();
+    zField[0] = CbmL1::Instance()->fpAlgo->GetParameters().GetTargetPositionZ();
     fld.Set(fB[2], zField[2], fB[1], zField[1], fB[0], zField[0]);
     for (int i = 0; i < nTracks_SIMD; i++) {
       field.emplace_back(fld, i);
@@ -716,7 +717,7 @@ void CbmL1PFFitter::CalculateFieldRegionAtLastPoint(vector<CbmStsTrack>& Tracks,
   CbmStsTrack* tr[fvec::size()];
 
   int ista;
-  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters()->GetStations().begin();
+  const ca::Station* sta = CbmL1::Instance()->fpAlgo->GetParameters().GetStations().begin();
   ca::FieldValue fB[3], fB_temp _fvecalignment;
   fvec zField[3];
 
diff --git a/reco/L1/CMakeLists.txt b/reco/L1/CMakeLists.txt
index 3ab91e31e3..773cd40127 100644
--- a/reco/L1/CMakeLists.txt
+++ b/reco/L1/CMakeLists.txt
@@ -29,13 +29,7 @@ set(SRCS
   OffLineInterface/CbmL1StsTrackFinder.cxx
   OffLineInterface/CbmL1GlobalTrackFinder.cxx
   OffLineInterface/CbmL1GlobalFindTracksEvents.cxx
-  L1Algo/utils/CaAlgoRandom.cxx
-  L1Algo/L1Algo.cxx
-  L1Algo/L1TripletConstructor.cxx
-  L1Algo/L1CaTrackFinder.cxx
-  L1Algo/L1CaTrackFinderSlice.cxx
-  L1Algo/L1BranchExtender.cxx
-  L1Algo/L1TrackFitter.cxx
+  
   CbmL1Util.cxx
   CbmL1Performance.cxx
   CbmL1ReadEvent.cxx
@@ -43,12 +37,13 @@ set(SRCS
   CbmCaTimeSliceReader.cxx
   CbmL1MCTrack.cxx
   CbmL1Track.cxx
-  L1Algo/L1CloneMerger.cxx
+
   L1Algo/utils/L1AlgoDraw.cxx
   L1Algo/utils/L1AlgoEfficiencyPerformance.cxx
   L1Algo/utils/L1AlgoPulls.cxx
   L1Algo/utils/CaUvConverter.cxx
- 
+  L1Algo/utils/CaAlgoRandom.cxx
+  
   catools/CaToolsHitRecord.cxx
   catools/CaToolsMCData.cxx
   catools/CaToolsMCPoint.cxx
@@ -187,6 +182,3 @@ install(FILES CbmL1Counters.h
   DESTINATION include
 )
 
-install(FILES L1Algo/L1Algo.h
-  DESTINATION include/L1Algo
-)
diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx
index 4cf9dec8e7..0a5df93def 100644
--- a/reco/L1/CbmL1.cxx
+++ b/reco/L1/CbmL1.cxx
@@ -64,9 +64,10 @@
 #include <iostream>
 #include <list>
 
+#include "CaFramework.h"
 #include "CaHit.h"
+#include "CaToolsDebugger.h"
 #include "CaToolsField.h"
-#include "L1Algo/L1Algo.h"
 
 using namespace cbm::algo;  // TODO: remove this line
 
@@ -79,7 +80,7 @@ using cbm::ca::tools::MaterialHelper;
 
 ClassImp(CbmL1);
 
-static L1Algo gAlgo _fvecalignment;  // TODO: Change coupling logic between L1Algo and CbmL1
+static ca::Framework gAlgo _fvecalignment;  // TODO: Change coupling logic between ca::Framework and CbmL1
 
 CbmL1* CbmL1::fpInstance = 0;
 
@@ -196,7 +197,7 @@ InitStatus CbmL1::Init()
 
   FairRootManager* fairManager = FairRootManager::Instance();
 
-  if (L1Algo::TrackingMode::kSts == fTrackingMode) {
+  if (ca::Framework::TrackingMode::kSts == fTrackingMode) {
     fUseMVD  = 1;
     fUseSTS  = 1;
     fUseMUCH = 0;
@@ -207,7 +208,7 @@ InitStatus CbmL1::Init()
     if (findTask) fUseMVD = findTask->MvdUsage();
   }
 
-  if (L1Algo::TrackingMode::kMcbm == fTrackingMode) {
+  if (ca::Framework::TrackingMode::kMcbm == fTrackingMode) {
     fUseMVD  = 1;
     fUseSTS  = 1;
     fUseMUCH = 1;
@@ -216,7 +217,7 @@ InitStatus CbmL1::Init()
     fInitManager.DevSetIgnoreHitSearchAreas(true);  // uncomment for debug
   }
 
-  if (L1Algo::TrackingMode::kGlobal == fTrackingMode) {
+  if (ca::Framework::TrackingMode::kGlobal == fTrackingMode) {
     //at the moment trd2d tracking only
     fUseMVD  = 1;
     fUseSTS  = 1;
@@ -413,9 +414,9 @@ InitStatus CbmL1::Init()
 
       std::string mainConfig = std::string(gSystem->Getenv("VMCWORKDIR")) + "/macro/L1/configs/";
       switch (fTrackingMode) {
-        case L1Algo::TrackingMode::kSts: mainConfig += "ca_params_sts.yaml"; break;
-        case L1Algo::TrackingMode::kMcbm: mainConfig += "ca_params_mcbm.yaml"; break;
-        case L1Algo::TrackingMode::kGlobal: mainConfig += "ca_params_global.yaml"; break;
+        case ca::Framework::TrackingMode::kSts: mainConfig += "ca_params_sts.yaml"; break;
+        case ca::Framework::TrackingMode::kMcbm: mainConfig += "ca_params_mcbm.yaml"; break;
+        case ca::Framework::TrackingMode::kGlobal: mainConfig += "ca_params_global.yaml"; break;
       }
       fInitManager.SetConfigMain(mainConfig);
     }
@@ -502,7 +503,7 @@ InitStatus CbmL1::Init()
         // TODO: SZh 15.08.2022: Replace station type with ca::EDetectorID
         stationInfo.SetStationType(1);  // MVD
         stationInfo.SetTimeInfo(mvdInterface->IsTimeInfoProvided(iSt));
-        stationInfo.SetFieldStatus(fTrackingMode == L1Algo::TrackingMode::kMcbm ? 0 : 1);
+        stationInfo.SetFieldStatus(fTrackingMode == ca::Framework::TrackingMode::kMcbm ? 0 : 1);
         stationInfo.SetZref(mvdInterface->GetZref(iSt));
         stationInfo.SetZmin(mvdInterface->GetZmin(iSt));
         stationInfo.SetZmax(mvdInterface->GetZmax(iSt));
@@ -525,9 +526,9 @@ InitStatus CbmL1::Init()
         // TODO: SZh 15.08.2022: Replace station type with ca::EDetectorID
         stationInfo.SetStationType(0);  // STS
         stationInfo.SetTimeInfo(stsInterface->IsTimeInfoProvided(iSt));
-        stationInfo.SetTimeInfo(L1Algo::TrackingMode::kMcbm != fTrackingMode ? stsInterface->IsTimeInfoProvided(iSt)
-                                                                             : false);
-        stationInfo.SetFieldStatus(L1Algo::TrackingMode::kMcbm == fTrackingMode ? 0 : 1);
+        stationInfo.SetTimeInfo(
+          ca::Framework::TrackingMode::kMcbm != fTrackingMode ? stsInterface->IsTimeInfoProvided(iSt) : false);
+        stationInfo.SetFieldStatus(ca::Framework::TrackingMode::kMcbm == fTrackingMode ? 0 : 1);
         stationInfo.SetZref(stsInterface->GetZref(iSt));
         stationInfo.SetZmin(stsInterface->GetZmin(iSt));
         stationInfo.SetZmax(stsInterface->GetZmax(iSt));
@@ -551,8 +552,8 @@ InitStatus CbmL1::Init()
         // TODO: SZh 15.08.2022: Replace station type with ca::EDetectorID
         stationInfo.SetStationType(2);  // MuCh
         stationInfo.SetTimeInfo(muchInterface->IsTimeInfoProvided(iSt));
-        stationInfo.SetTimeInfo(L1Algo::TrackingMode::kMcbm != fTrackingMode ? stsInterface->IsTimeInfoProvided(iSt)
-                                                                             : false);
+        stationInfo.SetTimeInfo(
+          ca::Framework::TrackingMode::kMcbm != fTrackingMode ? stsInterface->IsTimeInfoProvided(iSt) : false);
         stationInfo.SetFieldStatus(0);
         stationInfo.SetZref(muchInterface->GetZref(iSt));
         stationInfo.SetZmin(muchInterface->GetZmin(iSt));
@@ -577,8 +578,8 @@ InitStatus CbmL1::Init()
         // TODO: SZh 15.08.2022: Replace station type with ca::EDetectorID
         stationInfo.SetStationType((iSt == 1 || iSt == 3) ? 6 : 3);  // MuCh
         stationInfo.SetTimeInfo(trdInterface->IsTimeInfoProvided(iSt));
-        stationInfo.SetTimeInfo(L1Algo::TrackingMode::kMcbm != fTrackingMode ? stsInterface->IsTimeInfoProvided(iSt)
-                                                                             : false);
+        stationInfo.SetTimeInfo(
+          ca::Framework::TrackingMode::kMcbm != fTrackingMode ? stsInterface->IsTimeInfoProvided(iSt) : false);
         stationInfo.SetFieldStatus(0);
         stationInfo.SetZref(trdInterface->GetZref(iSt));
         stationInfo.SetZmin(trdInterface->GetZmin(iSt));
@@ -586,7 +587,7 @@ InitStatus CbmL1::Init()
         stationInfo.SetXmax(trdInterface->GetXmax(iSt));
         stationInfo.SetYmax(trdInterface->GetYmax(iSt));
 
-        if (L1Algo::TrackingMode::kGlobal == fTrackingMode) { stationInfo.SetTimeInfo(false); }
+        if (ca::Framework::TrackingMode::kGlobal == fTrackingMode) { stationInfo.SetTimeInfo(false); }
         stationInfo.SetTrackingStatus(true);
         if (fvmDisabledStationIDs[ca::EDetectorID::kTrd].find(iSt)
             != fvmDisabledStationIDs[ca::EDetectorID::kTrd].cend()) {
@@ -604,8 +605,8 @@ InitStatus CbmL1::Init()
         // TODO: SZh 15.08.2022: Replace station type with ca::EDetectorID
         stationInfo.SetStationType(4);
         stationInfo.SetTimeInfo(tofInterface->IsTimeInfoProvided(iSt));
-        stationInfo.SetTimeInfo(L1Algo::TrackingMode::kMcbm != fTrackingMode ? stsInterface->IsTimeInfoProvided(iSt)
-                                                                             : false);
+        stationInfo.SetTimeInfo(
+          ca::Framework::TrackingMode::kMcbm != fTrackingMode ? stsInterface->IsTimeInfoProvided(iSt) : false);
         stationInfo.SetFieldStatus(0);
         stationInfo.SetZref(tofInterface->GetZref(iSt));
         stationInfo.SetZmin(tofInterface->GetZmin(iSt));
@@ -654,27 +655,27 @@ InitStatus CbmL1::Init()
   // Init L1 algo core
 
   // FIXME: SZh 22.08.2023:
-  //   Re-organize the the relation between CbmL1 and L1Algo. I belive, we don't need a global pointer to the L1Algo
+  //   Re-organize the the relation between CbmL1 and ca::Framework. I belive, we don't need a global pointer to the ca::Framework
   //   instance.
   fpAlgo = &gAlgo;
   fpAlgo->Init(fTrackingMode);
 
 
   //
-  // ** Send formed parameters object to L1Algo instance **
+  // ** Send formed parameters object to ca::Framework instance **
   //
   fpAlgo->ReceiveParameters(fInitManager.TakeParameters());
 
   /*** Get numbers of active stations ***/
 
-  fNMvdStations  = fpAlgo->GetParameters()->GetNstationsActive(ca::EDetectorID::kMvd);
-  fNStsStations  = fpAlgo->GetParameters()->GetNstationsActive(ca::EDetectorID::kSts);
-  fNTrdStations  = fpAlgo->GetParameters()->GetNstationsActive(ca::EDetectorID::kTrd);
-  fNMuchStations = fpAlgo->GetParameters()->GetNstationsActive(ca::EDetectorID::kMuch);
-  fNTofStations  = fpAlgo->GetParameters()->GetNstationsActive(ca::EDetectorID::kTof);
-  fNStations     = fpAlgo->GetParameters()->GetNstationsActive();
+  fNMvdStations  = fpAlgo->GetParameters().GetNstationsActive(ca::EDetectorID::kMvd);
+  fNStsStations  = fpAlgo->GetParameters().GetNstationsActive(ca::EDetectorID::kSts);
+  fNTrdStations  = fpAlgo->GetParameters().GetNstationsActive(ca::EDetectorID::kTrd);
+  fNMuchStations = fpAlgo->GetParameters().GetNstationsActive(ca::EDetectorID::kMuch);
+  fNTofStations  = fpAlgo->GetParameters().GetNstationsActive(ca::EDetectorID::kTof);
+  fNStations     = fpAlgo->GetParameters().GetNstationsActive();
 
-  LOG(info) << fpAlgo->GetParameters()->ToString(1);
+  LOG(info) << fpAlgo->GetParameters().ToString(1);
   fpIODataManager->SetNofActiveStations(fNStations);
 
   LOG(info) << "----- Numbers of stations active in tracking -----";
@@ -690,7 +691,7 @@ InitStatus CbmL1::Init()
     LOG(info) << "\033[31;1m-------------------- L1 material -----------------------------\033[0m";
     fMaterialMonitor.clear();
     for (int i = 0; i < fNStations; i++) {
-      ca::MaterialMonitor m(&(fpAlgo->GetParameters()->GetThicknessMaps()[i]), Form("station %d", i));
+      ca::MaterialMonitor m(&(fpAlgo->GetParameters().GetThicknessMaps()[i]), Form("station %d", i));
       LOG(info) << m.ToString();
       fMaterialMonitor.push_back(m);
     }
@@ -757,7 +758,7 @@ void CbmL1::Reconstruct(CbmEvent* event)
 
   if (fVerbose > 1) { cout << "\nCbmL1::Exec event " << fEventNo << " ...\n\n"; }
 
-  // ----- Read data from branches and send data from IODataManager to L1Algo ----------------------------------------
+  // ----- Read data from branches and send data from IODataManager to ca::Framework ----------------------------------------
 
   ReadEvent(event);
   //if (fPerformance) {
@@ -794,7 +795,7 @@ void CbmL1::Reconstruct(CbmEvent* event)
   //  FieldIntegralCheck();
 
   if (fVerbose > 1) { LOG(info) << "L1 Track finder..."; }
-  fpAlgo->CaTrackFinder();
+  fpAlgo->fTrackFinder.FindTracks();
   //       IdealTrackFinder();
   fTrackingTime = fpAlgo->fCaRecoTime;  // TODO: remove (not used)
 
@@ -958,6 +959,7 @@ void CbmL1::Finish()
   gFile      = currentFile;
   gDirectory = curr;
   fpAlgo->Finish();
+  cbm::ca::tools::Debugger::Instance().Write();
 }
 
 
@@ -1043,7 +1045,7 @@ void CbmL1::IdealTrackFinder()
     CaTrack algoTr;
     algoTr.fNofHits = 0;
 
-    ca::Vector<int> hitIndices("CbmL1::hitIndices", fpAlgo->GetParameters()->GetNstationsActive(), -1);
+    ca::Vector<int> hitIndices("CbmL1::hitIndices", fpAlgo->GetParameters().GetNstationsActive(), -1);
 
     for (unsigned int iH = 0; iH < MC.Hits.size(); iH++) {
       const int hitI               = MC.Hits[iH];
@@ -1053,7 +1055,7 @@ void CbmL1::IdealTrackFinder()
     }
 
 
-    for (int iH = 0; iH < fpAlgo->GetParameters()->GetNstationsActive(); iH++) {
+    for (int iH = 0; iH < fpAlgo->GetParameters().GetNstationsActive(); iH++) {
       const int hitI = hitIndices[iH];
       if (hitI < 0) continue;
 
@@ -1064,7 +1066,7 @@ void CbmL1::IdealTrackFinder()
 
     if (algoTr.fNofHits < 3) continue;
 
-    for (int iH = 0; iH < fpAlgo->GetParameters()->GetNstationsActive(); iH++) {
+    for (int iH = 0; iH < fpAlgo->GetParameters().GetNstationsActive(); iH++) {
       const int hitI = hitIndices[iH];
       if (hitI < 0) continue;
       fpAlgo->fRecoHits.push_back(hitI);
@@ -1283,7 +1285,7 @@ void CbmL1::DumpMaterialToFile(TString fileName)
 {
   TFile* f = new TFile(fileName, "RECREATE");
   f->cd();
-  const auto& param = *fpAlgo->GetParameters();
+  const auto& param = fpAlgo->GetParameters();
   const auto& map   = param.GetThicknessMaps();
   for (int ist = 0; ist < param.GetNstationsActive(); ist++) {
     //const ca::Station& st   = param.GetStation(ist);
diff --git a/reco/L1/CbmL1.h b/reco/L1/CbmL1.h
index ec4bba1492..30d34cbd70 100644
--- a/reco/L1/CbmL1.h
+++ b/reco/L1/CbmL1.h
@@ -54,13 +54,13 @@
 
 #include "AlgoFairloggerCompat.h"
 #include "CaDataManager.h"
+#include "CaFramework.h"
 #include "CaInitManager.h"
 #include "CaMaterialMonitor.h"
 #include "CaMonitor.h"
+#include "CaTrackParam.h"
 #include "CaVector.h"
-#include "L1Algo/L1Algo.h"
 
-class L1Algo;
 class CbmL1MCTrack;
 class CbmMCDataObject;
 class CbmEvent;
@@ -106,10 +106,10 @@ namespace std
 
 // TODO: insert documentation! (S.Zh.)
 //
-/// L1Algo runtime constants modification can be performed in run_reco.C. Example:
+/// ca::Framework runtime constants modification can be performed in run_reco.C. Example:
 ///
 ///   l1->GetInitManager()->GetParameters()->SetMaxDoubletsPerSinglet(149);
-/// TODO: L1InitManager - main interface of communication between cbmroot/bmnroot and L1Algo (S.Zharko)
+/// TODO: L1InitManager - main interface of communication between cbmroot/bmnroot and ca::Framework (S.Zharko)
 ///
 class CbmL1 : public FairTask {
 public:
@@ -254,9 +254,9 @@ public:
   }
 
   void SetExtrapolateToTheEndOfSTS(bool b) { fExtrapolateToTheEndOfSTS = b; }
-  void SetStsOnlyMode() { fTrackingMode = L1Algo::TrackingMode::kSts; }
-  void SetMcbmMode() { fTrackingMode = L1Algo::TrackingMode::kMcbm; }
-  void SetGlobalMode() { fTrackingMode = L1Algo::TrackingMode::kGlobal; }
+  void SetStsOnlyMode() { fTrackingMode = ca::Framework::TrackingMode::kSts; }
+  void SetMcbmMode() { fTrackingMode = ca::Framework::TrackingMode::kMcbm; }
+  void SetGlobalMode() { fTrackingMode = ca::Framework::TrackingMode::kGlobal; }
 
   // Tracking monitor (prototype)
   enum class EMonitorKey
@@ -408,7 +408,7 @@ private:
   /// \note Should be called only after CbmL1::Performance()
   void TrackFitPerformance();
 
-  void FillFitHistos(TrackParamV& tr, const CbmL1MCPoint& mc, bool isTimeFitted, TH1F* h[]);
+  void FillFitHistos(cbm::algo::ca::TrackParamV& tr, const CbmL1MCPoint& mc, bool isTimeFitted, TH1F* h[]);
 
   /// Fills performance histograms
   void HistoPerformance();
@@ -488,9 +488,10 @@ private:
 public:
   // ** Basic data members **
 
-  L1Algo* fpAlgo = nullptr;  ///< Pointer to the L1 track finder algorithm
+  ca::Framework* fpAlgo = nullptr;  ///< Pointer to the L1 track finder algorithm
 
-  L1Algo::TrackingMode fTrackingMode = L1Algo::TrackingMode::kSts;  ///< Tracking mode: kSts, kMcbm or kGlobal
+  ca::Framework::TrackingMode fTrackingMode =
+    ca::Framework::TrackingMode::kSts;  ///< Tracking mode: kSts, kMcbm or kGlobal
 
   DFSET fvSelectedMcEvents {};  ///< Set of selected MC events with fileID and eventId
 
diff --git a/reco/L1/CbmL1MCTrack.cxx b/reco/L1/CbmL1MCTrack.cxx
index 0b19922af3..331177e256 100644
--- a/reco/L1/CbmL1MCTrack.cxx
+++ b/reco/L1/CbmL1MCTrack.cxx
@@ -28,7 +28,7 @@
 
 #include "CaConstants.h"
 #include "CaHit.h"
-#include "L1Algo/L1Algo.h"
+
 
 using cbm::algo::ca::constants::size::MaxNstations;
 
@@ -123,7 +123,7 @@ void CbmL1MCTrack::CountHitStations()
   nHitContStations = 0;
   int ncont        = 0;
 
-  for (int ista = 0; ista < L1->fpAlgo->GetParameters()->GetNstationsActive(); ista++) {
+  for (int ista = 0; ista < L1->fpAlgo->GetParameters().GetNstationsActive(); ista++) {
     if (maxNStaHits < stationNhits[ista]) { maxNStaHits = stationNhits[ista]; }
     if (stationNhits[ista] > 0) {
       nStations++;
diff --git a/reco/L1/CbmL1Performance.cxx b/reco/L1/CbmL1Performance.cxx
index 8cf2daa8f5..182f670d4e 100644
--- a/reco/L1/CbmL1Performance.cxx
+++ b/reco/L1/CbmL1Performance.cxx
@@ -55,9 +55,12 @@
 
 #include <cmath>
 
+#include "CaFramework.h"
 #include "CaToolsDebugger.h"
 #include "CaTrackFit.h"
-#include "L1Algo.h"
+#include "CaTrackParam.h"
+
+using namespace cbm::algo::ca;
 
 using cbm::ca::tools::Debugger;
 using std::cout;
@@ -335,7 +338,7 @@ void CbmL1::EfficienciesPerformance()
         cout << " n mc stations: " << t.NMCStations() << endl;
       }
       for (unsigned int i = 0; i < rtraIt->Hits.size(); i++) {
-        const ca::Hit& h           = fpAlgo->fInputData.GetHit(rtraIt->Hits[i]);
+        const ca::Hit& h           = fpAlgo->GetInputData().GetHit(rtraIt->Hits[i]);
         const CbmL1HitDebugInfo& s = fvHitDebugInfo[rtraIt->Hits[i]];
         cout << " x y z t " << s.x << " " << s.y << " " << h.Z() << " dx " << s.dx << " dy " << s.dy << std::endl;
         cbm::ca::tools::Debugger::Instance().FillNtuple("ghost", statNghost, i, fabs(1. / tr.GetQp()[0]), s.x, s.y,
@@ -346,10 +349,10 @@ void CbmL1::EfficienciesPerformance()
     }
   }
 
-  int sta_nhits[fpAlgo->GetParameters()->GetNstationsActive()];
-  int sta_nfakes[fpAlgo->GetParameters()->GetNstationsActive()];
+  int sta_nhits[fpAlgo->GetParameters().GetNstationsActive()];
+  int sta_nfakes[fpAlgo->GetParameters().GetNstationsActive()];
 
-  for (int i = 0; i < fpAlgo->GetParameters()->GetNstationsActive(); i++) {
+  for (int i = 0; i < fpAlgo->GetParameters().GetNstationsActive(); i++) {
     sta_nhits[i]  = 0;
     sta_nfakes[i] = 0;
   }
@@ -486,7 +489,7 @@ void CbmL1::EfficienciesPerformance()
     if (fVerbose > 1) {
       ntra.PrintEff(true, true);
       cout << "Number of true and fake hits in stations: " << endl;
-      for (int i = 0; i < fpAlgo->GetParameters()->GetNstationsActive(); i++) {
+      for (int i = 0; i < fpAlgo->GetParameters().GetNstationsActive(); i++) {
         cout << sta_nhits[i] - sta_nfakes[i] << "+" << sta_nfakes[i] << "   ";
       }
       cout << endl;
@@ -839,16 +842,16 @@ void CbmL1::HistoPerformance()  // TODO: check if works correctly. Change vHitFa
 
       int iFstHit  = prtra->GetFirstHitIndex();
       auto& fstHit = fvHitDebugInfo[iFstHit];
-      h2_fst_hit_yz->Fill(fpAlgo->GetParameters()->GetStation(fstHit.iStation).fZ[0], fstHit.GetY());
+      h2_fst_hit_yz->Fill(fpAlgo->GetParameters().GetStation(fstHit.iStation).fZ[0], fstHit.GetY());
 
       int iLstHit  = prtra->GetLastHitIndex();
       auto& lstHit = fvHitDebugInfo[iLstHit];
-      h2_lst_hit_yz->Fill(fpAlgo->GetParameters()->GetStation(lstHit.iStation).fZ[0], lstHit.GetY());
+      h2_lst_hit_yz->Fill(fpAlgo->GetParameters().GetStation(lstHit.iStation).fZ[0], lstHit.GetY());
 
       for (int iH : prtra->Hits) {
         const auto& hit = fvHitDebugInfo[iH];
         int y           = hit.GetY();
-        int z           = fpAlgo->GetParameters()->GetStation(hit.iStation).fZ[0];
+        int z           = fpAlgo->GetParameters().GetStation(hit.iStation).fZ[0];
         h2_all_hit_yz->Fill(z, y);
       }
     }
@@ -888,8 +891,8 @@ void CbmL1::HistoPerformance()  // TODO: check if works correctly. Change vHitFa
       CbmL1HitDebugInfo& h2 = fvHitDebugInfo[prtra->Hits[1]];
       h_ghost_fstation->Fill(h1.iStation);
       h_ghost_r->Fill(sqrt(fabs(h1.x * h1.x + h1.y * h1.y)));
-      double z1 = fpAlgo->GetParameters()->GetStation(h1.iStation).fZ[0];
-      double z2 = fpAlgo->GetParameters()->GetStation(h2.iStation).fZ[0];
+      double z1 = fpAlgo->GetParameters().GetStation(h1.iStation).fZ[0];
+      double z2 = fpAlgo->GetParameters().GetStation(h2.iStation).fZ[0];
       if (fabs(z2 - z1) > 1.e-4) {
         h_ghost_tx->Fill((h2.x - h1.x) / (z2 - z1));
         h_ghost_ty->Fill((h2.y - h1.y) / (z2 - z1));
@@ -1092,8 +1095,8 @@ void CbmL1::HistoPerformance()  // TODO: check if works correctly. Change vHitFa
       //      CbmL1HitDebugInfo &ph21 = fvHitDebugInfo[mtra.Hits[0]];
       //      CbmL1HitDebugInfo &ph22 = fvHitDebugInfo[mtra.Hits[1]];
 
-      //      double z21 = fpAlgo->GetParameters()->GetStation(ph21.iStation).fZ[0];
-      //      double z22 = fpAlgo->GetParameters()->GetStation(ph22.iStation).fZ[0];
+      //      double z21 = fpAlgo->GetParameters().GetStation(ph21.iStation).fZ[0];
+      //      double z22 = fpAlgo->GetParameters().GetStation(ph22.iStation).fZ[0];
       //      if( fabs(z22-z21)>1.e-4 ){
       //        h_notfound_tx->Fill((ph22.x-ph21.x)/(z22-z21));
       //        h_notfound_ty->Fill((ph22.y-ph21.y)/(z22-z21));
@@ -1221,7 +1224,7 @@ void CbmL1::TrackFitPerformance()
                          {"pvi", "Pull Vi [residual/estimated_error]", 100, -10., 10.},
                          {"distrVi", "Vi distribution [1/c]", 100, 0., 4.}};
 
-      if (L1Algo::kGlobal == fpAlgo->fTrackingMode) {
+      if (ca::Framework::kGlobal == fpAlgo->fTrackingMode) {
         Table[4].l = -1.;
         Table[4].r = 1.;
       }
@@ -1254,7 +1257,7 @@ void CbmL1::TrackFitPerformance()
                                  {"pvi", "Pull Vi [residual/estimated_error]", 100, -10., 10.},
                                  {"distrVi", "Vi distribution [1/c]", 100, -10., 10.}};
 
-      if (L1Algo::kGlobal == fpAlgo->fTrackingMode) {
+      if (ca::Framework::kGlobal == fpAlgo->fTrackingMode) {
         TableVertex[4].l = -1.;
         TableVertex[4].r = 1.;
       }
@@ -1296,7 +1299,7 @@ void CbmL1::TrackFitPerformance()
       int nTimeMeasurenments = 0;
       for (unsigned int ih = 0; ih < it->Hits.size(); ih++) {
         int ista = fvHitDebugInfo[it->Hits[ih]].iStation;
-        if (fpAlgo->GetParameters()->GetStation(ista).timeInfo) { nTimeMeasurenments++; }
+        if (fpAlgo->GetParameters().GetStation(ista).timeInfo) { nTimeMeasurenments++; }
       }
       isTimeFitted = (nTimeMeasurenments > 1);
     }
@@ -1382,14 +1385,14 @@ void CbmL1::TrackFitPerformance()
           fit.Extrapolate(mc.z, fld);
           // add material
           const int fSta = fvHitDebugInfo[it->Hits[0]].iStation;
-          const int dir  = int((mc.z - fpAlgo->GetParameters()->GetStation(fSta).fZ[0])
-                              / fabs(mc.z - fpAlgo->GetParameters()->GetStation(fSta).fZ[0]));
-          //         if (abs(mc.z - fpAlgo->GetParameters()->GetStation(fSta).fZ[0]) > 10.) continue; // can't extrapolate on large distance
+          const int dir  = int((mc.z - fpAlgo->GetParameters().GetStation(fSta).fZ[0])
+                              / fabs(mc.z - fpAlgo->GetParameters().GetStation(fSta).fZ[0]));
+          //         if (abs(mc.z - fpAlgo->GetParameters().GetStation(fSta).fZ[0]) > 10.) continue; // can't extrapolate on large distance
           for (int iSta = fSta /*+dir*/; (iSta >= 0) && (iSta < fNStations)
-                                         && (dir * (mc.z - fpAlgo->GetParameters()->GetStation(iSta).fZ[0]) > 0);
+                                         && (dir * (mc.z - fpAlgo->GetParameters().GetStation(iSta).fZ[0]) > 0);
                iSta += dir) {
             //           cout << iSta << " " << dir << endl;
-            auto radThick = fpAlgo->GetParameters()->GetMaterialThickness(iSta, fit.Tr().GetX(), fit.Tr().GetY());
+            auto radThick = fpAlgo->GetParameters().GetMaterialThickness(iSta, fit.Tr().GetX(), fit.Tr().GetY());
             fit.MultipleScattering(radThick);
             fit.EnergyLossCorrection(radThick, fvec::One());
           }
@@ -1446,16 +1449,16 @@ void CbmL1::TrackFitPerformance()
           // add material
           const int fSta = fvHitDebugInfo[it->Hits[0]].iStation;
 
-          const int dir = (mc.z - fpAlgo->GetParameters()->GetStation(fSta).fZ[0])
-                          / abs(mc.z - fpAlgo->GetParameters()->GetStation(fSta).fZ[0]);
-          //         if (abs(mc.z - fpAlgo->GetParameters()->GetStation(fSta].fZ[0]) > 10.) continue; // can't extrapolate on large distance
+          const int dir = (mc.z - fpAlgo->GetParameters().GetStation(fSta).fZ[0])
+                          / abs(mc.z - fpAlgo->GetParameters().GetStation(fSta).fZ[0]);
+          //         if (abs(mc.z - fpAlgo->GetParameters().GetStation(fSta].fZ[0]) > 10.) continue; // can't extrapolate on large distance
 
           for (int iSta = fSta + dir; (iSta >= 0) && (iSta < fNStations)
-                                      && (dir * (mc.z - fpAlgo->GetParameters()->GetStation(iSta).fZ[0]) > 0);
+                                      && (dir * (mc.z - fpAlgo->GetParameters().GetStation(iSta).fZ[0]) > 0);
                iSta += dir) {
 
-            fit.Extrapolate(fpAlgo->GetParameters()->GetStation(iSta).fZ, fld);
-            auto radThick = fpAlgo->GetParameters()->GetMaterialThickness(iSta, fit.Tr().GetX(), fit.Tr().GetY());
+            fit.Extrapolate(fpAlgo->GetParameters().GetStation(iSta).fZ, fld);
+            auto radThick = fpAlgo->GetParameters().GetMaterialThickness(iSta, fit.Tr().GetX(), fit.Tr().GetY());
             fit.MultipleScattering(radThick);
             fit.EnergyLossCorrection(radThick, fvec::One());
           }
@@ -1632,9 +1635,9 @@ void CbmL1::FieldApproxCheck()
   FairField* MF = FairRunAna::Instance()->GetField();
   assert(MF);
 
-  for (int ist = 0; ist < fpAlgo->GetParameters()->GetNstationsActive(); ist++) {
+  for (int ist = 0; ist < fpAlgo->GetParameters().GetNstationsActive(); ist++) {
 
-    const ca::Station& st = fpAlgo->GetParameters()->GetStation(ist);
+    const ca::Station& st = fpAlgo->GetParameters().GetStation(ist);
 
     double z    = st.fZ[0];
     double Xmax = st.Xmax[0];
diff --git a/reco/L1/CbmL1ReadEvent.cxx b/reco/L1/CbmL1ReadEvent.cxx
index c01b291e0d..f37f73ec4f 100644
--- a/reco/L1/CbmL1ReadEvent.cxx
+++ b/reco/L1/CbmL1ReadEvent.cxx
@@ -48,8 +48,8 @@
 
 #include <iostream>
 
+#include "CaFramework.h"
 #include "CaToolsDebugger.h"
-#include "L1Algo/L1Algo.h"
 
 using std::cout;
 using std::endl;
@@ -383,7 +383,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
       CbmMvdHit* h = dynamic_cast<CbmMvdHit*>(fpMvdHits->At(hitIndex));
       {
         th.ExtIndex = hitIndex;
-        th.iStation = fpAlgo->GetParameters()->GetStationIndexActive(
+        th.iStation = fpAlgo->GetParameters().GetStationIndexActive(
           CbmMvdTrackingInterface::Instance()->GetTrackingStationIndex(h), ca::EDetectorID::kMvd);
 
         if (th.iStation < 0) continue;
@@ -449,7 +449,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
         th.ExtIndex = hitIndex;
         th.Det      = 1;
 
-        th.iStation = fpAlgo->GetParameters()->GetStationIndexActive(
+        th.iStation = fpAlgo->GetParameters().GetStationIndexActive(
           CbmStsTrackingInterface::Instance()->GetTrackingStationIndex(h), ca::EDetectorID::kSts);
 
         if (th.iStation < 0) continue;
@@ -511,7 +511,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
         th.ExtIndex = hitIndex;
         th.Det      = 2;
 
-        th.iStation = fpAlgo->GetParameters()->GetStationIndexActive(
+        th.iStation = fpAlgo->GetParameters().GetStationIndexActive(
           CbmMuchTrackingInterface::Instance()->GetTrackingStationIndex(h), ca::EDetectorID::kMuch);
 
         if (th.iStation < 0) continue;
@@ -567,7 +567,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
       Int_t hitIndex = (event ? event->GetIndex(ECbmDataType::kTrdHit, iHit) : iHit);
       CbmTrdHit* h   = dynamic_cast<CbmTrdHit*>(fpTrdHits->At(hitIndex));
 
-      if ((L1Algo::TrackingMode::kGlobal == fTrackingMode) && (int) h->GetClassType() != 1) {
+      if ((ca::Framework::TrackingMode::kGlobal == fTrackingMode) && (int) h->GetClassType() != 1) {
         // SGtrd2d!! skip TRD-1D hit
         continue;
       }
@@ -575,7 +575,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
       th.ExtIndex = hitIndex;
       th.Det      = 3;
 
-      th.iStation = fpAlgo->GetParameters()->GetStationIndexActive(
+      th.iStation = fpAlgo->GetParameters().GetStationIndexActive(
         CbmTrdTrackingInterface::Instance()->GetTrackingStationIndex(h), ca::EDetectorID::kTrd);
 
       if (th.iStation < 0) continue;
@@ -645,7 +645,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
 
       if (5 == CbmTofAddress::GetSmType(h->GetAddress())) continue;  // Skip T0 hits from TOF
 
-      th.iStation = fpAlgo->GetParameters()->GetStationIndexActive(
+      th.iStation = fpAlgo->GetParameters().GetStationIndexActive(
         CbmTofTrackingInterface::Instance()->GetTrackingStationIndex(h), ca::EDetectorID::kTof);
 
       if (th.iStation < 0) continue;
@@ -673,7 +673,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
       std::tie(th.rangeX, th.rangeY, th.rangeT) = CbmTofTrackingInterface::Instance()->GetHitRanges(*h);
 
       //TODO:  is it still needed here? (S.Zharko)
-      if (L1Algo::TrackingMode::kMcbm == fTrackingMode && th.z > 400) continue;
+      if (ca::Framework::TrackingMode::kMcbm == fTrackingMode && th.z > 400) continue;
 
       if (fPerformance) { std::tie(th.iBestMc, th.vMc) = MatchHitWithMc<ca::EDetectorID::kTof>(hitIndex); }
 
@@ -781,7 +781,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
 
   if (fVerbose >= 2) cout << "ReadEvent: mvd and sts are saved." << endl;
 
-  // ----- Send data from IODataManager to L1Algo --------------------------------------------------------------------
+  // ----- Send data from IODataManager to ca::Framework --------------------------------------------------------------------
   if (1 == fSTAPDataMode) { WriteSTAPAlgoInputData(nCalls); }
   if (2 == fSTAPDataMode) { ReadSTAPAlgoInputData(nCalls); }
   // TODO: SZh: If we read data from file, we don't need to collect them above. This should be addressed
@@ -932,7 +932,7 @@ void CbmL1::ReadMCPoint(ca::EDetectorID iDet, int file, int event, int iPoint)
 
   CbmL1MCPoint MC;
 
-  MC.iStation = fpAlgo->GetParameters()->GetStationIndexActive(iStLoc, iDet);
+  MC.iStation = fpAlgo->GetParameters().GetStationIndexActive(iStLoc, iDet);
   if (MC.iStation < 0) { return; }
 
   TVector3 xyzI, PI;
diff --git a/reco/L1/L1Algo/L1Algo.h b/reco/L1/L1Algo/L1Algo.h
deleted file mode 100644
index 41bd91f5c3..0000000000
--- a/reco/L1/L1Algo/L1Algo.h
+++ /dev/null
@@ -1,435 +0,0 @@
-/* Copyright (C) 2007-2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Maksym Zyzak, Valentina Akishina, Igor Kulakov [committer], Sergei Zharko */
-
-#ifndef L1Algo_h
-#define L1Algo_h
-
-/// Debug features
-// #define PULLS            // triplets pulls
-// #define TRIP_PERFORMANCE // triplets efficiencies
-// #define DOUB_PERFORMANCE // doublets efficiencies
-// #define DRAW             // event display
-#ifdef DRAW
-class L1AlgoDraw;
-#endif
-//#define XXX               // time debug
-//#define COUNTERS          // diff counters (hits, doublets, ... )
-
-//#define GLOBAL
-//#define mCBM
-
-#include <array>
-#include <iomanip>
-#include <iostream>
-#include <limits>
-#include <map>
-
-#include "CaBranch.h"
-#include "CaConstants.h"
-#include "CaField.h"
-#include "CaGrid.h"
-#include "CaGridEntry.h"
-#include "CaHit.h"
-#include "CaInputData.h"
-#include "CaMeasurementXy.h"
-#include "CaParameters.h"
-#include "CaStation.h"
-#include "CaTimer.h"
-#include "CaTrack.h"
-#include "CaTrackParam.h"
-#include "CaTrackingMonitor.h"
-#include "CaTriplet.h"
-#include "CaVector.h"
-#include "L1CloneMerger.h"
-
-using namespace cbm::algo::ca;  //TODO: remove
-
-class CbmL1MCTrack;
-
-// *******************************
-// ** Types definition (global) **
-// *******************************
-
-using L1StationsArray_t = std::array<ca::Station, constants::size::MaxNstations>;
-using L1MaterialArray_t = std::array<ca::MaterialMap, constants::size::MaxNstations>;
-using Tindex            = int;  // TODO: Replace with ca::HitIndex_t, if suitable
-
-#ifdef PULLS
-#define TRIP_PERFORMANCE
-class L1AlgoPulls;
-#endif
-#ifdef TRIP_PERFORMANCE
-template<Tindex NHits>
-class L1AlgoEfficiencyPerformance;
-#endif
-#ifdef DOUB_PERFORMANCE
-template<Tindex NHits>
-class L1AlgoEfficiencyPerformance;
-#endif
-
-struct L1HitTimeInfo {
-  fscal fEventTimeMin {-std::numeric_limits<fscal>::max() / 2.};
-  fscal fEventTimeMax {std::numeric_limits<fscal>::max() / 2.};
-  fscal fMaxTimeBeforeHit {0.};  //< max event time for hits [0 .. hit] in the station hit array
-  fscal fMinTimeAfterHit {0.};   //< min event time for hits [hit ... ] in the station hit array
-};
-
-/// Main class of L1 CA track finder algorithm
-///
-class L1Algo {
-public:
-  // *************************
-  // ** Friend classes list **
-  // *************************
-
-  friend class CbmL1;  /// TODO: Remove this dependency
-  friend class L1TripletConstructor;
-#ifdef DRAW
-  friend class L1AlgoDraw;
-#endif
-  // ***************************
-  // ** Internal enumerations **
-  // ***************************
-
-  /// TODO: Move to L1
-  enum TrackingMode
-  {
-    kSts,
-    kGlobal,
-    kMcbm
-  };
-
-
-  // **********************************
-  // ** Member functions declaration **
-  // **********************************
-
-  // ** Constructors and destructor
-
-  /// Constructor
-  L1Algo();
-
-  /// Copy constructor
-  L1Algo(const L1Algo&) = delete;
-
-  /// Move constructor
-  L1Algo(L1Algo&&) = delete;
-
-  /// Copy assignment operator
-  L1Algo& operator=(const L1Algo&) = delete;
-
-  /// Move assignment operator
-  L1Algo& operator=(L1Algo&&) = delete;
-
-  /// Destructor
-  ~L1Algo() = default;
-
-
-  // ** Functions, which pack and unpack indexes of station and triplet **
-
-  // TODO: move to ca::Triplet class (S.Zharko)
-  /// Packs station and triplet indices to an unique triplet ID
-  /// \param  iStation  Index of station in the active stations array
-  /// \param  iTriplet  Index of triplet
-  static unsigned int PackTripletId(unsigned int iStation, unsigned int iTriplet);
-
-  /// Unpacks the triplet ID to its station index
-  /// \param  id  Unique triplet ID
-  static unsigned int TripletId2Station(unsigned int id);
-
-  /// Unpacks the triplet ID to its triplet index
-  /// \param  id  Unique triplet ID
-  static unsigned int TripletId2Triplet(unsigned int id);
-
-
-  /// Sets L1Algo parameters object
-  /// \param other - reference to the Parameters object
-  void SetParameters(const Parameters& other) { fParameters = other; }
-  // TODO: remove it (S.Zharko)
-
-  /// Gets a pointer to the L1Algo parameters object
-  const Parameters* GetParameters() const { return &fParameters; }
-
-  /// Receives input data
-  void ReceiveInputData(InputData&& inputData);
-
-  /// Receives tracking parameters
-  void ReceiveParameters(Parameters&& parameters);
-
-  /// Gets pointer to input data object for external access
-  const InputData& GetInputData() const { return fInputData; }
-
-  int PackIndex(const int& a, const int& b, const int& c);
-
-  int UnPackIndex(const int& i, int& a, int& b, int& c);
-
-  /// \brief Sets a default particle mass for the track fit
-  /// \param mass Default particle mass
-  ///
-  /// The function is used during the reconstruction in order to estimate the multiple scattering and energy loss
-  void SetDefaultParticleMass(float mass) { fDefaultMass = mass; }
-
-  /// \brief  Gets default particle mass
-  /// \return particle mass
-  float GetDefaultParticleMass() const { return fDefaultMass; }
-
-  /// \brief  Gets default particle mass squared
-  /// \return particle mass squared
-  float GetDefaultParticleMass2() const { return fDefaultMass * fDefaultMass; }
-
-
-  /*********************************************************************************************/ /**
-   *                             ------  FUNCTIONAL PART ------
-   ************************************************************************************************/
-
-  /// ----- Subroutines used by L1Algo::CaTrackFinder() ------
-
-  void ReadWindowData();
-
-  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);
-
-
-  /// \brief Fits track
-  /// \param t - track with hits
-  /// \param T - track parameters
-  /// \param dir - false - forward, true - backward
-  /// \param qp0 - momentum for extrapolation
-  /// \param initParams - should be params ititialized. 1 - yes.
-  void BranchFitterFast(const ca::Branch& t, TrackParamV& T, const bool dir, const fvec qp0 = 0.,
-                        const bool initParams = true);
-
-  /// \brief Fits track. more precise than FitterFast
-  /// \param t - track with hits
-  /// \param T - track parameters
-  /// \param dir - false - forward, true - backward
-  /// \param qp0 - momentum for extrapolation
-  /// \param initParams - should be params ititialized. 1 - yes.
-  void BranchFitter(const ca::Branch& t, TrackParamV& T, const bool dir, const fvec qp0 = 0.,
-                    const bool initParams = true);
-
-  /// \brief Finds additional hits for already found track
-  /// \param t - track with hits
-  /// \param T - track params
-  /// \param dir - 0 - forward, 1 - backward
-  /// \param qp0 - momentum for extrapolation
-  void FindMoreHits(ca::Branch& t, TrackParamV& T, const bool dir, const fvec qp0 = 0.0);
-
-  /// \brief  Finds additional hits for existing track
-  /// \return chi2
-  fscal BranchExtender(ca::Branch& t);
-
-#ifdef DRAW
-  L1AlgoDraw* draw {nullptr};
-#endif
-
-
-  void Init(const TrackingMode mode);
-
-  void Finish();
-
-  void PrintHits();
-
-  /// The main procedure - find tracks
-  void CaTrackFinder();
-
-  /// find tracks in a sub-timeslice
-  void CaTrackFinderSlice();
-
-  /// Track fitting procedures
-
-  void L1KFTrackFitter();  // version from SIMD-KF benchmark
-
-
-  float GetMaxInvMom() const { return fMaxInvMom[0]; }
-
-  /// \brief Gets reference to the monitor
-  const TrackingMonitor& GetMonitor() const { return fMonitor; }
-
-public:
-  /// Gets number of stations before the pipe (MVD stations in CBM)
-  int GetNstationsBeforePipe() const { return fNstationsBeforePipe; }
-
-  /// Gets number of stations situated in field region (MVD + STS in CBM)
-  int GetNfieldStations() const { return fNfieldStations; }
-
-  /// Get mc track ID for a hit (debug tool)
-  int GetMcTrackIdForCaHit(int iHit) const;
-
-  /// Get mc track ID for a hit (debug tool)
-  int GetMcTrackIdForWindowHit(int iGridHit) const;
-
-  const CbmL1MCTrack* GetMcTrackForWindowHit(int iHit) const;
-
-private:
-  bool checkTripletMatch(const ca::Triplet& l, const ca::Triplet& r, fscal& dchi2) const;
-
-  int fNstationsBeforePipe {0};  ///< number of stations before pipe (MVD stations in CBM)
-  int fNfieldStations {0};       ///< number of stations in the field region
-  //alignas(16) L1StationsArray_t fStations {};  ///< array of ca::Station objects
-  //alignas(16) L1MaterialArray_t fRadThick {};  ///< material for each station
-  float fDefaultMass {constants::phys::MuonMass};  ///< mass of the propagated particle [GeV/c2]
-
-
-  // ***************************
-  // ** Member variables list **
-  // ***************************
-
-  Parameters fParameters;  ///< Object of L1Algo parameters class
-  InputData fInputData;    ///< Tracking input data
-
-  Vector<unsigned char> fvHitKeyFlags {
-    "L1Algo::fvHitKeyFlags"};  ///< List of key flags: has been this hit or cluster already used
-
-  ca::TrackingMonitor fMonitor {"CA Algo"};  ///< Tracking monitor
-
-public:
-  Vector<L1HitTimeInfo> fHitTimeInfo;
-
-  ca::Grid vGrid[constants::size::MaxNstations];  ///<
-
-  /// ----- Data used during track finding -----
-  ///
-
-  ///\brief hits of the current time window
-  /// it is a portion of fInputData to process in the current time window
-  /// hit.Id is replaced by the hit index in fInputData
-  Vector<ca::Hit> fWindowHits {"L1Algo::fWindowHits"};
-
-  Vector<unsigned char> fIsWindowHitSuppressed {"L1Algo::fIsWindowHitSuppressed"};
-
-  ///\brief first index of the station hits in the time window
-  ca::HitIndex_t fStationHitsStartIndex[constants::size::MaxNstations + 1] {0};
-
-  ///\brief number of station hits in the time window
-  ca::HitIndex_t fStationNhits[constants::size::MaxNstations + 1] {0};
-
-  /// ----------
-
-  double fCaRecoTime {0.};  // time of the track finder + fitter
-
-  Vector<Track> fRecoTracks {"L1Algo::fRecoTracks"};       ///< reconstructed tracks
-  Vector<ca::HitIndex_t> fRecoHits {"L1Algo::fRecoHits"};  ///< packed hits of reconstructed tracks
-
-  Vector<Track> fSliceRecoTracks {"L1Algo::fSliceRecoTracks"};       ///< reconstructed tracks in sub-timeslice
-  Vector<ca::HitIndex_t> fSliceRecoHits {"L1Algo::fSliceRecoHits"};  ///< packed hits of reconstructed tracks
-
-  /// Created triplets vs station index
-  // FIXME: Better std::array<Vector<Triplet>, constants::size::MaxNstations>
-  Vector<ca::Triplet> fTriplets[constants::size::MaxNstations] {{"L1Algo::fTriplets"}};
-
-  /// Track candidates created out of adjacent triplets before the final track selection.
-  /// The candidates may share any amount of hits.
-  // FIXME: Better std::array<Vector<Branch>, constants::size::MaxNstations>
-  Vector<ca::Branch> fTrackCandidates {"L1Algo::fTrackCandidates"};
-
-  ///< indices of the sub-slice hits
-  // FIXME: Better std::array<Vector<HitIndex_t>, constants::size::MaxNstations>
-  Vector<ca::HitIndex_t> fSliceHitIds[constants::size::MaxNstations] {"L1Algo::fSliceHitIds"};
-
-  Vector<int> fStripToTrack {"L1Algo::fStripToTrack"};  // strip to track pointers
-
-  TrackingMode fTrackingMode {kSts};
-
-  fvec EventTime {0.f};
-  fvec Err {0.f};
-
-  /// --- data used during finding iterations
-  unsigned int fCurrentIterationIndex {0};        ///< index of the corrent iteration, needed for debug output
-  const Iteration* fpCurrentIteration = nullptr;  ///< pointer to the current CA track finder iteration
-
-  Vector<int> fHitFirstTriplet {"L1Algo::fHitFirstTriplet"};  /// link hit -> first triplet { hit, *, *}
-  Vector<int> fHitNtriplets {"L1Algo::fHitNtriplets"};        /// link hit ->n triplets { hit, *, *}
-
-
-private:
-  L1CloneMerger fCloneMerger {*this};  ///< Object of L1Algo clones merger algorithm
-
-  /// =================================  DATA PART  =================================
-
-  /// ----- Different parameters of CATrackFinder -----
-
-  Tindex fFirstCAstation {0};  //first station used in CA
-
-  // fNFindIterations - set number of interation for trackfinding
-  // itetation of finding:
-
-  int fNFindIterations = -1;  // TODO investigate kAllPrimJumpIter & kAllSecJumpIter
-
-  float fTrackChi2Cut {10.f};
-  float fTripletFinalChi2Cut {10.f};
-  float fTripletChi2Cut {5.f};  // cut for selecting triplets before collecting tracks.per one DoF
-  float fDoubletChi2Cut {5.f};
-  float fTimeCut1 {0.f};  // TODO: please, specify "1" and "2" (S.Zharko)
-  float fTimeCut2 {0.f};
-
-  /// correction in order to take into account overlaping and iff z. if sort by y then it is max diff between same station's modules (~0.4cm)
-  fvec fMaxDZ {constants::Undef<fvec>};
-
-  /// parameters which are different for different iterations. Set in the begin of CAL1TrackFinder
-
-  float fPickGather {constants::Undef<fvec>};       ///< same for attaching additional hits to track
-  float fTripletLinkChi2 {constants::Undef<fvec>};  ///< (dp2/dp_error2 < fTripletLinkChi2)  =>  triplets are neighbours
-  fvec fMaxInvMom {constants::Undef<fvec>};         ///< max considered q/p for tracks
-  fvec fMaxSlopePV {constants::Undef<fvec>};        ///< max slope (tx\ty) in prim vertex
-  float fMaxSlope {constants::Undef<fvec>};         ///< max slope (tx\ty) in 3d hit position of a triplet
-
-  fvec fTargX {constants::Undef<fvec>};  ///< target position x coordinate for the current iteration (modifiable)
-  fvec fTargY {constants::Undef<fvec>};  ///< target position y coordinate for the current iteration (modifiable)
-  fvec fTargZ {constants::Undef<fvec>};  ///< target position z coordinate for the current iteration (modifiable)
-
-  bool fIsTargetField {false};  ///< is the magnetic field present at the target
-
-  ca::FieldValue fTargB _fvecalignment {};  // field in the target point (modifiable, do not touch!!)
-  ca::MeasurementXy<fvec> TargetMeasurement _fvecalignment {};  // target constraint  [cm]
-
-  int fGhostSuppression {1};  // NOTE: Should be equal to 0 in TRACKS_FROM_TRIPLETS mode!
-
-  /// ----- Debug features -----
-#ifdef PULLS
-  L1AlgoPulls* fL1Pulls;
-#endif
-#ifdef TRIP_PERFORMANCE
-  L1AlgoEfficiencyPerformance<3>* fL1Eff_triplets;
-  L1AlgoEfficiencyPerformance<3>* fL1Eff_triplets2;
-#endif
-#ifdef DOUB_PERFORMANCE
-  L1AlgoEfficiencyPerformance<2>* fL1Eff_doublets;
-#endif
-} _fvecalignment;
-
-
-// ********************************************
-// ** Inline member functions implementation **
-// ********************************************
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-[[gnu::always_inline]] inline unsigned int L1Algo::PackTripletId(unsigned int iStation, unsigned int iTriplet)
-{
-#ifndef FAST_CODE
-  assert(iStation < constants::size::MaxNstations);
-  assert(iTriplet < constants::size::MaxNtriplets);
-#endif
-  constexpr unsigned int kMoveStation = constants::size::TripletBits;
-  return (iStation << kMoveStation) + iTriplet;
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-[[gnu::always_inline]] inline unsigned int L1Algo::TripletId2Station(unsigned int id)
-{
-  constexpr unsigned int kMoveStation = constants::size::TripletBits;
-  return id >> kMoveStation;
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-[[gnu::always_inline]] inline unsigned int L1Algo::TripletId2Triplet(unsigned int id)
-{
-  constexpr unsigned int kTripletMask = (1u << constants::size::TripletBits) - 1u;
-  return id & kTripletMask;
-}
-
-#endif
diff --git a/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx b/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx
deleted file mode 100644
index c4b39e28e2..0000000000
--- a/reco/L1/L1Algo/L1CaTrackFinderSlice.cxx
+++ /dev/null
@@ -1,871 +0,0 @@
-/* Copyright (C) 2009-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Valentina Akishina, Ivan Kisel, Sergey Gorbunov [committer], Igor Kulakov, Maksym Zyzak */
-
-/*
- *=====================================================
- *
- *  CBM Level 1 4D Reconstruction
- *
- *  Authors: V.Akishina, I.Kisel,  S.Gorbunov, I.Kulakov, M.Zyzak
- *  Documentation: V.Akishina
- *
- *  e-mail : v.akishina@gsi.de
- *
- *=====================================================
- *
- *  Finds tracks using the Cellular Automaton algorithm
- *
- */
-
-
-#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 "L1TripletConstructor.h"
-#ifdef DRAW
-#include "utils/L1AlgoDraw.h"
-#endif  // DRAW
-#ifdef PULLS
-#include "utils/L1AlgoPulls.h"
-#endif  // PULLS
-#ifdef TRIP_PERFORMANCE
-#include "utils/L1AlgoEfficiencyPerformance.h"
-#endif  // TRIP_PERFORMANCE
-#ifdef DOUB_PERFORMANCE
-#include "utils/L1AlgoEfficiencyPerformance.h"
-#endif  // DOUB_PERFORMANCE
-
-#include <algorithm>
-#include <fstream>
-#include <iostream>
-#include <list>
-#include <map>
-
-#include <stdio.h>
-
-#include "CaToolsDebugger.h"
-
-
-// using namespace std;
-using std::cout;
-using std::endl;
-using Track = cbm::algo::ca::Track;
-
-bool L1Algo::checkTripletMatch(const ca::Triplet& l, const ca::Triplet& r, fscal& dchi2) const
-{
-  dchi2 = 1.e20;
-
-  if (r.GetMHit() != l.GetRHit()) return false;
-  if (r.GetLHit() != l.GetMHit()) return false;
-
-  if (r.GetMSta() != l.GetRSta()) return false;
-  if (r.GetLSta() != l.GetMSta()) return false;
-
-
-  if (r.IsMomentumFitted()) {
-    assert(l.IsMomentumFitted());
-
-    fscal dqp = l.GetQp() - r.GetQp();
-    fscal Cqp = l.GetCqp() + r.GetCqp();
-
-    if (!std::isfinite(dqp)) return false;
-    if (!std::isfinite(Cqp)) return false;
-
-    if (dqp * dqp > fTripletLinkChi2 * Cqp) {
-      return false;  // bad neighbour // CHECKME why do we need recheck it?? (it really change result)
-    }
-    dchi2 = dqp * dqp / Cqp;
-  }
-  else {
-    fscal dtx = l.GetTx() - r.GetTx();
-    fscal Ctx = l.GetCtx() + r.GetCtx();
-
-    fscal dty = l.GetTy() - r.GetTy();
-    fscal Cty = l.GetCty() + r.GetCty();
-
-    // it shouldn't happen, but happens sometimes
-
-    if (!std::isfinite(dtx)) return false;
-    if (!std::isfinite(dty)) return false;
-    if (!std::isfinite(Ctx)) return false;
-    if (!std::isfinite(Cty)) return false;
-
-    if (dty * dty > fTripletLinkChi2 * Cty) return false;
-    if (dtx * dtx > fTripletLinkChi2 * Ctx) return false;
-
-    //dchi2 = 0.5f * (dtx * dtx / Ctx + dty * dty / Cty);
-    dchi2 = 0.;
-  }
-
-  if (!std::isfinite(dchi2)) return false;
-
-  return true;
-}
-
-
-// **************************************************************************************************
-// *                                                                                                *
-// *                            ------ CATrackFinder procedure ------                               *
-// *                                                                                                *
-// **************************************************************************************************
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void L1Algo::ReadWindowData()
-{
-  int nHits = 0;
-  for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
-    fStationHitsStartIndex[iS] = nHits;
-    fStationNhits[iS]          = fSliceHitIds[iS].size();
-    nHits += fStationNhits[iS];
-  }
-  fStationHitsStartIndex[fParameters.GetNstationsActive()] = nHits;
-
-  fWindowHits.reset(nHits);
-  fIsWindowHitSuppressed.reset(nHits, 0);
-
-  for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
-    for (ca::HitIndex_t ih = 0; ih < fSliceHitIds[iS].size(); ++ih) {
-      ca::Hit h = fInputData.GetHit(fSliceHitIds[iS][ih]);
-      h.SetId(fSliceHitIds[iS][ih]);
-
-      fWindowHits[fStationHitsStartIndex[iS] + ih] = h;
-    }
-  }
-
-  fHitFirstTriplet.reset(nHits, 0);
-  fHitNtriplets.reset(nHits, 0);
-
-  // TODO: SG: reduce the array size to the number of keys in subslice
-
-  fStripToTrack.reset(fInputData.GetNhitKeys(), -1);
-
-  fSliceRecoTracks.clear();
-  fSliceRecoTracks.reserve(2 * nHits / fParameters.GetNstationsActive());
-
-  fSliceRecoHits.clear();
-  fSliceRecoHits.reserve(2 * nHits);
-
-  fTrackCandidates.clear();
-  fTrackCandidates.reserve(nHits / 10);
-  for (unsigned int iS = 0; iS < constants::size::MaxNstations; iS++) {
-    int nHitsStation = fSliceHitIds[iS].size();
-    fTriplets[iS].clear();
-    fTriplets[iS].reserve(2 * nHitsStation);
-  }
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void L1Algo::CaTrackFinderSlice()
-{
-  fNFindIterations = fParameters.GetNcaIterations();
-
-  /*******************************/ /**
-   * Performance monitors setting
-   **********************************/
-
-#ifdef PULLS
-  static L1AlgoPulls* l1Pulls_ = new L1AlgoPulls();
-  fL1Pulls                     = l1Pulls_;
-  fL1Pulls->Init();
-#endif
-#ifdef TRIP_PERFORMANCE
-  static L1AlgoEfficiencyPerformance<3>* l1Eff_triplets_ = new L1AlgoEfficiencyPerformance<3>();
-  fL1Eff_triplets                                        = l1Eff_triplets_;
-  fL1Eff_triplets->Init();
-  static L1AlgoEfficiencyPerformance<3>* l1Eff_triplets2_ = new L1AlgoEfficiencyPerformance<3>();
-  fL1Eff_triplets2                                        = l1Eff_triplets2_;
-  fL1Eff_triplets2->Init();
-#endif
-#ifdef DOUB_PERFORMANCE
-  static L1AlgoEfficiencyPerformance<2>* l1Eff_doublets_ = new L1AlgoEfficiencyPerformance<2>();
-  fL1Eff_doublets                                        = l1Eff_doublets_;
-  fL1Eff_doublets->Init();
-#endif
-
-#ifdef DRAW
-  if (!draw) draw = new L1AlgoDraw;
-  draw->InitL1Draw(this);
-#endif
-
-
-#if defined(COUNTERS)
-  static unsigned int stat_N = 0;  // number of events
-  stat_N++;
-
-  static Tindex stat_nStartHits              = 0;
-  static Tindex stat_nHits[fNFindIterations] = {0};
-
-  static Tindex stat_nSinglets[fNFindIterations] = {0};
-  //  static Tindex stat_nDoublets[fNFindIterations] = {0};
-  static Tindex stat_nTriplets[fNFindIterations] = {0};
-
-  static Tindex stat_nLevels[constants::size::MaxNstations - 2][fNFindIterations] = {{0}};
-  static Tindex stat_nCalls[fNFindIterations]                                     = {0};  // n calls of CAFindTrack
-  static Tindex stat_nTrCandidates[fNFindIterations]                              = {0};
-
-  for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
-    stat_nStartHits += fSliceHitIds[iS].size();
-  }
-#endif
-
-  /********************************/ /**
-   * CATrackFinder routine setting
-   ***********************************/
-
-  ReadWindowData();
-
-  for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
-
-    bool timeUninitialised = 1;
-    fscal lasttime         = 0;
-    fscal starttime        = 0;
-
-
-    fscal gridMinX = -0.1;
-    fscal gridMaxX = 0.1;
-    fscal gridMinY = -0.1;
-    fscal gridMaxY = 0.1;
-
-    for (ca::HitIndex_t ih = 0; ih < fSliceHitIds[iS].size(); ++ih) {
-      const ca::Hit& h = fInputData.GetHit(fSliceHitIds[iS][ih]);
-
-      if (h.X() < gridMinX) { gridMinX = h.X(); }
-      if (h.X() > gridMaxX) { gridMaxX = h.X(); }
-      if (h.Y() < gridMinY) { gridMinY = h.Y(); }
-      if (h.Y() > gridMaxY) { gridMaxY = h.Y(); }
-
-      const fscal time = h.T();
-      assert(std::isfinite(time));
-      if (timeUninitialised || lasttime < time) { lasttime = time; }
-      if (timeUninitialised || starttime > time) { starttime = time; }
-      timeUninitialised = false;
-    }
-
-    // TODO: changing the grid also changes the result. Investigate why it happens.
-    // TODO: find the optimal grid size
-
-    int nSliceHits = fSliceHitIds[iS].size();
-    fscal sizeY    = gridMaxY - gridMinY;
-    fscal sizeX    = gridMaxX - gridMinX;
-    int nBins2D    = 1 + nSliceHits;
-    fscal yStep    = sizeY / sqrt(nBins2D);
-    fscal xStep    = sizeX / sqrt(nBins2D);
-
-    fscal scale = fParameters.GetStation(iS).GetZScal() - fParameters.GetTargetPositionZ()[0];
-
-    if (yStep > 0.3 * scale) yStep = 0.3 * scale;
-    if (yStep < 0.01 * scale) yStep = 0.01 * scale;
-    if (xStep > 0.3 * scale) xStep = 0.3 * scale;
-    if (xStep < 0.01 * scale) xStep = 0.01 * scale;
-
-    vGrid[iS].BuildBins(gridMinX, gridMaxX, gridMinY, gridMaxY, xStep, yStep);
-    vGrid[iS].StoreHits(fWindowHits, fStationHitsStartIndex[iS], fStationNhits[iS], fvHitKeyFlags);
-  }
-
-
-  // ---- Loop over Track Finder iterations ----------------------------------------------------------------//
-
-
-  assert(fNFindIterations == (int) fParameters.GetCAIterations().size());
-
-  for (fCurrentIterationIndex = 0; fCurrentIterationIndex < fParameters.GetCAIterations().size();
-       ++fCurrentIterationIndex) {
-
-    // current iteration of the CA tracker
-    const auto& caIteration = fParameters.GetCAIterations()[fCurrentIterationIndex];
-    fpCurrentIteration      = &caIteration;
-
-    if (fCurrentIterationIndex > 0) {
-      for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
-        vGrid[ista].RemoveUsedHits(fWindowHits, fvHitKeyFlags);
-      }
-    }
-
-    fIsWindowHitSuppressed.reset(fWindowHits.size(), 0);
-
-    for (int j = 0; j < fParameters.GetNstationsActive(); j++) {
-      fTriplets[j].clear();
-    }
-
-#ifdef COUNTERS
-    Tindex nSinglets = 0;
-#endif
-
-    fHitFirstTriplet.reset(fWindowHits.size(), 0);
-    fHitNtriplets.reset(fWindowHits.size(), 0);
-
-    {
-      // #pragma omp  task
-      {
-        // --- SET PARAMETERS FOR THE ITERATION ---
-
-        fFirstCAstation      = caIteration.GetFirstStationIndex();
-        fTrackChi2Cut        = caIteration.GetTrackChi2Cut();
-        fDoubletChi2Cut      = caIteration.GetDoubletChi2Cut();  //11.3449 * 2.f / 3.f;  // prob = 0.1
-        fTripletChi2Cut      = caIteration.GetTripletChi2Cut();  //21.1075;  // prob = 0.01%
-        fTripletFinalChi2Cut = caIteration.GetTripletFinalChi2Cut();
-        fPickGather          = caIteration.GetPickGather();       //3.0;
-        fTripletLinkChi2     = caIteration.GetTripletLinkChi2();  //5.0;
-        fMaxInvMom           = caIteration.GetMaxQp();            //1.0 / 0.5;  // max considered q/p
-        fMaxSlopePV          = caIteration.GetMaxSlopePV();       //1.1;
-        fMaxSlope            = caIteration.GetMaxSlope();         //2.748;  // corresponds to 70 grad
-
-        // define the target
-        fTargX = fParameters.GetTargetPositionX();
-        fTargY = fParameters.GetTargetPositionY();
-        fTargZ = fParameters.GetTargetPositionZ();
-
-        fscal SigmaTargetX = caIteration.GetTargetPosSigmaX();
-        fscal SigmaTargetY = caIteration.GetTargetPosSigmaY();  // target constraint [cm]
-
-        // Select magnetic field. For primary tracks - fVtxFieldValue, for secondary tracks - st.fieldSlice
-        if (caIteration.GetPrimaryFlag()) { fTargB = fParameters.GetVertexFieldValue(); }
-        else {
-          fTargB = fParameters.GetStation(0).fieldSlice.GetFieldValue(0, 0);
-        }  // NOTE: calculates field fTargB in the center of 0th station
-
-        fIsTargetField = (fabs(fTargB.y[0]) > 0.001);
-
-        TargetMeasurement.SetX(fTargX);
-        TargetMeasurement.SetY(fTargY);
-        TargetMeasurement.SetDx2(SigmaTargetX * SigmaTargetX);
-        TargetMeasurement.SetDxy(0);
-        TargetMeasurement.SetDy2(SigmaTargetY * SigmaTargetY);
-        TargetMeasurement.SetNdfX(1);
-        TargetMeasurement.SetNdfY(1);
-
-        /// Set correction in order to take into account overlaping and iff z.
-        /// The reason is that low momentum tracks are too curved and goes not from target direction. That's why sort by hit_y/hit_z is not work idealy
-        /// If sort by y then it is max diff between same station's modules (~0.4cm)
-        fMaxDZ = caIteration.GetMaxDZ();  //0;
-      }
-    }
-
-
-    ///   stage for triplets creation
-    fMonitor.StartTimer(ETimer::TripletConstruction);
-    L1TripletConstructor constructor1(this);
-    L1TripletConstructor constructor2(this);
-    L1TripletConstructor constructor3(this);
-
-    for (int istal = fParameters.GetNstationsActive() - 2; istal >= fFirstCAstation;
-         istal--) {  // start with downstream chambers
-      Tindex nGridEntriesL = vGrid[istal].GetEntries().size();
-
-      for (Tindex iel = 0; iel < nGridEntriesL; ++iel) {
-        ca::HitIndex_t ihitl = vGrid[istal].GetEntries()[iel].GetObjectId();
-        constructor1.CreateTripletsForHit(istal, istal + 1, istal + 2, ihitl);
-
-        if (fpCurrentIteration->GetJumpedFlag()) {
-          constructor2.CreateTripletsForHit(istal, istal + 1, istal + 3, ihitl);
-          constructor3.CreateTripletsForHit(istal, istal + 2, istal + 3, ihitl);
-        }
-
-        auto oldSize = fTriplets[istal].size();
-
-        fTriplets[istal].insert(fTriplets[istal].end(), constructor1.GetTriplets().begin(),
-                                constructor1.GetTriplets().end());
-        fTriplets[istal].insert(fTriplets[istal].end(), constructor2.GetTriplets().begin(),
-                                constructor2.GetTriplets().end());
-        fTriplets[istal].insert(fTriplets[istal].end(), constructor3.GetTriplets().begin(),
-                                constructor3.GetTriplets().end());
-
-        fHitFirstTriplet[ihitl] = PackTripletId(istal, oldSize);
-        fHitNtriplets[ihitl]    = fTriplets[istal].size() - oldSize;
-      }
-      fMonitor.IncrementCounter(ECounter::Triplet, fTriplets[istal].size());
-    }  // istal
-    fMonitor.StopTimer(ETimer::TripletConstruction);
-
-    // search for neighbouring triplets
-    fMonitor.StartTimer(ETimer::NeighboringTripletSearch);
-    for (int istal = fParameters.GetNstationsActive() - 2; istal >= fFirstCAstation;
-         istal--) {  // start with downstream chambers
-
-      for (unsigned int it = 0; it < fTriplets[istal].size(); ++it) {
-
-        ca::Triplet& tr = fTriplets[istal][it];
-        tr.SetLevel(0);
-        tr.SetFNeighbour(0);
-        tr.SetNNeighbours(0);
-
-        if (istal > (fParameters.GetNstationsActive() - 4)) break;
-
-        unsigned int nNeighbours = fHitNtriplets[tr.GetMHit()];
-
-        unsigned int neighLocation = fHitFirstTriplet[tr.GetMHit()];
-        unsigned int neighStation  = TripletId2Station(neighLocation);
-        unsigned int neighTriplet  = TripletId2Triplet(neighLocation);
-
-        if (nNeighbours > 0) { assert((int) neighStation == istal + 1 || (int) neighStation == istal + 2); }
-
-        unsigned char level = 0;
-
-        for (unsigned int iN = 0; iN < nNeighbours; ++iN, ++neighTriplet, ++neighLocation) {
-
-          ca::Triplet& neighbour = fTriplets[neighStation][neighTriplet];
-
-          fscal dchi2 = 0.;
-          if (!checkTripletMatch(tr, neighbour, dchi2)) continue;
-
-          if (tr.GetFNeighbour() == 0) { tr.SetFNeighbour(neighLocation); }
-
-          tr.SetNNeighbours(neighLocation - tr.GetFNeighbour() + 1);
-
-          const unsigned char neighbourLevel = neighbour.GetLevel();
-
-          if (level <= neighbourLevel) { level = neighbourLevel + 1; }
-        }
-        tr.SetLevel(level);
-      }  // neighbour search
-    }    // istal
-    fMonitor.StopTimer(ETimer::NeighboringTripletSearch);
-
-    ///====================================================================
-    ///=                                                                  =
-    ///=        Collect track candidates. CREATE TRACKS                   =
-    ///=                                                                  =
-    ///====================================================================
-
-    // min level to start triplet. So min track length = min_level+3.
-    int min_level = std::min(caIteration.GetMinNhits(), caIteration.GetMinNhitsStation0()) - 3;
-
-    // TODO: SZh 04.10.2022: Why this fatal error is called?
-    // NOTE: This line was wrapped into TRACKS_FROM_TRIPLETS ifdef
-    //LOG(FATAL) << "L1CATrackFinder: min_level undefined in " << __FILE__ << " : " << __LINE__;
-    if (fpCurrentIteration->GetTrackFromTripletsFlag()) { min_level = 0; }
-
-    ca::Branch curr_tr;
-    ca::Branch new_tr[constants::size::MaxNstations];
-    ca::Branch best_tr;
-
-    int ndf = 1;
-
-
-    // collect consequtive: the longest tracks, shorter, more shorter and so on
-    for (int firstTripletLevel = fParameters.GetNstationsActive() - 3; firstTripletLevel >= min_level;
-         firstTripletLevel--) {
-      // choose length in triplets number - firstTripletLevel - the maximum possible triplet level among all triplets in the searched candidate
-
-      //  how many levels to check
-      int nlevel = (fParameters.GetNstationsActive() - 2) - firstTripletLevel + 1;
-
-      const unsigned char min_best_l =
-        (firstTripletLevel > min_level) ? firstTripletLevel + 2 : min_level + 3;  // loose maximum
-
-
-      fTrackCandidates.clear();
-
-      fStripToTrack.reset(fInputData.GetNhitKeys(), -1);
-
-      //== Loop over triplets with the required level, find and store track candidates
-
-      for (int istaF = fFirstCAstation; istaF <= fParameters.GetNstationsActive() - 3 - firstTripletLevel; ++istaF) {
-
-        if (--nlevel == 0) break;  //TODO: SG: this is not needed
-
-        for (Tindex itrip = 0; itrip < (Tindex) fTriplets[istaF].size(); ++itrip) {
-
-          ca::Triplet& first_trip = (fTriplets[istaF][itrip]);
-          if (fvHitKeyFlags[fWindowHits[first_trip.GetLHit()].FrontKey()]
-              || fvHitKeyFlags[fWindowHits[first_trip.GetLHit()].BackKey()]) {
-            continue;
-          }
-          //               ghost suppression !!!
-          //
-
-          if (!fpCurrentIteration->GetTrackFromTripletsFlag()) {  // ghost suppression !!!
-            int nHits = 3 + first_trip.GetLevel();
-            if (fWindowHits[first_trip.GetLHit()].Station() == 0) {
-              if (nHits < fpCurrentIteration->GetMinNhitsStation0()) { continue; }
-            }
-            else {
-              if (nHits < fpCurrentIteration->GetMinNhits()) { continue; }
-            }
-          }
-
-          // Collect triplets, which can start a track with length equal to firstTipletLevel + 3. This cut suppresses
-          // ghost tracks, but does not affect the efficiency
-          if (first_trip.GetLevel() < firstTripletLevel) { continue; }
-
-          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;
-
-          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_tr.NofHits() < firstTripletLevel + 2) continue;  // loose maximum one hit
-
-          if (best_tr.NofHits() < min_level + 3) continue;  // should find all hits for min_level
-
-          ndf = best_tr.NofHits() * 2 - 5;
-
-          // TODO: automatize the NDF calculation
-
-          if (kGlobal == fTrackingMode || kMcbm == fTrackingMode) { ndf = best_tr.NofHits() * 2 - 4; }
-
-          best_tr.SetChi2(best_tr.Chi2() / ndf);
-          if (fGhostSuppression) {
-            if (3 == best_tr.NofHits()) {
-              if (!fpCurrentIteration->GetPrimaryFlag() && (istaF != 0)) continue;  // too /*short*/ non-MAPS track
-              if (fpCurrentIteration->GetPrimaryFlag() && (best_tr.Chi2() > 5.0)) continue;
-            }
-          }
-          fTrackCandidates.push_back(best_tr);
-          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 = " << best_tr.NofHits()
-                 << " chi2= " << best_tr.Chi2() << endl;
-            cout << " hits: ";
-            for (auto hitId : tr.Hits()) {
-              cout << GetMcTrackIdForCaHit(hitId) << " ";
-            }
-            cout << endl;
-          }
-        }  // itrip
-      }    // istaF
-
-      for (ca::Branch& tr : fTrackCandidates) {
-        tr.SetAlive(false);
-      }
-
-      bool repeatCompetition = true;
-      int iComp              = 0;
-      for (iComp = 0; (iComp < 100) && repeatCompetition; ++iComp) {
-
-        // == Loop over track candidates and mark their strips
-
-        repeatCompetition = false;
-
-        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.Id())) {  // strip is used by other candidate
-                const auto& other = fTrackCandidates[stripF];
-                if (!other.IsAlive() && tr.IsBetterThan(other)) { stripF = tr.Id(); }
-                else {
-                  isAlive = false;
-                }
-              }
-              else {
-                stripF = tr.Id();
-              }
-              if (!isAlive) { break; }
-            }
-
-            {  // back strip
-              auto& stripB = (fStripToTrack)[h.BackKey()];
-              if ((stripB >= 0) && (stripB != tr.Id())) {  // strip is used by other candidate
-                const auto& other = fTrackCandidates[stripB];
-                if (!other.IsAlive() && tr.IsBetterThan(other)) { stripB = tr.Id(); }
-                else {
-                  isAlive = false;
-                }
-              }
-              else {
-                stripB = tr.Id();
-              }
-              if (!isAlive) { break; }
-            }
-          }  // loop over hits
-        }    // itrack
-
-        // == Check if some suppressed candidates are still alive
-
-        for (ca::Branch& tr : fTrackCandidates) {
-          if (tr.IsAlive()) { continue; }
-
-          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.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 {
-            repeatCompetition = true;
-          }
-        }  // itrack
-
-      }  // competitions
-
-      // cout << " N Competitions: " << iComp << endl;
-
-      // ==
-
-      for (Tindex iCandidate = 0; iCandidate < (Tindex) fTrackCandidates.size(); ++iCandidate) {
-        ca::Branch& tr = fTrackCandidates[iCandidate];
-        if (!tr.IsAlive()) continue;
-        if (kMcbm == fTrackingMode) {
-          if (tr.NofHits() <= 3) { continue; }
-        }
-        else if (kGlobal == fTrackingMode) {
-          if (tr.NofHits() < 3) { continue; }
-        }
-        else {
-          if (tr.NofHits() < 3) { continue; }
-        }
-        if (fpCurrentIteration->GetExtendTracksFlag()) {
-          if (tr.NofHits() < fParameters.GetNstationsActive()) { BranchExtender(tr); }
-        }
-
-        for (auto iHit : tr.Hits()) {
-          const ca::Hit& hit = fInputData.GetHit(iHit);
-
-          /// used strips are marked
-
-          fvHitKeyFlags[hit.FrontKey()] = 1;
-          fvHitKeyFlags[hit.BackKey()]  = 1;
-
-          fSliceRecoHits.push_back(iHit);
-        }
-        Track t;
-        t.fNofHits = tr.NofHits();
-        fSliceRecoTracks.push_back(t);
-        if (0) {  // SG debug
-          cout << "store track " << iCandidate << " chi2= " << tr.Chi2() << endl;
-          cout << " hits: ";
-          for (unsigned int ih = 0; ih < tr.Hits().size(); ih++) {
-            cout << GetMcTrackIdForCaHit(tr.Hits()[ih]) << " ";
-          }
-          cout << '\n';
-        }
-
-      }  // tracks
-
-    }  // firstTripletLevel
-
-
-    // suppress strips of suppressed hits
-    for (unsigned int ih = 0; ih < fWindowHits.size(); ih++) {
-      if (fIsWindowHitSuppressed[ih]) {
-        const ca::Hit& hit            = fWindowHits[ih];
-        fvHitKeyFlags[hit.FrontKey()] = 1;
-        fvHitKeyFlags[hit.BackKey()]  = 1;
-      }
-    }
-
-    {
-      // #ifdef DRAW
-      //     draw->ClearVeiw();
-      // //   draw->DrawInfo();
-      //     draw->DrawRestHits(fGridHitStartIndex, fGridHitStopIndex, RealIHit);
-      //     draw->DrawRecoTracks();
-      //     draw->SaveCanvas("Reco_"+iCaIteration+"_");
-      //     draw->DrawAsk();
-      // #endif
-
-      // #ifdef PULLS
-      //       fL1Pulls->Build(1);
-      // #endif
-#ifdef COUNTERS
-      //  stat_nHits[iCaIteration] += (fGridHits*)->Size();
-      cout << "iter = " << iCaIteration << endl;
-      cout << " NSinglets = " << stat_nSinglets[iCaIteration] / stat_N << endl;
-      //    cout << " NDoublets = " << stat_nDoublets[iCaIteration]/stat_N << endl;
-      cout << " NTriplets = " << stat_nTriplets[iCaIteration] / stat_N << endl;
-      cout << " NfGridHit = " << stat_nHits[iCaIteration] / stat_N << endl;
-#endif  // COUNTERS
-    }
-
-  }  // ---- Loop over Track Finder iterations: END -----------------------------------------------------------//
-
-  // Fit tracks
-  this->L1KFTrackFitter();
-
-  // Merge clones
-  fCloneMerger.Exec(fSliceRecoTracks, fSliceRecoHits);
-
-  //==================================
-
-#ifdef DRAW
-  draw->ClearVeiw();
-  //   draw->DrawInputHits();
-  //   draw->DrawInfo();
-  draw->DrawRecoTracks();
-
-  draw->SaveCanvas("Reco_");
-  draw->DrawAsk();
-#endif
-#ifdef PULLS
-  static int iEvee = 0;
-  iEvee++;
-  if (iEvee % 1 == 0) fL1Pulls->Build(1);
-#endif
-#ifdef DOUB_PERFORMANCE
-  fL1Eff_doublets->CalculateEff();
-  fL1Eff_doublets->Print("Doublets performance.", 1);
-#endif
-#ifdef TRIP_PERFORMANCE
-  fL1Eff_triplets->CalculateEff();
-  fL1Eff_triplets->Print("Triplet performance", 1);
-//   fL1Eff_triplets2->CalculateEff();
-//   fL1Eff_triplets2->Print("Triplet performance. After chi2 cut");
-#endif
-}
-
-
-// ---------------------------------------------------------------------------------------------------------------------
-//  ****************************************************************
-//  *                                                              *
-//  *     The routine performs recursive search for tracks         *
-//  *                                                              *
-//  *     I. Kisel                                    06.03.05     *
-//  *     I.Kulakov                                    2012        *
-//  *                                                              *
-//  ****************************************************************
-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
-/// output: @&NCalls - number of function calls
-{
-
-  if (curr_trip->GetLevel() == 0)  // the end of the track -> check and store
-  {
-    // -- finish with current track
-    // add rest of hits
-    const ca::HitIndex_t& ihitm = curr_trip->GetMHit();
-    const ca::HitIndex_t& ihitr = curr_trip->GetRHit();
-
-
-    //if (!GetFUsed((*fStripFlag)[fGridHits[ihitm].f] | (*fStripFlag)[fGridHits[ihitm].b])) {
-    //L1_SHOW(fInputData.GetNhitKeys());
-    //L1_SHOW(fvHitKeyFlags.size());
-    //L1_SHOW(fGridHits[ihitm].f);
-    //L1_SHOW(fGridHits[ihitm].b);
-    if (!(fvHitKeyFlags[fWindowHits[ihitm].FrontKey()] || fvHitKeyFlags[fWindowHits[ihitm].BackKey()])) {
-
-      //        curr_tr.Hits.push_back(fGridHitIds[ihitm]);
-
-      curr_tr.AddHit(fWindowHits[ihitm].Id());
-    }
-
-    //if (!GetFUsed((*fStripFlag)[fGridHits[ihitr].f] | (*fStripFlag)[fGridHits[ihitr].b])) {
-    //L1_SHOW(fInputData.GetNhitKeys());
-    //L1_SHOW(fvHitKeyFlags.size());
-    //L1_SHOW(fGridHits[ihitr].f);
-    //L1_SHOW(fGridHits[ihitr].b);
-    if (!(fvHitKeyFlags[fWindowHits[ihitr].FrontKey()] || fvHitKeyFlags[fWindowHits[ihitr].BackKey()])) {
-
-      //curr_tr.Hits.push_back(fGridHitIds[ihitr]);
-      curr_tr.AddHit(fWindowHits[ihitr].Id());
-    }
-
-    //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_tr.NofHits() * 2 - 5;
-
-    if (kGlobal == fTrackingMode || kMcbm == fTrackingMode) { ndf = curr_tr.NofHits() * 2 - 4; }
-
-    if (curr_tr.Chi2() > fTrackChi2Cut * ndf) { return; }
-
-
-    // -- select the best
-    if ((curr_tr.NofHits() > best_tr.NofHits())
-        || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
-      best_tr = curr_tr;
-    }
-
-    return;
-  }
-  else  //MEANS level ! = 0
-  {
-    int N_neighbour = (curr_trip->GetNNeighbours());
-
-    for (Tindex in = 0; in < N_neighbour; in++) {
-
-      unsigned int ID = curr_trip->GetFNeighbour() + in;
-
-      unsigned int Station = TripletId2Station(ID);
-      unsigned int Triplet = TripletId2Triplet(ID);
-
-      const ca::Triplet& new_trip = fTriplets[Station][Triplet];
-
-      fscal dchi2 = 0.;
-      if (!checkTripletMatch(*curr_trip, new_trip, dchi2)) continue;
-
-      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_tr.NofHits() > best_tr.NofHits())
-            || ((curr_tr.NofHits() == best_tr.NofHits()) && (curr_tr.Chi2() < best_tr.Chi2()))) {
-          best_tr = curr_tr;
-        }
-      }
-      else {  // hit is not used: add the left hit from the new triplet to the current track
-
-        unsigned char new_L = curr_tr.NofHits() + 1;
-        fscal new_chi2      = curr_tr.Chi2() + dchi2;
-
-
-        if (0) {  //SGtrd2d debug!!
-          int mc01 = GetMcTrackIdForWindowHit(curr_trip->GetLHit());
-          int mc02 = GetMcTrackIdForWindowHit(curr_trip->GetMHit());
-          int mc03 = GetMcTrackIdForWindowHit(curr_trip->GetRHit());
-          int mc11 = GetMcTrackIdForWindowHit(new_trip.GetLHit());
-          int mc12 = GetMcTrackIdForWindowHit(new_trip.GetMHit());
-          int mc13 = GetMcTrackIdForWindowHit(new_trip.GetRHit());
-          if ((mc01 == mc02) && (mc02 == mc03)) {
-            cout << " sta " << ista << " mc0 " << mc01 << " " << mc02 << " " << mc03 << " mc1 " << mc11 << " " << mc12
-                 << " " << 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;
-          }
-        }
-
-        int ndf = 2 * (new_L + 2) - 5;
-
-        if (kGlobal == fTrackingMode) {  //SGtrd2d!!!
-          ndf = 2 * (new_L + 2) - 4;
-        }
-        else if (kMcbm == fTrackingMode) {
-          ndf = 2 * (new_L + 2) - 4;
-        }
-        else {
-          ndf = new_L;  // TODO: SG:  2 * (new_L + 2) - 5
-        }
-
-        if (new_chi2 > fTrackChi2Cut * ndf) continue;
-
-        // add new hit
-        new_tr[ista] = curr_tr;
-        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, &new_trip, new_tr[ista], min_best_l, new_tr);
-      }  // add triplet to track
-    }    // for neighbours
-  }      // level = 0
-}
diff --git a/reco/L1/L1Algo/L1CloneMerger.h b/reco/L1/L1Algo/L1CloneMerger.h
deleted file mode 100644
index d115dac8c5..0000000000
--- a/reco/L1/L1Algo/L1CloneMerger.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Sergei Zharko [committer], Maksym Zyzak */
-
-/// \file    L1CloneMerger.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 L1CloneMerger_h
-#define L1CloneMerger_h 1
-
-#include "CaHit.h"   // For ca::HitIndex_t
-#include "CaSimd.h"  // TEMPORARY FOR fvec, fscal
-#include "CaVector.h"
-
-
-using namespace cbm::algo::ca;  //TODO: remove
-using namespace cbm::algo;      //TODO: remove
-
-namespace cbm::algo::ca
-{
-  class Track;
-}
-
-class L1Algo;
-
-namespace
-{  // TMP
-  using cbm::algo::ca::Track;
-  using cbm::algo::ca::Vector;
-}  // namespace
-
-/// Class implements a clones merger algorithm for the CA (L1) track finder
-///
-class L1CloneMerger {
-public:
-  /// Default constructor
-  L1CloneMerger(const L1Algo& algo);
-
-  /// Destructor
-  ~L1CloneMerger();
-
-  /// Copy constructor
-  L1CloneMerger(const L1CloneMerger&) = delete;
-
-  /// Move constructor
-  L1CloneMerger(L1CloneMerger&&) = delete;
-
-  /// Copy assignment operator
-  L1CloneMerger& operator=(const L1CloneMerger&) = delete;
-
-  /// Move assignment operator
-  L1CloneMerger& operator=(L1CloneMerger&&) = 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(Vector<Track>& extTracks, Vector<ca::HitIndex_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
-  Vector<unsigned short> fTrackFirstStation {"L1CloneMerger::fTrackFirstStation"};
-
-  /// Last station of a track
-  Vector<unsigned short> fTrackLastStation {"L1CloneMerger::fTrackLastStation"};
-
-  /// Index of the first hit of a track
-  Vector<ca::HitIndex_t> fTrackFirstHit {"L1CloneMerger::fTrackFirstHit"};
-
-  /// Index of the last hit of a track
-  Vector<ca::HitIndex_t> fTrackLastHit {"L1CloneMerger::fTrackLastHit"};
-
-  /// Index (TODO:??) of a track that can be merge with the given track
-  Vector<unsigned short> fTrackNeighbour {"L1CloneMerger::fTrackNeighbour"};
-
-  /// Chi2 value of the track merging procedure
-  Vector<float> fTrackChi2 {"L1CloneMerger::fTrackChi2"};
-
-  /// Flag: is the given track already stored to the output
-  Vector<char> fTrackIsStored {"L1CloneMerger::fTrackIsStored"};
-
-  /// Flag: is the track a downstream neighbour of another track
-  Vector<char> fTrackIsDownstreamNeighbour {"L1CloneMerger::fTrackIsDownstreamNeighbour"};
-
-  Vector<Track> fTracksNew {"L1CAMergerClones::fTracksNew"};  ///< vector of tracks after the merge
-
-  Vector<ca::HitIndex_t> fRecoHitsNew {"L1CAMergerClones::fRecoHitsNew"};  ///< vector of track hits after the merge
-
-  const L1Algo& frAlgo;  ///< Reference to the main track finder algorithm class
-};
-
-#endif  // L1CloneMerger_h
diff --git a/reco/L1/L1Algo/L1TripletConstructor.h b/reco/L1/L1Algo/L1TripletConstructor.h
deleted file mode 100644
index 89187ad476..0000000000
--- a/reco/L1/L1Algo/L1TripletConstructor.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
-   SPDX-License-Identifier: GPL-3.0-only
-   Authors: Sergey Gorbunov [committer] */
-
-#ifndef L1TripletConstructor_h
-#define L1TripletConstructor_h
-
-#include "CaField.h"
-#include "CaGridEntry.h"
-#include "CaStation.h"
-#include "CaTrackFit.h"
-#include "CaTrackParam.h"
-#include "CaTriplet.h"
-#include "CaVector.h"
-#include "L1Algo.h"
-
-namespace
-{  // TMP!!
-  using cbm::algo::ca::Vector;
-}
-
-
-/// Construction of triplets for the CA tracker
-///
-class L1TripletConstructor {
-public:
-  ///                             ------  Constructors and destructor ------
-
-  /// Constructor
-  /// \param nThreads  Number of threads for multi-threaded mode
-  L1TripletConstructor(L1Algo* algo);
-
-  /// Copy constructor
-  L1TripletConstructor(const L1TripletConstructor&) = delete;
-
-  /// Move constructor
-  L1TripletConstructor(L1TripletConstructor&&) = delete;
-
-  /// Copy assignment operator
-  L1TripletConstructor& operator=(const L1TripletConstructor&) = delete;
-
-  /// Move assignment operator
-  L1TripletConstructor& operator=(L1TripletConstructor&&) = delete;
-
-  /// Destructor
-  ~L1TripletConstructor() = default;
-
-
-  ///                             ------  FUNCTIONAL PART ------
-
-  void InitStations(int istal, int istam, int istar);
-
-  void CreateTripletsForHit(int istal, int istam, int istar, ca::HitIndex_t ihl);
-
-  const Vector<ca::Triplet>& GetTriplets() const { return fTriplets; }
-
-  /// Find the doublets. Reformat data in the portion of doublets.
-  void FindDoublets();
-  void FitDoublets();
-
-  /// Find triplets on station
-  void FindTriplets();
-
-  /// Add the middle hits to parameters estimation. Propagate to right station.
-  /// Find the triplets (right hit). Reformat data in the portion of triplets.
-  void FindRightHit();
-
-  /// Fit Triplets
-  void FitTriplets();
-
-  /// Select triplets. Save them into vTriplets.
-  void StoreTriplets();
-
-  void CollectHits(const TrackParamV& Tr, const int iSta, const double chi2Cut, const int iMC,
-                   Vector<ca::HitIndex_t>& collectedHits, int maxNhits);
-
-private:
-  /// left station
-  const ca::Station& staL() { return *fStaL; }
-  /// middle station
-  const ca::Station& staM() { return *fStaM; }
-  /// right station
-  const ca::Station& staR() { return *fStaR; }
-
-private:
-  bool fIsInitialized {false};  ///< is initialized;
-  L1Algo* fAlgo {nullptr};      ///< pointer to L1Algo object
-
-  int fIstaL {-1};  ///< left station index
-  int fIstaM {-1};  ///< middle station index
-  int fIstaR {-1};  ///< right station index
-
-  const ca::Station* fStaL {nullptr};  ///< left station
-  const ca::Station* fStaM {nullptr};  ///< mid station
-  const ca::Station* fStaR {nullptr};  ///< right station
-
-  const ca::Station* fFld0Sta[2];  // two stations for approximating the field between the target and the left hit
-  const ca::Station* fFld1Sta[3];  // three stations for approximating the field between the left and the right hit
-
-  ca::HitIndex_t fIhitL;  ///< index of the left hit in fAlgo->fWindowHits
-  TrackParamV fTrL;
-  ca::FieldRegion fFldL;
-
-  Vector<ca::HitIndex_t> fHitsM_2 {"L1TripletConstructor::fHitsM_2"};
-  Vector<TrackParamV> fTracks_2 {"L1TripletConstructor::fTracks_2"};
-
-  Vector<TrackParamV> fTracks_3 {"L1TripletConstructor::fTracks_3"};
-  Vector<ca::HitIndex_t> fHitsM_3 {"L1TripletConstructor::fHitsM_3"};
-  Vector<ca::HitIndex_t> fHitsR_3 {"L1TripletConstructor::fHitsR_3"};
-
-  Vector<ca::Triplet> fTriplets {"L1TripletConstructor::fTriplets"};
-
-  ca::TrackFit fFit;
-
-} _fvecalignment;
-
-#endif
diff --git a/reco/L1/L1Algo/utils/L1AlgoDraw.cxx b/reco/L1/L1Algo/utils/L1AlgoDraw.cxx
index b4e6b7850b..aab0a32588 100644
--- a/reco/L1/L1Algo/utils/L1AlgoDraw.cxx
+++ b/reco/L1/L1Algo/utils/L1AlgoDraw.cxx
@@ -22,7 +22,10 @@
 #include "TText.h"
 #include "TView3D.h"
 
-#include "L1Algo.h"
+#include "CaFramework.h"
+#include "CaSimd.h"
+
+using namespace cbm::algo::ca;
 
 // NOTE: using std::cout, std::endl were removed from one of the headers, and it
 //       caused errors. Please, don't use "using" in headers
@@ -71,7 +74,7 @@ L1AlgoDraw::L1AlgoDraw()
   ask      = true;
 }
 
-void L1AlgoDraw::InitL1Draw(L1Algo* algo_)
+void L1AlgoDraw::InitL1Draw(ca::Framework* algo_)
 {
   //   algo = CbmL1::Instance()->algo;
   algo = algo_;
@@ -81,11 +84,11 @@ void L1AlgoDraw::InitL1Draw(L1Algo* algo_)
   for (unsigned int i = 0; i < algo->fWindowHits.size(); i++) {
     vHits.push_back(algo->fWindowHits[i]);
   }
-  NStations = algo->GetParameters()->GetNstationsActive();
+  NStations = algo->GetParameters().GetNstationsActive();
   for (int i = 0; i < NStations; i++) {
     HitsStartIndex[i] = algo->fStationHitsStartIndex[i];
     HitsStopIndex[i]  = algo->fStationHitsStartIndex[i] + algo->fStationNhits[i];
-    vStations[i]      = algo->GetParameters()->GetStation(i);
+    vStations[i]      = algo->GetParameters().GetStation(i);
   }
 }
 
diff --git a/reco/L1/L1Algo/utils/L1AlgoDraw.h b/reco/L1/L1Algo/utils/L1AlgoDraw.h
index dbb0d68b08..39f7f9110e 100644
--- a/reco/L1/L1Algo/utils/L1AlgoDraw.h
+++ b/reco/L1/L1Algo/utils/L1AlgoDraw.h
@@ -20,7 +20,11 @@ namespace
 }
 
 class TCanvas;
-class L1Algo;
+
+namespace cbm::algo::ca
+{
+  class Framework;
+}
 
 class L1AlgoDraw {
   struct Point {
@@ -32,7 +36,7 @@ class L1AlgoDraw {
 public:
   L1AlgoDraw();
 
-  void InitL1Draw(L1Algo* algo_);
+  void InitL1Draw(ca::Framework* algo_);
 
   void DrawMCTracks();
   void DrawRecoTracks();
@@ -63,7 +67,7 @@ private:
   void DrawTriplet(int il, int im, int ir);
   void DrawDoublet(int il, int ir);
 
-  L1Algo* algo {nullptr};
+  ca::Framework* algo {nullptr};
 
   std::vector<ca::Hit> vHits {};
   int HitsStartIndex[20] {0};
diff --git a/reco/L1/L1Algo/utils/L1AlgoEfficiencyPerformance.h b/reco/L1/L1Algo/utils/L1AlgoEfficiencyPerformance.h
index 07656bb9c1..4c6600bde4 100644
--- a/reco/L1/L1Algo/utils/L1AlgoEfficiencyPerformance.h
+++ b/reco/L1/L1Algo/utils/L1AlgoEfficiencyPerformance.h
@@ -14,12 +14,11 @@
 
 #include "CbmL1.h"
 #include "CbmL1Counters.h"
+#include "CbmL1MCTrack.h"
 
 #include <iostream>
 #include <vector>
 
-#include "L1Algo.h"
-
 using std::cout;
 using std::endl;
 using std::vector;
diff --git a/reco/L1/L1Algo/utils/L1AlgoPulls.cxx b/reco/L1/L1Algo/utils/L1AlgoPulls.cxx
index 2f84229276..cf6133e965 100644
--- a/reco/L1/L1Algo/utils/L1AlgoPulls.cxx
+++ b/reco/L1/L1Algo/utils/L1AlgoPulls.cxx
@@ -4,6 +4,8 @@
 
 #include "L1AlgoPulls.h"
 
+using namespace cbm::algo::ca;
+
 const TString L1TrackParametersNames[TL1TrackParameters::NParameters] = {"x", "y", "tx", "ty", "qp"};
 
 void L1AlgoPulls::Init()
diff --git a/reco/L1/L1Algo/utils/L1AlgoPulls.h b/reco/L1/L1Algo/utils/L1AlgoPulls.h
index e82bc5cf25..9ab379840e 100644
--- a/reco/L1/L1Algo/utils/L1AlgoPulls.h
+++ b/reco/L1/L1Algo/utils/L1AlgoPulls.h
@@ -24,7 +24,6 @@ const int NStations = 0;
 #include <vector>
 
 #include "CaTrackParam.h"
-#include "L1Algo.h"
 
 using std::cout;
 using std::endl;
@@ -37,7 +36,7 @@ struct TL1TrackParameters {
 
   TL1TrackParameters() {};
 
-  TL1TrackParameters(TrackParamV& T, int i)
+  TL1TrackParameters(cbm::algo::ca::TrackParamV& T, int i)
     : x(T.GetX()[i])
     , y(T.GetY()[i])
     , tx(T.GetTx()[i])
@@ -90,7 +89,7 @@ public:
   void Init();
 
   //     void AddVec(TrackParamV& T, ca::HitIndex_t ih);
-  void AddOne(TrackParamV& T, int i, ca::HitIndex_t ih);
+  void AddOne(cbm::algo::ca::TrackParamV& T, int i, ca::HitIndex_t ih);
   void Print();  // fast method to see pulls :)
   void Build(bool draw = 1);
 
diff --git a/reco/L1/OffLineInterface/CbmL1GlobalTrackFinder.cxx b/reco/L1/OffLineInterface/CbmL1GlobalTrackFinder.cxx
index efea0e6fcf..de59be1823 100644
--- a/reco/L1/OffLineInterface/CbmL1GlobalTrackFinder.cxx
+++ b/reco/L1/OffLineInterface/CbmL1GlobalTrackFinder.cxx
@@ -39,7 +39,6 @@
 #include <iostream>
 #include <vector>
 
-#include "L1Algo/L1Algo.h"
 
 using std::cout;
 using std::endl;
diff --git a/reco/L1/OffLineInterface/CbmL1StsTrackFinder.cxx b/reco/L1/OffLineInterface/CbmL1StsTrackFinder.cxx
index a0c074d7ae..c24827ea0a 100644
--- a/reco/L1/OffLineInterface/CbmL1StsTrackFinder.cxx
+++ b/reco/L1/OffLineInterface/CbmL1StsTrackFinder.cxx
@@ -34,7 +34,6 @@
 #include <iostream>
 #include <vector>
 
-#include "L1Algo/L1Algo.h"
 
 using std::cout;
 using std::endl;
diff --git a/reco/L1/catools/CaToolsDebugger.cxx b/reco/L1/catools/CaToolsDebugger.cxx
index 9394c4993e..5783a6c29e 100644
--- a/reco/L1/catools/CaToolsDebugger.cxx
+++ b/reco/L1/catools/CaToolsDebugger.cxx
@@ -38,13 +38,13 @@ Debugger& Debugger::Instance()
 Debugger::Debugger(const char* fileName)
 {
   /// Default constructor
-  fFile = new TFile(fileName, "RECREATE");
+  fFileName = fileName;
 }
 
 void Debugger::Write()
 {
   /// Write data to file
-  fIsWritten = true;
+  fIsWritten          = true;
   TDirectory* currDir = gDirectory;
   if (fFile) {
     fFile->cd();
@@ -58,12 +58,14 @@ void Debugger::Write()
 Debugger::~Debugger()
 {
   /// Destructor
-  if (!fIsWritten) { std::cerr << "CaDebugger: you forgot to Write()!!" << std::endl; }
+  if (!fIsWritten && fFile) { std::cerr << "CaDebugger: you forgot to Write()!!" << std::endl; }
 }
 
 void Debugger::AddNtuple(const char* name, const char* varlist)
 {
   /// add ntuple
+
+  if (!fFile) { fFile = new TFile(fFileName.c_str(), "RECREATE"); }
   assert(fFile);
   if (GetNtupleIndex(name) >= 0) return;
   TDirectory* currDir = gDirectory;
diff --git a/reco/L1/catools/CaToolsDebugger.h b/reco/L1/catools/CaToolsDebugger.h
index fc9f2c8c31..8b7698110b 100644
--- a/reco/L1/catools/CaToolsDebugger.h
+++ b/reco/L1/catools/CaToolsDebugger.h
@@ -86,6 +86,7 @@ namespace cbm::ca::tools
     }
 
   private:
+    std::string fFileName {"CAdebug.root"};
     bool fIsWritten {0};
     TFile* fFile {nullptr};
     std::vector<TNtuple*> fNtuples;
-- 
GitLab