From c5582998d531ef34500668e033bb6179c6b48244 Mon Sep 17 00:00:00 2001
From: Volker Friese <friese@lxi099.gsi.de>
Date: Wed, 31 Jan 2024 06:04:29 +0100
Subject: [PATCH] First version of V0 trigger algorithm

---
 algo/CMakeLists.txt        |  2 +
 algo/trigger/V0Trigger.cxx | 78 ++++++++++++++++++++++++++++++++++++++
 algo/trigger/V0Trigger.h   | 73 +++++++++++++++++++++++++++++++++++
 3 files changed, 153 insertions(+)
 create mode 100644 algo/trigger/V0Trigger.cxx
 create mode 100644 algo/trigger/V0Trigger.h

diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt
index 378c2d50bb..79552f5987 100644
--- a/algo/CMakeLists.txt
+++ b/algo/CMakeLists.txt
@@ -82,6 +82,7 @@ set(SRCS
   evbuild/EventbuildChain.cxx
   trigger/DigiTriggerConfig.cxx
   trigger/TimeClusterTrigger.cxx
+  trigger/V0Trigger.cxx
   evselector/DigiEventSelector.cxx
   evselector/DigiEventSelectorConfig.cxx
   unpack/CommonUnpacker.cxx
@@ -166,6 +167,7 @@ target_include_directories(Algo
          ${CMAKE_CURRENT_SOURCE_DIR}/ca
          ${CMAKE_CURRENT_SOURCE_DIR}/qa/unpack
          ${CMAKE_CURRENT_SOURCE_DIR}/ca/qa
+         ${CMAKE_CURRENT_SOURCE_DIR}/ca/core/data
          ${CMAKE_CURRENT_SOURCE_DIR}
          ${CMAKE_SOURCE_DIR}/core/data/global
 )
diff --git a/algo/trigger/V0Trigger.cxx b/algo/trigger/V0Trigger.cxx
new file mode 100644
index 0000000000..1bd3937c8d
--- /dev/null
+++ b/algo/trigger/V0Trigger.cxx
@@ -0,0 +1,78 @@
+/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer], Dominik Smith */
+
+#include "V0Trigger.h"
+
+namespace cbm::algo
+{
+
+
+  V0Trigger::Result V0Trigger::operator()(const TrackVector& tracks, const V0TriggerConfig& config) const
+  {
+
+    Result result;
+
+    for (auto trackIter1 = tracks.begin(); trackIter1 != tracks.end(); trackIter1++) {
+      for (auto trackIter2 = trackIter1++; trackIter2 != tracks.end(); trackIter2++) {
+
+        // Check track time difference
+        float time1 = trackIter1->fParFirst.GetTime();
+        float time2 = trackIter2->fParFirst.GetTime();
+        if (time2 < time1) {
+          result.second.errTracksUnsorted++;
+          continue;
+        }
+        result.second.numTrackPairs++;
+        if (time2 - time1 > config.cutTime) break;
+        result.second.numTrackPairsWithinTimeCut++;
+
+        // Check PCA cuts
+        auto pca       = CalcPCA(trackIter1->fParFirst, trackIter2->fParFirst);
+        double zVertex = pca.first;
+        double dist    = pca.second;
+        if (zVertex > config.cutZ && dist < config.cutDist) {
+          double tVertex = 0.5 * (time1 + time2);
+          result.first.push_back(tVertex);
+        }
+      }
+    }
+
+    return result;
+  };
+
+
+  std::pair<double, double> V0Trigger::CalcPCA(const TrackParam& track1, const TrackParam& track2) const
+  {
+
+    // Start point and direction of first track at z = 0
+    const double ax = track1.GetX() - track1.GetTx() * track1.GetZ();
+    const double ay = track1.GetY() - track1.GetTy() * track1.GetZ();
+    const double ux = track1.GetTx();
+    const double uy = track1.GetTy();
+
+    // Start point and direction of second track at z = 0
+    const double bx = track2.GetX() - track2.GetTx() * track2.GetZ();
+    const double by = track2.GetY() - track2.GetTy() * track2.GetZ();
+    const double vx = track2.GetTx();
+    const double vy = track2.GetTy();
+
+    // Difference vectors
+    const double cx = ax - bx;
+    const double cy = ay - by;
+    const double wx = ux - vx;
+    const double wy = uy - vy;
+
+    // z coordinate at closest approach in the x-y plane
+    const double z = -1. * (cx * wx + cy * wy) / (wx * wx + wy * wy);
+
+    // Distance at closest approach in the x-y plane
+    const double dx   = cx + z * wx;
+    const double dy   = cy + z * wy;
+    const double dist = sqrt(dx * dx + dy * dy);
+
+    return std::make_pair(z, dist);
+  }
+
+
+}  // namespace cbm::algo
diff --git a/algo/trigger/V0Trigger.h b/algo/trigger/V0Trigger.h
new file mode 100644
index 0000000000..67bdd732b8
--- /dev/null
+++ b/algo/trigger/V0Trigger.h
@@ -0,0 +1,73 @@
+/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+#pragma once  // include this header only once per compilation unit
+
+#include "CaTrack.h"
+#include "CaVector.h"
+
+#include <utility>
+#include <vector>
+
+namespace cbm::algo
+{
+
+  /** @struct V0TriggerConfig
+ ** @brief Configuration (cut values) for the V0Trigger class
+**/
+  struct V0TriggerConfig {
+    double cutTime{};  /// Maximum time difference of tracks
+    double cutZ{};     /// Minimum z position at closest approach
+    double cutDist{};  /// Maximum distance at closest approach
+  };
+
+
+  /** @struct V0TriggerMoniData
+ ** @brief Monitoring information for the algorithm V0Trigger
+ **/
+  struct V0TriggerMoniData {
+    size_t errTracksUnsorted{0};
+    size_t numTrackPairs{0};
+    size_t numTrackPairsWithinTimeCut{0};
+  };
+
+
+  class V0Trigger {
+
+   public:
+    typedef std::pair<std::vector<double>, V0TriggerMoniData> Result;
+    typedef cbm::algo::ca::Track Track;
+    typedef cbm::algo::ca::Vector<cbm::algo::ca::Track> TrackVector;
+    typedef cbm::algo::ca::TrackParamS TrackParam;
+
+    /** @brief Constructor **/
+    V0Trigger() = default;
+
+    /** @brief Execution
+     ** @param  dataVec     Source data vector
+     ** @param  winSize     Size of trigger window
+     ** @param  minNumData  Threshold on number of data within the trigger window
+     ** @param  deadTime    Minimum time between two triggers
+     ** @return Vector of trigger times and monitoring data
+     **/
+    Result operator()(const TrackVector& tracks, const V0TriggerConfig& config) const;
+
+    /** @brief Info to string **/
+    std::string ToString() const;
+
+
+   private:
+    /** @brief Calculation of closest approach of two tracks (straight lines)
+ ** @param track1  Parameters of first track
+ ** @param track2  Parameters of second track
+ ** @return (z position, distance)
+ ** 
+ ** The closest approach is defined at the z position where the transverse distance of the tracks (in the x-y plane) is minimal.
+ ** This is not strictly the minimal distance in 3-d space, which is mathematically and computationally more involved.
+ ** 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;
+  };
+
+}  // namespace cbm::algo
-- 
GitLab