diff --git a/core/qa/CbmQaTask.cxx b/core/qa/CbmQaTask.cxx
index d01349387c578253215e3005bf5f9895e59ff478..4bc40d55986ceb2c1ff3f7e4a91a0b77b4b04268 100644
--- a/core/qa/CbmQaTask.cxx
+++ b/core/qa/CbmQaTask.cxx
@@ -37,7 +37,6 @@ CbmQaTask::CbmQaTask(const char* name, const char* prefix, int verbose, bool isM
 void CbmQaTask::Exec(Option_t* /*option*/)
 {
   fNofEvents.SetVal(fNofEvents.GetVal() + 1);
-  LOG_IF(info, fVerbose > 1) << fName << ": event " << fNofEvents.GetVal();
   this->InitTimeSlice();
   this->FillHistograms();
 }
diff --git a/macro/mcbm/mcbm_qa.C b/macro/mcbm/mcbm_qa.C
index a8d95846eae557a9a50406d6de46bd9887735e93..310a3e3b6261db1ac503c7bf7240416858155cd3 100644
--- a/macro/mcbm/mcbm_qa.C
+++ b/macro/mcbm/mcbm_qa.C
@@ -36,7 +36,7 @@
 #endif
 
 void mcbm_qa(Int_t nEvents = 0, TString dataset = "data/mcbm_beam_2020_03_test",
-             TString setupName = "mcbm_beam_2020_03")
+             TString setupName = "mcbm_beam_2020_03", Bool_t bUseMC = kTRUE)
 {
 
   // ========================================================================
@@ -48,7 +48,6 @@ void mcbm_qa(Int_t nEvents = 0, TString dataset = "data/mcbm_beam_2020_03_test",
   // ------------------------------------------------------------------------
 
   // -----   Environment   --------------------------------------------------
-  bool bUseMC    = true;                           // flag: true - MC information is used
   int verbose    = 6;                              // verbose level
   TString myName = "mcbm_qa";                      // this macro's name for screen output
   TString srcDir = gSystem->Getenv("VMCWORKDIR");  // top source directory
@@ -164,9 +163,16 @@ void mcbm_qa(Int_t nEvents = 0, TString dataset = "data/mcbm_beam_2020_03_test",
   // ------------------------------------------------------------------------
 
   // -----   MCDataManager (legacy mode)  -----------------------------------
-  CbmMCDataManager* mcManager = new CbmMCDataManager("MCDataManager", 1);
-  mcManager->AddFile(traFile);
-  run->AddTask(mcManager);
+  if (bUseMC) {
+    std::cout << "-I- " << myName << ": Adding MC manager and MC to reco matching tasks\n";
+
+    auto* mcManager = new CbmMCDataManager("MCDataManager", 1);
+    mcManager->AddFile(traFile);
+    run->AddTask(mcManager);
+
+    auto* matchRecoToMC = new CbmMatchRecoToMC();
+    run->AddTask(matchRecoToMC);
+  }
   // ------------------------------------------------------------------------
 
   // ----- MUCH QA  ---------------------------------
@@ -179,6 +185,7 @@ void mcbm_qa(Int_t nEvents = 0, TString dataset = "data/mcbm_beam_2020_03_test",
   }
   // ------------------------------------------------------------------------
 
+
   // ----- CA tracking QA ---------------------------------------------------
   // Tracking detector interface initialization
   run->AddTask(new CbmTrackingDetectorInterfaceInit());
diff --git a/reco/L1/CbmCaMCModule.cxx b/reco/L1/CbmCaMCModule.cxx
index d636d9bbf4c7ef7ec8e51e2f913659eb49a8ea3c..cfaea58318bbff75ccdb57c56147c67c784a54c6 100644
--- a/reco/L1/CbmCaMCModule.cxx
+++ b/reco/L1/CbmCaMCModule.cxx
@@ -470,7 +470,6 @@ void CbmCaMCModule::MatchRecoAndMCTracks()
       trkRe.SetMaxPurity(maxPurity);
     }  // loop over hit map: end
     assert(trkRe.GetNofMCTracks() < 2);
-
   }  // loop over reconstructed tracks: end
 }
 
diff --git a/reco/L1/L1LinkDef.h b/reco/L1/L1LinkDef.h
index 6097328d6e5cc3b8afea9cd1f18a3ef8d9b3466f..9423ce3d123d2f4c4b222835fa864eb30f542ab6 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++ enum cbm::ca::ETrackType;
 #pragma link C++ class cbm::ca::OutputQa + ;
 #pragma link C++ class ca::tools::WindowFinder + ;
 
