diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx
index a52f9a5ac4f88050be6eb8af5e0f5a99c607fbf3..7637594e20f8c0381a3fe9a3b85ad0674b224948 100644
--- a/algo/global/Reco.cxx
+++ b/algo/global/Reco.cxx
@@ -262,10 +262,10 @@ RecoResults Reco::Run(const fles::Timeslice& ts)
     if (fStsHitFinder) {
       xpu::scoped_timer timerSTS("STS Reco", &procMon.timeSTS);
       xpu::t_add_bytes(digis.fSts.size() * sizeof(CbmStsDigi));
-      bool storeClusters  = Opts().HasOutput(RecoData::Cluster);
-      auto stsResults     = (*fStsHitFinder)(digis.fSts, storeClusters);
-      stsHitfinderMonitor = std::move(stsResults.monitor);
-      recoData.stsHits    = stsResults.hits;
+      bool storeClusters   = Opts().HasOutput(RecoData::Cluster);
+      auto stsResults      = (*fStsHitFinder)(digis.fSts, storeClusters);
+      stsHitfinderMonitor  = std::move(stsResults.monitor);
+      recoData.stsHits     = stsResults.hits;
       recoData.stsClusters = std::move(stsResults.clusters);
       QueueStsRecoMetrics(stsHitfinderMonitor);
     }
@@ -321,7 +321,7 @@ RecoResults Reco::Run(const fles::Timeslice& ts)
       recoData.tracks = std::move(trackingOutput.tracks);
       std::sort(recoData.tracks.begin(), recoData.tracks.end(),
                 [](const cbm::algo::ca::Track& track1, const cbm::algo::ca::Track& track2) {
-                  return track1.fParFirst.Time() < track2.fParFirst.Time();
+                  return track1.fParPV.Time() < track2.fParPV.Time();
                 });
       QueueTrackingMetrics(trackingOutput.monitorData);
     }
diff --git a/algo/trigger/V0Trigger.cxx b/algo/trigger/V0Trigger.cxx
index 041ad7469bd8f4d2c3af1b9cef0e2b49ce4d1191..bf9264801a9a444d56dac990a8998f3cc3da511a 100644
--- a/algo/trigger/V0Trigger.cxx
+++ b/algo/trigger/V0Trigger.cxx
@@ -22,26 +22,30 @@ namespace cbm::algo::evbuild
 
     Result result;
 
