diff --git a/core/base/CbmTrackingDetectorInterfaceBase.h b/core/base/CbmTrackingDetectorInterfaceBase.h
index 33cfb21e19676dbeec1777ea3b6600b832be07f5..857d51502968abdd7b129a534e7b880d03906997 100644
--- a/core/base/CbmTrackingDetectorInterfaceBase.h
+++ b/core/base/CbmTrackingDetectorInterfaceBase.h
@@ -15,6 +15,8 @@
 #include "CbmHit.h"
 #include "CbmPixelHit.h"
 
+#include "FairMCPoint.h"
+
 #include <array>
 #include <string>
 #include <tuple>
@@ -51,17 +53,16 @@ public:
   /// @return Local index of the tracking station
   virtual int GetTrackingStationIndex(const CbmHit* hit) const = 0;
 
+  /// @brief  Gets a tracking station of a FairMCPoint
+  /// @param  point  A pointer to FairMCHit
+  /// @return Local index of the tracking station
+  virtual int GetTrackingStationIndex(const FairMCPoint* point) const = 0;
+
   /// @brief  Gets a tracking station by the address of element
   /// @param  address  Unique element address
   /// @return Local index of the tracking station
   virtual int GetTrackingStationIndex(int address) const = 0;
 
-  /// @brief  Gets a tracking station index of MC point
-  /// @param  zPos  z-coordinate of hit/point position [cm]
-  ///
-  /// The function searches for the closest station in beam axis direction
-  int GetTrackingStationIndex(double zPos) const;
-
   /// @brief  Gets upper bound of a station along the X-axis
   /// @param  stationId  Tracking station ID in the setup (NOTE: must be in range [0..GetNstations()-1])
   /// @return Size of station along the X-axis [cm]
@@ -120,26 +121,4 @@ public:
   std::string ToString() const;
 };
 
-// **********************************************************
-// **     Template and inline function implementations     **
-// **********************************************************
-
-// ---------------------------------------------------------------------------------------------------------------------
-//
-inline int CbmTrackingDetectorInterfaceBase::GetTrackingStationIndex(double zPos) const
-{
-  double bestDist = 1.e+20;  // arbitrary large number
-  int nStations   = GetNtrackingStations();
-  int iStSelected = -1;
-  for (int iSt = 0; iSt < nStations; ++iSt) {
-    auto dist = std::fabs(zPos - GetZref(iSt));
-    if (dist < bestDist) {
-      bestDist    = dist;
-      iStSelected = iSt;
-    }
-  }
-  return iStSelected;
-}
-
-
 #endif  // CbmTrackingDetectorInterfaceBase_h
diff --git a/core/detectors/much/CbmMuchTrackingInterface.h b/core/detectors/much/CbmMuchTrackingInterface.h
index 8989e4719c7fdf28b55201d5a2c0dead1e549517..8449b0b05f85306f0127b2a09384ddd0e6e70939 100644
--- a/core/detectors/much/CbmMuchTrackingInterface.h
+++ b/core/detectors/much/CbmMuchTrackingInterface.h
@@ -99,6 +99,14 @@ public:
            + CbmMuchGeoScheme::GetLayerIndex(address);
   }
 
+  /// @brief  Gets a tracking station of a FairMCPoint
+  /// @param  point  A pointer to FairMCHit
+  /// @return Local index of the tracking station
+  int GetTrackingStationIndex(const FairMCPoint* point) const
+  {
+    return GetTrackingStationIndex(point->GetDetectorID());
+  }
+
   // TODO: SZh 30.08.2023: Provide automatic definintion of bounds
   /// @brief  Gets upper bound of a station along the X-axis
   /// @param  stationId  Tracking station ID in the setup (NOTE: must be in range [0..GetNstations()-1])
diff --git a/core/detectors/mvd/CbmMvdTrackingInterface.h b/core/detectors/mvd/CbmMvdTrackingInterface.h
index 5c75038dcf3cb2a223fd69d626bc03d0da394de2..17b397b97a2fe68c063c4d7b9d9f587595493d33 100644
--- a/core/detectors/mvd/CbmMvdTrackingInterface.h
+++ b/core/detectors/mvd/CbmMvdTrackingInterface.h
@@ -12,19 +12,20 @@
 #ifndef CbmMvdTrackingInterface_h
 #define CbmMvdTrackingInterface_h 1
 
-#include "CbmHit.h"                            // for CbmHit
-#include "CbmMvdDetectorId.h"                  // for CbmMvdDetectorId
-#include "CbmMvdHit.h"                         // for CbmMvdHit
-#include "CbmMvdStationPar.h"                  // for CbmMvdStationPar
-#include "CbmTrackingDetectorInterfaceBase.h"  // for CbmTrackingDetectorInt...
+#include "CbmHit.h"
+#include "CbmMvdDetectorId.h"
+#include "CbmMvdHit.h"
+#include "CbmMvdStationPar.h"
+#include "CbmTrackingDetectorInterfaceBase.h"
 
 #include <FairTask.h>  // for InitStatus, FairTask
 
 #include <Rtypes.h>  // for ClassDef
 #include <TMath.h>   // for Pi
 
-#include <algorithm>  // for min, max
-#include <string>     // for string
+#include <algorithm>
+#include <limits>
+#include <string>
 
 class TBuffer;
 class TClass;
@@ -93,6 +94,14 @@ public:
     return hitMvd->GetStationNr();
   }
 
+  /// @brief  Gets a tracking station of a FairMCPoint
+  /// @param  point  A pointer to FairMCHit
+  /// @return Local index of the tracking station
+  int GetTrackingStationIndex(const FairMCPoint* point) const
+  {
+    return GetTrackingStationIndex(point->GetDetectorID());
+  }
+
   /// @brief  Gets a tracking station by the address of element (detectorID in terms of MVD)
   /// @param  detectorId  Unique element address (detectorID in terms of MVD)
   /// @return Local index of the tracking station
diff --git a/core/detectors/sts/CbmStsTrackingInterface.h b/core/detectors/sts/CbmStsTrackingInterface.h
index 941a597ece86a1f40986e80fbe7119cd7ca15ffb..6853da15d9332285a82cb4009feb8209b4f3ccfa 100644
--- a/core/detectors/sts/CbmStsTrackingInterface.h
+++ b/core/detectors/sts/CbmStsTrackingInterface.h
@@ -83,6 +83,14 @@ public:
   /// @return Local index of the tracking station
   int GetTrackingStationIndex(int address) const { return CbmStsSetup::Instance()->GetStationNumber(address); }
 
+  /// @brief  Gets a tracking station of a FairMCPoint
+  /// @param  point  A pointer to FairMCHit
+  /// @return Local index of the tracking station
+  int GetTrackingStationIndex(const FairMCPoint* point) const
+  {
+    return GetTrackingStationIndex(point->GetDetectorID());
+  }
+
   /// @brief  Gets upper edge of a station along the X-axis
   /// @param  stationId  Tracking station ID in the setup (NOTE: must be in range [0..GetNstations()-1])
   /// @return Size of station along the X-axis [cm]
diff --git a/core/detectors/tof/CbmTofTrackingInterface.h b/core/detectors/tof/CbmTofTrackingInterface.h
index 1ae4ff16a373499432fde15b0687bc47237e61c2..638173a41a50a0e046a7f06a74f1504d6d92c6c1 100644
--- a/core/detectors/tof/CbmTofTrackingInterface.h
+++ b/core/detectors/tof/CbmTofTrackingInterface.h
@@ -79,6 +79,14 @@ public:
     return iSt;
   }
 
+  /// @brief  Gets a tracking station of a FairMCPoint
+  /// @param  point  A pointer to FairMCHit
+  /// @return Local index of the tracking station
+  int GetTrackingStationIndex(const FairMCPoint* point) const
+  {
+    return GetTrackingStationIndex(point->GetDetectorID());
+  }
+
   // TODO: SZh. 10.09.2023: Provide automatic selection
   /// @brief  Gets upper bound of a station along the X-axis
   /// @param  stationId  Tracking station ID in the setup (NOTE: must be in range [0..GetNstations()-1])
diff --git a/core/detectors/trd/CbmTrdTrackingInterface.h b/core/detectors/trd/CbmTrdTrackingInterface.h
index c1215c303f40ee5a3a5805b521731e0bc4c9a31f..cdb4d23938a8af71172c2b7aec548d555ea6ac82 100644
--- a/core/detectors/trd/CbmTrdTrackingInterface.h
+++ b/core/detectors/trd/CbmTrdTrackingInterface.h
@@ -73,6 +73,14 @@ public:
   /// @return Local index of the tracking station
   int GetTrackingStationIndex(int address) const { return CbmTrdAddress::GetLayerId(address); }
 
+  /// @brief  Gets a tracking station of a FairMCPoint
+  /// @param  point  A pointer to FairMCHit
+  /// @return Local index of the tracking station
+  int GetTrackingStationIndex(const FairMCPoint* point) const
+  {
+    return GetTrackingStationIndex(point->GetDetectorID());
+  }
+
   /// @brief  Gets upper edge of a station along the X-axis
   /// @param  stationId  Tracking station ID in the setup (NOTE: must be in range [0..GetNstations()-1])
   /// @return Size of station along the X-axis [cm]
diff --git a/macro/mcbm/CMakeLists.txt b/macro/mcbm/CMakeLists.txt
index 945dea38171292c02ade0f2b379741880932f7c1..3b5c13838932d67092ad74b6457a919def30cc05 100644
--- a/macro/mcbm/CMakeLists.txt
+++ b/macro/mcbm/CMakeLists.txt
@@ -140,6 +140,7 @@ ForEach(setup IN LISTS cbm_setup)
 EndForEach(setup IN LISTS cbm_setup)
 
 Install(FILES .rootrc mcbm_transport.C mcbm_digi.C mcbm_reco_event.C mcbm_match_check.C mcbm_hadron_analysis.C mcbm_qa.C
+        mcbm_transport_boxgen.C
         DESTINATION share/cbmroot/macro/mcbm
        )
 Install(DIRECTORY modules DESTINATION share/cbmroot/macro/mcbm)