diff --git a/reco/L1/catools/CaToolsMCData.cxx b/reco/L1/catools/CaToolsMCData.cxx
index d4b8cdf36c0e203c8baca9ce98570b0fd2ccbc4c..33213add261b31944358880775aeff42d3671bb3 100644
--- a/reco/L1/catools/CaToolsMCData.cxx
+++ b/reco/L1/catools/CaToolsMCData.cxx
@@ -94,7 +94,6 @@ void MCData::Clear()
 //
 void MCData::InitTrackInfo(const L1Vector<CbmL1HitDebugInfo>& vHits)
 {
-  LOG(info) << "\033[1;32m!!!! FLAG a\033[0m";
   for (auto& aTrk : fvTracks) {
     // Assign hits to tracks
     aTrk.ClearHitIndexes();
@@ -109,7 +108,6 @@ void MCData::InitTrackInfo(const L1Vector<CbmL1HitDebugInfo>& vHits)
     aTrk.InitPointsInfo(fvPoints);
     aTrk.InitHitsInfo(vHits);
   }
-  LOG(info) << "\033[1;32m!!!! FLAG b\033[0m";
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
diff --git a/reco/L1/qa/CbmCaOutputQa.cxx b/reco/L1/qa/CbmCaOutputQa.cxx
index 549a52f2951f3fbc18f4c60483eaedbcc9e8d7ac..af42719b282bd283fc7439ba8e4557612913fd5a 100644
--- a/reco/L1/qa/CbmCaOutputQa.cxx
+++ b/reco/L1/qa/CbmCaOutputQa.cxx
@@ -15,11 +15,41 @@
 #include "L1InitManager.h"
 
 using ca::tools::Debugger;
+using ::ca::tools::MCTrack;
 using cbm::ca::OutputQa;
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-OutputQa::OutputQa(int verbose, bool isMCUsed) : CbmQaTask("CbmCaOutputQa", "caout", verbose, isMCUsed) {}
+OutputQa::OutputQa(int verbose, bool isMCUsed) : CbmQaTask("CbmCaOutputQa", "caout", verbose, isMCUsed)
+{
+  // Turn on default track classes
+  AddTrackType(ETrackType::kAll);
+  AddTrackType(ETrackType::kGhost);
+  AddTrackType(ETrackType::kPrim);
+  AddTrackType(ETrackType::kSec);
+  AddTrackType(ETrackType::kPrimPIP);
+  AddTrackType(ETrackType::kPrimPIM);
+  AddTrackType(ETrackType::kSecPIP);
+  AddTrackType(ETrackType::kSecPIM);
+  AddTrackType(ETrackType::kPrimMUP);
+  AddTrackType(ETrackType::kPrimMUM);
+  AddTrackType(ETrackType::kSecMUP);
+  AddTrackType(ETrackType::kSecMUM);
+
+  //AddTrackType(ETrackType::kAllE);
+  //AddTrackType(ETrackType::kAllMU);
+  //AddTrackType(ETrackType::kAllPI);
+  //AddTrackType(ETrackType::kAllK);
+  //AddTrackType(ETrackType::kAllPPBAR);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void OutputQa::AddTrackType(ETrackType type, bool flag)
+{
+  LOG_IF(fatal, type >= kEND || type < 0) << fName << ": attempt to add unsupported track type " << type;
+  fvbTrackTypeOn[type] = flag;
+}
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
@@ -36,68 +66,169 @@ void OutputQa::FillHistograms()
   // ** Fill distributions for reconstructed tracks (including ghost ones) **
   // ************************************************************************
 
-  for (size_t iTrkReco = 0; iTrkReco < fvRecoTracks.size(); ++iTrkReco) {
-    const auto& recoTrk = fvRecoTracks[iTrkReco];
+  // TODO: (experimental) more general approach for filling track types utilizing cuts on MC and reco tracks
+  if constexpr (kEXPTRACKFILL) {
+    // Fill histograms for each defined track type
+    for (int iType = 0; iType < ETrackType::kEND; ++iType) {
+      if (fvbTrackTypeOn[iType]) {
+        fvpTrackHistograms[iType]->FillRecoTracks();
+        if (fvpTrackHistograms[iType]->IsMCUsed()) { fvpTrackHistograms[iType]->FillMCTracks(); }
+      }  // if track type ID filled
+    }    // track type ID
+  }
+  else {
+    for (size_t iTrkReco = 0; iTrkReco < fvRecoTracks.size(); ++iTrkReco) {
+      const auto& recoTrk = fvRecoTracks[iTrkReco];
+
+      // Reject tracks, which do not contain hits
+      if (recoTrk.GetNofHits() < 1) { continue; }
 
-    // Reject tracks, which do not contain hits
-    if (recoTrk.GetNofHits() < 1) { continue; }
+      if (fvbTrackTypeOn[ETrackType::kAll]) { fvpTrackHistograms[ETrackType::kAll]->FillRecoTrack(iTrkReco); }
 
-    fvpTrackHistograms[ETrackType::kAll]->FillRecoTrack(iTrkReco);
+      if (IsMCUsed()) {
+        if (fvbTrackTypeOn[ETrackType::kGhost] && recoTrk.IsGhost()) {
+          fvpTrackHistograms[ETrackType::kGhost]->FillRecoTrack(iTrkReco);
+        }
+        int iTrkMC = recoTrk.GetMatchedMCTrackIndex();
+        if (iTrkMC > -1) {
+          const auto& mcTrk = fMCData.GetTrack(iTrkMC);
+          int pdg           = mcTrk.GetPdgCode();
+          bool isPrimary    = mcTrk.IsPrimary();
+
+          // Cut tracks, which did not leave hits in tracker
+          if (mcTrk.GetNofHits() == 0) { continue; }
+
+          if (isPrimary) {
+            if (fvbTrackTypeOn[ETrackType::kPrim]) { fvpTrackHistograms[ETrackType::kPrim]->FillRecoTrack(iTrkReco); }
+
+            if (fvbTrackTypeOn[ETrackType::kPrimPI] && std::abs(pdg) == 211) {
+              fvpTrackHistograms[ETrackType::kPrimPI]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kPrimPIP] && pdg == +211) {
+              fvpTrackHistograms[ETrackType::kPrimPIP]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kPrimPIM] && pdg == -211) {
+              fvpTrackHistograms[ETrackType::kPrimPIM]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kPrimMU] && std::abs(pdg) == 13) {
+              fvpTrackHistograms[ETrackType::kPrimMU]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kPrimMUP] && pdg == +13) {
+              fvpTrackHistograms[ETrackType::kPrimMUP]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kPrimMUM] && pdg == -13) {
+              fvpTrackHistograms[ETrackType::kPrimMUM]->FillRecoTrack(iTrkReco);
+            }
+          }
+          else {
+            if (fvbTrackTypeOn[ETrackType::kSec]) { fvpTrackHistograms[ETrackType::kSec]->FillRecoTrack(iTrkReco); }
+
+            if (fvbTrackTypeOn[ETrackType::kSecPI] && std::abs(pdg) == 211) {
+              fvpTrackHistograms[ETrackType::kSecPI]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kSecPIP] && pdg == +211) {
+              fvpTrackHistograms[ETrackType::kSecPIP]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kSecPIM] && pdg == -211) {
+              fvpTrackHistograms[ETrackType::kSecPIM]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kSecMU] && std::abs(pdg) == 13) {
+              fvpTrackHistograms[ETrackType::kSecMU]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kSecMUP] && pdg == +13) {
+              fvpTrackHistograms[ETrackType::kSecMUP]->FillRecoTrack(iTrkReco);
+            }
+
+            if (fvbTrackTypeOn[ETrackType::kSecMUM] && pdg == -13) {
+              fvpTrackHistograms[ETrackType::kSecMUM]->FillRecoTrack(iTrkReco);
+            }
+          }
+        }
+      }
+    }  // loop over recoTrk: end
 
