From dfc262826a4328ac8606f0a6d85d531741661e57 Mon Sep 17 00:00:00 2001
From: "s.zharko@gsi.de" <s.zharko@gsi.de>
Date: Thu, 30 Jan 2025 01:18:07 +0100
Subject: [PATCH] - ca: misalignment tolerances of x and y are set to 0 -
 V0Finder:   - YAML config   - cuts on velocity of pion and proton candidates 
  - enhanced cut for decay length (0.1 -> 5 cm)

---
 algo/CMakeLists.txt                    |   4 +
 algo/kfp/KfpV0FinderConfig.cxx         |  71 +++++++++++++++++
 algo/kfp/KfpV0FinderConfig.h           |  87 +++++++++++++++++++++
 macro/KF/CMakeLists.txt                |   2 +
 macro/KF/configs/CMakeLists.txt        |   3 +
 macro/KF/configs/mcbm_kfpf_lambda.yaml |  31 ++++++++
 macro/L1/configs/ca_params_mcbm.yaml   |   8 +-
 macro/mcbm/mcbm_hadron_kfp_ana.C       |  18 +----
 reco/KF/CbmKFV0FinderTask.cxx          | 103 +++++++++++++++++++++++++
 reco/KF/CbmKFV0FinderTask.h            |  71 ++++++++++++-----
 10 files changed, 357 insertions(+), 41 deletions(-)
 create mode 100644 algo/kfp/KfpV0FinderConfig.cxx
 create mode 100644 algo/kfp/KfpV0FinderConfig.h
 create mode 100644 macro/KF/configs/CMakeLists.txt
 create mode 100644 macro/KF/configs/mcbm_kfpf_lambda.yaml

diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt
index 770daf126b..5776eeb2aa 100644
--- a/algo/CMakeLists.txt
+++ b/algo/CMakeLists.txt
@@ -154,6 +154,7 @@ set(SRCS
   ca/TrackingSetup.cxx
   ca/TrackingChain.cxx
   ca/qa/CaQa.cxx
+  kfp/KfpV0FinderConfig.cxx
 )
 
 set(BUILD_INFO_CXX ${CMAKE_CURRENT_BINARY_DIR}/base/BuildInfo.cxx)
