From 4dfdfe093bdde8c13109561320c8d8fea52f3c78 Mon Sep 17 00:00:00 2001
From: "s.zharko@gsi.de" <s.zharko@gsi.de>
Date: Sat, 30 Mar 2024 23:58:45 +0100
Subject: [PATCH] kf: KfCore library

---
 algo/CMakeLists.txt                   |   1 +
 algo/ca/TrackingChain.cxx             |   2 +-
 algo/ca/core/CMakeLists.txt           |   1 +
 algo/ca/core/pars/CaConstants.h       |   8 ++
 algo/ca/core/pars/CaInitManager.cxx   |   8 ++
 algo/ca/core/pars/CaInitManager.h     |  16 +++
 algo/ca/core/tracking/CaFramework.cxx |  14 +++
 algo/ca/core/tracking/CaFramework.h   |  14 +++
 algo/kf/CMakeLists.txt                |   1 +
 algo/kf/core/CMakeLists.txt           |  59 +++++++++++
 algo/kf/core/KfDefs.h                 |  77 ++++++++++++++
 algo/kf/core/KfFramework.cxx          |  48 +++++++++
 algo/kf/core/KfFramework.h            |  65 ++++++++++++
 algo/kf/core/pars/KfMaterialMap.cxx   | 143 ++++++++++++++++++++++++++
 algo/kf/core/pars/KfMaterialMap.h     | 137 ++++++++++++++++++++++++
 algo/kf/core/pars/KfParameters.cxx    |  59 +++++++++++
 algo/kf/core/pars/KfParameters.h      |  83 +++++++++++++++
 algo/kf/core/pars/KfSetup.cxx         |  61 +++++++++++
 algo/kf/core/pars/KfSetup.h           |  92 +++++++++++++++++
 algo/kf/core/utils/KfVector.h         |  95 +++++++++++++++++
 reco/L1/CbmL1.cxx                     |   4 +-
 21 files changed, 985 insertions(+), 3 deletions(-)
 create mode 100644 algo/kf/CMakeLists.txt
 create mode 100644 algo/kf/core/CMakeLists.txt
 create mode 100644 algo/kf/core/KfDefs.h
 create mode 100644 algo/kf/core/KfFramework.cxx
 create mode 100644 algo/kf/core/KfFramework.h
 create mode 100644 algo/kf/core/pars/KfMaterialMap.cxx
 create mode 100644 algo/kf/core/pars/KfMaterialMap.h
 create mode 100644 algo/kf/core/pars/KfParameters.cxx
 create mode 100644 algo/kf/core/pars/KfParameters.h
 create mode 100644 algo/kf/core/pars/KfSetup.cxx
 create mode 100644 algo/kf/core/pars/KfSetup.h
 create mode 100644 algo/kf/core/utils/KfVector.h

diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt
index b04d23c36f..85b74016e4 100644
--- a/algo/CMakeLists.txt
+++ b/algo/CMakeLists.txt
@@ -53,6 +53,7 @@ endif()
 
 add_subdirectory(log)
 add_subdirectory(data)
+add_subdirectory(kf)
 add_subdirectory(ca)
 
 # exclude unittests from being build inside the container
diff --git a/algo/ca/TrackingChain.cxx b/algo/ca/TrackingChain.cxx
index 1599bf88fe..93347a0b08 100644
--- a/algo/ca/TrackingChain.cxx
+++ b/algo/ca/TrackingChain.cxx
@@ -63,8 +63,8 @@ void TrackingChain::Init()
   // ------ Initialize CA framework
   fCaMonitor.Reset();
   fCaFramework.SetNofThreads(fConfig.fNofThreads);
-  fCaFramework.Init(ca::Framework::TrackingMode::kMcbm);
   fCaFramework.ReceiveParameters(std::move(parameters));