+    size_t numTracksUsed = 0;
     for (auto trackIter1 = tracks.begin(); trackIter1 != tracks.end(); trackIter1++) {
+      if (!Select(*trackIter1, config)) continue;
+      numTracksUsed++;
       for (auto trackIter2 = std::next(trackIter1); trackIter2 != tracks.end(); trackIter2++) {
+        if (!Select(*trackIter2, config)) continue;
 
         // Check track time difference
-        float time1 = trackIter1->fParFirst.GetTime();
-        float time2 = trackIter2->fParFirst.GetTime();
+        float time1 = trackIter1->fParPV.GetTime();
+        float time2 = trackIter2->fParPV.GetTime();
         if (time2 < time1) {
           result.second.errTracksUnsorted++;
           continue;
         }
         result.second.numTrackPairs++;
-        if (time2 - time1 > config.CutTime()) break;
+        if (time2 - time1 > config.PairDeltaT_max()) break;
         result.second.numTrackPairsAfterTimeCut++;
 
         // Check PCA cuts
-        auto [zVertex, dist] = CalcPCA(trackIter1->fParFirst, trackIter2->fParFirst);
-        if (zVertex > config.CutZ()) {
-          result.second.numTrackPairsAfterZCut++;
-          if (dist < config.CutDist()) {
-            result.second.numTrackPairsAfterDistCut++;
+        auto [zVertex, dist] = CalcPCA(trackIter1->fParPV, trackIter2->fParPV);
+        if (dist < config.PairDist_max()) {
+          result.second.numTrackPairsAfterDistCut++;
+          if (zVertex >= config.PairZ_min() && zVertex <= config.PairZ_max()) {
+            result.second.numTrackPairsAfterZCut++;
             double tVertex = 0.5 * (time1 + time2);
             result.first.push_back(tVertex);
           }
@@ -50,9 +54,10 @@ namespace cbm::algo::evbuild
     }
 
     result.second.time = xpu::pop_timer();
-    L_(info) << "V0Trigger: tracks " << tracks.size() << ", track pairs " << result.second.numTrackPairs
-             << ", after time cut " << result.second.numTrackPairsAfterTimeCut << ", after z cut "
-             << result.second.numTrackPairsAfterZCut << ", after dist cut " << result.second.numTrackPairsAfterDistCut;
+    L_(info) << "V0Trigger: tracks " << tracks.size() << ", unsorted " << result.second.errTracksUnsorted
+             << ", used tracks " << numTracksUsed << ", track pairs " << result.second.numTrackPairs
+             << ", after time cut " << result.second.numTrackPairsAfterTimeCut << ", after dist cut "
+             << result.second.numTrackPairsAfterDistCut << ", after z cut " << result.second.numTrackPairsAfterZCut;
     return result;
   };
 
@@ -89,6 +94,40 @@ namespace cbm::algo::evbuild
     return std::make_pair(z, dist);
   }
 
+
+  bool V0Trigger::Select(const Track& track, const V0TriggerConfig& config) const
+  {
+
+    // Minimum z at first measurement
+    if (!(track.fParFirst.Z() >= config.TrackStartZ_min())) return false;
+
+    // Maximum z at first measurement
+    if (!(track.fParFirst.Z() <= config.TrackStartZ_max())) return false;
+
+    // Minimum z at last measurement
+    if (!(track.fParLast.Z() >= config.TrackEndZ_min())) return false;
+
+    // Reject primaries
+    if (IsPrimary(track.fParPV, config)) return false;
+
+    return true;
+  };
+
+  bool V0Trigger::IsPrimary(const TrackParam& track, const V0TriggerConfig& config) const
+  {
+
+    // x coordinate of impact at target
+    if (track.X() < config.TrackImpactX_min()) return false;
+    if (track.X() > config.TrackImpactX_max()) return false;
+
+    // y coordinate of impact at target
+    if (track.Y() < config.TrackImpactY_min()) return false;
+    if (track.Y() > config.TrackImpactY_max()) return false;
+
+    return true;
+  }
+
+
   std::string V0Trigger::ToString() const
   {
     std::stringstream out;
diff --git a/algo/trigger/V0Trigger.h b/algo/trigger/V0Trigger.h
index 38b4b3c46f720706a7db9a8b5044aec4f7a145bb..fb553b8452327b63aa79c870b67925129509b93f 100644
--- a/algo/trigger/V0Trigger.h
+++ b/algo/trigger/V0Trigger.h
@@ -72,6 +72,18 @@ namespace cbm::algo::evbuild
      ** It should be a good criterion for the purpose of finding displaced vertices.
      **/
     std::pair<double, double> CalcPCA(const TrackParam& track1, const TrackParam& track2) const;
+
+    /** @brief Check track cuts 
+     ** @param track  Track
+     ** @return decision
+     **/
+    bool Select(const Track& track, const V0TriggerConfig& config) const;
+
+    /** @brief Check if track is a priomary 
+     ** @param track  Track parameters in target plane
+     ** @return decision
+     **/
+    bool IsPrimary(const TrackParam& track, const V0TriggerConfig& config) const;
   };
 
 }  // namespace cbm::algo::evbuild
diff --git a/algo/trigger/V0TriggerConfig.cxx b/algo/trigger/V0TriggerConfig.cxx
index 566565a842480d406eaa0e397815bc8ed569686c..6170756d276a2912d3830492444fca8dd0afa07f 100644
--- a/algo/trigger/V0TriggerConfig.cxx
+++ b/algo/trigger/V0TriggerConfig.cxx
@@ -15,20 +15,28 @@ namespace cbm::algo::evbuild
       fIsSet = false;
       return;
     }
