diff --git a/core/qa/CbmQaTask.cxx b/core/qa/CbmQaTask.cxx
index 78ce9c0386afae4cdb57a19d029dcaf779d0934d..a534f1758b23431830a0b34e19d833585f5d3f82 100644
--- a/core/qa/CbmQaTask.cxx
+++ b/core/qa/CbmQaTask.cxx
@@ -37,7 +37,8 @@ void CbmQaTask::Exec(Option_t* /*option*/)
 {
   fNofEvents.SetVal(fNofEvents.GetVal() + 1);
   LOG_IF(info, fVerbose > 1) << fName << ": event " << fNofEvents.GetVal();
-  FillHistograms();
+  this->InitTimeSlice();
+  this->FillHistograms();
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
diff --git a/core/qa/CbmQaTask.h b/core/qa/CbmQaTask.h
index 2415e28a41b7d274595abb28ca6de2547b213d0c..61f876d7e9af887b9f5c8c73b6f648868e566a1a 100644
--- a/core/qa/CbmQaTask.h
+++ b/core/qa/CbmQaTask.h
@@ -85,6 +85,9 @@ protected:
   /// Initializes canvases
   virtual InitStatus InitCanvases();
 
+  /// Initializes event / time-slice
+  virtual InitStatus InitTimeSlice() { return kSUCCESS; }
+
   /// Method to fill histograms per event or time-slice
   virtual void FillHistograms();
 
diff --git a/reco/L1/CMakeLists.txt b/reco/L1/CMakeLists.txt
index 52aa3bb0775addc455bcd47cc01e175a23d426f0..ddad3866d316bef46926039ad3d1c441724d7e98 100644
--- a/reco/L1/CMakeLists.txt
+++ b/reco/L1/CMakeLists.txt
@@ -49,6 +49,7 @@ set(SRCS
   CbmL1Performance.cxx
   CbmL1ReadEvent.cxx
   CbmCaMCModule.cxx
+  CbmCaTimeSliceReader.cxx
   L1Algo/L1Station.cxx
   L1Algo/L1Fit.cxx
   L1Algo/L1MCEvent.cxx
@@ -86,6 +87,7 @@ set(SRCS
   qa/CbmCaInputQaMuch.cxx
   qa/CbmCaInputQaTrd.cxx
   qa/CbmCaInputQaTof.cxx
+  qa/CbmCaOutputQa.cxx
   qa/CbmTofInteraction.cxx # Tests
 )
 
diff --git a/reco/L1/CbmCaTimeSliceReader.cxx b/reco/L1/CbmCaTimeSliceReader.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e4f7fa6b592e68cbbf14e436704458c0cef609ca
--- /dev/null
+++ b/reco/L1/CbmCaTimeSliceReader.cxx
@@ -0,0 +1,312 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   CbmCaTimeSliceReader.cxx
+/// @brief  Time-slice/event reader for CA tracker in CBM (implementation)
+/// @since  24.02.2023
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#include "CbmCaTimeSliceReader.h"
+
+#include "CbmGlobalTrack.h"
+#include "CbmKFMath.h"  // for CopyTrackParam2TC
+#include "CbmStsTrack.h"
+
+#include "FairRootManager.h"
+#include "Logger.h"
+
+#include "L1Constants.h"
+#include "L1InputData.h"
+#include "L1Parameters.h"
+
+using cbm::ca::TimeSliceReader;
+using L1Constants::clrs::kCL;   // clear log
+using L1Constants::clrs::kGNb;  // green bold log
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+TimeSliceReader::TimeSliceReader(ECbmTrackingMode mode) : fTrackingMode(mode) {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::Clear()
+{
+  // Detector used
+  fbUseMvd  = false;
+  fbUseSts  = false;
+  fbUseMuch = false;
+  fbUseTrd  = false;
+  fbUseTof  = false;
+
+  // Input branches
+  fpBrTimeSlice = nullptr;
+
+  fpBrMvdHits  = nullptr;
+  fpBrStsHits  = nullptr;
+  fpBrMuchHits = nullptr;
+  fpBrTrdHits  = nullptr;
+  fpBrTofHits  = nullptr;
+
+  fpBrRecoTracks = nullptr;
+  fpBrStsTracks  = nullptr;
+  fpBrMuchTracks = nullptr;
+  fpBrTrdTracks  = nullptr;
+  fpBrTofTracks  = nullptr;
+
+  // Pointers to output containers
+  fpvHitIds       = nullptr;
+  fpvDbgHits      = nullptr;
+  fpIODataManager = nullptr;
+  fpvTracks       = nullptr;
+
+  // Other
+  fpParameters = nullptr;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::InitRun()
+{
+  LOG(info) << "TimeSliceReader: initializing run ... ";
+
+  // Init tracking detector interfaces
+  fpMvdInterface  = CbmMvdTrackingInterface::Instance();
+  fpStsInterface  = CbmStsTrackingInterface::Instance();
+  fpMuchInterface = CbmMuchTrackingInterface::Instance();
+  fpTrdInterface  = CbmTrdTrackingInterface::Instance();
+  fpTofInterface  = CbmTofTrackingInterface::Instance();
+
+  // ** Init data branches **
+
+  auto* pFairManager = FairRootManager::Instance();
+  LOG_IF(fatal, !pFairManager) << "TimeSliceReader: FairRootManager was not defined";
+
+  fpBrTimeSlice = dynamic_cast<CbmTimeSlice*>(pFairManager->GetObject("TimeSlice."));
+  LOG_IF(fatal, !fpBrTimeSlice) << "TimeSliceReader: time slice was not defined";
+
+  // Init hit branches
+  if (fbUseMvd) {
+    fpBrMvdHits = dynamic_cast<TClonesArray*>(pFairManager->GetObject("MvdHit"));
+    LOG_IF(fatal, !fpBrMvdHits) << "TimeSliceReader: MVD hits were not found";
+  }
+
+  if (fbUseSts) {
+    fpBrStsHits = dynamic_cast<TClonesArray*>(pFairManager->GetObject("StsHit"));
+    LOG_IF(fatal, !fpBrStsHits) << "TimeSliceReader: STS hits were not found";
+  }
+
+  if (fbUseMuch) {
+    fpBrMuchHits = dynamic_cast<TClonesArray*>(pFairManager->GetObject("MuchPixelHit"));
+    LOG_IF(fatal, !fpBrMuchHits) << "TimeSliceReader: MuCh hits were not found";
+  }
+
+  if (fbUseTrd) {
+    fpBrTrdHits = dynamic_cast<TClonesArray*>(pFairManager->GetObject("TrdHit"));
+    LOG_IF(fatal, !fpBrTrdHits) << "TimeSliceReader: TRD hits were not found";
+  }
+
+  if (fbUseTof) {
+    fpBrTofHits = dynamic_cast<TClonesArray*>(pFairManager->GetObject("TofHit"));
+    LOG_IF(fatal, !fpBrTofHits) << "TimeSliceReader: TOF hits were not found";
+  }
+
+  // Init track branches
+  if (fpvTracks) {
+    switch (fTrackingMode) {
+      case ECbmTrackingMode::kSTS:
+        fpBrRecoTracks = dynamic_cast<TClonesArray*>(pFairManager->GetObject("StsTrack"));
+        LOG_IF(fatal, !fpBrRecoTracks) << "TimeSliceReader: StsTrack not found";
+        break;
+      case ECbmTrackingMode::kMCBM:
+        fpBrRecoTracks = dynamic_cast<TClonesArray*>(pFairManager->GetObject("GlobalTrack"));
+        LOG_IF(fatal, !fpBrRecoTracks) << "TimeSliceReader: GlobalTrack not found";
+        if (fbUseSts) {
+          fpBrStsTracks = dynamic_cast<TClonesArray*>(pFairManager->GetObject("StsTrack"));
+          LOG_IF(fatal, !fpBrStsTracks) << "TimeSliceReader: StsTrack not found";
+        }
+        if (fbUseMuch) {
+          fpBrMuchTracks = dynamic_cast<TClonesArray*>(pFairManager->GetObject("MuchTrack"));
+          LOG_IF(fatal, !fpBrMuchTracks) << "TimeSliceReader: MuchTrack not found";
+        }
+        if (fbUseTrd) {
+          fpBrTrdTracks = dynamic_cast<TClonesArray*>(pFairManager->GetObject("TrdTrack"));
+          LOG_IF(fatal, !fpBrTrdTracks) << "TimeSliceReader: TrdTrack not found";
+        }
+        if (fbUseTof) {
+          fpBrTofTracks = dynamic_cast<TClonesArray*>(pFairManager->GetObject("TofTrack"));
+          LOG_IF(fatal, !fpBrTofTracks) << "TimeSliceReader: TofTrack not found";
+        }
+        break;
+    }
+  }
+
+  LOG(info) << "TimeSliceReader: initializing run ... " << kGNb << "done" << kCL;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::InitTimeSlice() { LOG(info) << "TimeSliceReader: initializing time slice"; }
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::ReadHits()
+{
+  fNofHits     = 0;
+  fNofHitKeys  = 0;
+  fFirstHitKey = 0;
+
+  // Get total number of hits
+  int nHitsTot = 0;
+  if (fbUseMvd) { nHitsTot += fpBrMvdHits->GetEntriesFast(); }
+  if (fbUseSts) { nHitsTot += fpBrStsHits->GetEntriesFast(); }
+  if (fbUseMuch) { nHitsTot += fpBrMuchHits->GetEntriesFast(); }
+  if (fbUseTrd) { nHitsTot += fpBrTrdHits->GetEntriesFast(); }
+  if (fbUseTof) { nHitsTot += fpBrTofHits->GetEntriesFast(); }
+
+  // Resize the containers
+  fpvHitIds->clear();
+  fpvHitIds->reserve(nHitsTot);
+  fpvDbgHits->clear();
+  fpvDbgHits->reserve(nHitsTot);
+  fpIODataManager->ResetInputData();
+  fpIODataManager->ReserveNhits(nHitsTot);
+
+  // Read hits for different detectors
+  if (fbUseMvd) { fNofHits += ReadHitsForDetector<L1DetectorID::kMvd>(fpBrMvdHits); }
+  if (fbUseSts) { fNofHits += ReadHitsForDetector<L1DetectorID::kSts>(fpBrStsHits); }
+  if (fbUseMuch) { fNofHits += ReadHitsForDetector<L1DetectorID::kMuch>(fpBrMuchHits); }
+  if (fbUseTrd) { fNofHits += ReadHitsForDetector<L1DetectorID::kTrd>(fpBrTrdHits); }
+  if (fbUseTof) { fNofHits += ReadHitsForDetector<L1DetectorID::kTof>(fpBrTofHits); }
+
+  fpIODataManager->SetNhitKeys(fNofHitKeys);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::ReadRecoTracks()
+{
+  if (!fpvTracks) {
+    LOG(warn) << "TimeSliceReader: reconstructed tracks should not be read in this regime";
+    return;
+  }
+
+  assert(fpBrRecoTracks);
+  int nTracks = fpBrRecoTracks->GetEntriesFast();
+  fpvTracks->reset(nTracks);
+  switch (fTrackingMode) {
+    case ECbmTrackingMode::kSTS:
+      // Fill tracks from StsTrack branch
+      for (int iT = 0; iT < nTracks; ++iT) {
+        auto* pInputTrack = static_cast<CbmStsTrack*>(fpBrRecoTracks->At(iT));
+        auto& track       = (*fpvTracks)[iT];
+        CbmKFMath::CopyTrackParam2TC(pInputTrack->GetParamFirst(), track.T, track.C);
+        CbmKFMath::CopyTrackParam2TC(pInputTrack->GetParamLast(), track.TLast, track.CLast);
+        track.chi2      = pInputTrack->GetChiSq();
+        track.NDF       = pInputTrack->GetNDF();
+        track.Tpv[6]    = pInputTrack->GetStartTime();
+        track.Cpv[20]   = pInputTrack->GetStartTimeError();
+        track.T[6]      = pInputTrack->GetFirstHitTime();
+        track.C[20]     = pInputTrack->GetFirstHitTimeError();
+        track.TLast[6]  = pInputTrack->GetLastHitTime();
+        track.CLast[20] = pInputTrack->GetLastHitTimeError();
+        track.Hits.clear();
+        track.Hits.reserve(pInputTrack->GetNofHits());
+        for (int iH = 0; iH < pInputTrack->GetNofMvdHits(); ++iH) {
+          track.Hits.push_back(-pInputTrack->GetMvdHitIndex(iH) - 1);  // !!!!
+        }                                                              // iH
+        for (int iH = 0; iH < pInputTrack->GetNofStsHits(); ++iH) {
+          track.Hits.push_back(pInputTrack->GetStsHitIndex(iH));
+        }  // iH
+      }    // iT
+      break;
+
+    case ECbmTrackingMode::kMCBM:
+      LOG(fatal) << "Sorry, mCBM mode has not been implemented yet. Stay tuned :)";
+      //  TODO: fill Global track here
+      break;
+  }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::RegisterHitDebugInfoContainer(L1Vector<CbmL1HitDebugInfo>& vDbgHits) { fpvDbgHits = &vDbgHits; }
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::RegisterHitIndexContainer(L1Vector<CbmL1HitId>& vHitIds) { fpvHitIds = &vHitIds; }
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::RegisterIODataManager(std::shared_ptr<L1IODataManager>& pIODataManager)
+{
+  LOG_IF(fatal, !pIODataManager.get()) << "TimeSliceReader: passed null pointer as a L1IODataManager instance";
+  fpIODataManager = pIODataManager;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::RegisterTracksContainer(L1Vector<CbmL1Track>& vTracks) { fpvTracks = &vTracks; }
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::SetDetector(L1DetectorID detID, bool flag)
+{
+  switch (detID) {
+    case L1DetectorID::kMvd: fbUseMvd = flag; break;
+    case L1DetectorID::kSts: fbUseSts = flag; break;
+    case L1DetectorID::kMuch: fbUseMuch = flag; break;
+    case L1DetectorID::kTrd: fbUseTrd = flag; break;
+    case L1DetectorID::kTof: fbUseTof = flag; break;
+  }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::SetParameters(const L1Parameters* pParameters)
+{
+  LOG_IF(fatal, !pParameters) << "TimeSliceReader: passed null pointer as L1IODataManager instance";
+  fpParameters = pParameters;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TimeSliceReader::StoreHitRecord(const HitRecord& hitRecord)
+{
+  int iHitGlob = static_cast<int>(fpIODataManager->GetNofHits());  // Current hit global index
+
+  // Save the algo hit
+  if (fpIODataManager.get()) {
+    L1Hit aHit;
+    aHit.iSt = hitRecord.fStaId;
+    aHit.f   = hitRecord.fStripF;
+    aHit.b   = hitRecord.fStripB;
+    aHit.ID  = -1;
+    aHit.z   = hitRecord.fZ;
+    aHit.u   = hitRecord.fU;
+    aHit.v   = hitRecord.fV;
+    aHit.t   = hitRecord.fT;
+    aHit.dt2 = hitRecord.fDt * hitRecord.fDt;
+    aHit.du2 = hitRecord.fDu * hitRecord.fDu;
+    aHit.dv2 = hitRecord.fDv * hitRecord.fDv;
+    fpIODataManager->PushBackHit(aHit, hitRecord.fDataStream);
+  }
+
+  // Save hit ID information
+  if (fpvHitIds) { fpvHitIds->emplace_back(hitRecord.fDet, hitRecord.fExtId); }
+
+  // Save debug information
+  if (fpvDbgHits) {
+    CbmL1HitDebugInfo hitDbg;
+    hitDbg.Det      = hitRecord.fDet;
+    hitDbg.ExtIndex = hitRecord.fExtId;
+    hitDbg.iStation = hitRecord.fStaId;
+    hitDbg.x        = hitRecord.fX;
+    hitDbg.y        = hitRecord.fY;
+    hitDbg.dx       = hitRecord.fDx;
+    hitDbg.dy       = hitRecord.fDy;
+    hitDbg.dxy      = hitRecord.fDxy;
+    hitDbg.time     = hitRecord.fT;
+    fpvDbgHits->push_back(hitDbg);
+  }
+}
diff --git a/reco/L1/CbmCaTimeSliceReader.h b/reco/L1/CbmCaTimeSliceReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..92ff3c3644a7b8dbda287380d79f44ccde082f82
--- /dev/null
+++ b/reco/L1/CbmCaTimeSliceReader.h
@@ -0,0 +1,323 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   CbmCaTimeSliceReader.h
+/// @brief  Time-slice/event reader for CA tracker in CBM (header)
+/// @since  24.02.2023
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#ifndef CbmCaTimeSliceReader_h
+#define CbmCaTimeSliceReader_h 1
+
+#include "CbmL1.h"  // TMP: for CbmL1HitStore
+#include "CbmL1DetectorID.h"
+#include "CbmL1Hit.h"
+#include "CbmL1Track.h"
+#include "CbmMuchPixelHit.h"
+#include "CbmMuchTrackingInterface.h"
+#include "CbmMvdHit.h"
+#include "CbmMvdTrackingInterface.h"
+#include "CbmPixelHit.h"
+#include "CbmStsHit.h"
+#include "CbmStsTrackingInterface.h"
+#include "CbmTofHit.h"
+#include "CbmTofTrackingInterface.h"
+#include "CbmTrdHit.h"
+#include "CbmTrdTrackingInterface.h"
+
+#include "TClonesArray.h"
+
+#include "L1Vector.h"
+
+
+class CbmTimeSlice;
+class L1IODataManager;
+class L1Parameters;
+
+namespace cbm::ca
+{
+  /// @brief A structure to store hits information from different detectors in a uniform manner
+  struct HitRecord {
+    double fX           = 0.;  ///< x component of hit position [cm]
+    double fY           = 0.;  ///< y component of hit position [cm]
+    double fDx          = 0.;  ///< error of x component of hit position [cm]
+    double fDy          = 0.;  ///< error of y component of hit position [cm]
+    double fDxy         = 0.;  ///< correlation between x and y components [cm]
+    double fU           = 0.;  ///< hit position in direction of front strips [cm]
+    double fV           = 0.;  ///< hit position in direction of back strips [cm]
+    double fDu          = 0.;  ///< hit position error in direction of front strips [cm]
+    double fDv          = 0.;  ///< hit position error in direction of back strips [cm]
+    double fZ           = 0.;  ///< z component of hit position [cm]
+    double fT           = 0.;  ///< time of hit [ns]
+    double fDt          = 0.;  ///< time error of hit [ns]
+    int64_t fDataStream = -1;  ///< Global index of detector module
+    int fExtId          = -1;  ///< external index of hit
+    int fStaId          = -1;  ///< index of active tracking station
+    int fStripF         = -1;  ///< index of front strip
+    int fStripB         = -1;  ///< index of back strip
+    int fDet            = -1;  ///< detector ID
+  };
+
+  /// @brief A reader of time slice for CA tracker
+  ///
+  /// The class reads reconstructed hits and reconstructed tracks (optionally) and fills the CA tracking internal
+  /// data structures.
+  ///
+  class TimeSliceReader {
+  public:
+    /// @brief Constructor from parameters
+    /// @param mode  Tracking mode
+    TimeSliceReader(ECbmTrackingMode mode);
+
+    /// @brief Destructor
+    ~TimeSliceReader() = default;
+
+    /// @brief Copy constructor
+    TimeSliceReader(const TimeSliceReader&) = delete;
+
+    /// @brief Move constructor
+    TimeSliceReader(TimeSliceReader&&) = delete;
+
+    /// @brief Copy assignment operator
+    TimeSliceReader& operator=(const TimeSliceReader&) = delete;
+
+    /// @brief Move assignment operator
+    TimeSliceReader& operator=(TimeSliceReader&&) = delete;
+
+    /// @brief Clears class content
+    void Clear();
+
+    /// @brief Run initializer function
+    ///
+    /// Initializes data branches and provides necessary checks in the beginning of the run
+    void InitRun();
+
+    /// @brief Reads time slice
+    ///
+    /// Reads hits from time slice
+    void InitTimeSlice();
+
+    /// @brief Reads hits
+    void ReadHits();
+
+    /// @brief Reads reconstructed tracks
+    void ReadRecoTracks();
+
+    /// @brief Registers hit debug info container
+    /// @param vDbgHits  Reference to debug hit container
+    void RegisterHitDebugInfoContainer(L1Vector<CbmL1HitDebugInfo>& vDbgHits);
+
+    /// @brief Registers hit index container
+    /// @param vHitIds  Reference to hits indexes container
+    void RegisterHitIndexContainer(L1Vector<CbmL1HitId>& vHitIds);
+
+    /// @brief Registers the CA IO data manager instance
+    /// @param pIODataManager  Shared pointer to the IO data manager instance
+    void RegisterIODataManager(std::shared_ptr<L1IODataManager>& ioDataManager);
+
+    /// @brief Register the reconstructed tracks container
+    /// @param vTracks  Reference to reconstructed tracks container
+    void RegisterTracksContainer(L1Vector<CbmL1Track>& vTracks);
+
+    /// @brief Sets used detector subsystems
+    /// @param  detID  Id of detector
+    /// @param  flag   Flag: true - detector is used
+    /// @note Should be called before this->Init()
+    void SetDetector(L1DetectorID detID, bool flag = true);
+
+    /// @brief Sets the instance of parameters object
+    /// @param pParameters  Pointer to the parameters instance
+    void SetParameters(const L1Parameters* pParameters);
+
+
+  private:
+    /// @brief Reads hits for a given detector subsystem
+    /// @tparam Detector ID
+    /// @param  pBrHits  Pointer to input hit branch
+    /// @return  Number of stored hits
+    /// @note The function modifies fNofHitKey and fFirstHitKey counters
+    template<L1DetectorID DetID>
+    int ReadHitsForDetector(const TClonesArray* pBrHits);
+
+    /// @brief Saves hit to data structures
+    ///
+    /// Stores recorded hit information into registered hit containers
+    void StoreHitRecord(const HitRecord& hitRecord);
+
+    // Flags for detector subsystems being used
+    bool fbUseMvd     = false;  ///< is MVD used
+    bool fbUseSts     = false;  ///< is STS used
+    bool fbUseMuch    = false;  ///< is MuCh used
+    bool fbUseTrd     = false;  ///< is TRD used
+    bool fbUseTof     = false;  ///< is TOF used
+    bool fbReadTracks = true;   ///< flag to read reconstructed tracks from reco.root
+
+    // Pointers to the tracking detector interfaces
+    CbmTrackingDetectorInterfaceBase* fpMvdInterface  = nullptr;
+    CbmTrackingDetectorInterfaceBase* fpStsInterface  = nullptr;
+    CbmTrackingDetectorInterfaceBase* fpMuchInterface = nullptr;
+    CbmTrackingDetectorInterfaceBase* fpTrdInterface  = nullptr;
+    CbmTrackingDetectorInterfaceBase* fpTofInterface  = nullptr;
+
+    // Input data branches
+    CbmTimeSlice* fpBrTimeSlice = nullptr;  ///< Pointer to the TS object
+
+    TClonesArray* fpBrMvdHits  = nullptr;  ///< Input branch for MVD hits ("MvdHit")
+    TClonesArray* fpBrStsHits  = nullptr;  ///< Input branch for STS hits ("StsHit")
+    TClonesArray* fpBrMuchHits = nullptr;  ///< Input branch for MuCh hits ("MuchPixelHit")
+    TClonesArray* fpBrTrdHits  = nullptr;  ///< Input branch for TRD hits ("TrdHit")
+    TClonesArray* fpBrTofHits  = nullptr;  ///< Input branch for TOF hits ("TofHit")
+
+    // Branches for reconstructed tracks. The input at the moment (as for 27.02.2023) depends on the selected
+    // tracking mode. For simulations in CBM, the CA tracking is used only in STS + MVD detectors. In this case
+    // the reconstructed tracks are saved to the "StsTrack" branch as CbmStsTrack objects. For mCBM, the tracks from
+    // CA are saved as global tracks, and the local ones are used to keep indexes of hits in different subsystems
+    TClonesArray* fpBrRecoTracks = nullptr;  ///< Input branch for reconstructed tracks ("GlobalTrack", "StsTrack")
+    TClonesArray* fpBrStsTracks  = nullptr;  ///< Input branch for reconstructed STS tracks ("StsTrack")
+    TClonesArray* fpBrMuchTracks = nullptr;  ///< Input branch for reconstructed MuCh tracks ("MuchTrack")
+    TClonesArray* fpBrTrdTracks  = nullptr;  ///< Input branch for reconstructed TRD tracks ("TrdTrack")
+    TClonesArray* fpBrTofTracks  = nullptr;  ///< Input branch for reconstructed TOF tracks ("TofTrack")
+
+    // Pointers to output data containers
+    L1Vector<CbmL1HitId>* fpvHitIds                  = nullptr;  ///< Pointer to array of hit index objects
+    L1Vector<CbmL1HitDebugInfo>* fpvDbgHits          = nullptr;  ///< Pointer to array of debug hits
+    L1Vector<CbmL1Track>* fpvTracks                  = nullptr;  ///< Pointer to array of reconstructed tracks
+    std::shared_ptr<L1IODataManager> fpIODataManager = nullptr;  ///< Pointer to input data manager
+
+
+    // Additional
+    const L1Parameters* fpParameters = nullptr;  ///< Pointer to the defined parameters instance
+    ECbmTrackingMode fTrackingMode;              ///< Tracking mode
+
+    // Indexes
+    int fNofHits     = 0;  ///< Stored number of hits
+    int fNofHitKeys  = 0;  ///< Recorded number of hit keys
+    int fFirstHitKey = 0;  ///< First index of hit key for the detector subsystem
+  };
+}  // namespace cbm::ca
+
+
+// **************************************************
+// ** Inline and template function implementations **
+// **************************************************
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+template<L1DetectorID DetID>
+int cbm::ca::TimeSliceReader::ReadHitsForDetector(const TClonesArray* pBrHits)
+{
+  int nHitsTot    = pBrHits->GetEntriesFast();  // total number of hits stored in a branch
+  int nHitsStored = 0;                          // number of hits stored
+
+  fFirstHitKey = fNofHitKeys;
+
+  for (int iH = 0; iH < nHitsTot; ++iH) {
+    cbm::ca::HitRecord hitRecord;  // Record of hits information
+
+    CbmPixelHit* pPixelHit = nullptr;  // Pointer to hit object
+    float phiF             = 0.;       // Stereo angle of front strips
+    float phiB             = 0.;       // Stereo angle of back strips
+    int iStGeom            = -1;       // Geometry station number
+
+    // Fill out detector specific data
+    if constexpr (L1DetectorID::kMvd == DetID) {
+      CbmMvdHit* pMvdHit = static_cast<CbmMvdHit*>(pBrHits->At(iH));
+      iStGeom            = fpMvdInterface->GetTrackingStationIndex(pMvdHit->GetStationNr());
+      phiF               = fpMvdInterface->GetStripsStereoAngleFront(iStGeom);
+      phiB               = fpMvdInterface->GetStripsStereoAngleBack(iStGeom);
+      pPixelHit          = static_cast<CbmPixelHit*>(pMvdHit);
+      hitRecord.fDu      = pMvdHit->GetDx();
+      hitRecord.fDv      = pMvdHit->GetDy();
+    }
+    else if constexpr (L1DetectorID::kSts == DetID) {
+      CbmStsHit* pStsHit = static_cast<CbmStsHit*>(pBrHits->At(iH));
+      iStGeom            = fpStsInterface->GetTrackingStationIndex(pStsHit->GetAddress());
+      phiF               = fpStsInterface->GetStripsStereoAngleFront(iStGeom);
+      phiB               = fpStsInterface->GetStripsStereoAngleBack(iStGeom);
+      pPixelHit          = static_cast<CbmPixelHit*>(pStsHit);
+      hitRecord.fStripF  = fFirstHitKey + pStsHit->GetFrontClusterId();
+      hitRecord.fStripB  = fFirstHitKey + pStsHit->GetBackClusterId();
+      hitRecord.fDu      = pStsHit->GetDu();
+      hitRecord.fDv      = pStsHit->GetDv();
+    }
+    else if constexpr (L1DetectorID::kMuch == DetID) {
+      CbmMuchPixelHit* pMuchHit = static_cast<CbmMuchPixelHit*>(pBrHits->At(iH));
+      iStGeom                   = fpMuchInterface->GetTrackingStationIndex(pMuchHit->GetAddress());
+      phiF                      = fpMuchInterface->GetStripsStereoAngleFront(iStGeom);
+      phiB                      = fpMuchInterface->GetStripsStereoAngleBack(iStGeom);
+      pPixelHit                 = static_cast<CbmPixelHit*>(pMuchHit);
+      hitRecord.fDu             = pMuchHit->GetDx();
+      hitRecord.fDv             = pMuchHit->GetDy();
+    }
+    else if constexpr (L1DetectorID::kTrd == DetID) {
+      CbmTrdHit* pTrdHit = static_cast<CbmTrdHit*>(pBrHits->At(iH));
+      iStGeom            = fpTrdInterface->GetTrackingStationIndex(pTrdHit->GetAddress());
+      phiF               = fpTrdInterface->GetStripsStereoAngleFront(iStGeom);
+      phiB               = fpTrdInterface->GetStripsStereoAngleBack(iStGeom);
+      pPixelHit          = static_cast<CbmPixelHit*>(pTrdHit);
+      hitRecord.fDu      = pTrdHit->GetDx();
+      hitRecord.fDv      = pTrdHit->GetDy();
+    }
+    else if constexpr (L1DetectorID::kTof == DetID) {
+      CbmTofHit* pTofHit = static_cast<CbmTofHit*>(pBrHits->At(iH));
+      iStGeom            = fpTofInterface->GetTrackingStationIndex(pTofHit->GetAddress());
+      phiF               = fpTofInterface->GetStripsStereoAngleFront(iStGeom);
+      phiB               = fpTofInterface->GetStripsStereoAngleBack(iStGeom);
+      pPixelHit          = static_cast<CbmPixelHit*>(pTofHit);
+      hitRecord.fDu      = pTofHit->GetDx();
+      hitRecord.fDv      = pTofHit->GetDy();
+
+      // *** Additional cuts for TOF ***
+      // Skip T0 hits
+      if (5 == CbmTofAddress::GetSmType(pTofHit->GetAddress())) { continue; }
+
+      // FIXME: Figure it out, if this cut is still needed (introduced a year ago for mCBM)
+      if (ECbmTrackingMode::kMCBM == fTrackingMode && pTofHit->GetZ() > 400) { continue; }
+    }
+
+    //int iStActive = fpParameters->GetStationIndexActive(iStGeom);
+    int iStActive = iStGeom;            // !!!! Initialize fParameters
+    if (iStActive == -1) { continue; }  // Cut off inactive stations
+
+    // Fill out data common for all the detectors
+    hitRecord.fStaId      = iStGeom;
+    hitRecord.fX          = pPixelHit->GetX();
+    hitRecord.fY          = pPixelHit->GetY();
+    hitRecord.fZ          = pPixelHit->GetZ();
+    hitRecord.fDx         = pPixelHit->GetDx();
+    hitRecord.fDy         = pPixelHit->GetDy();
+    hitRecord.fDxy        = pPixelHit->GetDxy();
+    hitRecord.fT          = pPixelHit->GetTime();
+    hitRecord.fDt         = pPixelHit->GetTimeError();
+    hitRecord.fDet        = static_cast<int>(DetID);
+    hitRecord.fDataStream = (static_cast<int64_t>(hitRecord.fDet) << 60) | pPixelHit->GetAddress();
+    hitRecord.fU          = hitRecord.fX * cos(phiF) + hitRecord.fY * sin(phiF);
+    hitRecord.fV          = hitRecord.fX * cos(phiB) + hitRecord.fY * sin(phiB);
+
+    // Update hit external index
+    if constexpr (L1DetectorID::kMvd == DetID) { hitRecord.fExtId = -(1 + iH); }
+    else {
+      hitRecord.fExtId = iH;
+    }
+
+    // Update number of hit keys
+    if constexpr (L1DetectorID::kSts == DetID) {
+      if (fNofHitKeys <= hitRecord.fStripF) { fNofHitKeys += hitRecord.fStripF; }
+      if (fNofHitKeys <= hitRecord.fStripB) { fNofHitKeys += hitRecord.fStripB; }
+    }
+    else {
+      hitRecord.fStripF = fFirstHitKey + iH;
+      hitRecord.fStripB = hitRecord.fStripF;
+      if (fNofHitKeys <= hitRecord.fStripF) { fNofHitKeys += hitRecord.fStripF; }
+    }
+
+    // Save hit to data structures
+    this->StoreHitRecord(hitRecord);
+    ++nHitsStored;
+  }  // iH
+  return nHitsStored;
+}
+
+
+#endif  // CbmCaTimeSliceReader_h
diff --git a/reco/L1/CbmL1.cxx b/reco/L1/CbmL1.cxx
index 0be8e167f99e0a5b8a749b7cb04ac37e6fef96fe..0efebbde0145ace8e6884a28123895b66da59187 100644
--- a/reco/L1/CbmL1.cxx
+++ b/reco/L1/CbmL1.cxx
@@ -90,7 +90,6 @@ CbmL1::CbmL1() : CbmL1("L1") {}
 CbmL1::CbmL1(const char* name, Int_t verbose, Int_t performance, int dataMode, const TString& dataDir,
              int findParticleMode)
   : FairTask(name, verbose)
-  , fIODataManager(L1IODataManager(gAlgo.GetParameters()))
   , fPerformance(performance)
   , fSTAPDataMode(dataMode)
   , fFindParticlesMode(findParticleMode)
@@ -103,6 +102,8 @@ CbmL1::CbmL1(const char* name, Int_t verbose, Int_t performance, int dataMode, c
     default: LOG(info) << "CbmL1: tracking will be run without external data R/W"; break;
   }
 
+  fpIODataManager = std::make_shared<L1IODataManager>();
+
   if (1 == fSTAPDataMode || 2 == fSTAPDataMode) { this->DefineSTAPNames(dataDir); }
 
   if (!CbmTrackingDetectorInterfaceInit::Instance()) {
@@ -867,6 +868,7 @@ InitStatus CbmL1::Init()
   fNStations     = fpAlgo->GetParameters()->GetNstationsActive();
 
   LOG(info) << fpAlgo->GetParameters()->ToString(0);
+  fpIODataManager->SetNofActiveStations(fNStations);
 
   LOG(info) << "----- Numbers of stations active in tracking -----";
   LOG(info) << "  MVD:    " << fNMvdStations;
@@ -1202,7 +1204,7 @@ void CbmL1::WriteSTAPAlgoInputData(int iJob)  // must be called after ReadEvent
                      + TString::Format(kSTAPAlgoIDataSuffix.data(), iJob);
 
   // Write file
-  fIODataManager.WriteInputData(filename.Data());
+  fpIODataManager->WriteInputData(filename.Data());
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
@@ -1228,7 +1230,7 @@ void CbmL1::ReadSTAPAlgoInputData(int iJob)
                      + TString::Format(kSTAPAlgoIDataSuffix.data(), iJob);
 
   // Read file
-  fIODataManager.ReadInputData(filename.Data());
+  fpIODataManager->ReadInputData(filename.Data());
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
diff --git a/reco/L1/CbmL1.h b/reco/L1/CbmL1.h
index db0ee01adc5195c64236b64276c79b349fcb63e1..a5d550da97d4ee05b47e1c84a17ebad602964b2b 100644
--- a/reco/L1/CbmL1.h
+++ b/reco/L1/CbmL1.h
@@ -445,8 +445,8 @@ private:
   // ***************************
 
 
-  L1InitManager fInitManager;      ///< Tracking parameters data manager
-  L1IODataManager fIODataManager;  ///< Input-output data manager
+  L1InitManager fInitManager;                                  ///< Tracking parameters data manager
+  std::shared_ptr<L1IODataManager> fpIODataManager = nullptr;  ///< Input-output data manager
 
   //std::unique_ptr<CbmCaMCModule> fpMCModule = nullptr;  ///< MC-module for tracking
 
diff --git a/reco/L1/CbmL1DetectorID.h b/reco/L1/CbmL1DetectorID.h
index 6bffea7026eb95166b225f8b28b44914a3df189f..c63df00909f01f3c7b0155b648273e51aa1cb49c 100644
--- a/reco/L1/CbmL1DetectorID.h
+++ b/reco/L1/CbmL1DetectorID.h
@@ -23,4 +23,12 @@ enum class L1DetectorID
   kTof
 };
 
+/// @brief Enumeration for different tracking running modes
+enum class ECbmTrackingMode
+{
+  kSTS,  ///< Local tracking in CBM (STS + MVD), results stored to the StsTrack branch
+  kMCBM  ///< Global tracking in mCBM (STS, MuCh, TRD, TOF), results stored to GlobalTrack branch
+};
+
+
 #endif  // CbmL1DetectorID_h
diff --git a/reco/L1/CbmL1ReadEvent.cxx b/reco/L1/CbmL1ReadEvent.cxx
index 3a96dd7dbbdebcfea76db50b63d636c28742f148..5655a3fdc36435a572adeceaa85d0ab6ffc46999 100644
--- a/reco/L1/CbmL1ReadEvent.cxx
+++ b/reco/L1/CbmL1ReadEvent.cxx
@@ -851,7 +851,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
 
         th.dx  = h->GetDx();
         th.dy  = h->GetDy();
-        th.dxy = 0;
+        th.dxy = 0;  /// FIXME: ???
 
         th.du = h->GetDx();
         th.dv = h->GetDy();
@@ -1056,7 +1056,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
 
       if (0x00202806 == h->GetAddress() || 0x00002806 == h->GetAddress()) continue;  // TODO: Why? (S.Zharko)
 
-      if (5 == CbmTofAddress::GetSmType(h->GetAddress())) continue;
+      if (5 == CbmTofAddress::GetSmType(h->GetAddress())) continue;  // Skip T0 hits from TOF
 
       int sttof = CbmTofTrackingInterface::Instance()->GetTrackingStationIndex(h);
 
@@ -1150,9 +1150,9 @@ void CbmL1::ReadEvent(CbmEvent* event)
   fvHitDebugInfo.reserve(nHits);
   fvHitPointIndexes.reserve(nHits);
 
-  fIODataManager.ResetInputData();
-  fIODataManager.ReserveNhits(nHits);
-  fIODataManager.SetNhitKeys(NStrips);
+  fpIODataManager->ResetInputData();
+  fpIODataManager->ReserveNhits(nHits);
+  fpIODataManager->SetNhitKeys(NStrips);
 
   // ----- Fill
   for (int iHit = 0; iHit < nHits; ++iHit) {
@@ -1191,12 +1191,12 @@ void CbmL1::ReadEvent(CbmEvent* event)
 
     // TODO: Here one should fill in the fvExternalHits[iHit].mcPointIds
 
-    fIODataManager.PushBackHit(h, th.fDataStream);
+    fpIODataManager->PushBackHit(h, th.fDataStream);
 
     fvHitDebugInfo.push_back(s);
     fvHitPointIndexes.push_back(th.iMC);
   }
-  if (fPerformance) { HitMatch(); }                                       /// OLD
+  if (fPerformance) { HitMatch(); }  /// OLD
 
   if (fVerbose >= 2) cout << "ReadEvent: mvd and sts are saved." << endl;
 
@@ -1204,7 +1204,7 @@ void CbmL1::ReadEvent(CbmEvent* event)
   if (1 == fSTAPDataMode) { WriteSTAPAlgoInputData(nCalls); }
   if (2 == fSTAPDataMode) { ReadSTAPAlgoInputData(nCalls); }
   // TODO: SZh: If we read data from file, we don't need to collect them above. This should be addressed
-  fIODataManager.SendInputData(fpAlgo);
+  fpIODataManager->SendInputData(fpAlgo);
 
   if (fPerformance) {
     if (fVerbose >= 10) cout << "HitMatch is done." << endl;
diff --git a/reco/L1/L1Algo/L1Algo.h b/reco/L1/L1Algo/L1Algo.h
index 3c89d2cf89815f2f251402e1c4e97d092cef0678..2500a4425738567fe36ec26af22759a1959c8761 100644
--- a/reco/L1/L1Algo/L1Algo.h
+++ b/reco/L1/L1Algo/L1Algo.h
@@ -348,6 +348,7 @@ public:
   void DrawRecoTracksTime(const L1Vector<CbmL1Track>& tracks);
 #endif
 
+  /// TODO: Move to L1
   enum TrackingMode
   {
     kSts,
diff --git a/reco/L1/L1Algo/L1IODataManager.cxx b/reco/L1/L1Algo/L1IODataManager.cxx
index dbe5a6a95d9ec192ef373f120cec7efaa13833b9..73d9a572b900ff3af7c2b5d08fc528b3034ced90 100644
--- a/reco/L1/L1Algo/L1IODataManager.cxx
+++ b/reco/L1/L1Algo/L1IODataManager.cxx
@@ -16,9 +16,6 @@
 
 #include "L1Algo.h"
 
-// ---------------------------------------------------------------------------------------------------------------------
-//
-L1IODataManager::L1IODataManager(const L1Parameters* pParameters) : fpParameters(pParameters) {}
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
diff --git a/reco/L1/L1Algo/L1IODataManager.h b/reco/L1/L1Algo/L1IODataManager.h
index 05c2c3f131c2fdc5ba1a53808ceb57f237ab8854..166972ecbe678a7e84910ac5146fbcf0cee19d7a 100644
--- a/reco/L1/L1Algo/L1IODataManager.h
+++ b/reco/L1/L1Algo/L1IODataManager.h
@@ -13,7 +13,6 @@
 #include "L1Constants.h"
 #include "L1InputData.h"
 
-class L1Parameters;
 class L1Algo;
 //class L1OutputData;
 
@@ -28,11 +27,7 @@ public:
   // ** Constructors and destructor **
 
   /// Default constructor
-  L1IODataManager() = delete;
-
-  /// Constructor
-  /// \param fpParameters  Pointer to the L1 tracking algorithm parameters instance
-  L1IODataManager(const L1Parameters* pParameters);
+  L1IODataManager() = default;
 
   /// Destructor
   ~L1IODataManager() = default;
@@ -49,6 +44,10 @@ public:
   /// Move assignment operator
   L1IODataManager& operator=(L1IODataManager&& other) = delete;
 
+  /// @brief Gets number of hits stored
+  /// @return  Number of hits
+  int GetNofHits() { return fInputData.fHits.size(); }
+
   /// Reads input data object from boost-serialized binary file
   /// \param  fileName  Name of input file
   void ReadInputData(const std::string& fileName);
@@ -78,6 +77,10 @@ public:
   /// \param  nKeys  Number of hit keys
   void SetNhitKeys(int nKeys) { fInputData.fNhitKeys = nKeys; }
 
+  /// @brief Sets number of active stations
+  /// @param nStations  Number of stations
+  void SetNofActiveStations(int nStations) { fNofActiveStations = nStations; }
+
   /// Sends (moves) input data to the destination reference
   /// \param  pAlgo  Pointer to the L1 tracking algorithm main class
   /// \return Success flag
@@ -110,9 +113,8 @@ private:
 
   L1InputData fInputData {};  ///< Object of input data
 
-  const L1Parameters* fpParameters {nullptr};  ///< Pointer to the tracking parameters object
-
   int64_t fLastStreamId {-1};  ///< data stream Id of the last hit added
+  int fNofActiveStations = -1;  ///< Number of active stations
 };
 
 
diff --git a/reco/L1/L1LinkDef.h b/reco/L1/L1LinkDef.h
index 3681e47ae71d0ac7aa593d1ea6a966f5ce92c09b..6097328d6e5cc3b8afea9cd1f18a3ef8d9b3466f 100644
--- a/reco/L1/L1LinkDef.h
+++ b/reco/L1/L1LinkDef.h
@@ -34,6 +34,7 @@
 #pragma link C++ class CbmCaInputQaSts + ;
 #pragma link C++ class CbmCaInputQaTrd + ;
 #pragma link C++ class CbmCaInputQaTof + ;
+#pragma link C++ class cbm::ca::OutputQa + ;
 #pragma link C++ class ca::tools::WindowFinder + ;
 
 #endif
diff --git a/reco/L1/qa/CbmCaOutputQa.cxx b/reco/L1/qa/CbmCaOutputQa.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2f6713f24d23994653380230f880a389493427ec
--- /dev/null
+++ b/reco/L1/qa/CbmCaOutputQa.cxx
@@ -0,0 +1,65 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   CbmCaOutputQa.cxx
+/// @brief  Tracking output QA-task (implementation)
+/// @since  24.02.2023
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#include "CbmCaOutputQa.h"
+
+#include "Logger.h"
+
+using ca::tools::Debugger;
+using cbm::ca::OutputQa;
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+OutputQa::OutputQa(int verbose, bool isMCUsed) : CbmQaTask("CbmCaOutputQa", "caout", verbose, isMCUsed) {}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void OutputQa::EnableDebugger(const char* filename)
+{
+  if (!fpDebugger.get()) { fpDebugger = std::make_shared<Debugger>(filename); }
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+InitStatus OutputQa::InitDataBranches()
+{
+  LOG(info) << fName << ": Initializing data branches";
+
+  if (!fpTSReader.get()) { fpTSReader = std::make_unique<TimeSliceReader>(fTrackingMode); }
+
+  if (!fpDataManager.get()) { fpDataManager = std::make_shared<L1IODataManager>(); }
+
+  // Initialize time slice reader instance
+  fpTSReader->SetDetector(L1DetectorID::kMvd, fbUseMvd);
+  fpTSReader->SetDetector(L1DetectorID::kSts, fbUseSts);
+  fpTSReader->SetDetector(L1DetectorID::kMuch, fbUseMuch);
+  fpTSReader->SetDetector(L1DetectorID::kTrd, fbUseTrd);
+  fpTSReader->SetDetector(L1DetectorID::kTof, fbUseTof);
+
+  fpTSReader->RegisterIODataManager(fpDataManager);
+  fpTSReader->RegisterTracksContainer(fvRecoTracks);
+  fpTSReader->RegisterHitDebugInfoContainer(fvDbgHits);
+  fpTSReader->RegisterHitIndexContainer(fvHitIds);
+
+  fpTSReader->InitRun();
+  return kSUCCESS;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+InitStatus OutputQa::InitTimeSlice()
+{
+  // Read hits
+  fpTSReader->ReadHits();
+
+  // Read reconstructed tracks
+  fpTSReader->ReadRecoTracks();
+
+  return kSUCCESS;
+}
diff --git a/reco/L1/qa/CbmCaOutputQa.h b/reco/L1/qa/CbmCaOutputQa.h
new file mode 100644
index 0000000000000000000000000000000000000000..6a0c6f01b321b91eacf49869b62a6af199f5bfa3
--- /dev/null
+++ b/reco/L1/qa/CbmCaOutputQa.h
@@ -0,0 +1,111 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Sergei Zharko [committer] */
+
+/// @file   CbmCaOutputQa.h
+/// @brief  Tracking output QA-task (header)
+/// @since  24.02.2023
+/// @author Sergei Zharko <s.zharko@gsi.de>
+
+#ifndef CbmCaOutputQa_h
+#define CbmCaOutputQa_h 1
+
+#include "CbmCaTimeSliceReader.h"
+#include "CbmL1DetectorID.h"
+#include "CbmQaTask.h"
+
+#include "CaToolsDebugger.h"
+
+namespace cbm::ca
+{
+  /// @brief  QA-task for CA tracking output results
+  ///
+  class OutputQa : public CbmQaTask {
+  public:
+    /// @brief  Constructor from parameters
+    /// @param  verbose   Verbosity level
+    /// @param  isMCUsed  Flag, if MC information is available for this task
+    OutputQa(int verbose, bool isMCUsed);
+
+    /// @brief Sets MVD use flag
+    /// @param flag  Boolean flag: true - detector subsystem is used, false - detector subsystem is ignored
+    void SetUseMvd(bool flag = true) { fbUseMvd = flag; }
+
+    /// @brief Sets STS use flag
+    /// @param flag  Boolean flag: true - detector subsystem is used, false - detector subsystem is ignored
+    void SetUseSts(bool flag = true) { fbUseSts = flag; }
+
+    /// @brief Sets MuCh use flag
+    /// @param flag  Boolean flag: true - detector subsystem is used, false - detector subsystem is ignored
+    void SetUseMuch(bool flag = true) { fbUseMuch = flag; }
+
+    /// @brief Sets TRD use flag
+    /// @param flag  Boolean flag: true - detector subsystem is used, false - detector subsystem is ignored
+    void SetUseTrd(bool flag = true) { fbUseTrd = flag; }
+
+    /// @brief Sets TOF use flag
+    /// @param flag  Boolean flag: true - detector subsystem is used, false - detector subsystem is ignored
+    void SetUseTof(bool flag = true) { fbUseTof = flag; }
+
+    /// @brief Sets STS tracking mode
+    void SetStsTrackingMode() { fTrackingMode = ECbmTrackingMode::kSTS; }
+
+    /// @brief Sets mCBM global tracking mode
+    void SetMcbmTrackingMode() { fTrackingMode = ECbmTrackingMode::kMCBM; }
+
+    /// @brief Enables debugger
+    /// @param filename  Name of output ROOT file
+    ///
+    /// Creates a debugger and enables its usage inside a QA task
+    void EnableDebugger(const char* filename);
+
+
+    ClassDef(OutputQa, 0);
+
+  protected:
+    /// @brief Checks results of the QA and returns a success flag
+    /// @return  true   QA is passed
+    /// @return  false  QA is failed
+    bool Check() { return true; }
+
+    /// @brief Initializes canvases
+    InitStatus InitCanvases() { return kSUCCESS; }
+
+    /// @brief Initialises data branches in the beginning of the run
+    InitStatus InitDataBranches();
+
+    /// @brief Initializes histograms
+    InitStatus InitHistograms() { return kSUCCESS; }
+
+    /// @brief Initializes time slice
+    /// @note  Is called in the FairTask::Exec function
+    InitStatus InitTimeSlice();
+
+    /// @brief Fills histograms
+    void FillHistograms() {}
+
+    /// @brief De-initializes histograms
+    void DeInit() {}
+
+  private:
+    // Flags for detector subsystems being used
+    bool fbUseMvd  = false;  ///< is MVD used
+    bool fbUseSts  = false;  ///< is STS used
+    bool fbUseMuch = false;  ///< is MuCh used
+    bool fbUseTrd  = false;  ///< is TRD used
+    bool fbUseTof  = false;  ///< is TOF used
+
+    ECbmTrackingMode fTrackingMode = ECbmTrackingMode::kSTS;  ///< Tracking mode
+
+    std::unique_ptr<TimeSliceReader> fpTSReader       = nullptr;  ///< Reader of the time slice
+    std::shared_ptr<L1IODataManager> fpDataManager    = nullptr;  ///< Data manager
+    std::shared_ptr<::ca::tools::Debugger> fpDebugger = nullptr;  ///< Debugger
+
+    L1Vector<CbmL1HitId> fvHitIds {"CbmCaOutputQa::fvHitIds"};
+    L1Vector<CbmL1HitDebugInfo> fvDbgHits {"CbmCaOutputQa::fvDbgHits"};
+    L1Vector<CbmL1Track> fvRecoTracks {"CbmCaOutputQa::fvRecoTracks"};
+  };
+}  // namespace cbm::ca
+
+
+#endif  // CbmCaOutputQa_h