diff --git a/reco/qa/CbmRecoQaTask.cxx b/reco/qa/CbmRecoQaTask.cxx
index cbca9816885c980447e8e80557bb27bca04909fc..259210dc0bc8d04b1caff856e418143974fb52bb 100644
--- a/reco/qa/CbmRecoQaTask.cxx
+++ b/reco/qa/CbmRecoQaTask.cxx
@@ -53,17 +53,15 @@ InitStatus CbmRecoQaTask::Init()
   }
 
   LOG(info) << GetName() << "::Init: Registered projections " << fProjView.size();
-  for (auto zprj : fProjView)
-    LOG(debug) << GetName() << "::Init: Project trks @ " << zprj.first;
 
-  int itrkLy(0);
+  int itrkLy(0), iprjLy(0);
   TFolder *modDir(nullptr), *smDir(nullptr);
   fOutFolder.Clear();
   switch (fSetupClass) {
     case kMcbm22:
       LOG(info) << GetName() << "::Init: Setup config for \"mCBM 2022\".";
-      modDir = fOutFolder.AddFolder("STS", "STS reziduals to CA");
       // STS U0 - station 0
+      modDir = fOutFolder.AddFolder("STS", "STS reziduals to CA");
       fModView[itrkLy].push_back(ModuleView());
       fModView[itrkLy][0].hdXx.first = 10;
       fModView[itrkLy][0].hdXx.second =
@@ -105,6 +103,7 @@ InitStatus CbmRecoQaTask::Init()
         new TH2D(Form("hpully%d", itrkLy), Form("STS U1 pully-tht; dy/dz_{trk}; pull Y"), 160, -0.8, 0.8, 100, -5, 5);
       modDir->Add(fModView[itrkLy][0].hpullYtht);
       itrkLy++;
+
       // ===============================================================================
       modDir = fOutFolder.AddFolder("TRD", "TRD reziduals to CA");
       // TRD 2D - station 2
@@ -170,10 +169,11 @@ InitStatus CbmRecoQaTask::Init()
         new TH2D(Form("hpully%d", itrkLy), Form("TRD1Dy pully-tht; dy/dz_{trk}; pull Y"), 100, -0.5, 0.5, 100, -5, 5);
       modDir->Add(fModView[itrkLy][0].hpullYtht);
       itrkLy++;
+
       // ===============================================================================
-      modDir = fOutFolder.AddFolder("ToF", "ToF reziduals to CA");
       // ToF Sm0 & Sm3 (Typ0) - station 5
-      smDir = modDir->AddFolder("SM0_0", "ToF reziduals to CA for Sm0 and Sm3 type 0");
+      modDir = fOutFolder.AddFolder("ToF", "ToF reziduals to CA");
+      smDir  = modDir->AddFolder("SM0_0", "ToF reziduals to CA for Sm0 and Sm3 type 0");
       for (int irpc(0); irpc < 5; irpc++) {
         fModView[itrkLy].push_back(ModuleView());
         ModuleView* cdet = &fModView[itrkLy][irpc];
@@ -202,7 +202,6 @@ InitStatus CbmRecoQaTask::Init()
         smDir->Add(cdet->hpullYtht);
       }
       itrkLy++;
-
       // ToF Sm1 (Typ0) - station 6
       smDir = modDir->AddFolder("SM1_0", "ToF reziduals to CA for Sm1 type 0");
       for (int irpc(0); irpc < 5; irpc++) {
@@ -233,7 +232,6 @@ InitStatus CbmRecoQaTask::Init()
         smDir->Add(cdet->hpullYtht);
       }
       itrkLy++;
-
       // ToF Sm0 (Typ2) - station 7
       smDir = modDir->AddFolder("SM0_2", "ToF reziduals to CA for Sm0 type 2");
       for (int irpc(0); irpc < 5; irpc++) {
@@ -264,7 +262,6 @@ InitStatus CbmRecoQaTask::Init()
         smDir->Add(cdet->hpullYtht);
       }
       itrkLy++;
-
       // ToF Sm2 (Typ0) - station 8
       smDir = modDir->AddFolder("SM2_0", "ToF reziduals to CA for Sm2 type 0");
       for (int irpc(0); irpc < 5; irpc++) {
@@ -294,6 +291,27 @@ InitStatus CbmRecoQaTask::Init()
                    -0.45, 0.45, 100, -5, 5);
         smDir->Add(cdet->hpullYtht);
       }