diff --git a/macro/mcbm/mcbm_transport_boxgen.C b/macro/mcbm/mcbm_transport_boxgen.C
new file mode 100644
index 0000000000000000000000000000000000000000..e867d1202303e5576ffdb2eb4b96434732c5059d
--- /dev/null
+++ b/macro/mcbm/mcbm_transport_boxgen.C
@@ -0,0 +1,174 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+void SetTrack(CbmTransport*, Double_t, Int_t, Double_t, Double_t, Double_t);
+
+/// @brief Function to run a mCBM transport with a box generator
+/// @param nEvents       Number of events
+/// @param setupName     Name of the setup
+/// @param output        Prefix of the output name
+/// @param overwrite     Flag: if overwrite output
+/// @param randomSeed    Seed of the random generator
+/// @param pdg           PDG code for particles to generate
+/// @param multiplicity  Multiplicity of generated particles
+// clang-format off
+void mcbm_transport_boxgen(Int_t nEvents = 10,
+                    //                  const char* setupName = "mcbm_beam_2022_08",
+                    //                  const char* setupName = "mcbm_beam_2022_07",
+                    //                  const char* setupName = "mcbm_beam_2022_06",
+                    //                  const char* setupName = "mcbm_beam_2022_05",
+                    //                  const char* setupName = "mcbm_beam_2022_04",
+                    //                  const char* setupName = "mcbm_beam_2022_03",
+                    //                  const char* setupName = "mcbm_beam_2022_02",
+                    //                  const char* setupName = "mcbm_beam_2022_01",
+                    //                  const char* setupName = "mcbm_beam_2022_06_16_gold",
+                                      const char* setupName = "mcbm_beam_2022_05_23_nickel",
+                    //                  const char* setupName = "mcbm_beam_2022_03_28_uranium",
+                    //                  const char* setupName = "mcbm_beam_2022_03_27_iron",
+                    //                  const char* setupName = "mcbm_beam_2022_03_22_iron",
+                    //                  const char* setupName = "mcbm_beam_2022_03_20_iron",
+                    //                  const char* setupName = "mcbm_beam_2022_03_09_carbon",
+                    //                  const char* setupName = "mcbm_beam_2021_07_surveyed",
+                    //                  const char* setupName = "mcbm_beam_2021_04",
+                    //                  const char* setupName = "mcbm_beam_2021_03",
+                    //                  const char* setupName = "mcbm_beam_2020_03",
+                    //                  const char* setupName = "mcbm_beam_2019_11",
+                    //                  const char* setupName = "mcbm_beam_2019_03",
+                    //                  const char* setupName = "sis18_mcbm_25deg_long",
+                    const char* output = "data/test", 
+                    Bool_t overwrite = kTRUE, 
+                    int randomSeed = 1,
+                    int pdg = 2212,
+                    int multiplicity = 1
+                    )
+// clang-format on
+{
+  // --- Define the beam angle ----------------------------------------------
+  Double_t beamRotY = 25.;
+  // ------------------------------------------------------------------------
+
+  // --- Define the target geometry -----------------------------------------
+  //
+  // The target is not part of the setup, since one and the same setup can
+  // and will be used with different targets.
+  // The target is constructed as a tube in z direction with the specified
+  // diameter (in x and y) and thickness (in z). It will be placed at the
+  // specified position as daughter volume of the volume present there. It is
+  // in the responsibility of the user that no overlaps or extrusions are
+  // created by the placement of the target.
+  //
+  TString targetElement = "Gold";
+  Double_t targetPosX   = 0.;  // target x position in global c.s. [cm]
+  Double_t targetPosY   = 0.;  // target y position in global c.s. [cm]
+  Double_t targetPosZ   = 0.;  // target z position in global c.s. [cm]
+
+  //  Double_t targetThickness = 0.1;    // full thickness in cm
+  //  Double_t targetDiameter  = 0.5;    // diameter in cm
+  //  Double_t targetRotY      = 25.;    // target rotation angle around the y axis [deg]
+
+  Double_t targetThickness = 0.025;  // mCBM thin gold target 0.25 mm = 0.025 cm thickness
+  Double_t targetDiameter  = 1.5;    // mCBM target width 15 mm = 1.5 cm
+  //  Double_t targetDiameter  = 0.1;      // set small target for window acceptance plots
+  Double_t targetRotY = beamRotY;  // target rotation angle around the y axis [deg]
+  // ------------------------------------------------------------------------
+
+  // --- Logger settings ----------------------------------------------------
+  FairLogger::GetLogger()->SetLogScreenLevel("INFO");
+  FairLogger::GetLogger()->SetLogVerbosityLevel("VERYHIGH");
+  // ------------------------------------------------------------------------
+
+
+  // -----   Environment   --------------------------------------------------
+  TString myName = "mcbm_transport_boxgen";        // this macro's name for screen output
+  TString srcDir = gSystem->Getenv("VMCWORKDIR");  // top source directory
+  // ------------------------------------------------------------------------
+
+
+  // -----   In- and output file names   ------------------------------------
+  TString dataset(output);
+  TString outFile = dataset + ".tra.root";
+  TString parFile = dataset + ".par.root";
+  TString geoFile = dataset + ".geo.root";
+  std::cout << "Output file:     " << outFile << '\n';
+  std::cout << "Parameters file: " << parFile << '\n';
+  std::cout << "Geometry file:   " << geoFile << '\n';
+  std::cout << '\n';
+  // ------------------------------------------------------------------------
+
+
+  // -----   Timer   --------------------------------------------------------
+  TStopwatch timer;
+  timer.Start();
+  // ------------------------------------------------------------------------
+
+
+  // ----- Transport run   --------------------------------------------------
+  CbmTransport run;
+
+  // ----- Box generator of a single -----------------------
+  FairBoxGenerator* boxGen = new FairBoxGenerator(pdg, multiplicity);
+  boxGen->SetPRange(0.1, 3.);
+  boxGen->SetPhiRange(0., 360.);
+  boxGen->SetThetaRange(0, 50.);
+  boxGen->SetCosTheta();
+  boxGen->Init();
+  run.AddInput(boxGen);
+  // ----- Box generator of a single proton per event -----------------------
+
+  run.SetOutFileName(outFile, overwrite);
+  run.SetParFileName(parFile);
+  run.SetGeoFileName(geoFile);
+  run.LoadSetup(setupName);
+  run.SetField(new CbmFieldConst());
+  run.SetTarget(targetElement, targetThickness, targetDiameter, targetPosX, targetPosY, targetPosZ,
+                targetRotY * TMath::DegToRad());
+  run.SetBeamPosition(0., 0., 0.1, 0.1);  // Beam width 1 mm is assumed
+  run.SetBeamAngle(beamRotY * TMath::DegToRad(), 0.);
+  if (nEvents <= 10)  // store only for small number of events
+    run.StoreTrajectories();
+  run.SetRandomSeed(randomSeed);
+  run.Run(nEvents);
+  // ------------------------------------------------------------------------
+
+
+  // -----   Finish   -------------------------------------------------------
+  timer.Stop();
+  Double_t rtime = timer.RealTime();
+  Double_t ctime = timer.CpuTime();
+  std::cout << std::endl << std::endl;
+  std::cout << "Macro finished successfully." << std::endl;
+  std::cout << "Output file is " << outFile << std::endl;
+  std::cout << "Parameter file is " << parFile << std::endl;
+  std::cout << "Real time " << rtime << " s, CPU time " << ctime << "s" << std::endl << std::endl;
+  // ------------------------------------------------------------------------
+
+
+  // -----   Resource monitoring   ------------------------------------------
+  FairSystemInfo sysInfo;
+  Float_t maxMemory = sysInfo.GetMaxMemory();
+  std::cout << "<DartMeasurement name=\"MaxMemory\" type=\"numeric/double\">";
+  std::cout << maxMemory;
+  std::cout << "</DartMeasurement>" << std::endl;
+
+  Float_t cpuUsage = ctime / rtime;
+  std::cout << "<DartMeasurement name=\"CpuLoad\" type=\"numeric/double\">";
+  std::cout << cpuUsage;
+  std::cout << "</DartMeasurement>" << std::endl;
+
+
+  std::cout << " Test passed" << std::endl;
+  std::cout << " All ok " << std::endl;
+  // ------------------------------------------------------------------------
+}
+
+
+void SetTrack(CbmTransport* run, Double_t beamRotY, Int_t pdgid, Double_t x, Double_t y, Double_t z)
+{
+  TVector3 v;
+  v.SetXYZ(x, y, z);
+  v.RotateY(-beamRotY * acos(-1.) / 180.);
+  cout << "X " << v.X() << " Y " << v.Y() << " Z " << v.Z() << endl;
+
+  run->AddInput(new FairParticleGenerator(pdgid, 1, v.X(), v.Y(), v.Z()));  // single electron along beam axis
+}
diff --git a/macro/qa/qa_compare_ca.C b/macro/qa/qa_compare_ca.C
index 4204ae75ff35d9ca3bf897884f478b1af75b674b..3bc59effd5b419a213df06a3f32c8ef16d909923 100644
--- a/macro/qa/qa_compare_ca.C
+++ b/macro/qa/qa_compare_ca.C
@@ -36,7 +36,7 @@ int qa_compare_ca(
   pQaChecker->SetFromYAML(configName);      // Read file-object map
 
   //// ----- Run comparision routine
-  pQaChecker->Process("PB");
+  pQaChecker->Process("P");
 
   //// ----- Scan results
   bool res = pQaChecker->Scan();  // true - objects are the same, false - objects differ
diff --git a/reco/L1/CMakeLists.txt b/reco/L1/CMakeLists.txt
index 4f849847864423aae9a64785775450b71a7ca249..f13f88b3ac3afdde0a7c110cc9eeacbfc10a6960 100644
--- a/reco/L1/CMakeLists.txt
+++ b/reco/L1/CMakeLists.txt
@@ -69,6 +69,7 @@ set(SRCS
   L1Algo/utils/L1AlgoPulls.cxx
   L1Algo/utils/CaUvConverter.cxx
 
+  catools/CaToolsHitRecord.cxx
   catools/CaToolsMCData.cxx
   catools/CaToolsMCPoint.cxx
   catools/CaToolsMCTrack.cxx
diff --git a/reco/L1/CbmCaMCModule.cxx b/reco/L1/CbmCaMCModule.cxx
index 25632feb4c7b1a4b9dbdc21b3a330113cc4b2b15..44c364231074f6c49929aa4f619d7c2437f33f03 100644
--- a/reco/L1/CbmCaMCModule.cxx
+++ b/reco/L1/CbmCaMCModule.cxx
@@ -50,6 +50,13 @@ bool MCModule::InitRun()
 try {
   LOG(info) << "CA MC Module: initializing CA tracking Monte-Carlo module... ";
 
+  // Detector interfaces
+  if (fvbUseDet[L1DetectorID::kMvd]) { fvpDetInterface[L1DetectorID::kMvd] = CbmMvdTrackingInterface::Instance(); }
+  if (fvbUseDet[L1DetectorID::kSts]) { fvpDetInterface[L1DetectorID::kSts] = CbmStsTrackingInterface::Instance(); }
+  if (fvbUseDet[L1DetectorID::kMuch]) { fvpDetInterface[L1DetectorID::kMuch] = CbmMuchTrackingInterface::Instance(); }
+  if (fvbUseDet[L1DetectorID::kTrd]) { fvpDetInterface[L1DetectorID::kTrd] = CbmTrdTrackingInterface::Instance(); }
+  if (fvbUseDet[L1DetectorID::kTof]) { fvpDetInterface[L1DetectorID::kTof] = CbmTofTrackingInterface::Instance(); }
+
   auto fairManager = FairRootManager::Instance();
   assert(fairManager);
 
@@ -89,6 +96,7 @@ try {
   InitMatchesBranch("TrdHitMatch", L1DetectorID::kTrd);
   InitMatchesBranch("TofHitMatch", L1DetectorID::kTof);
 
+
   // Check initialization
   this->CheckInit();
 
@@ -158,6 +166,7 @@ void MCModule::ProcessEvent(CbmEvent*) {}
 //
 void MCModule::InitTrackInfo()
 {
+  // FIXME: Reconstructable criteria initialization should be verified!
   // ----- Initialize stations arrangement and hit indexes
   fpMCData->InitTrackInfo(*fpvQaHits);
 
@@ -169,7 +178,7 @@ void MCModule::InitTrackInfo()
     isRec &= aTrk.GetP() > CbmL1Constants::MinRecoMom;
 
     // Cut on max number of points on station
-    isRec &= aTrk.GetMaxNofPointsOnStation() <= 4;
+    isRec &= aTrk.GetMaxNofPointsOnStation() <= 3;
 
     bool isAdd = isRec;  // is track additional
 
@@ -360,18 +369,19 @@ void MCModule::ReadMCPointsForDetector<L1DetectorID::kTof>()
 
       // Select station index for a point
       double zPos     = pExtPoint->GetZ();
-      float bestDist  = 1000.;  // arbitrary large length [cm]
-      int iStSelected = -1;     // local geometry index of TOF station
-
-      for (int iStLocGeo = 0; iStLocGeo < nTofStationsGeo; ++iStLocGeo) {
-        int iStActive = fpParameters->GetStationIndexActive(iStLocGeo, L1DetectorID::kTof);
-        if (iStActive < 0) { continue; }  // station is not used in tracking
-        const L1Station& station = fpParameters->GetStation(iStActive);
-        if (fabs(zPos - station.fZ[0]) < bestDist) {
-          bestDist    = fabs(zPos - station.fZ[0]);
-          iStSelected = iStLocGeo;
-        }
-      }
+      //float bestDist  = 1000.;  // arbitrary large length [cm]
+      //int iStSelected = -1;     // local geometry index of TOF station
+
+      //for (int iStLocGeo = 0; iStLocGeo < nTofStationsGeo; ++iStLocGeo) {
+      //  int iStActive = fpParameters->GetStationIndexActive(iStLocGeo, L1DetectorID::kTof);
+      //  if (iStActive < 0) { continue; }  // station is not used in tracking
+      //  const L1Station& station = fpParameters->GetStation(iStActive);
+      //  if (fabs(zPos - station.fZ[0]) < bestDist) {
+      //    bestDist    = fabs(zPos - station.fZ[0]);
+      //    iStSelected = iStLocGeo;
+      //  }
+      //}
+      int iStSelected = CbmTofTrackingInterface::Instance()->GetTrackingStationIndex(pExtPoint->GetDetectorID());
 
       int iTrack = fpMCData->FindInternalTrackIndex(pExtPoint->GetTrackID(), iEvent, iFile);
       assert(iTrack > -1);
diff --git a/reco/L1/CbmCaMCModule.h b/reco/L1/CbmCaMCModule.h
index d02e0339cf904511b493c7c81906d09cf7d96cdc..ba885d05fb0936446721e7fb0f05965842776f37 100644
--- a/reco/L1/CbmCaMCModule.h
+++ b/reco/L1/CbmCaMCModule.h
@@ -19,11 +19,16 @@
 #include "CbmMCTrack.h"
 #include "CbmMatch.h"
 #include "CbmMuchPoint.h"
+#include "CbmMuchTrackingInterface.h"
 #include "CbmMvdPoint.h"
+#include "CbmMvdTrackingInterface.h"
 #include "CbmStsPoint.h"
+#include "CbmStsTrackingInterface.h"
 #include "CbmTimeSlice.h"
 #include "CbmTofPoint.h"
+#include "CbmTofTrackingInterface.h"
 #include "CbmTrdPoint.h"
+#include "CbmTrdTrackingInterface.h"
 
 #include "TClonesArray.h"
 #include "TDatabasePDG.h"
@@ -233,6 +238,8 @@ namespace cbm::ca
     CbmMCDataObject* fpMCEventHeader = nullptr;  ///< MC event header
     CbmMCDataArray* fpMCTracks       = nullptr;  ///< MC tracks input
 
+    DetIdArr_t<CbmTrackingDetectorInterfaceBase*> fvpDetInterface = {{nullptr}};  ///< Tracking detector interface
+
     DetIdArr_t<CbmMCDataArray*> fvpBrPoints   = {{nullptr}};  ///< Array of points vs. detector
     DetIdArr_t<TClonesArray*> fvpBrHitMatches = {{nullptr}};  ///< Array of hit match branches vs. detector
 
@@ -325,85 +332,52 @@ std::optional<::ca::tools::MCPoint> cbm::ca::MCModule::FillMCPoint(int iExtId, i
   TVector3 posOut;            // Position at exist of station [cm]
   TVector3 momIn;             // 3-momentum at entrance to station [GeV/c]
   TVector3 momOut;            // 3-momentum at exit of station [GeV/c]
-  double time = undef::kD;    // Time of MC point (after beginning of the event) [ns]
-  int iTmcExt = undef::kI32;  // Track ID in the external container
 
   auto* pBrPoints = fvpBrPoints[DetID];
 
+  PointTypes_t::at<DetID>* pExtPoint = dynamic_cast<PointTypes_t::at<DetID>*>(pBrPoints->Get(iFile, iEvent, iExtId));
+  if (!pExtPoint) {
+    LOG(warn) << "CbmCaMCModule: " << kDetName[DetID] << " MC point with iExtId = " << iExtId << ", iEvent = " << iEvent
+              << ", iFile = " << iFile << " does not exist";
+    return std::nullopt;
+  }
   if constexpr (L1DetectorID::kMvd == DetID) {
-    auto* pExtPoint = dynamic_cast<CbmMvdPoint*>(pBrPoints->Get(iFile, iEvent, iExtId));
-    if (!pExtPoint) {
-      LOG(warn) << "CbmCaMCModule: MVD MC point with iExtId = " << iExtId << ", iEvent = " << iEvent
-                << ", iFile = " << iFile << " does not exist";
-      return std::nullopt;
-    }
     pExtPoint->Position(posIn);
     pExtPoint->PositionOut(posOut);
     pExtPoint->Momentum(momIn);
     pExtPoint->MomentumOut(momOut);
-    time    = pExtPoint->GetTime();
-    iTmcExt = pExtPoint->GetTrackID();
   }
   // STS
   else if constexpr (L1DetectorID::kSts == DetID) {
-    auto* pExtPoint = dynamic_cast<CbmStsPoint*>(pBrPoints->Get(iFile, iEvent, iExtId));
-    if (!pExtPoint) {
-      LOG(warn) << "CbmCaMCModule: STS MC point with iExtId = " << iExtId << ", iEvent = " << iEvent
-                << ", iFile = " << iFile << " does not exist";
-      return std::nullopt;
-    }
     pExtPoint->Position(posIn);
     pExtPoint->PositionOut(posOut);
     pExtPoint->Momentum(momIn);
     pExtPoint->MomentumOut(momOut);
-    time    = pExtPoint->GetTime();
-    iTmcExt = pExtPoint->GetTrackID();
   }
   // MuCh
   else if constexpr (L1DetectorID::kMuch == DetID) {
-    auto* pExtPoint = dynamic_cast<CbmMuchPoint*>(pBrPoints->Get(iFile, iEvent, iExtId));
-    if (!pExtPoint) {
-      LOG(warn) << "CbmCaMCModule: MuCh MC point with iExtId = " << iExtId << ", iEvent = " << iEvent
-                << ", iFile = " << iFile << " does not exist";
-      return std::nullopt;
-    }
     pExtPoint->Position(posIn);
     pExtPoint->PositionOut(posOut);
     pExtPoint->Momentum(momIn);
     pExtPoint->Momentum(momOut);
-    time    = pExtPoint->GetTime();
-    iTmcExt = pExtPoint->GetTrackID();
   }
   // TRD
   else if constexpr (L1DetectorID::kTrd == DetID) {
-    auto* pExtPoint = dynamic_cast<CbmTrdPoint*>(pBrPoints->Get(iFile, iEvent, iExtId));
-    if (!pExtPoint) {
-      LOG(warn) << "CbmCaMCModule: TRD MC point with iExtId = " << iExtId << ", iEvent = " << iEvent
-                << ", iFile = " << iFile << " does not exist";
-      return std::nullopt;
-    }
     pExtPoint->Position(posIn);
     pExtPoint->PositionOut(posOut);
     pExtPoint->Momentum(momIn);
     pExtPoint->MomentumOut(momOut);
-    time    = pExtPoint->GetTime();
-    iTmcExt = pExtPoint->GetTrackID();
   }
   // TOF
   else if constexpr (L1DetectorID::kTof == DetID) {
-    auto* pExtPoint = dynamic_cast<CbmTofPoint*>(pBrPoints->Get(iFile, iEvent, iExtId));
-    if (!pExtPoint) {
-      LOG(warn) << "CbmCaMCModule: TOF MC point with iExtId = " << iExtId << ", iEvent = " << iEvent
-                << ", iFile = " << iFile << " does not exist";
-      return std::nullopt;
-    }
     pExtPoint->Position(posIn);
     pExtPoint->Position(posOut);
     pExtPoint->Momentum(momIn);
     pExtPoint->Momentum(momOut);
-    time    = pExtPoint->GetTime();
-    iTmcExt = pExtPoint->GetTrackID();
   }
+  double time = pExtPoint->GetTime();
+  int iTmcExt = pExtPoint->GetTrackID();
+
   if (iTmcExt < 0) {
     LOG(warn) << "CbmCaMCModule: For MC point with iExtId = " << iExtId << ", iEvent = " << iEvent
               << ", iFile = " << iFile << " MC track is undefined (has ID = " << iTmcExt << ')';
@@ -413,35 +387,12 @@ std::optional<::ca::tools::MCPoint> cbm::ca::MCModule::FillMCPoint(int iExtId, i
   TVector3 momMid = 0.5 * (momIn + momOut);
 
   // // ----- Get station index
-  int stationID    = undef::kI32;  // Index of station in the array of active tracking stations
-  int nStationsGeo = fpParameters->GetNstationsGeometry(DetID);
-  // MVD, STS TODO: Try to extend for MuCh and TRD
-  if constexpr (L1DetectorID::kMvd == DetID || L1DetectorID::kSts == DetID) {
-    // Determine active station global index
-    double bestDist = 1.e+20;
-    for (int iStLocGeo = 0; iStLocGeo < nStationsGeo; ++iStLocGeo) {
-      int iStActive = fpParameters->GetStationIndexActive(iStLocGeo, DetID);
-      if (iStActive < 0) { continue; }
-      const L1Station& station = fpParameters->GetStation(iStActive);
-      double dist              = posIn.Z() - station.fZ[0];
-      if (fabs(dist) < fabs(bestDist)) {
-        bestDist  = dist;
-        stationID = iStActive;
-      }
-    }
-  }
-  // MuCh, TRD
-  else if constexpr (L1DetectorID::kMuch == DetID || L1DetectorID::kTrd == DetID) {
-    // Offset for MuCh - 2.5 cm, for TRD - 20. cm. TODO: Where did these values came from?
-    double offset = (L1DetectorID::kMuch == DetID) ? 2.5 : 20.;
-    for (int iStLocGeo = 0; iStLocGeo < nStationsGeo; ++iStLocGeo) {
-      int iStActive = fpParameters->GetStationIndexActive(iStLocGeo, DetID);
-      if (iStActive < 0) { continue; }
-      const L1Station& station = fpParameters->GetStation(iStActive);
-      if (posMid.Z() > station.fZ[0] - offset) { stationID = iStActive; }
-    }
-  }
+  int iStLoc    = fvpDetInterface[DetID]->GetTrackingStationIndex(pExtPoint);
+  int stationID = fpParameters->GetStationIndexActive(iStLoc, DetID);
 
+  if constexpr (L1DetectorID::kTof != DetID) {     // ????
+    if (stationID == -1) { return std::nullopt; }  // Skip points from inactive stations
+  }
 
   // Update point time with event time
   time += fpMCEventList->GetEventTime(iEvent, iFile);
diff --git a/reco/L1/CbmCaTimeSliceReader.cxx b/reco/L1/CbmCaTimeSliceReader.cxx
index b47900dccecb67d16432900453f7bfbe6ec49fbe..94d7ff9af8644e06f9fa61cc8029ba97dbae27d3 100644
--- a/reco/L1/CbmCaTimeSliceReader.cxx
+++ b/reco/L1/CbmCaTimeSliceReader.cxx
@@ -422,6 +422,7 @@ void TimeSliceReader::StoreHitRecord(const HitRecord& hitRecord)
     aHitQa.iStation = hitRecord.fStaId;
     aHitQa.x        = hitRecord.fX;
     aHitQa.y        = hitRecord.fY;
+    aHitQa.z        = hitRecord.fZ;
     aHitQa.dx       = sqrt(hitRecord.fDx2);
     aHitQa.dy       = sqrt(hitRecord.fDy2);
     aHitQa.dxy      = hitRecord.fDxy;
diff --git a/reco/L1/CbmCaTimeSliceReader.h b/reco/L1/CbmCaTimeSliceReader.h
index 966abdefefbb644850d529a47e13680662149f58..271f3c4286275b4cce0a65c91aeac69476099af1 100644
--- a/reco/L1/CbmCaTimeSliceReader.h
+++ b/reco/L1/CbmCaTimeSliceReader.h
@@ -299,8 +299,10 @@ int cbm::ca::TimeSliceReader::ReadHitsForDetector()
     }
 
     // Save hit to data structures
-    this->StoreHitRecord(hitRecord);
-    ++nHitsStored;
+    if (hitRecord.Accept()) {
+      this->StoreHitRecord(hitRecord);
+      ++nHitsStored;
+    }
   }  // iH
 
   return nHitsStored;
diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx
index bf0a7c1cdd5f357226fbb5d2b540c6cc263a6fae..3b57facba89b7ebff79aa389d65f2a1670e330ac 100644
--- a/reco/L1/CbmL1.cxx
+++ b/reco/L1/CbmL1.cxx
@@ -663,6 +663,11 @@ InitStatus CbmL1::Init()
   fMonitor.SetKeyName(EMonitorKey::kEvent, "N events");
   fMonitor.SetKeyName(EMonitorKey::kRecoTrack, "N reco tracks");
   fMonitor.SetKeyName(EMonitorKey::kRecoHit, "N hits");
+  fMonitor.SetKeyName(EMonitorKey::kDiscardedHitMvd, "N discarded hits in MVD");
+  fMonitor.SetKeyName(EMonitorKey::kDiscardedHitSts, "N discarded hits in STS");
+  fMonitor.SetKeyName(EMonitorKey::kDiscardedHitMuch, "N discarded hits in MUCH");
+  fMonitor.SetKeyName(EMonitorKey::kDiscardedHitTrd, "N discarded hits in TRD");
+  fMonitor.SetKeyName(EMonitorKey::kDiscardedHitTof, "N discarded hits in TOF");
   fMonitor.SetRatioKeys({EMonitorKey::kEvent, EMonitorKey::kRecoTrack});
   fMonitor.Reset();
 
@@ -811,6 +816,44 @@ void CbmL1::Reconstruct(CbmEvent* event)
     //
 
     TrackMatch();
+
+    // ****** DEBUG: BEGIN
+    if constexpr (0) {
+      using std::setw;
+      {
+        LOG(info) << "---------- Reco track sample";
+        int id = 0;
+        if (fvRecoTracks.size()) { LOG(info) << setw(4) << "No." << ' ' << fvRecoTracks[0].ToString(3, true); }
+        for (const auto& trk : fvRecoTracks) {
+          LOG(info) << setw(4) << (id++) << ' ' << trk.ToString(3);
+        }
+      }
+      {
+        LOG(info) << "---------- Reco hit sample";
+        int id = 0;
+        if (fvHitDebugInfo.size()) { LOG(info) << setw(4) << "No." << ' ' << fvHitDebugInfo[0].ToString(3, true); }
+        for (const auto& h : fvHitDebugInfo) {
+          LOG(info) << setw(4) << (id++) << ' ' << h.ToString(3);
+        }
+      }
+      if (fPerformance) {
+        LOG(info) << "---------- MC tracks sample";
+        int id = 0;
+        if (fvMCTracks.size()) { LOG(info) << setw(4) << "No." << ' ' << fvMCTracks[0].ToString(3, true); }
+        for (const auto& trk : fvMCTracks) {
+          if (trk.Hits.size() || trk.Points.size()) { LOG(info) << setw(4) << (id++) << ' ' << trk.ToString(3); }
+        }
+      }
+      if (fPerformance) {
+        LOG(info) << "---------- MC points sample";
+        int id = 0;
+        if (fvMCPoints.size()) { LOG(info) << setw(4) << "No." << ' ' << fvMCPoints[0].ToString(3, true); }
+        for (const auto& p : fvMCPoints) {
+          LOG(info) << setw(4) << (id++) << ' ' << p.ToString(3);
+        }
+      }
+    }
+    // ****** DEBUG: END
     EfficienciesPerformance();
     HistoPerformance();
     TrackFitPerformance();
diff --git a/reco/L1/CbmL1.h b/reco/L1/CbmL1.h
index ce0b0b4f4d611a8c353dd95db28dbeef8b6dbd57..b3e751dbe64a2ff9a03d9a13c7033b3bbd30d4e3 100644
--- a/reco/L1/CbmL1.h
+++ b/reco/L1/CbmL1.h
@@ -261,9 +261,14 @@ public:
   // Tracking monitor (prototype)
   enum class EMonitorKey
   {
-    kEvent,
-    kRecoTrack,
-    kRecoHit,
+    kEvent,             ///< Number of processed events
+    kRecoTrack,         ///< Number of reconstructed tracks
+    kRecoHit,           ///< Number of reconstructed hits
+    kDiscardedHitMvd,   ///< Number of discarded hits in MVD
+    kDiscardedHitSts,   ///< Number of discarded hits in STS
+    kDiscardedHitMuch,  ///< Number of discarded hits in MuCh
+    kDiscardedHitTrd,   ///< Number of discarded hits in TRD
+    kDiscardedHitTof,   ///< Number of discarded hits in TOF
     kEND
   };
 
diff --git a/reco/L1/CbmL1Constants.h b/reco/L1/CbmL1Constants.h
index cb17176fdaa22eabe896e9944056b9f5bcfebe0e..da461cc131442b3d0dcdc0f1061f6104ad576ce2 100644
--- a/reco/L1/CbmL1Constants.h
+++ b/reco/L1/CbmL1Constants.h
@@ -14,4 +14,6 @@ namespace CbmL1Constants
   const int MinNStations  = 4;    // min number of stations on track to be reconstructable
 }  // namespace CbmL1Constants
 
+// FIXME: This values should be read from iterations!
+
 #endif
diff --git a/reco/L1/CbmL1Hit.h b/reco/L1/CbmL1Hit.h
index 92b76f8770f3458d57cb2c7a111c84f007639396..d6090ad65b3696b16494f078e7a1af75bb22c0f2 100644
--- a/reco/L1/CbmL1Hit.h
+++ b/reco/L1/CbmL1Hit.h
@@ -79,6 +79,9 @@ public:
   /// @brief Gets y component of position [cm]
   double GetY() const { return y; }
 
+  /// @brief Gets z component of position [cm]
+  double GetZ() const { return z; }
+
   /// @brief Sets index of matched MC point
   /// @param pointID  Internal index of MC point
   void SetMCPointIndex(int pointID) { fPointID = pointID; }
@@ -92,6 +95,7 @@ public:
     using std::setfill;
     using std::setw;
     std::stringstream msg;
+    msg.precision(4);
     if (header) {
       msg << setw(8) << setfill(' ') << "ext. ID" << ' ';
       msg << setw(8) << setfill(' ') << "int. ID" << ' ';
@@ -100,6 +104,7 @@ public:
       msg << setw(8) << setfill(' ') << "MC p. ID" << ' ';
       msg << setw(14) << setfill(' ') << "x [cm]" << ' ';
       msg << setw(14) << setfill(' ') << "y [cm]" << ' ';
+      msg << setw(14) << setfill(' ') << "z [cm]" << ' ';
       msg << setw(14) << setfill(' ') << "time [ns]" << ' ';
       if (verbose > 0) {
         msg << setw(14) << setfill(' ') << "dx [cm]" << ' ';
@@ -116,6 +121,7 @@ public:
       msg << setw(8) << setfill(' ') << GetMCPointIndex() << ' ';
       msg << setw(14) << setfill(' ') << x << ' ';
       msg << setw(14) << setfill(' ') << y << ' ';
+      msg << setw(14) << setfill(' ') << z << ' ';
       msg << setw(14) << setfill(' ') << time << ' ';
       if (verbose > 0) {
         msg << setw(14) << setfill(' ') << dx << ' ';
@@ -134,6 +140,7 @@ public:
   int Det;                                                     ///< detector subsystem ID
   double x;                                                    ///< x coordinate of position [cm]
   double y;                                                    ///< y coordinate of position [cm]
+  double z;                                                    ///< z coordinate of position [cm]
   double time;                                                 ///< hit time [ns]
   double dx;                                                   ///< x coordinate error [cm]
   double dy;                                                   ///< y coordinate error [cm]
diff --git a/reco/L1/CbmL1MCPoint.h b/reco/L1/CbmL1MCPoint.h
index 3760a0a4e0fa87fee80287068e9059d3b8775a97..5055de0a1c0148519d9c82f4aa9bb8017eea6562 100644
--- a/reco/L1/CbmL1MCPoint.h
+++ b/reco/L1/CbmL1MCPoint.h
@@ -78,47 +78,62 @@ struct CbmL1MCPoint {
     if (verbose < 1) { return std::string(); }
 
     std::stringstream msg;
+    msg.precision(4);
     if (printHeader) {
       if (verbose > 0) {
-        msg << std::setw(10) << std::setfill(' ') << "track ID" << ' ';
-        msg << std::setw(10) << std::setfill(' ') << "mother ID" << '|';
-        msg << std::setw(10) << std::setfill(' ') << "station ID" << '|';
-        msg << std::setw(10) << std::setfill(' ') << "PDG" << ' ';
-        msg << std::setw(10) << std::setfill(' ') << "m [GeV/c2]" << ' ';
-        msg << std::setw(10) << std::setfill(' ') << "q [e]" << '|';
-        msg << std::setw(14) << std::setfill(' ') << "t [ns]" << ' ';
-        msg << std::setw(14) << std::setfill(' ') << "x [cm]" << ' ';
-        msg << std::setw(14) << std::setfill(' ') << "y [cm]" << ' ';
-        msg << std::setw(14) << std::setfill(' ') << "z [cm]" << '|';
+        msg << std::setw(10) << "track ID" << ' ';
+        msg << std::setw(10) << "mother ID" << '|';
+        msg << std::setw(10) << "station ID" << '|';
+        msg << std::setw(10) << "PDG" << ' ';
+        if (verbose > 3) {
+          msg << std::setw(10) << "m [GeV/c2]" << ' ';
+          msg << std::setw(10) << "q [e]" << '|';
+        }
+        msg << std::setw(14) << "t [ns]" << ' ';
+        msg << std::setw(14) << "x [cm]" << ' ';
+        msg << std::setw(14) << "y [cm]" << ' ';
+        msg << std::setw(14) << "z [cm]" << '|';
         if (verbose > 1) {
-          msg << std::setw(14) << std::setfill(' ') << "zIn [cm]" << ' ';
-          msg << std::setw(14) << std::setfill(' ') << "zOut [cm]" << '|';
-          msg << std::setw(14) << std::setfill(' ') << "p [GeV/c]" << '|';
-          msg << std::setw(10) << std::setfill(' ') << "point ID" << ' ';
-          msg << std::setw(10) << std::setfill(' ') << "event ID" << ' ';
-          msg << std::setw(10) << std::setfill(' ') << "file ID" << ' ';
+          msg << std::setw(14) << "zIn [cm]" << ' ';
+          msg << std::setw(14) << "zOut [cm]" << '|';
+          msg << std::setw(14) << "p [GeV/c]" << '|';
+          msg << std::setw(10) << "point ID" << ' ';
+          if (verbose > 3) {
+            msg << std::setw(10) << "event ID" << ' ';
+            msg << std::setw(10) << "file ID" << ' ';
+          }
+          msg << std::setw(16) << "hit indices" << ' ';
         }
       }
     }
     else {
       if (verbose > 0) {
-        msg << std::setw(10) << std::setfill(' ') << ID << ' ';
-        msg << std::setw(10) << std::setfill(' ') << mother_ID << '|';
-        msg << std::setw(10) << std::setfill(' ') << iStation << '|';
-        msg << std::setw(10) << std::setfill(' ') << pdg << ' ';
-        msg << std::setw(10) << std::setfill(' ') << mass << ' ';
-        msg << std::setw(10) << std::setfill(' ') << q << '|';
-        msg << std::setw(14) << std::setfill(' ') << time << ' ';
-        msg << std::setw(14) << std::setfill(' ') << x << ' ';
-        msg << std::setw(14) << std::setfill(' ') << y << ' ';
-        msg << std::setw(14) << std::setfill(' ') << z << '|';
+        msg << std::setw(10) << ID << ' ';
+        msg << std::setw(10) << mother_ID << '|';
+        msg << std::setw(10) << iStation << '|';
+        msg << std::setw(10) << pdg << ' ';
+        if (verbose > 3) {
+          msg << std::setw(10) << mass << ' ';
+          msg << std::setw(10) << q << '|';
+        }
+        msg << std::setw(14) << time << ' ';
+        msg << std::setw(14) << x << ' ';
+        msg << std::setw(14) << y << ' ';
+        msg << std::setw(14) << z << '|';
         if (verbose > 1) {
-          msg << std::setw(14) << std::setfill(' ') << zIn << ' ';
-          msg << std::setw(14) << std::setfill(' ') << zOut << '|';
-          msg << std::setw(14) << std::setfill(' ') << p << '|';
-          msg << std::setw(10) << std::setfill(' ') << pointId << ' ';
-          msg << std::setw(10) << std::setfill(' ') << event << ' ';
-          msg << std::setw(10) << std::setfill(' ') << file << ' ';
+          msg << std::setw(14) << zIn << ' ';
+          msg << std::setw(14) << zOut << '|';
+          msg << std::setw(14) << p << '|';
+          msg << std::setw(10) << pointId << ' ';
+          if (verbose > 3) {
+            msg << std::setw(10) << event << ' ';
+            msg << std::setw(10) << file << ' ';
+          }
+          std::stringstream msgHits;
+          for (int iH : hitIds) {
+            msgHits << iH << ' ';
+          }
+          msg << std::setw(16) << msgHits.str() << ' ';
         }
       }
     }
diff --git a/reco/L1/CbmL1ReadEvent.cxx b/reco/L1/CbmL1ReadEvent.cxx
index d8248eb8440d86d2452c542c4246aef128ab056a..df15dbfcc10116f5405f83b5bd69a02194bbec2d 100644
--- a/reco/L1/CbmL1ReadEvent.cxx
+++ b/reco/L1/CbmL1ReadEvent.cxx
@@ -69,7 +69,7 @@ struct TmpHit {
   int iStripF;          ///< index of front strip
   int iStripB;          ///< index of back strip
   int iStation;         ///< index of station
-  int64_t fDataStream;  ///< global index of detector module
+  int64_t fDataStream;  ///< global index of detector module (4 left bits -- station number, other - address)
   int ExtIndex;         ///< index of hit in the external TClonesArray array (NOTE: negative for MVD)
   double x;             ///< position of hit along x axis [cm]
   double y;             ///< position of hit along y axis [cm]
@@ -85,6 +85,44 @@ struct TmpHit {
   double rangeT;        ///< hit range in T [ns]
 
   int Det;
+
+  static constexpr bool kVerboseAccept = true;
+  /// @brief  Tests quality of the hit (eg., if one of its quantity is nan)
+  /// @return true   Hit is passed and send to the CaCore
+  /// @return false  Hit is discarded due to corrupted quantity values
+  bool IfAccept() const
+  {
+    if constexpr (kVerboseAccept) {
+      std::stringstream msg;
+      if (std::isnan(x) || std::isinf(x)) { msg << ", x = " << x; }
+      if (std::isnan(y) || std::isinf(y)) { msg << ", y = " << y; }
+      if (std::isnan(z) || std::isinf(z)) { msg << ", z = " << z; }
+      if (std::isnan(time) || std::isinf(time)) { msg << ", t = " << time; }
+      if (std::isnan(dx2) || std::isinf(dx2)) { msg << ", dx2 = " << dx2; }
+      if (std::isnan(dy2) || std::isinf(dy2)) { msg << ", dy2 = " << dy2; }
+      if (std::isnan(dxy) || std::isinf(dxy)) { msg << ", dxy = " << dxy; }
+      if (std::isnan(dt2) || std::isinf(dt2)) { msg << ", dt2 = " << dt2; }
+      const auto& sMsg = msg.str();
+      if (sMsg.size()) {
+        LOG(warn) << "CbmL1: Discarding hit " << ExtIndex << ": det = " << Det
+                  << ", addr = " << static_cast<int32_t>(fDataStream) << ", " << sMsg;
+        return false;
+      }
+    }
+    else {
+      bool res = true;
+      res      = res && !(std::isnan(x) || std::isinf(x));
+      res      = res && !(std::isnan(y) || std::isinf(y));
+      res      = res && !(std::isnan(z) || std::isinf(z));
+      res      = res && !(std::isnan(time) || std::isinf(time));
+      res      = res && !(std::isnan(dx2) || std::isinf(dx2));
+      res      = res && !(std::isnan(dy2) || std::isinf(dy2));
+      res      = res && !(std::isnan(dt2) || std::isinf(dt2));
+      res      = res && !(std::isnan(dxy) || std::isinf(dxy));
+      return res;
+    }
+    return true;
+  }
 };
 
 
@@ -187,22 +225,10 @@ void CbmL1::ReadEvent(CbmEvent* event)
         for (Int_t iMC = 0; iMC < fNpointsMvdInEvent; iMC++) {
           CbmL1MCPoint MC;
           if (!ReadMCPoint(&MC, iMC, iFile, iEvent, 0)) {
-            MC.iStation          = -1;
-            const L1Station* sta = fpAlgo->GetParameters()->GetStations().begin();
-            double bestDist      = 1.e20;
-            for (Int_t iSt = 0; iSt < fNMvdStationsGeom; iSt++) {
-              // use z_in since z_out is sometimes very wrong
-              // due to a problem in transport
-              int iStActive = fpAlgo->GetParameters()->GetStationIndexActive(iSt, L1DetectorID::kMvd);
-              if (iStActive == -1) { continue; }
-              double d = (MC.zIn - sta[iStActive].fZ[0]);
-              if (fabs(d) < fabs(bestDist)) {
-                bestDist    = d;
-                MC.iStation = iStActive;
-              }
-            }
-            assert(MC.iStation >= 0);
-            if (fabs(maxDeviation) < fabs(bestDist)) { maxDeviation = bestDist; }
+            CbmMvdPoint* pPoint = static_cast<CbmMvdPoint*>(fpMvdPoints->Get(iFile, iEvent, iMC));
+            int iStLoc          = CbmMvdTrackingInterface::Instance()->GetTrackingStationIndex(pPoint);
+            MC.iStation         = fpAlgo->GetParameters()->GetStationIndexActive(iStLoc, L1DetectorID::kMvd);
+            if (MC.iStation < 0) { continue; }  // Reject MC points from inactive stations
             auto itTrack = fmMCTracksLinksMap.find(CbmL1LinkKey(MC.ID, iEvent, iFile));
             assert(itTrack != fmMCTracksLinksMap.cend());
             MC.ID = itTrack->second;
@@ -225,22 +251,10 @@ void CbmL1::ReadEvent(CbmEvent* event)
         for (Int_t iMC = 0; iMC < nMC; iMC++) {
           CbmL1MCPoint MC;
           if (!ReadMCPoint(&MC, iMC, iFile, iEvent, 1)) {
-            MC.iStation          = -1;
-            const L1Station* sta = fpAlgo->GetParameters()->GetStations().begin();
-            double bestDist      = 1.e20;
-            for (Int_t iSt = 0; iSt < fNStsStationsGeom; iSt++) {
-              int iStActive = fpAlgo->GetParameters()->GetStationIndexActive(iSt, L1DetectorID::kSts);
-              if (iStActive == -1) { continue; }
-              // use z_in since z_out is sometimes very wrong
-              // due to a problem in transport
-              double d = (MC.zIn - sta[iStActive].fZ[0]);
-              if (fabs(d) < fabs(bestDist)) {
-                bestDist    = d;
-                MC.iStation = iStActive;
-              }
-            }
-            assert(MC.iStation >= 0);
-            if (fabs(maxDeviation) < fabs(bestDist)) { maxDeviation = bestDist; }
+            auto* pPoint = static_cast<CbmStsPoint*>(fpStsPoints->Get(iFile, iEvent, iMC));
+            int iStLoc   = CbmStsTrackingInterface::Instance()->GetTrackingStationIndex(pPoint->GetDetectorID());
+            MC.iStation  = fpAlgo->GetParameters()->GetStationIndexActive(iStLoc, L1DetectorID::kSts);
+            if (MC.iStation < 0) { continue; }  // Reject MC points from inactive stations
             auto itTrack = fmMCTracksLinksMap.find(CbmL1LinkKey(MC.ID, iEvent, iFile));
             assert(itTrack != fmMCTracksLinksMap.cend());
             MC.ID = itTrack->second;
@@ -279,13 +293,9 @@ void CbmL1::ReadEvent(CbmEvent* event)
         for (Int_t iMC = 0; iMC < fpTrdPoints->Size(iFile, iEvent); iMC++) {
           CbmL1MCPoint MC;
           if (!ReadMCPoint(&MC, iMC, iFile, iEvent, 3)) {
-            MC.iStation          = -1;
-            const L1Station* sta = fpAlgo->GetParameters()->GetStations().begin();
-            for (Int_t iSt = 0; iSt < fNTrdStationsGeom; iSt++) {
-              int iStActive = fpAlgo->GetParameters()->GetStationIndexActive(iSt, L1DetectorID::kTrd);
-              if (iStActive < 0) { continue; }
-              if (MC.z > sta[iStActive].fZ[0] - 20.0) { MC.iStation = iStActive; }
-            }
+            auto* pPoint = static_cast<CbmTrdPoint*>(fpTrdPoints->Get(iFile, iEvent, iMC));
+            int iStLoc   = CbmTrdTrackingInterface::Instance()->GetTrackingStationIndex(pPoint->GetDetectorID());
+            MC.iStation  = fpAlgo->GetParameters()->GetStationIndexActive(iStLoc, L1DetectorID::kSts);
             if (MC.iStation < 0) { continue; }  // Reject MC points from inactive stations
             auto itTrack = fmMCTracksLinksMap.find(CbmL1LinkKey(MC.ID, iEvent, iFile));
             assert(itTrack != fmMCTracksLinksMap.cend());
@@ -342,30 +352,20 @@ void CbmL1::ReadEvent(CbmEvent* event)
             MC.iStation          = -1;
             const L1Station* sta = fpAlgo->GetParameters()->GetStations().begin();
 
-            float dist   = 1000;
-            int iSta     = -1;
-            int iStaGlob = -1;
-            for (int iSt = 0; iSt < fNTofStationsGeom; iSt++) {
-              int iStActive = fpAlgo->GetParameters()->GetStationIndexActive(iSt, L1DetectorID::kTof);
-              if (iStActive == -1) { continue; }
-              if (fabs(MC.z - sta[iStActive].fZ[0]) < dist) {
-                dist     = fabs(MC.z - sta[iStActive].fZ[0]);
-                iSta     = iSt;
-                iStaGlob = iStActive;
-              }
-            }
-
-            MC.iStation = fpAlgo->GetParameters()->GetStationIndexActive(iSta, L1DetectorID::kTof);
-            assert(MC.iStation >= 0);
+            auto* pPoint = static_cast<CbmTofPoint*>(fpTofPoints->Get(iFile, iEvent, iMC));
+            int iStLoc   = CbmTofTrackingInterface::Instance()->GetTrackingStationIndex(pPoint->GetDetectorID());
+            MC.iStation  = fpAlgo->GetParameters()->GetStationIndexActive(iStLoc, L1DetectorID::kTof);
+            if (MC.iStation < 0) { continue; }  // In case of inactive station
 
             auto itTrack = fmMCTracksLinksMap.find(CbmL1LinkKey(MC.ID, iEvent, iFile));
             assert(itTrack != fmMCTracksLinksMap.cend());
             int iTrack = itTrack->second;
-
-            if (iSta >= 0) {
-              if (fabs(sta[iStaGlob].fZ[0] - MC.z) < vTofPointToTrackdZ[iSta][iTrack]) {
-                vTofPointToTrack[iSta][iTrack]   = iMC;
-                vTofPointToTrackdZ[iSta][iTrack] = fabs(sta[iStaGlob].fZ[0] - MC.z);
+            if (iStLoc >= 0) {
+              // Select the closest point to the station
+              // NOTE: Probably, there is no sence to select the closest point to the station center
+              if (fabs(sta[MC.iStation].fZ[0] - MC.z) < vTofPointToTrackdZ[iStLoc][iTrack]) {
+                vTofPointToTrack[iStLoc][iTrack]   = iMC;
+                vTofPointToTrackdZ[iStLoc][iTrack] = fabs(sta[MC.iStation].fZ[0] - MC.z);
               }
             }
           }
@@ -477,10 +477,13 @@ void CbmL1::ReadEvent(CbmEvent* event)
       th.iMC         = fPerformance ? MatchHitWithMc<L1DetectorID::kMvd>(hitIndex) : -1;
       th.fDataStream = (static_cast<int64_t>(th.Det) << 60) | h->GetAddress();
       //if(  th.iMC >=0 ) // DEBUG !!!!
-      {
+      if (th.IfAccept()) {
         tmpHits.push_back(th);
         nMvdHits++;
       }
+      else {
+        fMonitor.Increment(EMonitorKey::kDiscardedHitMvd);
+      }
     }  // for j
   }    // if fpMvdHits
 
@@ -541,9 +544,13 @@ void CbmL1::ReadEvent(CbmEvent* event)
 
       th.iMC         = fPerformance ? MatchHitWithMc<L1DetectorID::kSts>(hitIndex) : -1;
       th.fDataStream = (static_cast<int64_t>(th.Det) << 60) | h->GetAddress();
-      tmpHits.push_back(th);
-      nStsHits++;
-
+      if (th.IfAccept()) {
+        tmpHits.push_back(th);
+        nStsHits++;
+      }
+      else {
+        fMonitor.Increment(EMonitorKey::kDiscardedHitSts);
+      }
     }  // for j
   }    // if fpStsHits
 
@@ -592,8 +599,13 @@ void CbmL1::ReadEvent(CbmEvent* event)
       }
       th.iMC         = fPerformance ? MatchHitWithMc<L1DetectorID::kMuch>(th.ExtIndex) : -1;
       th.fDataStream = (static_cast<int64_t>(th.Det) << 60) | h->GetAddress();
-      tmpHits.push_back(th);
-      nMuchHits++;
+      if (th.IfAccept()) {
+        tmpHits.push_back(th);
+        nMuchHits++;
+      }
+      else {
+        fMonitor.Increment(EMonitorKey::kDiscardedHitMuch);
+      }
 
     }  // for j
   }    // if listMuchHits
@@ -660,8 +672,13 @@ void CbmL1::ReadEvent(CbmEvent* event)
       th.iMC = fPerformance ? MatchHitWithMc<L1DetectorID::kTrd>(hitIndex) : -1;
 
       th.fDataStream = (static_cast<int64_t>(th.Det) << 60) | h->GetAddress();
-      tmpHits.push_back(th);
-      nTrdHits++;
+      if (th.IfAccept()) {
+        tmpHits.push_back(th);
+        nTrdHits++;
+      }
+      else {
+        fMonitor.Increment(EMonitorKey::kDiscardedHitTrd);
+      }
     }  // for fpTrdHits
   }    // read TRD hits
 
@@ -723,9 +740,13 @@ void CbmL1::ReadEvent(CbmEvent* event)
       th.iMC = fPerformance ? MatchHitWithMc<L1DetectorID::kTof>(hitIndex) : -1;
 
       th.fDataStream = (static_cast<int64_t>(th.Det) << 60) | h->GetAddress();
-      tmpHits.push_back(th);
-      nTofHits++;
-
+      if (th.IfAccept()) {
+        tmpHits.push_back(th);
+        nTofHits++;
+      }
+      else {
+        fMonitor.Increment(EMonitorKey::kDiscardedHitTof);
+      }
     }  // for j
   }    // if listTofHits
 
@@ -763,6 +784,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
     s.iStation = th.iStation;
     s.x        = th.x;
     s.y        = th.y;
+    s.z        = th.z;
     s.dx       = sqrt(th.dx2);
     s.dy       = sqrt(th.dy2);
     s.dxy      = th.dxy;
diff --git a/reco/L1/CbmL1Track.cxx b/reco/L1/CbmL1Track.cxx
index 271fd8649beebf522a7343eb66768f3cfd711488..d7aec0a2f65f2d179bec9cc0e5b03a85eeec13dc 100644
--- a/reco/L1/CbmL1Track.cxx
+++ b/reco/L1/CbmL1Track.cxx
@@ -36,8 +36,8 @@ std::string CbmL1Track::ToString(int verbose, bool header) const
     msg << setw(12) << setfill(' ') << GetTx() << ' ';
     msg << setw(8) << setfill(' ') << GetNofHits() << ' ';
     msg << setw(8) << setfill(' ') << GetNofMCTracks() << ' ';
-    msg << setw(12) << setfill(' ') << GetMatchedMCTrackIndex() << ' ';
     msg << setw(12) << setfill(' ') << (mcTracks.size() ? mcTracks[0]->ID : -1) << ' ';
+    msg << setw(12) << setfill(' ') << GetMatchedMCTrackIndex() << ' ';
     msg << setw(8) << setfill(' ') << IsGhost() << ' ';
     msg << setw(8) << setfill(' ') << GetMaxPurity() << ' ';
     msg << '\n';
diff --git a/reco/L1/catools/CaToolsHitRecord.cxx b/reco/L1/catools/CaToolsHitRecord.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2286b1273005a65672b19fd79344ee2d63dad3a6
--- /dev/null
+++ b/reco/L1/catools/CaToolsHitRecord.cxx
@@ -0,0 +1,54 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// \file   CbmCaHitRecord.h
+/// \brief  An implementation for cbm::ca::HitRecord structure
+/// \since  17.09.2023
+/// \author S.Zharko <s.zharko@gsi.de>
+
+#include "CaToolsHitRecord.h"
+
+#include "Logger.h"
+
+#include <sstream>
+
+#include <cmath>
+
+using ca::tools::HitRecord;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+bool HitRecord::Accept() const
+{
+  if constexpr (kVerboseAccept) {
+    std::stringstream msg;
+    if (std::isnan(fX) || std::isinf(fX)) { msg << ", x = " << fX; }
+    if (std::isnan(fY) || std::isinf(fY)) { msg << ", y = " << fY; }
+    if (std::isnan(fZ) || std::isinf(fZ)) { msg << ", z = " << fZ; }
+    if (std::isnan(fT) || std::isinf(fT)) { msg << ", t = " << fT; }
+    if (std::isnan(fDx2) || std::isinf(fDx2)) { msg << ", dx2 = " << fDx2; }
+    if (std::isnan(fDy2) || std::isinf(fDy2)) { msg << ", dy2 = " << fDy2; }
+    if (std::isnan(fDxy) || std::isinf(fDxy)) { msg << ", dxy = " << fDxy; }
+    if (std::isnan(fDt2) || std::isinf(fDt2)) { msg << ", dt2 = " << fDt2; }
+    const auto& sMsg = msg.str();
+    if (sMsg.size()) {
+      LOG(warn) << "HitRecord: Discarding hit " << fExtId << ": det = " << fDet
+                << ", addr = " << static_cast<int32_t>(fDataStream) << ", " << sMsg;
+      return false;
+    }
+  }
+  else {
+    bool res = true;
+    res      = res && !(std::isnan(fX) || std::isinf(fX));
+    res      = res && !(std::isnan(fY) || std::isinf(fY));
+    res      = res && !(std::isnan(fZ) || std::isinf(fZ));
+    res      = res && !(std::isnan(fT) || std::isinf(fT));
+    res      = res && !(std::isnan(fDx2) || std::isinf(fDx2));
+    res      = res && !(std::isnan(fDy2) || std::isinf(fDy2));
+    res      = res && !(std::isnan(fDt2) || std::isinf(fDt2));
+    res      = res && !(std::isnan(fDxy) || std::isinf(fDxy));
+    return res;
+  }
+  return true;
+}
diff --git a/reco/L1/catools/CaToolsHitRecord.h b/reco/L1/catools/CaToolsHitRecord.h
index c5d91fd958deb25cc7e7aa5f2a8444e067054c97..98d99a982a4609b5f8c1c3808492294654a44aba 100644
--- a/reco/L1/catools/CaToolsHitRecord.h
+++ b/reco/L1/catools/CaToolsHitRecord.h
@@ -38,6 +38,12 @@ namespace ca::tools
     int fStripF         = -2;   ///< index of front strip
     int fStripB         = -2;   ///< index of back strip
     int fDet            = -2;   ///< detector ID
+
+    /// @brief  Tests hit quality (for example, if all the quantities are not nan)
+    /// @return true   Hit is accepted
+    /// @return false  Hit is discarded
+    static constexpr bool kVerboseAccept = true;
+    bool Accept() const;
   };
 }  // namespace ca::tools
 
diff --git a/reco/L1/catools/CaToolsMCPoint.cxx b/reco/L1/catools/CaToolsMCPoint.cxx
index 3df6aaea5d13ed8cbd7ce203cd3ff577ac7272f6..fc3cc474c44bab32a9e3ef50208dee4f8d644691 100644
--- a/reco/L1/catools/CaToolsMCPoint.cxx
+++ b/reco/L1/catools/CaToolsMCPoint.cxx
@@ -22,49 +22,64 @@ std::string MCPoint::ToString(int verbose, bool printHeader) const
   if (verbose < 1) { return std::string(); }
 
   std::stringstream msg;
+  msg.precision(4);
   if (printHeader) {
     if (verbose > 0) {
-      msg << std::setw(10) << std::setfill(' ') << "track ID" << ' ';
-      msg << std::setw(10) << std::setfill(' ') << "mother ID" << '|';
-      msg << std::setw(10) << std::setfill(' ') << "station ID" << '|';
-      msg << std::setw(10) << std::setfill(' ') << "PDG" << ' ';
-      msg << std::setw(10) << std::setfill(' ') << "m [GeV/c2]" << ' ';
-      msg << std::setw(10) << std::setfill(' ') << "q [e]" << '|';
-      msg << std::setw(14) << std::setfill(' ') << "t [ns]" << ' ';
-      msg << std::setw(14) << std::setfill(' ') << "x [cm]" << ' ';
-      msg << std::setw(14) << std::setfill(' ') << "y [cm]" << ' ';
-      msg << std::setw(14) << std::setfill(' ') << "z [cm]" << '|';
+      msg << std::setw(10) << "track ID" << ' ';
+      msg << std::setw(10) << "mother ID" << '|';
+      msg << std::setw(10) << "station ID" << '|';
+      msg << std::setw(10) << "PDG" << ' ';
+      if (verbose > 3) {
+        msg << std::setw(10) << "m [GeV/c2]" << ' ';
+        msg << std::setw(10) << "q [e]" << '|';
+      }
+      msg << std::setw(14) << "t [ns]" << ' ';
+      msg << std::setw(14) << "x [cm]" << ' ';
+      msg << std::setw(14) << "y [cm]" << ' ';
+      msg << std::setw(14) << "z [cm]" << '|';
       if (verbose > 1) {
-        msg << std::setw(14) << std::setfill(' ') << "zIn [cm]" << ' ';
-        msg << std::setw(14) << std::setfill(' ') << "zOut [cm]" << '|';
-        msg << std::setw(14) << std::setfill(' ') << "p [GeV/c]" << '|';
-        msg << std::setw(10) << std::setfill(' ') << "point ID" << ' ';
-        msg << std::setw(10) << std::setfill(' ') << "point ID (ext)" << ' ';
-        msg << std::setw(10) << std::setfill(' ') << "event ID" << ' ';
-        msg << std::setw(10) << std::setfill(' ') << "file ID" << ' ';
+        msg << std::setw(14) << "zIn [cm]" << ' ';
+        msg << std::setw(14) << "zOut [cm]" << '|';
+        msg << std::setw(14) << "p [GeV/c]" << '|';
+        msg << std::setw(10) << "point ID" << ' ';
+        msg << std::setw(10) << "point ID (ext)" << ' ';
+        if (verbose > 3) {
+          msg << std::setw(10) << "event ID" << ' ';
+          msg << std::setw(10) << "file ID" << ' ';
+        }
+        msg << std::setw(16) << "hit indices" << ' ';
       }
     }
   }
   else {
     if (verbose > 0) {
-      msg << std::setw(10) << std::setfill(' ') << fTrackId << ' ';
-      msg << std::setw(10) << std::setfill(' ') << fMotherId << '|';
-      msg << std::setw(10) << std::setfill(' ') << fStationId << '|';
-      msg << std::setw(10) << std::setfill(' ') << fPdgCode << ' ';
-      msg << std::setw(10) << std::setfill(' ') << fMass << ' ';
-      msg << std::setw(10) << std::setfill(' ') << fCharge << '|';
-      msg << std::setw(14) << std::setfill(' ') << fTime << ' ';
-      msg << std::setw(14) << std::setfill(' ') << fPos[0] << ' ';
-      msg << std::setw(14) << std::setfill(' ') << fPos[1] << ' ';
-      msg << std::setw(14) << std::setfill(' ') << fPos[2] << '|';
+      msg << std::setw(10) << fTrackId << ' ';
+      msg << std::setw(10) << fMotherId << '|';
+      msg << std::setw(10) << fStationId << '|';
+      msg << std::setw(10) << fPdgCode << ' ';
+      if (verbose > 3) {
+        msg << std::setw(10) << fMass << ' ';
+        msg << std::setw(10) << fCharge << '|';
+      }
+      msg << std::setw(14) << fTime << ' ';
+      msg << std::setw(14) << fPos[0] << ' ';
+      msg << std::setw(14) << fPos[1] << ' ';
+      msg << std::setw(14) << fPos[2] << '|';
       if (verbose > 1) {
-        msg << std::setw(14) << std::setfill(' ') << fPosIn[2] << ' ';
-        msg << std::setw(14) << std::setfill(' ') << fPosOut[2] << '|';
-        msg << std::setw(14) << std::setfill(' ') << this->GetP() << '|';
-        msg << std::setw(10) << std::setfill(' ') << fId << ' ';
-        msg << std::setw(10) << std::setfill(' ') << fLinkKey.fIndex << ' ';
-        msg << std::setw(10) << std::setfill(' ') << fLinkKey.fEvent << ' ';
-        msg << std::setw(10) << std::setfill(' ') << fLinkKey.fFile << ' ';
+        msg << std::setw(14) << fPosIn[2] << ' ';
+        msg << std::setw(14) << fPosOut[2] << '|';
+        msg << std::setw(14) << this->GetP() << '|';
+        msg << std::setw(10) << fId << ' ';
+        msg << std::setw(10) << fLinkKey.fIndex << ' ';
+        if (verbose > 3) {
+          msg << std::setw(10) << fLinkKey.fEvent << ' ';
+          msg << std::setw(10) << fLinkKey.fFile << ' ';
+        }
+        std::stringstream msgHits;
+        for (int iH : fvHitIndexes) {
+          msgHits << iH << ' ';
+        }
+        msg << std::setw(16) << msgHits.str() << ' ';
       }
     }
   }
diff --git a/reco/L1/qa/CbmCaInputQaBase.cxx b/reco/L1/qa/CbmCaInputQaBase.cxx
index a955b55639f7cf2148733d0ddba3b7e7167b0c91..4b54e7c81b9db7f5fa9715d384d27a6869e295ec 100644
--- a/reco/L1/qa/CbmCaInputQaBase.cxx
+++ b/reco/L1/qa/CbmCaInputQaBase.cxx
@@ -736,9 +736,15 @@ InitStatus CbmCaInputQaBase<DetID>::InitDataBranches()
     frYmin[i] -= dy;
     frYmax[i] += dy;
 
-    double dz = 0.05 * fabs(frZmax[i] - frZmin[i]);
-    frZmin[i] -= dz;
-    frZmax[i] += dz;
+    if constexpr (L1DetectorID::kMuch == DetID) {
+      frZmin[i] -= 40;
+      frZmax[i] += 40;
+    }
+    else {
+      double dz = 0.05 * fabs(frZmax[i] - frZmin[i]);
+      frZmin[i] -= dz;
+      frZmax[i] += dz;
+    }
   }
 
 
@@ -906,7 +912,7 @@ InitStatus CbmCaInputQaBase<DetID>::InitHistograms()
       // Difference between MC input z and hit z coordinates
       sN = (TString) "point_hit_delta_z" + nsuff;
       sT = (TString) "Distance between " + detName + " point and hit along z axis" + tsuff + ";z_{reco} - z_{MC} [cm]";
-      fvph_point_hit_delta_z[iSt] = MakeQaObject<TH1F>(sF + sN, sT, fNbins, -0.05, 0.05);
+      fvph_point_hit_delta_z[iSt] = MakeQaObject<TH1F>(sF + sN, sT, fNbins, fRangeDzHitPoint[0], fRangeDzHitPoint[1]);
 
       sN              = (TString) "res_x" + nsuff;
       sT              = (TString) "Residuals for X" + tsuff + ";x_{reco} - x_{MC} [cm]";
diff --git a/reco/L1/qa/CbmCaInputQaBase.h b/reco/L1/qa/CbmCaInputQaBase.h
index cc0272beabb84478c6faa9f6b0bdb240501a6ce3..d3a8292d899ee419e2a075dc299f34f4c0fcc65b 100644
--- a/reco/L1/qa/CbmCaInputQaBase.h
+++ b/reco/L1/qa/CbmCaInputQaBase.h
@@ -185,6 +185,8 @@ protected:
   std::array<double, 2> fRResV = {kNAN, kNAN};  ///< Range for residual of v coordinate [cm]
   std::array<double, 2> fRResT = {kNAN, kNAN};  ///< Range for residual of time [ns]
 
+  std::array<double, 2> fRangeDzHitPoint = {-0.05, 0.05};  ///< Range for z-pos difference of the hit and point [cm]
+
   // NOTE: Pull binning is fixed by convention, since it is used for hit finder calibrations. Please,
   //       do not modify!
   static constexpr int kNbinsPull   = 200;
diff --git a/reco/L1/qa/CbmCaInputQaMuch.cxx b/reco/L1/qa/CbmCaInputQaMuch.cxx
index c39121e8c42434cf6ed4b0c4388761292577da89..18644b723a102e0572e86ea4ae8074050d55816e 100644
--- a/reco/L1/qa/CbmCaInputQaMuch.cxx
+++ b/reco/L1/qa/CbmCaInputQaMuch.cxx
@@ -53,6 +53,7 @@ void CbmCaInputQaMuch::DefineParameters()
   SetRange(fRResU, -2.00, 2.00);
   SetRange(fRResV, -4.00, 4.00);
   SetRange(fRResT, -5.00, 5.00);
+  SetRange(fRangeDzHitPoint, -50., 50.);
   // QA result selection criteria
   SetRange(fEffRange, 10.0, 30.0);  ///< Range for hit efficiency approximation
   fResMeanThrsh   = 0.50;           ///< Maximum allowed deviation of residual mean from zero [sigma]
diff --git a/reco/L1/qa/CbmCaOutputQa.cxx b/reco/L1/qa/CbmCaOutputQa.cxx
index 121e8359885ebf416757747846f7774a5b438003..abb6e8b7ed5017becb156be1bf59424a66f117ba 100644
--- a/reco/L1/qa/CbmCaOutputQa.cxx
+++ b/reco/L1/qa/CbmCaOutputQa.cxx
@@ -627,6 +627,48 @@ InitStatus OutputQa::InitTimeSlice()
     fpMCModule->MatchRecoAndMC();
   }
 
+  // ****** DEBUG: BEGIN
+  if constexpr (0) {
+    using std::setw;
+    {
+      LOG(info) << "---------- Reco track sample";
+      int id = 0;
+      if (fvRecoTracks.size()) { LOG(info) << setw(4) << "No." << ' ' << fvRecoTracks[0].ToString(3, true); }
+      for (const auto& trk : fvRecoTracks) {
+        LOG(info) << setw(4) << (id++) << ' ' << trk.ToString(3);
+      }
+    }
+    {
+      LOG(info) << "---------- Reco hit sample";
+      int id = 0;
+      if (fvHits.size()) { LOG(info) << setw(4) << "No." << ' ' << fvHits[0].ToString(3, true); }
+      for (const auto& h : fvHits) {
+        LOG(info) << setw(4) << (id++) << ' ' << h.ToString(3);
+      }
+    }
+    if (IsMCUsed()) {
+      LOG(info) << "---------- MC tracks sample";
+      int id = 0;
+      if (fMCData.GetTrackContainer().size()) {
+        LOG(info) << setw(4) << "No." << ' ' << fMCData.GetTrack(0).ToString(3, true);
+      }
+      for (const auto& trk : fMCData.GetTrackContainer()) {
+        if (trk.GetNofHits() || trk.GetNofPoints()) { LOG(info) << setw(4) << (id++) << ' ' << trk.ToString(3); }
+      }
+    }
+    if (IsMCUsed()) {
+      LOG(info) << "---------- MC points sample";
+      int id = 0;
+      if (fMCData.GetPointContainer().size()) {
+        LOG(info) << setw(4) << "No." << ' ' << fMCData.GetPoint(0).ToString(3, true);
+      }
+      for (const auto& p : fMCData.GetPointContainer()) {
+        LOG(info) << setw(4) << (id++) << ' ' << p.ToString(3);
+      }
+    }
+  }
+  // ****** DEBUG: END
+
   LOG_IF(info, fVerbose > 1) << fName << ": Data sample consists of " << nHits << " hits, " << nRecoTracks
                              << " reco tracks, " << nMCTracks << " MC tracks, " << nMCPoints << " MC points";
 
diff --git a/reco/L1/qa/CbmCaOutputQa.h b/reco/L1/qa/CbmCaOutputQa.h
index cabc82c0b8d852103c180e729664856671c22e79..afa5c54f0ead843d6e50671ed4fe53d81824645e 100644
--- a/reco/L1/qa/CbmCaOutputQa.h
+++ b/reco/L1/qa/CbmCaOutputQa.h
@@ -164,7 +164,7 @@ namespace cbm::ca
     void SetMcbmTrackingMode() { fTrackingMode = ECbmCaTrackingMode::kMCBM; }
 
     /// @brief Sets performance mode
-    /// @param mode  Performance mode (3 is default: TODO - test)
+    /// @param mode  Performance mode (1 is default: TODO - test)
     void SetPerformanceMode(int mode) { fPerformanceMode = mode; }
 
     ClassDef(OutputQa, 0);
@@ -231,7 +231,7 @@ namespace cbm::ca
     bool fbUseTrd  = false;  ///< is TRD used
     bool fbUseTof  = false;  ///< is TOF used
 
-    int fPerformanceMode = 3;  ///< Performance mode
+    int fPerformanceMode = 1;  ///< Performance mode
 
     ECbmCaTrackingMode fTrackingMode = ECbmCaTrackingMode::kSTS;  ///< Tracking mode