+  fCaFramework.Init(ca::Framework::TrackingMode::kMcbm);
 
   // ------ Initialize QA modules
   if (fInputQa.IsSenderDefined()) {
diff --git a/algo/ca/core/CMakeLists.txt b/algo/ca/core/CMakeLists.txt
index 90a19d9f52..b255a4bfdb 100644
--- a/algo/ca/core/CMakeLists.txt
+++ b/algo/ca/core/CMakeLists.txt
@@ -62,6 +62,7 @@ target_include_directories(CaCore
 
 target_compile_definitions(CaCore PUBLIC NO_ROOT)
 target_link_libraries(CaCore
+                      KfCore
                       Vc::Vc                      
                       Boost::serialization
                       OnlineDataLog          # needed for the logger
diff --git a/algo/ca/core/pars/CaConstants.h b/algo/ca/core/pars/CaConstants.h
index 4fd8d9bf84..c858914bc1 100644
--- a/algo/ca/core/pars/CaConstants.h
+++ b/algo/ca/core/pars/CaConstants.h
@@ -10,9 +10,17 @@
 #pragma once  // include this header only once per compilation unit
 
 #include "CaSimd.h"
+#include "KfFramework.h"
 
 #include <limits>
 
+namespace cbm::algo::ca
+{
+  using KfFramework_t  = cbm::algo::kf::Framework<float>;
+  using KfParameters_t = cbm::algo::kf::Parameters<float>;
+  using KfSetup_t      = cbm::algo::kf::Setup<float>;
+}  // namespace cbm::algo::ca
+
 /// Namespace contains compile-time constants definition for the CA tracking algorithm
 ///
 namespace cbm::algo::ca::constants
diff --git a/algo/ca/core/pars/CaInitManager.cxx b/algo/ca/core/pars/CaInitManager.cxx
index b2318db200..3ab0d39044 100644
--- a/algo/ca/core/pars/CaInitManager.cxx
+++ b/algo/ca/core/pars/CaInitManager.cxx
@@ -504,6 +504,14 @@ void InitManager::SetTargetPosition(double x, double y, double z)
 //
 Parameters<fvec>&& InitManager::TakeParameters() { return std::move(fParameters); }
 
+// ----------------------------------------------------------------------------------------------------------------------
+//
+KfParameters_t&& InitManager::TakeKfParameters() { return std::move(fKfParameters); }
+
+// ----------------------------------------------------------------------------------------------------------------------
+//
+KfSetup_t&& InitManager::TakeKfSetup() { return std::move(fKfSetup); }
+
 // ----------------------------------------------------------------------------------------------------------------------
 //
 void InitManager::WriteParametersObject(const std::string& fileName) const
diff --git a/algo/ca/core/pars/CaInitManager.h b/algo/ca/core/pars/CaInitManager.h
index 1667d07b61..7cb30eea68 100644
--- a/algo/ca/core/pars/CaInitManager.h
+++ b/algo/ca/core/pars/CaInitManager.h
@@ -17,6 +17,8 @@
 #include "CaSimd.h"
 #include "CaStationInitializer.h"
 #include "CaUtils.h"
+#include "KfParameters.h"
+#include "KfSetup.h"
 
 #include <array>
 #include <bitset>
@@ -247,10 +249,20 @@ namespace cbm::algo::ca
       fParameters.fMisalignmentT[static_cast<int>(detectorId)] = t;
     }
 
+    /// \brief Sets default fitter mass
+    /// \param mass Particle mass [GeV/c2]
+    void SetDefaultMass(double mass) { fKfParameters.SetDefaultMass(mass); }
+
     /// \brief  Takes parameters object from the init-manager instance
     /// \return A parameter object
     Parameters<fvec>&& TakeParameters();
 
+    /// \brief Takes KF parameters object
+    KfParameters_t&& TakeKfParameters();
+
+    /// \brief Takes KF setup object
+    KfSetup_t&& TakeKfSetup();
+
     /// \brief Writes parameters object from boost-serialized binary file
     /// \param  fileName  Name of input file
     void WriteParametersObject(const std::string& fileName) const;
@@ -310,6 +322,10 @@ namespace cbm::algo::ca
     int fCAIterationsNumberCrosscheck{-1};  ///< Number of iterations to be passed (must be used for cross-checks)
 
     Parameters<fvec> fParameters{};  ///< CA parameters object
+    KfParameters_t fKfParameters{};  ///< Kf-parameters object
+    KfSetup_t fKfSetup{};            ///< Kf setup object
+    // TODO: With a separate KF-framework instance we need to figure it out, how to store and read the corresponding
+    //       parameters (essential for the online reconstruction!!!)
 
     std::string fsConfigInputMain = "";  ///< name for the input configuration file
     std::string fsConfigInputUser = "";  ///< name for the input configuration file
diff --git a/algo/ca/core/tracking/CaFramework.cxx b/algo/ca/core/tracking/CaFramework.cxx
index 82326d6755..43a7085dbe 100644
--- a/algo/ca/core/tracking/CaFramework.cxx
+++ b/algo/ca/core/tracking/CaFramework.cxx
@@ -22,6 +22,8 @@ Framework::Framework()
 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::KfFramework_t;
+using cbm::algo::ca::KfParameters_t;
 //using cbm::ca::tools::Debugger;
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -37,6 +39,7 @@ void Framework::Init(const TrackingMode mode)
     fvTrackFinderWindow.emplace_back(*this, fvWData[iThread], fvMonitorDataThread[iThread]);
   }
   fTrackFinder.Init();
+  fKf.Init();
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -76,6 +79,17 @@ void Framework::ReceiveParameters(Parameters<fvec>&& parameters)
   ca::FieldRegion<fvec>::ForceUseOfOriginalField(fParameters.DevIsUseOfOriginalField());
 }
 
