From 4eb2101fbaacb6f0013100205aa047cf358b7ca5 Mon Sep 17 00:00:00 2001
From: "s.zharko@gsi.de" <s.zharko@gsi.de>
Date: Tue, 28 Feb 2023 00:12:08 +0100
Subject: [PATCH] CA: Introduced partial sorting of hits by stations in
 L1IODataManager

---
 reco/L1/L1Algo/L1IODataManager.cxx | 45 +++++++++++++++++-------------
 reco/L1/L1Algo/L1IODataManager.h   |  9 ++++--
 reco/L1/L1Algo/L1InputData.cxx     |  1 -
 reco/L1/L1Algo/L1InputData.h       | 22 ++++-----------
 4 files changed, 39 insertions(+), 38 deletions(-)

diff --git a/reco/L1/L1Algo/L1IODataManager.cxx b/reco/L1/L1Algo/L1IODataManager.cxx
index 86bc8a7662..1c389b282b 100644
--- a/reco/L1/L1Algo/L1IODataManager.cxx
+++ b/reco/L1/L1Algo/L1IODataManager.cxx
@@ -25,7 +25,7 @@ L1IODataManager::L1IODataManager(const L1Parameters* pParameters) : fpParameters
 bool L1IODataManager::SendInputData(L1Algo* pAlgo)
 {
   // Set boundary hit indexes
-  SetStartStopHitIndexes();
+  InitData();
 
   // Check data before input
   if (CheckInputData<L1Constants::control::kInputDataQaLevel>()) {
@@ -69,26 +69,33 @@ void L1IODataManager::ResetInputData() noexcept
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
-void L1IODataManager::SetStartStopHitIndexes()
+void L1IODataManager::InitData()
 {
-  // TODO: probably, it is better to loop before the actual number of stations
-  for (int iStation = 0; iStation < fpParameters->GetNstationsActive(); ++iStation) {
-    fInputData.fvStartHitIndexes[iStation] =
-      std::lower_bound(fInputData.fvHits.begin(), fInputData.fvHits.end(), iStation,
-                       [](const L1Hit& hit, int ist) { return hit.iSt < ist; })
-      - fInputData.fvHits.begin();
-
-    fInputData.fvStopHitIndexes[iStation] =
-      std::upper_bound(fInputData.fvHits.begin(), fInputData.fvHits.end(), iStation,
-                       [](int ist, const L1Hit& hit) { return hit.iSt > ist; })
-      - fInputData.fvHits.begin();
-
-    // Account for stations with no hits
-    if (fInputData.fvStartHitIndexes[iStation] == fInputData.fvStopHitIndexes[iStation]) {
-      fInputData.fvStartHitIndexes[iStation] = 0;
-      fInputData.fvStopHitIndexes[iStation]  = 0;
-    }
+  // Sort hits within stations
+  L1Vector<L1Hit> fvHitsNew;
+  fvHitsNew.reset(fInputData.fvHits.size());
+
+  std::fill(fvHitIndex.begin(), fvHitIndex.end(), 0);
+  std::fill(fInputData.fvStartHitIndexes.begin(), fInputData.fvStartHitIndexes.end(), 0);
+
+  // Count number of hits in each station
+  for (const auto& hit : fInputData.fvHits) {
+    ++fInputData.fvStartHitIndexes[hit.iSt + 1];
+  }
+
+  // Fill bordering numbers of hits for each station
+  for (int iSt = 0; iSt < fpParameters->GetNstationsActive(); ++iSt) {
+    fInputData.fvStartHitIndexes[iSt + 1] += fInputData.fvStartHitIndexes[iSt];
   }
+
+  // Save ordered hits to new vector
+  for (const auto& hit : fInputData.fvHits) {
+    int iSt                                                            = hit.iSt;
+    fvHitsNew[fInputData.fvStartHitIndexes[iSt] + (fvHitIndex[iSt]++)] = hit;
+  }
+
+  // Swap contents of old and new hits vector
+  std::swap(fvHitsNew, fInputData.fvHits);
 }
 
 // ---------------------------------------------------------------------------------------------------------------------
diff --git a/reco/L1/L1Algo/L1IODataManager.h b/reco/L1/L1Algo/L1IODataManager.h
index a59dfcaa30..c744493b46 100644
--- a/reco/L1/L1Algo/L1IODataManager.h
+++ b/reco/L1/L1Algo/L1IODataManager.h
@@ -79,8 +79,10 @@ public:
   void WriteInputData(const std::string& fileName) const;
 
 private:
-  /// Sets the start and stop indexes vs. station index
-  void SetStartStopHitIndexes();
+  /// @brief Initializes data object
+  ///
+  /// Sorts hits by stations (complexity O(n)) and defines bordering hit index for station
+  void InitData();
 
   /// Provides quick QA for input data
   /// \tparam  Level  The level of the checks. The values of the parameter:
@@ -100,6 +102,9 @@ private:
   L1InputData fInputData {};  ///< Object of input data
 
   const L1Parameters* fpParameters = nullptr;  ///< Pointer to the tracking parameters object
+
+  /// @brief Utility array for sorting hits by stations
+  std::array<L1HitIndex_t, L1Constants::size::kMaxNstations + 1> fvHitIndex = {0};
 };
 
 
diff --git a/reco/L1/L1Algo/L1InputData.cxx b/reco/L1/L1Algo/L1InputData.cxx
index 48bdb49dce..e301b6a86e 100644
--- a/reco/L1/L1Algo/L1InputData.cxx
+++ b/reco/L1/L1Algo/L1InputData.cxx
@@ -19,7 +19,6 @@ L1InputData::L1InputData() {}
 L1InputData::L1InputData(const L1InputData& other)
   : fvHits(other.fvHits)
   , fvStartHitIndexes(other.fvStartHitIndexes)
-  , fvStopHitIndexes(other.fvStopHitIndexes)
   , fNhitKeys(other.fNhitKeys)
 {
 }
diff --git a/reco/L1/L1Algo/L1InputData.h b/reco/L1/L1Algo/L1InputData.h
index a3cb66fe09..be6756666b 100644
--- a/reco/L1/L1Algo/L1InputData.h
+++ b/reco/L1/L1Algo/L1InputData.h
@@ -80,11 +80,11 @@ public:
 
   /// Gets index of (the last + 1) hit in the sorted hits vector
   /// \param iStation  Index of the tracking station in the active stations array
-  L1HitIndex_t GetStopHitIndex(int iStation) const { return fvStopHitIndexes[iStation]; }
+  L1HitIndex_t GetStopHitIndex(int iStation) const { return fvStartHitIndexes[iStation + 1]; }
 
   /// Gets n hits for the station
   /// \param iStation  Index of the tracking station in the active stations array
-  L1HitIndex_t GetNhits(int iStation) const { return fvStopHitIndexes[iStation] - fvStartHitIndexes[iStation]; }
+  L1HitIndex_t GetNhits(int iStation) const { return fvStartHitIndexes[iStation + 1] - fvStartHitIndexes[iStation]; }
 
 
 private:
@@ -97,7 +97,6 @@ private:
   {
     ar& fvHits;
     ar& fvStartHitIndexes;
-    ar& fvStopHitIndexes;
     ar& fNhitKeys;
   }
 
@@ -105,21 +104,13 @@ private:
   // ** Member variables list **
   // ***************************
 
-  /// Sorted sample of input hits
-  /// \note Hits in the vector are sorted as follows. Among two hits
-  ///       the largest has the largest station index in the active
-  ///       stations array. If both indexes were measured withing one
-  ///       station, the largest hit has the largest y component of
-  ///       the coordinates
+  /// @brief Sample of input hits
   L1Vector<L1Hit> fvHits = {"L1InputData::fvHits"};
 
-  /// Index of the first hit in the sorted hits vector for a given station
-  std::array<L1HitIndex_t, L1Constants::size::kMaxNstations> fvStartHitIndexes = {0};
+  /// @brief Index of the first hit in the sorted hits vector for a given station
+  std::array<L1HitIndex_t, L1Constants::size::kMaxNstations + 1> fvStartHitIndexes = {0};
 
-  /// Index of the last hit in the sorted hits vector for a given station
-  std::array<L1HitIndex_t, L1Constants::size::kMaxNstations> fvStopHitIndexes = {0};
-
-  /// Number of hit keys used for rejecting fake STS hits
+  /// @brief Number of hit keys used for rejecting fake STS hits
   int fNhitKeys = -1;
 };
 
@@ -134,7 +125,6 @@ private:
 {
   std::swap(fvHits, other.fvHits);
   std::swap(fvStartHitIndexes, other.fvStartHitIndexes);
-  std::swap(fvStopHitIndexes, other.fvStopHitIndexes);
   std::swap(fNhitKeys, other.fNhitKeys);
 }
 
-- 
GitLab