+    fTrackStartZ_min  = GetDoubleRequired(config, "track_start_z_min");
+    fTrackStartZ_max  = GetDoubleRequired(config, "track_start_z_max");
+    fTrackEndZ_min    = GetDoubleRequired(config, "track_end_z_min");
+    fTrackImpactX_min = GetDoubleRequired(config, "track_impact_x_min");
+    fTrackImpactX_max = GetDoubleRequired(config, "track_impact_x_max");
+    fTrackImpactY_min = GetDoubleRequired(config, "track_impact_y_min");
+    fTrackImpactY_max = GetDoubleRequired(config, "track_impact_y_max");
+    fPairDeltaT_max   = GetDoubleRequired(config, "pair_deltaT_max");
+    fPairDist_max     = GetDoubleRequired(config, "pair_dist_max");
+    fPairZ_min        = GetDoubleRequired(config, "pair_z_min");
+    fPairZ_max        = GetDoubleRequired(config, "pair_z_max");
+    fIsSet            = true;
+  }
+  // --------------------------------------------------------------------------
 
-    auto cutTime = config["max_time_diff"];
-    if (!cutTime) throw std::runtime_error("time difference cut is not specified");
-    fCutTime = cutTime.as<double>();
-
-    auto cutZ = config["min_z_pca"];
-    if (!cutZ) throw std::runtime_error("PCA position cut is not specified");
-    fCutZ = cutZ.as<double>();
-
-    auto cutDist = config["max_dist_at_pca"];
-    if (!cutDist) throw std::runtime_error("track distance cut is not specified");
-    fCutDist = cutDist.as<size_t>();
 
-    fIsSet = true;
+  // -----   Geta a required double value from YAML   -------------------------
+  double V0TriggerConfig::GetDoubleRequired(const YAML::Node& config, const char* key)
+  {
+    auto value = config[key];
+    if (!value) throw std::runtime_error(key + std::string(" required but not defined"));
+    return value.as<double>();
   }
   // --------------------------------------------------------------------------
 
@@ -37,9 +45,17 @@ namespace cbm::algo::evbuild
   YAML::Node V0TriggerConfig::ToYaml() const
   {
     YAML::Node result;
-    result["max_time_diff"]   = fCutTime;
-    result["min_z_pca"]       = fCutZ;
-    result["max_dist_at_pca"] = fCutDist;
+    result["track_start_z_min"]  = fTrackStartZ_min;
+    result["track_start_z_max"]  = fTrackStartZ_max;
+    result["track_end_z_min"]    = fTrackEndZ_min;
+    result["track_impact_x_min"] = fTrackImpactX_min;
+    result["track_impact_x_max"] = fTrackImpactX_max;
+    result["track_impact_y_min"] = fTrackImpactY_min;
+    result["track_impact_y_max"] = fTrackImpactY_max;
+    result["pair_deltaT_max"]    = fPairDeltaT_max;
+    result["pair_dist_max"]      = fPairDist_max;
+    result["pair_z_min"]         = fPairZ_min;
+    result["pair_z_max"]         = fPairZ_max;
     return result;
   }
   // --------------------------------------------------------------------------
diff --git a/algo/trigger/V0TriggerConfig.h b/algo/trigger/V0TriggerConfig.h
index b54535b1e80769a0f6e5e2452467e7c8fe027785..c2026d0da63347658364c27b6e0afaece2daa9e2 100644
--- a/algo/trigger/V0TriggerConfig.h
+++ b/algo/trigger/V0TriggerConfig.h
@@ -30,6 +30,7 @@ namespace cbm::algo::evbuild
      ** @param cutZ     Minimum z position at closest approach
      ** @param cutDist  Maximum distance at closest approach
      **/