+// ---------------------------------------------------------------------------------------------------------------------
+//
+
+void Framework::ReceiveKfSettings(KfParameters_t&& pars, KfSetup_t&& setup)
+{
+  fKf.Pars()  = std::move(pars);
+  fKf.Setup() = std::move(setup);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
 int Framework::GetMcTrackIdForCaHit(int /*iHit*/) const
 {
   return -1;
diff --git a/algo/ca/core/tracking/CaFramework.h b/algo/ca/core/tracking/CaFramework.h
index 7239170b0a..409b165cb9 100644
--- a/algo/ca/core/tracking/CaFramework.h
+++ b/algo/ca/core/tracking/CaFramework.h
@@ -27,6 +27,7 @@
 #include "CaTriplet.h"
 #include "CaVector.h"
 #include "CaWindowData.h"
+#include "KfFramework.h"
 
 #include <array>
 #include <iomanip>
@@ -140,6 +141,11 @@ namespace cbm::algo::ca
     /// Receives tracking parameters
     void ReceiveParameters(Parameters<fvec>&& parameters);
 
+    /// \brief Receives KF-framework parameters and setup
+    /// \param pars  KF parameters object
+    /// \param setup KF setup object
+    void ReceiveKfSettings(KfParameters_t&& pars, KfSetup_t&& setup);
+
     /// Gets pointer to input data object for external access
     const InputData& GetInputData() const { return fInputData; }
 
@@ -207,7 +213,15 @@ namespace cbm::algo::ca
     /// \brief Gets number of threads
     int GetNofThreads() const { return fNofThreads; }
 
+    /// \brief Accesses KF framework instance
+    KfFramework_t& Kf() { return fKf; }
+
+    /// \brief Accesses KF framework instance (immutable)
+    const KfFramework_t& Kf() const { return fKf; }
+
    private:
+    KfFramework_t fKf;  ///< KF framework instance
+
     int fNstationsBeforePipe{0};                    ///< number of stations before pipe (MVD stations in CBM)
     int fNfieldStations{0};                         ///< number of stations in the field region
     float fDefaultMass{constants::phys::MuonMass};  ///< mass of the propagated particle [GeV/c2]
diff --git a/algo/kf/CMakeLists.txt b/algo/kf/CMakeLists.txt
new file mode 100644
index 0000000000..ad6d4787c2
--- /dev/null
+++ b/algo/kf/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(core)
diff --git a/algo/kf/core/CMakeLists.txt b/algo/kf/core/CMakeLists.txt
new file mode 100644
index 0000000000..f89e9015c6
--- /dev/null
+++ b/algo/kf/core/CMakeLists.txt
@@ -0,0 +1,59 @@
+set(INCLUDE_DIRECTORIES
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${CMAKE_CURRENT_SOURCE_DIR}/data
+  ${CMAKE_CURRENT_SOURCE_DIR}/pars 
+  ${CMAKE_CURRENT_SOURCE_DIR}/utils
+)
+
+set(SRCS 
+  ${CMAKE_CURRENT_SOURCE_DIR}/KfFramework.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/pars/KfMaterialMap.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/pars/KfParameters.cxx
+  ${CMAKE_CURRENT_SOURCE_DIR}/pars/KfSetup.cxx
+)
+
+SET_SOURCE_FILES_PROPERTIES(${SRCS} PROPERTIES COMPILE_FLAGS "-O3")
+
+If(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+  ADD_DEFINITIONS(-Wall -Wextra -Wsign-promo -Wctor-dtor-privacy -Wreorder -Wno-deprecated -Wno-parentheses) # -Weffc++ -Wnon-virtual-dtor -Woverloaded-virtual -Wold-style-cast : wait for other parts of cbmroot\root.
+Else()
+  ADD_DEFINITIONS(-Wall -Wextra -Wsign-promo -Wno-pmf-conversions -Wctor-dtor-privacy -Wreorder -Wno-deprecated -Wstrict-null-sentinel -Wno-non-template-friend -Wno-parentheses -Wmissing-field-initializers) # -Weffc++ -Wnon-virtual-dtor -Woverloaded-virtual -Wold-style-cast : wait for other parts of cbmroot\root.
+EndIf()
+
+add_library(KfCore SHARED ${SRCS})
+
+target_include_directories(KfCore
+  PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/data
+         ${CMAKE_CURRENT_SOURCE_DIR}/pars
+         ${CMAKE_CURRENT_SOURCE_DIR}/utils
+         ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+target_compile_definitions(KfCore PUBLIC NO_ROOT)
+
+target_link_libraries(KfCore
+                      Vc::Vc                      
+                      Boost::serialization
+                      OnlineDataLog          # needed for the logger
+                      external::fles_logging # needed for the logger
+                      external::fles_ipc     # needed for the logger
+                      external::yaml-cpp
+                     )
+
+install(TARGETS KfCore DESTINATION lib)
+install(DIRECTORY kf TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
+install(DIRECTORY kf/utils TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
+install(DIRECTORY kf/data TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
+install(DIRECTORY kf/pars TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
+
+install(
+  FILES
+    KfFramework.h
+    KfDefs.h
+    pars/KfMaterialMap.h 
+    pars/KfParameters.h 
+    pars/KfSetup.h
+    utils/KfVector.h
+  DESTINATION
+    include/
+)
diff --git a/algo/kf/core/KfDefs.h b/algo/kf/core/KfDefs.h
new file mode 100644
index 0000000000..3fafcc560e
--- /dev/null
+++ b/algo/kf/core/KfDefs.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   KfDefs.h
+/// @brief  Common constant definitions for the Kalman Filter library
+/// @since  28.03.2024
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#pragma once
+
+#include <limits>
+
+namespace cbm::algo::kf::defs
+{
+  // ----- Control -----------------------------------------------------------------------------------------------------
+  constexpr int DebugLvl     = 0;     ///< Level of debug output
+  constexpr bool GetterCheck = true;  ///< Bound check in getters
+
+
+  // ----- Math --------------------------------------------------------------------------------------------------------
+  template<class T = double>
+  constexpr T Pi = T(3.14159265358979323846L);  ///< Value of PI, used in ROOT TMath
+
+
+  // ----- Physics -----------------------------------------------------------------------------------------------------
+  template<class T = double>
+  constexpr T MuonMass = T(0.105658375523L);  ///< Muon mass [GeV/c2]
+
+  template<class T = double>
+  constexpr T PionMass = T(0.1395703918L);  ///< Pion mass [GeV/c2]
+
+  template<class T = double>
+  constexpr T KaonMass = T(0.493677L);  ///< Kaon mass [GeV/c2] (PDG 22.08.2023)
+
+  template<class T = double>
+  constexpr T ElectronMass = T(0.0005109989500015L);  ///< Electron mass [GeV/c2]
+
+  template<class T = double>
+  constexpr T ProtonMass = T(0.93827208816L);  ///< Proton mass [GeV/c2] (PDG 11.08.2022)
+
+  template<class T = double>
+  constexpr T SpeedOfLight = T(29.9792458L);  ///< Speed of light [cm/ns]
+
+  template<class T = double>
+  constexpr T SpeedOfLightInv = T(1.L) / SpeedOfLight<T>;  ///< Inverse speed of light [ns/cm]
+
+  template<class T = double>
+  constexpr T MinFeild = T(1.e-4L);  ///< Minimal (negligible) magnetic field value [kG]
+
+
+  // ----- Misc --------------------------------------------------------------------------------------------------------
+  constexpr int MemAlign = 16;  ///< Default alignment of memory (bytes)
+
+
+  // ----- Undefined values --------------------------------------------------------------------------------------------
+  /// \brief Undefined values
+  template<typename T1, typename T2 = T1>
+  constexpr T2 Undef;
+
+  template<>
+  inline constexpr int Undef<int> = std::numeric_limits<int>::min();
+
+  template<>
+  inline constexpr unsigned Undef<unsigned> = std::numeric_limits<unsigned>::max();
+
+  template<>
+  inline constexpr float Undef<float> = std::numeric_limits<float>::signaling_NaN();
+
+  template<>
+  inline constexpr double Undef<double> = std::numeric_limits<double>::signaling_NaN();
+
+  // TODO: provide SIMD
+  //template<>
+  //inline constexpr fscal Undef<fvec> = std::numeric_limits<fscal>::signaling_NaN();
+
+}  // namespace cbm::algo::kf::defs
diff --git a/algo/kf/core/KfFramework.cxx b/algo/kf/core/KfFramework.cxx
new file mode 100644
index 0000000000..a11fe973de
--- /dev/null
+++ b/algo/kf/core/KfFramework.cxx
@@ -0,0 +1,48 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   KfFramework.cxx
+/// @brief  The Kalman-filter framework main class (header)
+/// @since  28.03.2024
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#include "KfFramework.h"
+
+using cbm::algo::kf::Framework;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<typename DataT>
+bool Framework<DataT>::Init()
+try {
+  std::stringstream errMsg;
+  try {
+    fPars.Init();
+  }
+  catch (const std::runtime_error& err) {
+    errMsg << "\tParameters initialization errors: " << err.what() << '\n';
+  }
+
+  try {
+    fSetup.Init();
+  }
+  catch (const std::runtime_error& err) {
+    errMsg << "\tSetup initialization errors: " << err.what() << '\n';
+  }
+
+  if (!errMsg.str().empty()) {
+    throw std::runtime_error(errMsg.str());
+  }
+
+  L_(info) << '\n' << fPars.ToString(3) << '\n' << fSetup.ToString(3);
+  return true;
+}
+catch (const std::exception& err) {
+  L_(error) << "kf::Framework: initialization failed. Reason: " << err.what();
+  return false;
+}
+
+template class cbm::algo::kf::Framework<float>;
+template class cbm::algo::kf::Framework<double>;
+// template class cbm::algo::kf::Framework<fvec>;
diff --git a/algo/kf/core/KfFramework.h b/algo/kf/core/KfFramework.h
new file mode 100644
index 0000000000..902126523d
--- /dev/null
+++ b/algo/kf/core/KfFramework.h
@@ -0,0 +1,65 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   KfFramework.h
+/// @brief  The Kalman-filter framework main class (header)
+/// @since  28.03.2024
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#pragma once
+
+#include "KfDefs.h"
+#include "KfParameters.h"
+#include "KfSetup.h"
+
+namespace cbm::algo::kf
+{
+  /// \class Framework
+  /// \brief Main class of the KfCore library
+  /// \tparam DataT  Underlying data-type
+  template<typename DataT>
+  class Framework {
+   public:
+    /// \brief Default constructor
+    Framework() = default;
+
+    /// \brief Copy constructor
+    Framework(const Framework&) = delete;
+
+    /// \brief Move constructor
+    Framework(Framework&&) = delete;
+
+    /// \brief Destructor
+    ~Framework() = default;
+
+    /// \brief Copy assignment operator
+    Framework& operator=(const Framework&) = delete;
+
+    /// \brief Move assignment operator
+    Framework& operator=(Framework&&) = delete;
+
+    /// \brief Initialization method
+    bool Init();
+
+    /// \brief Initialization satus
+    bool IsInitialized() const { return fbInitialized; }
+
+    /// \brief Parameters access
+    Parameters<DataT>& Pars() { return fPars; }
+
+    /// \brief Parameters access
+    const kf::Parameters<DataT>& Pars() const { return fPars; }
+
+    /// \brief Setup access (mutable)
+    kf::Setup<DataT>& Setup() { return fSetup; }
+
+    /// \brief Setup access
+    const kf::Setup<DataT>& Setup() const { return fSetup; }
+
+   private:
+    kf::Parameters<DataT> fPars;  ///< KF parameters
+    kf::Setup<DataT> fSetup;      ///< KF setup
+    bool fbInitialized = false;   ///< Initialization status
+  };
+}  // namespace cbm::algo::kf
diff --git a/algo/kf/core/pars/KfMaterialMap.cxx b/algo/kf/core/pars/KfMaterialMap.cxx
new file mode 100644
index 0000000000..809e22753e
--- /dev/null
+++ b/algo/kf/core/pars/KfMaterialMap.cxx
@@ -0,0 +1,143 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergey Gorbunov, Sergei Zharko [committer] */
+
+#include "KfMaterialMap.h"
+
+#include "AlgoFairloggerCompat.h"
+
+#include <iomanip>
+#include <sstream>
+#include <vector>
+
+using cbm::algo::kf::MaterialMap;
+
+//------------------------------------------------------------------------------------------------------------------------------------
+//
+MaterialMap::MaterialMap(MaterialMap&& other) noexcept { this->Swap(other); }
+
+//------------------------------------------------------------------------------------------------------------------------------------
+//
+MaterialMap& MaterialMap::operator=(MaterialMap&& other) noexcept
+{
+  if (this != &other) {
+    MaterialMap tmp(std::move(other));
+    this->Swap(tmp);
+  }
+  return *this;
+}
+
+//------------------------------------------------------------------------------------------------------------------------------------
+int MaterialMap::GetBin(float x, float y) const
+{
+  int i = static_cast<int>((x + fXYmax) * fFactor);
+  int j = static_cast<int>((y + fXYmax) * fFactor);
+  if (i < 0 || j < 0 || i >= fNbins || j >= fNbins) {
+    return -1;
+  }
+  return i + j * fNbins;
+}
+
+//------------------------------------------------------------------------------------------------------------------------------------
+//
+float MaterialMap::GetRadThickScal(float x, float y) const
+{
+  x     = (x < fXYmax && x >= -fXYmax) ? x : 0;
+  y     = (y < fXYmax && y >= -fXYmax) ? y : 0;
+  int i = static_cast<int>((x + fXYmax) * fFactor);
+  int j = static_cast<int>((y + fXYmax) * fFactor);
+  i     = (i < fNbins && i >= 0) ? i : fNbins / 2;
+  j     = (j < fNbins && j >= 0) ? j : fNbins / 2;
+  return fTable[i + j * fNbins];
+}
+
+//------------------------------------------------------------------------------------------------------------------------------------
+// TODO: provide SIMD
+//fvec MaterialMap::GetRadThickVec(fvec x, fvec y) const
+//{
+//  fvec r;
+//  for (size_t i = 0; i < fvec::size(); i++)
+//    r[i] = GetRadThickScal(x[i], y[i]);
+//  return r;
+//}
+
+//------------------------------------------------------------------------------------------------------------------------------------
+//
+void MaterialMap::CheckConsistency() const
+{
+  /* (i) Check, if the object was initialized */
+  // TODO: provide undef checking utility
+  //if (IsNaN()) {
+  //  throw std::logic_error("MaterialMap: class was not initialized");
+  //}
+
+  /* (ii) Check if the thickness values correct (non-negative) */
+  bool isThicknessOk = true;
+  for (int i = 0; i < int(fTable.size()); ++i) {
+    if (fTable[i] < 0) {
+      isThicknessOk = false;
+      LOG(error) << "MaterialMap: found illegal negative station thickness value " << fTable[i]
+                 << " at iBinX = " << (i % fNbins) << ", iBin = " << (i / fNbins);
+    }
+  }
+  if (!isThicknessOk) {
+    throw std::logic_error("MaterialMap: incorrect station thickness values found in the thickness map");
+  }
+}
+
+//------------------------------------------------------------------------------------------------------------------------------------
+//
+void MaterialMap::Initialize(int nBins, float xyMax, float zRef, float zMin, float zMax)
+{
+  fNbins = nBins;
+  fXYmax = xyMax;
+  fZref  = zRef;
+  fZmin  = zMin;
+  fZmax  = zMax;
+
+  if (fNbins < 1) {
+    std::stringstream aStream;
+    aStream << "MaterialMap: object cannot be initialized with non-positive nBins = " << fNbins;
+    throw std::logic_error(aStream.str());
+  }
+
+  if (fXYmax < 0.) {
+    std::stringstream aStream;
+    aStream << "MaterialMap: object cannot be initialized with non-positive XYmax = " << fXYmax << " [cm]";
+    throw std::logic_error(aStream.str());
+  }
+
+  if (!((fZmin <= fZref) && (fZref <= zMax))) {
+    std::stringstream aStream;
+    aStream << "MaterialMap: object cannot be initialized with inconsistent Z: min " << fZmin << " ref " << fZref
+            << " max " << fZmax << " [cm]";
+    throw std::logic_error(aStream.str());
+  }
+
+  fFactor = 0.5 * fNbins / fXYmax;
+  fTable.resize(fNbins * fNbins);
+}
+
+//------------------------------------------------------------------------------------------------------------------------------------
+//
+void MaterialMap::Swap(MaterialMap& other) noexcept
+{
+  std::swap(fNbins, other.fNbins);
+  std::swap(fXYmax, other.fXYmax);
+  std::swap(fFactor, other.fFactor);
+  std::swap(fZref, other.fZref);
+  std::swap(fZmin, other.fZmin);
+  std::swap(fZmax, other.fZmax);
+  std::swap(fTable, other.fTable);  // Probably can cause segmentation violation (did not understand)
+}
+
+//------------------------------------------------------------------------------------------------------------------------------------
+//
+std::string MaterialMap::ToString() const
+{
+  std::stringstream msg;
+  using std::setw;
+  msg << "[mat.map] nBins " << setw(6) << fNbins << ", XYmax " << setw(12) << fXYmax << " , z (ref, min, max) "
+      << setw(12) << fZref << ' ' << setw(12) << fZmin << ' ' << setw(12) << fZmax;
+  return msg.str();
+}
diff --git a/algo/kf/core/pars/KfMaterialMap.h b/algo/kf/core/pars/KfMaterialMap.h
new file mode 100644
index 0000000000..b97fde1f90
--- /dev/null
+++ b/algo/kf/core/pars/KfMaterialMap.h
@@ -0,0 +1,137 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Igor Kulakov, Sergey Gorbunov, Andrey Lebedev, Sergei Zharko [committer] */
+
+#pragma once  // include this header only once per compilation unit
+
+// NOTE: No dependency from CaCore is allowed
+//#include "CaSimd.h"
+//#include "CaUtils.h"
+#include "AlgoFairloggerCompat.h"
+#include "KfDefs.h"
+
+#include <boost/serialization/vector.hpp>
+
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace cbm::algo::kf
+{
+  /// \class MaterialMap
+  /// \brief A map of station thickness in units of radiation length (X0) to the specific point in XY plane
+  class MaterialMap {
+   public:
+    /// \brief Default constructor
+    MaterialMap() = default;
+
+    /// \brief Copy constructor
+    MaterialMap(const MaterialMap& other) = default;
+
+    /// \brief Copy assignment operator
+    MaterialMap& operator=(const MaterialMap& other) = default;
+
+    /// \brief Move constructor
+    MaterialMap(MaterialMap&& other) noexcept;
+
+    /// \brief Move assignment operator
+    MaterialMap& operator=(MaterialMap&& other) noexcept;
+
+    /// \brief Destructor
+    ~MaterialMap() noexcept = default;
+
+    /// \brief Gets number of bins (rows or columns) of the material table
+    int GetNbins() const { return fNbins; }
+
+    /// \brief Gets radius in cm of the material table
+    float GetXYmax() const { return fXYmax; }
+
+    /// \brief Gets reference Z of the material in cm
+    float GetZref() const { return fZref; }
+
+    /// \brief Gets minimal Z of the collected material in cm
+    float GetZmin() const { return fZmin; }
+
+    /// \brief Gets maximal Z of the collected material in cm
+    float GetZmax() const { return fZmax; }
+
+    /// \brief Gets value of X/X0 in a given cell of the material table by the indeces of the row and column
+    /// \param iBinX  Index of table column
+    /// \param iBinY  Index of table row
+    float GetRadThickBin(int iBinX, int iBinY) const { return fTable[iBinX + fNbins * iBinY]; }
+
+    /// \brief Gets value of X/X0 in a given cell of the material table by the index of the bin
+    /// \param iBin  Index of the bin in 2d table
+    float GetRadThickBin(int iBin) const { return fTable[iBin]; }
+
+    /// \brief Gets material thickness in units of X0 in (x,y) point of the station
+    /// \param x  X coordinate of the point [cm]
+    /// \param y  Y coordinate of the point [cm]
+    float GetRadThickScal(float x, float y) const;
+
+    /// \brief Gets material thickness in units of X0 in (x,y) point of the station
+    /// cbm::algo::ca::fvec type can be float, that is why "Vec" and "Scal" specifications
+    /// \param x  X coordinate of the point [cm] (SIMDized vector)
+    /// \param y  Y coordinate of the point [cm] (SIMDized veotor)
+    // TODO: provide SIMD
+    //fvec GetRadThickVec(fvec x, fvec y) const;
+
+    /// \brief Checks, if the fields are NaN
+    //bool IsNaN() const
+    //{
+    //  return utils::IsUndefined(fNbins) || utils::IsUndefined(fXYmax) || utils::IsUndefined(fFactor)
+    //         || utils::IsUndefined(fZref) || utils::IsUndefined(fZmin) || utils::IsUndefined(fZmax);
+    //}
+
+    /// \brief Verifies class invariant consistency
+    void CheckConsistency() const;
+
+    /// \brief Sets value of material thickness in units of X0 for a given cell of the material table
+    /// \param iBinX      Index of table column
+    /// \param iBinY      Index of table row
+    /// \param thickness  Thickness of the material in units of X0
+    /// \note  Indices of rows and columns in the table runs from 0 to nBins-1 inclusively, where nBins is the number
+    ///        both of rows and columns. One should be careful while reading and storing the table from ROOT-file,
+    ///        because iBinX = 0 and iBinY = 0 in the TH1::SetBinContent method of usually defines the underflow bin.
+    void SetRadThickBin(int iBinX, int iBinY, float thickness) { fTable[iBinX + fNbins * iBinY] = thickness; }
+
+    /// \brief Sets properties of the material table -- number of rows or columnts and the size of station in XY plane
+    /// \param nBins  Number of rows or columns
+    /// \param xyMax  Size of station in x and y dimensions [cm]
+    void Initialize(int nBins, float xyMax, float zRef, float zMin, float zMax);
+
+    /// \brief Swap method
+    void Swap(MaterialMap& other) noexcept;
+
+    /// \brief Get bin index for (x,y). Returns -1 when outside of the map
+    int GetBin(float x, float y) const;
+
+    /// \brief String representation of the object
+    std::string ToString() const;
+
+   private:
+    int fNbins    = defs::Undef<int>;    ///< Number of rows (== N columns) in the material budget table
+    float fXYmax  = defs::Undef<float>;  ///< Size of the station in x and y dimensions [cm]
+    float fFactor = defs::Undef<float>;  ///< Util. var. for the conversion of point coordinates to row/column id
+    float fZref   = defs::Undef<float>;  ///< Reference Z of the collected material [cm]
+    float fZmin   = defs::Undef<float>;  ///< Minimal Z of the collected material [cm]
+    float fZmax   = defs::Undef<float>;  ///< Minimal Z of the collected material [cm]
+    std::vector<float> fTable{};         ///< Material budget table
+
+    /// \brief Serialization function
+    friend class boost::serialization::access;
+    template<class Archive>
+    void serialize(Archive& ar, const unsigned int)
+    {
+      ar& fNbins;
+      ar& fXYmax;
+      ar& fFactor;
+      ar& fZref;
+      ar& fZmin;
+      ar& fZmax;
+      ar& fTable;
+    }
+  };
+
+}  // namespace cbm::algo::kf
diff --git a/algo/kf/core/pars/KfParameters.cxx b/algo/kf/core/pars/KfParameters.cxx
new file mode 100644
index 0000000000..999aec0b9a
--- /dev/null
+++ b/algo/kf/core/pars/KfParameters.cxx
@@ -0,0 +1,59 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   KfParameters.cxx
+/// @brief  Parameters representation for the Kalman-filter framework (source)
+/// @since  28.03.2024
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#include "KfParameters.h"
+
+#include <sstream>
+
+using cbm::algo::kf::Parameters;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<typename DataT>
+void Parameters<DataT>::CheckConsistency() const
+{
+  std::stringstream errMsg;
+
+  // checks go here... the errMsg is to be filled on each checking stage
+
+  if (!errMsg.str().empty()) {
+    throw std::runtime_error(errMsg.str());
+  }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<typename DataT>
+void Parameters<DataT>::Init()
+{
+  fbInitialized = true;
+  this->CheckConsistency();
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<typename DataT>
+std::string Parameters<DataT>::ToString(int verbosity, int indentLevel) const
+{
+  std::stringstream msg;
+
+  if (verbosity > 0) {
+    constexpr char indentCh = '\t';
+    std::string indent(indentLevel, indentCh);
+    msg << indent << " ----- KF Parameters list ----- \n";
+    msg << indent << "RUNTIME CONSTANTS:\n";
+    msg << indent << indentCh << "Default particle mass: " << fDefaultMass << " [GeV/c2] \n";
+  }
+
+  return msg.str();
+}
+
+template class cbm::algo::kf::Parameters<float>;
+template class cbm::algo::kf::Parameters<double>;
+// template class cbm::algo::kf::Parameters<fvec>;
diff --git a/algo/kf/core/pars/KfParameters.h b/algo/kf/core/pars/KfParameters.h
new file mode 100644
index 0000000000..922f4454a4
--- /dev/null
+++ b/algo/kf/core/pars/KfParameters.h
@@ -0,0 +1,83 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   KfParameters.cxx
+/// @brief  Parameter set for the Kalman-filter framework (header)
+/// @since  28.03.2024
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#pragma once
+
+#include "KfDefs.h"
+
+#include <boost/serialization/access.hpp>
+
+#include <string>
+
+namespace cbm::algo::kf
+{
+  /// \class  Parameters
+  /// \brief  Parameter set of the Kalman-filter framework
+  /// \tparam DataT  Underlying data type
+  template<typename DataT>
+  class Parameters {
+   public:
+    /// \brief Default constructor
+    Parameters() = default;
+
+    /// \brief Copy constructor
+    Parameters(const Parameters&) = default;
+
+    /// \brief Move constructor
+    Parameters(Parameters&&) = default;
+
+    /// \brief Destructor
+    ~Parameters() = default;
+
+    /// \brief Copy assignment operator
+    Parameters& operator=(const Parameters&) = default;
+
+    /// \brief Move assignment operator
+    Parameters& operator=(Parameters&&) = default;
+
+    /// \brief Checks parameters instance
+    /// \note  Throws std::runtime_error, if the class inconsistent
+    void CheckConsistency() const;
+
+    /// \brief Gets default mass
+    const DataT GetDefaultMass() const { return fDefaultMass; }
+
+    /// \brief Initialization method
+    void Init();
+
+    /// \brief Returns initialization status
+    bool IsInitialized() const { return fbInitialized; }
+
+    /// \brief Resets the contents of the parameters
+    void Reset() { *this = std::move(Parameters<DataT>{}); }
+
+    /// \brief Sets default mass
+    void SetDefaultMass(DataT mass) { fDefaultMass = mass; }
+
+    /// \brief String representation of the contents
+    /// \param verbosity    A verbose level for output
+    /// \param indentLevel  Indent level of the string output
+    std::string ToString(int verbosity = 0, int indentLevel = 0) const;
+
+   private:
+    /// \brief Serialization method
+    friend class boost::serialization::access;
+    template<class Archive>
+    void serialize(Archive& ar, const unsigned int /*version*/)
+    {
+      ar& fDefaultMass;
+      ar& fbInitialized;
+    }
+
+    DataT fDefaultMass = defs::PionMass<DataT>;  ///< Default particle mass [GeV/c2]
+
+    bool fbInitialized = false;  ///< Is instance initialized
+  };
+
+}  // namespace cbm::algo::kf
diff --git a/algo/kf/core/pars/KfSetup.cxx b/algo/kf/core/pars/KfSetup.cxx
new file mode 100644
index 0000000000..bce84eece3
--- /dev/null
+++ b/algo/kf/core/pars/KfSetup.cxx
@@ -0,0 +1,61 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   KfSetup.cxx
+/// @brief  Setup representation for the Kalman-filter framework (source)
+/// @since  28.03.2024
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#include "KfSetup.h"
+
+#include <sstream>
+
+using cbm::algo::kf::Setup;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<typename DataT>
+void Setup<DataT>::CheckConsistency() const
+{
+  std::stringstream errMsg;
+
+  // checks go here... the errMsg is to be filled on each checking stage
+
+  if (!errMsg.str().empty()) {
+    throw std::runtime_error(errMsg.str());
+  }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<typename DataT>
+void Setup<DataT>::Init()
+{
+  fbInitialized = true;
+  CheckConsistency();
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<typename DataT>
+std::string Setup<DataT>::ToString(int verbosity, int indentLevel) const
+{
+  std::stringstream msg;
+
+  if (verbosity > 0) {
+    constexpr char indentCh = '\t';
+    std::string indent(indentLevel, indentCh);
+    msg << indent << " ----- KF setup -----\n";
+    msg << indent << "MATERIAL LAYERS:\n";
+    for (const auto& layer : fvMatLayers) {
+      msg << indent << indentCh << layer.ToString() << '\n';
+    }
+  }
+
+  return msg.str();
+}
+
+template class cbm::algo::kf::Setup<float>;
+template class cbm::algo::kf::Setup<double>;
+//template class cbm::algo::kf::Setup<fvec>;
diff --git a/algo/kf/core/pars/KfSetup.h b/algo/kf/core/pars/KfSetup.h
new file mode 100644
index 0000000000..dcd211771e
--- /dev/null
+++ b/algo/kf/core/pars/KfSetup.h
@@ -0,0 +1,92 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   KfSetup.h
+/// @brief  Setup representation for the Kalman-filter framework (header)
+/// @since  28.03.2024
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#pragma once  // include this header only once per compilation unit
+
+#include "KfDefs.h"
+#include "KfMaterialMap.h"
+#include "KfVector.h"
+
+#include <boost/serialization/access.hpp>
+
+#include <string>
+#include <vector>
+
+namespace cbm::algo::kf
+{
+  using MaterialContainer_t = Vector<MaterialMap>;
+
+  /// \brief  KF-framework representation of the detector setup
+  /// \tparam DataT Underlying data type
+  template<typename DataT>
+  class alignas(defs::MemAlign) Setup {
+   public:
+    /// \brief Default constructor
+    Setup() = default;
+
+    /// \brief Destructor
+    ~Setup() = default;
+
+    /// \brief Copy constructor
+    Setup(const Setup&) = default;
+
+    /// \brief Move constructor
+    Setup(Setup&&) = default;
+
+    /// \brief Copy assignment operator
+    Setup& operator=(const Setup&) = default;
+
+    /// \brief Move assignment operator
+    Setup& operator=(Setup&&) = default;
+
+    /// \brief Adds material layer
+    void AddMaterialLayer(const MaterialMap& layer) { fvMatLayers.push_back(layer); }
+
+    /// \brief Adds material layer, moving it from the source
+    void AddMaterialLayer(MaterialMap&& layer) { fvMatLayers.push_back(std::move(layer)); }
+
+    /// \brief Check method
+    /// \note  Throws std::runtime_error, if the class inconsistent
+    void CheckConsistency() const;
+
+    /// \brief Gets material layer
+    [[gnu::always_inline]] const MaterialMap& GetMaterialLayer(int iLayer) const
+    {
+      return fvMatLayers.at<defs::GetterCheck>(iLayer);
+    }
+
+    /// \brief   Initializes setup
+    void Init();
+
+    /// \brief Returns initialization status
+    bool IsInitialized() const { return fbInitialized; }
+
+    /// \brief  Resets initialization
+    void Reset() { *this = std::move(Setup{}); }
+
+    /// \brief String representation of the class contents
+    /// \param verbosity    A verbose level for output
+    /// \param indentLevel  Indent level of the string output
+    std::string ToString(int verbosity = 0, int indentLevel = 0) const;
+
+   private:
+    /// \brief Serialization method
+    friend class boost::serialization::access;
+    template<class Archive>
+    void serialize(Archive& ar, const unsigned int /*version*/)
+    {
+      ar& fvMatLayers;
+      ar& fbInitialized;
+    }
+
+    MaterialContainer_t fvMatLayers = {};  ///< Material layers map
+
+    bool fbInitialized = false;  ///< Is instance initialized
+  };
+}  // namespace cbm::algo::kf
diff --git a/algo/kf/core/utils/KfVector.h b/algo/kf/core/utils/KfVector.h
new file mode 100644
index 0000000000..9074b71a78
--- /dev/null
+++ b/algo/kf/core/utils/KfVector.h
@@ -0,0 +1,95 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// \file   KfVector.h
+/// \brief  std::vector with an additional utility set
+/// \since  30.03.2024
+/// \author Sergei Zharko <s.zharko@gsi.de>
+
+#pragma once
+
+#include "AlgoFairloggerCompat.h"
+
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/base_object.hpp>
+#include <boost/serialization/vector.hpp>
+//#include <boost/stacktrace.hpp>
+
+#include <exception>
+#include <sstream>
+#include <vector>
+
+namespace cbm::algo::kf
+{
+  /// \class Vector
+  /// \brief A std::vector with additional debugging utility set
+  template<class T, class Allocator = std::allocator<T>>
+  class Vector : public std::vector<T, Allocator> {
+   public:
+    using BaseVector_t = std::vector<T, Allocator>;
+
+    /// \brief Generic constructor from parameters
+    template<typename... Args>
+    Vector(Args... values) : BaseVector_t(values...)
+    {
+    }
+
+    /// \brief Copy constructor
+    Vector(const Vector& other) : BaseVector_t(other) {}
+
+    /// \brief Move constructor
+    Vector(Vector&& other) : BaseVector_t(std::move(other)) {}
+
+    /// \brief Copy assignment operator
+    //Vector& operator=(const Vector& other) { return BaseVector_t::operator=(other); }
+    Vector& operator=(const Vector& other) = default;
+
+    /// \brief Move assignment operator
+    //Vector& operator=(Vector&& other) { return BaseVector_t::operator=(std::move(other)); }
+    Vector& operator=(Vector&& other) = default;
+
+    /// \brief Access operator overload
+    template<bool CheckBoundaries = false>
+    T& at(std::size_t pos)
+    {
+      if constexpr (CheckBoundaries) {
+        if (pos >= this->size()) {
+          std::stringstream msg;
+          msg << "kf::Vector::operator[]: accessing element with index out of boundaries (pos = " << pos
+              << ", size = " << this->size() << "). "
+              << "Stack trace:\n";
+          //<< boost::stacktrace::stacktrace();
+          throw std::runtime_error(msg.str());
+        }
+      }
+      return BaseVector_t::operator[](pos);
+    }
+
+    /// \brief Constant access operator overload
+    template<bool CheckBoundaries = false>
+    const T& at(std::size_t pos) const
+    {
+      if constexpr (CheckBoundaries) {
+        if (pos >= this->size()) {
+          std::stringstream msg;
+          msg << "kf::Vector::operator[]: accessing element with index out of boundaries (pos = " << pos
+              << ", size = " << this->size() << "). "
+              << "Stack trace:\n";
+          //<< boost::stacktrace::stacktrace();
+          throw std::runtime_error(msg.str());
+        }
+      }
+      return BaseVector_t::operator[](pos);
+    }
+
+   private:
+    /// \brief Serialization method
+    friend class boost::serialization::access;
+    template<class Archive>
+    void serialize(Archive& ar, const unsigned int /*version*/)
+    {
+      ar& boost::serialization::base_object<BaseVector_t>(*this);
+    }
+  };
+}  // namespace cbm::algo::kf
diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx
index 0e38eeb956..493e306ea0 100644
--- a/reco/L1/CbmL1.cxx
+++ b/reco/L1/CbmL1.cxx
@@ -526,8 +526,6 @@ try {
   //   Re-organize the the relation between CbmL1 and ca::Framework. I believe, we don't need a global pointer to the ca::Framework
   //   instance.
   fpAlgo = &gAlgo;
-  fpAlgo->Init(fTrackingMode);
-
 
   //
   // ** Send formed parameters object to ca::Framework instance **
@@ -536,7 +534,9 @@ try {
     auto parameters = fInitManager.TakeParameters();
     fpParameters    = std::make_shared<ca::Parameters<ca::fvec>>(parameters);
     fpAlgo->ReceiveParameters(std::move(parameters));
+    fpAlgo->ReceiveKfSettings(fInitManager.TakeKfParameters(), fInitManager.TakeKfSetup());
   }
+  fpAlgo->Init(fTrackingMode);
 
   // Initialize time-slice reader
   fpTSReader = std::make_unique<TimeSliceReader>();
-- 
GitLab