+      itrkLy++;
+
+      // ===============================================================================
+      // TRG - upstream projections
+      modDir = fOutFolder.AddFolder("Target", "Target tomography with CA");
+      iprjLy = itrkLy;
+      for (auto zprj : fProjView) {
+        LOG(debug) << GetName() << "::Init: Project trks @ " << zprj.first;
+        fModView[iprjLy].push_back(ModuleView());
+        fModView[iprjLy][0].hdXx.first = 1;
+        fModView[iprjLy][0].hdXx.second =
+          new TH2D(Form("hxy%d", iprjLy - itrkLy), Form("Project @ z = %+5.2f; X_{trk} (cm); Y_{trk} (cm)", zprj.first),
+                   700, -25, 10, 100, -5, 5);
+        modDir->Add(fModView[iprjLy][0].hdXx.second);
+        fModView[iprjLy][0].hdYy.first = 1;
+        fModView[iprjLy][0].hdYy.second =
+          new TH2D(Form("hxt%d", iprjLy), Form("Project @ z = %+5.2f; X_{trk} (cm); T_{trk} - T_{ev} (ns)", zprj.first),
+                   700, -25, 10, 350, -15.5, 5.5);
+        modDir->Add(fModView[iprjLy][0].hdYy.second);
+        iprjLy++;
+      }
       break;
     case kMcbm24: LOG(info) << GetName() << "::Init: Setup config for \"mCBM 2024\". Not implemented."; break;
     case kDefault: LOG(info) << GetName() << "::Init: Setup config for \"DEFAULT\". Not implemented."; break;
@@ -307,7 +325,7 @@ void CbmRecoQaTask::Exec(Option_t*)
 {
   LOG(debug) << GetName() << "::Exec : Evs[" << (fEvents ? fEvents->GetEntriesFast() : 0) << "] Trks["
              << fTracks->GetEntriesFast() << "]";
-  int itrack(0);
+  int itrack(0), nnodes(0);
   for (auto trackObj : *fTracks) {
     //printf("GlobalTrack %d\n", itrack);
     auto track = dynamic_cast<const CbmGlobalTrack*>(trackObj);
@@ -318,15 +336,12 @@ void CbmRecoQaTask::Exec(Option_t*)
     }
     trkKf.fMsQp0      = 1. / 0.5;
     trkKf.fIsMsQp0Set = true;
+    if (!nnodes) nnodes = (int) trkKf.fNodes.size();
 
+    // minimalistic QA tool for tracks used for target projection
+    int nhit[(size_t) ECbmModuleId::kLastModule] = {0};
     for (auto& n : trkKf.fNodes) {
       if (n.fHitSystemId == ECbmModuleId::kNotExist) continue;
-      //printf("  %d z[%6.2f]\n", n.fMaterialLayer, n.fZ);
-      //printf("    D[%d] hit[%d %d] Flags[%c %c %c %c]\n",
-      //       (int)n.fHitSystemId, n.fHitAddress, n.fHitIndex,
-      //       (n.fIsXySet ? 'y' : 'n'), (n.fIsTimeSet ? 'y' : 'n'), (n.fIsFitted ? 'y' : 'n'), (n.fIsRadThickSet ? 'y' : 'n'));
-      //printf("    hit x[%+6.2f] y[%+6.2f] t[%f]\n", (double)n.fMxy.X()[0], (double)n.fMxy.Y()[0], (double)n.fMt.T()[0]);
-
       n.fIsTimeSet = false;
       n.fIsXySet   = false;
       trkKf.MakeConsistent();
@@ -334,20 +349,33 @@ void CbmRecoQaTask::Exec(Option_t*)
       double dx = n.fMxy.X()[0] - n.fTrack.X()[0], dy = n.fMxy.Y()[0] - n.fTrack.Y()[0],
              dt    = n.fMt.T()[0] - n.fTrack.Time()[0],
              pullx = dx / sqrt(n.fMxy.Dx2()[0] + n.fTrack.GetCovariance(0, 0)[0]),
-             pully = dy / sqrt(n.fMxy.Dy2()[0] + n.fTrack.GetCovariance(1, 1)[0]),
-             pullt = dt / sqrt(n.fMt.Dt2()[0] + n.fTrack.GetCovariance(5, 5)[0]);
-      //printf("    res dx[%+6.4f] dy[%+6.4f] dt[%+6.4f]\n    pull x[%+6.4f]  y[%+6.4f]  t[%+6.4f]\n", dx, dy, dt, pullx, pully, pullt);
+             pully = dy / sqrt(n.fMxy.Dy2()[0] + n.fTrack.GetCovariance(1, 1)[0]);
+      // pullt = dt / sqrt(n.fMt.Dt2()[0] + n.fTrack.GetCovariance(5, 5)[0]);
 
       // add granularity for specific systems
       int modId = 0;
-      if (n.fHitSystemId == ECbmModuleId::kTof) modId = CbmTofAddress::GetRpcId(n.fHitAddress);
+      switch (n.fHitSystemId) {
+        case ECbmModuleId::kTof:
+          modId = CbmTofAddress::GetRpcId(n.fHitAddress);
+          nhit[(int) n.fHitSystemId]++;
+          break;
+        default: nhit[(int) n.fHitSystemId]++; break;
+      }
 
       // check that we have correctly created all views
-      if (fModView.find(n.fMaterialLayer) == fModView.end()) continue;
-      if (fModView[n.fMaterialLayer].size() <= (size_t) modId) continue;
+      if (fModView.find(n.fMaterialLayer) == fModView.end()) {
+        LOG(debug) << GetName() << "::Exec: view for tracking layer " << n.fMaterialLayer << " not defined.";
+        continue;
+      }
+      if (fModView[n.fMaterialLayer].size() <= (size_t) modId) {
+        LOG(debug) << GetName() << "::Exec: view for tracking layer " << n.fMaterialLayer << " @ " << modId
+                   << " not defined.";
+        continue;
+      }
       ModuleView* mod = &fModView[n.fMaterialLayer][modId];
       if (!mod) {
-        LOG(warn) << GetName() << "::Exec: can not access mod view for " << modId;
+        LOG(warn) << GetName() << "::Exec: can not access view for tracking layer " << n.fMaterialLayer << " @ "
+                  << modId;
         continue;
       }
       if (mod->hdXx.second) mod->hdXx.second->Fill(n.fMxy.X()[0], mod->hdXx.first * dx);
@@ -367,6 +395,9 @@ void CbmRecoQaTask::Exec(Option_t*)
       n.fIsXySet   = true;
     }
 
+    // track QA filtering
+    if (!FilterTrack(nhit)) continue;
+
     // Fit track with all hits ON for vx projection
     int iprj(0);
     for (auto zprj : fProjView) {
@@ -380,7 +411,15 @@ void CbmRecoQaTask::Exec(Option_t*)
     fFitter.FitTrack(trkKf);
     for (auto& n : trkKf.fNodes) {
       if (n.fReference1 < 0) continue;
-      //printf("    prj[%d] z[%+6.4f] x[%+6.4f] y[%+6.4f] t[%+6.4f]\n", n.fReference1, n.fZ, (double)n.fTrack.X()[0], (double)n.fTrack.Y()[0], (double)n.fTrack.Time()[0]);
+      if (fModView.find(n.fReference1 + nnodes) == fModView.end()) {
+        LOG(debug) << GetName() << "::Exec: view for tracking layer " << n.fReference1 + nnodes << " not defined.";
+        continue;
+      }
+      ModuleView* mod = &fModView[n.fReference1 + nnodes][0];
+
+      if (mod->hdXx.second)
+        mod->hdXx.second->Fill(mod->hdXx.first * n.fTrack.X()[0], mod->hdXx.first * n.fTrack.Y()[0]);
+      if (mod->hdYy.second) mod->hdYy.second->Fill(mod->hdYy.first * n.fTrack.X()[0], n.fTrack.Time()[0]);
     }
     itrack++;
   }
@@ -395,6 +434,23 @@ void CbmRecoQaTask::SetProjections(std::vector<double> vzpj)
   }
 }
 