+    /*
     V0TriggerConfig(double cutTime, double cutZ, double cutDist)
       : fCutTime(cutTime)
       , fCutZ(cutZ)
@@ -37,6 +38,7 @@ namespace cbm::algo::evbuild
       , fIsSet(true)
     {
     }
+    */
 
     /** @brief Constructor from YAML **/
     V0TriggerConfig(YAML::Node config);
@@ -44,14 +46,38 @@ namespace cbm::algo::evbuild
     /** @brief Destructor **/
     ~V0TriggerConfig() = default;
 
-    /** @brief Cut on time difference between tracks **/
-    double CutTime() const { return fCutTime; }
+    /** @brief Minimum z at first track measurement **/
+    double TrackStartZ_min() const { return fTrackStartZ_min; }
 
-    /** @brief Cut on z position of closest approach **/
-    double CutZ() const { return fCutZ; }
+    /** @brief Maximum z at first track measurement **/
+    double TrackStartZ_max() const { return fTrackStartZ_max; }
 
-    /** @brief Cut on distance of tracks at closest approach **/
-    double CutDist() const { return fCutDist; }
+    /** @brief Minimum z at last track measurement **/
+    double TrackEndZ_min() const { return fTrackEndZ_min; }
+
+    /** @brief Minimum x of track impact in target plane **/
+    double TrackImpactX_min() const { return fTrackImpactX_min; }
+
+    /** @brief Maximum x of track impact in target plane **/
+    double TrackImpactX_max() const { return fTrackImpactX_max; }
+
+    /** @brief Minimum y of track impact in target plane **/
+    double TrackImpactY_min() const { return fTrackImpactY_min; }
+
+    /** @brief Maximum y of track impact in target plane **/
+    double TrackImpactY_max() const { return fTrackImpactY_max; }
+
+    /** @brief Maximum time difference of tracks **/
+    double PairDeltaT_max() const { return fPairDeltaT_max; }
+
+    /** @brief Maximum distance at closest approach **/
+    double PairDist_max() const { return fPairDist_max; }
+
+    /** @brief Minimum z of PCA **/
+    double PairZ_min() const { return fPairZ_min; }
+
+    /** @brief Maximum z of PCA **/
+    double PairZ_max() const { return fPairZ_max; }
 
     /** @brief Check whether config was set **/
     bool IsSet() const { return fIsSet; }
@@ -61,10 +87,24 @@ namespace cbm::algo::evbuild
 
 
    private:
-    double fCutTime{0.};  /// Maximum time difference of tracks
-    double fCutZ{0.};     /// Minimum z position at closest approach
-    double fCutDist{0.};  /// Maximum distance at closest approach
-    bool fIsSet{false};   /// Flag whether a configuration was set
+    // Track cuts
+    double fTrackStartZ_min{0.};   /// Minimum z at first track measurement
+    double fTrackStartZ_max{0.};   /// Maximum z at first track measurement
+    double fTrackEndZ_min{0.};     /// Minimum z at last track measurement
+    double fTrackImpactX_min{0.};  /// Minimum x of excluded track impact in target plane
+    double fTrackImpactX_max{0.};  /// Maximum x of excluded track impact in target plane
+    double fTrackImpactY_min{0.};  /// Minimum y of excluded track impact in target plane
+    double fTrackImpactY_max{0.};  /// Maximum y of excluded track impact in target plane
+
+    // Track pair cuts
+    double fPairDeltaT_max{0.};  /// Maximum time difference of tracks
+    double fPairDist_max{0.};    /// Maximum distance at closest approach
+    double fPairZ_min{0.};       /// Minimum z of PCA
+    double fPairZ_max{0.};       /// Maximum z of PCA
+
+    bool fIsSet{false};  /// Flag whether a configuration was set
+
+    double GetDoubleRequired(const YAML::Node& config, const char* key);
   };