@@ -189,6 +190,7 @@ target_include_directories(Algo
          ${CMAKE_CURRENT_SOURCE_DIR}/kf
          ${CMAKE_CURRENT_SOURCE_DIR}/kf/core
          ${CMAKE_CURRENT_SOURCE_DIR}/kf/core/utils
+         ${CMAKE_CURRENT_SOURCE_DIR}/kfp
          ${CMAKE_CURRENT_SOURCE_DIR}/ca
          ${CMAKE_CURRENT_SOURCE_DIR}/ca/qa
          ${CMAKE_CURRENT_SOURCE_DIR}/ca/core/data
@@ -261,6 +263,7 @@ if (NOT CBM_ONLINE_STANDALONE)
            ${CMAKE_CURRENT_SOURCE_DIR}/kf
            ${CMAKE_CURRENT_SOURCE_DIR}/kf/core
            ${CMAKE_CURRENT_SOURCE_DIR}/kf/core/utils
+           ${CMAKE_CURRENT_SOURCE_DIR}/kfp
            ${CMAKE_CURRENT_SOURCE_DIR}/ca
            ${CMAKE_CURRENT_SOURCE_DIR}/ca/qa
            ${CMAKE_CURRENT_SOURCE_DIR}/ca/core/data
@@ -328,6 +331,7 @@ install(DIRECTORY ca/qa TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
 install(DIRECTORY qa TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
 install(DIRECTORY qa/unpack TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
 install(DIRECTORY ca TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
+install(DIRECTORY kfp TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
 
 
 install(
diff --git a/algo/kfp/KfpV0FinderConfig.cxx b/algo/kfp/KfpV0FinderConfig.cxx
new file mode 100644
index 0000000000..54e08ec323
--- /dev/null
+++ b/algo/kfp/KfpV0FinderConfig.cxx
@@ -0,0 +1,71 @@
+/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// \file   KfpV0FinderConfig.cxx
+/// \date   01.02.2025
+/// \brief  Configuration structure for V0 selector in mCBM (implementation)
+/// \author Sergei Zharko <s.zharko@gsi.de>
+
+#include "KfpV0FinderConfig.h"
+
+#include <sstream>
+
+using cbm::algo::kfp::Cuts;
+using cbm::algo::kfp::CutsKfp;
+using cbm::algo::kfp::ParticlePid;
+using cbm::algo::kfp::V0FinderConfig;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+std::string CutsKfp::ToString() const
+{
+  std::stringstream msg;
+  msg << "CUTS FOR KF PARTICLE FINDER:";
+  msg << "\n\tmin. decay length (l):                           " << minDecayLength << " [cm]";
+  msg << "\n\tmin. l/dl ratio:                                 " << minDecayLDL;
+  msg << "\n\tmax. chi2/NDF for primary particles (chi2_prim): " << maxChi2NdfPrim;
+  msg << "\n\tmax. chi2/NDF for V0 candidates (chi2_geo):      " << maxChi2NdfGeo;
+  return msg.str();
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+std::string ParticlePid::ToString() const
+{
+  std::stringstream msg;
+  msg << "\tPDG: " << pdg;
+  msg << "\n\t\tmin. DCA to PV: " << minDca << " [cm]";
+  msg << "\n\t\tmin. velocity:  " << minVelocity << " [cm/ns]";
+  msg << "\n\t\tmax. velocity:  " << maxVelocity << " [cm/ns]";
+  return msg.str();
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+std::string Cuts::ToString() const
+{
+  std::stringstream msg;
+  msg << kfp.ToString() << '\n';
+  msg << "PARTICLE SELECTION PROPERTIES:";
+  for (const auto& particle : particles) {
+    msg << '\n' << particle.ToString();
+  }
+  return msg.str();
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+std::string V0FinderConfig::ToString() const
+{
+  std::stringstream msg;
+  msg << "\n-------------- KFP V0-finder Configuration: ------------------------------------------------";
+  msg << "\nGOAL V0 (PDG): " << reconstructPdg;
+  msg << '\n' << cuts.ToString();
+  msg << "\nOTHER PARAMETERS:";
+  msg << "\n\tt0-offset:                " << tZeroOffset << " [ns]";
+  msg << "\n\tq/p relative uncertainty: " << qpAssignedUncertainty;
+  msg << "\n\tassigned PDG of primary:  " << primaryAssignedPdg;
+  msg << "\n--------------------------------------------------------------------------------------------";
+  return msg.str();
+}
diff --git a/algo/kfp/KfpV0FinderConfig.h b/algo/kfp/KfpV0FinderConfig.h
new file mode 100644
index 0000000000..dacc3705d8
--- /dev/null
+++ b/algo/kfp/KfpV0FinderConfig.h
@@ -0,0 +1,87 @@
+/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// \file   KfpV0FinderConfig.h
+/// \date   29.01.2025
+/// \brief  Configuration structure for V0 selector in mCBM
+/// \author Sergei Zharko <s.zharko@gsi.de>
+
+#pragma once
+
+#include "yaml/Yaml.h"
+
+#include <string>
+#include <vector>
+
+namespace cbm::algo::kfp
+{
+  /// \struct CutsKfp
+  /// \brief  Cuts for the KFParticleFinder
+  struct CutsKfp {
+    float minDecayLength;  ///< Minimal decay length of particles [cm]
+    float minDecayLDL;     ///< Minimal value of decay length to decay length error ratio
+    float maxChi2NdfPrim;  ///< Maximal chi2/NDF for primary particles (coming from the PV)
+    float maxChi2NdfGeo;   ///< Maximal chi2/NDF for V0 candidates
+
+    CBM_YAML_PROPERTIES(
+      yaml::Property(&CutsKfp::minDecayLength, "min_decay_length", "Minimal decay length of particles [cm]"),
+      yaml::Property(&CutsKfp::minDecayLDL, "min_decay_ldl", "Minimal value of decay length to decay length error ratio"),
+      yaml::Property(&CutsKfp::maxChi2NdfPrim, "max_chi2_ndf_prim", "Maximal chi2/NDF for primary particles"),
+      yaml::Property(&CutsKfp::maxChi2NdfGeo, "max_chi2_ndf_geo", "Maximal chi2/NDF for V0 candidates"));
+
+    /// \brief String representation of the structure
+    std::string ToString() const;
+  };
+
+  /// \struct ParticlePid
+  /// \brief  PID and pre-selection cuts for a given particle
+  struct ParticlePid {
+    int pdg;             ///< PDG code for particle
+    double minDca;       ///< Minimal DCA to PV [cm]
+    double minVelocity;  ///< Minimal velocity [cm/ns]
+    double maxVelocity;  ///< Maximal velocity [cm/ns]
+
+    CBM_YAML_PROPERTIES(
+      yaml::Property(&ParticlePid::pdg, "pdg", "PDG code of the particle"),
+      yaml::Property(&ParticlePid::minDca, "min_dca", "Minimal DCA to PV [cm]"),
+      yaml::Property(&ParticlePid::minVelocity, "min_velocity", "Minimal velocity [cm/ns]"),
+      yaml::Property(&ParticlePid::maxVelocity, "max_velocity", "Maximal velocity [cm/ns]"));
+
+    /// \brief String representation of the structure
+    std::string ToString() const;
+  };
+
+  /// \struct Cuts;
+  struct Cuts {
+    CutsKfp kfp;                         ///< Specific cuts for the KFParticleFinder
+    std::vector<ParticlePid> particles;  ///< Daughter PID cuts and other properties
+
+    CBM_YAML_PROPERTIES(
+      yaml::Property(&Cuts::kfp, "kfp", "Specific cuts for the KFParticleFinder"),
+      yaml::Property(&Cuts::particles,  "particles", "Particle identification cuts and properties"));
+
+    /// \brief String representation of the structure
+    std::string ToString() const;
+  };
+
+  /// \struct LambdaFinderConfig
+  /// \brief  Configuration for the V0 finder
+  struct V0FinderConfig {
+    Cuts cuts;                     ///< Different selection cuts
+    double tZeroOffset;            ///< Offset for T0 [ns]
+    double qpAssignedUncertainty;  ///< Assigned relative uncertainty for q/p estimation
+    int primaryAssignedPdg;        ///< Assigned PDG hypothesis for primary particles
+    int reconstructPdg;            ///< PDG of the particle, the decay of which is to be reconstructed
+
+    CBM_YAML_PROPERTIES(
+      yaml::Property(&V0FinderConfig::cuts, "cuts", "Different selection cuts"),
+      yaml::Property(&V0FinderConfig::tZeroOffset, "t0_offset", "The t0 offset [ns]"),
+      yaml::Property(&V0FinderConfig::qpAssignedUncertainty, "qa_uncertainty", "Assigned relative uncertainty for q/p"),
+      yaml::Property(&V0FinderConfig::primaryAssignedPdg, "primary_pdg", "Assigned PDG code for primary tracks"),
+      yaml::Property(&V0FinderConfig::reconstructPdg, "reconstruct_pdg", "PDG code of the particle to be reconstructed"));
+
+    /// \brief String representation of the contents
+    std::string ToString() const;
+  };
+}  // namespace cbm::algo::kfp
diff --git a/macro/KF/CMakeLists.txt b/macro/KF/CMakeLists.txt
index dbac328cee..5eecce9204 100644
--- a/macro/KF/CMakeLists.txt
+++ b/macro/KF/CMakeLists.txt
@@ -1,3 +1,5 @@
+add_subdirectory(configs)
+
 # Generate shell scripts
 Set(MACRO_DIR ${CBMROOT_BINARY_DIR}/macro/KF)
 GENERATE_CBM_TEST_SCRIPT(${CBMROOT_SOURCE_DIR}/macro/KF/kf_thermal_signal_generator.C ${MACRO_DIR})
diff --git a/macro/KF/configs/CMakeLists.txt b/macro/KF/configs/CMakeLists.txt
new file mode 100644
index 0000000000..eb2ee12b2d
--- /dev/null
+++ b/macro/KF/configs/CMakeLists.txt
@@ -0,0 +1,3 @@
+Install(FILES mcbm_kfpf_lambda.yaml
+              DESTINATION share/cbmroot/macro/KF/configs
+       )
diff --git a/macro/KF/configs/mcbm_kfpf_lambda.yaml b/macro/KF/configs/mcbm_kfpf_lambda.yaml
new file mode 100644
index 0000000000..01e77b1855
--- /dev/null
+++ b/macro/KF/configs/mcbm_kfpf_lambda.yaml
@@ -0,0 +1,31 @@
+# Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+# SPDX-License-Identifier: GPL-3.0-only
+# Authors: Sergei Zharko [committer] */
+#
+# \file   mcbm_kfpf_lambda.yaml
+# \date   29.01.2025
+# \brief  Standard configuration for the lambda finding in mCBM
+# \author Sergei Zharko <s.zharko@gsi.de>
+
+reconstruct_pdg: 3122  # Lambda -> pi- p
+
+t0_offset: 0.12      # Time offset for T0 [ns]
+qa_uncertainty: 0.1  # Assigned relative uncertainty for the q/p estimation
+primary_pdg: 321     # Assigned PDG code for primary tracks
+
+cuts:  # Different cuts
+  kfp:  # KFParticleFinder specific cuts
+    min_decay_length: 5.  # Minimal decay length of particles [cm]
+    min_decay_ldl: 1.     # Minimal value of decay length to decay length error ratio
+    max_chi2_ndf_prim: 0. # Maximal chi2/NDF for primary particles
+    max_chi2_ndf_geo: 50. # Maximal chi2/NDF for V0 candidates
+  particles:  # Defined particle
+    - pdg: -211  # Pion
+      min_dca: 1.5        # [cm]
+      min_velocity: 25.   # [cm/ns]
+      max_velocity: 29.5  # [cm/ns]
+    - pdg: 2212  # Proton
+      min_dca: 0.5       # [cm]
+      min_velocity: 15.  # [cm/ns]
+      max_velocity: 28.  # [cm/ns]
+
diff --git a/macro/L1/configs/ca_params_mcbm.yaml b/macro/L1/configs/ca_params_mcbm.yaml
index 79141d8dd6..1cc693e4c6 100644
--- a/macro/L1/configs/ca_params_mcbm.yaml
+++ b/macro/L1/configs/ca_params_mcbm.yaml
@@ -30,10 +30,10 @@ ca:
 
       # Misalignment tolerances x[cm], y[cm], t[ns]
       misalignment_tolerance: 
-        sts:  [0.2, 0.2, 100.0]
-        much: [0.2, 0.2, 100.0]
-        trd:  [0.2, 0.2, 100.0]
-        tof:  [0.2, 0.2, 100.0]
+        sts:  [0.0, 0.0, 100.0]
+        much: [0.0, 0.0, 100.0]
+        trd:  [0.0, 0.0, 100.0]
+        tof:  [0.0, 0.0, 100.0]
 
       # Random seed
       random_seed: 1
diff --git a/macro/mcbm/mcbm_hadron_kfp_ana.C b/macro/mcbm/mcbm_hadron_kfp_ana.C
index bd44f80b29..46a29f9e9b 100644
--- a/macro/mcbm/mcbm_hadron_kfp_ana.C
+++ b/macro/mcbm/mcbm_hadron_kfp_ana.C
@@ -178,27 +178,11 @@ Bool_t mcbm_hadron_kfp_ana(UInt_t uRunId         = 2391,
 
   // -- V0 Finder ------------------------------------------------------------------------------------------------------
   auto* pV0 = new cbm::kfp::V0FinderTask(/*verbose = */ 3);
-  // TODO:  define all the setters initialization within a config file
-  // The task parameters:
-  pV0->SetMinPionDca(1.5);
-  pV0->SetMinProtonDca(0.5);
-  //pV0->SetTzeroOffset(0.12);
-  pV0->SetTzeroOffset(0.);
-  pV0->SetQpAssignedUncertainty(0.10);  // 10% uncertainty for track q/p
   pV0->SetMixedEventMode(bMixEvent);
   pV0->SetProcessingMode(cbm::kfp::V0FinderTask::EProcessingMode::TimeBased);
   pV0->SetPidApproach(cbm::kfp::V0FinderTask::EPidApproach::Topo);
   pV0->SetPvFindingMode(cbm::kfp::V0FinderTask::EPvUsageMode::Target);
-
-  // Decays to be reconstructed:
-  pV0->AddDecayToReconstructionList(3122);  // Lambda
-
-  // KFParticleFinder cuts:
-  pV0->SetChiPrimaryCut2D(0.f);
-  pV0->SetLdLCut2D(1.f);
-  pV0->SetLCut(0.1);
-  pV0->SetChi2Cut2D(50.f);
-
+  pV0->SetConfigName(srcDir + "/macro/KF/configs/mcbm_kfpf_lambda.yaml");
   // QA output setting
   {
     TString sQaFile{sSinkFile};
diff --git a/reco/KF/CbmKFV0FinderTask.cxx b/reco/KF/CbmKFV0FinderTask.cxx
index bb4d223a11..aaf6b26efe 100644
--- a/reco/KF/CbmKFV0FinderTask.cxx
+++ b/reco/KF/CbmKFV0FinderTask.cxx
@@ -23,9 +23,13 @@
 #include "FairRunAna.h"
 #include "KFPTrackVector.h"
 #include "KFVertex.h"
+#include "KfpV0FinderConfig.h"
 #include "Logger.h"
 #include "TClonesArray.h"
 #include "TMatrixTSym.h"
+#include "yaml/Yaml.h"
+
+#include <boost/filesystem.hpp>
 
 #include <algorithm>
 #include <cmath>
@@ -40,6 +44,87 @@
 
 using cbm::kfp::V0FinderTask;
 
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void V0FinderTask::ApplyConfiguration()
+{
+  namespace fs        = boost::filesystem;
+  namespace yml       = cbm::algo::yaml;
+  fs::path configPath = fsConfigName.Data();
+  if (!fs::exists(configPath)) {
+    std::stringstream msg;
+    msg << fName << ": configuration file " << configPath.string() << " does not exist";
+    throw std::runtime_error(msg.str());
+  }
+
+  LOG_(info, 1) << "applying configuration from " << configPath.string();
+  auto config = yml::ReadFromFile<cbm::algo::kfp::V0FinderConfig>(configPath);
+
+  LOG_(info, 1) << config.ToString();
+
+
+  // -- Read the config
+  if (config.reconstructPdg != 3122) {  // At the moment only Lambda analysis is possible
+    std::stringstream msg;
+    msg << fName << ": at the moment only lambda finding is possible. Provided PDG: " << config.reconstructPdg;
+    throw std::runtime_error(msg.str());
+  }
+
+  // Check daughter particles:
+  auto& particles = config.cuts.particles;
+  int iPion       = -1;
+  int iProton     = -1;
+  for (int iPart = 0; iPart < int(particles.size()); ++iPart) {
+    const auto& particle = particles[iPart];
+    if (particle.pdg == -211) {
+      if (iPion == -1) {
+        iPion = iPart;
+      }
+      else {
+        std::stringstream msg;
+        msg << fName << ": pion entry is defined more then one time in the config.cuts.particles";
+        throw std::runtime_error(msg.str());
+      }
+    }
+    else if (particle.pdg == 2212) {
+      if (iProton == -1) {
+        iProton = iPart;
+      }
+      else {
+        std::stringstream msg;
+        msg << fName << ": proton entry is defined more then one time in the config.cuts.particles";
+        throw std::runtime_error(msg.str());
+      }
+    }
+  }
+  if (iProton == -1 || iPion == -1) {
+    std::stringstream msg;
+    msg << fName << ": config cuts/particles: either pion or proton settings are not found";
+    throw std::runtime_error(msg.str());
+  }
+
+  const auto& pion{particles[iPion]};
+  const auto& proton{particles[iProton]};
+
+  SetMinPionDca(pion.minDca);
+  SetPionVelocityRange(pion.minVelocity, pion.maxVelocity);
+  SetMinProtonDca(proton.minDca);
+  SetProtonVelocityRange(proton.minVelocity, proton.maxVelocity);
+
+  SetTzeroOffset(config.tZeroOffset);
+  SetQpAssignedUncertainty(config.qpAssignedUncertainty);
+  AddDecayToReconstructionList(config.reconstructPdg);  // Lambda
+
+  fPrimaryAssignedPdg = config.primaryAssignedPdg;
+
+  // KFParticleFinder cuts:
+  auto& kfpCuts = config.cuts.kfp;
+  SetChiPrimaryCut2D(kfpCuts.maxChi2NdfPrim);
+  SetLdLCut2D(kfpCuts.minDecayLDL);
+  SetLCut(kfpCuts.minDecayLength);  // 5cm cut
+  SetChi2Cut2D(kfpCuts.maxChi2NdfGeo);
+}
+
 // ---------------------------------------------------------------------------------------------------------------------
 //
 bool V0FinderTask::AssignMomentum(CbmGlobalTrack* pTrack, int pdg)
@@ -79,11 +164,19 @@ bool V0FinderTask::AssignMomentum(CbmGlobalTrack* pTrack, int pdg)
     fpQa->fph_beta_all->Fill(qpAndBeta.fBeta);
   }
 
+  auto& beta = qpAndBeta.fBeta;
   if (qpAndBeta.fBeta > 1) {
     ++fCounters[ECounter::TracksWithUnphysicalBeta];
     return false;  // unphysical track
   }
 
+  // Extra cut on pion and proton velocity (TODO: maybe put this cut earlier)
+  if ((pdg == -211 && (beta > fMaxBetaPion || beta < fMinBetaPion))
+      || (pdg == 2212 && (beta > fMaxBetaProton || beta < fMinBetaProton))) {
+    return false;
+  }
+
+
   // Update the track with the PID hypothesis and momentum
   FairTrackParam parFst(*pTrack->GetParamFirst());
   FairTrackParam parLst(*pTrack->GetParamLast());
@@ -406,6 +499,16 @@ InitStatus V0FinderTask::Init()
     return kFATAL;
   }
 
+  if (!fsConfigName.IsNull()) {
+    try {
+      ApplyConfiguration();
+    }
+    catch (const std::exception& err) {
+      ERR_ << "configuration from a config was required, but failed. Reason: " << err.what();
+      return kFATAL;
+    }
+  }
+
   // ----- Input data branches initialization
   const auto* pTarget = kf::Target::Instance();  // CBM target info
 
diff --git a/reco/KF/CbmKFV0FinderTask.h b/reco/KF/CbmKFV0FinderTask.h
index caf2a23793..274eb4e4df 100644
--- a/reco/KF/CbmKFV0FinderTask.h
+++ b/reco/KF/CbmKFV0FinderTask.h
@@ -34,27 +34,11 @@ class CbmEventTriggers;
 
 namespace cbm::kfp
 {
+
   /// \class  V0FinderTask
   /// \brief  A class to find V0 candidates in mCBM
   class V0FinderTask : public FairTask {
    public:
-    /// \struct QpAndBeta
-    /// \brief  Qp and beta container
-    struct QpAndBeta {
-      double fQp{std::numeric_limits<double>::signaling_NaN()};
-      double fQpVar{std::numeric_limits<double>::signaling_NaN()};
-      double fBeta{std::numeric_limits<double>::signaling_NaN()};
-      double fBetaVar{std::numeric_limits<double>::signaling_NaN()};
-    };
-
-    /// \struct DcaVector
-    /// \brief  A vector representation of DCA to target
-    struct DcaVector {
-      double fAbs{std::numeric_limits<double>::signaling_NaN()};  ///< Absolute value
-      double fX{std::numeric_limits<double>::signaling_NaN()};    ///< X-component of the unit-vector
-      double fY{std::numeric_limits<double>::signaling_NaN()};    ///< Y-component of the unit-vector
-    };
-
     /// \enum   Counter
     /// \brief  Enumeration of counters (for the entire run)
     enum class ECounter : uint8_t
@@ -108,6 +92,23 @@ namespace cbm::kfp
       Mc                    //< Use MC-true primary vertex
     };
 
+    /// \struct QpAndBeta
+    /// \brief  Qp and beta container
+    struct QpAndBeta {
+      double fQp{std::numeric_limits<double>::signaling_NaN()};
+      double fQpVar{std::numeric_limits<double>::signaling_NaN()};
+      double fBeta{std::numeric_limits<double>::signaling_NaN()};
+      double fBetaVar{std::numeric_limits<double>::signaling_NaN()};
+    };
+
+    /// \struct DcaVector
+    /// \brief  A vector representation of DCA to target
+    struct DcaVector {
+      double fAbs{std::numeric_limits<double>::signaling_NaN()};  ///< Absolute value
+      double fX{std::numeric_limits<double>::signaling_NaN()};    ///< X-component of the unit-vector
+      double fY{std::numeric_limits<double>::signaling_NaN()};    ///< Y-component of the unit-vector
+    };
+
     /// \brief  Constructor
     /// \param  verbose  Verbosity of the task
     explicit V0FinderTask(int verbose = 1) : FairTask("V0FinderTask", verbose){};
@@ -152,10 +153,14 @@ namespace cbm::kfp
     }
 
     /// \brief  Accessor to the track DCA
-    //const
+    const std::vector<DcaVector>& GetTrackDca() { return fvTrackDca; }
 
     //* Task logic and preliminary selection cut setters
 
+    /// \brief  Sets name of the configuration file
+    /// \param  fileName  Name of the config file
+    void SetConfigName(const TString& fileName) { fsConfigName = fileName; }
+
     /// \brief  Sets processing mode (time-based/event-based)
     void SetProcessingMode(EProcessingMode mode) { fProcessingMode = mode; }
 
@@ -171,6 +176,24 @@ namespace cbm::kfp
     /// \brief  Sets the flag: if the QA should be executed
     void SetRunQa(bool bRunQa) { fbRunQa = bRunQa; }
 
+    /// \brief  Sets pion velocity range
+    /// \param  vMin  Minimal velocity [cm/ns]
+    /// \param  vMax  Maximal velocity [cm/ns]
+    void SetPionVelocityRange(double vMin, double vMax)
+    {
+      fMinBetaPion = vMin / kSpeedOfLight;
+      fMaxBetaPion = vMax / kSpeedOfLight;
+    }
+
+    /// \brief  Sets proton velocity range
+    /// \param  vMin  Minimal velocity [cm/ns]
+    /// \param  vMax  Maximal velocity [cm/ns]
+    void SetProtonVelocityRange(double vMin, double vMax)
+    {
+      fMinBetaProton = vMin / kSpeedOfLight;
+      fMaxBetaProton = vMax / kSpeedOfLight;
+    }
+
     /// \brief  Sets minimal pion DCA to primary vertex
     /// \param  dca  DCA [cm]
     void SetMinPionDca(double dca) { fMinPionDca = dca; }
@@ -334,6 +357,9 @@ namespace cbm::kfp
    private:
     //* Auxilary internal methods
 
+    /// \brief   Applies configuration from fsConfigName
+    void ApplyConfiguration();
+
     /// \brief   Assigns momentum to a global track
     /// \param   pTrack  Pointer to a global track
     /// \param   pdg     PID hypothesis
@@ -420,12 +446,16 @@ namespace cbm::kfp
     static constexpr double kProtonMass{0.938272088};   ///< Proton mass [GeV/c2]
     static constexpr double kSpeedOfLight{29.9792458};  ///< Speed of light [cm/ns]
 
-    //* Different run-time flags;
+    //* Different run-time cuts and flags (TODO: define in a config)
     double fTzeroOffset{0.};             ///< Offset for T0
     double fMinPionDca{1.5};             ///< Minimum DCA to PV for pions
     double fMinProtonDca{0.5};           ///< Minimum DCA to PV for protons
     double fQpAssignedUncertainty{0.1};  ///< Assigned relative uncertainty for q/p estimation
     int fPrimaryAssignedPdg{321};        ///< Assigned PDG hypothesis for primary particles
+    double fMinBetaProton{0.};           ///< Minimal proton velocity (beta) [c]
+    double fMaxBetaProton{1.};           ///< Maximal proton velocity (beta) [c]
+    double fMinBetaPion{0.};             ///< Minimal proton velocity (beta) [c]
+    double fMaxBetaPion{1.};             ///< Maximal proton velocity (beta) [c]
 
     //* Input data branches
     TClonesArray* fpBrRecoEvents{nullptr};
@@ -443,7 +473,7 @@ namespace cbm::kfp
     // TODO: in principle one can store the found KF particles and vertices as well
 
     //* Temporary data and auxilary variables (per FairTask::Exec() call)
-    std::vector<DcaVector> fvTrackDca;  ///< Track DCA vector [n selected tracks]
+    std::vector<DcaVector> fvTrackDca;  ///< Track DCA vector [n global tracks]
     std::unique_ptr<CbmVertex> fpOrigin{
       std::make_unique<CbmVertex>()};  ///< Origin (e.g., can be either reconstructed PV or target)
 
@@ -468,6 +498,7 @@ namespace cbm::kfp
     cbm::core::EnumArray<ECounter, size_t> fCounters{{0}};  ///< Counters per run
     std::unique_ptr<V0FinderQa> fpQa{nullptr};              ///< If QA is processed
     TString fsQaOutputName{"./V0FinderQa.root"};            ///< Output QA name
+    TString fsConfigName{""};                               ///< Name of the config
 
 
     ClassDefOverride(V0FinderTask, 0);
-- 
GitLab