+//_____________________________________________________________________
+bool CbmRecoQaTask::FilterTrack(int* ptr)
+{
+  bool ret = false;
+  switch (fSetupClass) {
+    case kMcbm22: {
+      int* nhit = ptr;
+      if (nhit[int(ECbmModuleId::kSts)] == 2 && nhit[int(ECbmModuleId::kTrd2d)] && nhit[int(ECbmModuleId::kTof)])
+        ret = true;
+      break;
+    }
+    case kMcbm24: break;
+    case kDefault: break;
+  }
+  return ret;
+}
+
 //_____________________________________________________________________
 void CbmRecoQaTask::Finish()
 {
diff --git a/reco/qa/CbmRecoQaTask.h b/reco/qa/CbmRecoQaTask.h
index 156088158fc38da5371fe2c4017b688caf6cf121..44dca4e5d08b3c6959cb9e3de45e1d81aa2747cc 100644
--- a/reco/qa/CbmRecoQaTask.h
+++ b/reco/qa/CbmRecoQaTask.h
@@ -34,6 +34,11 @@ class CbmRecoQaTask : public FairTask {
   /** \brief Executed task **/
   virtual void Exec(Option_t* option);
 
+  /** \brief Filter tracks for further use (e.g. track projections) 
+   * \param[in] ptr information on which to filter (e.g. nhits from detectors)
+   * \return true if track accepted
+   */
+  virtual bool FilterTrack(int* ptr);
   virtual void Finish();
 
   /** \brief Define the set of extra z positions where the track should be projected in the x-y plane */