+
+    // *************************************
+    // ** Fill distributions of MC-tracks **
+    // *************************************
     if (IsMCUsed()) {
-      if (recoTrk.IsGhost()) { fvpTrackHistograms[ETrackType::kGhost]->FillRecoTrack(iTrkReco); }
-      int iTrkMC = recoTrk.GetMatchedMCTrackIndex();
-      if (iTrkMC > -1) {
+
+
+      for (int iTrkMC = 0; iTrkMC < fMCData.GetNofTracks(); ++iTrkMC) {
         const auto& mcTrk = fMCData.GetTrack(iTrkMC);
-        int pdg           = mcTrk.GetPdgCode();
-        bool isPrimary    = mcTrk.IsPrimary();
+
+        // Cut tracks, which did not leave hits in tracker
+        if (mcTrk.GetNofHits() == 0) { continue; }
+
+        // Fill different track categories
+        if (fvbTrackTypeOn[ETrackType::kAll]) { fvpTrackHistograms[ETrackType::kAll]->FillMCTrack(iTrkMC); }
+
+        int pdg        = mcTrk.GetPdgCode();
+        bool isPrimary = mcTrk.IsPrimary();
 
         if (isPrimary) {
-          fvpTrackHistograms[ETrackType::kPrim]->FillRecoTrack(iTrkReco);
+          if (fvbTrackTypeOn[ETrackType::kPrim]) { fvpTrackHistograms[ETrackType::kPrim]->FillMCTrack(iTrkMC); }
 
-          if (pdg == +211) { fvpTrackHistograms[ETrackType::kPrimPIP]->FillRecoTrack(iTrkReco); }
-          if (pdg == -211) { fvpTrackHistograms[ETrackType::kPrimPIM]->FillRecoTrack(iTrkReco); }
-        }
-        else {
-          fvpTrackHistograms[ETrackType::kSec]->FillRecoTrack(iTrkReco);
+          if (fvbTrackTypeOn[ETrackType::kPrimPI] && std::abs(pdg) == 211) {
+            fvpTrackHistograms[ETrackType::kPrimPI]->FillMCTrack(iTrkMC);
+          }
 
-          if (pdg == +211) { fvpTrackHistograms[ETrackType::kSecPIP]->FillRecoTrack(iTrkReco); }
-          if (pdg == -211) { fvpTrackHistograms[ETrackType::kSecPIM]->FillRecoTrack(iTrkReco); }
-        }
-      }
-    }
+          if (fvbTrackTypeOn[ETrackType::kPrimPIP] && pdg == +211) {
+            fvpTrackHistograms[ETrackType::kPrimPIP]->FillMCTrack(iTrkMC);
+          }
 
+          if (fvbTrackTypeOn[ETrackType::kPrimPIM] && pdg == -211) {
+            fvpTrackHistograms[ETrackType::kPrimPIM]->FillMCTrack(iTrkMC);
+          }
 
-  }  // loop over recoTrk: end
+          if (fvbTrackTypeOn[ETrackType::kPrimMU] && std::abs(pdg) == 13) {
+            fvpTrackHistograms[ETrackType::kPrimMU]->FillMCTrack(iTrkMC);
+          }
 
