diff --git a/algo/ca/TrackingChain.cxx b/algo/ca/TrackingChain.cxx
index cffede81ec2f89f36b88f324108032358e57ce59..73b3d47f008991eedb614585c2ba53d5f50f168a 100644
--- a/algo/ca/TrackingChain.cxx
+++ b/algo/ca/TrackingChain.cxx
@@ -26,8 +26,6 @@
 #include <fmt/format.h>
 #include <xpu/host.h>
 
-using namespace cbm::algo;
-
 using cbm::algo::TrackingChain;
 using cbm::algo::ca::EDetectorID;
 using cbm::algo::ca::Framework;
@@ -41,7 +39,7 @@ using cbm::algo::ca::constants::clrs::GNb;  // grin bald text
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-TrackingChain::TrackingChain(std::shared_ptr<HistogramSender> histoSender) : fQa(Qa(histoSender)) {}
+TrackingChain::TrackingChain(std::shared_ptr<cbm::algo::HistogramSender> histoSender) : fQa(Qa(histoSender)) {}
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
diff --git a/algo/ca/core/data/CaGrid.cxx b/algo/ca/core/data/CaGrid.cxx
index f1e615cfb9af0cb7d0ee3b667331ddab5f904863..f41d2853f3a90c9fda0c6b687f725bd7d0bbfa10 100644
--- a/algo/ca/core/data/CaGrid.cxx
+++ b/algo/ca/core/data/CaGrid.cxx
@@ -14,113 +14,112 @@
 #include <cstring>
 
 
-using namespace cbm::algo::ca;
-using namespace cbm::algo;
-
-
-void Grid::BuildBins(fscal xMin, fscal xMax, fscal yMin, fscal yMax, fscal binWidthX, fscal binWidthY)
+namespace cbm::algo::ca
 {
-  fMinX = std::min(xMin, xMax);
-  fMinY = std::min(yMin, yMax);
+  void Grid::BuildBins(fscal xMin, fscal xMax, fscal yMin, fscal yMax, fscal binWidthX, fscal binWidthY)
+  {
+    fMinX = std::min(xMin, xMax);
+    fMinY = std::min(yMin, yMax);
 
-  xMax = std::max(xMin, xMax);
-  yMax = std::max(yMin, yMax);
+    xMax = std::max(xMin, xMax);
+    yMax = std::max(yMin, yMax);
 
-  fBinWidthX = binWidthX;
-  fBinWidthY = binWidthY;
+    fBinWidthX = binWidthX;
+    fBinWidthY = binWidthY;
 
-  // some sanity checks
-  if (fBinWidthX < 0.001) {
-    fBinWidthX = 0.001;
-  }
-  if (fBinWidthY < 0.001) {
-    fBinWidthY = 0.001;
-  }
+    // some sanity checks
+    if (fBinWidthX < 0.001) {
+      fBinWidthX = 0.001;
+    }
+    if (fBinWidthY < 0.001) {
+      fBinWidthY = 0.001;
+    }
 
-  fBinWidthXinv = 1. / fBinWidthX;
-  fBinWidthYinv = 1. / fBinWidthY;
+    fBinWidthXinv = 1. / fBinWidthX;
+    fBinWidthYinv = 1. / fBinWidthY;
 
-  fNx = static_cast<int>(std::ceil((xMax - fMinX) / fBinWidthX));
-  fNy = static_cast<int>(std::ceil((yMax - fMinY) / fBinWidthY));
+    fNx = static_cast<int>(std::ceil((xMax - fMinX) / fBinWidthX));
+    fNy = static_cast<int>(std::ceil((yMax - fMinY) / fBinWidthY));
 
-  // some sanity checks
-  if (fNx < 1) fNx = 1;
-  if (fNy < 1) fNy = 1;
+    // some sanity checks
+    if (fNx < 1) fNx = 1;
+    if (fNy < 1) fNy = 1;
 
-  fN = fNx * fNy;
+    fN = fNx * fNy;
 
-  fEntries.clear();
-  fFirstBinEntryIndex.reset(fN + 1, 0);
-  fNofBinEntries.reset(fN + 1, 0);
-}
+    fEntries.clear();
+    fFirstBinEntryIndex.reset(fN + 1, 0);
+    fNofBinEntries.reset(fN + 1, 0);
+  }
 
 
-void Grid::StoreHits(const Vector<ca::Hit>& hits, ca::HitIndex_t hitStartIndex, ca::HitIndex_t nHits,
-                     const Vector<unsigned char>& hitKeyFlags)
-{
-  fFirstBinEntryIndex.reset(fN + 1, 0);
-  fNofBinEntries.reset(fN + 1, 0);
-
-  int nEntries = 0;
-  for (ca::HitIndex_t ih = 0; ih < nHits; ih++) {
-    const ca::Hit& hit = hits[hitStartIndex + ih];
-    if (!(hitKeyFlags[hit.FrontKey()] || hitKeyFlags[hit.BackKey()])) {
-      fNofBinEntries[GetBin(hit.X(), hit.Y())]++;
-      nEntries++;
+  void Grid::StoreHits(const Vector<ca::Hit>& hits, ca::HitIndex_t hitStartIndex, ca::HitIndex_t nHits,
+                       const Vector<unsigned char>& hitKeyFlags)
+  {
+    fFirstBinEntryIndex.reset(fN + 1, 0);
+    fNofBinEntries.reset(fN + 1, 0);
+
+    int nEntries = 0;
+    for (ca::HitIndex_t ih = 0; ih < nHits; ih++) {
+      const ca::Hit& hit = hits[hitStartIndex + ih];
+      if (!(hitKeyFlags[hit.FrontKey()] || hitKeyFlags[hit.BackKey()])) {
+        fNofBinEntries[GetBin(hit.X(), hit.Y())]++;
+        nEntries++;
+      }
     }
-  }
 
-  fEntries.reset(nEntries);
+    fEntries.reset(nEntries);
 
-  for (int bin = 0; bin < fN; bin++) {
-    fFirstBinEntryIndex[bin + 1] = fFirstBinEntryIndex[bin] + fNofBinEntries[bin];
-    fNofBinEntries[bin]          = 0;
-  }
-  fNofBinEntries[fN] = 0;
-
-  fMaxRangeX = 0.;
-  fMaxRangeY = 0.;
-  fMaxRangeT = 0.;
-
-  for (ca::HitIndex_t ih = 0; ih < nHits; ih++) {
-    const ca::Hit& hit = hits[hitStartIndex + ih];
-    if (!(hitKeyFlags[hit.FrontKey()] || hitKeyFlags[hit.BackKey()])) {
-      int bin = GetBin(hit.X(), hit.Y());
-      fEntries[fFirstBinEntryIndex[bin] + fNofBinEntries[bin]].Set(hit, hitStartIndex + ih);
-      fNofBinEntries[bin]++;
-      fMaxRangeX = std::max(fMaxRangeX, hit.RangeX());
-      fMaxRangeY = std::max(fMaxRangeY, hit.RangeY());
-      fMaxRangeT = std::max(fMaxRangeT, hit.RangeT());
+    for (int bin = 0; bin < fN; bin++) {
+      fFirstBinEntryIndex[bin + 1] = fFirstBinEntryIndex[bin] + fNofBinEntries[bin];
+      fNofBinEntries[bin]          = 0;
     }
-  }
-}
+    fNofBinEntries[fN] = 0;
 
-void Grid::RemoveUsedHits(const Vector<ca::Hit>& hits, const Vector<unsigned char>& hitKeyFlags)
-{
-  int nEntries = 0;
-  fMaxRangeX   = 0.;
-  fMaxRangeY   = 0.;
-  fMaxRangeT   = 0.;
-
-  for (int bin = 0; bin < fN; bin++) {
-    ca::HitIndex_t firstEntryOld = fFirstBinEntryIndex[bin];
-    fFirstBinEntryIndex[bin]     = nEntries;
-    fNofBinEntries[bin]          = 0;
-    for (ca::HitIndex_t i = firstEntryOld; i < fFirstBinEntryIndex[bin + 1]; i++) {
-      auto entry         = fEntries[i];
-      const ca::Hit& hit = hits[entry.GetObjectId()];
+    fMaxRangeX = 0.;
+    fMaxRangeY = 0.;
+    fMaxRangeT = 0.;
 
+    for (ca::HitIndex_t ih = 0; ih < nHits; ih++) {
+      const ca::Hit& hit = hits[hitStartIndex + ih];
       if (!(hitKeyFlags[hit.FrontKey()] || hitKeyFlags[hit.BackKey()])) {
-        fEntries[nEntries] = entry;
-        nEntries++;
+        int bin = GetBin(hit.X(), hit.Y());
+        fEntries[fFirstBinEntryIndex[bin] + fNofBinEntries[bin]].Set(hit, hitStartIndex + ih);
         fNofBinEntries[bin]++;
-        fMaxRangeX = std::max(fMaxRangeX, entry.RangeX());
-        fMaxRangeY = std::max(fMaxRangeY, entry.RangeY());
-        fMaxRangeT = std::max(fMaxRangeT, entry.RangeT());
+        fMaxRangeX = std::max(fMaxRangeX, hit.RangeX());
+        fMaxRangeY = std::max(fMaxRangeY, hit.RangeY());
+        fMaxRangeT = std::max(fMaxRangeT, hit.RangeT());
+      }
+    }
+  }
+
+  void Grid::RemoveUsedHits(const Vector<ca::Hit>& hits, const Vector<unsigned char>& hitKeyFlags)
+  {
+    int nEntries = 0;
+    fMaxRangeX   = 0.;
+    fMaxRangeY   = 0.;
+    fMaxRangeT   = 0.;
+
+    for (int bin = 0; bin < fN; bin++) {
+      ca::HitIndex_t firstEntryOld = fFirstBinEntryIndex[bin];
+      fFirstBinEntryIndex[bin]     = nEntries;
+      fNofBinEntries[bin]          = 0;
+      for (ca::HitIndex_t i = firstEntryOld; i < fFirstBinEntryIndex[bin + 1]; i++) {
+        auto entry         = fEntries[i];
+        const ca::Hit& hit = hits[entry.GetObjectId()];
+
+        if (!(hitKeyFlags[hit.FrontKey()] || hitKeyFlags[hit.BackKey()])) {
+          fEntries[nEntries] = entry;
+          nEntries++;
+          fNofBinEntries[bin]++;
+          fMaxRangeX = std::max(fMaxRangeX, entry.RangeX());
+          fMaxRangeY = std::max(fMaxRangeY, entry.RangeY());
+          fMaxRangeT = std::max(fMaxRangeT, entry.RangeT());
+        }
       }
     }
+    fFirstBinEntryIndex[fN] = nEntries;
+    fNofBinEntries[fN]      = 0;
+    fEntries.shrink(nEntries);
   }
-  fFirstBinEntryIndex[fN] = nEntries;
-  fNofBinEntries[fN]      = 0;
-  fEntries.shrink(nEntries);
-}
+}  // namespace cbm::algo::ca
\ No newline at end of file
diff --git a/algo/ca/core/pars/CaConfigReader.cxx b/algo/ca/core/pars/CaConfigReader.cxx
index 88dd41f4ef04796704b96659bdc2ddf5f516f5cd..5df9fc277ea0d55275171c03e252f0b97c74fd01 100644
--- a/algo/ca/core/pars/CaConfigReader.cxx
+++ b/algo/ca/core/pars/CaConfigReader.cxx
@@ -22,10 +22,10 @@
 #include <yaml-cpp/yaml.h>
 
 
-using namespace std::string_literals;
 using cbm::algo::ca::ConfigReader;
 using cbm::algo::ca::EDetectorID;
 using cbm::algo::ca::InitManager;
+using cbm::algo::ca::Iteration;
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
diff --git a/algo/ca/core/pars/CaConfigReader.h b/algo/ca/core/pars/CaConfigReader.h
index d2d4b2cbe3aff562f51c986f98893aa03ce55afd..9178f975c14a8d0aec99adf0dd92b94f1048f040 100644
--- a/algo/ca/core/pars/CaConfigReader.h
+++ b/algo/ca/core/pars/CaConfigReader.h
@@ -18,8 +18,6 @@
 
 #include <yaml-cpp/yaml.h>
 
-using namespace cbm::algo::ca;
-
 namespace YAML
 {
   class Node;
diff --git a/algo/ca/core/pars/CaInitManager.cxx b/algo/ca/core/pars/CaInitManager.cxx
index 02530363ecbd5dff79a54d9ba886182f6cd857bb..4d3996da3efaef0f25b365b7e3273f9ad7b8615b 100644
--- a/algo/ca/core/pars/CaInitManager.cxx
+++ b/algo/ca/core/pars/CaInitManager.cxx
@@ -20,544 +20,543 @@
 #include <fstream>
 #include <sstream>
 
-using namespace constants;
+namespace cbm::algo::ca
+{
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::AddStation(const StationInitializer& inStation) { fvStationInfo.push_back(inStation); }
+
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::CheckInit()
+  {
+    this->CheckCAIterationsInit();
+    this->CheckStationsInfoInit();
+    fbConfigIsRead       = false;
+    fbGeometryConfigLock = false;
+  }
+
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::ClearSetupInfo()
+  {
+    // Clear stations set and a thickness map
+    fvStationInfo.clear();
+    fInitController.SetFlag(EInitKey::kStationsInfo, false);
+
+    // Set number of stations do default values
+    this->ClearStationLayout();
+
+    // Clear field info
+    fParameters.fVertexFieldRegion = kf::FieldRegion<fvec>();
+    fParameters.fVertexFieldValue  = kf::FieldValue<fvec>();
+    fInitController.SetFlag(EInitKey::kPrimaryVertexField, false);
+
+    // Clear target position
+    fParameters.fTargetPos.fill(Undef<float>);
+    fTargetZ = 0.;
+    fInitController.SetFlag(EInitKey::kTargetPos, false);
+
+    // Clear field function
+    fFieldFunction = FieldFunction_t([](const double(&)[3], double(&)[3]) {});
+    fInitController.SetFlag(EInitKey::kFieldFunction, false);
+
+    // Clear other flags
+    fParameters.fRandomSeed       = 1;
+    fParameters.fGhostSuppression = 0;
+    fInitController.SetFlag(EInitKey::kRandomSeed, false);
+    fInitController.SetFlag(EInitKey::kGhostSuppression, false);
+
+    fParameters.fMisalignmentX.fill(0.);
+    fParameters.fMisalignmentY.fill(0.);
+    fParameters.fMisalignmentT.fill(0.);
+
+    fParameters.fDevIsIgnoreHitSearchAreas     = false;
+    fParameters.fDevIsUseOfOriginalField       = false;
+    fParameters.fDevIsMatchDoubletsViaMc       = false;
+    fParameters.fDevIsMatchTripletsViaMc       = false;
+    fParameters.fDevIsExtendTracksViaMc        = false;
+    fParameters.fDevIsSuppressOverlapHitsViaMc = false;
+    fParameters.fDevIsParSearchWUsed           = false;
+  }
+
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::ClearCAIterations()
+  {
+    fParameters.fCAIterations.clear();
+    fCAIterationsNumberCrosscheck = -1;
+    fInitController.SetFlag(EInitKey::kCAIterations, false);
+    fInitController.SetFlag(EInitKey::kCAIterationsNumberCrosscheck, false);
+  }
+
+  // --------------------------------------------------------------------------------------------------------------------
+  // NOTE: this function should be called once in the SendParameters
+  bool InitManager::FormParametersContainer()
+  {
+    // Read configuration files
+    this->ReadInputConfigs();
+    if (!fbConfigIsRead) {  // Check config reading status
+      return false;
+    }
 
-using cbm::algo::ca::InitManager;
-using cbm::algo::ca::Station;
-using cbm::algo::ca::StationInitializer;
+    if (!fParameters.fDevIsParSearchWUsed) {
+      fInitController.SetFlag(EInitKey::kSearchWindows, true);
+    }
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::AddStation(const StationInitializer& inStation) { fvStationInfo.push_back(inStation); }
+    // Apply magnetic field to the station info objects
+    std::for_each(fvStationInfo.begin(), fvStationInfo.end(), [&](auto& st) { st.SetFieldFunction(fFieldFunction); });
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::CheckInit()
-{
-  this->CheckCAIterationsInit();
-  this->CheckStationsInfoInit();
-  fbConfigIsRead       = false;
-  fbGeometryConfigLock = false;
-}
-
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::ClearSetupInfo()
-{
-  // Clear stations set and a thickness map
-  fvStationInfo.clear();
-  fInitController.SetFlag(EInitKey::kStationsInfo, false);
-
-  // Set number of stations do default values
-  this->ClearStationLayout();
-
-  // Clear field info
-  fParameters.fVertexFieldRegion = kf::FieldRegion<fvec>();
-  fParameters.fVertexFieldValue  = kf::FieldValue<fvec>();
-  fInitController.SetFlag(EInitKey::kPrimaryVertexField, false);
-
-  // Clear target position
-  fParameters.fTargetPos.fill(Undef<float>);
-  fTargetZ = 0.;
-  fInitController.SetFlag(EInitKey::kTargetPos, false);
-
-  // Clear field function
-  fFieldFunction = FieldFunction_t([](const double(&)[3], double(&)[3]) {});
-  fInitController.SetFlag(EInitKey::kFieldFunction, false);
-
-  // Clear other flags
-  fParameters.fRandomSeed       = 1;
-  fParameters.fGhostSuppression = 0;
-  fInitController.SetFlag(EInitKey::kRandomSeed, false);
-  fInitController.SetFlag(EInitKey::kGhostSuppression, false);
-
-  fParameters.fMisalignmentX.fill(0.);
-  fParameters.fMisalignmentY.fill(0.);
-  fParameters.fMisalignmentT.fill(0.);
-
-  fParameters.fDevIsIgnoreHitSearchAreas     = false;
-  fParameters.fDevIsUseOfOriginalField       = false;
-  fParameters.fDevIsMatchDoubletsViaMc       = false;
-  fParameters.fDevIsMatchTripletsViaMc       = false;
-  fParameters.fDevIsExtendTracksViaMc        = false;
-  fParameters.fDevIsSuppressOverlapHitsViaMc = false;
-  fParameters.fDevIsParSearchWUsed           = false;
-}
-
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::ClearCAIterations()
-{
-  fParameters.fCAIterations.clear();
-  fCAIterationsNumberCrosscheck = -1;
-  fInitController.SetFlag(EInitKey::kCAIterations, false);
-  fInitController.SetFlag(EInitKey::kCAIterationsNumberCrosscheck, false);
-}
-
-// ----------------------------------------------------------------------------------------------------------------------
-// NOTE: this function should be called once in the SendParameters
-bool InitManager::FormParametersContainer()
-{
-  // Read configuration files
-  this->ReadInputConfigs();
-  if (!fbConfigIsRead) {  // Check config reading status
-    return false;
-  }
+    // Check initialization
+    this->CheckInit();
 
-  if (!fParameters.fDevIsParSearchWUsed) {
-    fInitController.SetFlag(EInitKey::kSearchWindows, true);
-  }
+    if (!fInitController.IsFinalized()) {
+      LOG(error) << "ca::InitManager: Attempt to form parameters container before all necessary fields were initialized"
+                 << fInitController.ToString();
+      return false;
+    }
 
-  // Apply magnetic field to the station info objects
-  std::for_each(fvStationInfo.begin(), fvStationInfo.end(), [&](auto& st) { st.SetFieldFunction(fFieldFunction); });
+    {  // Form array of stations
+      auto destIt = fParameters.fStations.begin();
+      for (const auto& station : fvStationInfo) {
+        if (!station.GetTrackingStatus()) {
+          continue;
+        }
+        *destIt = station.GetStation();
+        ++destIt;
+      }
+    }
 
-  // Check initialization
-  this->CheckInit();
+    // Check the consistency of the parameters object. If object inconsistent, it throws std::logic_error
+    try {
+      fParameters.CheckConsistency();
+    }
+    catch (const std::logic_error& err) {
+      LOG(error) << "ca::InitManager: parameters container consistency check failed. Reason: " << err.what();
+      return false;
+    }
 
-  if (!fInitController.IsFinalized()) {
-    LOG(error) << "ca::InitManager: Attempt to form parameters container before all necessary fields were initialized"
-               << fInitController.ToString();
-    return false;
+    return true;
   }
 
-  {  // Form array of stations
-    auto destIt = fParameters.fStations.begin();
-    for (const auto& station : fvStationInfo) {
-      if (!station.GetTrackingStatus()) {
-        continue;
-      }
-      *destIt = station.GetStation();
-      ++destIt;
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  int InitManager::GetNstationsActive() const
+  {
+    if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
+      std::stringstream msg;
+      msg << "ca::InitManager: number of active stations cannot be accessed until the station layout is initialized";
+      throw std::runtime_error(msg.str());
     }
+    return fParameters.GetNstationsActive();
   }
 
-  // Check the consistency of the parameters object. If object inconsistent, it throws std::logic_error
-  try {
-    fParameters.CheckConsistency();
-  }
-  catch (const std::logic_error& err) {
-    LOG(error) << "ca::InitManager: parameters container consistency check failed. Reason: " << err.what();
-    return false;
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  int InitManager::GetNstationsActive(EDetectorID detectorID) const
+  {
+    if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
+      std::stringstream msg;
+      msg << "ca::InitManager: number of active stations cannot be accessed until the station layout is initialized";
+      throw std::runtime_error(msg.str());
+    }
+    return fParameters.GetNstationsActive(detectorID);
   }
 
-  return true;
-}
-
-// ----------------------------------------------------------------------------------------------------------------------
-//
-int InitManager::GetNstationsActive() const
-{
-  if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
-    std::stringstream msg;
-    msg << "ca::InitManager: number of active stations cannot be accessed until the station layout is initialized";
-    throw std::runtime_error(msg.str());
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  int InitManager::GetNstationsGeometry() const
+  {
+    if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
+      std::stringstream msg;
+      msg << "ca::InitManager: number of geometry stations cannot be accessed until the station layout is initialized";
+      throw std::runtime_error(msg.str());
+    }
+    return fParameters.GetNstationsGeometry();
   }
-  return fParameters.GetNstationsActive();
-}
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-int InitManager::GetNstationsActive(EDetectorID detectorID) const
-{
-  if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
-    std::stringstream msg;
-    msg << "ca::InitManager: number of active stations cannot be accessed until the station layout is initialized";
-    throw std::runtime_error(msg.str());
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  int InitManager::GetNstationsGeometry(EDetectorID detectorID) const
+  {
+    if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
+      std::stringstream msg;
+      msg << "ca::InitManager: number of geometry stations cannot be accessed until the station layout is initialized";
+      throw std::runtime_error(msg.str());
+    }
+    return fParameters.GetNstationsGeometry(detectorID);
   }
-  return fParameters.GetNstationsActive(detectorID);
-}
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-int InitManager::GetNstationsGeometry() const
-{
-  if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
-    std::stringstream msg;
-    msg << "ca::InitManager: number of geometry stations cannot be accessed until the station layout is initialized";
-    throw std::runtime_error(msg.str());
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  std::vector<StationInitializer>& InitManager::GetStationInfo()
+  {
+    if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
+      std::stringstream msg;
+      msg << "ca::InitManager: station info container cannot be accessed until the station layout is initialized";
+      throw std::runtime_error(msg.str());
+    }
+    return fvStationInfo;
   }
-  return fParameters.GetNstationsGeometry();
-}
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-int InitManager::GetNstationsGeometry(EDetectorID detectorID) const
-{
-  if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
-    std::stringstream msg;
-    msg << "ca::InitManager: number of geometry stations cannot be accessed until the station layout is initialized";
-    throw std::runtime_error(msg.str());
-  }
-  return fParameters.GetNstationsGeometry(detectorID);
-}
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-std::vector<StationInitializer>& InitManager::GetStationInfo()
-{
-  if (!fInitController.GetFlag(EInitKey::kStationLayoutInitialized)) {
-    std::stringstream msg;
-    msg << "ca::InitManager: station info container cannot be accessed until the station layout is initialized";
-    throw std::runtime_error(msg.str());
-  }
-  return fvStationInfo;
-}
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::InitStationLayout()
+  {
+    LOG(info) << "ca::InitManager::InitStationLayout(): ....";
+    this->ClearStationLayout();
+    std::sort(fvStationInfo.begin(), fvStationInfo.end());
 
+    for (const auto& aStation : fvStationInfo) {
+      ++fParameters.fvFirstGeoId[static_cast<int>(aStation.GetDetectorID()) + 1];
+    }
+    for (int iDet = 1; iDet < static_cast<int>(fParameters.fvFirstGeoId.size()) - 1; ++iDet) {
+      fParameters.fvFirstGeoId[iDet + 1] += fParameters.fvFirstGeoId[iDet];
+    }
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::InitStationLayout()
-{
-  LOG(info) << "ca::InitManager::InitStationLayout(): ....";
-  this->ClearStationLayout();
-  std::sort(fvStationInfo.begin(), fvStationInfo.end());
+    fParameters.fNstationsActiveTotal = 0;
+    for (int iStGeo = 0; iStGeo < static_cast<int>(fvStationInfo.size()); ++iStGeo) {
+      const auto& aStation = fvStationInfo[iStGeo];
+      int iDet             = static_cast<int>(aStation.GetDetectorID());
+      int iStLocal         = aStation.GetStationID();
+      // Fill local -> geo map
+      fParameters.fvGeoToLocalIdMap[iStGeo] = std::make_pair(aStation.GetDetectorID(), iStLocal);
+      // Fill geo -> local map
+      fParameters.fvLocalToGeoIdMap[fParameters.fvFirstGeoId[iDet] + iStLocal] = iStGeo;
+      // Fill geo <-> active map
+      int iStActive                        = aStation.GetTrackingStatus() ? fParameters.fNstationsActiveTotal++ : -1;
+      fParameters.fvGeoToActiveMap[iStGeo] = iStActive;
+      if (iStActive > -1) {
+        fParameters.fvActiveToGeoMap[iStActive] = iStGeo;
+      }
+    }
+    fInitController.SetFlag(EInitKey::kStationLayoutInitialized, true);
 
-  for (const auto& aStation : fvStationInfo) {
-    ++fParameters.fvFirstGeoId[static_cast<int>(aStation.GetDetectorID()) + 1];
-  }
-  for (int iDet = 1; iDet < static_cast<int>(fParameters.fvFirstGeoId.size()) - 1; ++iDet) {
-    fParameters.fvFirstGeoId[iDet + 1] += fParameters.fvFirstGeoId[iDet];
+    for (auto& aStation : fvStationInfo) {
+      aStation.SetGeoLayerID(fParameters.GetStationIndexGeometry(aStation.GetStationID(), aStation.GetDetectorID()));
+    }
   }
 
-  fParameters.fNstationsActiveTotal = 0;
-  for (int iStGeo = 0; iStGeo < static_cast<int>(fvStationInfo.size()); ++iStGeo) {
-    const auto& aStation = fvStationInfo[iStGeo];
-    int iDet             = static_cast<int>(aStation.GetDetectorID());
-    int iStLocal         = aStation.GetStationID();
-    // Fill local -> geo map
-    fParameters.fvGeoToLocalIdMap[iStGeo] = std::make_pair(aStation.GetDetectorID(), iStLocal);
-    // Fill geo -> local map
-    fParameters.fvLocalToGeoIdMap[fParameters.fvFirstGeoId[iDet] + iStLocal] = iStGeo;
-    // Fill geo <-> active map
-    int iStActive                        = aStation.GetTrackingStatus() ? fParameters.fNstationsActiveTotal++ : -1;
-    fParameters.fvGeoToActiveMap[iStGeo] = iStActive;
-    if (iStActive > -1) {
-      fParameters.fvActiveToGeoMap[iStActive] = iStGeo;
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::InitTargetField(double zStep)
+  {
+    if (fInitController.GetFlag(EInitKey::kPrimaryVertexField)) {
+      LOG(warn) << "ca::InitManager::InitTargetField: attempt to reinitialize the field value and field region "
+                << "near target. Ignore";
+      return;
     }
-  }
-  fInitController.SetFlag(EInitKey::kStationLayoutInitialized, true);
 
-  for (auto& aStation : fvStationInfo) {
-    aStation.SetGeoLayerID(fParameters.GetStationIndexGeometry(aStation.GetStationID(), aStation.GetDetectorID()));
+    // Check for field function
+    if (!fInitController.GetFlag(EInitKey::kFieldFunction)) {
+      std::stringstream msg;
+      msg << "Attempt to initialize the field value and field region near target before initializing field function";
+      throw std::runtime_error(msg.str());
+    }
+    // Check for target defined
+    if (!fInitController.GetFlag(EInitKey::kTargetPos)) {
+      std::stringstream msg;
+      msg << "Attempt to initialize the field value and field region near target before the target position"
+          << "initialization";
+      throw std::runtime_error(msg.str());
+    }
+    constexpr int nDimensions{3};
+    constexpr int nPointsNodal{3};
+
+    std::array<double, nPointsNodal> inputNodalZ{fTargetZ, fTargetZ + zStep, fTargetZ + 2. * zStep};
+    std::array<kf::FieldValue<fvec>, nPointsNodal> B{};
+    std::array<fvec, nPointsNodal> z{};
+    // loop over nodal points
+    for (int idx = 0; idx < nPointsNodal; ++idx) {
+      double point[nDimensions]{0., 0., inputNodalZ[idx]};
+      double field[nDimensions]{};
+      fFieldFunction(point, field);
+      z[idx] = inputNodalZ[idx];
+      B[idx].Set(field[0], field[1], field[2]);
+    }  // loop over nodal points: end
+    fParameters.fVertexFieldRegion.Set(B[0], z[0], B[1], z[1], B[2], z[2]);
+    fParameters.fVertexFieldValue = B[0];
+
+    fInitController.SetFlag(EInitKey::kPrimaryVertexField);
+  }
+
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::PushBackCAIteration(const Iteration& iteration)
+  {
+    // TODO: probably some checks must be inserted here (S.Zharko)
+    if (!fInitController.GetFlag(EInitKey::kCAIterationsNumberCrosscheck)) {
+      std::stringstream msg;
+      msg << "Attempt to push back a CA track finder iteration before the number of iterations was defined";
+      throw std::runtime_error(msg.str());
+    }
+    fParameters.fCAIterations.push_back(iteration);
+  }
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::ReadInputConfigs()
+  {
+    if (!fbConfigIsRead) {
+      LOG(info) << "ca::InitManager: reading parameter configuration ...";
+      try {
+        auto configReader = ConfigReader(this, 4);
+        configReader.SetMainConfigPath(fsConfigInputMain);
+        configReader.SetUserConfigPath(fsConfigInputUser);
+        configReader.SetGeometryLock(fbGeometryConfigLock);
+        configReader.Read();
+        fbConfigIsRead = true;
+        LOG(info) << "ca::InitManager: reading parameter configuration ... \033[1;32mdone\033[0m";
+      }
+      catch (const std::runtime_error& err) {
+        LOG(error) << "ca::InitManager: reading parameter configuration ... \033[1;31mfail\033[0m. Reason: "
+                   << err.what();
+      }
+    }
   }
-}
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::InitTargetField(double zStep)
-{
-  if (fInitController.GetFlag(EInitKey::kPrimaryVertexField)) {
-    LOG(warn) << "ca::InitManager::InitTargetField: attempt to reinitialize the field value and field region "
-              << "near target. Ignore";
-    return;
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::ReadGeometrySetup(const std::string& fileName)
+  {
+    // Open input binary file
+    this->SetGeometrySetup(cbm::algo::kf::SetupBuilder::Load<fvec>(fileName));
   }
 
-  // Check for field function
-  if (!fInitController.GetFlag(EInitKey::kFieldFunction)) {
-    std::stringstream msg;
-    msg << "Attempt to initialize the field value and field region near target before initializing field function";
-    throw std::runtime_error(msg.str());
-  }
-  // Check for target defined
-  if (!fInitController.GetFlag(EInitKey::kTargetPos)) {
-    std::stringstream msg;
-    msg << "Attempt to initialize the field value and field region near target before the target position"
-        << "initialization";
-    throw std::runtime_error(msg.str());
-  }
-  constexpr int nDimensions{3};
-  constexpr int nPointsNodal{3};
-
-  std::array<double, nPointsNodal> inputNodalZ{fTargetZ, fTargetZ + zStep, fTargetZ + 2. * zStep};
-  std::array<kf::FieldValue<fvec>, nPointsNodal> B{};
-  std::array<fvec, nPointsNodal> z{};
-  // loop over nodal points
-  for (int idx = 0; idx < nPointsNodal; ++idx) {
-    double point[nDimensions]{0., 0., inputNodalZ[idx]};
-    double field[nDimensions]{};
-    fFieldFunction(point, field);
-    z[idx] = inputNodalZ[idx];
-    B[idx].Set(field[0], field[1], field[2]);
-  }  // loop over nodal points: end
-  fParameters.fVertexFieldRegion.Set(B[0], z[0], B[1], z[1], B[2], z[2]);
-  fParameters.fVertexFieldValue = B[0];
-
-  fInitController.SetFlag(EInitKey::kPrimaryVertexField);
-}
-
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::PushBackCAIteration(const Iteration& iteration)
-{
-  // TODO: probably some checks must be inserted here (S.Zharko)
-  if (!fInitController.GetFlag(EInitKey::kCAIterationsNumberCrosscheck)) {
-    std::stringstream msg;
-    msg << "Attempt to push back a CA track finder iteration before the number of iterations was defined";
-    throw std::runtime_error(msg.str());
-  }
-  fParameters.fCAIterations.push_back(iteration);
-}
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::ReadParametersObject(const std::string& fileName)
+  {
+    using namespace constants;
+    // clrs::CL  - end colored log
+    // clrs::GNb - bold green log
+    // clrs::RDb - bold red log
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::ReadInputConfigs()
-{
-  if (!fbConfigIsRead) {
-    LOG(info) << "ca::InitManager: reading parameter configuration ...";
-    try {
-      auto configReader = ConfigReader(this, 4);
-      configReader.SetMainConfigPath(fsConfigInputMain);
-      configReader.SetUserConfigPath(fsConfigInputUser);
-      configReader.SetGeometryLock(fbGeometryConfigLock);
-      configReader.Read();
-      fbConfigIsRead = true;
-      LOG(info) << "ca::InitManager: reading parameter configuration ... \033[1;32mdone\033[0m";
-    }
-    catch (const std::runtime_error& err) {
-      LOG(error) << "ca::InitManager: reading parameter configuration ... \033[1;31mfail\033[0m. Reason: "
-                 << err.what();
+    // Open input binary file
+    std::ifstream ifs(fileName, std::ios::binary);
+    if (!ifs) {
+      std::stringstream msg;
+      msg << "ca::InitManager: parameters data file \"" << clrs::GNb << fileName << clrs::CL << "\" was not found";
+      throw std::runtime_error(msg.str());
     }
-  }
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::ReadGeometrySetup(const std::string& fileName)
-{
-  // Open input binary file
-  this->SetGeometrySetup(cbm::algo::kf::SetupBuilder::Load<fvec>(fileName));
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::ReadParametersObject(const std::string& fileName)
-{
-  // clrs::CL  - end colored log
-  // clrs::GNb - bold green log
-  // clrs::RDb - bold red log
-
-  // Open input binary file
-  std::ifstream ifs(fileName, std::ios::binary);
-  if (!ifs) {
-    std::stringstream msg;
-    msg << "ca::InitManager: parameters data file \"" << clrs::GNb << fileName << clrs::CL << "\" was not found";
-    throw std::runtime_error(msg.str());
-  }
+    // Get L1InputData object
+    try {
+      boost::archive::binary_iarchive ia(ifs);
+      ia >> fParameters;
+      fbGeometryConfigLock = true;
+    }
+    catch (const std::exception&) {
+      std::stringstream msg;
+      msg << "ca::InitManager: parameters file \"" << clrs::GNb << fileName << clrs::CL
+          << "\" has incorrect data format or was corrupted";
+      throw std::runtime_error(msg.str());
+    }
 
-  // Get L1InputData object
-  try {
-    boost::archive::binary_iarchive ia(ifs);
-    ia >> fParameters;
-    fbGeometryConfigLock = true;
-  }
-  catch (const std::exception&) {
-    std::stringstream msg;
-    msg << "ca::InitManager: parameters file \"" << clrs::GNb << fileName << clrs::CL
-        << "\" has incorrect data format or was corrupted";
-    throw std::runtime_error(msg.str());
+    fInitController.SetFlag(EInitKey::kStationLayoutInitialized, true);
+    fInitController.SetFlag(EInitKey::kPrimaryVertexField, true);
+    fInitController.SetFlag(EInitKey::kSearchWindows, true);
   }
 
-  fInitController.SetFlag(EInitKey::kStationLayoutInitialized, true);
-  fInitController.SetFlag(EInitKey::kPrimaryVertexField, true);
-  fInitController.SetFlag(EInitKey::kSearchWindows, true);
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::ReadSearchWindows(const std::string& fileName)
-{
-  // Open input binary file
-  std::ifstream ifs(fileName);
-  if (!ifs) {
-    std::stringstream msg;
-    msg << "ca::InitManager: search window file \"" << fileName << "\" was not found";
-    throw std::runtime_error(msg.str());
-  }
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::ReadSearchWindows(const std::string& fileName)
+  {
+    // Open input binary file
+    std::ifstream ifs(fileName);
+    if (!ifs) {
+      std::stringstream msg;
+      msg << "ca::InitManager: search window file \"" << fileName << "\" was not found";
+      throw std::runtime_error(msg.str());
+    }
 
-  try {
-    boost::archive::text_iarchive ia(ifs);
-    int nPars    = -1;
-    int nWindows = -1;
-    ia >> nPars;
-    assert(nPars == 1);  // Currently only the constant windows are available
-    ia >> nWindows;
-    std::stringstream errMsg;
-    for (int iW = 0; iW < nWindows; ++iW) {
-      SearchWindow swBuffer;
-      ia >> swBuffer;
-      int iStationID = swBuffer.GetStationID();
-      int iTrackGrID = swBuffer.GetTrackGroupID();
-      if (iStationID < 0 || iStationID > constants::size::MaxNstations) {
-        errMsg << "\t- wrong station id for entry " << iW << ": " << iStationID << " (should be between 0 and "
-               << constants::size::MaxNstations << ")\n";
+    try {
+      boost::archive::text_iarchive ia(ifs);
+      int nPars    = -1;
+      int nWindows = -1;
+      ia >> nPars;
+      assert(nPars == 1);  // Currently only the constant windows are available
+      ia >> nWindows;
+      std::stringstream errMsg;
+      for (int iW = 0; iW < nWindows; ++iW) {
+        SearchWindow swBuffer;
+        ia >> swBuffer;
+        int iStationID = swBuffer.GetStationID();
+        int iTrackGrID = swBuffer.GetTrackGroupID();
+        if (iStationID < 0 || iStationID > constants::size::MaxNstations) {
+          errMsg << "\t- wrong station id for entry " << iW << ": " << iStationID << " (should be between 0 and "
+                 << constants::size::MaxNstations << ")\n";
+        }
+        if (iTrackGrID < 0 || iTrackGrID > constants::size::MaxNtrackGroups) {
+          errMsg << "\t- wrong track group id for entry " << iW << ": " << iTrackGrID << " (should be between 0 and "
+                 << constants::size::MaxNtrackGroups << ")\n";
+        }
+        fParameters.fSearchWindows[iTrackGrID * constants::size::MaxNstations + iStationID] = swBuffer;
       }
-      if (iTrackGrID < 0 || iTrackGrID > constants::size::MaxNtrackGroups) {
-        errMsg << "\t- wrong track group id for entry " << iW << ": " << iTrackGrID << " (should be between 0 and "
-               << constants::size::MaxNtrackGroups << ")\n";
+      if (errMsg.str().size()) {
+        std::stringstream msg;
+        msg << "ca::InitManager: some errors occurred while reading search windows: " << errMsg.str();
+        throw std::runtime_error(msg.str());
       }
-      fParameters.fSearchWindows[iTrackGrID * constants::size::MaxNstations + iStationID] = swBuffer;
     }
-    if (errMsg.str().size()) {
+    catch (const std::exception& err) {
       std::stringstream msg;
-      msg << "ca::InitManager: some errors occurred while reading search windows: " << errMsg.str();
+      msg << "search windows file \"" << fileName << "\" has incorrect data format or was corrupted. ";
+      msg << "Exception catched: " << err.what();
       throw std::runtime_error(msg.str());
     }
-  }
-  catch (const std::exception& err) {
-    std::stringstream msg;
-    msg << "search windows file \"" << fileName << "\" has incorrect data format or was corrupted. ";
-    msg << "Exception catched: " << err.what();
-    throw std::runtime_error(msg.str());
-  }
-
-  fInitController.SetFlag(EInitKey::kSearchWindows, true);
-}
-
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::SetCAIterationsNumberCrosscheck(int nIterations)
-{
-  fCAIterationsNumberCrosscheck = nIterations;
-  auto& iterationsContainer     = fParameters.fCAIterations;
 
-  // NOTE: should be called to prevent multiple copies of objects between the memory reallocations
-  iterationsContainer.reserve(nIterations);
-  fInitController.SetFlag(EInitKey::kCAIterationsNumberCrosscheck);
-}
-
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::SetFieldFunction(const FieldFunction_t& fieldFunction)
-{
-  if (!fInitController.GetFlag(EInitKey::kFieldFunction)) {
-    fFieldFunction = fieldFunction;
-    fInitController.SetFlag(EInitKey::kFieldFunction);
-  }
-  else {
-    LOG(warn) << "ca::InitManager::SetFieldFunction: attempt to reinitialize the field function. Ignored";
+    fInitController.SetFlag(EInitKey::kSearchWindows, true);
   }
-}
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::SetGhostSuppression(int ghostSuppression)
-{
-  if (fInitController.GetFlag(EInitKey::kGhostSuppression)) {
-    LOG(warn) << "ca::InitManager::SetGhostSuppression: attempt of reinitializating the ghost suppresion flag. Ignore";
-    return;
-  }
-  fParameters.fGhostSuppression = ghostSuppression;
-  fInitController.SetFlag(EInitKey::kGhostSuppression);
-}
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::SetCAIterationsNumberCrosscheck(int nIterations)
+  {
+    fCAIterationsNumberCrosscheck = nIterations;
+    auto& iterationsContainer     = fParameters.fCAIterations;
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::SetRandomSeed(unsigned int seed)
-{
-  if (fInitController.GetFlag(EInitKey::kRandomSeed)) {
-    LOG(warn) << "ca::InitManager::SetRandomSeed: attempt of reinitializating the random seed. Ignore";
-    return;
+    // NOTE: should be called to prevent multiple copies of objects between the memory reallocations
+    iterationsContainer.reserve(nIterations);
+    fInitController.SetFlag(EInitKey::kCAIterationsNumberCrosscheck);
   }
-  fParameters.fRandomSeed = seed;
-  fInitController.SetFlag(EInitKey::kRandomSeed);
-}
 
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::SetTargetPosition(double x, double y, double z)
-{
-  if (fInitController.GetFlag(EInitKey::kTargetPos)) {
-    LOG(warn) << "ca::InitManager::SetTargetPosition: attempt to reinitialize the target position. Ignore";
-    return;
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::SetFieldFunction(const FieldFunction_t& fieldFunction)
+  {
+    if (!fInitController.GetFlag(EInitKey::kFieldFunction)) {
+      fFieldFunction = fieldFunction;
+      fInitController.SetFlag(EInitKey::kFieldFunction);
+    }
+    else {
+      LOG(warn) << "ca::InitManager::SetFieldFunction: attempt to reinitialize the field function. Ignored";
+    }
   }
 
-  /// Fill fvec target fields
-  fParameters.fTargetPos[0] = x;
-  fParameters.fTargetPos[1] = y;
-  fParameters.fTargetPos[2] = z;
-  /// Set additional field for z component in double precision
-  fTargetZ = z;
-  fInitController.SetFlag(EInitKey::kTargetPos);
-}
-
-// ----------------------------------------------------------------------------------------------------------------------
-//
-Parameters<fvec>&& InitManager::TakeParameters() { return std::move(fParameters); }
-
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::WriteParametersObject(const std::string& fileName) const
-{
-  using clrs::CL;
-  using clrs::GNb;
-  // Open output binary file
-  std::ofstream ofs(fileName, std::ios::binary);
-  if (!ofs) {
-    std::stringstream msg;
-    msg << "ca::InitManager: failed opening file \"" << GNb << fileName << CL << "\" to write parameters object";
-    throw std::runtime_error(msg.str());
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::SetGhostSuppression(int ghostSuppression)
+  {
+    if (fInitController.GetFlag(EInitKey::kGhostSuppression)) {
+      LOG(warn)
+        << "ca::InitManager::SetGhostSuppression: attempt of reinitializating the ghost suppresion flag. Ignore";
+      return;
+    }
+    fParameters.fGhostSuppression = ghostSuppression;
+    fInitController.SetFlag(EInitKey::kGhostSuppression);
   }
 
-  LOG(info) << "ca::InitManager: writing CA parameters object to file \"" << GNb << fileName << '\"' << CL;
-
-  // Serialize L1Parameters object and write
-  boost::archive::binary_oarchive oa(ofs);
-  oa << fParameters;
-}
-
-// ----------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::CheckCAIterationsInit()
-{
-  bool ifInitPassed = true;
-  if (!fInitController.GetFlag(EInitKey::kCAIterations)) {
-    int nIterationsActual   = fParameters.fCAIterations.size();
-    int nIterationsExpected = fCAIterationsNumberCrosscheck;
-    if (nIterationsActual != nIterationsExpected) {
-      LOG(warn) << "ca::InitManager::CheckCAIterations: incorrect number of iterations registered: "
-                << nIterationsActual << " of " << nIterationsExpected << " expected";
-      ifInitPassed = false;
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::SetRandomSeed(unsigned int seed)
+  {
+    if (fInitController.GetFlag(EInitKey::kRandomSeed)) {
+      LOG(warn) << "ca::InitManager::SetRandomSeed: attempt of reinitializating the random seed. Ignore";
+      return;
     }
+    fParameters.fRandomSeed = seed;
+    fInitController.SetFlag(EInitKey::kRandomSeed);
   }
-  fInitController.SetFlag(EInitKey::kCAIterations, ifInitPassed);
-}
 
-// ----------------------------------------------------------------------------------------------------------------------
-// TODO: REWRITE! and add const qualifier (S.Zharko)
-void InitManager::CheckStationsInfoInit()
-{
-  bool ifInitPassed = true;
-  if (!fInitController.GetFlag(EInitKey::kStationsInfo)) {
-    // (1) Check the stations themselves
-    bool bStationsFinalized = std::all_of(fvStationInfo.begin(), fvStationInfo.end(),
-                                          [](const auto& st) { return st.GetInitController().IsFinalized(); });
-    if (!bStationsFinalized) {
-      std::stringstream msg;
-      msg << "ca::InitManager: At least one of the StationInitializer objects is not finalized";
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::SetTargetPosition(double x, double y, double z)
+  {
+    if (fInitController.GetFlag(EInitKey::kTargetPos)) {
+      LOG(warn) << "ca::InitManager::SetTargetPosition: attempt to reinitialize the target position. Ignore";
+      return;
     }
 
-    // (2) Check for maximum allowed number of stations
-    if (fParameters.GetNstationsGeometry() > constants::size::MaxNstations) {
+    /// Fill fvec target fields
+    fParameters.fTargetPos[0] = x;
+    fParameters.fTargetPos[1] = y;
+    fParameters.fTargetPos[2] = z;
+    /// Set additional field for z component in double precision
+    fTargetZ = z;
+    fInitController.SetFlag(EInitKey::kTargetPos);
+  }
+
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  Parameters<fvec>&& InitManager::TakeParameters() { return std::move(fParameters); }
+
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::WriteParametersObject(const std::string& fileName) const
+  {
+    using constants::clrs::CL;
+    using constants::clrs::GNb;
+    // Open output binary file
+    std::ofstream ofs(fileName, std::ios::binary);
+    if (!ofs) {
       std::stringstream msg;
-      msg << "Actual total number of registered stations in geometry (" << fParameters.GetNstationsGeometry()
-          << ") is larger then possible (" << constants::size::MaxNstations
-          << "). Please, select another set of active tracking detectors or recompile the code with enlarged"
-          << " constants::size::MaxNstations value";
+      msg << "ca::InitManager: failed opening file \"" << GNb << fileName << CL << "\" to write parameters object";
       throw std::runtime_error(msg.str());
     }
-  }
-  fInitController.SetFlag(EInitKey::kStationsInfo, ifInitPassed);
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void InitManager::ClearStationLayout()
-{
-  fParameters.fvFirstGeoId.fill(0);
-  fParameters.fvLocalToGeoIdMap.fill(0);
-  fParameters.fvGeoToLocalIdMap.fill(std::make_pair(static_cast<EDetectorID>(0), -1));
-  fParameters.fvGeoToActiveMap.fill(-1);  // Note: by default all the stations are inactive
-  fParameters.fvActiveToGeoMap.fill(0);
-  fParameters.fNstationsActiveTotal = -1;
-  fInitController.SetFlag(EInitKey::kStationLayoutInitialized, false);
-}
+    LOG(info) << "ca::InitManager: writing CA parameters object to file \"" << GNb << fileName << '\"' << CL;
+
+    // Serialize L1Parameters object and write
+    boost::archive::binary_oarchive oa(ofs);
+    oa << fParameters;
+  }
+
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::CheckCAIterationsInit()
+  {
+    bool ifInitPassed = true;
+    if (!fInitController.GetFlag(EInitKey::kCAIterations)) {
+      int nIterationsActual   = fParameters.fCAIterations.size();
+      int nIterationsExpected = fCAIterationsNumberCrosscheck;
+      if (nIterationsActual != nIterationsExpected) {
+        LOG(warn) << "ca::InitManager::CheckCAIterations: incorrect number of iterations registered: "
+                  << nIterationsActual << " of " << nIterationsExpected << " expected";
+        ifInitPassed = false;
+      }
+    }
+    fInitController.SetFlag(EInitKey::kCAIterations, ifInitPassed);
+  }
+
+  // --------------------------------------------------------------------------------------------------------------------
+  // TODO: REWRITE! and add const qualifier (S.Zharko)
+  void InitManager::CheckStationsInfoInit()
+  {
+    bool ifInitPassed = true;
+    if (!fInitController.GetFlag(EInitKey::kStationsInfo)) {
+      // (1) Check the stations themselves
+      bool bStationsFinalized = std::all_of(fvStationInfo.begin(), fvStationInfo.end(),
+                                            [](const auto& st) { return st.GetInitController().IsFinalized(); });
+      if (!bStationsFinalized) {
+        std::stringstream msg;
+        msg << "ca::InitManager: At least one of the StationInitializer objects is not finalized";
+      }
+
+      // (2) Check for maximum allowed number of stations
+      if (fParameters.GetNstationsGeometry() > constants::size::MaxNstations) {
+        std::stringstream msg;
+        msg << "Actual total number of registered stations in geometry (" << fParameters.GetNstationsGeometry()
+            << ") is larger then possible (" << constants::size::MaxNstations
+            << "). Please, select another set of active tracking detectors or recompile the code with enlarged"
+            << " constants::size::MaxNstations value";
+        throw std::runtime_error(msg.str());
+      }
+    }
+    fInitController.SetFlag(EInitKey::kStationsInfo, ifInitPassed);
+  }
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void InitManager::ClearStationLayout()
+  {
+    fParameters.fvFirstGeoId.fill(0);
+    fParameters.fvLocalToGeoIdMap.fill(0);
+    fParameters.fvGeoToLocalIdMap.fill(std::make_pair(static_cast<EDetectorID>(0), -1));
+    fParameters.fvGeoToActiveMap.fill(-1);  // Note: by default all the stations are inactive
+    fParameters.fvActiveToGeoMap.fill(0);
+    fParameters.fNstationsActiveTotal = -1;
+    fInitController.SetFlag(EInitKey::kStationLayoutInitialized, false);
+  }
+}  // namespace cbm::algo::ca
\ No newline at end of file
diff --git a/algo/ca/core/pars/CaParameters.cxx b/algo/ca/core/pars/CaParameters.cxx
index c89279a12c1c24c77b9b03cc28d931f4ad47b931..286b3c42e98c6e505993b5a876580b74656e4f30 100644
--- a/algo/ca/core/pars/CaParameters.cxx
+++ b/algo/ca/core/pars/CaParameters.cxx
@@ -311,7 +311,7 @@ std::string Parameters<DataT>::ToString(int verbosity, int indentLevel) const
   msg << indent << indentCh << "Random seed:                        " << fRandomSeed << '\n';
   msg << indent << indentCh << "Max number of doublets per singlet: " << fMaxDoubletsPerSinglet << '\n';
   msg << indent << indentCh << "Max number of triplets per doublet: " << fMaxTripletPerDoublets << '\n';
-  msg << indent << indentCh << "Ghost suppresion:                   " << fGhostSuppression << '\n';
+  msg << indent << indentCh << "Ghost suppression:                   " << fGhostSuppression << '\n';
   msg << indent << clrs::CLb << "CA TRACK FINDER ITERATIONS:\n" << clrs::CL;
   msg << Iteration::ToTableFromVector(fCAIterations);
   msg << indent << clrs::CLb << "GEOMETRY:\n" << clrs::CL;
diff --git a/algo/ca/core/pars/CaStation.cxx b/algo/ca/core/pars/CaStation.cxx
index ce84b8ce17f16886e0d81234bc5cab3b084e53e2..a83c1f974f1fe3559db7a50673007c0a34304af1 100644
--- a/algo/ca/core/pars/CaStation.cxx
+++ b/algo/ca/core/pars/CaStation.cxx
@@ -9,104 +9,103 @@
 #include <iomanip>
 #include <sstream>
 
-using namespace cbm::algo::ca;
-
-//------------------------------------------------------------------------------------------------------------------------------------
-//
-template<typename DataT>
-void Station<DataT>::CheckConsistency() const
+namespace cbm::algo::ca
 {
-  /// Integer fields initialization checks
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename DataT>
+  void Station<DataT>::CheckConsistency() const
+  {
+    /// Integer fields initialization checks
 
-  if (type < 0) {
-    std::stringstream msg;
-    msg << "CaStation: station type was not initialized (type = " << type << ", type > 0)";
-    throw std::logic_error(msg.str());
-  }
+    if (type < 0) {
+      std::stringstream msg;
+      msg << "CaStation: station type was not initialized (type = " << type << ", type > 0)";
+      throw std::logic_error(msg.str());
+    }
 
-  if (timeInfo != 0 && timeInfo != 1) {
-    std::stringstream msg;
-    msg << "CaStation: illegal time information flag (timeInfo = " << timeInfo << ", "
-        << "0 [time information is not used] or 1 [time information is used] expected)";
-    throw std::logic_error(msg.str());
-  }
+    if (timeInfo != 0 && timeInfo != 1) {
+      std::stringstream msg;
+      msg << "CaStation: illegal time information flag (timeInfo = " << timeInfo << ", "
+          << "0 [time information is not used] or 1 [time information is used] expected)";
+      throw std::logic_error(msg.str());
+    }
 
-  if (fieldStatus != 0 && fieldStatus != 1) {
-    std::stringstream msg;
-    msg << "CaStation: illegal field status flag (fieldStatus = " << fieldStatus << ", "
-        << "0 [station is outside the field] or 1 [station is inside the field] expected";
-    throw std::logic_error(msg.str());
-  }
+    if (fieldStatus != 0 && fieldStatus != 1) {
+      std::stringstream msg;
+      msg << "CaStation: illegal field status flag (fieldStatus = " << fieldStatus << ", "
+          << "0 [station is outside the field] or 1 [station is inside the field] expected";
+      throw std::logic_error(msg.str());
+    }
 
-  /// SIMD vector checks: all the words in a SIMD vector must be equal
-  // TODO: SZh 06.06.2024: Do we still need these checks?
-  kfutils::CheckSimdVectorEquality<DataT>(fZ, "CaStation::fZ");
-  kfutils::CheckSimdVectorEquality<DataT>(Xmax, "CaStation::Xmax");
-  kfutils::CheckSimdVectorEquality<DataT>(Ymax, "CaStation::Ymax");
+    /// SIMD vector checks: all the words in a SIMD vector must be equal
+    // TODO: SZh 06.06.2024: Do we still need these checks?
+    kfutils::CheckSimdVectorEquality<DataT>(fZ, "CaStation::fZ");
+    kfutils::CheckSimdVectorEquality<DataT>(Xmax, "CaStation::Xmax");
+    kfutils::CheckSimdVectorEquality<DataT>(Ymax, "CaStation::Ymax");
 
 
-  /// Inner and outer radia checks:
-  ///  (i)  both Xmax and Ymax must be > 0
+    /// Inner and outer radia checks:
+    ///  (i)  both Xmax and Ymax must be > 0
 
-  if (this->GetXmax<float>() < 0. || this->GetYmax<float>() < 0.) {
-    std::stringstream msg;
-    msg << "CaStation: " << this->ToString() << " has incorrect sizes: "
-        << "Xmax = " << this->GetXmax<float>() << " [cm], Ymax = " << this->GetYmax<float>()
-        << " [cm] (0 < Xmax && 0 < Ymax expected)";
-    throw std::logic_error(msg.str());
-  }
-
-  /// Check consistency of other members
+    if (this->GetXmax<float>() < 0. || this->GetYmax<float>() < 0.) {
+      std::stringstream msg;
+      msg << "CaStation: " << this->ToString() << " has incorrect sizes: "
+          << "Xmax = " << this->GetXmax<float>() << " [cm], Ymax = " << this->GetYmax<float>()
+          << " [cm] (0 < Xmax && 0 < Ymax expected)";
+      throw std::logic_error(msg.str());
+    }
 
-  //materialInfo.CheckConsistency();
-  // TODO: Temporarily switched off, because Much has RL = 0, which is actually incorrect, but really is not used.
-  //       One should provide average radiation length values for each Much layer (S.Zharko)
-  fieldSlice.CheckConsistency();
-}
+    /// Check consistency of other members
 
-//------------------------------------------------------------------------------------------------------------------------------------
-//
-template<typename DataT>
-std::string Station<DataT>::ToString(int verbosityLevel, int indentLevel, bool isHeader) const
-{
-  std::stringstream msg{};
-  constexpr char indentChar = '\t';
-  constexpr char columnSize = 15;
-  std::string indent(indentLevel, indentChar);
-  if (verbosityLevel == 0) {
-    msg << "station type = " << type << ", z = " << this->GetZ<float>() << " cm";
+    //materialInfo.CheckConsistency();
+    // TODO: Temporarily switched off, because Much has RL = 0, which is actually incorrect, but really is not used.
+    //       One should provide average radiation length values for each Much layer (S.Zharko)
+    fieldSlice.CheckConsistency();
   }
-  else {
-    if (isHeader) {
-      verbosityLevel = 0;
-      msg << indent;
-      msg << std::setw(columnSize) << std::setfill(' ') << "type" << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << "time status" << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << "field status" << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << "geo layer ID" << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << "z [cm]" << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << "Xmax [cm]" << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << "Ymax [cm]";
+
+  // --------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename DataT>
+  std::string Station<DataT>::ToString(int verbosityLevel, int indentLevel, bool isHeader) const
+  {
+    std::stringstream msg{};
+    constexpr char indentChar = '\t';
+    constexpr char columnSize = 15;
+    std::string indent(indentLevel, indentChar);
+    if (verbosityLevel == 0) {
+      msg << "station type = " << type << ", z = " << this->GetZ<float>() << " cm";
     }
     else {
-      msg << indent;
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetType() << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetTimeStatus() << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetFieldStatus() << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetGeoLayerID() << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetZ<float>() << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetXmax<float>() << ' ';
-      msg << std::setw(columnSize) << std::setfill(' ') << this->GetYmax<float>();
-    }
-    if (verbosityLevel > 3) {
-      msg << indent << "Field approcimation coefficients:\n";
-      msg << fieldSlice.ToString(indentLevel + 1) << '\n';
+      if (isHeader) {
+        verbosityLevel = 0;
+        msg << indent;
+        msg << std::setw(columnSize) << std::setfill(' ') << "type" << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << "time status" << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << "field status" << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << "geo layer ID" << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << "z [cm]" << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << "Xmax [cm]" << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << "Ymax [cm]";
+      }
+      else {
+        msg << indent;
+        msg << std::setw(columnSize) << std::setfill(' ') << this->GetType() << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << this->GetTimeStatus() << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << this->GetFieldStatus() << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << this->GetGeoLayerID() << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << this->GetZ<float>() << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << this->GetXmax<float>() << ' ';
+        msg << std::setw(columnSize) << std::setfill(' ') << this->GetYmax<float>();
+      }
+      if (verbosityLevel > 3) {
+        msg << indent << "\nField slices:\n";
+        msg << fieldSlice.ToString(indentLevel + 1, verbosityLevel) << '\n';
+      }
     }
+    return msg.str();
   }
-  return msg.str();
-}
-namespace cbm::algo::ca
-{
+
   template class Station<fvec>;
   template class Station<float>;
   template class Station<double>;
diff --git a/algo/ca/core/tracking/CaCloneMerger.cxx b/algo/ca/core/tracking/CaCloneMerger.cxx
index cfc7404ef6dc3080918db70b000fc3a192acc00a..a36c206cdeae18f2c3fc6d1aacc1233af1485d6e 100644
--- a/algo/ca/core/tracking/CaCloneMerger.cxx
+++ b/algo/ca/core/tracking/CaCloneMerger.cxx
@@ -17,364 +17,366 @@
 
 #include <iostream>
 
-using namespace cbm::algo::ca;
-using namespace cbm::algo;
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-CloneMerger::CloneMerger(const ca::Parameters<fvec>& pars, const fscal mass) : fParameters(pars), fDefaultMass(mass) {}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-CloneMerger::~CloneMerger() {}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void CloneMerger::Exec(const ca::InputData& input, WindowData& wData)
+namespace cbm::algo::ca
 {
-  Vector<Track>& extTracks            = wData.RecoTracks();
-  Vector<ca::HitIndex_t>& extRecoHits = wData.RecoHitIndices();
-
-  Vector<unsigned short>& firstStation = fTrackFirstStation;
-  Vector<unsigned short>& lastStation  = fTrackLastStation;
-  Vector<ca::HitIndex_t>& firstHit     = fTrackFirstHit;
-  Vector<ca::HitIndex_t>& lastHit      = fTrackLastHit;
-  Vector<unsigned short>& neighbour    = fTrackNeighbour;
-  Vector<fscal>& trackChi2             = fTrackChi2;
-  Vector<char>& isStored               = fTrackIsStored;
-  Vector<char>& isDownstreamNeighbour  = fTrackIsDownstreamNeighbour;
-
-  int nTracks = extTracks.size();
-
-  assert(nTracks < std::numeric_limits<unsigned short>::max());
-
-  constexpr unsigned short kNoNeighbour = std::numeric_limits<unsigned short>::max();
-
-  fTracksNew.clear();
-  fTracksNew.reserve(nTracks);
-  fRecoHitsNew.clear();
-  fRecoHitsNew.reserve(extRecoHits.size());
-
-  firstStation.reset(nTracks);
-  lastStation.reset(nTracks);
-  firstHit.reset(nTracks);
-  lastHit.reset(nTracks);
-  isStored.reset(nTracks);
-  trackChi2.reset(nTracks);
-  neighbour.reset(nTracks);
-  isDownstreamNeighbour.reset(nTracks);
-
-  ca::HitIndex_t start_hit = 0;
-
-  for (int iTr = 0; iTr < nTracks; iTr++) {
-    firstHit[iTr]     = start_hit;
-    firstStation[iTr] = input.GetHit(extRecoHits[start_hit]).Station();
-    start_hit += extTracks[iTr].fNofHits - 1;
-    lastHit[iTr]     = start_hit;
-    lastStation[iTr] = input.GetHit(extRecoHits[start_hit]).Station();
-    start_hit++;
-
-    isStored[iTr]              = false;
-    neighbour[iTr]             = kNoNeighbour;
-    trackChi2[iTr]             = 100000.;
-    isDownstreamNeighbour[iTr] = false;
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  CloneMerger::CloneMerger(const ca::Parameters<fvec>& pars, const fscal mass) : fParameters(pars), fDefaultMass(mass)
+  {
   }
 
-  kf::TrackKalmanFilter<fvec> fitB;
-  fitB.SetParticleMass(fDefaultMass);
-  fitB.SetMask(fmask::One());
-  fitB.SetQp0(fvec(0.));
-
-  kf::TrackKalmanFilter<fvec> fitF;
-  fitF.SetParticleMass(fDefaultMass);
-  fitF.SetMask(fmask::One());
-  fitF.SetQp0(fvec(0.));
-
-  TrackParamV& Tb = fitB.Tr();
-  TrackParamV& Tf = fitF.Tr();
-  kf::FieldValue<fvec> fBm, fBb, fBf _fvecalignment;
-  kf::FieldRegion<fvec> fld _fvecalignment;
-
-  // Max length for merging
-  unsigned char maxLengthForMerge = static_cast<unsigned char>(fParameters.GetNstationsActive() - 3);
-
-  for (int iTr = 0; iTr < nTracks; iTr++) {
-    if (extTracks[iTr].fNofHits > maxLengthForMerge) continue;
-    for (int jTr = 0; jTr < nTracks; jTr++) {
-      if (extTracks[jTr].fNofHits > maxLengthForMerge) continue;
-      if (iTr == jTr) continue;
-      if (firstStation[iTr] <= lastStation[jTr]) continue;
-
-      unsigned short stab = firstStation[iTr];
-
-      Tb.Set(extTracks[iTr].fParFirst);
-
-      fitB.SetQp0(fitB.Tr().GetQp());
-
-      unsigned short staf = lastStation[jTr];
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  CloneMerger::~CloneMerger() {}
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void CloneMerger::Exec(const ca::InputData& input, WindowData& wData)
+  {
+    Vector<Track>& extTracks            = wData.RecoTracks();
+    Vector<ca::HitIndex_t>& extRecoHits = wData.RecoHitIndices();
+
+    Vector<unsigned short>& firstStation = fTrackFirstStation;
+    Vector<unsigned short>& lastStation  = fTrackLastStation;
+    Vector<ca::HitIndex_t>& firstHit     = fTrackFirstHit;
+    Vector<ca::HitIndex_t>& lastHit      = fTrackLastHit;
+    Vector<unsigned short>& neighbour    = fTrackNeighbour;
+    Vector<fscal>& trackChi2             = fTrackChi2;
+    Vector<char>& isStored               = fTrackIsStored;
+    Vector<char>& isDownstreamNeighbour  = fTrackIsDownstreamNeighbour;
+
+    int nTracks = extTracks.size();
+
+    assert(nTracks < std::numeric_limits<unsigned short>::max());
+
+    constexpr unsigned short kNoNeighbour = std::numeric_limits<unsigned short>::max();
+
+    fTracksNew.clear();
+    fTracksNew.reserve(nTracks);
+    fRecoHitsNew.clear();
+    fRecoHitsNew.reserve(extRecoHits.size());
+
+    firstStation.reset(nTracks);
+    lastStation.reset(nTracks);
+    firstHit.reset(nTracks);
+    lastHit.reset(nTracks);
+    isStored.reset(nTracks);
+    trackChi2.reset(nTracks);
+    neighbour.reset(nTracks);
+    isDownstreamNeighbour.reset(nTracks);
+
+    ca::HitIndex_t start_hit = 0;
+
+    for (int iTr = 0; iTr < nTracks; iTr++) {
+      firstHit[iTr]     = start_hit;
+      firstStation[iTr] = input.GetHit(extRecoHits[start_hit]).Station();
+      start_hit += extTracks[iTr].fNofHits - 1;
+      lastHit[iTr]     = start_hit;
+      lastStation[iTr] = input.GetHit(extRecoHits[start_hit]).Station();
+      start_hit++;
+
+      isStored[iTr]              = false;
+      neighbour[iTr]             = kNoNeighbour;
+      trackChi2[iTr]             = 100000.;
+      isDownstreamNeighbour[iTr] = false;
+    }
 
-      Tf.Set(extTracks[jTr].fParLast);
-      fitF.SetQp0(fitF.Tr().GetQp());
+    kf::TrackKalmanFilter<fvec> fitB;
+    fitB.SetParticleMass(fDefaultMass);
+    fitB.SetMask(fmask::One());
+    fitB.SetQp0(fvec(0.));
 
-      if (Tf.NdfTime()[0] >= 0. && Tb.NdfTime()[0] >= 0.) {
-        if (fabs(Tf.GetTime()[0] - Tb.GetTime()[0]) > 3 * sqrt(Tf.C55()[0] + Tb.C55()[0])) continue;
-      }
+    kf::TrackKalmanFilter<fvec> fitF;
+    fitF.SetParticleMass(fDefaultMass);
+    fitF.SetMask(fmask::One());
+    fitF.SetQp0(fvec(0.));
 
-      unsigned short stam;
+    TrackParamV& Tb = fitB.Tr();
+    TrackParamV& Tf = fitF.Tr();
+    kf::FieldValue<fvec> fBm, fBb, fBf _fvecalignment;
+    kf::FieldRegion<fvec> fld _fvecalignment;
 
-      fBf = fParameters.GetStation(staf).fieldSlice.GetFieldValue(Tf.X(), Tf.Y());
-      fBb = fParameters.GetStation(stab).fieldSlice.GetFieldValue(Tb.X(), Tb.Y());
+    // Max length for merging
+    unsigned char maxLengthForMerge = static_cast<unsigned char>(fParameters.GetNstationsActive() - 3);
 
-      unsigned short dist = firstStation[iTr] - lastStation[jTr];
+    for (int iTr = 0; iTr < nTracks; iTr++) {
+      if (extTracks[iTr].fNofHits > maxLengthForMerge) continue;
+      for (int jTr = 0; jTr < nTracks; jTr++) {
+        if (extTracks[jTr].fNofHits > maxLengthForMerge) continue;
+        if (iTr == jTr) continue;
+        if (firstStation[iTr] <= lastStation[jTr]) continue;
 
-      if (dist > 1)
-        stam = staf + 1;
-      else
-        stam = staf - 1;
+        unsigned short stab = firstStation[iTr];
 
-      fvec zm = fParameters.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     = fParameters.GetStation(stam).fieldSlice.GetFieldValue(xm, ym);
-      fld.Set(fBb, Tb.Z(), fBm, zm, fBf, Tf.Z());
+        Tb.Set(extTracks[iTr].fParFirst);
 
-      fvec zMiddle = fvec(0.5) * (Tb.Z() + Tf.Z());
+        fitB.SetQp0(fitB.Tr().GetQp());
 
-      fitF.Extrapolate(zMiddle, fld);
-      fitB.Extrapolate(zMiddle, fld);
+        unsigned short staf = lastStation[jTr];
 
-      fvec Chi2Tracks(0.);
-      FilterTracks(&(Tf.X()), &(Tf.C00()), &(Tb.X()), &(Tb.C00()), nullptr, nullptr, &Chi2Tracks);
-      if (Chi2Tracks[0] > 50) continue;
+        Tf.Set(extTracks[jTr].fParLast);
+        fitF.SetQp0(fitF.Tr().GetQp());
 
-      if (Chi2Tracks[0] < trackChi2[iTr] || Chi2Tracks[0] < trackChi2[jTr]) {
-        if (neighbour[iTr] < kNoNeighbour) {
-          neighbour[neighbour[iTr]]             = kNoNeighbour;
-          trackChi2[neighbour[iTr]]             = 100000.;
-          isDownstreamNeighbour[neighbour[iTr]] = false;
+        if (Tf.NdfTime()[0] >= 0. && Tb.NdfTime()[0] >= 0.) {
+          if (fabs(Tf.GetTime()[0] - Tb.GetTime()[0]) > 3 * sqrt(Tf.C55()[0] + Tb.C55()[0])) continue;
         }
-        if (neighbour[jTr] < kNoNeighbour) {
-          neighbour[neighbour[jTr]]             = kNoNeighbour;
-          trackChi2[neighbour[jTr]]             = 100000.;
-          isDownstreamNeighbour[neighbour[jTr]] = false;
+
+        unsigned short stam;
+
+        fBf = fParameters.GetStation(staf).fieldSlice.GetFieldValue(Tf.X(), Tf.Y());
+        fBb = fParameters.GetStation(stab).fieldSlice.GetFieldValue(Tb.X(), Tb.Y());
+
+        unsigned short dist = firstStation[iTr] - lastStation[jTr];
+
+        if (dist > 1)
+          stam = staf + 1;
+        else
+          stam = staf - 1;
+
+        fvec zm = fParameters.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     = fParameters.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());
+
+        fitF.Extrapolate(zMiddle, fld);
+        fitB.Extrapolate(zMiddle, fld);
+
+        fvec Chi2Tracks(0.);
+        FilterTracks(&(Tf.X()), &(Tf.C00()), &(Tb.X()), &(Tb.C00()), nullptr, nullptr, &Chi2Tracks);
+        if (Chi2Tracks[0] > 50) continue;
+
+        if (Chi2Tracks[0] < trackChi2[iTr] || Chi2Tracks[0] < trackChi2[jTr]) {
+          if (neighbour[iTr] < kNoNeighbour) {
+            neighbour[neighbour[iTr]]             = kNoNeighbour;
+            trackChi2[neighbour[iTr]]             = 100000.;
+            isDownstreamNeighbour[neighbour[iTr]] = false;
+          }
+          if (neighbour[jTr] < kNoNeighbour) {
+            neighbour[neighbour[jTr]]             = kNoNeighbour;
+            trackChi2[neighbour[jTr]]             = 100000.;
+            isDownstreamNeighbour[neighbour[jTr]] = false;
+          }
+          neighbour[iTr]             = jTr;
+          neighbour[jTr]             = iTr;
+          trackChi2[iTr]             = Chi2Tracks[0];
+          trackChi2[jTr]             = Chi2Tracks[0];
+          isDownstreamNeighbour[iTr] = true;
+          isDownstreamNeighbour[jTr] = false;
         }
-        neighbour[iTr]             = jTr;
-        neighbour[jTr]             = iTr;
-        trackChi2[iTr]             = Chi2Tracks[0];
-        trackChi2[jTr]             = Chi2Tracks[0];
-        isDownstreamNeighbour[iTr] = true;
-        isDownstreamNeighbour[jTr] = false;
       }
     }
-  }
 
-  for (int iTr = 0; iTr < nTracks; iTr++) {
-    if (isStored[iTr]) continue;
+    for (int iTr = 0; iTr < nTracks; iTr++) {
+      if (isStored[iTr]) continue;
 
-    fTracksNew.push_back(extTracks[iTr]);
-    if (!isDownstreamNeighbour[iTr]) {
-      for (ca::HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) {
-        fRecoHitsNew.push_back(extRecoHits[HI]);
+      fTracksNew.push_back(extTracks[iTr]);
+      if (!isDownstreamNeighbour[iTr]) {
+        for (ca::HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) {
+          fRecoHitsNew.push_back(extRecoHits[HI]);
+        }
       }
-    }
 
-    if (neighbour[iTr] < kNoNeighbour) {
-      isStored[neighbour[iTr]] = true;
-      fTracksNew.back().fNofHits += extTracks[neighbour[iTr]].fNofHits;
-      for (ca::HitIndex_t HI = firstHit[neighbour[iTr]]; HI <= lastHit[neighbour[iTr]]; HI++)
-        fRecoHitsNew.push_back(extRecoHits[HI]);
-    }
+      if (neighbour[iTr] < kNoNeighbour) {
+        isStored[neighbour[iTr]] = true;
+        fTracksNew.back().fNofHits += extTracks[neighbour[iTr]].fNofHits;
+        for (ca::HitIndex_t HI = firstHit[neighbour[iTr]]; HI <= lastHit[neighbour[iTr]]; HI++)
+          fRecoHitsNew.push_back(extRecoHits[HI]);
+      }
 
-    if (isDownstreamNeighbour[iTr]) {
-      for (ca::HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) {
-        fRecoHitsNew.push_back(extRecoHits[HI]);
+      if (isDownstreamNeighbour[iTr]) {
+        for (ca::HitIndex_t HI = firstHit[iTr]; HI <= lastHit[iTr]; HI++) {
+          fRecoHitsNew.push_back(extRecoHits[HI]);
+        }
       }
     }
-  }
 
-  // Save the merging results into external vectors
-  extTracks   = std::move(fTracksNew);
-  extRecoHits = std::move(fRecoHitsNew);
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-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++) {
-    if (W) W[i] = C[i];
-    S[i] = C[i] + V[i];
+    // Save the merging results into external vectors
+    extTracks   = std::move(fTracksNew);
+    extRecoHits = std::move(fRecoHitsNew);
   }
 
-  InvertCholesky(S);
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  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++) {
+      if (W) W[i] = C[i];
+      S[i] = C[i] + V[i];
+    }
 
-  fvec dzeta[5];
+    InvertCholesky(S);
 
-  for (int i = 0; i < 5; i++)
-    dzeta[i] = m[i] - r[i];
+    fvec dzeta[5];
 
-  if (W && R) {
     for (int i = 0; i < 5; i++)
-      R[i] = r[i];
-
-    fvec K[5][5];
-    MultiplySS(C, S, K);
-
-    fvec KC[15];
-    MultiplyMS(K, C, KC);
-    for (int i = 0; i < 15; i++)
-      W[i] -= KC[i];
+      dzeta[i] = m[i] - r[i];
+
+    if (W && R) {
+      for (int i = 0; i < 5; i++)
+        R[i] = r[i];
+
+      fvec K[5][5];
+      MultiplySS(C, S, K);
+
+      fvec KC[15];
+      MultiplyMS(K, C, KC);
+      for (int i = 0; i < 15; i++)
+        W[i] -= KC[i];
+
+      fvec kd;
+      for (int i = 0; i < 5; i++) {
+        kd = 0.f;
+        for (int j = 0; j < 5; j++)
+          kd += K[i][j] * dzeta[j];
+        R[i] += kd;
+      }
+    }
+    if (chi2) {
+      fvec S_dzeta[5];
+      MultiplySR(S, dzeta, S_dzeta);
+      *chi2 = dzeta[0] * S_dzeta[0] + dzeta[1] * S_dzeta[1] + dzeta[2] * S_dzeta[2] + dzeta[3] * S_dzeta[3]
+              + dzeta[4] * S_dzeta[4];
+    }
+  }
 
-    fvec kd;
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void CloneMerger::InvertCholesky(fvec a[15])
+  {
+    fvec d[5], uud, u[5][5];
     for (int i = 0; i < 5; i++) {
-      kd = 0.f;
+      d[i] = 0.f;
       for (int j = 0; j < 5; j++)
-        kd += K[i][j] * dzeta[j];
-      R[i] += kd;
+        u[i][j] = 0.f;
     }
-  }
-  if (chi2) {
-    fvec S_dzeta[5];
-    MultiplySR(S, dzeta, S_dzeta);
-    *chi2 = dzeta[0] * S_dzeta[0] + dzeta[1] * S_dzeta[1] + dzeta[2] * S_dzeta[2] + dzeta[3] * S_dzeta[3]
-            + dzeta[4] * S_dzeta[4];
-  }
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void CloneMerger::InvertCholesky(fvec a[15])
-{
-  fvec d[5], uud, u[5][5];
-  for (int i = 0; i < 5; i++) {
-    d[i] = 0.f;
-    for (int j = 0; j < 5; j++)
-      u[i][j] = 0.f;
-  }
-
-  for (int i = 0; i < 5; i++) {
-    uud = 0.f;
-    for (int j = 0; j < i; j++)
-      uud += u[j][i] * u[j][i] * d[j];
-    uud = a[i * (i + 3) / 2] - uud;
-
-    fvec smallval(1.e-12);
-    uud = iif(uud >= smallval, uud, smallval);
-
-    d[i]    = uud / kf::utils::fabs(uud);
-    u[i][i] = sqrt(kf::utils::fabs(uud));
 
-    for (int j = i + 1; j < 5; j++) {
+    for (int i = 0; i < 5; i++) {
       uud = 0.f;
-      for (int k = 0; k < i; k++)
-        uud += u[k][i] * u[k][j] * d[k];
-      uud     = a[j * (j + 1) / 2 + i] /*a[i][j]*/ - uud;
-      u[i][j] = d[i] / u[i][i] * uud;
+      for (int j = 0; j < i; j++)
+        uud += u[j][i] * u[j][i] * d[j];
+      uud = a[i * (i + 3) / 2] - uud;
+
+      fvec smallval(1.e-12);
+      uud = iif(uud >= smallval, uud, smallval);
+
+      d[i]    = uud / kf::utils::fabs(uud);
+      u[i][i] = sqrt(kf::utils::fabs(uud));
+
+      for (int j = i + 1; j < 5; j++) {
+        uud = 0.f;
+        for (int k = 0; k < i; k++)
+          uud += u[k][i] * u[k][j] * d[k];
+        uud     = a[j * (j + 1) / 2 + i] /*a[i][j]*/ - uud;
+        u[i][j] = d[i] / u[i][i] * uud;
+      }
     }
-  }
 
-  fvec u1[5];
+    fvec u1[5];
 
-  for (int i = 0; i < 5; i++) {
-    u1[i]   = u[i][i];
-    u[i][i] = 1.f / u[i][i];
+    for (int i = 0; i < 5; i++) {
+      u1[i]   = u[i][i];
+      u[i][i] = 1.f / u[i][i];
+    }
+    for (int i = 0; i < 4; i++) {
+      u[i][i + 1] = -u[i][i + 1] * u[i][i] * u[i + 1][i + 1];
+    }
+    for (int i = 0; i < 3; i++) {
+      u[i][i + 2] = u[i][i + 1] * u1[i + 1] * u[i + 1][i + 2] - u[i][i + 2] * u[i][i] * u[i + 2][i + 2];
+    }
+    for (int i = 0; i < 2; i++) {
+      u[i][i + 3] = u[i][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i][i + 3] * u[i][i] * u[i + 3][i + 3];
+      u[i][i + 3] -= u[i][i + 1] * u1[i + 1] * (u[i + 1][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i + 1][i + 3]);
+    }
+    u[0][4] = u[0][2] * u1[2] * u[2][4] - u[0][4] * u[0][0] * u[4][4];
+    u[0][4] += u[0][1] * u1[1] * (u[1][4] - u[1][3] * u1[3] * u[3][4] - u[1][2] * u1[2] * u[2][4]);
+    u[0][4] += u[3][4] * u1[3] * (u[0][3] - u1[2] * u[2][3] * (u[0][2] - u[0][1] * u1[1] * u[1][2]));
+
+    for (int i = 0; i < 5; i++)
+      a[i + 10] = u[i][4] * d[4] * u[4][4];
+    for (int i = 0; i < 4; i++)
+      a[i + 6] = u[i][3] * u[3][3] * d[3] + u[i][4] * u[3][4] * d[4];
+    for (int i = 0; i < 3; i++)
+      a[i + 3] = u[i][2] * u[2][2] * d[2] + u[i][3] * u[2][3] * d[3] + u[i][4] * u[2][4] * d[4];
+    for (int i = 0; i < 2; i++)
+      a[i + 1] =
+        u[i][1] * u[1][1] * d[1] + u[i][2] * u[1][2] * d[2] + u[i][3] * u[1][3] * d[3] + u[i][4] * u[1][4] * d[4];
+    a[0] = u[0][0] * u[0][0] * d[0] + u[0][1] * u[0][1] * d[1] + u[0][2] * u[0][2] * d[2] + u[0][3] * u[0][3] * d[3]
+           + u[0][4] * u[0][4] * d[4];
   }
-  for (int i = 0; i < 4; i++) {
-    u[i][i + 1] = -u[i][i + 1] * u[i][i] * u[i + 1][i + 1];
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  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];
+
+    K[1] = C[1][0] * V[0] + C[1][1] * V[1] + C[1][2] * V[3] + C[1][3] * V[6] + C[1][4] * V[10];
+    K[2] = C[1][0] * V[1] + C[1][1] * V[2] + C[1][2] * V[4] + C[1][3] * V[7] + C[1][4] * V[11];
+
+    K[3] = C[2][0] * V[0] + C[2][1] * V[1] + C[2][2] * V[3] + C[2][3] * V[6] + C[2][4] * V[10];
+    K[4] = C[2][0] * V[1] + C[2][1] * V[2] + C[2][2] * V[4] + C[2][3] * V[7] + C[2][4] * V[11];
+    K[5] = C[2][0] * V[3] + C[2][1] * V[4] + C[2][2] * V[5] + C[2][3] * V[8] + C[2][4] * V[12];
+
+    K[6] = C[3][0] * V[0] + C[3][1] * V[1] + C[3][2] * V[3] + C[3][3] * V[6] + C[3][4] * V[10];
+    K[7] = C[3][0] * V[1] + C[3][1] * V[2] + C[3][2] * V[4] + C[3][3] * V[7] + C[3][4] * V[11];
+    K[8] = C[3][0] * V[3] + C[3][1] * V[4] + C[3][2] * V[5] + C[3][3] * V[8] + C[3][4] * V[12];
+    K[9] = C[3][0] * V[6] + C[3][1] * V[7] + C[3][2] * V[8] + C[3][3] * V[9] + C[3][4] * V[13];
+
+    K[10] = C[4][0] * V[0] + C[4][1] * V[1] + C[4][2] * V[3] + C[4][3] * V[6] + C[4][4] * V[10];
+    K[11] = C[4][0] * V[1] + C[4][1] * V[2] + C[4][2] * V[4] + C[4][3] * V[7] + C[4][4] * V[11];
+    K[12] = C[4][0] * V[3] + C[4][1] * V[4] + C[4][2] * V[5] + C[4][3] * V[8] + C[4][4] * V[12];
+    K[13] = C[4][0] * V[6] + C[4][1] * V[7] + C[4][2] * V[8] + C[4][3] * V[9] + C[4][4] * V[13];
+    K[14] = C[4][0] * V[10] + C[4][1] * V[11] + C[4][2] * V[12] + C[4][3] * V[13] + C[4][4] * V[14];
   }
-  for (int i = 0; i < 3; i++) {
-    u[i][i + 2] = u[i][i + 1] * u1[i + 1] * u[i + 1][i + 2] - u[i][i + 2] * u[i][i] * u[i + 2][i + 2];
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  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];
+    r_out[2] = r_in[0] * C[3] + r_in[1] * C[4] + r_in[2] * C[5] + r_in[3] * C[8] + r_in[4] * C[12];
+    r_out[3] = r_in[0] * C[6] + r_in[1] * C[7] + r_in[2] * C[8] + r_in[3] * C[9] + r_in[4] * C[13];
+    r_out[4] = r_in[0] * C[10] + r_in[1] * C[11] + r_in[2] * C[12] + r_in[3] * C[13] + r_in[4] * C[14];
   }
-  for (int i = 0; i < 2; i++) {
-    u[i][i + 3] = u[i][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i][i + 3] * u[i][i] * u[i + 3][i + 3];
-    u[i][i + 3] -= u[i][i + 1] * u1[i + 1] * (u[i + 1][i + 2] * u1[i + 2] * u[i + 2][i + 3] - u[i + 1][i + 3]);
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  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];
+    K[0][2] = C[0] * V[3] + C[1] * V[4] + C[3] * V[5] + C[6] * V[8] + C[10] * V[12];
+    K[0][3] = C[0] * V[6] + C[1] * V[7] + C[3] * V[8] + C[6] * V[9] + C[10] * V[13];
+    K[0][4] = C[0] * V[10] + C[1] * V[11] + C[3] * V[12] + C[6] * V[13] + C[10] * V[14];
+
+    K[1][0] = C[1] * V[0] + C[2] * V[1] + C[4] * V[3] + C[7] * V[6] + C[11] * V[10];
+    K[1][1] = C[1] * V[1] + C[2] * V[2] + C[4] * V[4] + C[7] * V[7] + C[11] * V[11];
+    K[1][2] = C[1] * V[3] + C[2] * V[4] + C[4] * V[5] + C[7] * V[8] + C[11] * V[12];
+    K[1][3] = C[1] * V[6] + C[2] * V[7] + C[4] * V[8] + C[7] * V[9] + C[11] * V[13];
+    K[1][4] = C[1] * V[10] + C[2] * V[11] + C[4] * V[12] + C[7] * V[13] + C[11] * V[14];
+
+    K[2][0] = C[3] * V[0] + C[4] * V[1] + C[5] * V[3] + C[8] * V[6] + C[12] * V[10];
+    K[2][1] = C[3] * V[1] + C[4] * V[2] + C[5] * V[4] + C[8] * V[7] + C[12] * V[11];
+    K[2][2] = C[3] * V[3] + C[4] * V[4] + C[5] * V[5] + C[8] * V[8] + C[12] * V[12];
+    K[2][3] = C[3] * V[6] + C[4] * V[7] + C[5] * V[8] + C[8] * V[9] + C[12] * V[13];
+    K[2][4] = C[3] * V[10] + C[4] * V[11] + C[5] * V[12] + C[8] * V[13] + C[12] * V[14];
+
+    K[3][0] = C[6] * V[0] + C[7] * V[1] + C[8] * V[3] + C[9] * V[6] + C[13] * V[10];
+    K[3][1] = C[6] * V[1] + C[7] * V[2] + C[8] * V[4] + C[9] * V[7] + C[13] * V[11];
+    K[3][2] = C[6] * V[3] + C[7] * V[4] + C[8] * V[5] + C[9] * V[8] + C[13] * V[12];
+    K[3][3] = C[6] * V[6] + C[7] * V[7] + C[8] * V[8] + C[9] * V[9] + C[13] * V[13];
+    K[3][4] = C[6] * V[10] + C[7] * V[11] + C[8] * V[12] + C[9] * V[13] + C[13] * V[14];
+
+    K[4][0] = C[10] * V[0] + C[11] * V[1] + C[12] * V[3] + C[13] * V[6] + C[14] * V[10];
+    K[4][1] = C[10] * V[1] + C[11] * V[2] + C[12] * V[4] + C[13] * V[7] + C[14] * V[11];
+    K[4][2] = C[10] * V[3] + C[11] * V[4] + C[12] * V[5] + C[13] * V[8] + C[14] * V[12];
+    K[4][3] = C[10] * V[6] + C[11] * V[7] + C[12] * V[8] + C[13] * V[9] + C[14] * V[13];
+    K[4][4] = C[10] * V[10] + C[11] * V[11] + C[12] * V[12] + C[13] * V[13] + C[14] * V[14];
   }
-  u[0][4] = u[0][2] * u1[2] * u[2][4] - u[0][4] * u[0][0] * u[4][4];
-  u[0][4] += u[0][1] * u1[1] * (u[1][4] - u[1][3] * u1[3] * u[3][4] - u[1][2] * u1[2] * u[2][4]);
-  u[0][4] += u[3][4] * u1[3] * (u[0][3] - u1[2] * u[2][3] * (u[0][2] - u[0][1] * u1[1] * u[1][2]));
-
-  for (int i = 0; i < 5; i++)
-    a[i + 10] = u[i][4] * d[4] * u[4][4];
-  for (int i = 0; i < 4; i++)
-    a[i + 6] = u[i][3] * u[3][3] * d[3] + u[i][4] * u[3][4] * d[4];
-  for (int i = 0; i < 3; i++)
-    a[i + 3] = u[i][2] * u[2][2] * d[2] + u[i][3] * u[2][3] * d[3] + u[i][4] * u[2][4] * d[4];
-  for (int i = 0; i < 2; i++)
-    a[i + 1] =
-      u[i][1] * u[1][1] * d[1] + u[i][2] * u[1][2] * d[2] + u[i][3] * u[1][3] * d[3] + u[i][4] * u[1][4] * d[4];
-  a[0] = u[0][0] * u[0][0] * d[0] + u[0][1] * u[0][1] * d[1] + u[0][2] * u[0][2] * d[2] + u[0][3] * u[0][3] * d[3]
-         + u[0][4] * u[0][4] * d[4];
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void 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];
-
-  K[1] = C[1][0] * V[0] + C[1][1] * V[1] + C[1][2] * V[3] + C[1][3] * V[6] + C[1][4] * V[10];
-  K[2] = C[1][0] * V[1] + C[1][1] * V[2] + C[1][2] * V[4] + C[1][3] * V[7] + C[1][4] * V[11];
-
-  K[3] = C[2][0] * V[0] + C[2][1] * V[1] + C[2][2] * V[3] + C[2][3] * V[6] + C[2][4] * V[10];
-  K[4] = C[2][0] * V[1] + C[2][1] * V[2] + C[2][2] * V[4] + C[2][3] * V[7] + C[2][4] * V[11];
-  K[5] = C[2][0] * V[3] + C[2][1] * V[4] + C[2][2] * V[5] + C[2][3] * V[8] + C[2][4] * V[12];
-
-  K[6] = C[3][0] * V[0] + C[3][1] * V[1] + C[3][2] * V[3] + C[3][3] * V[6] + C[3][4] * V[10];
-  K[7] = C[3][0] * V[1] + C[3][1] * V[2] + C[3][2] * V[4] + C[3][3] * V[7] + C[3][4] * V[11];
-  K[8] = C[3][0] * V[3] + C[3][1] * V[4] + C[3][2] * V[5] + C[3][3] * V[8] + C[3][4] * V[12];
-  K[9] = C[3][0] * V[6] + C[3][1] * V[7] + C[3][2] * V[8] + C[3][3] * V[9] + C[3][4] * V[13];
-
-  K[10] = C[4][0] * V[0] + C[4][1] * V[1] + C[4][2] * V[3] + C[4][3] * V[6] + C[4][4] * V[10];
-  K[11] = C[4][0] * V[1] + C[4][1] * V[2] + C[4][2] * V[4] + C[4][3] * V[7] + C[4][4] * V[11];
-  K[12] = C[4][0] * V[3] + C[4][1] * V[4] + C[4][2] * V[5] + C[4][3] * V[8] + C[4][4] * V[12];
-  K[13] = C[4][0] * V[6] + C[4][1] * V[7] + C[4][2] * V[8] + C[4][3] * V[9] + C[4][4] * V[13];
-  K[14] = C[4][0] * V[10] + C[4][1] * V[11] + C[4][2] * V[12] + C[4][3] * V[13] + C[4][4] * V[14];
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void 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];
-  r_out[2] = r_in[0] * C[3] + r_in[1] * C[4] + r_in[2] * C[5] + r_in[3] * C[8] + r_in[4] * C[12];
-  r_out[3] = r_in[0] * C[6] + r_in[1] * C[7] + r_in[2] * C[8] + r_in[3] * C[9] + r_in[4] * C[13];
-  r_out[4] = r_in[0] * C[10] + r_in[1] * C[11] + r_in[2] * C[12] + r_in[3] * C[13] + r_in[4] * C[14];
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void 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];
-  K[0][2] = C[0] * V[3] + C[1] * V[4] + C[3] * V[5] + C[6] * V[8] + C[10] * V[12];
-  K[0][3] = C[0] * V[6] + C[1] * V[7] + C[3] * V[8] + C[6] * V[9] + C[10] * V[13];
-  K[0][4] = C[0] * V[10] + C[1] * V[11] + C[3] * V[12] + C[6] * V[13] + C[10] * V[14];
-
-  K[1][0] = C[1] * V[0] + C[2] * V[1] + C[4] * V[3] + C[7] * V[6] + C[11] * V[10];
-  K[1][1] = C[1] * V[1] + C[2] * V[2] + C[4] * V[4] + C[7] * V[7] + C[11] * V[11];
-  K[1][2] = C[1] * V[3] + C[2] * V[4] + C[4] * V[5] + C[7] * V[8] + C[11] * V[12];
-  K[1][3] = C[1] * V[6] + C[2] * V[7] + C[4] * V[8] + C[7] * V[9] + C[11] * V[13];
-  K[1][4] = C[1] * V[10] + C[2] * V[11] + C[4] * V[12] + C[7] * V[13] + C[11] * V[14];
-
-  K[2][0] = C[3] * V[0] + C[4] * V[1] + C[5] * V[3] + C[8] * V[6] + C[12] * V[10];
-  K[2][1] = C[3] * V[1] + C[4] * V[2] + C[5] * V[4] + C[8] * V[7] + C[12] * V[11];
-  K[2][2] = C[3] * V[3] + C[4] * V[4] + C[5] * V[5] + C[8] * V[8] + C[12] * V[12];
-  K[2][3] = C[3] * V[6] + C[4] * V[7] + C[5] * V[8] + C[8] * V[9] + C[12] * V[13];
-  K[2][4] = C[3] * V[10] + C[4] * V[11] + C[5] * V[12] + C[8] * V[13] + C[12] * V[14];
-
-  K[3][0] = C[6] * V[0] + C[7] * V[1] + C[8] * V[3] + C[9] * V[6] + C[13] * V[10];
-  K[3][1] = C[6] * V[1] + C[7] * V[2] + C[8] * V[4] + C[9] * V[7] + C[13] * V[11];
-  K[3][2] = C[6] * V[3] + C[7] * V[4] + C[8] * V[5] + C[9] * V[8] + C[13] * V[12];
-  K[3][3] = C[6] * V[6] + C[7] * V[7] + C[8] * V[8] + C[9] * V[9] + C[13] * V[13];
-  K[3][4] = C[6] * V[10] + C[7] * V[11] + C[8] * V[12] + C[9] * V[13] + C[13] * V[14];
-
-  K[4][0] = C[10] * V[0] + C[11] * V[1] + C[12] * V[3] + C[13] * V[6] + C[14] * V[10];
-  K[4][1] = C[10] * V[1] + C[11] * V[2] + C[12] * V[4] + C[13] * V[7] + C[14] * V[11];
-  K[4][2] = C[10] * V[3] + C[11] * V[4] + C[12] * V[5] + C[13] * V[8] + C[14] * V[12];
-  K[4][3] = C[10] * V[6] + C[11] * V[7] + C[12] * V[8] + C[13] * V[9] + C[14] * V[13];
-  K[4][4] = C[10] * V[10] + C[11] * V[11] + C[12] * V[12] + C[13] * V[13] + C[14] * V[14];
-}
+}  // namespace cbm::algo::ca
\ No newline at end of file
diff --git a/algo/ca/core/tracking/CaFramework.cxx b/algo/ca/core/tracking/CaFramework.cxx
index 422f282f51704d1985bf7002af116d82322dc115..7d06bc85d4ee58074d5d46d12ec80beb5d7bf81a 100644
--- a/algo/ca/core/tracking/CaFramework.cxx
+++ b/algo/ca/core/tracking/CaFramework.cxx
@@ -14,80 +14,71 @@
 #include <sstream>
 #include <thread>
 
-using namespace cbm::algo::ca;
-
-namespace
-{
-  using namespace cbm::algo;  // to keep ca:: prefixes in the code
-}
-
-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::algo::ca::Track;
-using constants::phys::ProtonMassD;
-using constants::phys::SpeedOfLightInv;
-using constants::phys::SpeedOfLightInvD;
-//using cbm::ca::tools::Debugger;
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void Framework::Init(const TrackingMode mode)
+namespace cbm::algo::ca
 {
-  fpTrackFinder =
-    std::make_unique<ca::TrackFinder>(fParameters, fDefaultMass, mode, fMonitorData, fNofThreads, fCaRecoTime);
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void Framework::Finish()
-{
-  //Debugger::Instance().Write();
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void Framework::ReceiveInputData(InputData&& inputData)
-{
-  // ----- Get input data ----------------------------------------------------------------------------------------------
-  fInputData = std::move(inputData);
-}
-
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void Framework::ReceiveParameters(Parameters<fvec>&& parameters)
-{
-  fParameters          = std::move(parameters);
-  fNstationsBeforePipe = fParameters.GetNstationsActive(static_cast<EDetectorID>(0));
-
-  kf::GlobalField::ForceUseOfOriginalField(fParameters.DevIsUseOfOriginalField());
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-int Framework::GetMcTrackIdForCaHit(int /*iHit*/)
-{
-  return -1;
-  /*
-  int hitId    = iHit;
-  int iMcPoint = CbmL1::Instance()->GetHitBestMcRefs()[hitId];
-  if (iMcPoint < 0) return -1;
-  return CbmL1::Instance()->GetMcPoints()[iMcPoint].ID;
-  */
-}
-
-int Framework::GetMcTrackIdForWindowHit(int /*iHit*/)
-{
-  return -1;
-  /*
-  int hitId    = fWindowHits[iHit].Id();
-  int iMcPoint = CbmL1::Instance()->GetHitBestMcRefs()[hitId];
-  if (iMcPoint < 0) return -1;
-  return CbmL1::Instance()->GetMcPoints()[iMcPoint].ID;
-  */
-}
-
+  using constants::phys::ProtonMassD;
+  using constants::phys::SpeedOfLightInv;
+  using constants::phys::SpeedOfLightInvD;
+  //using cbm::ca::tools::Debugger;
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void Framework::Init(const TrackingMode mode)
+  {
+    fpTrackFinder =
+      std::make_unique<ca::TrackFinder>(fParameters, fDefaultMass, mode, fMonitorData, fNofThreads, fCaRecoTime);
+  }
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void Framework::Finish()
+  {
+    //Debugger::Instance().Write();
+  }
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void Framework::ReceiveInputData(InputData&& inputData)
+  {
+    // ----- Get input data --------------------------------------------------------------------------------------------
+    fInputData = std::move(inputData);
+  }
+
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void Framework::ReceiveParameters(Parameters<fvec>&& parameters)
+  {
+    fParameters          = std::move(parameters);
+    fNstationsBeforePipe = fParameters.GetNstationsActive(static_cast<EDetectorID>(0));
+
+    kf::GlobalField::ForceUseOfOriginalField(fParameters.DevIsUseOfOriginalField());
+  }
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  int Framework::GetMcTrackIdForCaHit(int /*iHit*/)
+  {
+    return -1;
+    /*
+    int hitId    = iHit;
+    int iMcPoint = CbmL1::Instance()->GetHitBestMcRefs()[hitId];
+    if (iMcPoint < 0) return -1;
+    return CbmL1::Instance()->GetMcPoints()[iMcPoint].ID;
+    */
+  }
+
+  int Framework::GetMcTrackIdForWindowHit(int /*iHit*/)
+  {
+    return -1;
+    /*
+    int hitId    = fWindowHits[iHit].Id();
+    int iMcPoint = CbmL1::Instance()->GetHitBestMcRefs()[hitId];
+    if (iMcPoint < 0) return -1;
+    return CbmL1::Instance()->GetMcPoints()[iMcPoint].ID;
+    */
+  }
+}  // namespace cbm::algo::ca
 /*
 const CbmL1MCTrack* Framework::GetMcTrackForWindowHit(int iHit) const
 {
diff --git a/algo/ca/core/tracking/CaTrackExtender.cxx b/algo/ca/core/tracking/CaTrackExtender.cxx
index 30e19df12ba888da2cfa91b95088a17d40960d20..e05c6d3296027a02a0e4422e98a2822db236c270 100644
--- a/algo/ca/core/tracking/CaTrackExtender.cxx
+++ b/algo/ca/core/tracking/CaTrackExtender.cxx
@@ -18,316 +18,315 @@
 
 #include <iostream>
 
-using cbm::algo::ca::Vector;  // TMP!!
 
-using namespace cbm::algo::ca;
+namespace cbm::algo::ca
+{
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  TrackExtender::TrackExtender(const ca::Parameters<fvec>& pars, const fscal mass)
+    : fParameters(pars)
+    , fSetup(fParameters.GetActiveSetup())
+    , fDefaultMass(mass)
+  {
+  }
 
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-TrackExtender::TrackExtender(const ca::Parameters<fvec>& pars, const fscal mass)
-  : fParameters(pars)
-  , fSetup(fParameters.GetActiveSetup())
-  , fDefaultMass(mass)
-{
-}
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  TrackExtender::~TrackExtender() {}
 
+  // -------------------------------------------------------------------------------------------------------------------
+  //
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-TrackExtender::~TrackExtender() {}
+  void TrackExtender::FitBranchFast(const ca::Branch& t, TrackParamV& Tout, const kf::FitDirection direction,
+                                    const fvec qp0, const bool initParams)
+  {
+    CBMCA_DEBUG_ASSERT(t.NHits >= 3);
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
+    kf::TrackKalmanFilter<fvec> fit;
+    fit.SetParticleMass(fDefaultMass);
+    fit.SetMask(fmask::One());
+    fit.SetTrack(Tout);
+    TrackParamV& T = fit.Tr();
 
-void TrackExtender::FitBranchFast(const ca::Branch& t, TrackParamV& Tout, const kf::FitDirection direction,
-                                  const fvec qp0, const bool initParams)
-{
-  CBMCA_DEBUG_ASSERT(t.NHits >= 3);
-
-  kf::TrackKalmanFilter<fvec> fit;
-  fit.SetParticleMass(fDefaultMass);
-  fit.SetMask(fmask::One());
-  fit.SetTrack(Tout);
-  TrackParamV& T = fit.Tr();
-
-  // get hits of current track
-  const Vector<ca::HitIndex_t>& hits = t.Hits();  // array of indeses of hits of current track
-  const int nHits                    = t.NofHits();
-
-  const signed short int step = (direction == kf::FitDirection::kUpstream ? -1 : 1);  // increment for station index
-  const int iFirstHit         = (direction == kf::FitDirection::kUpstream) ? nHits - 1 : 0;
-  const int iLastHit          = (direction == kf::FitDirection::kUpstream) ? 0 : nHits - 1;
-
-  const ca::Hit& hit0 = frWData->Hit(hits[iFirstHit]);
-  const ca::Hit& hit1 = frWData->Hit(hits[iFirstHit + step]);
-  const ca::Hit& hit2 = frWData->Hit(hits[iFirstHit + 2 * step]);
-
-  int ista0 = hit0.Station();
-  int ista1 = hit1.Station();
-  int ista2 = hit2.Station();
-
-  const ca::Station<fvec>& sta0 = fParameters.GetStation(ista0);
-  const ca::Station<fvec>& sta1 = fParameters.GetStation(ista1);
-  const ca::Station<fvec>& sta2 = fParameters.GetStation(ista2);
-
-  fvec x0 = hit0.X();
-  fvec y0 = hit0.Y();
-  fvec z0 = hit0.Z();
-
-  fvec x1 = hit1.X();
-  fvec y1 = hit1.Y();
-  fvec z1 = hit1.Z();
-
-  fvec x2 = hit2.X();
-  fvec y2 = hit2.Y();
-
-  T.X() = x0;
-  T.Y() = y0;
-  if (initParams) {
-    fvec dzi = fvec(1.) / (z1 - z0);
-    T.Tx()   = (x1 - x0) * dzi;
-    T.Ty()   = (y1 - y0) * dzi;
-    T.Qp()   = qp0;
-  }
-  fit.SetQp0(qp0);
+    // get hits of current track
+    const Vector<ca::HitIndex_t>& hits = t.Hits();  // array of indeses of hits of current track
+    const int nHits                    = t.NofHits();
 
-  T.Z()    = z0;
-  T.Time() = hit0.T();
-  T.Vi()   = 0.;
+    const signed short int step = (direction == kf::FitDirection::kUpstream ? -1 : 1);  // increment for station index
+    const int iFirstHit         = (direction == kf::FitDirection::kUpstream) ? nHits - 1 : 0;
+    const int iLastHit          = (direction == kf::FitDirection::kUpstream) ? 0 : nHits - 1;
 
-  T.ResetErrors(1., 1., .1, .1, 1., (sta0.timeInfo ? hit0.dT2() : 1.e6), 1.e6);
-  T.Ndf()     = fvec(2.);
-  T.NdfTime() = sta0.timeInfo ? fvec(-1.) : fvec(-2.);
+    const ca::Hit& hit0 = frWData->Hit(hits[iFirstHit]);
+    const ca::Hit& hit1 = frWData->Hit(hits[iFirstHit + step]);
+    const ca::Hit& hit2 = frWData->Hit(hits[iFirstHit + 2 * step]);
 
-  T.C00() = hit0.dX2();
-  T.C10() = hit0.dXY();
-  T.C11() = hit0.dY2();
+    int ista0 = hit0.Station();
+    int ista1 = hit1.Station();
+    int ista2 = hit2.Station();
 
-  kf::FieldRegion<fvec> fld _fvecalignment;
-  fvec fldZ0 = sta1.fZ;  // suppose field is smoth
-  fvec fldZ1 = sta2.fZ;
-  fvec fldZ2 = sta0.fZ;
+    const ca::Station<fvec>& sta0 = fParameters.GetStation(ista0);
+    const ca::Station<fvec>& sta1 = fParameters.GetStation(ista1);
+    const ca::Station<fvec>& sta2 = fParameters.GetStation(ista2);
 
+    fvec x0 = hit0.X();
+    fvec y0 = hit0.Y();
+    fvec z0 = hit0.Z();
 
-  kf::FieldValue fldB0 = sta1.fieldSlice.GetFieldValue(x1, y1);
-  kf::FieldValue fldB1 = sta2.fieldSlice.GetFieldValue(x2, y2);
-  kf::FieldValue fldB2 = sta0.fieldSlice.GetFieldValue(x0, y0);
+    fvec x1 = hit1.X();
+    fvec y1 = hit1.Y();
+    fvec z1 = hit1.Z();
 
-  fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
+    fvec x2 = hit2.X();
+    fvec y2 = hit2.Y();
 
-  for (int i = iFirstHit + step; step * i <= step * iLastHit; i += step) {
-    const ca::Hit& hit           = frWData->Hit(hits[i]);
-    int ista                     = hit.Station();
-    const ca::Station<fvec>& sta = fParameters.GetStation(ista);
+    T.X() = x0;
+    T.Y() = y0;
+    if (initParams) {
+      fvec dzi = fvec(1.) / (z1 - z0);
+      T.Tx()   = (x1 - x0) * dzi;
+      T.Ty()   = (y1 - y0) * dzi;
+      T.Qp()   = qp0;
+    }
+    fit.SetQp0(qp0);
 
-    fit.Extrapolate(hit.Z(), fld);
-    ca::utils::FilterHit(fit, hit, fmask(sta.timeInfo));
-    auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(T.X(), T.Y());
-    fit.MultipleScattering(radThick);
-    fit.EnergyLossCorrection(radThick, direction);
+    T.Z()    = z0;
+    T.Time() = hit0.T();
+    T.Vi()   = 0.;
 
-    fldB0 = fldB1;
-    fldB1 = fldB2;
-    fldZ0 = fldZ1;
-    fldZ1 = fldZ2;
-    fldB2 = sta.fieldSlice.GetFieldValue(hit.X(), hit.Y());
-    fldZ2 = sta.fZ;
-    fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
-  }  // i
+    T.ResetErrors(1., 1., .1, .1, 1., (sta0.timeInfo ? hit0.dT2() : 1.e6), 1.e6);
+    T.Ndf()     = fvec(2.);
+    T.NdfTime() = sta0.timeInfo ? fvec(-1.) : fvec(-2.);
 
-  Tout = T;
-}  // void ca::Framework::BranchFitterFast
+    T.C00() = hit0.dX2();
+    T.C10() = hit0.dXY();
+    T.C11() = hit0.dY2();
 
-/// like BranchFitterFast but more precise
-void TrackExtender::FitBranch(const ca::Branch& t, TrackParamV& T, const kf::FitDirection direction, const fvec qp0,
-                              const bool initParams)
-{
-  FitBranchFast(t, T, direction, qp0, initParams);
-  for (int i = 0; i < 1; i++) {
-    FitBranchFast(t, T, !direction, T.Qp(), false);
-    FitBranchFast(t, T, direction, T.Qp(), false);
-  }
-}  // void ca::Framework::BranchFitter
+    kf::FieldRegion<fvec> fld _fvecalignment;
+    fvec fldZ0 = sta1.fZ;  // suppose field is smoth
+    fvec fldZ1 = sta2.fZ;
+    fvec fldZ2 = sta0.fZ;
 
 
-void TrackExtender::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const kf::FitDirection direction, const fvec qp0)
-{
-  Vector<ca::HitIndex_t> newHits{"ca::TrackExtender::newHits"};
-  newHits.reserve(fParameters.GetNstationsActive());
+    kf::FieldValue fldB0 = sta1.fieldSlice.GetFieldValue(x1, y1);
+    kf::FieldValue fldB1 = sta2.fieldSlice.GetFieldValue(x2, y2);
+    kf::FieldValue fldB2 = sta0.fieldSlice.GetFieldValue(x0, y0);
 
-  kf::TrackKalmanFilter<fvec> fit;
-  fit.SetParticleMass(fDefaultMass);
-  fit.SetMask(fmask::One());
-  fit.SetTrack(Tout);
-  fit.SetQp0(qp0);
+    fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
 
-  const signed short int step = (direction == kf::FitDirection::kUpstream) ? -1 : 1;  // increment for station index
-  const int iFirstHit         = (direction == kf::FitDirection::kUpstream) ? 2 : t.NofHits() - 3;
-  //  int ista = fInputData->GetHit(t.Hits[iFirstHit]).iSt + 2 * step; // current station. set to the end of track
+    for (int i = iFirstHit + step; step * i <= step * iLastHit; i += step) {
+      const ca::Hit& hit           = frWData->Hit(hits[i]);
+      int ista                     = hit.Station();
+      const ca::Station<fvec>& sta = fParameters.GetStation(ista);
+
+      fit.Extrapolate(hit.Z(), fld);
+      ca::utils::FilterHit(fit, hit, fmask(sta.timeInfo));
+      auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(T.X(), T.Y());
+      fit.MultipleScattering(radThick);
+      fit.EnergyLossCorrection(radThick, direction);
+
+      fldB0 = fldB1;
+      fldB1 = fldB2;
+      fldZ0 = fldZ1;
+      fldZ1 = fldZ2;
+      fldB2 = sta.fieldSlice.GetFieldValue(hit.X(), hit.Y());
+      fldZ2 = sta.fZ;
+      fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
+    }  // i
+
+    Tout = T;
+  }  // void ca::Framework::BranchFitterFast
+
+  /// like BranchFitterFast but more precise
+  void TrackExtender::FitBranch(const ca::Branch& t, TrackParamV& T, const kf::FitDirection direction, const fvec qp0,
+                                const bool initParams)
+  {
+    FitBranchFast(t, T, direction, qp0, initParams);
+    for (int i = 0; i < 1; i++) {
+      FitBranchFast(t, T, !direction, T.Qp(), false);
+      FitBranchFast(t, T, direction, T.Qp(), false);
+    }
+  }  // void ca::Framework::BranchFitter
 
-  const ca::Hit& hit0 = frWData->Hit(t.Hits()[iFirstHit]);  // optimize
-  const ca::Hit& hit1 = frWData->Hit(t.Hits()[iFirstHit + step]);
-  const ca::Hit& hit2 = frWData->Hit(t.Hits()[iFirstHit + 2 * step]);
 
-  const int ista0 = hit0.Station();
-  const int ista1 = hit1.Station();
-  const int ista2 = hit2.Station();
+  void TrackExtender::FindMoreHits(ca::Branch& t, TrackParamV& Tout, const kf::FitDirection direction, const fvec qp0)
+  {
+    Vector<ca::HitIndex_t> newHits{"ca::TrackExtender::newHits"};
+    newHits.reserve(fParameters.GetNstationsActive());
 
-  const ca::Station<fvec>& sta0 = fParameters.GetStation(ista0);
-  const ca::Station<fvec>& sta1 = fParameters.GetStation(ista1);
-  const ca::Station<fvec>& sta2 = fParameters.GetStation(ista2);
+    kf::TrackKalmanFilter<fvec> fit;
+    fit.SetParticleMass(fDefaultMass);
+    fit.SetMask(fmask::One());
+    fit.SetTrack(Tout);
+    fit.SetQp0(qp0);
 
-  fvec x0 = hit0.X();
-  fvec y0 = hit0.Y();
+    const signed short int step = (direction == kf::FitDirection::kUpstream) ? -1 : 1;  // increment for station index
+    const int iFirstHit         = (direction == kf::FitDirection::kUpstream) ? 2 : t.NofHits() - 3;
+    //  int ista = fInputData->GetHit(t.Hits[iFirstHit]).iSt + 2 * step; // current station. set to the end of track
 
-  fvec x1 = hit1.X();
-  fvec y1 = hit1.Y();
+    const ca::Hit& hit0 = frWData->Hit(t.Hits()[iFirstHit]);  // optimize
+    const ca::Hit& hit1 = frWData->Hit(t.Hits()[iFirstHit + step]);
+    const ca::Hit& hit2 = frWData->Hit(t.Hits()[iFirstHit + 2 * step]);
 
-  fvec x2 = hit2.X();
-  fvec y2 = hit2.Y();
+    const int ista0 = hit0.Station();
+    const int ista1 = hit1.Station();
+    const int ista2 = hit2.Station();
 
-  kf::FieldRegion<fvec> fld _fvecalignment;
-  fvec fldZ0 = sta1.fZ;
-  fvec fldZ1 = sta2.fZ;
-  fvec fldZ2 = sta0.fZ;
+    const ca::Station<fvec>& sta0 = fParameters.GetStation(ista0);
+    const ca::Station<fvec>& sta1 = fParameters.GetStation(ista1);
+    const ca::Station<fvec>& sta2 = fParameters.GetStation(ista2);
 
-  kf::FieldValue fldB0 = sta1.fieldSlice.GetFieldValue(x1, y1);
-  kf::FieldValue fldB1 = sta2.fieldSlice.GetFieldValue(x2, y2);
-  kf::FieldValue fldB2 = sta0.fieldSlice.GetFieldValue(x0, y0);
+    fvec x0 = hit0.X();
+    fvec y0 = hit0.Y();
 
-  fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
+    fvec x1 = hit1.X();
+    fvec y1 = hit1.Y();
 
-  int ista = ista2 + 2 * step;  // skip one station. if there would be hit it has to be found on previous stap
+    fvec x2 = hit2.X();
+    fvec y2 = hit2.Y();
 
-  if (ista2 == frWData->CurrentIteration()->GetFirstStationIndex()) ista = ista2 + step;
+    kf::FieldRegion<fvec> fld _fvecalignment;
+    fvec fldZ0 = sta1.fZ;
+    fvec fldZ1 = sta2.fZ;
+    fvec fldZ2 = sta0.fZ;
 
-  const fscal pickGather = frWData->CurrentIteration()->GetPickGather();
-  const fvec pickGather2 = pickGather * pickGather;
-  const fvec maxDZ       = frWData->CurrentIteration()->GetMaxDZ();
-  for (; (ista < fParameters.GetNstationsActive()) && (ista >= 0); ista += step) {  // CHECKME why ista2?
+    kf::FieldValue fldB0 = sta1.fieldSlice.GetFieldValue(x1, y1);
+    kf::FieldValue fldB1 = sta2.fieldSlice.GetFieldValue(x2, y2);
+    kf::FieldValue fldB2 = sta0.fieldSlice.GetFieldValue(x0, y0);
 
-    const ca::Station<fvec>& sta = fParameters.GetStation(ista);
+    fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
 
-    fit.Extrapolate(sta.fZ, fld);
+    int ista = ista2 + 2 * step;  // skip one station. if there would be hit it has to be found on previous stap
 
-    fscal r2_best = 1e8;  // best distance to hit
-    int iHit_best = -1;   // index of the best hit
+    if (ista2 == frWData->CurrentIteration()->GetFirstStationIndex()) ista = ista2 + step;
 
-    TrackParamV& tr = fit.Tr();
+    const fscal pickGather = frWData->CurrentIteration()->GetPickGather();
+    const fvec pickGather2 = pickGather * pickGather;
+    const fvec maxDZ       = frWData->CurrentIteration()->GetMaxDZ();
+    for (; (ista < fParameters.GetNstationsActive()) && (ista >= 0); ista += step) {  // CHECKME why ista2?
 
-    const auto& grid = frWData->Grid(ista);
-    ca::GridArea area(grid, tr.X()[0], tr.Y()[0],
-                      (sqrt(pickGather * tr.C00()) + grid.GetMaxRangeX() + maxDZ * kf::utils::fabs(tr.Tx()))[0],
-                      (sqrt(pickGather * tr.C11()) + grid.GetMaxRangeY() + maxDZ * kf::utils::fabs(tr.Ty()))[0]);
+      const ca::Station<fvec>& sta = fParameters.GetStation(ista);
 
-    if (fParameters.DevIsIgnoreHitSearchAreas()) {
-      area.DoLoopOverEntireGrid();
-    }
+      fit.Extrapolate(sta.fZ, fld);
 
-    ca::HitIndex_t ih = 0;
+      fscal r2_best = 1e8;  // best distance to hit
+      int iHit_best = -1;   // index of the best hit
 
-    while (area.GetNextObjectId(ih)) {  // loop over the hits in the area
+      TrackParamV& tr = fit.Tr();
 
-      if (frWData->IsHitSuppressed(ih)) {
-        continue;
-      }
-      const ca::Hit& hit = frWData->Hit(ih);
+      const auto& grid = frWData->Grid(ista);
+      ca::GridArea area(grid, tr.X()[0], tr.Y()[0],
+                        (sqrt(pickGather * tr.C00()) + grid.GetMaxRangeX() + maxDZ * kf::utils::fabs(tr.Tx()))[0],
+                        (sqrt(pickGather * tr.C11()) + grid.GetMaxRangeY() + maxDZ * kf::utils::fabs(tr.Ty()))[0]);
 
-      if (sta.timeInfo && tr.NdfTime()[0] > -2.) {
-        fscal dt = hit.T() - tr.Time()[0];
-        if (fabs(dt) > sqrt(25. * tr.C55()[0]) + hit.RangeT()) continue;
+      if (fParameters.DevIsIgnoreHitSearchAreas()) {
+        area.DoLoopOverEntireGrid();
       }
 
-      //if (GetFUsed((*fStripFlag)[hit.f] | (*fStripFlag)[hit.b])) continue;  // if used
+      ca::HitIndex_t ih = 0;
 
-      if (frWData->IsHitKeyUsed(hit.FrontKey()) || frWData->IsHitKeyUsed(hit.BackKey())) {
-        continue;
-      }
+      while (area.GetNextObjectId(ih)) {  // loop over the hits in the area
 
-      auto [y, C11] = fit.ExtrapolateLineYdY2(hit.Z());
+        if (frWData->IsHitSuppressed(ih)) {
+          continue;
+        }
+        const ca::Hit& hit = frWData->Hit(ih);
 
-      //   fscal dym_est = ( fPickGather * sqrt(fabs(C11[0]+sta.XYInfo.C11[0])) );
-      //   fscal y_minus_new = y[0] - dym_est;
-      // if (yh < y_minus_new) continue;  // CHECKME take into account overlaping?
+        if (sta.timeInfo && tr.NdfTime()[0] > -2.) {
+          fscal dt = hit.T() - tr.Time()[0];
+          if (fabs(dt) > sqrt(25. * tr.C55()[0]) + hit.RangeT()) continue;
+        }
 
-      auto [x, C00] = fit.ExtrapolateLineXdX2(hit.Z());
+        //if (GetFUsed((*fStripFlag)[hit.f] | (*fStripFlag)[hit.b])) continue;  // if used
 
-      fscal d_x = hit.X() - x[0];
-      fscal d_y = hit.Y() - y[0];
-      fscal d2  = d_x * d_x + d_y * d_y;
-      if (d2 > r2_best) continue;
-      fscal dxm_est = sqrt(pickGather2 * C00)[0] + grid.GetMaxRangeX();
-      if (fabs(d_x) > dxm_est) continue;
+        if (frWData->IsHitKeyUsed(hit.FrontKey()) || frWData->IsHitKeyUsed(hit.BackKey())) {
+          continue;
+        }
 
-      fscal dym_est = sqrt(pickGather2 * C11)[0] + grid.GetMaxRangeY();
-      if (fabs(d_y) > dym_est) continue;
+        auto [y, C11] = fit.ExtrapolateLineYdY2(hit.Z());
 
-      r2_best   = d2;
-      iHit_best = ih;
-    }
+        //   fscal dym_est = ( fPickGather * sqrt(fabs(C11[0]+sta.XYInfo.C11[0])) );
+        //   fscal y_minus_new = y[0] - dym_est;
+        // if (yh < y_minus_new) continue;  // CHECKME take into account overlaping?
 
-    if (iHit_best < 0) break;
+        auto [x, C00] = fit.ExtrapolateLineXdX2(hit.Z());
 
+        fscal d_x = hit.X() - x[0];
+        fscal d_y = hit.Y() - y[0];
+        fscal d2  = d_x * d_x + d_y * d_y;
+        if (d2 > r2_best) continue;
+        fscal dxm_est = sqrt(pickGather2 * C00)[0] + grid.GetMaxRangeX();
+        if (fabs(d_x) > dxm_est) continue;
 
-    const ca::Hit& hit = frWData->Hit(iHit_best);
-    newHits.push_back(iHit_best);
+        fscal dym_est = sqrt(pickGather2 * C11)[0] + grid.GetMaxRangeY();
+        if (fabs(d_y) > dym_est) continue;
 
-    fit.Extrapolate(hit.Z(), fld);
-    ca::utils::FilterHit(fit, hit, fmask(sta.timeInfo));
-    auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(tr.X(), tr.Y());
-    fit.MultipleScattering(radThick);
-    fit.EnergyLossCorrection(radThick, direction);
+        r2_best   = d2;
+        iHit_best = ih;
+      }
 
-    fldB0 = fldB1;
-    fldB1 = fldB2;
-    fldZ0 = fldZ1;
-    fldZ1 = fldZ2;
-    fldB2 = sta.fieldSlice.GetFieldValue(hit.X(), hit.Y());
-    fldZ2 = sta.fZ;
-    fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
-  }
+      if (iHit_best < 0) break;
 
-  // save hits
-  const unsigned int NOldHits = t.NofHits();
-  const unsigned int NNewHits = newHits.size();
-  t.RefHits().enlarge(NNewHits + NOldHits);
 
-  if (direction == kf::FitDirection::kUpstream) {
-    for (int i = NOldHits - 1; i >= 0; i--) {
-      t.RefHits()[NNewHits + i] = t.RefHits()[i];
+      const ca::Hit& hit = frWData->Hit(iHit_best);
+      newHits.push_back(iHit_best);
+
+      fit.Extrapolate(hit.Z(), fld);
+      ca::utils::FilterHit(fit, hit, fmask(sta.timeInfo));
+      auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(tr.X(), tr.Y());
+      fit.MultipleScattering(radThick);
+      fit.EnergyLossCorrection(radThick, direction);
+
+      fldB0 = fldB1;
+      fldB1 = fldB2;
+      fldZ0 = fldZ1;
+      fldZ1 = fldZ2;
+      fldB2 = sta.fieldSlice.GetFieldValue(hit.X(), hit.Y());
+      fldZ2 = sta.fZ;
+      fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
     }
-    for (unsigned int i = 0, ii = NNewHits - 1; i < NNewHits; i++, ii--) {
-      t.RefHits()[i] = newHits[ii];
+
+    // save hits
+    const unsigned int NOldHits = t.NofHits();
+    const unsigned int NNewHits = newHits.size();
+    t.RefHits().enlarge(NNewHits + NOldHits);
+
+    if (direction == kf::FitDirection::kUpstream) {
+      for (int i = NOldHits - 1; i >= 0; i--) {
+        t.RefHits()[NNewHits + i] = t.RefHits()[i];
+      }
+      for (unsigned int i = 0, ii = NNewHits - 1; i < NNewHits; i++, ii--) {
+        t.RefHits()[i] = newHits[ii];
+      }
     }
-  }
-  else {  // downstream
-    for (unsigned int i = 0; i < newHits.size(); i++) {
-      t.RefHits()[NOldHits + i] = newHits[i];
+    else {  // downstream
+      for (unsigned int i = 0; i < newHits.size(); i++) {
+        t.RefHits()[NOldHits + i] = newHits[i];
+      }
     }
-  }
 
-  Tout = fit.Tr();
+    Tout = fit.Tr();
 
-}  // void ca::Framework::FindMoreHits
+  }  // void ca::Framework::FindMoreHits
 
-/// Try to extrapolate and find additional hits on other stations
-fscal TrackExtender::ExtendBranch(ca::Branch& t, WindowData& wData)
-{
-  frWData = &wData;
-  //   const unsigned int minNHits = 3;
+  /// Try to extrapolate and find additional hits on other stations
+  fscal TrackExtender::ExtendBranch(ca::Branch& t, WindowData& wData)
+  {
+    frWData = &wData;
+    //   const unsigned int minNHits = 3;
 
-  TrackParamV T;
+    TrackParamV T;
 
-  // downstream
+    // downstream
 
-  FitBranch(t, T, kf::FitDirection::kDownstream, 0.0);
-  FindMoreHits(t, T, kf::FitDirection::kDownstream, T.Qp());
+    FitBranch(t, T, kf::FitDirection::kDownstream, 0.0);
+    FindMoreHits(t, T, kf::FitDirection::kDownstream, T.Qp());
 
-  // upstream
+    // upstream
 
-  FitBranchFast(t, T, kf::FitDirection::kUpstream, T.Qp(), false);
-  FindMoreHits(t, T, kf::FitDirection::kUpstream, T.Qp());
+    FitBranchFast(t, T, kf::FitDirection::kUpstream, T.Qp(), false);
+    FindMoreHits(t, T, kf::FitDirection::kUpstream, T.Qp());
 
-  return T.GetChiSq()[0];
-}
+    return T.GetChiSq()[0];
+  }
+}  // namespace cbm::algo::ca
diff --git a/algo/ca/core/tracking/CaTrackFinder.cxx b/algo/ca/core/tracking/CaTrackFinder.cxx
index 4706cd67d3995d56781f9bc1df544b94b5b8c2be..41bb434f8386080fa99ece366931aeaba2814795 100644
--- a/algo/ca/core/tracking/CaTrackFinder.cxx
+++ b/algo/ca/core/tracking/CaTrackFinder.cxx
@@ -30,538 +30,535 @@
 #include <thread>
 
 
-using namespace cbm::algo::ca;
-
-using cbm::algo::ca::ECounter;  // monitor counter key type
-using cbm::algo::ca::ETimer;    // monitor timer key type
-using cbm::algo::ca::Track;
-using constants::phys::ProtonMassD;
-using constants::phys::SpeedOfLightInv;
-using constants::phys::SpeedOfLightInvD;
-
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-
-TrackFinder::TrackFinder(const ca::Parameters<fvec>& pars, const fscal mass, const ca::TrackingMode& mode,
-                         TrackingMonitorData& monitorData, int nThreads, double& recoTime)
-  : fParameters(pars)
-  , fDefaultMass(mass)
-  , fTrackingMode(mode)
-  , fMonitorData(monitorData)
-  , fvMonitorDataThread(nThreads)
-  , fvWData(nThreads)
-  , fNofThreads(nThreads)
-  , fCaRecoTime(recoTime)
-  , fvRecoTracks(nThreads)
-  , fvRecoHitIndices(nThreads)
-  , fWindowLength((ca::TrackingMode::kMcbm == mode) ? 500 : 10000)
+namespace cbm::algo::ca
 {
-  assert(fNofThreads > 0);
+  using constants::phys::ProtonMassD;
+  using constants::phys::SpeedOfLightInv;
+  using constants::phys::SpeedOfLightInvD;
 
-  for (int iThread = 0; iThread < fNofThreads; ++iThread) {
-    fvRecoTracks[iThread].SetName(std::string("TrackFinder::fvRecoTracks_") + std::to_string(iThread));
-    fvRecoHitIndices[iThread].SetName(std::string("TrackFinder::fvRecoHitIndices_") + std::to_string(iThread));
-  }
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//CBM Level 1 4D Reconstruction
-//Finds tracks using the Cellular Automaton algorithm
-//
-TrackFinder::Output_t TrackFinder::FindTracks(const InputData& input, TimesliceHeader& tsHeader)
-{
-  Output_t output;
-  Vector<Track>& recoTracks        = output.first;   //reconstructed tracks
-  Vector<ca::HitIndex_t>& recoHits = output.second;  //packed hits of reconstructed tracks
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  TrackFinder::TrackFinder(const ca::Parameters<fvec>& pars, const fscal mass, const ca::TrackingMode& mode,
+                           TrackingMonitorData& monitorData, int nThreads, double& recoTime)
+    : fParameters(pars)
+    , fDefaultMass(mass)
+    , fTrackingMode(mode)
+    , fMonitorData(monitorData)
+    , fvMonitorDataThread(nThreads)
+    , fvWData(nThreads)
+    , fNofThreads(nThreads)
+    , fCaRecoTime(recoTime)
+    , fvRecoTracks(nThreads)
+    , fvRecoHitIndices(nThreads)
+    , fWindowLength((ca::TrackingMode::kMcbm == mode) ? 500 : 10000)
+  {
+    assert(fNofThreads > 0);
 
-  if (input.GetNhits() < 1) {
-    LOG(warn) << "No hits were passed to the ca::TrackFinder. Stopping the routine";
-    return output;
+    for (int iThread = 0; iThread < fNofThreads; ++iThread) {
+      fvRecoTracks[iThread].SetName(std::string("TrackFinder::fvRecoTracks_") + std::to_string(iThread));
+      fvRecoHitIndices[iThread].SetName(std::string("TrackFinder::fvRecoHitIndices_") + std::to_string(iThread));
+    }
   }
 
+  // -------------------------------------------------------------------------------------------------------------------
+  //CBM Level 1 4D Reconstruction
+  //Finds tracks using the Cellular Automaton algorithm
   //
-  // The main CaTrackFinder routine
-  // It splits the input data into sub-timeslices
-  // and runs the track finder over the sub-slices
-  //
-  fMonitorData.StartTimer(ETimer::Tracking);
-  fMonitorData.StartTimer(ETimer::PrepareTimeslice);
-  fMonitorData.IncrementCounter(ECounter::TrackingCall);
-  fMonitorData.IncrementCounter(ECounter::RecoHit, input.GetNhits());
-
-  auto timerStart = std::chrono::high_resolution_clock::now();
-
-  auto& wDataThread0 = fvWData[0];  // NOTE: Thread 0 must be always defined
-
-  // ----- Reset data arrays -------------------------------------------------------------------------------------------
-
-  wDataThread0.HitKeyFlags().reset(input.GetNhitKeys(), 0);
-
-  fHitTimeInfo.reset(input.GetNhits());
-
-  // TODO: move these values to Parameters namespace (S.Zharko)
-
-  // length of sub-TS
-  const fscal minProtonMomentum = 0.1;
-  const fscal preFactor         = sqrt(1. + ProtonMassD * ProtonMassD / (minProtonMomentum * minProtonMomentum));
-  const fscal targX             = fParameters.GetTargetPositionX()[0];
-  const fscal targY             = fParameters.GetTargetPositionY()[0];
-  const fscal targZ             = fParameters.GetTargetPositionZ()[0];
-
-  fStatTsStart    = std::numeric_limits<fscal>::max();  // end time of the TS
-  fStatTsEnd      = 0.;                                 // end time of the TS
-  fStatNhitsTotal = 0;
-
-  // calculate possible event time for the hits (fHitTimeInfo array)
-  for (int iStream = 0; iStream < input.GetNdataStreams(); ++iStream) {
-
-    fscal maxTimeBeforeHit = std::numeric_limits<fscal>::lowest();
-    const int nStreamHits  = input.GetStreamNhits(iStream);
-    fStatNhitsTotal += nStreamHits;
+  TrackFinder::Output_t TrackFinder::FindTracks(const InputData& input, TimesliceHeader& tsHeader)
+  {
+    Output_t output;
+    Vector<Track>& recoTracks        = output.first;   //reconstructed tracks
+    Vector<ca::HitIndex_t>& recoHits = output.second;  //packed hits of reconstructed tracks
 
-    for (int ih = 0; ih < nStreamHits; ++ih) {
+    if (input.GetNhits() < 1) {
+      LOG(warn) << "No hits were passed to the ca::TrackFinder. Stopping the routine";
+      return output;
+    }
 
-      ca::HitIndex_t caHitId      = input.GetStreamStartIndex(iStream) + ih;
-      const ca::Hit& h            = input.GetHit(caHitId);
-      const ca::Station<fvec>& st = fParameters.GetStation(h.Station());
-      const fscal dx              = h.X() - targX;
-      const fscal dy              = h.Y() - targY;
-      const fscal dz              = h.Z() - targZ;
-      const fscal l               = sqrt(dx * dx + dy * dy + dz * dz);
-      const fscal timeOfFlightMin = l * SpeedOfLightInv;
-      const fscal timeOfFlightMax = 1.5 * l * preFactor * SpeedOfLightInvD;
-      const fscal dt              = h.RangeT();
-      // TODO: Is it possible, that the proton mass selection affects the search of heavier particles?
+    //
+    // The main CaTrackFinder routine
+    // It splits the input data into sub-timeslices
+    // and runs the track finder over the sub-slices
+    //
+    fMonitorData.StartTimer(ETimer::Tracking);
+    fMonitorData.StartTimer(ETimer::PrepareTimeslice);
+    fMonitorData.IncrementCounter(ECounter::TrackingCall);
+    fMonitorData.IncrementCounter(ECounter::RecoHit, input.GetNhits());
+
+    auto timerStart = std::chrono::high_resolution_clock::now();
+
+    auto& wDataThread0 = fvWData[0];  // NOTE: Thread 0 must be always defined
+
+    // ----- Reset data arrays -----------------------------------------------------------------------------------------
+
+    wDataThread0.HitKeyFlags().reset(input.GetNhitKeys(), 0);
+
+    fHitTimeInfo.reset(input.GetNhits());
+
+    // TODO: move these values to Parameters namespace (S.Zharko)
+
+    // length of sub-TS
+    const fscal minProtonMomentum = 0.1;
+    const fscal preFactor         = sqrt(1. + ProtonMassD * ProtonMassD / (minProtonMomentum * minProtonMomentum));
+    const fscal targX             = fParameters.GetTargetPositionX()[0];
+    const fscal targY             = fParameters.GetTargetPositionY()[0];
+    const fscal targZ             = fParameters.GetTargetPositionZ()[0];
+
+    fStatTsStart    = std::numeric_limits<fscal>::max();  // end time of the TS
+    fStatTsEnd      = 0.;                                 // end time of the TS
+    fStatNhitsTotal = 0;
+
+    // calculate possible event time for the hits (fHitTimeInfo array)
+    for (int iStream = 0; iStream < input.GetNdataStreams(); ++iStream) {
+
+      fscal maxTimeBeforeHit = std::numeric_limits<fscal>::lowest();
+      const int nStreamHits  = input.GetStreamNhits(iStream);
+      fStatNhitsTotal += nStreamHits;
+
+      for (int ih = 0; ih < nStreamHits; ++ih) {
+
+        ca::HitIndex_t caHitId      = input.GetStreamStartIndex(iStream) + ih;
+        const ca::Hit& h            = input.GetHit(caHitId);
+        const ca::Station<fvec>& st = fParameters.GetStation(h.Station());
+        const fscal dx              = h.X() - targX;
+        const fscal dy              = h.Y() - targY;
+        const fscal dz              = h.Z() - targZ;
+        const fscal l               = sqrt(dx * dx + dy * dy + dz * dz);
+        const fscal timeOfFlightMin = l * SpeedOfLightInv;
+        const fscal timeOfFlightMax = 1.5 * l * preFactor * SpeedOfLightInvD;
+        const fscal dt              = h.RangeT();
+        // TODO: Is it possible, that the proton mass selection affects the search of heavier particles?
+
+        CaHitTimeInfo& info = fHitTimeInfo[caHitId];
+        info.fEventTimeMin  = st.timeInfo ? (h.T() - dt - timeOfFlightMax) : -1.e10;
+        info.fEventTimeMax  = st.timeInfo ? (h.T() + dt - timeOfFlightMin) : 1.e10;
+
+        // NOTE: if not a MT part, use wDataThread0.IsHitKeyUsed, it will be later copied to other threads
+        if (info.fEventTimeMin > 500.e6 || info.fEventTimeMax < -500.) {  // cut hits with bogus start time > 500 ms
+          wDataThread0.IsHitKeyUsed(h.FrontKey()) = 1;
+          wDataThread0.IsHitKeyUsed(h.BackKey())  = 1;
+          LOG(error) << "CATrackFinder: skip bogus hit " << h.ToString();
+          continue;
+        }
+        maxTimeBeforeHit       = std::max(maxTimeBeforeHit, info.fEventTimeMax);
+        info.fMaxTimeBeforeHit = maxTimeBeforeHit;
+        fStatTsStart           = std::min(fStatTsStart, info.fEventTimeMax);
+        fStatTsEnd             = std::max(fStatTsEnd, info.fEventTimeMin);
+      }
 
-      CaHitTimeInfo& info = fHitTimeInfo[caHitId];
-      info.fEventTimeMin  = st.timeInfo ? (h.T() - dt - timeOfFlightMax) : -1.e10;
-      info.fEventTimeMax  = st.timeInfo ? (h.T() + dt - timeOfFlightMin) : 1.e10;
+      fscal minTimeAfterHit = std::numeric_limits<fscal>::max();
+      // loop in the reverse order to fill CaHitTimeInfo::fMinTimeAfterHit fields
 
-      // NOTE: if not a MT part, use wDataThread0.IsHitKeyUsed, it will be later copied to other threads
-      if (info.fEventTimeMin > 500.e6 || info.fEventTimeMax < -500.) {  // cut hits with bogus start time > 500 ms
-        wDataThread0.IsHitKeyUsed(h.FrontKey()) = 1;
-        wDataThread0.IsHitKeyUsed(h.BackKey())  = 1;
-        LOG(error) << "CATrackFinder: skip bogus hit " << h.ToString();
-        continue;
+      for (int ih = nStreamHits - 1; ih >= 0; --ih) {
+        ca::HitIndex_t caHitId = input.GetStreamStartIndex(iStream) + ih;
+        const ca::Hit& h       = input.GetHit(caHitId);
+        if (wDataThread0.IsHitKeyUsed(h.FrontKey()) || wDataThread0.IsHitKeyUsed(h.BackKey())) {
+          continue;
+        }  // the hit is skipped
+        CaHitTimeInfo& info   = fHitTimeInfo[caHitId];
+        minTimeAfterHit       = std::min(minTimeAfterHit, info.fEventTimeMin);
+        info.fMinTimeAfterHit = minTimeAfterHit;
       }
-      maxTimeBeforeHit       = std::max(maxTimeBeforeHit, info.fEventTimeMax);
-      info.fMaxTimeBeforeHit = maxTimeBeforeHit;
-      fStatTsStart           = std::min(fStatTsStart, info.fEventTimeMax);
-      fStatTsEnd             = std::max(fStatTsEnd, info.fEventTimeMin);
-    }
 
-    fscal minTimeAfterHit = std::numeric_limits<fscal>::max();
-    // loop in the reverse order to fill CaHitTimeInfo::fMinTimeAfterHit fields
-
-    for (int ih = nStreamHits - 1; ih >= 0; --ih) {
-      ca::HitIndex_t caHitId = input.GetStreamStartIndex(iStream) + ih;
-      const ca::Hit& h       = input.GetHit(caHitId);
-      if (wDataThread0.IsHitKeyUsed(h.FrontKey()) || wDataThread0.IsHitKeyUsed(h.BackKey())) {
-        continue;
-      }  // the hit is skipped
-      CaHitTimeInfo& info   = fHitTimeInfo[caHitId];
-      minTimeAfterHit       = std::min(minTimeAfterHit, info.fEventTimeMin);
-      info.fMinTimeAfterHit = minTimeAfterHit;
-    }
-
-    if (0) {
-      static int tmp = 0;
-      if (tmp < 10000) {
-        tmp++;
-        LOG(warning) << "\n\n stream " << iStream << " hits " << nStreamHits << "\n\n";
-        for (int ih = 0; (ih < nStreamHits) && (tmp < 10000); ++ih) {
-          ca::HitIndex_t caHitId = input.GetStreamStartIndex(iStream) + ih;
-          const ca::Hit& h       = input.GetHit(caHitId);
-          if (wDataThread0.IsHitKeyUsed(h.FrontKey()) || wDataThread0.IsHitKeyUsed(h.BackKey())) {
-            continue;
-          }  // the hit is skipped
-          CaHitTimeInfo& info = fHitTimeInfo[caHitId];
-          if (h.Station() < 4) {
-            tmp++;
-            LOG(warning) << " hit sta " << h.Station() << " stream " << iStream << " time " << h.T() << " event time "
-                         << info.fEventTimeMin << " .. " << info.fEventTimeMax << " max time before hit "
-                         << info.fMaxTimeBeforeHit << " min time after hit " << info.fMinTimeAfterHit;
+      if (0) {
+        static int tmp = 0;
+        if (tmp < 10000) {
+          tmp++;
+          LOG(warning) << "\n\n stream " << iStream << " hits " << nStreamHits << "\n\n";
+          for (int ih = 0; (ih < nStreamHits) && (tmp < 10000); ++ih) {
+            ca::HitIndex_t caHitId = input.GetStreamStartIndex(iStream) + ih;
+            const ca::Hit& h       = input.GetHit(caHitId);
+            if (wDataThread0.IsHitKeyUsed(h.FrontKey()) || wDataThread0.IsHitKeyUsed(h.BackKey())) {
+              continue;
+            }  // the hit is skipped
+            CaHitTimeInfo& info = fHitTimeInfo[caHitId];
+            if (h.Station() < 4) {
+              tmp++;
+              LOG(warning) << " hit sta " << h.Station() << " stream " << iStream << " time " << h.T() << " event time "
+                           << info.fEventTimeMin << " .. " << info.fEventTimeMax << " max time before hit "
+                           << info.fMaxTimeBeforeHit << " min time after hit " << info.fMinTimeAfterHit;
+            }
           }
         }
       }
     }
-  }
-  // all hits belong to one sub-timeslice; 1 s is the maximal length of the TS
-  fStatTsEnd = std::clamp(fStatTsEnd, fStatTsStart, fStatTsStart + 1.e9f);
+    // all hits belong to one sub-timeslice; 1 s is the maximal length of the TS
+    fStatTsEnd = std::clamp(fStatTsEnd, fStatTsStart, fStatTsStart + 1.e9f);
 
-  LOG(debug) << "CA tracker process time slice " << fStatTsStart * 1.e-6 << " -- " << fStatTsEnd * 1.e-6
-             << " [ms] with " << fStatNhitsTotal << " hits";
+    LOG(debug) << "CA tracker process time slice " << fStatTsStart * 1.e-6 << " -- " << fStatTsEnd * 1.e-6
+               << " [ms] with " << fStatNhitsTotal << " hits";
 
-  int nWindows = static_cast<int>((fStatTsEnd - fStatTsStart) / fWindowLength) + 1;
-  if (nWindows < 1) {  // Situation, when fStatTsEnd == fStatTsStart
-    nWindows = 1;
-  }
+    int nWindows = static_cast<int>((fStatTsEnd - fStatTsStart) / fWindowLength) + 1;
+    if (nWindows < 1) {  // Situation, when fStatTsEnd == fStatTsStart
+      nWindows = 1;
+    }
 
-  // int nWindowsThread = nWindows / fNofThreads;
-  // LOG(info) << "CA: estimated number of time windows: " << nWindows;
-
-  std::vector<std::pair<fscal, fscal>> vWindowRangeThread(fNofThreads);
-  {  // Estimation of number of hits in time windows
-    //Timer time;
-    //time.Start();
-    const HitIndex_t nHitsTot = input.GetNhits();
-    const int nSt             = fParameters.GetNstationsActive();
-
-    // Count number of hits per window and station
-    std::vector<HitIndex_t> nHitsWindowSta(nWindows * nSt, 0);
-
-    for (HitIndex_t iHit = 0; iHit < nHitsTot; ++iHit) {
-      const auto& hit  = input.GetHit(iHit);
-      const auto& info = fHitTimeInfo[iHit];
-      int iWindow      = static_cast<int>((info.fEventTimeMin - fStatTsStart) / fWindowLength);
-      if (iWindow < 0) {
-        iWindow = 0;
-      }
-      if (iWindow >= nWindows) {
-        LOG(error) << "ca: Hit out of range: iHit = " << iHit << ", min. event time = " << info.fEventTimeMin * 1.e-6
-                   << " ms, window = " << iWindow;
-        continue;
+    // int nWindowsThread = nWindows / fNofThreads;
+    // LOG(info) << "CA: estimated number of time windows: " << nWindows;
+
+    std::vector<std::pair<fscal, fscal>> vWindowRangeThread(fNofThreads);
+    {  // Estimation of number of hits in time windows
+      //Timer time;
+      //time.Start();
+      const HitIndex_t nHitsTot = input.GetNhits();
+      const int nSt             = fParameters.GetNstationsActive();
+
+      // Count number of hits per window and station
+      std::vector<HitIndex_t> nHitsWindowSta(nWindows * nSt, 0);
+
+      for (HitIndex_t iHit = 0; iHit < nHitsTot; ++iHit) {
+        const auto& hit  = input.GetHit(iHit);
+        const auto& info = fHitTimeInfo[iHit];
+        int iWindow      = static_cast<int>((info.fEventTimeMin - fStatTsStart) / fWindowLength);
+        if (iWindow < 0) {
+          iWindow = 0;
+        }
+        if (iWindow >= nWindows) {
+          LOG(error) << "ca: Hit out of range: iHit = " << iHit << ", min. event time = " << info.fEventTimeMin * 1.e-6
+                     << " ms, window = " << iWindow;
+          continue;
+        }
+        ++nHitsWindowSta[hit.Station() + iWindow * nSt];
       }
-      ++nHitsWindowSta[hit.Station() + iWindow * nSt];
-    }
 
-    // Remove hits from the "monster events"
-    if (ca::TrackingMode::kMcbm == fTrackingMode) {
-      const auto maxNofHitsSta = static_cast<HitIndex_t>(50 * fWindowLength / 1.e3);
-      for (auto& content : nHitsWindowSta) {
-        if (content > maxNofHitsSta) {
-          content = 0;
+      // Remove hits from the "monster events"
+      if (ca::TrackingMode::kMcbm == fTrackingMode) {
+        const auto maxNofHitsSta = static_cast<HitIndex_t>(50 * fWindowLength / 1.e3);
+        for (auto& content : nHitsWindowSta) {
+          if (content > maxNofHitsSta) {
+            content = 0;
+          }
         }
       }
-    }
 
-    // Integrate number of hits per window
-    std::vector<HitIndex_t> nHitsWindow;
-    nHitsWindow.reserve(nWindows);
-    HitIndex_t nHitsCollected = 0;
-    for (auto it = nHitsWindowSta.begin(); it != nHitsWindowSta.end(); it += nSt) {
-      nHitsCollected = nHitsWindow.emplace_back(std::accumulate(it, it + nSt, nHitsCollected));
-    }
+      // Integrate number of hits per window
+      std::vector<HitIndex_t> nHitsWindow;
+      nHitsWindow.reserve(nWindows);
+      HitIndex_t nHitsCollected = 0;
+      for (auto it = nHitsWindowSta.begin(); it != nHitsWindowSta.end(); it += nSt) {
+        nHitsCollected = nHitsWindow.emplace_back(std::accumulate(it, it + nSt, nHitsCollected));
+      }
 
-    // Get time range for threads
-    const HitIndex_t nHitsPerThread = nHitsCollected / fNofThreads;
-    auto windowIt                   = nHitsWindow.begin();
-    vWindowRangeThread[0].first     = fStatTsStart;
-    for (int iTh = 1; iTh < fNofThreads; ++iTh) {
-      windowIt                           = std::lower_bound(windowIt, nHitsWindow.end(), iTh * nHitsPerThread);
-      const size_t iWbegin               = std::distance(nHitsWindow.begin(), windowIt) + 1;
-      vWindowRangeThread[iTh].first      = fStatTsStart + iWbegin * fWindowLength;
-      vWindowRangeThread[iTh - 1].second = vWindowRangeThread[iTh].first;
+      // Get time range for threads
+      const HitIndex_t nHitsPerThread = nHitsCollected / fNofThreads;
+      auto windowIt                   = nHitsWindow.begin();
+      vWindowRangeThread[0].first     = fStatTsStart;
+      for (int iTh = 1; iTh < fNofThreads; ++iTh) {
+        windowIt                           = std::lower_bound(windowIt, nHitsWindow.end(), iTh * nHitsPerThread);
+        const size_t iWbegin               = std::distance(nHitsWindow.begin(), windowIt) + 1;
+        vWindowRangeThread[iTh].first      = fStatTsStart + iWbegin * fWindowLength;
+        vWindowRangeThread[iTh - 1].second = vWindowRangeThread[iTh].first;
+      }
+      vWindowRangeThread[fNofThreads - 1].second = fStatTsEnd;
+
+      //time.Stop();
+      //LOG(info) << "Thread boarders estimation time: " << time.GetTotalMs() << " ms";
+      LOG(debug) << "Fraction of hits from monster events: "
+                 << static_cast<double>(nHitsTot - nHitsCollected) / nHitsTot;
     }
-    vWindowRangeThread[fNofThreads - 1].second = fStatTsEnd;
 
-    //time.Stop();
-    //LOG(info) << "Thread boarders estimation time: " << time.GetTotalMs() << " ms";
-    LOG(debug) << "Fraction of hits from monster events: " << static_cast<double>(nHitsTot - nHitsCollected) / nHitsTot;
-  }
+    // cut data into sub-timeslices and process them one by one
+    //for (int iThread = 0; iThread < fNofThreads; ++iThread) {
+    //  vWindowStartThread[iThread] = fStatTsStart + iThread * nWindowsThread * fWindowLength;
+    //  vWindowEndThread[iThread] =
+    //    vWindowStartThread[iThread] + nWindowsThread * fWindowLength;
+    //}
 
-  // cut data into sub-timeslices and process them one by one
-  //for (int iThread = 0; iThread < fNofThreads; ++iThread) {
-  //  vWindowStartThread[iThread] = fStatTsStart + iThread * nWindowsThread * fWindowLength;
-  //  vWindowEndThread[iThread] =
-  //    vWindowStartThread[iThread] + nWindowsThread * fWindowLength;
-  //}
-
-  for (int iThread = 0; iThread < fNofThreads; ++iThread) {
-    auto& entry  = vWindowRangeThread[iThread];
-    double start = entry.first * 1.e-6;
-    double end   = entry.second * 1.e-6;
-    LOG(debug) << "Thread: " << iThread << " from " << start << " ms  to " << end << " ms (delta = " << end - start
-               << " ms)";
-  }
+    for (int iThread = 0; iThread < fNofThreads; ++iThread) {
+      auto& entry  = vWindowRangeThread[iThread];
+      double start = entry.first * 1.e-6;
+      double end   = entry.second * 1.e-6;
+      LOG(debug) << "Thread: " << iThread << " from " << start << " ms  to " << end << " ms (delta = " << end - start
+                 << " ms)";
+    }
 
-  // Statistics for monitoring
-  std::vector<int> vStatNwindows(fNofThreads), vStatNhitsProcessed(fNofThreads);
-
-  fMonitorData.StopTimer(ETimer::PrepareTimeslice);
-  // Save tracks
-  if (fNofThreads == 1) {
-    this->FindTracksThread(input, 0, std::ref(vWindowRangeThread[0]), std::ref(vStatNwindows[0]),
-                           std::ref(vStatNhitsProcessed[0]));
-    fMonitorData.StartTimer(ETimer::StoreTracksFinal);
-    recoTracks = std::move(fvRecoTracks[0]);
-    recoHits   = std::move(fvRecoHitIndices[0]);
-    fMonitorData.StopTimer(ETimer::StoreTracksFinal);
-  }
-  else {
-    std::vector<std::thread> vThreadList;
-    vThreadList.reserve(fNofThreads);
-    for (int iTh = 0; iTh < fNofThreads; ++iTh) {
-      vThreadList.emplace_back(&TrackFinder::FindTracksThread, this, std::ref(input), iTh,
-                               std::ref(vWindowRangeThread[iTh]), std::ref(vStatNwindows[iTh]),
-                               std::ref(vStatNhitsProcessed[iTh]));
+    // Statistics for monitoring
+    std::vector<int> vStatNwindows(fNofThreads), vStatNhitsProcessed(fNofThreads);
+
+    fMonitorData.StopTimer(ETimer::PrepareTimeslice);
+    // Save tracks
+    if (fNofThreads == 1) {
+      this->FindTracksThread(input, 0, std::ref(vWindowRangeThread[0]), std::ref(vStatNwindows[0]),
+                             std::ref(vStatNhitsProcessed[0]));
+      fMonitorData.StartTimer(ETimer::StoreTracksFinal);
+      recoTracks = std::move(fvRecoTracks[0]);
+      recoHits   = std::move(fvRecoHitIndices[0]);
+      fMonitorData.StopTimer(ETimer::StoreTracksFinal);
     }
-    for (auto& th : vThreadList) {
-      if (th.joinable()) {
-        th.join();
+    else {
+      std::vector<std::thread> vThreadList;
+      vThreadList.reserve(fNofThreads);
+      for (int iTh = 0; iTh < fNofThreads; ++iTh) {
+        vThreadList.emplace_back(&TrackFinder::FindTracksThread, this, std::ref(input), iTh,
+                                 std::ref(vWindowRangeThread[iTh]), std::ref(vStatNwindows[iTh]),
+                                 std::ref(vStatNhitsProcessed[iTh]));
       }
+      for (auto& th : vThreadList) {
+        if (th.joinable()) {
+          th.join();
+        }
+      }
+      fMonitorData.StartTimer(ETimer::StoreTracksFinal);
+      auto Operation  = [](size_t acc, const auto& v) { return acc + v.size(); };
+      int nRecoTracks = std::accumulate(fvRecoTracks.begin(), fvRecoTracks.end(), 0, Operation);
+      int nRecoHits   = std::accumulate(fvRecoHitIndices.begin(), fvRecoHitIndices.end(), 0, Operation);
+      recoTracks.reserve(nRecoTracks);
+      recoHits.reserve(nRecoHits);
+      for (int iTh = 0; iTh < fNofThreads; ++iTh) {
+        recoTracks.insert(recoTracks.end(), fvRecoTracks[iTh].begin(), fvRecoTracks[iTh].end());
+        recoHits.insert(recoHits.end(), fvRecoHitIndices[iTh].begin(), fvRecoHitIndices[iTh].end());
+      }
+      fMonitorData.StopTimer(ETimer::StoreTracksFinal);
     }
-    fMonitorData.StartTimer(ETimer::StoreTracksFinal);
-    auto Operation  = [](size_t acc, const auto& v) { return acc + v.size(); };
-    int nRecoTracks = std::accumulate(fvRecoTracks.begin(), fvRecoTracks.end(), 0, Operation);
-    int nRecoHits   = std::accumulate(fvRecoHitIndices.begin(), fvRecoHitIndices.end(), 0, Operation);
-    recoTracks.reserve(nRecoTracks);
-    recoHits.reserve(nRecoHits);
-    for (int iTh = 0; iTh < fNofThreads; ++iTh) {
-      recoTracks.insert(recoTracks.end(), fvRecoTracks[iTh].begin(), fvRecoTracks[iTh].end());
-      recoHits.insert(recoHits.end(), fvRecoHitIndices[iTh].begin(), fvRecoHitIndices[iTh].end());
-    }
-    fMonitorData.StopTimer(ETimer::StoreTracksFinal);
-  }
 
-  fMonitorData.IncrementCounter(ECounter::RecoTrack, recoTracks.size());
-  fMonitorData.IncrementCounter(ECounter::RecoHitUsed, recoHits.size());
+    fMonitorData.IncrementCounter(ECounter::RecoTrack, recoTracks.size());
+    fMonitorData.IncrementCounter(ECounter::RecoHitUsed, recoHits.size());
 
-  auto timerEnd = std::chrono::high_resolution_clock::now();
-  fCaRecoTime   = (double) (std::chrono::duration<double>(timerEnd - timerStart).count());
-
-  // Add thread monitors to the main monitor
-  for (auto& monitor : fvMonitorDataThread) {
-    fMonitorData.AddMonitorData(monitor, true);
-    //fMonitorData.AddMonitorData(monitor);
-    monitor.Reset();
-  }
+    auto timerEnd = std::chrono::high_resolution_clock::now();
+    fCaRecoTime   = (double) (std::chrono::duration<double>(timerEnd - timerStart).count());
 
-  const int statNhitsProcessedTotal = std::accumulate(vStatNhitsProcessed.begin(), vStatNhitsProcessed.end(), 0);
-  const int statNwindowsTotal       = std::accumulate(vStatNwindows.begin(), vStatNwindows.end(), 0);
+    // Add thread monitors to the main monitor
+    for (auto& monitor : fvMonitorDataThread) {
+      fMonitorData.AddMonitorData(monitor, true);
+      //fMonitorData.AddMonitorData(monitor);
+      monitor.Reset();
+    }
 
-  // Filling TS headear
-  tsHeader.Start() = fStatTsStart;
-  tsHeader.End()   = fStatTsEnd;
+    const int statNhitsProcessedTotal = std::accumulate(vStatNhitsProcessed.begin(), vStatNhitsProcessed.end(), 0);
+    const int statNwindowsTotal       = std::accumulate(vStatNwindows.begin(), vStatNwindows.end(), 0);
 
-  fMonitorData.StopTimer(ETimer::Tracking);
+    // Filling TS headear
+    tsHeader.Start() = fStatTsStart;
+    tsHeader.End()   = fStatTsEnd;
 
-  LOG(debug) << "CA tracker: time slice finished. Reconstructed " << recoTracks.size() << " tracks with "
-             << recoHits.size() << " hits. Processed " << statNhitsProcessedTotal << " hits in " << statNwindowsTotal
-             << " time windows. Reco time " << fCaRecoTime / 1.e9 << " s";
-  return output;
-}
+    fMonitorData.StopTimer(ETimer::Tracking);
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void TrackFinder::FindTracksThread(const InputData& input, int iThread, std::pair<fscal, fscal>& windowRange,
-                                   int& statNwindows, int& statNhitsProcessed)
-{
-  //std::stringstream filename;
-  //filename << "./dbg_caTrackFinder::FindTracksThread_" << iThread << ".txt";
-  //std::ofstream out(filename.str());
-  Timer timer;
-  timer.Start();
-
-  auto& monitor = fvMonitorDataThread[iThread];
-  monitor.StartTimer(ETimer::TrackingThread);
-  monitor.StartTimer(ETimer::PrepareThread);
-
-  // Init vectors
-  auto& tracks     = fvRecoTracks[iThread];
-  auto& hitIndices = fvRecoHitIndices[iThread];
-  auto& wData      = fvWData[iThread];
-  {
-    const int nStations          = fParameters.GetNstationsActive();
-    const size_t nHitsTot        = input.GetNhits();
-    const size_t nHitsExpected   = 2 * nHitsTot;
-    const size_t nTracksExpected = 2 * nHitsTot / nStations;
-    tracks.clear();
-    tracks.reserve(nTracksExpected / fNofThreads);
-    hitIndices.clear();
-    hitIndices.reserve(nHitsExpected / fNofThreads);
-    if (iThread != 0) {
-      wData.HitKeyFlags() = fvWData[0].HitKeyFlags();
-    }
-    for (int iS = 0; iS < nStations; ++iS) {
-      wData.TsHitIndices(iS).clear();
-      wData.TsHitIndices(iS).reserve(nHitsTot);
-    }
+    LOG(debug) << "CA tracker: time slice finished. Reconstructed " << recoTracks.size() << " tracks with "
+               << recoHits.size() << " hits. Processed " << statNhitsProcessedTotal << " hits in " << statNwindowsTotal
+               << " time windows. Reco time " << fCaRecoTime / 1.e9 << " s";
+    return output;
   }
 
-  // Begin and end index of hit-range for streams
-  std::vector<std::pair<HitIndex_t, HitIndex_t>> streamHitRanges(input.GetNdataStreams(), {0, 0});
-
-  // Define first hit, skip all the hits, which are before the first window
-  for (size_t iStream = 0; iStream < streamHitRanges.size(); ++iStream) {
-    auto& range  = streamHitRanges[iStream];
-    range.first  = input.GetStreamStartIndex(iStream);
-    range.second = input.GetStreamStopIndex(iStream);
-
-    for (HitIndex_t caHitId = range.first; caHitId < range.second; ++caHitId) {
-      const ca::Hit& h = input.GetHit(caHitId);
-      if (wData.IsHitKeyUsed(h.FrontKey()) || wData.IsHitKeyUsed(h.BackKey())) {
-        continue;
-      }
-      const CaHitTimeInfo& info = fHitTimeInfo[caHitId];
-      if (info.fMaxTimeBeforeHit < windowRange.first) {
-        range.first = caHitId + 1;
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void TrackFinder::FindTracksThread(const InputData& input, int iThread, std::pair<fscal, fscal>& windowRange,
+                                     int& statNwindows, int& statNhitsProcessed)
+  {
+    //std::stringstream filename;
+    //filename << "./dbg_caTrackFinder::FindTracksThread_" << iThread << ".txt";
+    //std::ofstream out(filename.str());
+    Timer timer;
+    timer.Start();
+
+    auto& monitor = fvMonitorDataThread[iThread];
+    monitor.StartTimer(ETimer::TrackingThread);
+    monitor.StartTimer(ETimer::PrepareThread);
+
+    // Init vectors
+    auto& tracks     = fvRecoTracks[iThread];
+    auto& hitIndices = fvRecoHitIndices[iThread];
+    auto& wData      = fvWData[iThread];
+    {
+      const int nStations          = fParameters.GetNstationsActive();
+      const size_t nHitsTot        = input.GetNhits();
+      const size_t nHitsExpected   = 2 * nHitsTot;
+      const size_t nTracksExpected = 2 * nHitsTot / nStations;
+      tracks.clear();
+      tracks.reserve(nTracksExpected / fNofThreads);
+      hitIndices.clear();
+      hitIndices.reserve(nHitsExpected / fNofThreads);
+      if (iThread != 0) {
+        wData.HitKeyFlags() = fvWData[0].HitKeyFlags();
       }
-      if (info.fMinTimeAfterHit > windowRange.second) {
-        range.second = caHitId;
+      for (int iS = 0; iS < nStations; ++iS) {
+        wData.TsHitIndices(iS).clear();
+        wData.TsHitIndices(iS).reserve(nHitsTot);
       }
     }
-  }
-
-  int statLastLogTimeChunk = -1;
-
-  // Track finder algorithm for the time window
-  ca::TrackFinderWindow trackFinderWindow(fParameters, fDefaultMass, fTrackingMode, monitor);
-  trackFinderWindow.InitTimeslice(input.GetNhitKeys());
-
-  monitor.StopTimer(ETimer::PrepareThread);
-
-  while (true) {
-    monitor.IncrementCounter(ECounter::SubTS);
-    // select the sub-slice hits
-    for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
-      wData.TsHitIndices(iS).clear();
-    }
-    bool areUntouchedDataLeft = false;  // is the whole TS processed
 
-    // TODO: SG: skip empty regions and start the subslice with the earliest hit
+    // Begin and end index of hit-range for streams
+    std::vector<std::pair<HitIndex_t, HitIndex_t>> streamHitRanges(input.GetNdataStreams(), {0, 0});
 
-    statNwindows++;
-    //out << statNwindows << ' ';
+    // Define first hit, skip all the hits, which are before the first window
+    for (size_t iStream = 0; iStream < streamHitRanges.size(); ++iStream) {
+      auto& range  = streamHitRanges[iStream];
+      range.first  = input.GetStreamStartIndex(iStream);
+      range.second = input.GetStreamStopIndex(iStream);
 
-    monitor.StartTimer(ETimer::PrepareWindow);
-
-    for (auto& range : streamHitRanges) {
       for (HitIndex_t caHitId = range.first; caHitId < range.second; ++caHitId) {
         const ca::Hit& h = input.GetHit(caHitId);
         if (wData.IsHitKeyUsed(h.FrontKey()) || wData.IsHitKeyUsed(h.BackKey())) {
-          // the hit is already reconstructed
           continue;
         }
         const CaHitTimeInfo& info = fHitTimeInfo[caHitId];
-        if (info.fEventTimeMax < windowRange.first) {
-          // the hit belongs to previous sub-slices
-          continue;
+        if (info.fMaxTimeBeforeHit < windowRange.first) {
+          range.first = caHitId + 1;
         }
-        if (info.fMinTimeAfterHit > windowRange.first + fWindowLength) {
-          // this hit and all later hits are out of the sub-slice
-          areUntouchedDataLeft = true;
-          break;
-        }
-        if (info.fEventTimeMin > windowRange.first + fWindowLength) {
-          // the hit is too late for the sub slice
-          areUntouchedDataLeft = true;
-          continue;
-        }
-
-        // the hit belongs to the sub-slice
-        wData.TsHitIndices(h.Station()).push_back(caHitId);
-        if (info.fMaxTimeBeforeHit < windowRange.first + fWindowLength) {
-          range.first = caHitId + 1;  // this hit and all hits before are before the overlap
+        if (info.fMinTimeAfterHit > windowRange.second) {
+          range.second = caHitId;
         }
       }
     }
 
-    //out << statNwindowHits << ' ';
-    //if (statNwindowHits == 0) {  // Empty window
-    //  monitor.StopTimer(ETimer::PrepareWindow);
-    //  out << 0 << ' ' << 0 << ' ' << 0 << '\n';
-    //  continue;
-    //}
+    int statLastLogTimeChunk = -1;
 
-    if (ca::TrackingMode::kMcbm == fTrackingMode) {
-      // cut at 50 hits per station per 1 us.
-      int maxStationHits = (int) (50 * fWindowLength / 1.e3);
-      for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
-        int nHitsSta = static_cast<int>(wData.TsHitIndices(ista).size());
-        if (nHitsSta > maxStationHits) {
-          wData.TsHitIndices(ista).clear();
+    // Track finder algorithm for the time window
+    ca::TrackFinderWindow trackFinderWindow(fParameters, fDefaultMass, fTrackingMode, monitor);
+    trackFinderWindow.InitTimeslice(input.GetNhitKeys());
+
+    monitor.StopTimer(ETimer::PrepareThread);
+
+    while (true) {
+      monitor.IncrementCounter(ECounter::SubTS);
+      // select the sub-slice hits
+      for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
+        wData.TsHitIndices(iS).clear();
+      }
+      bool areUntouchedDataLeft = false;  // is the whole TS processed
+
+      // TODO: SG: skip empty regions and start the subslice with the earliest hit
+
+      statNwindows++;
+      //out << statNwindows << ' ';
+
+      monitor.StartTimer(ETimer::PrepareWindow);
+
+      for (auto& range : streamHitRanges) {
+        for (HitIndex_t caHitId = range.first; caHitId < range.second; ++caHitId) {
+          const ca::Hit& h = input.GetHit(caHitId);
+          if (wData.IsHitKeyUsed(h.FrontKey()) || wData.IsHitKeyUsed(h.BackKey())) {
+            // the hit is already reconstructed
+            continue;
+          }
+          const CaHitTimeInfo& info = fHitTimeInfo[caHitId];
+          if (info.fEventTimeMax < windowRange.first) {
+            // the hit belongs to previous sub-slices
+            continue;
+          }
+          if (info.fMinTimeAfterHit > windowRange.first + fWindowLength) {
+            // this hit and all later hits are out of the sub-slice
+            areUntouchedDataLeft = true;
+            break;
+          }
+          if (info.fEventTimeMin > windowRange.first + fWindowLength) {
+            // the hit is too late for the sub slice
+            areUntouchedDataLeft = true;
+            continue;
+          }
+
+          // the hit belongs to the sub-slice
+          wData.TsHitIndices(h.Station()).push_back(caHitId);
+          if (info.fMaxTimeBeforeHit < windowRange.first + fWindowLength) {
+            range.first = caHitId + 1;  // this hit and all hits before are before the overlap
+          }
         }
       }
-    }
 
-    int statNwindowHits = 0;
-    for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
-      statNwindowHits += wData.TsHitIndices(ista).size();
-    }
-    statNhitsProcessed += statNwindowHits;
-
-    // print the LOG for every 10 ms of data processed
-    if constexpr (0) {
-      int currentChunk = (int) ((windowRange.first - fStatTsStart) / 10.e6);
-      if (!areUntouchedDataLeft || currentChunk > statLastLogTimeChunk) {
-        statLastLogTimeChunk = currentChunk;
-        double dataRead      = 100. * (windowRange.first + fWindowLength - fStatTsStart) / (fStatTsEnd - fStatTsStart);
-        if (dataRead > 100.) {
-          dataRead = 100.;
+      //out << statNwindowHits << ' ';
+      //if (statNwindowHits == 0) {  // Empty window
+      //  monitor.StopTimer(ETimer::PrepareWindow);
+      //  out << 0 << ' ' << 0 << ' ' << 0 << '\n';
+      //  continue;
+      //}
+
+      if (ca::TrackingMode::kMcbm == fTrackingMode) {
+        // cut at 50 hits per station per 1 us.
+        int maxStationHits = (int) (50 * fWindowLength / 1.e3);
+        for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
+          int nHitsSta = static_cast<int>(wData.TsHitIndices(ista).size());
+          if (nHitsSta > maxStationHits) {
+            wData.TsHitIndices(ista).clear();
+          }
         }
-        LOG(debug) << "CA tracker process sliding window N " << statNwindows << ": time " << windowRange.first / 1.e6
-                   << " ms + " << fWindowLength / 1.e3 << " us) with " << statNwindowHits << " hits. "
-                   << " Processing " << dataRead << " % of the TS time and "
-                   << 100. * statNhitsProcessed / fStatNhitsTotal << " % of TS hits."
-                   << " Already reconstructed " << tracks.size() << " tracks on thread #" << iThread;
       }
-    }
 
-    //out << statNwindowHits << ' ';
-    monitor.StopTimer(ETimer::PrepareWindow);
-
-    //Timer trackingInWindow;  //DBG
-    //trackingInWindow.Start();
-    monitor.StartTimer(ETimer::TrackingWindow);
-    trackFinderWindow.CaTrackFinderSlice(input, wData);
-    monitor.StopTimer(ETimer::TrackingWindow);
-    //trackingInWindow.Stop();
-    //out << trackingInWindow.GetTotalMs() << ' ';
-
-    // save reconstructed tracks with no hits in the overlap region
-    //if (windowRange.first > 13.23e6 && windowRange.first < 13.26e6) {
-    windowRange.first += fWindowLength;
-    // we should add hits from reconstructed but not stored tracks to the new sub-timeslice
-    // we do it in a simple way by extending the tsStartNew
-    // TODO: only add those hits from the region before tsStartNew that belong to the not stored tracks
-    //out << fvWData[iThread].RecoHitIndices().size() << ' ';
-    //out << fvWData[iThread].RecoTracks().size() << '\n';
-
-    monitor.StartTimer(ETimer::StoreTracksWindow);
-    auto trackFirstHit = wData.RecoHitIndices().begin();
-
-    for (const auto& track : wData.RecoTracks()) {
-
-      const bool isTrackCompletelyInOverlap =
-        std::all_of(trackFirstHit, trackFirstHit + track.fNofHits, [&](int caHitId) {
-          CaHitTimeInfo& info = fHitTimeInfo[caHitId];
-          return info.fEventTimeMax >= windowRange.first;
-        });
-
-      // Don't save tracks from the overlap region, since they might have additional hits in the next subslice.
-      // Don't reject tracks in the overlap when no more data are left
-      const bool useFlag = !isTrackCompletelyInOverlap || !areUntouchedDataLeft;
-
-      for (int i = 0; i < track.fNofHits; i++) {
-        const int caHitId                = *(trackFirstHit + i);
-        const auto& h                    = input.GetHit(caHitId);
-        wData.IsHitKeyUsed(h.FrontKey()) = static_cast<int>(useFlag);
-        wData.IsHitKeyUsed(h.BackKey())  = static_cast<int>(useFlag);
+      int statNwindowHits = 0;
+      for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
+        statNwindowHits += wData.TsHitIndices(ista).size();
+      }
+      statNhitsProcessed += statNwindowHits;
+
+      // print the LOG for every 10 ms of data processed
+      if constexpr (0) {
+        int currentChunk = (int) ((windowRange.first - fStatTsStart) / 10.e6);
+        if (!areUntouchedDataLeft || currentChunk > statLastLogTimeChunk) {
+          statLastLogTimeChunk = currentChunk;
+          double dataRead = 100. * (windowRange.first + fWindowLength - fStatTsStart) / (fStatTsEnd - fStatTsStart);
+          if (dataRead > 100.) {
+            dataRead = 100.;
+          }
+          LOG(debug) << "CA tracker process sliding window N " << statNwindows << ": time " << windowRange.first / 1.e6
+                     << " ms + " << fWindowLength / 1.e3 << " us) with " << statNwindowHits << " hits. "
+                     << " Processing " << dataRead << " % of the TS time and "
+                     << 100. * statNhitsProcessed / fStatNhitsTotal << " % of TS hits."
+                     << " Already reconstructed " << tracks.size() << " tracks on thread #" << iThread;
+        }
+      }
 
+      //out << statNwindowHits << ' ';
+      monitor.StopTimer(ETimer::PrepareWindow);
+
+      //Timer trackingInWindow;  //DBG
+      //trackingInWindow.Start();
+      monitor.StartTimer(ETimer::TrackingWindow);
+      trackFinderWindow.CaTrackFinderSlice(input, wData);
+      monitor.StopTimer(ETimer::TrackingWindow);
+      //trackingInWindow.Stop();
+      //out << trackingInWindow.GetTotalMs() << ' ';
+
+      // save reconstructed tracks with no hits in the overlap region
+      //if (windowRange.first > 13.23e6 && windowRange.first < 13.26e6) {
+      windowRange.first += fWindowLength;
+      // we should add hits from reconstructed but not stored tracks to the new sub-timeslice
+      // we do it in a simple way by extending the tsStartNew
+      // TODO: only add those hits from the region before tsStartNew that belong to the not stored tracks
+      //out << fvWData[iThread].RecoHitIndices().size() << ' ';
+      //out << fvWData[iThread].RecoTracks().size() << '\n';
+
+      monitor.StartTimer(ETimer::StoreTracksWindow);
+      auto trackFirstHit = wData.RecoHitIndices().begin();
+
+      for (const auto& track : wData.RecoTracks()) {
+
+        const bool isTrackCompletelyInOverlap =
+          std::all_of(trackFirstHit, trackFirstHit + track.fNofHits, [&](int caHitId) {
+            CaHitTimeInfo& info = fHitTimeInfo[caHitId];
+            return info.fEventTimeMax >= windowRange.first;
+          });
+
+        // Don't save tracks from the overlap region, since they might have additional hits in the next subslice.
+        // Don't reject tracks in the overlap when no more data are left
+        const bool useFlag = !isTrackCompletelyInOverlap || !areUntouchedDataLeft;
+
+        for (int i = 0; i < track.fNofHits; i++) {
+          const int caHitId                = *(trackFirstHit + i);
+          const auto& h                    = input.GetHit(caHitId);
+          wData.IsHitKeyUsed(h.FrontKey()) = static_cast<int>(useFlag);
+          wData.IsHitKeyUsed(h.BackKey())  = static_cast<int>(useFlag);
+
+          if (useFlag) {
+            hitIndices.push_back(caHitId);
+          }
+        }
         if (useFlag) {
-          hitIndices.push_back(caHitId);
+          tracks.push_back(track);
         }
-      }
-      if (useFlag) {
-        tracks.push_back(track);
-      }
 
-      trackFirstHit += track.fNofHits;
-    }  // sub-timeslice tracks
-    monitor.StopTimer(ETimer::StoreTracksWindow);
+        trackFirstHit += track.fNofHits;
+      }  // sub-timeslice tracks
+      monitor.StopTimer(ETimer::StoreTracksWindow);
 
-    if (windowRange.first > windowRange.second) {
-      break;
-    }
-    if (!areUntouchedDataLeft) {
-      break;
-    }
-  }  // while(true)
-  monitor.StopTimer(ETimer::TrackingThread);
-  //timer.Stop();
-  //LOG(info) << "CA: finishing tracking on thread " << iThread << " (time: " << timer.GetTotalMs() << " ms, "
-  //          << "hits processed: " << statNhitsProcessed << ", "
-  //          << "hits used: " << hitIndices.size() << ')';
-}
+      if (windowRange.first > windowRange.second) {
+        break;
+      }
+      if (!areUntouchedDataLeft) {
+        break;
+      }
+    }  // while(true)
+    monitor.StopTimer(ETimer::TrackingThread);
+    //timer.Stop();
+    //LOG(info) << "CA: finishing tracking on thread " << iThread << " (time: " << timer.GetTotalMs() << " ms, "
+    //          << "hits processed: " << statNhitsProcessed << ", "
+    //          << "hits used: " << hitIndices.size() << ')';
+  }
+}  // namespace cbm::algo::ca
\ No newline at end of file
diff --git a/algo/ca/core/tracking/CaTrackFinderWindow.cxx b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
index ab40955282594fe8e049d994ecf767ef9b832db2..1dd20f404078249a7411d275b6c80fa337416e1f 100644
--- a/algo/ca/core/tracking/CaTrackFinderWindow.cxx
+++ b/algo/ca/core/tracking/CaTrackFinderWindow.cxx
@@ -39,723 +39,723 @@
 
 // #include "CaToolsDebugger.h"
 
-using Track = cbm::algo::ca::Track;
-
-using namespace cbm::algo::ca;
-
-// ---------------------------------------------------------------------------------------------------------------------
-TrackFinderWindow::TrackFinderWindow(const ca::Parameters<fvec>& pars, const fscal mass, const ca::TrackingMode& mode,
-                                     ca::TrackingMonitorData& monitorData)
-  : fParameters(pars)
-  , fDefaultMass(mass)
-  , fTrackingMode(mode)
-  , frMonitorData(monitorData)
-  , fTrackExtender(pars, mass)
-  , fCloneMerger(pars, mass)
-  , fTrackFitter(pars, mass, mode)
+namespace cbm::algo::ca
 {
-}
+  // -------------------------------------------------------------------------------------------------------------------
+  TrackFinderWindow::TrackFinderWindow(const ca::Parameters<fvec>& pars, const fscal mass, const ca::TrackingMode& mode,
+                                       ca::TrackingMonitorData& monitorData)
+    : fParameters(pars)
+    , fDefaultMass(mass)
+    , fTrackingMode(mode)
+    , frMonitorData(monitorData)
+    , fTrackExtender(pars, mass)
+    , fCloneMerger(pars, mass)
+    , fTrackFitter(pars, mass, mode)
+  {
+  }
 
-// ---------------------------------------------------------------------------------------------------------------------
-bool TrackFinderWindow::checkTripletMatch(const ca::Triplet& l, const ca::Triplet& r, fscal& dchi2,
-                                          WindowData& wData) const
-{
-  dchi2 = 1.e20;
+  // -------------------------------------------------------------------------------------------------------------------
+  bool TrackFinderWindow::checkTripletMatch(const ca::Triplet& l, const ca::Triplet& r, fscal& dchi2,
+                                            WindowData& wData) const
+  {
+    dchi2 = 1.e20;
 
-  if (r.GetMHit() != l.GetRHit()) return false;
-  if (r.GetLHit() != l.GetMHit()) return false;
+    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.GetMSta() != l.GetRSta()) return false;
+    if (r.GetLSta() != l.GetMSta()) return false;
 
-  const fscal tripletLinkChi2 = wData.CurrentIteration()->GetTripletLinkChi2();
-  if (r.IsMomentumFitted()) {
-    assert(l.IsMomentumFitted());
+    const fscal tripletLinkChi2 = wData.CurrentIteration()->GetTripletLinkChi2();
+    if (r.IsMomentumFitted()) {
+      assert(l.IsMomentumFitted());
 
-    fscal dqp = l.GetQp() - r.GetQp();
-    fscal Cqp = l.GetCqp() + r.GetCqp();
+      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 (!std::isfinite(dqp)) return false;
+      if (!std::isfinite(Cqp)) return false;
 
-    if (dqp * dqp > tripletLinkChi2 * Cqp) {
-      return false;  // bad neighbour // CHECKME why do we need recheck it?? (it really change result)
+      if (dqp * dqp > tripletLinkChi2 * Cqp) {
+        return false;  // bad neighbour // CHECKME why do we need recheck it?? (it really change result)
+      }
+      dchi2 = dqp * dqp / Cqp;
     }
-    dchi2 = dqp * dqp / Cqp;
-  }
-  else {
-    fscal dtx = l.GetTx() - r.GetTx();
-    fscal Ctx = l.GetCtx() + r.GetCtx();
+    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();
+      fscal dty = l.GetTy() - r.GetTy();
+      fscal Cty = l.GetCty() + r.GetCty();
 
-    // it shouldn't happen, but happens sometimes
+      // 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 (!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 > tripletLinkChi2 * Cty) return false;
-    if (dtx * dtx > tripletLinkChi2 * Ctx) return false;
+      if (dty * dty > tripletLinkChi2 * Cty) return false;
+      if (dtx * dtx > tripletLinkChi2 * Ctx) return false;
 
-    //dchi2 = 0.5f * (dtx * dtx / Ctx + dty * dty / Cty);
-    dchi2 = 0.;
-  }
+      //dchi2 = 0.5f * (dtx * dtx / Ctx + dty * dty / Cty);
+      dchi2 = 0.;
+    }
 
-  if (!std::isfinite(dchi2)) return false;
+    if (!std::isfinite(dchi2)) return false;
 
-  return true;
-}
+    return true;
+  }
 
 
-// **************************************************************************************************
-// *                                                                                                *
-// *                            ------ CATrackFinder procedure ------                               *
-// *                                                                                                *
-// **************************************************************************************************
+  // **************************************************************************************************
+  // *                                                                                                *
+  // *                            ------ CATrackFinder procedure ------                               *
+  // *                                                                                                *
+  // **************************************************************************************************
 
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::CaTrackFinderSlice(const ca::InputData& input, WindowData& wData)
-{
-  // Init windows
-  frMonitorData.StartTimer(ETimer::InitWindow);
-  ReadWindowData(input.GetHits(), wData);
-  frMonitorData.StopTimer(ETimer::InitWindow);
-
-  // Init grids
-  frMonitorData.StartTimer(ETimer::PrepareGrid);
-  PrepareGrid(input.GetHits(), wData);
-  frMonitorData.StopTimer(ETimer::PrepareGrid);
-
-  // Run CA iterations
-  frMonitorData.StartTimer(ETimer::FindTracks);
-  auto& caIterations = fParameters.GetCAIterations();
-  for (auto iter = caIterations.begin(); iter != caIterations.end(); ++iter) {
-
-    // ----- Prepare iteration
-    frMonitorData.StartTimer(ETimer::PrepareIteration);
-    PrepareCAIteration(*iter, wData, iter == caIterations.begin());
-    frMonitorData.StopTimer(ETimer::PrepareIteration);
-
-    // ----- Triplets construction -----
-    frMonitorData.StartTimer(ETimer::ConstructTriplets);
-    ConstructTriplets(wData);
-    frMonitorData.StopTimer(ETimer::ConstructTriplets);
-
-    // ----- Search for neighbouring triplets -----
-    frMonitorData.StartTimer(ETimer::SearchNeighbours);
-    SearchNeighbors(wData);
-    frMonitorData.StopTimer(ETimer::SearchNeighbours);
-
-    // ----- Collect track candidates and create tracks
-    frMonitorData.StartTimer(ETimer::CreateTracks);
-    CreateTracks(wData, *iter, std::get<2>(fTripletData));
-    frMonitorData.StopTimer(ETimer::CreateTracks);
-
-    // ----- Suppress strips of suppressed hits
-    frMonitorData.StartTimer(ETimer::SuppressHitKeys);
-    for (unsigned int ih = 0; ih < wData.Hits().size(); ih++) {
-      if (wData.IsHitSuppressed(ih)) {
-        const ca::Hit& hit                 = wData.Hit(ih);
-        wData.IsHitKeyUsed(hit.FrontKey()) = 1;
-        wData.IsHitKeyUsed(hit.BackKey())  = 1;
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::CaTrackFinderSlice(const ca::InputData& input, WindowData& wData)
+  {
+    // Init windows
+    frMonitorData.StartTimer(ETimer::InitWindow);
+    ReadWindowData(input.GetHits(), wData);
+    frMonitorData.StopTimer(ETimer::InitWindow);
+
+    // Init grids
+    frMonitorData.StartTimer(ETimer::PrepareGrid);
+    PrepareGrid(input.GetHits(), wData);
+    frMonitorData.StopTimer(ETimer::PrepareGrid);
+
+    // Run CA iterations
+    frMonitorData.StartTimer(ETimer::FindTracks);
+    auto& caIterations = fParameters.GetCAIterations();
+    for (auto iter = caIterations.begin(); iter != caIterations.end(); ++iter) {
+
+      // ----- Prepare iteration
+      frMonitorData.StartTimer(ETimer::PrepareIteration);
+      PrepareCAIteration(*iter, wData, iter == caIterations.begin());
+      frMonitorData.StopTimer(ETimer::PrepareIteration);
+
+      // ----- Triplets construction -----
+      frMonitorData.StartTimer(ETimer::ConstructTriplets);
+      ConstructTriplets(wData);
+      frMonitorData.StopTimer(ETimer::ConstructTriplets);
+
+      // ----- Search for neighbouring triplets -----
+      frMonitorData.StartTimer(ETimer::SearchNeighbours);
+      SearchNeighbors(wData);
+      frMonitorData.StopTimer(ETimer::SearchNeighbours);
+
+      // ----- Collect track candidates and create tracks
+      frMonitorData.StartTimer(ETimer::CreateTracks);
+      CreateTracks(wData, *iter, std::get<2>(fTripletData));
+      frMonitorData.StopTimer(ETimer::CreateTracks);
+
+      // ----- Suppress strips of suppressed hits
+      frMonitorData.StartTimer(ETimer::SuppressHitKeys);
+      for (unsigned int ih = 0; ih < wData.Hits().size(); ih++) {
+        if (wData.IsHitSuppressed(ih)) {
+          const ca::Hit& hit                 = wData.Hit(ih);
+          wData.IsHitKeyUsed(hit.FrontKey()) = 1;
+          wData.IsHitKeyUsed(hit.BackKey())  = 1;
+        }
       }
-    }
-    frMonitorData.StopTimer(ETimer::SuppressHitKeys);
-  }  // ---- Loop over Track Finder iterations: END ----//
-  frMonitorData.StopTimer(ETimer::FindTracks);
-
-  // Fit tracks
-  frMonitorData.StartTimer(ETimer::FitTracks);
-  fTrackFitter.FitCaTracks(input, wData);
-  frMonitorData.StopTimer(ETimer::FitTracks);
-
-  // Merge clones
-  frMonitorData.StartTimer(ETimer::MergeClones);
-  fCloneMerger.Exec(input, wData);
-  frMonitorData.StopTimer(ETimer::MergeClones);
-
-  // Fit tracks
-  frMonitorData.StartTimer(ETimer::FitTracks);
-  fTrackFitter.FitCaTracks(input, wData);
-  frMonitorData.StopTimer(ETimer::FitTracks);
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::ReadWindowData(const Vector<Hit>& hits, WindowData& wData)
-{
-  int nHits = 0;
-  for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
-    wData.HitStartIndexOnStation(iS) = nHits;
-    wData.NofHitsOnStation(iS)       = wData.TsHitIndices(iS).size();
-    nHits += wData.NofHitsOnStation(iS);
+      frMonitorData.StopTimer(ETimer::SuppressHitKeys);
+    }  // ---- Loop over Track Finder iterations: END ----//
+    frMonitorData.StopTimer(ETimer::FindTracks);
+
+    // Fit tracks
+    frMonitorData.StartTimer(ETimer::FitTracks);
+    fTrackFitter.FitCaTracks(input, wData);
+    frMonitorData.StopTimer(ETimer::FitTracks);
+
+    // Merge clones
+    frMonitorData.StartTimer(ETimer::MergeClones);
+    fCloneMerger.Exec(input, wData);
+    frMonitorData.StopTimer(ETimer::MergeClones);
+
+    // Fit tracks
+    frMonitorData.StartTimer(ETimer::FitTracks);
+    fTrackFitter.FitCaTracks(input, wData);
+    frMonitorData.StopTimer(ETimer::FitTracks);
   }
-  wData.HitStartIndexOnStation(fParameters.GetNstationsActive()) = nHits;
-  wData.ResetHitData(nHits);
-
-  for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
-    int iFstHit = wData.HitStartIndexOnStation(iS);
-    for (ca::HitIndex_t ih = 0; ih < wData.TsHitIndices(iS).size(); ++ih) {
-      ca::Hit h = hits[wData.TsHitIndex(iS, ih)];  /// D.S. 29.7.24: There is a copy operation here. Can be avoided?
-      h.SetId(wData.TsHitIndex(iS, ih));
-      wData.Hit(iFstHit + ih) = h;
+
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::ReadWindowData(const Vector<Hit>& hits, WindowData& wData)
+  {
+    int nHits = 0;
+    for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
+      wData.HitStartIndexOnStation(iS) = nHits;
+      wData.NofHitsOnStation(iS)       = wData.TsHitIndices(iS).size();
+      nHits += wData.NofHitsOnStation(iS);
+    }
+    wData.HitStartIndexOnStation(fParameters.GetNstationsActive()) = nHits;
+    wData.ResetHitData(nHits);
+
+    for (int iS = 0; iS < fParameters.GetNstationsActive(); iS++) {
+      int iFstHit = wData.HitStartIndexOnStation(iS);
+      for (ca::HitIndex_t ih = 0; ih < wData.TsHitIndices(iS).size(); ++ih) {
+        ca::Hit h = hits[wData.TsHitIndex(iS, ih)];  /// D.S. 29.7.24: There is a copy operation here. Can be avoided?
+        h.SetId(wData.TsHitIndex(iS, ih));
+        wData.Hit(iFstHit + ih) = h;
+      }
     }
-  }
 
-  if constexpr (fDebug) {
-    LOG(info) << "===== Sliding Window hits: ";
-    for (int i = 0; i < nHits; ++i) {
-      LOG(info) << "    " << wData.Hit(i).ToString();
+    if constexpr (fDebug) {
+      LOG(info) << "===== Sliding Window hits: ";
+      for (int i = 0; i < nHits; ++i) {
+        LOG(info) << "    " << wData.Hit(i).ToString();
+      }
+      LOG(info) << "===== ";
     }
-    LOG(info) << "===== ";
-  }
 
-  wData.RecoTracks().clear();
-  wData.RecoTracks().reserve(2 * nHits / fParameters.GetNstationsActive());
+    wData.RecoTracks().clear();
+    wData.RecoTracks().reserve(2 * nHits / fParameters.GetNstationsActive());
+
+    wData.RecoHitIndices().clear();
+    wData.RecoHitIndices().reserve(2 * nHits);
+  }
 
-  wData.RecoHitIndices().clear();
-  wData.RecoHitIndices().reserve(2 * nHits);
-}
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::PrepareGrid(const Vector<Hit>& hits, WindowData& wData)
+  {
+    for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
+
+      fscal lasttime  = std::numeric_limits<fscal>::infinity();
+      fscal starttime = -std::numeric_limits<fscal>::infinity();
+      fscal gridMinX  = -0.1;
+      fscal gridMaxX  = 0.1;
+      fscal gridMinY  = -0.1;
+      fscal gridMaxY  = 0.1;
+
+      for (ca::HitIndex_t ih = 0; ih < wData.TsHitIndices(iS).size(); ++ih) {
+        const ca::Hit& h = hits[wData.TsHitIndex(iS, ih)];
+
+        gridMinX = std::min(gridMinX, h.X());
+        gridMinY = std::min(gridMinY, h.Y());
+        gridMaxX = std::max(gridMaxX, h.X());
+        gridMaxY = std::max(gridMaxY, h.Y());
+
+        const fscal time = h.T();
+        assert(std::isfinite(time));
+        lasttime  = std::min(lasttime, time);
+        starttime = std::max(starttime, time);
+      }
 
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::PrepareGrid(const Vector<Hit>& hits, WindowData& wData)
-{
-  for (int iS = 0; iS < fParameters.GetNstationsActive(); ++iS) {
-
-    fscal lasttime  = std::numeric_limits<fscal>::infinity();
-    fscal starttime = -std::numeric_limits<fscal>::infinity();
-    fscal gridMinX  = -0.1;
-    fscal gridMaxX  = 0.1;
-    fscal gridMinY  = -0.1;
-    fscal gridMaxY  = 0.1;
-
-    for (ca::HitIndex_t ih = 0; ih < wData.TsHitIndices(iS).size(); ++ih) {
-      const ca::Hit& h = hits[wData.TsHitIndex(iS, ih)];
-
-      gridMinX = std::min(gridMinX, h.X());
-      gridMinY = std::min(gridMinY, h.Y());
-      gridMaxX = std::max(gridMaxX, h.X());
-      gridMaxY = std::max(gridMaxY, h.Y());
-
-      const fscal time = h.T();
-      assert(std::isfinite(time));
-      lasttime  = std::min(lasttime, time);
-      starttime = std::max(starttime, time);
+      // TODO: changing the grid also changes the result. Investigate why it happens.
+      // TODO: find the optimal grid size
+
+      const int nSliceHits = wData.TsHitIndices(iS).size();
+      const fscal sizeY    = gridMaxY - gridMinY;
+      const fscal sizeX    = gridMaxX - gridMinX;
+      const int nBins2D    = 1 + nSliceHits;
+
+      // TODO: SG: the coefficients should be removed
+      const fscal scale    = fParameters.GetStation(iS).GetZ<fscal>() - fParameters.GetTargetPositionZ()[0];
+      const fscal maxScale = 0.3 * scale;
+      const fscal minScale = 0.01 * scale;
+
+      fscal yStep = 0.3 * sizeY / sqrt(nBins2D);
+      fscal xStep = 0.8 * sizeX / sqrt(nBins2D);
+      yStep       = std::clamp(yStep, minScale, maxScale);
+      xStep       = std::clamp(xStep, minScale, maxScale);
+
+      auto& grid = wData.Grid(iS);
+      grid.BuildBins(gridMinX, gridMaxX, gridMinY, gridMaxY, xStep, yStep);
+      /* clang-format off */
+      grid.StoreHits(wData.Hits(), 
+                     wData.HitStartIndexOnStation(iS), 
+                     wData.NofHitsOnStation(iS),
+                     wData.HitKeyFlags());
+      /* clang-format on */
     }
-
-    // TODO: changing the grid also changes the result. Investigate why it happens.
-    // TODO: find the optimal grid size
-
-    const int nSliceHits = wData.TsHitIndices(iS).size();
-    const fscal sizeY    = gridMaxY - gridMinY;
-    const fscal sizeX    = gridMaxX - gridMinX;
-    const int nBins2D    = 1 + nSliceHits;
-
-    // TODO: SG: the coefficients should be removed
-    const fscal scale    = fParameters.GetStation(iS).GetZ<fscal>() - fParameters.GetTargetPositionZ()[0];
-    const fscal maxScale = 0.3 * scale;
-    const fscal minScale = 0.01 * scale;
-
-    fscal yStep = 0.3 * sizeY / sqrt(nBins2D);
-    fscal xStep = 0.8 * sizeX / sqrt(nBins2D);
-    yStep       = std::clamp(yStep, minScale, maxScale);
-    xStep       = std::clamp(xStep, minScale, maxScale);
-
-    auto& grid = wData.Grid(iS);
-    grid.BuildBins(gridMinX, gridMaxX, gridMinY, gridMaxY, xStep, yStep);
-    /* clang-format off */
-    grid.StoreHits(wData.Hits(), 
-                   wData.HitStartIndexOnStation(iS), 
-                   wData.NofHitsOnStation(iS),
-                   wData.HitKeyFlags());
-    /* clang-format on */
   }
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::PrepareCAIteration(const ca::Iteration& caIteration, WindowData& wData, const bool isFirst)
-{
-  wData.SetCurrentIteration(&caIteration);
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::PrepareCAIteration(const ca::Iteration& caIteration, WindowData& wData, const bool isFirst)
+  {
+    wData.SetCurrentIteration(&caIteration);
 
-  // Check if it is not the first element
-  if (!isFirst) {
-    for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
-      wData.Grid(ista).RemoveUsedHits(wData.Hits(), wData.HitKeyFlags());
+    // Check if it is not the first element
+    if (!isFirst) {
+      for (int ista = 0; ista < fParameters.GetNstationsActive(); ++ista) {
+        wData.Grid(ista).RemoveUsedHits(wData.Hits(), wData.HitKeyFlags());
+      }
     }
-  }
 
-  // --> frAlgo.fIsWindowHitSuppressed.reset(frAlgo.fWindowHits.size(), 0);
-  wData.ResetHitSuppressionFlags();  // TODO: ??? No effect?
+    // --> frAlgo.fIsWindowHitSuppressed.reset(frAlgo.fWindowHits.size(), 0);
+    wData.ResetHitSuppressionFlags();  // TODO: ??? No effect?
 
-  // --- SET PARAMETERS FOR THE ITERATION ---
-  // define the target
-  const fscal SigmaTargetX = caIteration.GetTargetPosSigmaX();
-  const fscal SigmaTargetY = caIteration.GetTargetPosSigmaY();  // target constraint [cm]
+    // --- SET PARAMETERS FOR THE ITERATION ---
+    // define the target
+    const fscal SigmaTargetX = caIteration.GetTargetPosSigmaX();
+    const fscal SigmaTargetY = caIteration.GetTargetPosSigmaY();  // target constraint [cm]
 
-  // Select magnetic field. For primary tracks - fVtxFieldValue, for secondary tracks - st.fieldSlice
-  if (caIteration.GetPrimaryFlag()) {
-    wData.TargB() = fParameters.GetVertexFieldValue();
+    // Select magnetic field. For primary tracks - fVtxFieldValue, for secondary tracks - st.fieldSlice
+    if (caIteration.GetPrimaryFlag()) {
+      wData.TargB() = fParameters.GetVertexFieldValue();
+    }
+    else {
+      wData.TargB() = fParameters.GetStation(0).fieldSlice.GetFieldValue(0, 0);
+    }  // NOTE: calculates field frAlgo.fTargB in the center of 0th station
+
+    wData.TargetMeasurement().SetX(fParameters.GetTargetPositionX());
+    wData.TargetMeasurement().SetY(fParameters.GetTargetPositionY());
+    wData.TargetMeasurement().SetDx2(SigmaTargetX * SigmaTargetX);
+    wData.TargetMeasurement().SetDxy(0);
+    wData.TargetMeasurement().SetDy2(SigmaTargetY * SigmaTargetY);
+    wData.TargetMeasurement().SetNdfX(1);
+    wData.TargetMeasurement().SetNdfY(1);
   }
-  else {
-    wData.TargB() = fParameters.GetStation(0).fieldSlice.GetFieldValue(0, 0);
-  }  // NOTE: calculates field frAlgo.fTargB in the center of 0th station
-
-  wData.TargetMeasurement().SetX(fParameters.GetTargetPositionX());
-  wData.TargetMeasurement().SetY(fParameters.GetTargetPositionY());
-  wData.TargetMeasurement().SetDx2(SigmaTargetX * SigmaTargetX);
-  wData.TargetMeasurement().SetDxy(0);
-  wData.TargetMeasurement().SetDy2(SigmaTargetY * SigmaTargetY);
-  wData.TargetMeasurement().SetNdfX(1);
-  wData.TargetMeasurement().SetNdfY(1);
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::ConstructTriplets(WindowData& wData)
-{
-  auto& [vHitFirstTriplet, vHitNofTriplets, vTriplets] = fTripletData;
-  vHitFirstTriplet.reset(wData.Hits().size(), 0);  /// link hit -> first triplet { hit, *, *}
-  vHitNofTriplets.reset(wData.Hits().size(), 0);   /// link hit ->n triplets { hit, *, *}
 
-  ca::TripletConstructor constructor(fParameters, wData, fDefaultMass, fTrackingMode);
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::ConstructTriplets(WindowData& wData)
+  {
+    auto& [vHitFirstTriplet, vHitNofTriplets, vTriplets] = fTripletData;
+    vHitFirstTriplet.reset(wData.Hits().size(), 0);  /// link hit -> first triplet { hit, *, *}
+    vHitNofTriplets.reset(wData.Hits().size(), 0);   /// link hit ->n triplets { hit, *, *}
 
-  // prepare triplet storage
-  for (int j = 0; j < fParameters.GetNstationsActive(); j++) {
-    const size_t nHitsStation = wData.TsHitIndices(j).size();
-    vTriplets[j].clear();
-    vTriplets[j].reserve(2 * nHitsStation);
-  }
+    ca::TripletConstructor constructor(fParameters, wData, fDefaultMass, fTrackingMode);
 
-  // indices of the two neighbouring station, taking into account allowed gaps
-  std::vector<std::pair<int, int>> staPattern;
-  for (int gap = 0; gap <= wData.CurrentIteration()->GetMaxStationGap(); gap++) {
-    for (int i = 0; i <= gap; i++) {
-      staPattern.push_back(std::make_pair(1 + i, 2 + gap));
+    // prepare triplet storage
+    for (int j = 0; j < fParameters.GetNstationsActive(); j++) {
+      const size_t nHitsStation = wData.TsHitIndices(j).size();
+      vTriplets[j].clear();
+      vTriplets[j].reserve(2 * nHitsStation);
     }
-  }
 
-  for (int istal = fParameters.GetNstationsActive() - 2; istal >= wData.CurrentIteration()->GetFirstStationIndex();
-       istal--) {
-    // start with downstream chambers
-    const auto& grid = wData.Grid(istal);
-    for (auto& entry : grid.GetEntries()) {
-      ca::HitIndex_t ihitl = entry.GetObjectId();
-      const size_t oldSize = vTriplets[istal].size();
-      for (auto& pattern : staPattern) {
-        constructor.CreateTripletsForHit(fvTriplets, istal, istal + pattern.first, istal + pattern.second, ihitl);
-        vTriplets[istal].insert(vTriplets[istal].end(), fvTriplets.begin(), fvTriplets.end());
+    // indices of the two neighbouring station, taking into account allowed gaps
+    std::vector<std::pair<int, int>> staPattern;
+    for (int gap = 0; gap <= wData.CurrentIteration()->GetMaxStationGap(); gap++) {
+      for (int i = 0; i <= gap; i++) {
+        staPattern.push_back(std::make_pair(1 + i, 2 + gap));
       }
-      vHitFirstTriplet[ihitl] = PackTripletId(istal, oldSize);
-      vHitNofTriplets[ihitl]  = vTriplets[istal].size() - oldSize;
     }
-  }  // istal
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::SearchNeighbors(WindowData& wData)
-{
-  auto& [vHitFirstTriplet, vHitNofTriplets, vTriplets] = fTripletData;
+    for (int istal = fParameters.GetNstationsActive() - 2; istal >= wData.CurrentIteration()->GetFirstStationIndex();
+         istal--) {
+      // start with downstream chambers
+      const auto& grid = wData.Grid(istal);
+      for (auto& entry : grid.GetEntries()) {
+        ca::HitIndex_t ihitl = entry.GetObjectId();
+        const size_t oldSize = vTriplets[istal].size();
+        for (auto& pattern : staPattern) {
+          constructor.CreateTripletsForHit(fvTriplets, istal, istal + pattern.first, istal + pattern.second, ihitl);
+          vTriplets[istal].insert(vTriplets[istal].end(), fvTriplets.begin(), fvTriplets.end());
+        }
+        vHitFirstTriplet[ihitl] = PackTripletId(istal, oldSize);
+        vHitNofTriplets[ihitl]  = vTriplets[istal].size() - oldSize;
+      }
+    }  // istal
+  }
 
-  for (int istal = fParameters.GetNstationsActive() - 2; istal >= wData.CurrentIteration()->GetFirstStationIndex();
-       istal--) {
-    // start with downstream chambers
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::SearchNeighbors(WindowData& wData)
+  {
+    auto& [vHitFirstTriplet, vHitNofTriplets, vTriplets] = fTripletData;
 
-    for (ca::Triplet& tr : vTriplets[istal]) {
-      unsigned int nNeighbours   = vHitNofTriplets[tr.GetMHit()];
-      unsigned int neighLocation = vHitFirstTriplet[tr.GetMHit()];
-      unsigned int neighStation  = TripletId2Station(neighLocation);
-      unsigned int neighTriplet  = TripletId2Triplet(neighLocation);
+    for (int istal = fParameters.GetNstationsActive() - 2; istal >= wData.CurrentIteration()->GetFirstStationIndex();
+         istal--) {
+      // start with downstream chambers
 
-      if (nNeighbours > 0) {
-        assert((int) neighStation >= istal + 1
-               && (int) neighStation <= istal + 1 + wData.CurrentIteration()->GetMaxStationGap());
-      }
+      for (ca::Triplet& tr : vTriplets[istal]) {
+        unsigned int nNeighbours   = vHitNofTriplets[tr.GetMHit()];
+        unsigned int neighLocation = vHitFirstTriplet[tr.GetMHit()];
+        unsigned int neighStation  = TripletId2Station(neighLocation);
+        unsigned int neighTriplet  = TripletId2Triplet(neighLocation);
 
-      unsigned char level = 0;
+        if (nNeighbours > 0) {
+          assert((int) neighStation >= istal + 1
+                 && (int) neighStation <= istal + 1 + wData.CurrentIteration()->GetMaxStationGap());
+        }
 
-      for (unsigned int iN = 0; iN < nNeighbours; ++iN, ++neighTriplet, ++neighLocation) {
+        unsigned char level = 0;
 
-        ca::Triplet& neighbour = vTriplets[neighStation][neighTriplet];
+        for (unsigned int iN = 0; iN < nNeighbours; ++iN, ++neighTriplet, ++neighLocation) {
 
-        fscal dchi2 = 0.;
-        if (!checkTripletMatch(tr, neighbour, dchi2, wData)) continue;
+          ca::Triplet& neighbour = vTriplets[neighStation][neighTriplet];
 
-        if (tr.GetFNeighbour() == 0) {
-          tr.SetFNeighbour(neighLocation);
-        }
-        tr.SetNNeighbours(neighLocation - tr.GetFNeighbour() + 1);
+          fscal dchi2 = 0.;
+          if (!checkTripletMatch(tr, neighbour, dchi2, wData)) continue;
 
-        level = std::max(level, static_cast<unsigned char>(neighbour.GetLevel() + 1));
+          if (tr.GetFNeighbour() == 0) {
+            tr.SetFNeighbour(neighLocation);
+          }
+          tr.SetNNeighbours(neighLocation - tr.GetFNeighbour() + 1);
+
+          level = std::max(level, static_cast<unsigned char>(neighbour.GetLevel() + 1));
+        }
+        tr.SetLevel(level);
       }
-      tr.SetLevel(level);
+      frMonitorData.IncrementCounter(ECounter::Triplet, vTriplets[istal].size());
     }
-    frMonitorData.IncrementCounter(ECounter::Triplet, vTriplets[istal].size());
   }
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::CreateTracks(WindowData& wData, const ca::Iteration& caIteration, TripletArray_t& vTriplets)
-{
-  // min level to start triplet. So min track length = min_level+3.
-  const int min_level = wData.CurrentIteration()->GetTrackFromTripletsFlag()
-                          ? 0
-                          : std::min(caIteration.GetMinNhits(), caIteration.GetMinNhitsStation0()) - 3;
-
-  // 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
-    CreateTrackCandidates(wData, vTriplets, min_level, firstTripletLevel);
-    DoCompetitionLoop(wData);
-    SelectTracks(wData);
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::CreateTracks(WindowData& wData, const ca::Iteration& caIteration, TripletArray_t& vTriplets)
+  {
+    // min level to start triplet. So min track length = min_level+3.
+    const int min_level = wData.CurrentIteration()->GetTrackFromTripletsFlag()
+                            ? 0
+                            : std::min(caIteration.GetMinNhits(), caIteration.GetMinNhitsStation0()) - 3;
+
+    // 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
+      CreateTrackCandidates(wData, vTriplets, min_level, firstTripletLevel);
+      DoCompetitionLoop(wData);
+      SelectTracks(wData);
+    }
   }
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::CreateTrackCandidates(WindowData& wData, TripletArray_t& vTriplets, const int min_level,
-                                              const int firstTripletLevel)
-{
-  //  how many levels to check
-  int nlevel = (fParameters.GetNstationsActive() - 2) - firstTripletLevel + 1;
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::CreateTrackCandidates(WindowData& wData, TripletArray_t& vTriplets, const int min_level,
+                                                const int firstTripletLevel)
+  {
+    //  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
+    const unsigned char min_best_l =
+      (firstTripletLevel > min_level) ? firstTripletLevel + 2 : min_level + 3;  // loose maximum
 
-  // Uses persistent field to save memory allocations.
-  // fNewTr is only used here!
-  ca::Branch(&new_tr)[constants::size::MaxNstations] = fNewTr;
+    // Uses persistent field to save memory allocations.
+    // fNewTr is only used here!
+    ca::Branch(&new_tr)[constants::size::MaxNstations] = fNewTr;
 
-  fvTrackCandidates.clear();
-  fvTrackCandidates.reserve(wData.Hits().size() / 10);
+    fvTrackCandidates.clear();
+    fvTrackCandidates.reserve(wData.Hits().size() / 10);
 
-  for (const auto& h : wData.Hits()) {
-    fvHitKeyToTrack[h.FrontKey()] = -1;
-    fvHitKeyToTrack[h.BackKey()]  = -1;
-  }
+    for (const auto& h : wData.Hits()) {
+      fvHitKeyToTrack[h.FrontKey()] = -1;
+      fvHitKeyToTrack[h.BackKey()]  = -1;
+    }
 
-  //== Loop over triplets with the required level, find and store track candidates
-  for (int istaF = wData.CurrentIteration()->GetFirstStationIndex();
-       istaF <= fParameters.GetNstationsActive() - 3 - firstTripletLevel; ++istaF) {
+    //== Loop over triplets with the required level, find and store track candidates
+    for (int istaF = wData.CurrentIteration()->GetFirstStationIndex();
+         istaF <= fParameters.GetNstationsActive() - 3 - firstTripletLevel; ++istaF) {
 
-    if (--nlevel == 0) break;  //TODO: SG: this is not needed
+      if (--nlevel == 0) break;  //TODO: SG: this is not needed
 
-    for (ca::Triplet& first_trip : vTriplets[istaF]) {
+      for (ca::Triplet& first_trip : vTriplets[istaF]) {
 
-      const auto& fstTripLHit = wData.Hit(first_trip.GetLHit());
-      if (wData.IsHitKeyUsed(fstTripLHit.FrontKey()) || wData.IsHitKeyUsed(fstTripLHit.BackKey())) {
-        continue;
-      }
+        const auto& fstTripLHit = wData.Hit(first_trip.GetLHit());
+        if (wData.IsHitKeyUsed(fstTripLHit.FrontKey()) || wData.IsHitKeyUsed(fstTripLHit.BackKey())) {
+          continue;
+        }
 
-      //  skip track candidates that are too short
+        //  skip track candidates that are too short
 
-      int minNhits = wData.CurrentIteration()->GetMinNhits();
+        int minNhits = wData.CurrentIteration()->GetMinNhits();
 
-      if (fstTripLHit.Station() == 0) {
-        minNhits = wData.CurrentIteration()->GetMinNhitsStation0();
-      }
-      if (wData.CurrentIteration()->GetTrackFromTripletsFlag()) {
-        minNhits = 0;
-      }
+        if (fstTripLHit.Station() == 0) {
+          minNhits = wData.CurrentIteration()->GetMinNhitsStation0();
+        }
+        if (wData.CurrentIteration()->GetTrackFromTripletsFlag()) {
+          minNhits = 0;
+        }
 
-      if (3 + first_trip.GetLevel() < minNhits) {
-        continue;
-      }
+        if (3 + first_trip.GetLevel() < minNhits) {
+          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;
-      }
+        // 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;
+        }
 
-      ca::Branch curr_tr;
-      curr_tr.AddHit(first_trip.GetLHit());
-      curr_tr.SetChi2(first_trip.GetChi2());
+        ca::Branch curr_tr;
+        curr_tr.AddHit(first_trip.GetLHit());
+        curr_tr.SetChi2(first_trip.GetChi2());
 
-      ca::Branch best_tr = curr_tr;
+        ca::Branch best_tr = curr_tr;
 
-      /// reqursive func to build a tree of possible track-candidates and choose the best
-      CAFindTrack(istaF, best_tr, &first_trip, curr_tr, min_best_l, new_tr, wData, vTriplets);
+        /// reqursive func to build a tree of possible track-candidates and choose the best
+        CAFindTrack(istaF, best_tr, &first_trip, curr_tr, min_best_l, new_tr, wData, vTriplets);
 
-      if (best_tr.NofHits() < firstTripletLevel + 2) continue;  // loose maximum one hit
+        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
+        if (best_tr.NofHits() < min_level + 3) continue;  // should find all hits for min_level
 
-      if (best_tr.NofHits() < minNhits) {
-        continue;
-      }
+        if (best_tr.NofHits() < minNhits) {
+          continue;
+        }
 
-      int ndf = best_tr.NofHits() * 2 - 5;
+        int ndf = best_tr.NofHits() * 2 - 5;
 
-      // TODO: automatize the NDF calculation
+        // TODO: automatize the NDF calculation
 
-      if (ca::TrackingMode::kGlobal == fTrackingMode || ca::TrackingMode::kMcbm == fTrackingMode) {
-        ndf = best_tr.NofHits() * 2 - 4;
-      }
+        if (ca::TrackingMode::kGlobal == fTrackingMode || ca::TrackingMode::kMcbm == fTrackingMode) {
+          ndf = best_tr.NofHits() * 2 - 4;
+        }
 
-      best_tr.SetChi2(best_tr.Chi2() / ndf);
-      if (fParameters.GetGhostSuppression()) {
-        if (3 == best_tr.NofHits()) {
-          if (!wData.CurrentIteration()->GetPrimaryFlag() && (istaF != 0)) continue;  // too /*short*/ non-MAPS track
-          if (wData.CurrentIteration()->GetPrimaryFlag() && (best_tr.Chi2() > 5.0)) continue;
+        best_tr.SetChi2(best_tr.Chi2() / ndf);
+        if (fParameters.GetGhostSuppression()) {
+          if (3 == best_tr.NofHits()) {
+            if (!wData.CurrentIteration()->GetPrimaryFlag() && (istaF != 0)) continue;  // too /*short*/ non-MAPS track
+            if (wData.CurrentIteration()->GetPrimaryFlag() && (best_tr.Chi2() > 5.0)) continue;
+          }
         }
-      }
-      fvTrackCandidates.push_back(best_tr);
-      ca::Branch& tr = fvTrackCandidates.back();
-      tr.SetStation(istaF);
-      tr.SetId(fvTrackCandidates.size() - 1);
-      // Mark the candidate as dead. To became alive it should first pass the competition in DoCompetitionLoop
-      tr.SetAlive(false);
-      if constexpr (fDebug) {
-        std::stringstream s;
-        s << "iter " << wData.CurrentIteration()->GetName() << ", track candidate " << fvTrackCandidates.size() - 1
-          << " found, L = " << best_tr.NofHits() << " chi2= " << best_tr.Chi2() << " hits: ";
-        for (auto hitIdLoc : tr.Hits()) {
-          const auto hitId = wData.Hit(hitIdLoc).Id();
-          s << hitId << " (mc " << ca::Framework::GetMcTrackIdForCaHit(hitId) << ") ";
+        fvTrackCandidates.push_back(best_tr);
+        ca::Branch& tr = fvTrackCandidates.back();
+        tr.SetStation(istaF);
+        tr.SetId(fvTrackCandidates.size() - 1);
+        // Mark the candidate as dead. To became alive it should first pass the competition in DoCompetitionLoop
+        tr.SetAlive(false);
+        if constexpr (fDebug) {
+          std::stringstream s;
+          s << "iter " << wData.CurrentIteration()->GetName() << ", track candidate " << fvTrackCandidates.size() - 1
+            << " found, L = " << best_tr.NofHits() << " chi2= " << best_tr.Chi2() << " hits: ";
+          for (auto hitIdLoc : tr.Hits()) {
+            const auto hitId = wData.Hit(hitIdLoc).Id();
+            s << hitId << " (mc " << ca::Framework::GetMcTrackIdForCaHit(hitId) << ") ";
+          }
+          LOG(info) << s.str();
         }
-        LOG(info) << s.str();
-      }
-    }  // itrip
-  }    // istaF
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::DoCompetitionLoop(const WindowData& wData)
-{
+      }  // itrip
+    }    // istaF
+  }
 
-  // look at the dead track candidates in fvTrackCandidates pool; select the best ones and make them alive
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::DoCompetitionLoop(const WindowData& wData)
+  {
 
-  for (int iComp = 0; (iComp < 100); ++iComp) {
+    // look at the dead track candidates in fvTrackCandidates pool; select the best ones and make them alive
 
-    bool repeatCompetition = false;
+    for (int iComp = 0; (iComp < 100); ++iComp) {
 
-    // == Loop over track candidates and mark their strips
-    for (ca::Branch& tr : fvTrackCandidates) {
-      if (tr.IsAlive()) {
-        continue;
-      }
-      for (auto& hitId : tr.Hits()) {
+      bool repeatCompetition = false;
 
-        auto updateStrip = [&](int& strip) {
-          if ((strip >= 0) && (strip != tr.Id())) {  // strip is used by other candidate
-            const auto& other = fvTrackCandidates[strip];
-            if (!other.IsAlive() && tr.IsBetterThan(other)) {
-              strip = tr.Id();
+      // == Loop over track candidates and mark their strips
+      for (ca::Branch& tr : fvTrackCandidates) {
+        if (tr.IsAlive()) {
+          continue;
+        }
+        for (auto& hitId : tr.Hits()) {
+
+          auto updateStrip = [&](int& strip) {
+            if ((strip >= 0) && (strip != tr.Id())) {  // strip is used by other candidate
+              const auto& other = fvTrackCandidates[strip];
+              if (!other.IsAlive() && tr.IsBetterThan(other)) {
+                strip = tr.Id();
+              }
+              else {
+                return false;
+              }
             }
             else {
-              return false;
+              strip = tr.Id();
             }
+            return true;
+          };
+
+          const ca::Hit& h = wData.Hit(hitId);
+          if (!updateStrip(fvHitKeyToTrack[h.FrontKey()])) {  // front  strip
+            break;
           }
-          else {
-            strip = tr.Id();
+          if (!updateStrip(fvHitKeyToTrack[h.BackKey()])) {  // back  strip
+            break;
           }
-          return true;
-        };
+        }  // loop over hits
+      }    // itrack
+
+      // == Check if some suppressed candidates are still alive
 
-        const ca::Hit& h = wData.Hit(hitId);
-        if (!updateStrip(fvHitKeyToTrack[h.FrontKey()])) {  // front  strip
-          break;
+      for (ca::Branch& tr : fvTrackCandidates) {
+        if (tr.IsAlive()) {
+          continue;
         }
-        if (!updateStrip(fvHitKeyToTrack[h.BackKey()])) {  // back  strip
-          break;
+
+        tr.SetAlive(true);
+        for (const auto& hitIndex : tr.Hits()) {
+          if (!tr.IsAlive()) break;
+          const ca::Hit& h = wData.Hit(hitIndex);
+          tr.SetAlive((fvHitKeyToTrack[h.FrontKey()] == tr.Id()) && (fvHitKeyToTrack[h.BackKey()] == tr.Id()));
         }
-      }  // loop over hits
-    }    // itrack
 
-    // == Check if some suppressed candidates are still alive
+        if (!tr.IsAlive()) {  // release strips
+          for (auto hitId : tr.Hits()) {
+            const ca::Hit& h = wData.Hit(hitId);
+            if (fvHitKeyToTrack[h.FrontKey()] == tr.Id()) {
+              fvHitKeyToTrack[h.FrontKey()] = -1;
+            }
+            if (fvHitKeyToTrack[h.BackKey()] == tr.Id()) {
+              fvHitKeyToTrack[h.BackKey()] = -1;
+            }
+          }
+        }
+        else {
+          repeatCompetition = true;
+        }
+      }  // itrack
 
-    for (ca::Branch& tr : fvTrackCandidates) {
-      if (tr.IsAlive()) {
-        continue;
-      }
+      if (!repeatCompetition) break;
+    }  // competitions
+  }
+
+  // -------------------------------------------------------------------------------------------------------------------
+  void TrackFinderWindow::SelectTracks(WindowData& wData)
+  {
+    for (Tindex iCandidate = 0; iCandidate < (Tindex) fvTrackCandidates.size(); ++iCandidate) {
+      ca::Branch& tr = fvTrackCandidates[iCandidate];
 
-      tr.SetAlive(true);
-      for (const auto& hitIndex : tr.Hits()) {
-        if (!tr.IsAlive()) break;
-        const ca::Hit& h = wData.Hit(hitIndex);
-        tr.SetAlive((fvHitKeyToTrack[h.FrontKey()] == tr.Id()) && (fvHitKeyToTrack[h.BackKey()] == tr.Id()));
+      if constexpr (fDebug) {
+        LOG(info) << "iter " << wData.CurrentIteration()->GetName() << ", track candidate " << iCandidate
+                  << ": alive = " << tr.IsAlive();
       }
+      if (!tr.IsAlive()) continue;
 
-      if (!tr.IsAlive()) {  // release strips
-        for (auto hitId : tr.Hits()) {
-          const ca::Hit& h = wData.Hit(hitId);
-          if (fvHitKeyToTrack[h.FrontKey()] == tr.Id()) {
-            fvHitKeyToTrack[h.FrontKey()] = -1;
-          }
-          if (fvHitKeyToTrack[h.BackKey()] == tr.Id()) {
-            fvHitKeyToTrack[h.BackKey()] = -1;
-          }
+      if (wData.CurrentIteration()->GetExtendTracksFlag()) {
+        if (tr.NofHits() < fParameters.GetNstationsActive()) {
+          fTrackExtender.ExtendBranch(tr, wData);
         }
       }
-      else {
-        repeatCompetition = true;
-      }
-    }  // itrack
 
-    if (!repeatCompetition) break;
-  }  // competitions
-}
+      for (auto iHit : tr.Hits()) {
+        const ca::Hit& hit = wData.Hit(iHit);
+        /// used strips are marked
+        wData.IsHitKeyUsed(hit.FrontKey()) = 1;
+        wData.IsHitKeyUsed(hit.BackKey())  = 1;
+        wData.RecoHitIndices().push_back(hit.Id());
+      }
+      Track t;
+      t.fNofHits = tr.NofHits();
+      wData.RecoTracks().push_back(t);
+      if (0) {  // SG debug
+        std::stringstream s;
+        s << "store track " << iCandidate << " chi2= " << tr.Chi2() << "\n";
+        s << " hits: ";
+        for (auto hitLoc : tr.Hits()) {
+          auto hitId = wData.Hit(hitLoc).Id();
+          s << ca::Framework::GetMcTrackIdForCaHit(hitId) << " ";
+        }
+        LOG(info) << s.str();
+      }
+    }  // tracks
+  }
 
-// ---------------------------------------------------------------------------------------------------------------------
-void TrackFinderWindow::SelectTracks(WindowData& wData)
-{
-  for (Tindex iCandidate = 0; iCandidate < (Tindex) fvTrackCandidates.size(); ++iCandidate) {
-    ca::Branch& tr = fvTrackCandidates[iCandidate];
+  /** *************************************************************
+       *                                                              *
+       *     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, WindowData& wData,
+                                      TripletArray_t& vTriplets)
+  /// recursive search for tracks
+  /// input: @ista - station index, @&best_tr - best track for the privious call
+  /// output: @&NCalls - number of function calls
+  {
 
-    if constexpr (fDebug) {
-      LOG(info) << "iter " << wData.CurrentIteration()->GetName() << ", track candidate " << iCandidate
-                << ": alive = " << tr.IsAlive();
-    }
-    if (!tr.IsAlive()) continue;
+    if (curr_trip->GetLevel() == 0)  // the end of the track -> check and store
+    {
+      // -- finish with current track
+      // add rest of hits
+      const auto& hitM = wData.Hit(curr_trip->GetMHit());
+      const auto& hitR = wData.Hit(curr_trip->GetRHit());
 
-    if (wData.CurrentIteration()->GetExtendTracksFlag()) {
-      if (tr.NofHits() < fParameters.GetNstationsActive()) {
-        fTrackExtender.ExtendBranch(tr, wData);
+      if (!(wData.IsHitKeyUsed(hitM.FrontKey()) || wData.IsHitKeyUsed(hitM.BackKey()))) {
+        curr_tr.AddHit(curr_trip->GetMHit());
       }
-    }
-
-    for (auto iHit : tr.Hits()) {
-      const ca::Hit& hit = wData.Hit(iHit);
-      /// used strips are marked
-      wData.IsHitKeyUsed(hit.FrontKey()) = 1;
-      wData.IsHitKeyUsed(hit.BackKey())  = 1;
-      wData.RecoHitIndices().push_back(hit.Id());
-    }
-    Track t;
-    t.fNofHits = tr.NofHits();
-    wData.RecoTracks().push_back(t);
-    if (0) {  // SG debug
-      std::stringstream s;
-      s << "store track " << iCandidate << " chi2= " << tr.Chi2() << "\n";
-      s << " hits: ";
-      for (auto hitLoc : tr.Hits()) {
-        auto hitId = wData.Hit(hitLoc).Id();
-        s << ca::Framework::GetMcTrackIdForCaHit(hitId) << " ";
+      if (!(wData.IsHitKeyUsed(hitR.FrontKey()) || wData.IsHitKeyUsed(hitR.BackKey()))) {
+        curr_tr.AddHit(curr_trip->GetRHit());
       }
-      LOG(info) << s.str();
-    }
-  }  // tracks
-}
-
-/** *************************************************************
-     *                                                              *
-     *     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, WindowData& wData,
-                                    TripletArray_t& vTriplets)
-/// 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 auto& hitM = wData.Hit(curr_trip->GetMHit());
-    const auto& hitR = wData.Hit(curr_trip->GetRHit());
+      //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 (!(wData.IsHitKeyUsed(hitM.FrontKey()) || wData.IsHitKeyUsed(hitM.BackKey()))) {
-      curr_tr.AddHit(curr_trip->GetMHit());
-    }
-    if (!(wData.IsHitKeyUsed(hitR.FrontKey()) || wData.IsHitKeyUsed(hitR.BackKey()))) {
-      curr_tr.AddHit(curr_trip->GetRHit());
-    }
-
-    //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::TrackingMode::kGlobal == fTrackingMode || ca::TrackingMode::kMcbm == fTrackingMode) {
+        ndf = curr_tr.NofHits() * 2 - 4;
+      }
+      if (curr_tr.Chi2() > wData.CurrentIteration()->GetTrackChi2Cut() * ndf) {
+        return;
+      }
 
-    if (ca::TrackingMode::kGlobal == fTrackingMode || ca::TrackingMode::kMcbm == fTrackingMode) {
-      ndf = curr_tr.NofHits() * 2 - 4;
-    }
-    if (curr_tr.Chi2() > wData.CurrentIteration()->GetTrackChi2Cut() * ndf) {
+      // -- 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());
 
-    // -- 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++) {
+      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);
+        unsigned int ID      = curr_trip->GetFNeighbour() + in;
+        unsigned int Station = TripletId2Station(ID);
+        unsigned int Triplet = TripletId2Triplet(ID);
 
-      const ca::Triplet& new_trip = vTriplets[Station][Triplet];
+        const ca::Triplet& new_trip = vTriplets[Station][Triplet];
 
-      fscal dchi2 = 0.;
-      if (!checkTripletMatch(*curr_trip, new_trip, dchi2, wData)) continue;
-
-      const auto& hitL = wData.Hit(new_trip.GetLHit());                                 // left hit of new triplet
-      if (wData.IsHitKeyUsed(hitL.FrontKey()) || wData.IsHitKeyUsed(hitL.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 constexpr (0) {  //SGtrd2d debug!!
-          int mc01 = ca::Framework::GetMcTrackIdForWindowHit(curr_trip->GetLHit());
-          int mc02 = ca::Framework::GetMcTrackIdForWindowHit(curr_trip->GetMHit());
-          int mc03 = ca::Framework::GetMcTrackIdForWindowHit(curr_trip->GetRHit());
-          int mc11 = ca::Framework::GetMcTrackIdForWindowHit(new_trip.GetLHit());
-          int mc12 = ca::Framework::GetMcTrackIdForWindowHit(new_trip.GetMHit());
-          int mc13 = ca::Framework::GetMcTrackIdForWindowHit(new_trip.GetRHit());
-
-          if ((mc01 == mc02) && (mc02 == mc03)) {
-            LOG(info) << " 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);
-            LOG(info) << "   hits " << curr_trip->GetLHit() << " " << curr_trip->GetMHit() << " "
-                      << curr_trip->GetRHit() << " " << new_trip.GetLHit();
+        fscal dchi2 = 0.;
+        if (!checkTripletMatch(*curr_trip, new_trip, dchi2, wData)) continue;
+
+        const auto& hitL = wData.Hit(new_trip.GetLHit());                                 // left hit of new triplet
+        if (wData.IsHitKeyUsed(hitL.FrontKey()) || wData.IsHitKeyUsed(hitL.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 constexpr (0) {  //SGtrd2d debug!!
+            int mc01 = ca::Framework::GetMcTrackIdForWindowHit(curr_trip->GetLHit());
+            int mc02 = ca::Framework::GetMcTrackIdForWindowHit(curr_trip->GetMHit());
+            int mc03 = ca::Framework::GetMcTrackIdForWindowHit(curr_trip->GetRHit());
+            int mc11 = ca::Framework::GetMcTrackIdForWindowHit(new_trip.GetLHit());
+            int mc12 = ca::Framework::GetMcTrackIdForWindowHit(new_trip.GetMHit());
+            int mc13 = ca::Framework::GetMcTrackIdForWindowHit(new_trip.GetRHit());
+
+            if ((mc01 == mc02) && (mc02 == mc03)) {
+              LOG(info) << " 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);
+              LOG(info) << "   hits " << curr_trip->GetLHit() << " " << curr_trip->GetMHit() << " "
+                        << curr_trip->GetRHit() << " " << new_trip.GetLHit();
+            }
+          }
 
-        int ndf = 2 * (new_L + 2) - 5;
+          int ndf = 2 * (new_L + 2) - 5;
 
-        if (ca::TrackingMode::kGlobal == fTrackingMode) {  //SGtrd2d!!!
-          ndf = 2 * (new_L + 2) - 4;
-        }
-        else if (ca::TrackingMode::kMcbm == fTrackingMode) {
-          ndf = 2 * (new_L + 2) - 4;
-        }
-        else {
-          ndf = new_L;  // TODO: SG:  2 * (new_L + 2) - 5
-        }
+          if (ca::TrackingMode::kGlobal == fTrackingMode) {  //SGtrd2d!!!
+            ndf = 2 * (new_L + 2) - 4;
+          }
+          else if (ca::TrackingMode::kMcbm == fTrackingMode) {
+            ndf = 2 * (new_L + 2) - 4;
+          }
+          else {
+            ndf = new_L;  // TODO: SG:  2 * (new_L + 2) - 5
+          }
 
-        if (new_chi2 > wData.CurrentIteration()->GetTrackChi2Cut() * ndf) continue;
+          if (new_chi2 > wData.CurrentIteration()->GetTrackChi2Cut() * ndf) continue;
 
-        // add new hit
-        new_tr[ista] = curr_tr;
-        new_tr[ista].AddHit(new_trip.GetLHit());
+          // add new hit
+          new_tr[ista] = curr_tr;
+          new_tr[ista].AddHit(new_trip.GetLHit());
 
-        const int new_ista = ista + new_trip.GetMSta() - new_trip.GetLSta();
-        new_tr[ista].SetChi2(new_chi2);
+          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, wData, vTriplets);
+        }  // add triplet to track
+      }    // for neighbours
+    }      // level = 0
+  }
 
-        CAFindTrack(new_ista, best_tr, &new_trip, new_tr[ista], min_best_l, new_tr, wData, vTriplets);
-      }  // add triplet to track
-    }    // for neighbours
-  }      // level = 0
-}
+}  // namespace cbm::algo::ca
diff --git a/algo/ca/core/tracking/CaTrackFitter.cxx b/algo/ca/core/tracking/CaTrackFitter.cxx
index 4f6d2e089ce2259b01d7835d45e4b8a3acc7deff..9d716e6da66bb2294a2515fdde728a469ca369fc 100644
--- a/algo/ca/core/tracking/CaTrackFitter.cxx
+++ b/algo/ca/core/tracking/CaTrackFitter.cxx
@@ -11,389 +11,386 @@
 #include <iostream>
 #include <vector>
 
-using std::vector;
-using Track = cbm::algo::ca::Track;
 
-using namespace cbm::algo::ca;
-using namespace cbm::algo;
-
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-TrackFitter::TrackFitter(const ca::Parameters<fvec>& pars, const fscal mass, const ca::TrackingMode& mode)
-  : fParameters(pars)
-  , fSetup(fParameters.GetActiveSetup())
-  , fDefaultMass(mass)
-  , fTrackingMode(mode)
+namespace cbm::algo::ca
 {
-}
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  TrackFitter::TrackFitter(const ca::Parameters<fvec>& pars, const fscal mass, const ca::TrackingMode& mode)
+    : fParameters(pars)
+    , fSetup(fParameters.GetActiveSetup())
+    , fDefaultMass(mass)
+    , fTrackingMode(mode)
+  {
+  }
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-TrackFitter::~TrackFitter() {}
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  TrackFitter::~TrackFitter() {}
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-void TrackFitter::FitCaTracks(const ca::InputData& input, WindowData& wData)
-{
-  //  LOG(info) << " Start CA Track Fitter ";
-  int start_hit = 0;  // for interation in wData.RecoHitIndices()
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  void TrackFitter::FitCaTracks(const ca::InputData& input, WindowData& wData)
+  {
+    //  LOG(info) << " Start CA Track Fitter ";
+    int start_hit = 0;  // for interation in wData.RecoHitIndices()
 
-  //  static kf::FieldValue fldB0, fldB1, fldB2 _fvecalignment;
-  //  static kf::FieldRegion fld _fvecalignment;
-  kf::FieldValue<fvec> fldB0, fldB1, fldB2 _fvecalignment;
-  kf::FieldRegion<fvec> fld _fvecalignment;
+    //  static kf::FieldValue fldB0, fldB1, fldB2 _fvecalignment;
+    //  static kf::FieldRegion fld _fvecalignment;
+    kf::FieldValue<fvec> fldB0, fldB1, fldB2 _fvecalignment;
+    kf::FieldRegion<fvec> fld _fvecalignment;
 
 
-  kf::FieldValue<fvec> fldB01, fldB11, fldB21 _fvecalignment;
-  kf::FieldRegion<fvec> fld1 _fvecalignment;
+    kf::FieldValue<fvec> fldB01, fldB11, fldB21 _fvecalignment;
+    kf::FieldRegion<fvec> fld1 _fvecalignment;
 
-  const int nStations = fParameters.GetNstationsActive();
-  int nTracks_SIMD    = fvec::size();
+    const int nStations = fParameters.GetNstationsActive();
+    int nTracks_SIMD    = fvec::size();
 
-  kf::TrackKalmanFilter<fvec> fit;  // fit parameters coresponding to the current track
-  TrackParamV& tr = fit.Tr();
-  fit.SetParticleMass(fDefaultMass);
-  fit.SetDoFitVelocity(true);
+    kf::TrackKalmanFilter<fvec> fit;  // fit parameters coresponding to the current track
+    TrackParamV& tr = fit.Tr();
+    fit.SetParticleMass(fDefaultMass);
+    fit.SetDoFitVelocity(true);
 
-  Track* t[fvec::size()]{nullptr};
+    Track* t[fvec::size()]{nullptr};
 
-  const ca::Station<fvec>* sta = fParameters.GetStations().begin();
+    const ca::Station<fvec>* sta = fParameters.GetStations().begin();
 
-  // Spatial-time position of a hit vs. station and track in the portion
+    // Spatial-time position of a hit vs. station and track in the portion
 
-  fvec x[constants::size::MaxNstations];                       // Hit position along the x-axis [cm]
-  fvec y[constants::size::MaxNstations];                       // Hit position along the y-axis [cm]
-  kf::MeasurementXy<fvec> mxy[constants::size::MaxNstations];  // Covariance matrix for x,y
+    fvec x[constants::size::MaxNstations];                       // Hit position along the x-axis [cm]
+    fvec y[constants::size::MaxNstations];                       // Hit position along the y-axis [cm]
+    kf::MeasurementXy<fvec> mxy[constants::size::MaxNstations];  // Covariance matrix for x,y
 
-  fvec z[constants::size::MaxNstations];  // Hit position along the z-axis (precised) [cm]
+    fvec z[constants::size::MaxNstations];  // Hit position along the z-axis (precised) [cm]
 
-  fvec time[constants::size::MaxNstations];  // Hit time [ns]
-  fvec dt2[constants::size::MaxNstations];   // Hit time uncertainty [ns] squared
+    fvec time[constants::size::MaxNstations];  // Hit time [ns]
+    fvec dt2[constants::size::MaxNstations];   // Hit time uncertainty [ns] squared
 
-  fvec x_first;
-  fvec y_first;
-  kf::MeasurementXy<fvec> mxy_first;
+    fvec x_first;
+    fvec y_first;
+    kf::MeasurementXy<fvec> mxy_first;
 
-  fvec time_first;
-  fvec wtime_first;
-  fvec dt2_first;
+    fvec time_first;
+    fvec wtime_first;
+    fvec dt2_first;
 
-  fvec x_last;
-  fvec y_last;
-  kf::MeasurementXy<fvec> mxy_last;
+    fvec x_last;
+    fvec y_last;
+    kf::MeasurementXy<fvec> mxy_last;
 
-  fvec time_last;
-  fvec wtime_last;
-  fvec dt2_last;
+    fvec time_last;
+    fvec wtime_last;
+    fvec dt2_last;
 
-  fvec By[constants::size::MaxNstations];
-  fmask w[constants::size::MaxNstations];
-  fmask w_time[constants::size::MaxNstations];  // !!!
+    fvec By[constants::size::MaxNstations];
+    fmask w[constants::size::MaxNstations];
+    fmask w_time[constants::size::MaxNstations];  // !!!
 
-  fvec y_temp;
-  fvec x_temp;
-  fvec fldZ0;
-  fvec fldZ1;
-  fvec fldZ2;
-  fvec z_start;
-  fvec z_end;
+    fvec y_temp;
+    fvec x_temp;
+    fvec fldZ0;
+    fvec fldZ1;
+    fvec fldZ2;
+    fvec z_start;
+    fvec z_end;
 
-  kf::FieldValue<fvec> fB[constants::size::MaxNstations], fB_temp _fvecalignment;
+    kf::FieldValue<fvec> fB[constants::size::MaxNstations], fB_temp _fvecalignment;
 
 
-  fvec ZSta[constants::size::MaxNstations];
-  for (int ista = 0; ista < nStations; ista++) {
-    ZSta[ista] = sta[ista].fZ;
-    mxy[ista].SetCov(1., 0., 1.);
-  }
+    fvec ZSta[constants::size::MaxNstations];
+    for (int ista = 0; ista < nStations; ista++) {
+      ZSta[ista] = sta[ista].fZ;
+      mxy[ista].SetCov(1., 0., 1.);
+    }
 
-  unsigned short N_vTracks = wData.RecoTracks().size();  // number of tracks processed per one SSE register
+    unsigned short N_vTracks = wData.RecoTracks().size();  // number of tracks processed per one SSE register
 
-  for (unsigned short itrack = 0; itrack < N_vTracks; itrack += fvec::size()) {
+    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;
+      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] = &wData.RecoTrack(itrack + i);
-    }
+      for (int i = 0; i < nTracks_SIMD; i++) {
+        t[i] = &wData.RecoTrack(itrack + i);
+      }
 
-    // fill the rest of the SIMD vectors with something reasonable
-    for (uint i = nTracks_SIMD; i < fvec::size(); i++) {
-      t[i] = &wData.RecoTrack(itrack);
-    }
+      // fill the rest of the SIMD vectors with something reasonable
+      for (uint i = nTracks_SIMD; i < fvec::size(); i++) {
+        t[i] = &wData.RecoTrack(itrack);
+      }
 
-    // get hits of current track
-    for (int ista = 0; ista < nStations; ista++) {
-      w[ista]      = fmask::Zero();
-      w_time[ista] = fmask::Zero();
-      z[ista]      = ZSta[ista];
-    }
+      // get hits of current track
+      for (int ista = 0; ista < nStations; ista++) {
+        w[ista]      = fmask::Zero();
+        w_time[ista] = fmask::Zero();
+        z[ista]      = ZSta[ista];
+      }
 
-    //fmask isFieldPresent = fmask::Zero();
+      //fmask isFieldPresent = fmask::Zero();
 
-    for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
+      for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
 
-      int nHitsTrack = t[iVec]->fNofHits;
-      int iSta[constants::size::MaxNstations];
+        int nHitsTrack = t[iVec]->fNofHits;
+        int iSta[constants::size::MaxNstations];
 
-      for (int ih = 0; ih < nHitsTrack; ih++) {
+        for (int ih = 0; ih < nHitsTrack; ih++) {
 
-        const ca::Hit& hit = input.GetHit(wData.RecoHitIndex(start_hit++));
-        const int ista     = hit.Station();
+          const ca::Hit& hit = input.GetHit(wData.RecoHitIndex(start_hit++));
+          const int ista     = hit.Station();
 
-        //if (sta[ista].fieldStatus) { isFieldPresent[iVec] = true; }
+          //if (sta[ista].fieldStatus) { isFieldPresent[iVec] = true; }
 
-        iSta[ih]      = ista;
-        w[ista][iVec] = true;
-        if (sta[ista].timeInfo) {
-          w_time[ista][iVec] = true;
-        }
+          iSta[ih]      = ista;
+          w[ista][iVec] = true;
+          if (sta[ista].timeInfo) {
+            w_time[ista][iVec] = true;
+          }
 
-        x[ista][iVec]    = hit.X();  //x_temp[iVec];
-        y[ista][iVec]    = hit.Y();  //y_temp[iVec];
-        time[ista][iVec] = hit.T();
-        dt2[ista][iVec]  = hit.dT2();
-        if (!sta[ista].timeInfo) {
-          dt2[ista][iVec] = 1.e4;
-        }
-        z[ista][iVec]          = hit.Z();
-        fB_temp                = sta[ista].fieldSlice.GetFieldValue(x[ista], y[ista]);
-        mxy[ista].X()[iVec]    = hit.X();
-        mxy[ista].Y()[iVec]    = hit.Y();
-        mxy[ista].Dx2()[iVec]  = hit.dX2();
-        mxy[ista].Dy2()[iVec]  = hit.dY2();
-        mxy[ista].Dxy()[iVec]  = hit.dXY();
-        mxy[ista].NdfX()[iVec] = 1.;
-        mxy[ista].NdfY()[iVec] = 1.;
-
-        fB[ista].SetSimdEntry(fB_temp.GetBx()[iVec], fB_temp.GetBy()[iVec], fB_temp.GetBz()[iVec], iVec);
-
-        if (ih == 0) {
-          z_start[iVec]          = z[ista][iVec];
-          x_first[iVec]          = x[ista][iVec];
-          y_first[iVec]          = y[ista][iVec];
-          time_first[iVec]       = time[ista][iVec];
-          wtime_first[iVec]      = sta[ista].timeInfo ? 1. : 0.;
-          dt2_first[iVec]        = dt2[ista][iVec];
-          mxy_first.X()[iVec]    = mxy[ista].X()[iVec];
-          mxy_first.Y()[iVec]    = mxy[ista].Y()[iVec];
-          mxy_first.Dx2()[iVec]  = mxy[ista].Dx2()[iVec];
-          mxy_first.Dy2()[iVec]  = mxy[ista].Dy2()[iVec];
-          mxy_first.Dxy()[iVec]  = mxy[ista].Dxy()[iVec];
-          mxy_first.NdfX()[iVec] = mxy[ista].NdfX()[iVec];
-          mxy_first.NdfY()[iVec] = mxy[ista].NdfY()[iVec];
-        }
-        else if (ih == nHitsTrack - 1) {
-          z_end[iVec]           = z[ista][iVec];
-          x_last[iVec]          = x[ista][iVec];
-          y_last[iVec]          = y[ista][iVec];
-          mxy_last.X()[iVec]    = mxy[ista].X()[iVec];
-          mxy_last.Y()[iVec]    = mxy[ista].Y()[iVec];
-          mxy_last.Dx2()[iVec]  = mxy[ista].Dx2()[iVec];
-          mxy_last.Dy2()[iVec]  = mxy[ista].Dy2()[iVec];
-          mxy_last.Dxy()[iVec]  = mxy[ista].Dxy()[iVec];
-          mxy_last.NdfX()[iVec] = mxy[ista].NdfX()[iVec];
-          mxy_last.NdfY()[iVec] = mxy[ista].NdfY()[iVec];
-          time_last[iVec]       = time[ista][iVec];
-          dt2_last[iVec]        = dt2[ista][iVec];
-          wtime_last[iVec]      = sta[ista].timeInfo ? 1. : 0.;
+          x[ista][iVec]    = hit.X();  //x_temp[iVec];
+          y[ista][iVec]    = hit.Y();  //y_temp[iVec];
+          time[ista][iVec] = hit.T();
+          dt2[ista][iVec]  = hit.dT2();
+          if (!sta[ista].timeInfo) {
+            dt2[ista][iVec] = 1.e4;
+          }
+          z[ista][iVec]          = hit.Z();
+          fB_temp                = sta[ista].fieldSlice.GetFieldValue(x[ista], y[ista]);
+          mxy[ista].X()[iVec]    = hit.X();
+          mxy[ista].Y()[iVec]    = hit.Y();
+          mxy[ista].Dx2()[iVec]  = hit.dX2();
+          mxy[ista].Dy2()[iVec]  = hit.dY2();
+          mxy[ista].Dxy()[iVec]  = hit.dXY();
+          mxy[ista].NdfX()[iVec] = 1.;
+          mxy[ista].NdfY()[iVec] = 1.;
+
+          fB[ista].SetSimdEntry(fB_temp.GetBx()[iVec], fB_temp.GetBy()[iVec], fB_temp.GetBz()[iVec], iVec);
+
+          if (ih == 0) {
+            z_start[iVec]          = z[ista][iVec];
+            x_first[iVec]          = x[ista][iVec];
+            y_first[iVec]          = y[ista][iVec];
+            time_first[iVec]       = time[ista][iVec];
+            wtime_first[iVec]      = sta[ista].timeInfo ? 1. : 0.;
+            dt2_first[iVec]        = dt2[ista][iVec];
+            mxy_first.X()[iVec]    = mxy[ista].X()[iVec];
+            mxy_first.Y()[iVec]    = mxy[ista].Y()[iVec];
+            mxy_first.Dx2()[iVec]  = mxy[ista].Dx2()[iVec];
+            mxy_first.Dy2()[iVec]  = mxy[ista].Dy2()[iVec];
+            mxy_first.Dxy()[iVec]  = mxy[ista].Dxy()[iVec];
+            mxy_first.NdfX()[iVec] = mxy[ista].NdfX()[iVec];
+            mxy_first.NdfY()[iVec] = mxy[ista].NdfY()[iVec];
+          }
+          else if (ih == nHitsTrack - 1) {
+            z_end[iVec]           = z[ista][iVec];
+            x_last[iVec]          = x[ista][iVec];
+            y_last[iVec]          = y[ista][iVec];
+            mxy_last.X()[iVec]    = mxy[ista].X()[iVec];
+            mxy_last.Y()[iVec]    = mxy[ista].Y()[iVec];
+            mxy_last.Dx2()[iVec]  = mxy[ista].Dx2()[iVec];
+            mxy_last.Dy2()[iVec]  = mxy[ista].Dy2()[iVec];
+            mxy_last.Dxy()[iVec]  = mxy[ista].Dxy()[iVec];
+            mxy_last.NdfX()[iVec] = mxy[ista].NdfX()[iVec];
+            mxy_last.NdfY()[iVec] = mxy[ista].NdfY()[iVec];
+            time_last[iVec]       = time[ista][iVec];
+            dt2_last[iVec]        = dt2[ista][iVec];
+            wtime_last[iVec]      = sta[ista].timeInfo ? 1. : 0.;
+          }
         }
-      }
 
-      for (int ih = nHitsTrack - 1; ih >= 0; ih--) {
-        const int ista              = iSta[ih];
-        const ca::Station<fvec>& st = fParameters.GetStation(ista);
-        By[ista][iVec]              = st.fieldSlice.GetFieldValue(0., 0.).GetBy()[0];
+        for (int ih = nHitsTrack - 1; ih >= 0; ih--) {
+          const int ista              = iSta[ih];
+          const ca::Station<fvec>& st = fParameters.GetStation(ista);
+          By[ista][iVec]              = st.fieldSlice.GetFieldValue(0., 0.).GetBy()[0];
+        }
       }
-    }
-
-    fit.GuessTrack(z_end, x, y, z, time, By, w, w_time, nStations);
-
-    if (ca::TrackingMode::kGlobal == fTrackingMode || ca::TrackingMode::kMcbm == fTrackingMode) {
-      tr.Qp() = fvec(1. / 1.1);
-    }
-
-    // tr.Qp() = iif(isFieldPresent, tr.Qp(), fvec(1. / 0.25));
 
-    for (int iter = 0; iter < 2; iter++) {  // 1.5 iterations
+      fit.GuessTrack(z_end, x, y, z, time, By, w, w_time, nStations);
 
-      fit.SetQp0(tr.Qp());
+      if (ca::TrackingMode::kGlobal == fTrackingMode || ca::TrackingMode::kMcbm == fTrackingMode) {
+        tr.Qp() = fvec(1. / 1.1);
+      }
 
-      // fit backward
+      // tr.Qp() = iif(isFieldPresent, tr.Qp(), fvec(1. / 0.25));
 
-      int ista = nStations - 1;
+      for (int iter = 0; iter < 2; iter++) {  // 1.5 iterations
 
-      time_last = iif(w_time[ista], time_last, fvec::Zero());
-      dt2_last  = iif(w_time[ista], dt2_last, fvec(1.e6));
+        fit.SetQp0(tr.Qp());
 
-      tr.ResetErrors(mxy_last.Dx2(), mxy_last.Dy2(), 0.1, 0.1, 1.0, dt2_last, 1.e-2);
-      tr.C10()  = mxy_last.Dxy();
-      tr.X()    = mxy_last.X();
-      tr.Y()    = mxy_last.Y();
-      tr.Time() = time_last;
-      tr.Vi()   = constants::phys::SpeedOfLightInv;
-      tr.InitVelocityRange(0.5);
-      tr.Ndf()     = fvec(-5.) + fvec(2.);
-      tr.NdfTime() = fvec(-2.) + wtime_last;
+        // fit backward
 
-      fldZ1 = z[ista];
+        int ista = nStations - 1;
 
-      fldB1 = sta[ista].fieldSlice.GetFieldValue(tr.X(), tr.Y());
+        time_last = iif(w_time[ista], time_last, fvec::Zero());
+        dt2_last  = iif(w_time[ista], dt2_last, fvec(1.e6));
 
-      fldB1.SetSimdEntries(fB[ista], w[ista]);
+        tr.ResetErrors(mxy_last.Dx2(), mxy_last.Dy2(), 0.1, 0.1, 1.0, dt2_last, 1.e-2);
+        tr.C10()  = mxy_last.Dxy();
+        tr.X()    = mxy_last.X();
+        tr.Y()    = mxy_last.Y();
+        tr.Time() = time_last;
+        tr.Vi()   = constants::phys::SpeedOfLightInv;
+        tr.InitVelocityRange(0.5);
+        tr.Ndf()     = fvec(-5.) + fvec(2.);
+        tr.NdfTime() = fvec(-2.) + wtime_last;
 
-      fldZ2   = z[ista - 2];
-      fvec dz = fldZ2 - fldZ1;
-      fldB2   = sta[ista].fieldSlice.GetFieldValue(tr.X() + tr.Tx() * dz, tr.Y() + tr.Ty() * dz);
-      fldB2.SetSimdEntries(fB[ista - 2], w[ista - 2]);
-      fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
+        fldZ1 = z[ista];
 
-      for (--ista; ista >= 0; ista--) {
+        fldB1 = sta[ista].fieldSlice.GetFieldValue(tr.X(), tr.Y());
 
-        fldZ0 = z[ista];
-        dz    = (fldZ1 - fldZ0);
-        fldB0 = sta[ista].fieldSlice.GetFieldValue(tr.X() - tr.Tx() * dz, tr.Y() - tr.Ty() * dz);
-        fldB0.SetSimdEntries(fB[ista], w[ista]);
-        fld.Set(fldB0, fldZ0, fldB1, fldZ1, fldB2, fldZ2);
+        fldB1.SetSimdEntries(fB[ista], w[ista]);
 
-        fmask initialised = (z[ista] < z_end) & (z_start <= z[ista]);
+        fldZ2   = z[ista - 2];
+        fvec dz = fldZ2 - fldZ1;
+        fldB2   = sta[ista].fieldSlice.GetFieldValue(tr.X() + tr.Tx() * dz, tr.Y() + tr.Ty() * dz);
+        fldB2.SetSimdEntries(fB[ista - 2], w[ista - 2]);
+        fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
 
-        fld1 = fld;
+        for (--ista; ista >= 0; ista--) {
 
-        fit.SetMask(initialised);
-        fit.Extrapolate(z[ista], fld1);
-        auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(tr.X(), tr.Y());
-        fit.MultipleScattering(radThick);
-        fit.EnergyLossCorrection(radThick, kf::FitDirection::kUpstream);
+          fldZ0 = z[ista];
+          dz    = (fldZ1 - fldZ0);
+          fldB0 = sta[ista].fieldSlice.GetFieldValue(tr.X() - tr.Tx() * dz, tr.Y() - tr.Ty() * dz);
+          fldB0.SetSimdEntries(fB[ista], w[ista]);
+          fld.Set(fldB0, fldZ0, fldB1, fldZ1, fldB2, fldZ2);
 
-        fit.SetMask(initialised && w[ista]);
-        fit.FilterXY(mxy[ista]);
-        fit.FilterTime(time[ista], dt2[ista], fmask(sta[ista].timeInfo));
+          fmask initialised = (z[ista] < z_end) & (z_start <= z[ista]);
 
+          fld1 = fld;
 
-        fldB2 = fldB1;
-        fldZ2 = fldZ1;
-        fldB1 = fldB0;
-        fldZ1 = fldZ0;
-      }
+          fit.SetMask(initialised);
+          fit.Extrapolate(z[ista], fld1);
+          auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(tr.X(), tr.Y());
+          fit.MultipleScattering(radThick);
+          fit.EnergyLossCorrection(radThick, kf::FitDirection::kUpstream);
 
-      // extrapolate to the PV region
+          fit.SetMask(initialised && w[ista]);
+          fit.FilterXY(mxy[ista]);
+          fit.FilterTime(time[ista], dt2[ista], fmask(sta[ista].timeInfo));
 
-      kf::TrackKalmanFilter fitpv = fit;
-      {
-        fitpv.SetMask(fmask::One());
 
-        kf::MeasurementXy<fvec> vtxInfo = wData.TargetMeasurement();
-        vtxInfo.SetDx2(1.e-8);
-        vtxInfo.SetDxy(0.);
-        vtxInfo.SetDy2(1.e-8);
+          fldB2 = fldB1;
+          fldZ2 = fldZ1;
+          fldB1 = fldB0;
+          fldZ1 = fldZ0;
+        }
 
-        if (ca::TrackingMode::kGlobal == fTrackingMode) {
-          kf::FieldRegion<fvec> fldFull(kf::GlobalField::fgOriginalFieldType, kf::GlobalField::fgOriginalField);
-          fitpv.SetMaxExtrapolationStep(1.);
-          for (int vtxIter = 0; vtxIter < 2; vtxIter++) {
+        // extrapolate to the PV region
+
+        kf::TrackKalmanFilter fitpv = fit;
+        {
+          fitpv.SetMask(fmask::One());
+
+          kf::MeasurementXy<fvec> vtxInfo = wData.TargetMeasurement();
+          vtxInfo.SetDx2(1.e-8);
+          vtxInfo.SetDxy(0.);
+          vtxInfo.SetDy2(1.e-8);
+
+          if (ca::TrackingMode::kGlobal == fTrackingMode) {
+            kf::FieldRegion<fvec> fldFull(kf::GlobalField::fgOriginalFieldType, kf::GlobalField::fgOriginalField);
+            fitpv.SetMaxExtrapolationStep(1.);
+            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(), fldFull);
+              fitpv.FilterXY(vtxInfo);
+            }
+          }
+          else {
             fitpv.SetQp0(fitpv.Tr().Qp());
-            fitpv.Tr()      = fit.Tr();
-            fitpv.Tr().Qp() = fitpv.Qp0();
-            fitpv.Extrapolate(fParameters.GetTargetPositionZ(), fldFull);
-            fitpv.FilterXY(vtxInfo);
+            fitpv.Extrapolate(fParameters.GetTargetPositionZ(), fld);
           }
         }
-        else {
-          fitpv.SetQp0(fitpv.Tr().Qp());
-          fitpv.Extrapolate(fParameters.GetTargetPositionZ(), fld);
-        }
-      }
 
-      //fit.SetQp0(tr.Qp());
-      //fit.SetMask(fmask::One());
-      //fit.MeasureVelocityWithQp();
-      //fit.FilterVi(TrackParamV::kClightNsInv);
+        //fit.SetQp0(tr.Qp());
+        //fit.SetMask(fmask::One());
+        //fit.MeasureVelocityWithQp();
+        //fit.FilterVi(TrackParamV::kClightNsInv);
 
-      TrackParamV Tf = fit.Tr();
-      if (ca::TrackingMode::kGlobal == fTrackingMode) {
-        Tf.Qp() = fitpv.Tr().Qp();
-      }
+        TrackParamV Tf = fit.Tr();
+        if (ca::TrackingMode::kGlobal == fTrackingMode) {
+          Tf.Qp() = fitpv.Tr().Qp();
+        }
 
-      for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
-        t[iVec]->fParFirst.Set(Tf, iVec);
-      }
+        for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
+          t[iVec]->fParFirst.Set(Tf, iVec);
+        }
 
-      for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
-        t[iVec]->fParPV.Set(fitpv.Tr(), iVec);
-      }
+        for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
+          t[iVec]->fParPV.Set(fitpv.Tr(), iVec);
+        }
 
-      if (iter == 1) {
-        break;
-      }  // only 1.5 iterations
+        if (iter == 1) {
+          break;
+        }  // only 1.5 iterations
 
-      // fit forward
+        // fit forward
 
-      ista = 0;
+        ista = 0;
 
-      tr.ResetErrors(mxy_first.Dx2(), mxy_first.Dy2(), 0.1, 0.1, 1., dt2_first, 1.e-2);
-      tr.C10() = mxy_first.Dxy();
+        tr.ResetErrors(mxy_first.Dx2(), mxy_first.Dy2(), 0.1, 0.1, 1., dt2_first, 1.e-2);
+        tr.C10() = mxy_first.Dxy();
 
-      tr.X()    = mxy_first.X();
-      tr.Y()    = mxy_first.Y();
-      tr.Time() = time_first;
-      tr.Vi()   = constants::phys::SpeedOfLightInv;
-      tr.InitVelocityRange(0.5);
+        tr.X()    = mxy_first.X();
+        tr.Y()    = mxy_first.Y();
+        tr.Time() = time_first;
+        tr.Vi()   = constants::phys::SpeedOfLightInv;
+        tr.InitVelocityRange(0.5);
 
-      tr.Ndf()     = fvec(-5. + 2.);
-      tr.NdfTime() = fvec(-2.) + wtime_first;
+        tr.Ndf()     = fvec(-5. + 2.);
+        tr.NdfTime() = fvec(-2.) + wtime_first;
 
-      fit.SetQp0(tr.Qp());
+        fit.SetQp0(tr.Qp());
 
-      fldZ1 = z[ista];
-      fldB1 = sta[ista].fieldSlice.GetFieldValue(tr.X(), tr.Y());
-      fldB1.SetSimdEntries(fB[ista], w[ista]);
+        fldZ1 = z[ista];
+        fldB1 = sta[ista].fieldSlice.GetFieldValue(tr.X(), tr.Y());
+        fldB1.SetSimdEntries(fB[ista], w[ista]);
 
-      fldZ2 = z[ista + 2];
-      dz    = fldZ2 - fldZ1;
-      fldB2 = sta[ista].fieldSlice.GetFieldValue(tr.X() + tr.Tx() * dz, tr.Y() + tr.Ty() * dz);
-      fldB2.SetSimdEntries(fB[ista + 2], w[ista + 2]);
-      fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
+        fldZ2 = z[ista + 2];
+        dz    = fldZ2 - fldZ1;
+        fldB2 = sta[ista].fieldSlice.GetFieldValue(tr.X() + tr.Tx() * dz, tr.Y() + tr.Ty() * dz);
+        fldB2.SetSimdEntries(fB[ista + 2], w[ista + 2]);
+        fld.Set(fldB2, fldZ2, fldB1, fldZ1, fldB0, fldZ0);
 
-      for (++ista; ista < nStations; ista++) {
-        fldZ0 = z[ista];
-        dz    = (fldZ1 - fldZ0);
-        fldB0 = sta[ista].fieldSlice.GetFieldValue(tr.X() - tr.Tx() * dz, tr.Y() - tr.Ty() * dz);
-        fldB0.SetSimdEntries(fB[ista], w[ista]);
-        fld.Set(fldB0, fldZ0, fldB1, fldZ1, fldB2, fldZ2);
+        for (++ista; ista < nStations; ista++) {
+          fldZ0 = z[ista];
+          dz    = (fldZ1 - fldZ0);
+          fldB0 = sta[ista].fieldSlice.GetFieldValue(tr.X() - tr.Tx() * dz, tr.Y() - tr.Ty() * dz);
+          fldB0.SetSimdEntries(fB[ista], w[ista]);
+          fld.Set(fldB0, fldZ0, fldB1, fldZ1, fldB2, fldZ2);
 
-        fmask initialised = (z[ista] <= z_end) & (z_start < z[ista]);
+          fmask initialised = (z[ista] <= z_end) & (z_start < z[ista]);
 
-        fit.SetMask(initialised);
-        fit.Extrapolate(z[ista], fld);
-        auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(tr.X(), tr.Y());
-        fit.MultipleScattering(radThick);
-        fit.EnergyLossCorrection(radThick, kf::FitDirection::kDownstream);
-        fit.SetMask(initialised && w[ista]);
-        fit.FilterXY(mxy[ista]);
-        fit.FilterTime(time[ista], dt2[ista], fmask(sta[ista].timeInfo));
+          fit.SetMask(initialised);
+          fit.Extrapolate(z[ista], fld);
+          auto radThick = fSetup.GetMaterial(ista).GetThicknessX0(tr.X(), tr.Y());
+          fit.MultipleScattering(radThick);
+          fit.EnergyLossCorrection(radThick, kf::FitDirection::kDownstream);
+          fit.SetMask(initialised && w[ista]);
+          fit.FilterXY(mxy[ista]);
+          fit.FilterTime(time[ista], dt2[ista], fmask(sta[ista].timeInfo));
 
-        fldB2 = fldB1;
-        fldZ2 = fldZ1;
-        fldB1 = fldB0;
-        fldZ1 = fldZ0;
-      }
+          fldB2 = fldB1;
+          fldZ2 = fldZ1;
+          fldB1 = fldB0;
+          fldZ1 = fldZ0;
+        }
 
-      //fit.SetQp0(tr.Qp());
-      //fit.SetMask(fmask::One());
-      //fit.MeasureVelocityWithQp();
-      //fit.FilterVi(TrackParamV::kClightNsInv);
+        //fit.SetQp0(tr.Qp());
+        //fit.SetMask(fmask::One());
+        //fit.MeasureVelocityWithQp();
+        //fit.FilterVi(TrackParamV::kClightNsInv);
 
-      TrackParamV Tl = fit.Tr();
-      if (ca::TrackingMode::kGlobal == fTrackingMode) {
-        Tl.Qp() = fitpv.Tr().Qp();
-      }
+        TrackParamV Tl = fit.Tr();
+        if (ca::TrackingMode::kGlobal == fTrackingMode) {
+          Tl.Qp() = fitpv.Tr().Qp();
+        }
 
-      for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
-        t[iVec]->fParLast.Set(Tl, iVec);
-      }
+        for (int iVec = 0; iVec < nTracks_SIMD; iVec++) {
+          t[iVec]->fParLast.Set(Tl, iVec);
+        }
 
-    }  // iter
+      }  // iter
+    }
   }
-}
+}  // namespace cbm::algo::ca
\ No newline at end of file
diff --git a/algo/ca/core/tracking/CaTripletConstructor.cxx b/algo/ca/core/tracking/CaTripletConstructor.cxx
index bcf80ffa2ab47790522629e74945e7c4f4ed6d40..1bb1298808d393240fc44db30a23cf254f1d32ae 100644
--- a/algo/ca/core/tracking/CaTripletConstructor.cxx
+++ b/algo/ca/core/tracking/CaTripletConstructor.cxx
@@ -17,750 +17,751 @@
 
 // using cbm::ca::tools::Debugger;
 
-using namespace cbm::algo::ca;
-
-TripletConstructor::TripletConstructor(const ca::Parameters<fvec>& pars, WindowData& wData, const fscal mass,
-                                       const ca::TrackingMode& mode)
-  : fParameters(pars)
-  , fSetup(fParameters.GetActiveSetup())
-  , frWData(wData)
-  , fDefaultMass(mass)
-  , fTrackingMode(mode)
+namespace cbm::algo::ca
 {
-  // FIXME: SZh 24.08.2022
-  //        This approach is suitable only for a case, when all the stations inside a magnetic field come right before
-  //        all the stations outside of the field!
-  fNfieldStations = std::lower_bound(fParameters.GetStations().cbegin(),
-                                     fParameters.GetStations().cbegin() + fParameters.GetNstationsActive(),
-                                     0,  // we are looking for the first zero element
-                                     [](const ca::Station<fvec>& s, int edge) { return bool(s.fieldStatus) > edge; })
-                    - fParameters.GetStations().cbegin();
+  TripletConstructor::TripletConstructor(const ca::Parameters<fvec>& pars, WindowData& wData, const fscal mass,
+                                         const ca::TrackingMode& mode)
+    : fParameters(pars)
+    , fSetup(fParameters.GetActiveSetup())
+    , frWData(wData)
+    , fDefaultMass(mass)
+    , fTrackingMode(mode)
+  {
+    // FIXME: SZh 24.08.2022
+    //        This approach is suitable only for a case, when all the stations inside a magnetic field come right before
+    //        all the stations outside of the field!
+    fNfieldStations = std::lower_bound(fParameters.GetStations().cbegin(),
+                                       fParameters.GetStations().cbegin() + fParameters.GetNstationsActive(),
+                                       0,  // we are looking for the first zero element
+                                       [](const ca::Station<fvec>& s, int edge) { return bool(s.fieldStatus) > edge; })
+                      - fParameters.GetStations().cbegin();
+
+    fIsTargetField = !frWData.TargB().IsZero();
+  }
 
-  fIsTargetField = !frWData.TargB().IsZero();
-}
 
+  bool TripletConstructor::InitStations(int istal, int istam, int istar)
+  {
+    fIstaL = istal;
+    fIstaM = istam;
+    fIstaR = istar;
 
-bool TripletConstructor::InitStations(int istal, int istam, int istar)
-{
-  fIstaL = istal;
-  fIstaM = istam;
-  fIstaR = istar;
+    if (fIstaM >= fParameters.GetNstationsActive()) {
+      return false;
+    }
+    fStaL = &fParameters.GetStation(fIstaL);
+    fStaM = &fParameters.GetStation(fIstaM);
+    fStaR = &fParameters.GetStation(fIstaR);
 
-  if (fIstaM >= fParameters.GetNstationsActive()) {
-    return false;
-  }
-  fStaL = &fParameters.GetStation(fIstaL);
-  fStaM = &fParameters.GetStation(fIstaM);
-  fStaR = &fParameters.GetStation(fIstaR);
+    {  // two stations for approximating the field between the target and the left hit
+      const int sta1 = (fNfieldStations <= 1) ? 1 : std::clamp(fIstaL, 1, fNfieldStations - 1);
+      const int sta0 = sta1 / 2;  // station between fIstaL and the target
 
-  {  // two stations for approximating the field between the target and the left hit
-    const int sta1 = (fNfieldStations <= 1) ? 1 : std::clamp(fIstaL, 1, fNfieldStations - 1);
-    const int sta0 = sta1 / 2;  // station between fIstaL and the target
+      assert(0 <= sta0 && sta0 < sta1 && sta1 < fParameters.GetNstationsActive());
+      fFld0Sta[0] = &fParameters.GetStation(sta0);
+      fFld0Sta[1] = &fParameters.GetStation(sta1);
+    }
 
-    assert(0 <= sta0 && sta0 < sta1 && sta1 < fParameters.GetNstationsActive());
-    fFld0Sta[0] = &fParameters.GetStation(sta0);
-    fFld0Sta[1] = &fParameters.GetStation(sta1);
-  }
+    {  // three stations for approximating the field between the left and the right hit
 
-  {  // three stations for approximating the field between the left and the right hit
+      int sta0 = fIstaL;
+      int sta1 = fIstaM;
+      int sta2 = fIstaM + 1;
+      if (sta2 >= fParameters.GetNstationsActive()) {
+        sta2 = fIstaM;
+        sta1 = fIstaM - 1;
+        sta0 = (sta1 <= 0) ? 0 : std::clamp(sta0, 0, sta1 - 1);
+      }
+      if (fParameters.GetNstationsActive() >= 3) {
+        assert(0 <= sta0 && sta0 < sta1 && sta1 < sta2 && sta2 < fParameters.GetNstationsActive());
+      }
 
-    int sta0 = fIstaL;
-    int sta1 = fIstaM;
-    int sta2 = fIstaM + 1;
-    if (sta2 >= fParameters.GetNstationsActive()) {
-      sta2 = fIstaM;
-      sta1 = fIstaM - 1;
-      sta0 = (sta1 <= 0) ? 0 : std::clamp(sta0, 0, sta1 - 1);
-    }
-    if (fParameters.GetNstationsActive() >= 3) {
-      assert(0 <= sta0 && sta0 < sta1 && sta1 < sta2 && sta2 < fParameters.GetNstationsActive());
+      fFld1Sta[0] = &fParameters.GetStation(sta0);
+      fFld1Sta[1] = &fParameters.GetStation(sta1);
+      fFld1Sta[2] = &fParameters.GetStation(sta2);
     }
-
-    fFld1Sta[0] = &fParameters.GetStation(sta0);
-    fFld1Sta[1] = &fParameters.GetStation(sta1);
-    fFld1Sta[2] = &fParameters.GetStation(sta2);
+    return true;
   }
-  return true;
-}
-
 
-void TripletConstructor::CreateTripletsForHit(Vector<ca::Triplet>& tripletsOut, int istal, int istam, int istar,
-                                              ca::HitIndex_t iHitL)
-{
-  if (!InitStations(istal, istam, istar)) {
-    tripletsOut.clear();
-    return;
-  }
 
-  kf::TrackKalmanFilter<fvec> fit(fmask::One(), true);
-  fit.SetParticleMass(frWData.CurrentIteration()->GetElectronFlag() ? constants::phys::ElectronMass : fDefaultMass);
-  fit.SetQp0(frWData.CurrentIteration()->GetMaxQp());
+  void TripletConstructor::CreateTripletsForHit(Vector<ca::Triplet>& tripletsOut, int istal, int istam, int istar,
+                                                ca::HitIndex_t iHitL)
+  {
+    if (!InitStations(istal, istam, istar)) {
+      tripletsOut.clear();
+      return;
+    }
 
-  fIhitL           = iHitL;
-  const auto& hitl = frWData.Hit(fIhitL);
+    kf::TrackKalmanFilter<fvec> fit(fmask::One(), true);
+    fit.SetParticleMass(frWData.CurrentIteration()->GetElectronFlag() ? constants::phys::ElectronMass : fDefaultMass);
+    fit.SetQp0(frWData.CurrentIteration()->GetMaxQp());
 
-  // fit a straight line through the target and the left hit.
-  TrackParamV& T = fit.Tr();
-  {
-    /// Get the field approximation. Add the target to parameters estimation.
-    /// Propagaete to the middle station of a triplet.
-    //kf::FieldValue<fvec> lB, mB, cB, rB _fvecalignment;           currently not used
-    //kf::FieldValue<fvec> l_B_global, centB_global _fvecalignment; currently not used
+    fIhitL           = iHitL;
+    const auto& hitl = frWData.Hit(fIhitL);
 
-    // get the magnetic field along the track.
-    // (suppose track is straight line with origin in the target)
+    // fit a straight line through the target and the left hit.
+    TrackParamV& T = fit.Tr();
     {
-      const fvec dzli = 1.f / (hitl.Z() - fParameters.GetTargetPositionZ());
-
-      T.X()    = hitl.X();
-      T.Y()    = hitl.Y();
-      T.Z()    = hitl.Z();
-      T.Tx()   = (hitl.X() - fParameters.GetTargetPositionX()) * dzli;
-      T.Ty()   = (hitl.Y() - fParameters.GetTargetPositionY()) * dzli;
-      T.Qp()   = fvec(0.);
-      T.Time() = hitl.T();
-      T.Vi()   = constants::phys::SpeedOfLightInv;
-
-      const fvec maxSlopePV = frWData.CurrentIteration()->GetMaxSlopePV();
-      const fvec maxQp      = frWData.CurrentIteration()->GetMaxQp();
-      const fvec txErr2     = maxSlopePV * maxSlopePV / fvec(9.);
-      const fvec qpErr2     = maxQp * maxQp / fvec(9.);
-
-      T.ResetErrors(1., 1., txErr2, txErr2, qpErr2, (fStaL->timeInfo ? hitl.dT2() : 1.e6), 1.e10);
-      T.InitVelocityRange(1. / frWData.CurrentIteration()->GetMaxQp());
-
-      T.C00()     = hitl.dX2();
-      T.C10()     = hitl.dXY();
-      T.C11()     = hitl.dY2();
-      T.Ndf()     = (frWData.CurrentIteration()->GetPrimaryFlag()) ? fvec(2.) : fvec(0.);
-      T.NdfTime() = (fStaL->timeInfo ? 0 : -1);
-    }
+      /// Get the field approximation. Add the target to parameters estimation.
+      /// Propagaete to the middle station of a triplet.
+      //kf::FieldValue<fvec> lB, mB, cB, rB _fvecalignment;           currently not used
+      //kf::FieldValue<fvec> l_B_global, centB_global _fvecalignment; currently not used
+
+      // get the magnetic field along the track.
+      // (suppose track is straight line with origin in the target)
+      {
+        const fvec dzli = 1.f / (hitl.Z() - fParameters.GetTargetPositionZ());
+
+        T.X()    = hitl.X();
+        T.Y()    = hitl.Y();
+        T.Z()    = hitl.Z();
+        T.Tx()   = (hitl.X() - fParameters.GetTargetPositionX()) * dzli;
+        T.Ty()   = (hitl.Y() - fParameters.GetTargetPositionY()) * dzli;
+        T.Qp()   = fvec(0.);
+        T.Time() = hitl.T();
+        T.Vi()   = constants::phys::SpeedOfLightInv;
+
+        const fvec maxSlopePV = frWData.CurrentIteration()->GetMaxSlopePV();
+        const fvec maxQp      = frWData.CurrentIteration()->GetMaxQp();
+        const fvec txErr2     = maxSlopePV * maxSlopePV / fvec(9.);
+        const fvec qpErr2     = maxQp * maxQp / fvec(9.);
+
+        T.ResetErrors(1., 1., txErr2, txErr2, qpErr2, (fStaL->timeInfo ? hitl.dT2() : 1.e6), 1.e10);
+        T.InitVelocityRange(1. / frWData.CurrentIteration()->GetMaxQp());
+
+        T.C00()     = hitl.dX2();
+        T.C10()     = hitl.dXY();
+        T.C11()     = hitl.dY2();
+        T.Ndf()     = (frWData.CurrentIteration()->GetPrimaryFlag()) ? fvec(2.) : fvec(0.);
+        T.NdfTime() = (fStaL->timeInfo ? 0 : -1);
+      }
 
-    // NDF = number of track parameters (6: x, y, tx, ty, qp, time)
-    //       - number of measured parameters (3: x, y, time) on station or (2: x, y) on target
+      // NDF = number of track parameters (6: x, y, tx, ty, qp, time)
+      //       - number of measured parameters (3: x, y, time) on station or (2: x, y) on target
 
-    // field made by  the left hit, the target and the station istac in-between.
-    // is used for extrapolation to the target and to the middle hit
-    kf::FieldRegion<fvec> fld0;
-    {
-      kf::FieldValue<fvec> B0 = fFld0Sta[0]->fieldSlice.GetFieldValueForLine(T);
-      kf::FieldValue<fvec> B1 = fFld0Sta[1]->fieldSlice.GetFieldValueForLine(T);
-      fld0.Set(frWData.TargB(), fParameters.GetTargetPositionZ(), B0, fFld0Sta[0]->fZ, B1, fFld0Sta[1]->fZ);
-    }
+      // field made by  the left hit, the target and the station istac in-between.
+      // is used for extrapolation to the target and to the middle hit
+      kf::FieldRegion<fvec> fld0;
+      {
+        kf::FieldValue<fvec> B0 = fFld0Sta[0]->fieldSlice.GetFieldValueForLine(T);
+        kf::FieldValue<fvec> B1 = fFld0Sta[1]->fieldSlice.GetFieldValueForLine(T);
+        fld0.Set(frWData.TargB(), fParameters.GetTargetPositionZ(), B0, fFld0Sta[0]->fZ, B1, fFld0Sta[1]->fZ);
+      }
+
+      {  // field, made by the left hit, the middle station and the right station
+        // Will be used for extrapolation to the right hit
+        kf::FieldValue<fvec> B0 = fFld1Sta[0]->fieldSlice.GetFieldValueForLine(T);
+        kf::FieldValue<fvec> B1 = fFld1Sta[1]->fieldSlice.GetFieldValueForLine(T);
+        kf::FieldValue<fvec> B2 = fFld1Sta[2]->fieldSlice.GetFieldValueForLine(T);
+        fFldL.Set(B0, fFld1Sta[0]->fZ, B1, fFld1Sta[1]->fZ, B2, fFld1Sta[2]->fZ);
+      }
+
+      // add the target constraint
+      fit.FilterWithTargetAtLine(fParameters.GetTargetPositionZ(), frWData.TargetMeasurement(), fld0);
+      fit.MultipleScattering(fSetup.GetMaterial(fIstaL).GetThicknessX0(T.GetX(), T.GetY()));
 
-    {  // field, made by the left hit, the middle station and the right station
-      // Will be used for extrapolation to the right hit
-      kf::FieldValue<fvec> B0 = fFld1Sta[0]->fieldSlice.GetFieldValueForLine(T);
-      kf::FieldValue<fvec> B1 = fFld1Sta[1]->fieldSlice.GetFieldValueForLine(T);
-      kf::FieldValue<fvec> B2 = fFld1Sta[2]->fieldSlice.GetFieldValueForLine(T);
-      fFldL.Set(B0, fFld1Sta[0]->fZ, B1, fFld1Sta[1]->fZ, B2, fFld1Sta[2]->fZ);
+      // extrapolate to the middle hit
+      fit.ExtrapolateLine(fStaM->fZ, fFldL);
     }
 
-    // add the target constraint
-    fit.FilterWithTargetAtLine(fParameters.GetTargetPositionZ(), frWData.TargetMeasurement(), fld0);
-    fit.MultipleScattering(fSetup.GetMaterial(fIstaL).GetThicknessX0(T.GetX(), T.GetY()));
+    /// Find the doublets. Reformat data into portions of doublets.
+    auto FindDoubletHits = [&]() {
+      const bool matchMc = fParameters.DevIsMatchDoubletsViaMc();
+      const int iMC      = matchMc ? ca::Framework::GetMcTrackIdForWindowHit(fIhitL) : -1;
+      fDoubletData.second.clear();
+      if (iMC < 0 && matchMc) {
+        return;
+      }
+      CollectHits(fDoubletData.second, fit, fIstaM, frWData.CurrentIteration()->GetDoubletChi2Cut(), iMC,
+                  fParameters.GetMaxDoubletsPerSinglet());
+    };
 
-    // extrapolate to the middle hit
-    fit.ExtrapolateLine(fStaM->fZ, fFldL);
-  }
+    FindDoubletHits();
+    FindDoublets(fit);
 
-  /// Find the doublets. Reformat data into portions of doublets.
-  auto FindDoubletHits = [&]() {
-    const bool matchMc = fParameters.DevIsMatchDoubletsViaMc();
-    const int iMC      = matchMc ? ca::Framework::GetMcTrackIdForWindowHit(fIhitL) : -1;
-    fDoubletData.second.clear();
-    if (iMC < 0 && matchMc) {
+    //D.Smith 28.8.24: Moving this upward (before doublet finding) changes QA output slightly
+    if (fIstaR >= fParameters.GetNstationsActive()) {
+      tripletsOut.clear();
       return;
     }
-    CollectHits(fDoubletData.second, fit, fIstaM, frWData.CurrentIteration()->GetDoubletChi2Cut(), iMC,
-                fParameters.GetMaxDoubletsPerSinglet());
-  };
 
-  FindDoubletHits();
-  FindDoublets(fit);
-
-  //D.Smith 28.8.24: Moving this upward (before doublet finding) changes QA output slightly
-  if (fIstaR >= fParameters.GetNstationsActive()) {
-    tripletsOut.clear();
-    return;
+    FindTripletHits();
+    FindTriplets();
+    SelectTriplets(tripletsOut);
   }
 
-  FindTripletHits();
-  FindTriplets();
-  SelectTriplets(tripletsOut);
-}
 
+  void TripletConstructor::FindDoublets(kf::TrackKalmanFilter<fvec>& fit)
+  {
+    // ---- Add the middle hits to parameters estimation ----
+    Vector<TrackParamV>& tracks   = fDoubletData.first;
+    Vector<ca::HitIndex_t>& hitsM = fDoubletData.second;
 
-void TripletConstructor::FindDoublets(kf::TrackKalmanFilter<fvec>& fit)
-{
-  // ---- Add the middle hits to parameters estimation ----
-  Vector<TrackParamV>& tracks   = fDoubletData.first;
-  Vector<ca::HitIndex_t>& hitsM = fDoubletData.second;
+    tracks.clear();
+    tracks.reserve(hitsM.size());
 
-  tracks.clear();
-  tracks.reserve(hitsM.size());
+    const bool isMomentumFitted = (fIsTargetField || (fStaL->fieldStatus != 0) || (fStaM->fieldStatus != 0));
 
-  const bool isMomentumFitted = (fIsTargetField || (fStaL->fieldStatus != 0) || (fStaM->fieldStatus != 0));
+    const TrackParamV Tr = fit.Tr();  // copy contents of fit
 
-  const TrackParamV Tr = fit.Tr();  // copy contents of fit
+    auto it2 = hitsM.begin();
+    for (auto it = hitsM.begin(); it != hitsM.end(); it++) {
 
-  auto it2 = hitsM.begin();
-  for (auto it = hitsM.begin(); it != hitsM.end(); it++) {
+      const ca::HitIndex_t indM = *it;
+      const ca::Hit& hitm       = frWData.Hit(indM);
 
-    const ca::HitIndex_t indM = *it;
-    const ca::Hit& hitm       = frWData.Hit(indM);
+      if (frWData.IsHitSuppressed(indM)) {
+        continue;
+      }
 
-    if (frWData.IsHitSuppressed(indM)) {
-      continue;
-    }
+      TrackParamV& T2 = fit.Tr();
+      T2              = Tr;
+      fit.SetQp0(fvec(0.f));
 
-    TrackParamV& T2 = fit.Tr();
-    T2              = Tr;
-    fit.SetQp0(fvec(0.f));
+      fvec z_2 = hitm.Z();
+      kf::MeasurementXy<fvec> m_2(hitm.X(), hitm.Y(), hitm.dX2(), hitm.dY2(), hitm.dXY(), fvec::One(), fvec::One());
+      fvec t_2   = hitm.T();
+      fvec dt2_2 = hitm.dT2();
 
-    fvec z_2 = hitm.Z();
-    kf::MeasurementXy<fvec> m_2(hitm.X(), hitm.Y(), hitm.dX2(), hitm.dY2(), hitm.dXY(), fvec::One(), fvec::One());
-    fvec t_2   = hitm.T();
-    fvec dt2_2 = hitm.dT2();
+      // add the middle hit
+      fit.ExtrapolateLineNoField(z_2);
+      fit.FilterXY(m_2);
+      fit.FilterTime(t_2, dt2_2, fmask(fStaM->timeInfo));
+      fit.SetQp0(isMomentumFitted ? fit.Tr().GetQp() : frWData.CurrentIteration()->GetMaxQp());
+      fit.MultipleScattering(fSetup.GetMaterial(fIstaM).GetThicknessX0(T2.GetX(), T2.Y()));
+      fit.SetQp0(fit.Tr().Qp());
 
-    // add the middle hit
-    fit.ExtrapolateLineNoField(z_2);
-    fit.FilterXY(m_2);
-    fit.FilterTime(t_2, dt2_2, fmask(fStaM->timeInfo));
-    fit.SetQp0(isMomentumFitted ? fit.Tr().GetQp() : frWData.CurrentIteration()->GetMaxQp());
-    fit.MultipleScattering(fSetup.GetMaterial(fIstaM).GetThicknessX0(T2.GetX(), T2.Y()));
-    fit.SetQp0(fit.Tr().Qp());
+      // check if there are other hits close to the doublet on the same station
+      if (ca::kMcbm != fTrackingMode) {
+        // TODO: SG: adjust cuts, put them to parameters
 
-    // check if there are other hits close to the doublet on the same station
-    if (ca::kMcbm != fTrackingMode) {
-      // TODO: SG: adjust cuts, put them to parameters
+        const fscal tx = T2.Tx()[0];
+        const fscal ty = T2.Ty()[0];
+        const fscal tt = T2.Vi()[0] * sqrt(1. + tx * tx + ty * ty);  // dt/dl * dl/dz
 
-      const fscal tx = T2.Tx()[0];
-      const fscal ty = T2.Ty()[0];
-      const fscal tt = T2.Vi()[0] * sqrt(1. + tx * tx + ty * ty);  // dt/dl * dl/dz
+        for (auto itClone = it + 1; itClone != hitsM.end(); itClone++) {
 
-      for (auto itClone = it + 1; itClone != hitsM.end(); itClone++) {
+          const int indClone      = *itClone;
+          const ca::Hit& hitClone = frWData.Hit(indClone);
 
-        const int indClone      = *itClone;
-        const ca::Hit& hitClone = frWData.Hit(indClone);
+          const fscal dz = hitClone.Z() - T2.Z()[0];
 
-        const fscal dz = hitClone.Z() - T2.Z()[0];
+          if ((fStaM->timeInfo) && (T2.NdfTime()[0] >= 0)) {
+            const fscal dt = T2.Time()[0] + tt * dz - hitClone.T();
+            if (!(fabs(dt) <= 3.5 * sqrt(T2.C55()[0]) + hitClone.RangeT())) {
+              continue;
+            }
+          }
 
-        if ((fStaM->timeInfo) && (T2.NdfTime()[0] >= 0)) {
-          const fscal dt = T2.Time()[0] + tt * dz - hitClone.T();
-          if (!(fabs(dt) <= 3.5 * sqrt(T2.C55()[0]) + hitClone.RangeT())) {
+          const fscal dx = T2.GetX()[0] + tx * dz - hitClone.X();
+          if (!(fabs(dx) <= 3.5 * sqrt(T2.C00()[0]) + hitClone.RangeX())) {
             continue;
           }
-        }
-
-        const fscal dx = T2.GetX()[0] + tx * dz - hitClone.X();
-        if (!(fabs(dx) <= 3.5 * sqrt(T2.C00()[0]) + hitClone.RangeX())) {
-          continue;
-        }
-
-        const fscal dy = T2.Y()[0] + ty * dz - hitClone.Y();
-        if (!(fabs(dy) <= 3.5 * sqrt(T2.C11()[0]) + hitClone.RangeY())) {
-          continue;
-        }
 
-        if (fParameters.DevIsSuppressOverlapHitsViaMc()) {
-          const int iMC = ca::Framework::GetMcTrackIdForWindowHit(fIhitL);
-          if ((iMC != ca::Framework::GetMcTrackIdForWindowHit(indM))
-              || (iMC != ca::Framework::GetMcTrackIdForWindowHit(indClone))) {
+          const fscal dy = T2.Y()[0] + ty * dz - hitClone.Y();
+          if (!(fabs(dy) <= 3.5 * sqrt(T2.C11()[0]) + hitClone.RangeY())) {
             continue;
           }
-        }
 
-        frWData.SuppressHit(indClone);
+          if (fParameters.DevIsSuppressOverlapHitsViaMc()) {
+            const int iMC = ca::Framework::GetMcTrackIdForWindowHit(fIhitL);
+            if ((iMC != ca::Framework::GetMcTrackIdForWindowHit(indM))
+                || (iMC != ca::Framework::GetMcTrackIdForWindowHit(indClone))) {
+              continue;
+            }
+          }
+
+          frWData.SuppressHit(indClone);
+        }
       }
-    }
 
-    tracks.push_back(T2);
-    *it2 = indM;
-    it2++;
-  }  // it
-  hitsM.shrink(std::distance(hitsM.begin(), it2));
-}
+      tracks.push_back(T2);
+      *it2 = indM;
+      it2++;
+    }  // it
+    hitsM.shrink(std::distance(hitsM.begin(), it2));
+  }
 
 
-void TripletConstructor::FindTripletHits()
-{
-  //auto& [tracks_2, hitsM_2] = doublets;   TO DO: Reactivate when MacOS compiler bug is fixed.
-  Vector<TrackParamV>& tracks_2   = fDoubletData.first;
-  Vector<ca::HitIndex_t>& hitsM_2 = fDoubletData.second;
+  void TripletConstructor::FindTripletHits()
+  {
+    //auto& [tracks_2, hitsM_2] = doublets;   TO DO: Reactivate when MacOS compiler bug is fixed.
+    Vector<TrackParamV>& tracks_2   = fDoubletData.first;
+    Vector<ca::HitIndex_t>& hitsM_2 = fDoubletData.second;
 
-  Vector<ca::HitIndex_t>& hitsM_3 = std::get<1>(fTripletData);
-  Vector<ca::HitIndex_t>& hitsR_3 = std::get<2>(fTripletData);
+    Vector<ca::HitIndex_t>& hitsM_3 = std::get<1>(fTripletData);
+    Vector<ca::HitIndex_t>& hitsR_3 = std::get<2>(fTripletData);
 
-  /// Add the middle hits to parameters estimation. Propagate to right station.
-  /// Find the triplets(right hit). Reformat data in the portion of triplets.
-  kf::TrackKalmanFilter<fvec> fit(fmask::One(), true);
-  fit.SetParticleMass(frWData.CurrentIteration()->GetElectronFlag() ? constants::phys::ElectronMass : fDefaultMass);
-  fit.SetQp0(fvec(0.));
+    /// Add the middle hits to parameters estimation. Propagate to right station.
+    /// Find the triplets(right hit). Reformat data in the portion of triplets.
+    kf::TrackKalmanFilter<fvec> fit(fmask::One(), true);
+    fit.SetParticleMass(frWData.CurrentIteration()->GetElectronFlag() ? constants::phys::ElectronMass : fDefaultMass);
+    fit.SetQp0(fvec(0.));
 
-  {
-    const int maxTriplets = hitsM_2.size() * fParameters.GetMaxTripletPerDoublets();
-    hitsM_3.clear();
-    hitsR_3.clear();
-    hitsM_3.reserve(maxTriplets);
-    hitsR_3.reserve(maxTriplets);
-  }
-  // ---- Add the middle hits to parameters estimation. Propagate to right station. ----
+    {
+      const int maxTriplets = hitsM_2.size() * fParameters.GetMaxTripletPerDoublets();
+      hitsM_3.clear();
+      hitsR_3.clear();
+      hitsM_3.reserve(maxTriplets);
+      hitsR_3.reserve(maxTriplets);
+    }
+    // ---- Add the middle hits to parameters estimation. Propagate to right station. ----
 
-  const double maxSlope       = frWData.CurrentIteration()->GetMaxSlope();
-  const double tripletChi2Cut = frWData.CurrentIteration()->GetTripletChi2Cut();
-  for (unsigned int i2 = 0; i2 < hitsM_2.size(); i2++) {
+    const double maxSlope       = frWData.CurrentIteration()->GetMaxSlope();
+    const double tripletChi2Cut = frWData.CurrentIteration()->GetTripletChi2Cut();
+    for (unsigned int i2 = 0; i2 < hitsM_2.size(); i2++) {
 
-    fit.SetTrack(tracks_2[i2]);
-    TrackParamV& T2 = fit.Tr();
+      fit.SetTrack(tracks_2[i2]);
+      TrackParamV& T2 = fit.Tr();
 
-    // extrapolate to the right hit station
-    fit.Extrapolate(fStaR->fZ, fFldL);
+      // extrapolate to the right hit station
+      fit.Extrapolate(fStaR->fZ, fFldL);
 
-    if constexpr (fDebugDublets) {
-      ca::HitIndex_t iwhit[2] = {fIhitL, hitsM_2[i2]};
-      ca::HitIndex_t ihit[2]  = {frWData.Hit(iwhit[0]).Id(), frWData.Hit(iwhit[1]).Id()};
+      if constexpr (fDebugDublets) {
+        ca::HitIndex_t iwhit[2] = {fIhitL, hitsM_2[i2]};
+        ca::HitIndex_t ihit[2]  = {frWData.Hit(iwhit[0]).Id(), frWData.Hit(iwhit[1]).Id()};
 
-      const int ih0     = ihit[0];
-      const int ih1     = ihit[1];
-      const ca::Hit& h0 = frWData.Hit(iwhit[0]);
-      const ca::Hit& h1 = frWData.Hit(iwhit[1]);
+        const int ih0     = ihit[0];
+        const int ih1     = ihit[1];
+        const ca::Hit& h0 = frWData.Hit(iwhit[0]);
+        const ca::Hit& h1 = frWData.Hit(iwhit[1]);
 
-      LOG(info) << "\n======  Extrapolated Doublet : "
-                << "  iter " << frWData.CurrentIteration()->GetName() << " hits: {" << fIstaL << "/" << ih0 << " "
-                << fIstaM << "/" << ih1 << " " << fIstaR << "/?} xyz: {" << h0.X() << " " << h0.Y() << " " << h0.Z()
-                << "}, {" << h1.X() << " " << h1.Y() << " " << h1.Z() << "} chi2 " << T2.GetChiSq()[0] << " ndf "
-                << T2.Ndf()[0] << " chi2time " << T2.ChiSqTime()[0] << " ndfTime " << T2.NdfTime()[0];
-      LOG(info) << "  extr. track: " << T2.ToString(0);
-    }
+        LOG(info) << "\n======  Extrapolated Doublet : "
+                  << "  iter " << frWData.CurrentIteration()->GetName() << " hits: {" << fIstaL << "/" << ih0 << " "
+                  << fIstaM << "/" << ih1 << " " << fIstaR << "/?} xyz: {" << h0.X() << " " << h0.Y() << " " << h0.Z()
+                  << "}, {" << h1.X() << " " << h1.Y() << " " << h1.Z() << "} chi2 " << T2.GetChiSq()[0] << " ndf "
+                  << T2.Ndf()[0] << " chi2time " << T2.ChiSqTime()[0] << " ndfTime " << T2.NdfTime()[0];
+        LOG(info) << "  extr. track: " << T2.ToString(0);
+      }
 
-    // ---- Find the triplets(right hit). Reformat data in the portion of triplets. ----
-    int iMC = -1;
+      // ---- Find the triplets(right hit). Reformat data in the portion of triplets. ----
+      int iMC = -1;
 
-    auto rejectDoublet = [&]() -> bool {
-      if (ca::TrackingMode::kSts == fTrackingMode && (T2.C44()[0] < 0)) {
-        return true;
-      }
-      if (T2.C00()[0] < 0 || T2.C11()[0] < 0 || T2.C22()[0] < 0 || T2.C33()[0] < 0 || T2.C55()[0] < 0) {
-        return true;
-      }
-      if (fabs(T2.Tx()[0]) > maxSlope) {
-        return true;
-      }
-      if (fabs(T2.Ty()[0]) > maxSlope) {
-        return true;
-      }
-      if (fParameters.DevIsMatchTripletsViaMc()) {
-        int indM = hitsM_2[i2];
-        iMC      = ca::Framework::GetMcTrackIdForWindowHit(fIhitL);
-        if (iMC < 0 || iMC != ca::Framework::GetMcTrackIdForWindowHit(indM)) {
+      auto rejectDoublet = [&]() -> bool {
+        if (ca::TrackingMode::kSts == fTrackingMode && (T2.C44()[0] < 0)) {
           return true;
         }
-      }
-      return false;
-    };
-    const bool isDoubletGood = !rejectDoublet();
+        if (T2.C00()[0] < 0 || T2.C11()[0] < 0 || T2.C22()[0] < 0 || T2.C33()[0] < 0 || T2.C55()[0] < 0) {
+          return true;
+        }
+        if (fabs(T2.Tx()[0]) > maxSlope) {
+          return true;
+        }
+        if (fabs(T2.Ty()[0]) > maxSlope) {
+          return true;
+        }
+        if (fParameters.DevIsMatchTripletsViaMc()) {
+          int indM = hitsM_2[i2];
+          iMC      = ca::Framework::GetMcTrackIdForWindowHit(fIhitL);
+          if (iMC < 0 || iMC != ca::Framework::GetMcTrackIdForWindowHit(indM)) {
+            return true;
+          }
+        }
+        return false;
+      };
+      const bool isDoubletGood = !rejectDoublet();
 
-    if constexpr (fDebugDublets) {
-      if (isDoubletGood) {
-        LOG(info) << "  extrapolated doublet accepted";
-      }
-      else {
-        LOG(info) << "  extrapolated doublet rejected";
-        LOG(info) << "======== end of extrapolated doublet ==== \n";
+      if constexpr (fDebugDublets) {
+        if (isDoubletGood) {
+          LOG(info) << "  extrapolated doublet accepted";
+        }
+        else {
+          LOG(info) << "  extrapolated doublet rejected";
+          LOG(info) << "======== end of extrapolated doublet ==== \n";
+        }
       }
-    }
 
-    if (!isDoubletGood) {
-      continue;
-    }
+      if (!isDoubletGood) {
+        continue;
+      }
 
-    Vector<ca::HitIndex_t> collectedHits;
-    CollectHits(collectedHits, fit, fIstaR, tripletChi2Cut, iMC, fParameters.GetMaxTripletPerDoublets());
+      Vector<ca::HitIndex_t> collectedHits;
+      CollectHits(collectedHits, fit, fIstaR, tripletChi2Cut, iMC, fParameters.GetMaxTripletPerDoublets());
 
-    if (collectedHits.size() >= fParameters.GetMaxTripletPerDoublets()) {
-      // FU, 28.08.2024, Comment the following log lines since it spams the output
-      // of our tests and finally results in crashes on run4
-      //      LOG(debug) << "Ca: GetMaxTripletPerDoublets==" << fParameters.GetMaxTripletPerDoublets()
-      //                 << " reached in findTripletsStep0()";
-      // reject already created triplets for this doublet
-      collectedHits.clear();
-    }
-    if constexpr (fDebugDublets) {
-      LOG(info) << " collected " << collectedHits.size() << " hits on the right station ";
-    }
-    for (ca::HitIndex_t& irh : collectedHits) {
+      if (collectedHits.size() >= fParameters.GetMaxTripletPerDoublets()) {
+        // FU, 28.08.2024, Comment the following log lines since it spams the output
+        // of our tests and finally results in crashes on run4
+        //      LOG(debug) << "Ca: GetMaxTripletPerDoublets==" << fParameters.GetMaxTripletPerDoublets()
+        //                 << " reached in findTripletsStep0()";
+        // reject already created triplets for this doublet
+        collectedHits.clear();
+      }
       if constexpr (fDebugDublets) {
-        const ca::Hit& h    = frWData.Hit(irh);
-        ca::HitIndex_t ihit = h.Id();
-        LOG(info) << "  hit " << ihit << " " << h.ToString();
+        LOG(info) << " collected " << collectedHits.size() << " hits on the right station ";
       }
-      if (frWData.IsHitSuppressed(irh)) {
+      for (ca::HitIndex_t& irh : collectedHits) {
         if constexpr (fDebugDublets) {
-          LOG(info) << "  the hit is suppressed";
+          const ca::Hit& h    = frWData.Hit(irh);
+          ca::HitIndex_t ihit = h.Id();
+          LOG(info) << "  hit " << ihit << " " << h.ToString();
         }
-        continue;
+        if (frWData.IsHitSuppressed(irh)) {
+          if constexpr (fDebugDublets) {
+            LOG(info) << "  the hit is suppressed";
+          }
+          continue;
+        }
+        // pack the triplet
+        hitsM_3.push_back(hitsM_2[i2]);
+        hitsR_3.push_back(irh);
+      }  // search area
+      if constexpr (fDebugDublets) {
+        LOG(info) << "======== end of extrapolated doublet ==== \n";
       }
-      // pack the triplet
-      hitsM_3.push_back(hitsM_2[i2]);
-      hitsR_3.push_back(irh);
-    }  // search area
-    if constexpr (fDebugDublets) {
-      LOG(info) << "======== end of extrapolated doublet ==== \n";
-    }
-  }  // i2
-}
-
-void TripletConstructor::FindTriplets()
-{
-  constexpr int nIterations = 2;
-
-  Vector<TrackParamV>& tracks   = std::get<0>(fTripletData);
-  Vector<ca::HitIndex_t>& hitsM = std::get<1>(fTripletData);
-  Vector<ca::HitIndex_t>& hitsR = std::get<2>(fTripletData);
-  assert(hitsM.size() == hitsR.size());
-
-  tracks.clear();
-  tracks.reserve(hitsM.size());
-
-  /// Refit Triplets
-  if constexpr (fDebugTriplets) {
-    //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");
+    }  // i2
   }
 
-  kf::TrackKalmanFilter<fvec> fit;
-  fit.SetMask(fmask::One());
-  fit.SetParticleMass(frWData.CurrentIteration()->GetElectronFlag() ? constants::phys::ElectronMass : fDefaultMass);
+  void TripletConstructor::FindTriplets()
+  {
+    constexpr int nIterations = 2;
 
-  // prepare data
-  const int NHits       = 3;  // triplets
-  const int ista[NHits] = {fIstaL, fIstaM, fIstaR};
+    Vector<TrackParamV>& tracks   = std::get<0>(fTripletData);
+    Vector<ca::HitIndex_t>& hitsM = std::get<1>(fTripletData);
+    Vector<ca::HitIndex_t>& hitsR = std::get<2>(fTripletData);
+    assert(hitsM.size() == hitsR.size());
 
-  const ca::Station<fvec> sta[NHits] = {fParameters.GetStation(ista[0]), fParameters.GetStation(ista[1]),
-                                        fParameters.GetStation(ista[2])};
+    tracks.clear();
+    tracks.reserve(hitsM.size());
 
-  const bool isMomentumFitted = ((fStaL->fieldStatus != 0) || (fStaM->fieldStatus != 0) || (fStaR->fieldStatus != 0));
-  const fvec ndfTrackModel    = 4 + (isMomentumFitted ? 1 : 0);  // straight line or track with momentum
+    /// Refit Triplets
+    if constexpr (fDebugTriplets) {
+      //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");
+    }
 
-  for (size_t i3 = 0; i3 < hitsM.size(); ++i3) {
+    kf::TrackKalmanFilter<fvec> fit;
+    fit.SetMask(fmask::One());
+    fit.SetParticleMass(frWData.CurrentIteration()->GetElectronFlag() ? constants::phys::ElectronMass : fDefaultMass);
 
     // prepare data
-    const ca::HitIndex_t iwhit[NHits] = {fIhitL, hitsM[i3], hitsR[i3]};
-
-    const ca::HitIndex_t ihit[NHits] = {frWData.Hit(iwhit[0]).Id(), frWData.Hit(iwhit[1]).Id(),
-                                        frWData.Hit(iwhit[2]).Id()};
-
-    if (fParameters.DevIsMatchTripletsViaMc()) {
-      int mc1 = ca::Framework::GetMcTrackIdForCaHit(ihit[0]);
-      int mc2 = ca::Framework::GetMcTrackIdForCaHit(ihit[1]);
-      int mc3 = ca::Framework::GetMcTrackIdForCaHit(ihit[2]);
-      if ((mc1 != mc2) || (mc1 != mc3)) {
-        // D.S.: Added to preserve the ordering when switching from index-based
-        // access to push_back(). Discuss with SZ.
-        tracks.push_back(TrackParamV());
-        continue;
-      }
-    }
+    const int NHits       = 3;  // triplets
+    const int ista[NHits] = {fIstaL, fIstaM, fIstaR};
 
-    fscal x[NHits], y[NHits], z[NHits], t[NHits];
-    fscal dt2[NHits];
-    kf::MeasurementXy<fvec> mxy[NHits];
+    const ca::Station<fvec> sta[NHits] = {fParameters.GetStation(ista[0]), fParameters.GetStation(ista[1]),
+                                          fParameters.GetStation(ista[2])};
 
-    for (int ih = 0; ih < NHits; ++ih) {
-      const ca::Hit& hit = frWData.Hit(iwhit[ih]);
-      mxy[ih] = kf::MeasurementXy<fvec>(hit.X(), hit.Y(), hit.dX2(), hit.dY2(), hit.dXY(), fvec::One(), fvec::One());
+    const bool isMomentumFitted = ((fStaL->fieldStatus != 0) || (fStaM->fieldStatus != 0) || (fStaR->fieldStatus != 0));
+    const fvec ndfTrackModel    = 4 + (isMomentumFitted ? 1 : 0);  // straight line or track with momentum
 
-      x[ih]   = hit.X();
-      y[ih]   = hit.Y();
-      z[ih]   = hit.Z();
-      t[ih]   = hit.T();
-      dt2[ih] = hit.dT2();
-    };
+    for (size_t i3 = 0; i3 < hitsM.size(); ++i3) {
 
-    // find the field along the track
+      // prepare data
+      const ca::HitIndex_t iwhit[NHits] = {fIhitL, hitsM[i3], hitsR[i3]};
 
-    kf::FieldValue<fvec> B[3] _fvecalignment;
-    kf::FieldRegion<fvec> fld _fvecalignment;
-    kf::FieldRegion<fvec> fldTarget _fvecalignment;
+      const ca::HitIndex_t ihit[NHits] = {frWData.Hit(iwhit[0]).Id(), frWData.Hit(iwhit[1]).Id(),
+                                          frWData.Hit(iwhit[2]).Id()};
 
-    fvec tx[3] = {(x[1] - x[0]) / (z[1] - z[0]), (x[2] - x[0]) / (z[2] - z[0]), (x[2] - x[1]) / (z[2] - z[1])};
-    fvec ty[3] = {(y[1] - y[0]) / (z[1] - z[0]), (y[2] - y[0]) / (z[2] - z[0]), (y[2] - y[1]) / (z[2] - z[1])};
+      if (fParameters.DevIsMatchTripletsViaMc()) {
+        int mc1 = ca::Framework::GetMcTrackIdForCaHit(ihit[0]);
+        int mc2 = ca::Framework::GetMcTrackIdForCaHit(ihit[1]);
+        int mc3 = ca::Framework::GetMcTrackIdForCaHit(ihit[2]);
+        if ((mc1 != mc2) || (mc1 != mc3)) {
+          // D.S.: Added to preserve the ordering when switching from index-based
+          // access to push_back(). Discuss with SZ.
+          tracks.push_back(TrackParamV());
+          continue;
+        }
+      }
 
-    for (int ih = 0; ih < NHits; ++ih) {
-      fvec dz = (sta[ih].fZ - z[ih]);
-      B[ih]   = sta[ih].fieldSlice.GetFieldValue(x[ih] + tx[ih] * dz, y[ih] + ty[ih] * dz);
-    };
+      fscal x[NHits], y[NHits], z[NHits], t[NHits];
+      fscal dt2[NHits];
+      kf::MeasurementXy<fvec> mxy[NHits];
 
-    fld.Set(B[0], sta[0].fZ, B[1], sta[1].fZ, B[2], sta[2].fZ);
-    fldTarget.Set(frWData.TargB(), fParameters.GetTargetPositionZ(), B[0], sta[0].fZ, B[1], sta[1].fZ);
+      for (int ih = 0; ih < NHits; ++ih) {
+        const ca::Hit& hit = frWData.Hit(iwhit[ih]);
+        mxy[ih] = kf::MeasurementXy<fvec>(hit.X(), hit.Y(), hit.dX2(), hit.dY2(), hit.dXY(), fvec::One(), fvec::One());
 
-    TrackParamV& T = fit.Tr();
+        x[ih]   = hit.X();
+        y[ih]   = hit.Y();
+        z[ih]   = hit.Z();
+        t[ih]   = hit.T();
+        dt2[ih] = hit.dT2();
+      };
 
-    // initial parameters
-    {
-      fvec dz01 = 1. / (z[1] - z[0]);
-      T.Tx()    = (x[1] - x[0]) * dz01;
-      T.Ty()    = (y[1] - y[0]) * dz01;
-      T.Qp()    = 0.;
-      T.Vi()    = 0.;
-    }
+      // find the field along the track
 
-    // repeat several times in order to improve the precision
-    for (int iiter = 0; iiter < nIterations; ++iiter) {
-
-      auto fitTrack = [&](int startIdx, int endIdx, int step, kf::FitDirection direction) {
-        const fvec maxQp = frWData.CurrentIteration()->GetMaxQp();
-        fit.SetQp0(T.Qp());
-        fit.Qp0()(fit.Qp0() > maxQp)  = maxQp;
-        fit.Qp0()(fit.Qp0() < -maxQp) = -maxQp;
-
-        int ih0  = startIdx;
-        T.X()    = x[ih0];
-        T.Y()    = y[ih0];
-        T.Z()    = z[ih0];
-        T.Time() = t[ih0];
-        T.Qp()   = 0.;
-        T.Vi()   = 0.;
-
-        T.ResetErrors(1., 1., 1., 1., 100., (sta[ih0].timeInfo ? dt2[ih0] : 1.e6), 1.e2);
-        T.C00() = mxy[ih0].Dx2();
-        T.C10() = mxy[ih0].Dxy();
-        T.C11() = mxy[ih0].Dy2();
-
-        T.Ndf()     = -ndfTrackModel + 2;
-        T.NdfTime() = sta[ih0].timeInfo ? 0 : -1;
-
-        if (startIdx == 0) {  //only for the forward fit
-          fit.FilterWithTargetAtLine(fParameters.GetTargetPositionZ(), frWData.TargetMeasurement(), fldTarget);
-        }
+      kf::FieldValue<fvec> B[3] _fvecalignment;
+      kf::FieldRegion<fvec> fld _fvecalignment;
+      kf::FieldRegion<fvec> fldTarget _fvecalignment;
 
-        for (int ih = startIdx + step; ih != endIdx; ih += step) {
-          fit.Extrapolate(z[ih], fld);
-          auto radThick = fSetup.GetMaterial(ista[ih]).GetThicknessX0(T.X(), T.Y());
-          fit.MultipleScattering(radThick);
-          fit.EnergyLossCorrection(radThick, direction);
-          fit.FilterXY(mxy[ih]);
-          fit.FilterTime(t[ih], dt2[ih], fmask(sta[ih].timeInfo));
-        }
+      fvec tx[3] = {(x[1] - x[0]) / (z[1] - z[0]), (x[2] - x[0]) / (z[2] - z[0]), (x[2] - x[1]) / (z[2] - z[1])};
+      fvec ty[3] = {(y[1] - y[0]) / (z[1] - z[0]), (y[2] - y[0]) / (z[2] - z[0]), (y[2] - y[1]) / (z[2] - z[1])};
+
+      for (int ih = 0; ih < NHits; ++ih) {
+        fvec dz = (sta[ih].fZ - z[ih]);
+        B[ih]   = sta[ih].fieldSlice.GetFieldValue(x[ih] + tx[ih] * dz, y[ih] + ty[ih] * dz);
       };
 
-      // Fit downstream
-      fitTrack(0, NHits, 1, kf::FitDirection::kDownstream);
+      fld.Set(B[0], sta[0].fZ, B[1], sta[1].fZ, B[2], sta[2].fZ);
+      fldTarget.Set(frWData.TargB(), fParameters.GetTargetPositionZ(), B[0], sta[0].fZ, B[1], sta[1].fZ);
 
-      if (iiter == nIterations - 1) break;
+      TrackParamV& T = fit.Tr();
 
-      // Fit upstream
-      fitTrack(NHits - 1, -1, -1, kf::FitDirection::kUpstream);
-    }  // for iiter
+      // initial parameters
+      {
+        fvec dz01 = 1. / (z[1] - z[0]);
+        T.Tx()    = (x[1] - x[0]) * dz01;
+        T.Ty()    = (y[1] - y[0]) * dz01;
+        T.Qp()    = 0.;
+        T.Vi()    = 0.;
+      }
 
-    tracks.push_back(T);
+      // repeat several times in order to improve the precision
+      for (int iiter = 0; iiter < nIterations; ++iiter) {
+
+        auto fitTrack = [&](int startIdx, int endIdx, int step, kf::FitDirection direction) {
+          const fvec maxQp = frWData.CurrentIteration()->GetMaxQp();
+          fit.SetQp0(T.Qp());
+          fit.Qp0()(fit.Qp0() > maxQp)  = maxQp;
+          fit.Qp0()(fit.Qp0() < -maxQp) = -maxQp;
+
+          int ih0  = startIdx;
+          T.X()    = x[ih0];
+          T.Y()    = y[ih0];
+          T.Z()    = z[ih0];
+          T.Time() = t[ih0];
+          T.Qp()   = 0.;
+          T.Vi()   = 0.;
+
+          T.ResetErrors(1., 1., 1., 1., 100., (sta[ih0].timeInfo ? dt2[ih0] : 1.e6), 1.e2);
+          T.C00() = mxy[ih0].Dx2();
+          T.C10() = mxy[ih0].Dxy();
+          T.C11() = mxy[ih0].Dy2();
+
+          T.Ndf()     = -ndfTrackModel + 2;
+          T.NdfTime() = sta[ih0].timeInfo ? 0 : -1;
+
+          if (startIdx == 0) {  //only for the forward fit
+            fit.FilterWithTargetAtLine(fParameters.GetTargetPositionZ(), frWData.TargetMeasurement(), fldTarget);
+          }
 
-    if constexpr (fDebugTriplets) {
-      int ih0 = ihit[0];
-      int ih1 = ihit[1];
-      int ih2 = ihit[2];
-      int mc1 = ca::Framework::GetMcTrackIdForCaHit(ih0);
-      int mc2 = ca::Framework::GetMcTrackIdForCaHit(ih1);
-      int mc3 = ca::Framework::GetMcTrackIdForCaHit(ih2);
-
-      if (1 || (mc1 >= 0) && (mc1 == mc2) && (mc1 == mc3)) {
-        const ca::Hit& h0 = frWData.Hit(iwhit[0]);
-        const ca::Hit& h1 = frWData.Hit(iwhit[1]);
-        const ca::Hit& h2 = frWData.Hit(iwhit[2]);
-        //const CbmL1MCTrack& mctr = CbmL1::Instance()->GetMcTracks()[mc1];
-        LOG(info) << "== fitted triplet: "
-                  << " iter " << frWData.CurrentIteration()->GetName() << " hits: {" << fIstaL << "/" << ih0 << " "
-                  << fIstaM << "/" << ih1 << " " << fIstaR << "/" << ih2 << "} xyz: {" << h0.X() << " " << h0.Y() << " "
-                  << h0.Z() << "}, {" << h1.X() << " " << h1.Y() << " " << h1.Z() << "}, {" << h2.X() << ", " << h2.Y()
-                  << ", " << h2.Z() << "} chi2 " << T.GetChiSq()[0] << " ndf " << T.Ndf()[0] << " chi2time "
-                  << T.ChiSqTime()[0] << " ndfTime " << T.NdfTime()[0];
-        /*
-        cbm::ca::tools::Debugger::Instance().FillNtuple(
-          "triplets", mctr.iEvent, frAlgo.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, (fscal) T.GetChiSq()[0],
-          (fscal) T.Ndf()[0], (fscal) T.ChiSqTime()[0], (fscal) T.NdfTime()[0]);
-        */
+          for (int ih = startIdx + step; ih != endIdx; ih += step) {
+            fit.Extrapolate(z[ih], fld);
+            auto radThick = fSetup.GetMaterial(ista[ih]).GetThicknessX0(T.X(), T.Y());
+            fit.MultipleScattering(radThick);
+            fit.EnergyLossCorrection(radThick, direction);
+            fit.FilterXY(mxy[ih]);
+            fit.FilterTime(t[ih], dt2[ih], fmask(sta[ih].timeInfo));
+          }
+        };
+
+        // Fit downstream
+        fitTrack(0, NHits, 1, kf::FitDirection::kDownstream);
+
+        if (iiter == nIterations - 1) break;
+
+        // Fit upstream
+        fitTrack(NHits - 1, -1, -1, kf::FitDirection::kUpstream);
+      }  // for iiter
+
+      tracks.push_back(T);
+
+      if constexpr (fDebugTriplets) {
+        int ih0 = ihit[0];
+        int ih1 = ihit[1];
+        int ih2 = ihit[2];
+        int mc1 = ca::Framework::GetMcTrackIdForCaHit(ih0);
+        int mc2 = ca::Framework::GetMcTrackIdForCaHit(ih1);
+        int mc3 = ca::Framework::GetMcTrackIdForCaHit(ih2);
+
+        if (1 || (mc1 >= 0) && (mc1 == mc2) && (mc1 == mc3)) {
+          const ca::Hit& h0 = frWData.Hit(iwhit[0]);
+          const ca::Hit& h1 = frWData.Hit(iwhit[1]);
+          const ca::Hit& h2 = frWData.Hit(iwhit[2]);
+          //const CbmL1MCTrack& mctr = CbmL1::Instance()->GetMcTracks()[mc1];
+          LOG(info) << "== fitted triplet: "
+                    << " iter " << frWData.CurrentIteration()->GetName() << " hits: {" << fIstaL << "/" << ih0 << " "
+                    << fIstaM << "/" << ih1 << " " << fIstaR << "/" << ih2 << "} xyz: {" << h0.X() << " " << h0.Y()
+                    << " " << h0.Z() << "}, {" << h1.X() << " " << h1.Y() << " " << h1.Z() << "}, {" << h2.X() << ", "
+                    << h2.Y() << ", " << h2.Z() << "} chi2 " << T.GetChiSq()[0] << " ndf " << T.Ndf()[0] << " chi2time "
+                    << T.ChiSqTime()[0] << " ndfTime " << T.NdfTime()[0];
+          /*
+          cbm::ca::tools::Debugger::Instance().FillNtuple(
+            "triplets", mctr.iEvent, frAlgo.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, (fscal) T.GetChiSq()[0],
+            (fscal) T.Ndf()[0], (fscal) T.ChiSqTime()[0], (fscal) T.NdfTime()[0]);
+          */
+        }
       }
-    }
-  }  //i3
-}  // FindTriplets
+    }  //i3
+  }    // FindTriplets
 
 
-void TripletConstructor::SelectTriplets(Vector<ca::Triplet>& tripletsOut)
-{
-  /// Selects good triplets and saves them into tripletsOut.
-  /// Finds neighbouring triplets at the next station.
+  void TripletConstructor::SelectTriplets(Vector<ca::Triplet>& tripletsOut)
+  {
+    /// Selects good triplets and saves them into tripletsOut.
+    /// Finds neighbouring triplets at the next station.
 
-  Vector<TrackParamV>& tracks   = std::get<0>(fTripletData);
-  Vector<ca::HitIndex_t>& hitsM = std::get<1>(fTripletData);
-  Vector<ca::HitIndex_t>& hitsR = std::get<2>(fTripletData);
+    Vector<TrackParamV>& tracks   = std::get<0>(fTripletData);
+    Vector<ca::HitIndex_t>& hitsM = std::get<1>(fTripletData);
+    Vector<ca::HitIndex_t>& hitsR = std::get<2>(fTripletData);
 
-  bool isMomentumFitted = ((fStaL->fieldStatus != 0) || (fStaM->fieldStatus != 0) || (fStaR->fieldStatus != 0));
+    bool isMomentumFitted = ((fStaL->fieldStatus != 0) || (fStaM->fieldStatus != 0) || (fStaR->fieldStatus != 0));
 
-  tripletsOut.clear();
-  tripletsOut.reserve(hitsM.size());
+    tripletsOut.clear();
+    tripletsOut.reserve(hitsM.size());
 
-  for (size_t i3 = 0; i3 < hitsM.size(); ++i3) {
+    for (size_t i3 = 0; i3 < hitsM.size(); ++i3) {
 
-    TrackParamV& T3 = tracks[i3];
+      TrackParamV& T3 = tracks[i3];
 
-    // TODO: SG: normalize chi2, separate cuts on time and space
+      // TODO: SG: normalize chi2, separate cuts on time and space
 
-    const fscal chi2 = T3.GetChiSq()[0] + T3.GetChiSqTime()[0];
+      const fscal chi2 = T3.GetChiSq()[0] + T3.GetChiSqTime()[0];
 
-    const ca::HitIndex_t ihitl = fIhitL;
-    const ca::HitIndex_t ihitm = hitsM[i3];
-    const ca::HitIndex_t ihitr = hitsR[i3];
+      const ca::HitIndex_t ihitl = fIhitL;
+      const ca::HitIndex_t ihitm = hitsM[i3];
+      const ca::HitIndex_t ihitr = hitsR[i3];
 
-    CBMCA_DEBUG_ASSERT(ihitl < frWData.HitStartIndexOnStation(fIstaL + 1));
-    CBMCA_DEBUG_ASSERT(ihitm < frWData.HitStartIndexOnStation(fIstaM + 1));
-    CBMCA_DEBUG_ASSERT(ihitr < frWData.HitStartIndexOnStation(fIstaR + 1));
+      CBMCA_DEBUG_ASSERT(ihitl < frWData.HitStartIndexOnStation(fIstaL + 1));
+      CBMCA_DEBUG_ASSERT(ihitm < frWData.HitStartIndexOnStation(fIstaM + 1));
+      CBMCA_DEBUG_ASSERT(ihitr < frWData.HitStartIndexOnStation(fIstaR + 1));
 
-    if (!frWData.CurrentIteration()->GetTrackFromTripletsFlag()) {
-      if (chi2 > frWData.CurrentIteration()->GetTripletFinalChi2Cut()) {
-        continue;
+      if (!frWData.CurrentIteration()->GetTrackFromTripletsFlag()) {
+        if (chi2 > frWData.CurrentIteration()->GetTripletFinalChi2Cut()) {
+          continue;
+        }
       }
-    }
-    // assert(std::isfinite(chi2) && chi2 > 0);
+      // assert(std::isfinite(chi2) && chi2 > 0);
 
-    if (!std::isfinite(chi2) || chi2 < 0) {
-      continue;
-    }
-    //if (!T3.IsEntryConsistent(true, 0)) { continue; }
+      if (!std::isfinite(chi2) || chi2 < 0) {
+        continue;
+      }
+      //if (!T3.IsEntryConsistent(true, 0)) { continue; }
 
-    fscal qp  = T3.Qp()[0];
-    fscal Cqp = T3.C44()[0];
+      fscal qp  = T3.Qp()[0];
+      fscal Cqp = T3.C44()[0];
 
-    // TODO: SG: a magic correction that comes from the legacy code
-    // removing it leads to a higher ghost ratio
-    Cqp += 0.001;
+      // TODO: SG: a magic correction that comes from the legacy code
+      // removing it leads to a higher ghost ratio
+      Cqp += 0.001;
 
-    tripletsOut.emplace_back(ihitl, ihitm, ihitr, fIstaL, fIstaM, fIstaR, 0, 0, 0, chi2, qp, Cqp, T3.Tx()[0],
-                             T3.C22()[0], T3.Ty()[0], T3.C33()[0], isMomentumFitted);
+      tripletsOut.emplace_back(ihitl, ihitm, ihitr, fIstaL, fIstaM, fIstaR, 0, 0, 0, chi2, qp, Cqp, T3.Tx()[0],
+                               T3.C22()[0], T3.Ty()[0], T3.C33()[0], isMomentumFitted);
+    }
   }
-}
-
 
-void TripletConstructor::CollectHits(Vector<ca::HitIndex_t>& collectedHits, kf::TrackKalmanFilter<fvec>& fit,
-                                     const int iSta, const double chi2Cut, const int iMC, const int maxNhits)
-{
-  /// Collect hits on a station
-  collectedHits.clear();
-  collectedHits.reserve(maxNhits);
-
-  const ca::Station<fvec>& sta = fParameters.GetStation(iSta);
-
-  TrackParamV& T = fit.Tr();
-  //LOG(info) << T.chi2[0] ;
-  T.ChiSq() = 0.;
-
-  // if make it bigger the found hits will be rejected later because of the chi2 cut.
-  const fvec Pick_m22    = (fvec(chi2Cut) - T.GetChiSq());
-  const fscal timeError2 = T.C55()[0];
-  const fscal time       = T.Time()[0];
-
-  const auto& grid = frWData.Grid(iSta);
-  const fvec maxDZ = frWData.CurrentIteration()->GetMaxDZ();
-  ca::GridArea area(grid, T.X()[0], T.Y()[0],
-                    (sqrt(Pick_m22 * T.C00()) + grid.GetMaxRangeX() + maxDZ * kf::utils::fabs(T.Tx()))[0],
-                    (sqrt(Pick_m22 * T.C11()) + grid.GetMaxRangeY() + maxDZ * kf::utils::fabs(T.Ty()))[0]);
-  if constexpr (fDebugCollectHits) {
-    LOG(info) << "search area: " << T.X()[0] << " " << T.Y()[0] << " "
-              << (sqrt(Pick_m22 * T.C00()) + grid.GetMaxRangeX() + maxDZ * kf::utils::fabs(T.Tx()))[0] << " "
-              << (sqrt(Pick_m22 * T.C11()) + grid.GetMaxRangeY() + maxDZ * kf::utils::fabs(T.Ty()))[0];
-  }
-  if (fParameters.DevIsIgnoreHitSearchAreas()) {
-    area.DoLoopOverEntireGrid();
-  }
 
-  // loop over station hits (index incremented in condition)
-  for (ca::HitIndex_t ih = 0; area.GetNextObjectId(ih) && ((int) collectedHits.size() < maxNhits);) {
+  void TripletConstructor::CollectHits(Vector<ca::HitIndex_t>& collectedHits, kf::TrackKalmanFilter<fvec>& fit,
+                                       const int iSta, const double chi2Cut, const int iMC, const int maxNhits)
+  {
+    /// Collect hits on a station
+    collectedHits.clear();
+    collectedHits.reserve(maxNhits);
 
-    if (frWData.IsHitSuppressed(ih)) {
-      continue;
-    }
+    const ca::Station<fvec>& sta = fParameters.GetStation(iSta);
 
-    const ca::Hit& hit = frWData.Hit(ih);
+    TrackParamV& T = fit.Tr();
+    //LOG(info) << T.chi2[0] ;
+    T.ChiSq() = 0.;
+
+    // if make it bigger the found hits will be rejected later because of the chi2 cut.
+    const fvec Pick_m22    = (fvec(chi2Cut) - T.GetChiSq());
+    const fscal timeError2 = T.C55()[0];
+    const fscal time       = T.Time()[0];
+
+    const auto& grid = frWData.Grid(iSta);
+    const fvec maxDZ = frWData.CurrentIteration()->GetMaxDZ();
+    ca::GridArea area(grid, T.X()[0], T.Y()[0],
+                      (sqrt(Pick_m22 * T.C00()) + grid.GetMaxRangeX() + maxDZ * kf::utils::fabs(T.Tx()))[0],
+                      (sqrt(Pick_m22 * T.C11()) + grid.GetMaxRangeY() + maxDZ * kf::utils::fabs(T.Ty()))[0]);
     if constexpr (fDebugCollectHits) {
-      LOG(info) << "hit in the search area: " << hit.ToString();
-      LOG(info) << "   check the hit.. ";
+      LOG(info) << "search area: " << T.X()[0] << " " << T.Y()[0] << " "
+                << (sqrt(Pick_m22 * T.C00()) + grid.GetMaxRangeX() + maxDZ * kf::utils::fabs(T.Tx()))[0] << " "
+                << (sqrt(Pick_m22 * T.C11()) + grid.GetMaxRangeY() + maxDZ * kf::utils::fabs(T.Ty()))[0];
     }
-
-    if (iMC >= 0) {  // match via MC
-      if (iMC != ca::Framework::GetMcTrackIdForWindowHit(ih)) {
-        if constexpr (fDebugCollectHits) {
-          LOG(info) << "   hit mc does not match";
-        }
-        continue;
-      }
+    if (fParameters.DevIsIgnoreHitSearchAreas()) {
+      area.DoLoopOverEntireGrid();
     }
 
-    // check time-boundaries
+    // loop over station hits (index incremented in condition)
+    for (ca::HitIndex_t ih = 0; area.GetNextObjectId(ih) && ((int) collectedHits.size() < maxNhits);) {
 
-    //TODO: move hardcoded cuts to parameters
-    if ((sta.timeInfo) && (T.NdfTime()[0] >= 0)) {
-      if (fabs(time - hit.T()) > 1.4 * (3.5 * sqrt(timeError2) + hit.RangeT())) {
-        if constexpr (fDebugCollectHits) {
-          LOG(info) << "   hit time does not match";
-        }
+      if (frWData.IsHitSuppressed(ih)) {
         continue;
       }
-      // if (fabs(time - hit.T()) > 30) continue;
-    }
-
-    // - check whether hit belong to the window ( track position +\- errors ) -
-    const fscal z = hit.Z();
-
-    // check y-boundaries
-    const auto [y, C11] = fit.ExtrapolateLineYdY2(z);
-    const fscal dy_est  = sqrt(Pick_m22[0] * C11[0]) + hit.RangeY();
-    const fscal dY      = hit.Y() - y[0];
 
-    if (fabs(dY) > dy_est) {
+      const ca::Hit& hit = frWData.Hit(ih);
       if constexpr (fDebugCollectHits) {
-        LOG(info) << "   hit Y does not match";
+        LOG(info) << "hit in the search area: " << hit.ToString();
+        LOG(info) << "   check the hit.. ";
       }
-      continue;
-    }
 
-    // check x-boundaries
-    const auto [x, C00] = fit.ExtrapolateLineXdX2(z);
-    const fscal dx_est  = sqrt(Pick_m22[0] * C00[0]) + hit.RangeX();
-    const fscal dX      = hit.X() - x[0];
+      if (iMC >= 0) {  // match via MC
+        if (iMC != ca::Framework::GetMcTrackIdForWindowHit(ih)) {
+          if constexpr (fDebugCollectHits) {
+            LOG(info) << "   hit mc does not match";
+          }
+          continue;
+        }
+      }
 
-    if (fabs(dX) > dx_est) {
-      if constexpr (fDebugCollectHits) {
-        LOG(info) << "   hit X does not match";
+      // check time-boundaries
+
+      //TODO: move hardcoded cuts to parameters
+      if ((sta.timeInfo) && (T.NdfTime()[0] >= 0)) {
+        if (fabs(time - hit.T()) > 1.4 * (3.5 * sqrt(timeError2) + hit.RangeT())) {
+          if constexpr (fDebugCollectHits) {
+            LOG(info) << "   hit time does not match";
+          }
+          continue;
+        }
+        // if (fabs(time - hit.T()) > 30) continue;
       }
-      continue;
-    }
 
-    // check chi2
-    kf::MeasurementXy<fvec> mxy(hit.X(), hit.Y(), hit.dX2(), hit.dY2(), hit.dXY(), fvec::One(), fvec::One());
+      // - check whether hit belong to the window ( track position +\- errors ) -
+      const fscal z = hit.Z();
 
-    const fvec C10            = fit.ExtrapolateLineDxy(z);
-    const auto [chi2x, chi2u] = kf::TrackKalmanFilter<fvec>::GetChi2XChi2U(mxy, x, y, C00, C10, C11);
+      // check y-boundaries
+      const auto [y, C11] = fit.ExtrapolateLineYdY2(z);
+      const fscal dy_est  = sqrt(Pick_m22[0] * C11[0]) + hit.RangeY();
+      const fscal dY      = hit.Y() - y[0];
 
-    // TODO: adjust the cut, cut on chi2x & chi2u separately
-    if (!frWData.CurrentIteration()->GetTrackFromTripletsFlag()) {
-      if (chi2x[0] > chi2Cut) {
+      if (fabs(dY) > dy_est) {
         if constexpr (fDebugCollectHits) {
-          LOG(info) << "   hit chi2X is too large";
+          LOG(info) << "   hit Y does not match";
         }
         continue;
       }
-      if (chi2u[0] > chi2Cut) {
+
+      // check x-boundaries
+      const auto [x, C00] = fit.ExtrapolateLineXdX2(z);
+      const fscal dx_est  = sqrt(Pick_m22[0] * C00[0]) + hit.RangeX();
+      const fscal dX      = hit.X() - x[0];
+
+      if (fabs(dX) > dx_est) {
         if constexpr (fDebugCollectHits) {
-          LOG(info) << "   hit chi2U is too large";
+          LOG(info) << "   hit X does not match";
         }
         continue;
       }
-    }
-    if constexpr (fDebugCollectHits) {
-      LOG(info) << "   hit passed all the checks";
-    }
-    collectedHits.push_back(ih);
 
-  }  // loop over the hits in the area
-}
+      // check chi2
+      kf::MeasurementXy<fvec> mxy(hit.X(), hit.Y(), hit.dX2(), hit.dY2(), hit.dXY(), fvec::One(), fvec::One());
+
+      const fvec C10            = fit.ExtrapolateLineDxy(z);
+      const auto [chi2x, chi2u] = kf::TrackKalmanFilter<fvec>::GetChi2XChi2U(mxy, x, y, C00, C10, C11);
+
+      // TODO: adjust the cut, cut on chi2x & chi2u separately
+      if (!frWData.CurrentIteration()->GetTrackFromTripletsFlag()) {
+        if (chi2x[0] > chi2Cut) {
+          if constexpr (fDebugCollectHits) {
+            LOG(info) << "   hit chi2X is too large";
+          }
+          continue;
+        }
+        if (chi2u[0] > chi2Cut) {
+          if constexpr (fDebugCollectHits) {
+            LOG(info) << "   hit chi2U is too large";
+          }
+          continue;
+        }
+      }
+      if constexpr (fDebugCollectHits) {
+        LOG(info) << "   hit passed all the checks";
+      }
+      collectedHits.push_back(ih);
+
+    }  // loop over the hits in the area
+  }
+}  // namespace cbm::algo::ca
diff --git a/algo/kf/core/geo/KfFieldRegion.cxx b/algo/kf/core/geo/KfFieldRegion.cxx
index 340e22a18d6b5378857c434fd3bf61473ef04bde..55c518c6db0cf98f3b81c07af64397f5b9472466 100644
--- a/algo/kf/core/geo/KfFieldRegion.cxx
+++ b/algo/kf/core/geo/KfFieldRegion.cxx
@@ -17,236 +17,223 @@
 
 #include <fmt/format.h>
 
-using cbm::algo::kf::EFieldMode;
-using cbm::algo::kf::FieldFn_t;
-using cbm::algo::kf::FieldRegion;
-using cbm::algo::kf::FieldValue;
-using cbm::algo::kf::GlobalField;
-
-using cbm::algo::kf::detail::FieldRegionBase;
-using namespace cbm::algo;
-
-FieldFn_t GlobalField::fgOriginalField = &GlobalField::UndefField;
-
-kf::EFieldType GlobalField::fgOriginalFieldType{kf::EFieldType::Null};
-
-
-bool GlobalField::fgForceUseOfOriginalField = false;
-
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-void FieldRegionBase<T, EFieldMode::Intrpl>::Set(const FieldValue<T>& b0, const T& z0, const FieldValue<T>& b1,
-                                                 const T& z1, const FieldValue<T>& b2, const T& z2)
+namespace cbm::algo::kf
 {
-  fZfirst = z0;
-
-  auto dz1 = z1 - z0;
-  auto dz2 = z2 - z0;
-  auto det = utils::simd::One<T>() / (dz1 * dz2 * (z2 - z1));
-  auto w21 = -dz2 * det;
-  auto w22 = dz1 * det;
-  auto w11 = -dz2 * w21;
-  auto w12 = -dz1 * w22;
-
-  for (int iD = 0; iD < 3; ++iD) {
-    auto db1    = b1.GetComponent(iD) - b0.GetComponent(iD);
-    auto db2    = b2.GetComponent(iD) - b0.GetComponent(iD);
-    auto& coeff = fCoeff[iD];
-    coeff[0]    = b0.GetComponent(iD);
-    coeff[1]    = db1 * w11 + db2 * w12;
-    coeff[2]    = db1 * w21 + db2 * w22;
+  using detail::FieldRegionBase;
+  FieldFn_t GlobalField::fgOriginalField{&GlobalField::UndefField};
+  EFieldType GlobalField::fgOriginalFieldType{EFieldType::Null};
+  bool GlobalField::fgForceUseOfOriginalField{false};
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  void FieldRegionBase<T, EFieldMode::Intrpl>::Set(const FieldValue<T>& b0, const T& z0, const FieldValue<T>& b1,
+                                                   const T& z1, const FieldValue<T>& b2, const T& z2)
+  {
+    fZfirst = z0;
+
+    auto dz1 = z1 - z0;
+    auto dz2 = z2 - z0;
+    auto det = utils::simd::One<T>() / (dz1 * dz2 * (z2 - z1));
+    auto w21 = -dz2 * det;
+    auto w22 = dz1 * det;
+    auto w11 = -dz2 * w21;
+    auto w12 = -dz1 * w22;
+
+    for (int iD = 0; iD < 3; ++iD) {
+      auto db1    = b1.GetComponent(iD) - b0.GetComponent(iD);
+      auto db2    = b2.GetComponent(iD) - b0.GetComponent(iD);
+      auto& coeff = fCoeff[iD];
+      coeff[0]    = b0.GetComponent(iD);
+      coeff[1]    = db1 * w11 + db2 * w12;
+      coeff[2]    = db1 * w21 + db2 * w22;
+    }
   }
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-FieldValue<T> FieldRegionBase<T, EFieldMode::Intrpl>::Get(const T& x, const T& y, const T& z) const
-{
-  if (GlobalField::IsUsingOriginalFieldForced()) {
-    return GlobalField::GetFieldValue(GlobalField::fgOriginalField, x, y, z);
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  FieldValue<T> FieldRegionBase<T, EFieldMode::Intrpl>::Get(const T& x, const T& y, const T& z) const
+  {
+    if (GlobalField::IsUsingOriginalFieldForced()) {
+      return GlobalField::GetFieldValue(GlobalField::fgOriginalField, x, y, z);
+    }
+    auto dz = z - this->fZfirst;
+    return FieldValue<T>{this->fCoeff[0][0] + dz * (this->fCoeff[0][1] + dz * this->fCoeff[0][2]),
+                         this->fCoeff[1][0] + dz * (this->fCoeff[1][1] + dz * this->fCoeff[1][2]),
+                         this->fCoeff[2][0] + dz * (this->fCoeff[2][1] + dz * this->fCoeff[2][2])};
   }
-  auto dz = z - this->fZfirst;
-  return FieldValue<T>{this->fCoeff[0][0] + dz * (this->fCoeff[0][1] + dz * this->fCoeff[0][2]),
-                       this->fCoeff[1][0] + dz * (this->fCoeff[1][1] + dz * this->fCoeff[1][2]),
-                       this->fCoeff[2][0] + dz * (this->fCoeff[2][1] + dz * this->fCoeff[2][2])};
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-std::tuple<T, T, T>
-FieldRegionBase<T, EFieldMode::Intrpl>::GetDoubleIntegrals(const T& /*x1*/, const T& /*y1*/, const T& z1,  //
-                                                           const T& /*x2*/, const T& /*y2*/, const T& z2) const
-{
-  // double integral of the field along z
 
-  if (GlobalField::IsUsingOriginalFieldForced()) {
-    // TODO: implement the double integral for the original field
-  }
-  auto fld = *this;
-  fld.Shift(z1);
-  T dz  = z2 - z1;
-  T dz2 = dz * dz;
-  T c0  = dz2 * T(1. / 2.);
-  T c1  = dz2 * dz * T(1. / 6.);
-  T c2  = dz2 * dz2 * T(1. / 12.);
-  return {c0 * fld.fCoeff[0][0] + c1 * fld.fCoeff[0][1] + c2 * fld.fCoeff[0][2],
-          c0 * fld.fCoeff[1][0] + c1 * fld.fCoeff[1][1] + c2 * fld.fCoeff[1][2],
-          c0 * fld.fCoeff[2][0] + c1 * fld.fCoeff[2][1] + c2 * fld.fCoeff[2][2]};
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-void FieldRegionBase<T, EFieldMode::Intrpl>::Shift(const T& z)
-{
-  auto dz = z - fZfirst;
-  for (int iD = 0; iD < 3; ++iD) {
-    auto& coeff = fCoeff[iD];
-    auto c2dz   = coeff[2] * dz;
-    coeff[0] += (coeff[1] + c2dz) * dz;
-    coeff[1] += (2 * c2dz);
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  std::tuple<T, T, T>
+  FieldRegionBase<T, EFieldMode::Intrpl>::GetDoubleIntegrals(const T& /*x1*/, const T& /*y1*/, const T& z1,  //
+                                                             const T& /*x2*/, const T& /*y2*/, const T& z2) const
+  {
+    // double integral of the field along z
+
+    if (GlobalField::IsUsingOriginalFieldForced()) {
+      // TODO: implement the double integral for the original field
+    }
+    auto fld = *this;
+    fld.Shift(z1);
+    T dz  = z2 - z1;
+    T dz2 = dz * dz;
+    T c0  = dz2 * T(1. / 2.);
+    T c1  = dz2 * dz * T(1. / 6.);
+    T c2  = dz2 * dz2 * T(1. / 12.);
+    return {c0 * fld.fCoeff[0][0] + c1 * fld.fCoeff[0][1] + c2 * fld.fCoeff[0][2],
+            c0 * fld.fCoeff[1][0] + c1 * fld.fCoeff[1][1] + c2 * fld.fCoeff[1][2],
+            c0 * fld.fCoeff[2][0] + c1 * fld.fCoeff[2][1] + c2 * fld.fCoeff[2][2]};
   }
-  fZfirst = z;
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-void FieldRegionBase<T, EFieldMode::Intrpl>::CheckConsistency() const
-{
-  // Check SIMD data vectors for consistent initialization
-  for (int iD = 0; iD < 3; ++iD) {
-    for (int iC = 0; iC < 3; ++iC) {
-      utils::CheckSimdVectorEquality(fCoeff[iD][iC], fmt::format("FieldRegion::fCoeff[{}][{}]", iD, iC).c_str());
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  void FieldRegionBase<T, EFieldMode::Intrpl>::Shift(const T& z)
+  {
+    auto dz = z - fZfirst;
+    for (int iD = 0; iD < 3; ++iD) {
+      auto& coeff = fCoeff[iD];
+      auto c2dz   = coeff[2] * dz;
+      coeff[0] += (coeff[1] + c2dz) * dz;
+      coeff[1] += (2 * c2dz);
     }
+    fZfirst = z;
   }
-  utils::CheckSimdVectorEquality(fZfirst, "FieldRegion::fZfirst");
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-std::string FieldRegionBase<T, EFieldMode::Intrpl>::ToString(int indentLevel, int) const
-{
-  constexpr char IndentChar = '\t';
-  std::stringstream msg;
-  std::string indent(indentLevel, IndentChar);
-  using fmt::format;
-  auto Cnv = [&](const auto& val) { return utils::simd::Cast<T, Literal_t<T>>(val); };  // alias for the conversion fn
-  const auto& coeff = this->fCoeff;
-  msg << indent << format("Field Region: dz = z - ({})", Cnv(this->fZfirst));
-  msg << '\n'
-      << indent << IndentChar
-      << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[0][0]), Cnv(coeff[0][1]), Cnv(coeff[0][2]));
-  msg << '\n'
-      << indent << IndentChar
-      << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[1][0]), Cnv(coeff[1][1]), Cnv(coeff[1][2]));
-  msg << '\n'
-      << indent << IndentChar
-      << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[2][0]), Cnv(coeff[2][1]), Cnv(coeff[2][2]));
-  if (GlobalField::IsUsingOriginalFieldForced()) {
-    msg
-      << indent
-      << "\nWARNING: the GlobalField::ForceUseOfOriginalField() is enabled, so the magnetic field interpolation "
-      << indent
-      << "\nis replaced with the global magnetic function for debugging purposes. If you see this message and are "
-      << indent
-      << "\nnot sure, what is going on, please call GlobalField::ForceUseOfOriginalField(false) and re-run the routine";
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  void FieldRegionBase<T, EFieldMode::Intrpl>::CheckConsistency() const
+  {
+    // Check SIMD data vectors for consistent initialization
+    for (int iD = 0; iD < 3; ++iD) {
+      for (int iC = 0; iC < 3; ++iC) {
+        utils::CheckSimdVectorEquality(fCoeff[iD][iC], fmt::format("FieldRegion::fCoeff[{}][{}]", iD, iC).c_str());
+      }
+    }
+    utils::CheckSimdVectorEquality(fZfirst, "FieldRegion::fZfirst");
   }
-  return msg.str();
-}
-
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-void FieldRegionBase<T, EFieldMode::Orig>::CheckConsistency() const
-{
-  // Check SIMD data vectors for consistent initialization
-}
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  std::string FieldRegionBase<T, EFieldMode::Intrpl>::ToString(int indentLevel, int) const
+  {
+    constexpr char IndentChar = '\t';
+    std::stringstream msg;
+    std::string indent(indentLevel, IndentChar);
+    using fmt::format;
+    auto Cnv = [&](const auto& val) { return utils::simd::Cast<T, Literal_t<T>>(val); };  // alias for the conversion fn
+    const auto& coeff = this->fCoeff;
+    msg << indent << format("Field Region: dz = z - ({})", Cnv(this->fZfirst));
+    msg << '\n'
+        << indent << IndentChar
+        << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[0][0]), Cnv(coeff[0][1]), Cnv(coeff[0][2]));
+    msg << '\n'
+        << indent << IndentChar
+        << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[1][0]), Cnv(coeff[1][1]), Cnv(coeff[1][2]));
+    msg << '\n'
+        << indent << IndentChar
+        << format("Bx(dz) = {:>12} + {:>12} dz + {:>12} dz2", Cnv(coeff[2][0]), Cnv(coeff[2][1]), Cnv(coeff[2][2]));
+    if (GlobalField::IsUsingOriginalFieldForced()) {
+      msg << indent
+          << "\nWARNING: the GlobalField::ForceUseOfOriginalField() is enabled, so the magnetic field interpolation "
+          << indent
+          << "\nis replaced with the global magnetic function for debugging purposes. If you see this message and are "
+          << indent
+          << "\nnot sure, what is going on, please call GlobalField::ForceUseOfOriginalField(false) and re-run the "
+             "routine";
+    }
+    return msg.str();
+  }
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-std::string FieldRegionBase<T, EFieldMode::Orig>::ToString(int indentLevel, int) const
-{
-  constexpr char IndentChar = '\t';
-  std::stringstream msg;
-  std::string indent(indentLevel, IndentChar);
-  msg << indent << "Field region: created from the original field function";
-  return msg.str();
-}
 
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  void FieldRegionBase<T, EFieldMode::Orig>::CheckConsistency() const
+  {
+    // Check SIMD data vectors for consistent initialization
+  }
 
-namespace cbm::algo::kf::detail
-{
-  template class FieldRegionBase<float, EFieldMode::Intrpl>;
-  template class FieldRegionBase<double, EFieldMode::Intrpl>;
-  template class FieldRegionBase<fvec, EFieldMode::Intrpl>;
-  template class FieldRegionBase<float, EFieldMode::Orig>;
-  template class FieldRegionBase<double, EFieldMode::Orig>;
-  template class FieldRegionBase<fvec, EFieldMode::Orig>;
-}  // namespace cbm::algo::kf::detail
-
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-void FieldRegion<T>::Shift(const T& z)
-{
-  if (fFieldMode == EFieldMode::Intrpl) {
-    foFldIntrpl->Shift(z);
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  std::string FieldRegionBase<T, EFieldMode::Orig>::ToString(int indentLevel, int) const
+  {
+    constexpr char IndentChar = '\t';
+    std::stringstream msg;
+    std::string indent(indentLevel, IndentChar);
+    msg << indent << "Field region: created from the original field function";
+    return msg.str();
   }
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-std::string FieldRegion<T>::ToString(int indentLevel, int) const
-{
-  constexpr char IndentChar = '\t';
-  std::stringstream msg;
-  std::string indent(indentLevel, IndentChar);
-  msg << indent << "FieldType: " << static_cast<int>(fFieldType) << '\n';
-  msg << indent << "FieldMode: " << static_cast<int>(fFieldMode) << '\n';
-  msg << indent
-      << (fFieldMode == EFieldMode::Intrpl ? foFldIntrpl->ToString(indentLevel) : foFldOrig->ToString(indentLevel));
-  return msg.str();
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-void FieldRegion<T>::CheckConsistency() const
-{
-  // Check SIMD data vectors for consistent initialization
 
-  if (fFieldMode == EFieldMode::Intrpl) {
-    foFldIntrpl->CheckConsistency();
+  namespace detail
+  {
+    template class FieldRegionBase<float, EFieldMode::Intrpl>;
+    template class FieldRegionBase<double, EFieldMode::Intrpl>;
+    template class FieldRegionBase<fvec, EFieldMode::Intrpl>;
+    template class FieldRegionBase<float, EFieldMode::Orig>;
+    template class FieldRegionBase<double, EFieldMode::Orig>;
+    template class FieldRegionBase<fvec, EFieldMode::Orig>;
+  }  // namespace detail
+
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  void FieldRegion<T>::Shift(const T& z)
+  {
+    if (fFieldMode == EFieldMode::Intrpl) {
+      foFldIntrpl->Shift(z);
+    }
   }
-  else {
-    foFldOrig->CheckConsistency();
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  std::string FieldRegion<T>::ToString(int indentLevel, int) const
+  {
+    constexpr char IndentChar = '\t';
+    std::stringstream msg;
+    std::string indent(indentLevel, IndentChar);
+    msg << indent << "FieldType: " << static_cast<int>(fFieldType) << '\n';
+    msg << indent << "FieldMode: " << static_cast<int>(fFieldMode) << '\n';
+    msg << indent
+        << (fFieldMode == EFieldMode::Intrpl ? foFldIntrpl->ToString(indentLevel) : foFldOrig->ToString(indentLevel));
+    return msg.str();
   }
-}
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-std::tuple<double, double, double> GlobalField::UndefField(double, double, double)
-{
-  assert(!GlobalField::IsUsingOriginalFieldForced()
-         && "cbm::algo::kf::GlobalField: The original globa magnetic field is required by "
-            "kf::defs::dbg::ForceOriginalField = true. Please provide it with the "
-            "kf::GlobalField::SetGlobalField() function.");
-  return std::make_tuple(defs::Undef<double>, defs::Undef<double>, defs::Undef<double>);
-}
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  void FieldRegion<T>::CheckConsistency() const
+  {
+    // Check SIMD data vectors for consistent initialization
 
+    if (fFieldMode == EFieldMode::Intrpl) {
+      foFldIntrpl->CheckConsistency();
+    }
+    else {
+      foFldOrig->CheckConsistency();
+    }
+  }
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  std::tuple<double, double, double> GlobalField::UndefField(double, double, double)
+  {
+    assert(!GlobalField::IsUsingOriginalFieldForced()
+           && "cbm::algo::kf::GlobalField: The original globa magnetic field is required by "
+              "kf::defs::dbg::ForceOriginalField = true. Please provide it with the "
+              "kf::GlobalField::SetGlobalField() function.");
+    return std::make_tuple(defs::Undef<double>, defs::Undef<double>, defs::Undef<double>);
+  }
 
-namespace cbm::algo::kf
-{
   template class FieldRegion<float>;
   template class FieldRegion<double>;
   template class FieldRegion<fvec>;
diff --git a/algo/kf/core/geo/KfFieldValue.cxx b/algo/kf/core/geo/KfFieldValue.cxx
index 3054b8579e7a54c2951d0656a81683454b633cad..eb7e637ab562738d2fd6492fe8bf4794e9f1332b 100644
--- a/algo/kf/core/geo/KfFieldValue.cxx
+++ b/algo/kf/core/geo/KfFieldValue.cxx
@@ -11,33 +11,34 @@
 
 #include <sstream>
 
-using namespace cbm::algo::kf;
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-template<typename T>
-void FieldValue<T>::CheckConsistency() const
+namespace cbm::algo::kf
 {
-  // Check SIMD data vectors for consistent initialization
-  utils::CheckSimdVectorEquality(fB[0], "FieldValue::x");
-  utils::CheckSimdVectorEquality(fB[1], "FieldValue::y");
-  utils::CheckSimdVectorEquality(fB[2], "FieldValue::z");
-
-  // TODO: Any other checks? (S.Zharko)
-}
 
-template<typename T>
-std::string FieldValue<T>::ToString(int indentLevel) const
-{
-  constexpr char IndentChar = '\t';
-  std::stringstream msg;
-  std::string indent(indentLevel, IndentChar);
-  msg << indent << "B = {" << fB[0] << ", " << fB[1] << ", " << fB[2] << "} [kG]";
-  return msg.str();
-}
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  void FieldValue<T>::CheckConsistency() const
+  {
+    // Check SIMD data vectors for consistent initialization
+    utils::CheckSimdVectorEquality(fB[0], "FieldValue::x");
+    utils::CheckSimdVectorEquality(fB[1], "FieldValue::y");
+    utils::CheckSimdVectorEquality(fB[2], "FieldValue::z");
+
+    // TODO: Any other checks? (S.Zharko)
+  }
+
+  // -------------------------------------------------------------------------------------------------------------------
+  //
+  template<typename T>
+  std::string FieldValue<T>::ToString(int indentLevel) const
+  {
+    constexpr char IndentChar = '\t';
+    std::stringstream msg;
+    std::string indent(indentLevel, IndentChar);
+    msg << indent << "B = {" << fB[0] << ", " << fB[1] << ", " << fB[2] << "} [kG]";
+    return msg.str();
+  }
 
-namespace cbm::algo::kf
-{
   template class FieldValue<float>;
   template class FieldValue<double>;
   template class FieldValue<fvec>;
diff --git a/reco/KF/ParticleFitter/CbmL1PFFitter.h b/reco/KF/ParticleFitter/CbmL1PFFitter.h
index 420d2a20933ce5e7f3b9f074305a6a1d0cbd2d94..050f2dfb8626d137de9e33e7e043e56d1a997488 100644
--- a/reco/KF/ParticleFitter/CbmL1PFFitter.h
+++ b/reco/KF/ParticleFitter/CbmL1PFFitter.h
@@ -28,9 +28,6 @@
 class CbmMvdHit;
 class CbmStsHit;
 class CbmStsTrack;
-
-using namespace cbm::algo;
-
 class CbmKFVertex;
 class TClonesArray;
 
@@ -39,9 +36,9 @@ class CbmL1PFFitter {
   // A container for parameters of kf::FieldRegion
   struct PFFieldRegion {
     PFFieldRegion() {}
-    PFFieldRegion(const kf::FieldRegion<kf::fvec>&, int i);
-    void setFromL1FieldRegion(const kf::FieldRegion<ca::fvec>&, int i);
-    void getL1FieldRegion(kf::FieldRegion<kf::fvec>&, int i);
+    PFFieldRegion(const cbm::algo::kf::FieldRegion<cbm::algo::kf::fvec>&, int i);
+    void setFromL1FieldRegion(const cbm::algo::kf::FieldRegion<cbm::algo::kf::fvec>&, int i);
+    void getL1FieldRegion(cbm::algo::kf::FieldRegion<cbm::algo::kf::fvec>&, int i);
 
     float fP[10]{0.};
   };
diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx
index a66957edd371d1ba14d94fcc58e34290e9a20be4..593b3527286f672420ea5bee4b3813acb93ba670 100644
--- a/reco/L1/CbmL1.cxx
+++ b/reco/L1/CbmL1.cxx
@@ -20,6 +20,7 @@
 
 #include "CbmL1.h"
 
+#include "CbmKfTarget.h"
 #include "CbmMCDataManager.h"
 #include "CbmMuchTrackingInterface.h"
 #include "CbmMvdTrackingInterface.h"
@@ -254,6 +255,10 @@ try {
     // ***************************
 
     {
+      const auto& pTarget = cbm::kf::Target::Instance();
+      fTargetX            = pTarget->GetX();
+      fTargetY            = pTarget->GetY();
+      fTargetZ            = pTarget->GetZ();
     }
     fInitManager.SetTargetPosition(fTargetX, fTargetY, fTargetZ);