+          if (fvbTrackTypeOn[ETrackType::kPrimMUP] && pdg == +13) {
+            fvpTrackHistograms[ETrackType::kPrimMUP]->FillMCTrack(iTrkMC);
+          }
 
-  // *************************************
-  // ** Fill distributions of MC-tracks **
-  // *************************************
-  if (IsMCUsed()) {
-    for (int iTrkMC = 0; iTrkMC < fMCData.GetNofTracks(); ++iTrkMC) {
-      const auto& mcTrk = fMCData.GetTrack(iTrkMC);
+          if (fvbTrackTypeOn[ETrackType::kPrimMUM] && pdg == -13) {
+            fvpTrackHistograms[ETrackType::kPrimMUM]->FillMCTrack(iTrkMC);
+          }
+        }
+        else {
+          if (fvbTrackTypeOn[ETrackType::kSec]) { fvpTrackHistograms[ETrackType::kSec]->FillMCTrack(iTrkMC); }
 
-      // Cut tracks, which did not leave hits in tracker
-      if (mcTrk.GetNofHits() == 0) { continue; }
+          if (fvbTrackTypeOn[ETrackType::kSecPIP] && std::abs(pdg) == 211) {
+            fvpTrackHistograms[ETrackType::kSecPIP]->FillMCTrack(iTrkMC);
+          }
 
-      // Fill different track categories
-      fvpTrackHistograms[ETrackType::kAll]->FillMCTrack(iTrkMC);
+          if (fvbTrackTypeOn[ETrackType::kSecPIP] && pdg == +211) {
+            fvpTrackHistograms[ETrackType::kPrimPIP]->FillMCTrack(iTrkMC);
+          }
 
-      int pdg        = mcTrk.GetPdgCode();
-      bool isPrimary = mcTrk.IsPrimary();
+          if (fvbTrackTypeOn[ETrackType::kSecPIM] && pdg == -211) {
+            fvpTrackHistograms[ETrackType::kPrimPIM]->FillMCTrack(iTrkMC);
+          }
 
-      if (isPrimary) {
-        fvpTrackHistograms[ETrackType::kPrim]->FillMCTrack(iTrkMC);
+          if (fvbTrackTypeOn[ETrackType::kSecMU] && std::abs(pdg) == 13) {
+            fvpTrackHistograms[ETrackType::kSecMU]->FillMCTrack(iTrkMC);
+          }
 
-        if (pdg == +211) { fvpTrackHistograms[ETrackType::kPrimPIP]->FillMCTrack(iTrkMC); }
-        if (pdg == -211) { fvpTrackHistograms[ETrackType::kPrimPIM]->FillMCTrack(iTrkMC); }
-      }
-      else {
-        fvpTrackHistograms[ETrackType::kSec]->FillMCTrack(iTrkMC);
+          if (fvbTrackTypeOn[ETrackType::kSecMUP] && pdg == +13) {
+            fvpTrackHistograms[ETrackType::kSecMUP]->FillMCTrack(iTrkMC);
+          }
 
-        if (pdg == +211) { fvpTrackHistograms[ETrackType::kSecPIP]->FillMCTrack(iTrkMC); }
-        if (pdg == -211) { fvpTrackHistograms[ETrackType::kSecPIM]->FillMCTrack(iTrkMC); }
+          if (fvbTrackTypeOn[ETrackType::kSecMUM] && pdg == -13) {
+            fvpTrackHistograms[ETrackType::kSecMUM]->FillMCTrack(iTrkMC);
+          }
+        }
       }
     }
   }
@@ -183,24 +314,229 @@ InitStatus OutputQa::InitDataBranches()
 InitStatus OutputQa::InitHistograms()
 {
   auto RegisterTrackQa = [&](const char* typeName, ETrackType type, bool bSuppressMC = false) {
+    if (!fvbTrackTypeOn[type]) { return; }
     bool bUseMC              = IsMCUsed() && !bSuppressMC;
     fvpTrackHistograms[type] = std::make_unique<TrackTypeQa>(typeName, fsPrefix.Data(), bUseMC, fpFolderRoot);
     fvpTrackHistograms[type]->RegisterParameters(fpParameters);
     fvpTrackHistograms[type]->RegisterRecoHits(fvHits);
     fvpTrackHistograms[type]->RegisterRecoTracks(fvRecoTracks);
     fvpTrackHistograms[type]->RegisterMCData(fMCData);
+
+    if constexpr (kEXPTRACKFILL) {
+      // Define track cuts
+      switch (type) {
+        //
+        // General
+        case ETrackType::kAll: break;
+        case ETrackType::kGhost:
+          fvpTrackHistograms[type]->SetRecoTrackCut([](const CbmL1Track& t) -> bool { return t.IsGhost(); });
+          break;
+        case kPrim:
+          fvpTrackHistograms[type]->SetMCTrackCut([](const MCTrack& t) -> bool { return t.IsPrimary(); });
+          break;
+        case kSec:
+          fvpTrackHistograms[type]->SetMCTrackCut([](const MCTrack& t) -> bool { return !t.IsPrimary(); });
+          break;
+        //
+        // Electrons
+        case kAllE:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return std::abs(t.GetPdgCode()) == 11; });
+          break;
+        case kPrimE:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && std::abs(t.GetPdgCode()) == 11; });
+          break;
+        case kPrimEP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == -11; });
+          break;
+        case kPrimEM:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == 11; });
+          break;
+        case kSecE:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && std::abs(t.GetPdgCode()) == 11; });
+          break;
+        case kSecEP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == -11; });
+          break;
+        case kSecEM:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == 11; });
+          break;
+        //
+        // Muons
+        case kAllMU:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return std::abs(t.GetPdgCode()) == 13; });
+          break;
+        case kPrimMU:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && std::abs(t.GetPdgCode()) == 13; });
+          break;
+        case kPrimMUP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == -13; });
+          break;
+        case kPrimMUM:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == 13; });
+          break;
+        case kSecMU:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && std::abs(t.GetPdgCode()) == 13; });
+          break;
+        case kSecMUP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == -13; });
+          break;
+        case kSecMUM:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == 13; });
+          break;
+        //
+        // Pions
+        case kAllPI:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return std::abs(t.GetPdgCode()) == 211; });
+          break;
+        case kPrimPI:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && std::abs(t.GetPdgCode()) == 211; });
+          break;
+        case kPrimPIP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == 211; });
+          break;
+        case kPrimPIM:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == -211; });
+          break;
+        case kSecPI:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && std::abs(t.GetPdgCode()) == 211; });
+          break;
+        case kSecPIP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == 211; });
+          break;
+        case kSecPIM:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == -211; });
+          break;
+        //
+        // Kaons
+        case kAllK:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return std::abs(t.GetPdgCode()) == 211; });
+          break;
+        case kPrimK:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && std::abs(t.GetPdgCode()) == 321; });
+          break;
+        case kPrimKP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == 321; });
+          break;
+        case kPrimKM:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == -321; });
+          break;
+        case kSecK:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && std::abs(t.GetPdgCode()) == 321; });
+          break;
+        case kSecKP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == 321; });
+          break;
+        case kSecKM:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == -321; });
+          break;
+        //
+        // Protons
+        case kAllPPBAR:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return std::abs(t.GetPdgCode()) == 2212; });
+          break;
+        case kPrimPPBAR:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && std::abs(t.GetPdgCode()) == 2212; });
+          break;
+        case kPrimP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == 2212; });
+          break;
+        case kPrimPBAR:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return t.IsPrimary() && t.GetPdgCode() == -2212; });
+          break;
+        case kSecPPBAR:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && std::abs(t.GetPdgCode()) == 2212; });
+          break;
+        case kSecP:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == 2212; });
+          break;
+        case kSecPBAR:
+          fvpTrackHistograms[type]->SetMCTrackCut(
+            [](const MCTrack& t) -> bool { return !t.IsPrimary() && t.GetPdgCode() == -2212; });
+          break;
+      }
+    }
+
     fvpTrackHistograms[type]->Init();
   };
 
-  RegisterTrackQa("ghost", ETrackType::kGhost, /*suppress MC*/ true);
+  for (int i = 0; i < ETrackType::kEND; ++i) {
+    LOG(info) << i << ' ' << fvpTrackHistograms[i].get() << ' ' << fvbTrackTypeOn[i];
+  }
+
   RegisterTrackQa("all", ETrackType::kAll);
   if (IsMCUsed()) {
+    RegisterTrackQa("ghost", ETrackType::kGhost, /*suppress MC*/ true);
     RegisterTrackQa("prim", ETrackType::kPrim);
     RegisterTrackQa("sec", ETrackType::kSec);
+    RegisterTrackQa("all_pi", ETrackType::kAllPI);
+    RegisterTrackQa("prim_pi", ETrackType::kPrimPI);
     RegisterTrackQa("prim_pip", ETrackType::kPrimPIP);
     RegisterTrackQa("prim_pim", ETrackType::kPrimPIM);
+    RegisterTrackQa("sec_pi", ETrackType::kSecPI);
     RegisterTrackQa("sec_pip", ETrackType::kSecPIP);
     RegisterTrackQa("sec_pim", ETrackType::kSecPIM);
+    RegisterTrackQa("all_e", ETrackType::kAllE);
+    RegisterTrackQa("prim_e", ETrackType::kPrimE);
+    RegisterTrackQa("prim_ep", ETrackType::kPrimEP);
+    RegisterTrackQa("prim_em", ETrackType::kPrimEM);
+    RegisterTrackQa("sec_e", ETrackType::kSecE);
+    RegisterTrackQa("sec_ep", ETrackType::kSecEP);
+    RegisterTrackQa("sec_em", ETrackType::kSecEM);
+    RegisterTrackQa("all_mu", ETrackType::kAllMU);
+    RegisterTrackQa("prim_mu", ETrackType::kPrimMU);
+    RegisterTrackQa("prim_mup", ETrackType::kPrimMUP);
+    RegisterTrackQa("prim_mum", ETrackType::kPrimMUM);
+    RegisterTrackQa("sec_mu", ETrackType::kSecMU);
+    RegisterTrackQa("sec_mup", ETrackType::kSecMUP);
+    RegisterTrackQa("sec_mum", ETrackType::kSecMUM);
+    RegisterTrackQa("all_k", ETrackType::kAllK);
+    RegisterTrackQa("prim_k", ETrackType::kPrimK);
+    RegisterTrackQa("prim_kp", ETrackType::kPrimKP);
+    RegisterTrackQa("prim_km", ETrackType::kPrimKM);
+    RegisterTrackQa("sec_k", ETrackType::kSecK);
+    RegisterTrackQa("sec_kp", ETrackType::kSecKP);
+    RegisterTrackQa("sec_km", ETrackType::kSecKM);
+    RegisterTrackQa("all_ppbar", ETrackType::kAllPPBAR);
+    RegisterTrackQa("prim_ppbar", ETrackType::kPrimPPBAR);
+    RegisterTrackQa("prim_p", ETrackType::kPrimP);
+    RegisterTrackQa("prim_pbar", ETrackType::kPrimPBAR);
+    RegisterTrackQa("sec_ppbar", ETrackType::kSecPPBAR);
+    RegisterTrackQa("sec_p", ETrackType::kSecP);
+    RegisterTrackQa("sec_pbar", ETrackType::kSecPBAR);
   }
 
   return kSUCCESS;
@@ -230,6 +566,7 @@ InitStatus OutputQa::InitTimeSlice()
   LOG_IF(info, fVerbose > 1) << fName << ": Data sample consists of " << nHits << " hits, " << nRecoTracks
                              << " reco tracks, " << nMCTracks << " MC tracks, " << nMCPoints << " MC points";
 
+
   return kSUCCESS;
 }
 
diff --git a/reco/L1/qa/CbmCaOutputQa.h b/reco/L1/qa/CbmCaOutputQa.h
index cd7ebc203692728682545da907c23fd2b3843adf..2cac1f21bc4c6d637c0dc8a918714d852c74eccb 100644
--- a/reco/L1/qa/CbmCaOutputQa.h
+++ b/reco/L1/qa/CbmCaOutputQa.h
@@ -25,62 +25,92 @@
 
 namespace cbm::ca
 {
+  /// @brief Enumeration of track category
+  enum ETrackType
+  {
+    kAll,        ///< all tracks
+    kGhost,      ///< ghost tracks (no MC is used)
+    kPrim,       ///< primary
+    kSec,        ///< secondary
+    kAllE,       ///< all e-/e+
+    kPrimE,      ///< primary e-/e+
+    kPrimEP,     ///< primary e+
+    kPrimEM,     ///< primary e-
+    kSecE,       ///< secondary e-/e+
+    kSecEP,      ///< secondary e+
+    kSecEM,      ///< secondary e-
+    kAllMU,      ///< all mu+/mu-
+    kPrimMU,     ///< primary mu+/mu-
+    kPrimMUP,    ///< primary mu+
+    kPrimMUM,    ///< primary mu-
+    kSecMU,      ///< secondary mu+/mu-
+    kSecMUP,     ///< secondary mu+
+    kSecMUM,     ///< secondary mu-
+    kAllPI,      ///< all pi+/pi-
+    kPrimPI,     ///< primary pi+/pi-
+    kPrimPIP,    ///< primary pi+
+    kPrimPIM,    ///< primary pi-
+    kSecPI,      ///< secondary pi+/pi-
+    kSecPIP,     ///< secondary pi+
+    kSecPIM,     ///< secondary pi-
+    kAllK,       ///< all K+/K-
+    kPrimK,      ///< primary K+/K-
+    kPrimKP,     ///< primary K+
+    kPrimKM,     ///< primary K-
+    kSecK,       ///< secondary K+/K-
+    kSecKP,      ///< secondary K+
+    kSecKM,      ///< secondary K-
+    kAllPPBAR,   ///< all p/p-bar
+    kPrimPPBAR,  ///< primary p/p-bar
+    kPrimP,      ///< primary p
+    kPrimPBAR,   ///< primary p-bar
+    kSecPPBAR,   ///< secondary p/p-bar
+    kSecP,       ///< secondary p
+    kSecPBAR,    ///< secondary p-bar
+    // kPrimD,
+    // kPrimDBAR,
+    // kSecD,
+    // kSecDBAR,
+    // kPrimT,
+    // kPrimTBAR,
+    // kSecT,
+    // kSecTBAR,
+    // kPrim3HE,
+    // kPrim3HEBAR,
+    // kSec3HE,
+    // kSec3HEBAR,
+    // kPrim4HE,
+    // kPrim4HEBAR,
+    // kSec4HE,
+    // kSec4HEBAR,
+    kEND
+  };
+
   /// @brief  QA-task for CA tracking output results
   ///
   class OutputQa : public CbmQaTask {
-  public:
-    /// @brief Enumeration of track category
-    enum ETrackType
-    {
-      kAll,    ///< all tracks
-      kGhost,  ///< ghost tracks (no MC is used)
-      kPrim,   ///< primary tracks
-      kSec,    ///< secondary tracks
-      // kPrimEP,  ///< primary electron tracks
-      // kPrimEM,  ///< primary positron tracks
-      // kSecEP,   ///< secondary electron tracks
-      // kSecEM,   ///< secondary positron tracks
-      // kPrimMUP, ///< primary .....
-      // kPrimMUM,
-      // kSecMUP,
-      // kSecMUM,
-      kPrimPIP,
-      kPrimPIM,
-      kSecPIP,
-      kSecPIM,
-      // kPrimKP,
-      // kPrimKM,
-      // kSecKP,
-      // kSecKM,
-      // kPrimP,
-      // kPrimPBAR,
-      // kSecP,
-      // kSecPBAR,
-      // kPrimD,
-      // kPrimDBAR,
-      // kSecD,
-      // kSecDBAR,
-      // kPrimT,
-      // kPrimTBAR,
-      // kSecT,
-      // kSecTBAR,
-      // kPrim3HE,
-      // kPrim3HEBAR,
-      // kSec3HE,
-      // kSec3HEBAR,
-      // kPrim4HE,
-      // kPrim4HEBAR,
-      // kSec4HE,
-      // kSec4HEBAR,
-      kEND
-    };
-
+    // WIP: Temporary flag to switch between two different approaches of filling track type histograms
+    //
+    // 1) Experimental approach (kEXPTRACKFILL = true) utilizes unified filling based on defined reco and MC cuts.
+    // 2) Feature is to be studied more precisely (descrepancy in primary/secondary track with a standard approach)
+    // 3) Experimental approach runs in ~10% slower, then the standard
+    static constexpr bool kEXPTRACKFILL = false;
 
+  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 Adds track type
+    /// @param type  Track type
+    /// @param flag  Flag: true/false
+    ///
+    /// Adds a track type for building distributions. By default, only all, primary, secondary and ghost track
+    /// distributions are booked.
+    void AddTrackType(ETrackType type, bool flag = true);
+
+
     /// @brief Enables debugger
     /// @param filename  Name of output ROOT file
     ///
@@ -149,6 +179,11 @@ namespace cbm::ca
     /// @brief De-initializes histograms
     void DeInit() {}
 
+    /// @brief Fills histograms for a given track types
+    /// @param type  Track type
+    /// @param
+    void FillTrackTypeHistograms();
+
   private:
     // Flags for detector subsystems being used
     bool fbUseMvd  = false;  ///< is MVD used
@@ -179,8 +214,7 @@ namespace cbm::ca
 
     /// Histograms of different track types
     std::array<std::unique_ptr<TrackTypeQa>, ETrackType::kEND> fvpTrackHistograms;
-
-    std::array<std::tuple<Style_t, Marker_t, Color_t>, ETrackType::kEND> fvpTrackHistogramStyles;
+    std::array<bool, ETrackType::kEND> fvbTrackTypeOn = {0};  ///< Track type is on
   };
 }  // namespace cbm::ca
 
diff --git a/reco/L1/qa/CbmCaTrackTypeQa.cxx b/reco/L1/qa/CbmCaTrackTypeQa.cxx
index eed783fb873e9fbf047ce6912d99920d5f5f9c44..77a329d086ea4634bb07e57baf92a1d53199f387 100644
--- a/reco/L1/qa/CbmCaTrackTypeQa.cxx
+++ b/reco/L1/qa/CbmCaTrackTypeQa.cxx
@@ -179,6 +179,33 @@ void TrackTypeQa::FillRecoTrack(int iTrkReco, double weight)
   }
 }
 
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TrackTypeQa::FillRecoTracks()
+{
+  for (int iTrkReco = 0; iTrkReco < (int) fpvRecoTracks->size(); ++iTrkReco) {
+    const auto& recoTrk = (*fpvRecoTracks)[iTrkReco];
+
+    // Reject tracks, which do not contain hits
+    if (recoTrk.GetNofHits() < 1) { continue; }
+
+    // Reject tracks, which do not pass the applied cuts
+    if (!fRecoTrackCut(recoTrk)) { continue; }
+
+    // Reject tracks, which have MC tracks not passing the applied cuts
+    if (fbUseMC) {
+      int iTrkMC = recoTrk.GetMatchedMCTrackIndex();
+      if (iTrkMC > -1) {
+        const auto& mcTrk = fpMCData->GetTrack(iTrkMC);
+        if (!fMCTrackCut(mcTrk)) { continue; }
+      }
+    }
+
+    // Fill histograms
+    this->FillRecoTrack(iTrkReco);
+  }
+}
+
 // ---------------------------------------------------------------------------------------------------------------------
 //
 void TrackTypeQa::FillMCTrack(int iTrkMC, double weight)
@@ -210,3 +237,25 @@ void TrackTypeQa::FillMCTrack(int iTrkMC, double weight)
   fph_eff_pMC_yMC->Fill(mcTrack.GetRapidity(), mcTrack.GetP(), bReco);
   fph_eff_thetaMC_phiMC->Fill(mcTrack.GetPhi(), mcTrack.GetPhi(), bReco);
 }
+
+// ---------------------------------------------------------------------------------------------------------------------
+//
+void TrackTypeQa::FillMCTracks()
+{
+  assert(fbUseMC);
+  for (int iTrkMC = 0; iTrkMC < fpMCData->GetNofTracks(); ++iTrkMC) {
+    const auto& mcTrk = fpMCData->GetTrack(iTrkMC);
+
+    // Cut tracks, which did not leave hits in tracker
+    if (mcTrk.GetNofHits() == 0) { continue; }
+
+    // Cut tracks, which do not pass the applied cut
+    if (!fMCTrackCut(mcTrk)) { continue; }
+
+    // TODO: Investigate, how to apply reconstructed track cuts here
+    // NOTE: Reconstructed track cut analogs must be applied to mc tracks
+
+    // Fill histograms
+    this->FillMCTrack(iTrkMC);
+  }
+}
diff --git a/reco/L1/qa/CbmCaTrackTypeQa.h b/reco/L1/qa/CbmCaTrackTypeQa.h
index 13acc148490ab9147d28031f757609c450ebd12f..73d284fcd74c8d0def7c4fff747495589f5f175c 100644
--- a/reco/L1/qa/CbmCaTrackTypeQa.h
+++ b/reco/L1/qa/CbmCaTrackTypeQa.h
@@ -23,7 +23,8 @@
 namespace ca::tools
 {
   class MCData;
-}
+  class MCTrack;
+}  // namespace ca::tools
 class CbmL1Track;
 class CbmL1HitDebugInfo;
 
@@ -69,18 +70,31 @@ namespace cbm::ca
     /// @brief Initializes histograms
     void Init();
 
+    /// @brief Flag on MC usage by the track type
+    /// @return true  Histograms relied on MC info are filled
+    /// @return false Histograms relied on MC info are not filled
+    bool IsMCUsed() const { return fbUseMC; }
+
     /// @brief Fills histograms with various track information
     /// @note  To be called in the loop over reconstructed tracks full sample
     /// @param iTrkReco  Index of reconstructed track
     /// @param weight    Weight
     void FillRecoTrack(int iTrkReco, double weight = 1);
 
+    /// @brief Fills histograms with recon tracks
+    /// @note  To be called once per event/TS
+    void FillRecoTracks();
+
     /// @brief Fills histograms with mc track information
     /// @note  To be called in the loop over MC tracks full sample
     /// @param iTrkMC  Index of MC track
     /// @param weight  Weight
     void FillMCTrack(int iTrkMC, double weight = 1);
 
+    /// @brief Fills histograms with recon tracks
+    /// @note  To be called once per event/TS
+    void FillMCTracks();
+
     /// @brief Registers the reconstructed tracks container
     /// @param vTracks  Reference to reconstructed tracks container
     void RegisterRecoTracks(L1Vector<CbmL1Track>& vTracks) { fpvRecoTracks = &vTracks; }
@@ -101,6 +115,18 @@ namespace cbm::ca
     /// @param title  Title of track type
     void SetTitle(const char* title) { fsTitle = title; }
 
+    /// @brief Sets selection cuts on MC tracks
+    /// @param cut  Functor <bool(const MCTrack&)> defining cut on MC track
+    ///
+    /// When function returns false,
+    void SetMCTrackCut(std::function<bool(const ::ca::tools::MCTrack&)> cut) { fMCTrackCut = cut; }
+
+    /// @brief Sets selection cuts on reconstructed tracks
+    /// @param cut  Functor <bool(const CbmL1Track&)> defining cut on reconstructed track
+    ///
+    /// When function returns false,
+    void SetRecoTrackCut(std::function<bool(const CbmL1Track&)> cut) { fRecoTrackCut = cut; }
+
     // ************************
     // ** List of histograms **
     // ************************
@@ -177,6 +203,15 @@ namespace cbm::ca
     ::ca::tools::MCData* fpMCData              = nullptr;  ///< Pointer to MC data object
     std::shared_ptr<L1Parameters> fpParameters = nullptr;  ///< Pointer to parameters object
 
+    // ** Cuts on tracks for a given track class **
+
+    /// Cut function on MC tracks
+    std::function<bool(const ::ca::tools::MCTrack&)> fMCTrackCut = [](const ::ca::tools::MCTrack&) { return true; };
+
+    /// Cut function on reconstructed tracks
+    std::function<bool(const CbmL1Track&)> fRecoTrackCut = [](const CbmL1Track&) { return true; };
+
+
     // **************************
     // ** Histogram properties **
     // **************************