From 1ce443c5ce682707aed381b7f6068064c4499cd7 Mon Sep 17 00:00:00 2001
From: Volker Friese <v.friese@gsi.de>
Date: Tue, 20 Apr 2021 12:04:49 +0000
Subject: [PATCH] Fix problem in CbmPVFinderKF (declaration of C array with
 non-positive size; redefine digi output file name for json to avoid
 overwriting conflict in the tests; slightly re-arrange tests from macro/run.
 Refs 2076.

---
 macro/run/CMakeLists.txt                 |  68 ++++++------
 macro/run/config.json                    |   2 +-
 reco/KF/Interface/CbmPVFinderKF.cxx      |  26 ++---
 reco/detectors/psd/CbmPsdHitProducer.cxx |   4 +-
 reco/global/CbmFindPrimaryVertex.cxx     | 131 +++++++++++++++--------
 reco/global/CbmFindPrimaryVertex.h       |  14 ++-
 6 files changed, 151 insertions(+), 94 deletions(-)

diff --git a/macro/run/CMakeLists.txt b/macro/run/CMakeLists.txt
index 6877a08873..dec6534b48 100644
--- a/macro/run/CMakeLists.txt
+++ b/macro/run/CMakeLists.txt
@@ -164,23 +164,53 @@ foreach(setup IN LISTS cbm_setup)
  	RESOURCE_LOCK collParDb_${setup}
   )
 
-  # --- Test run_reco_ev
+  # --- Test run_reco_ev_ideal
   # --- Event-by-event reconstruction from event-based simulation
-  set(testname run_${sname}_reco_ev)
+  # --- Ideal raw event builder
+  set(testname run_${sname}_reco_ev_ideal)
   add_test(${testname} ${MACRODIR}/run_reco.sh
-  	\"data/${sname}_ev\" -1 0 \"\" \"Ideal\" \"${setup}\" \"data/${sname}_coll\")
+  	\"data/${sname}_ev\" -1 0 \"data/${sname}_eb_eb_ideal\" \"Ideal\" \"${setup}\" \"data/${sname}_coll\")
   set_tests_properties(${testname} PROPERTIES
   	TIMEOUT ${timeOutTime}
   	PASS_REGULAR_EXPRESSION "Macro finished successfully"
 	FIXTURES_REQUIRED fixt_reco_ev_${setup}
  	RESOURCE_LOCK collParDb_${setup}
   )
+  
+  # --- Test run_reco_ev_real
+  # --- Event-by-event reconstruction from event-based simulation
+  # --- Real raw event builder
+  set(testname run_${sname}_reco_ev_real)
+  add_test(${testname} ${MACRODIR}/run_reco.sh
+    \"data/${sname}_ev\" -1 0 \"data/${sname}_eb_eb_real\" \"Real\" \"${setup}\"
+    \"data/${sname}_coll\")
+  set_tests_properties(${testname} PROPERTIES
+    TIMEOUT ${timeOutTime}
+    PASS_REGULAR_EXPRESSION "Macro finished successfully"
+    FIXTURES_REQUIRED fixt_reco_ev_${setup}
+    RESOURCE_LOCK collParDb_${setup}
+  )
 
-  # --- Test run_reco_ts_eb
+  # --- Test run_reco_ts_eb_ideal
   # --- Event-by-event reconstruction from time-based simulation
-  set(testname run_${sname}_reco_ts_eb)
+  # --- Ideal raw event builder
+  set(testname run_${sname}_reco_ts_eb_ideal)
   add_test(${testname} ${MACRODIR}/run_reco.sh
-  	\"data/${sname}_ts\" -1 0 \"data/${sname}_ts_eb\" \"Ideal\" \"${setup}\"
+  	\"data/${sname}_ts\" -1 0 \"data/${sname}_ts_eb_ideal\" \"Ideal\" \"${setup}\"
+  	\"data/${sname}_coll\")
+  set_tests_properties(${testname} PROPERTIES
+  	TIMEOUT ${timeOutTime}
+  	PASS_REGULAR_EXPRESSION "Macro finished successfully"
+	FIXTURES_REQUIRED fixt_reco_ts_${setup}
+ 	RESOURCE_LOCK collParDb_${setup}
+  )
+  
+  # --- Test run_reco_ts_eb_real
+  # --- Event-by-event reconstruction from time-based simulation
+  # --- Real raw event builder
+  set(testname run_${sname}_reco_ts_eb_real)
+  add_test(${testname} ${MACRODIR}/run_reco.sh
+  	\"data/${sname}_ts\" -1 0 \"data/${sname}_ts_eb_real\" \"Real\" \"${setup}\"
   	\"data/${sname}_coll\")
   set_tests_properties(${testname} PROPERTIES
   	TIMEOUT ${timeOutTime}
@@ -202,32 +232,6 @@ foreach(setup IN LISTS cbm_setup)
  	RESOURCE_LOCK collParDb_${setup}
   )
 
-  # --- Test run_reco_ev_real
-  # --- Event-by-event reconstruction from event-based simulation
-  set(testname run_${sname}_reco_ev_real)
-  add_test(${testname} ${MACRODIR}/run_reco.sh
-    \"data/${sname}_ev\" -1 0 \"data/${sname}_eb_eb_real\" \"Real\" \"${setup}\"
-    \"data/${sname}_coll\")
-  set_tests_properties(${testname} PROPERTIES
-    TIMEOUT ${timeOutTime}
-    PASS_REGULAR_EXPRESSION "Macro finished successfully"
-    FIXTURES_REQUIRED fixt_reco_ev_${setup}
-    RESOURCE_LOCK collParDb_${setup}
-  )
-
-  # --- Test run_reco_ts_eb_real
-  # --- Event-by-event reconstruction from time-based simulation
-  set(testname run_${sname}_reco_ts_eb_real)
-  add_test(${testname} ${MACRODIR}/run_reco.sh
-    \"data/${sname}_ts\" -1 0 \"data/${sname}_ts_eb_real\" \"Real\" \"${setup}\"
-    \"data/${sname}_coll\")
-  set_tests_properties(${testname} PROPERTIES
-    TIMEOUT ${timeOutTime}
-    PASS_REGULAR_EXPRESSION "Macro finished successfully"
-    FIXTURES_REQUIRED fixt_reco_ts_${setup}
-    RESOURCE_LOCK collParDb_${setup}
-  )
-
 endforeach(setup IN LISTS cbm_setup)
 # ============================================================================
 
diff --git a/macro/run/config.json b/macro/run/config.json
index 136720decf..63d6d4dc23 100644
--- a/macro/run/config.json
+++ b/macro/run/config.json
@@ -98,7 +98,7 @@
        "treeAccessMode": "random"}
     ],
     "output": {
-      "path": "test",
+      "path": "data/test_json",
       "overwrite": false
     },
     "geometry": {
diff --git a/reco/KF/Interface/CbmPVFinderKF.cxx b/reco/KF/Interface/CbmPVFinderKF.cxx
index 631a8fe70c..634f276a65 100644
--- a/reco/KF/Interface/CbmPVFinderKF.cxx
+++ b/reco/KF/Interface/CbmPVFinderKF.cxx
@@ -1,20 +1,21 @@
 #include "CbmPVFinderKF.h"
 
+#include "CbmEvent.h"
 #include "CbmKFPrimaryVertexFinder.h"
 #include "CbmKFTrack.h"
 #include "CbmKFVertex.h"
-
-#include "CbmEvent.h"
 #include "CbmStsTrack.h"
 
+#include <FairLogger.h>
+
 #include "TClonesArray.h"
 
 #include "math.h"
 
 ClassImp(CbmPVFinderKF)
 
-  Int_t CbmPVFinderKF::FindPrimaryVertex(TClonesArray* tracks,
-                                         CbmVertex* vertex) {
+  Int_t CbmPVFinderKF::FindPrimaryVertex(TClonesArray* tracks, CbmVertex* vertex)
+{
 
   Int_t NTracks = tracks->GetEntriesFast();
 
@@ -25,8 +26,7 @@ ClassImp(CbmPVFinderKF)
     Int_t NHits     = st->GetNofHits();
     if (NHits < 4) continue;
     if (st->GetFlag()) continue;
-    if (st->GetChiSq() < 0. || st->GetChiSq() > 3.5 * 3.5 * st->GetNDF())
-      continue;
+    if (st->GetChiSq() < 0. || st->GetChiSq() > 3.5 * 3.5 * st->GetNDF()) continue;
     CbmKFTrack& T = CloneArray[i];
     T.SetStsTrack(*st);
     if (!finite(T.GetTrack()[0]) || !finite(T.GetCovMatrix()[0])) continue;
@@ -36,12 +36,13 @@ ClassImp(CbmPVFinderKF)
   Finder.Fit(v);
   v.GetVertex(*vertex);
   delete[] CloneArray;
-  return 0;
+  return vertex->GetNTracks();
 }
 
 
 // ----   Find vertex for one event   ---------------------------------------
-Int_t CbmPVFinderKF::FindEventVertex(CbmEvent* event, TClonesArray* tracks) {
+Int_t CbmPVFinderKF::FindEventVertex(CbmEvent* event, TClonesArray* tracks)
+{
 
   assert(event);
   CbmKFPrimaryVertexFinder vFinder;
@@ -50,7 +51,9 @@ Int_t CbmPVFinderKF::FindEventVertex(CbmEvent* event, TClonesArray* tracks) {
   CbmVertex* vertex = event->GetVertex();
 
   // Copy input tracks to KF tracks
-  Int_t nTracks          = event->GetNofData(ECbmDataType::kStsTrack);
+  Int_t nTracks = event->GetNofData(ECbmDataType::kStsTrack);
+  if (nTracks <= 0) return 0;
+
   CbmKFTrack* trackArray = new CbmKFTrack[nTracks];
   for (Int_t iTrack = 0; iTrack < nTracks; iTrack++) {
     Int_t trackIndex   = event->GetIndex(ECbmDataType::kStsTrack, iTrack);
@@ -63,8 +66,7 @@ Int_t CbmPVFinderKF::FindEventVertex(CbmEvent* event, TClonesArray* tracks) {
       continue;
     CbmKFTrack& kTrack = trackArray[iTrack];
     kTrack.SetStsTrack(*track);
-    if (!finite(kTrack.GetTrack()[0]) || !finite(kTrack.GetCovMatrix()[0]))
-      continue;
+    if (!finite(kTrack.GetTrack()[0]) || !finite(kTrack.GetCovMatrix()[0])) continue;
     vFinder.AddTrack(&kTrack);
   }
 
@@ -76,6 +78,6 @@ Int_t CbmPVFinderKF::FindEventVertex(CbmEvent* event, TClonesArray* tracks) {
   v.GetVertex(*vertex);
 
   delete[] trackArray;
-  return 0;
+  return vertex->GetNTracks();
 }
 // --------------------------------------------------------------------------
diff --git a/reco/detectors/psd/CbmPsdHitProducer.cxx b/reco/detectors/psd/CbmPsdHitProducer.cxx
index 46e174427b..fe2ab8d5bd 100644
--- a/reco/detectors/psd/CbmPsdHitProducer.cxx
+++ b/reco/detectors/psd/CbmPsdHitProducer.cxx
@@ -148,10 +148,10 @@ void CbmPsdHitProducer::Exec(Option_t* /*opt*/)
   if (fEvents)
     LOG(info) << std::setw(20) << std::left << GetName() << fixed << setprecision(2) << " [" << timer.RealTime() * 1000.
               << " ms] TS " << fNofTs << ", events " << nEvents << ", digis " << nDigis << " / " << nDigisAll
-              << ", hits " << fNofHits;
+              << ", hits " << nHits;
   else
     LOG(info) << std::setw(20) << std::left << GetName() << fixed << setprecision(2) << " [" << timer.RealTime() * 1000.
-              << " ms] TS " << fNofTs << ", digis " << nDigis << " / " << nDigisAll << ", hits " << fNofHits;
+              << " ms] TS " << fNofTs << ", digis " << nDigis << " / " << nDigisAll << ", hits " << nHits;
   fNofTs++;
   fNofEvents += nEvents;
   fNofDigis += nDigis;
diff --git a/reco/global/CbmFindPrimaryVertex.cxx b/reco/global/CbmFindPrimaryVertex.cxx
index 6264f106da..ccbba618a3 100644
--- a/reco/global/CbmFindPrimaryVertex.cxx
+++ b/reco/global/CbmFindPrimaryVertex.cxx
@@ -4,6 +4,7 @@
 // -------------------------------------------------------------------------
 #include "CbmFindPrimaryVertex.h"
 
+#include "CbmEvent.h"
 #include "CbmPrimaryVertexFinder.h"
 #include "CbmVertex.h"
 
@@ -25,7 +26,8 @@ CbmFindPrimaryVertex::CbmFindPrimaryVertex()
   , fTracks(nullptr)
   , fPrimVert(nullptr)
   , fNofEvents(0)
-  , fTimeTot(0.) {
+  , fTimeTot(0.)
+{
   fName = "FindPrimaryVertex";
 }
 // -------------------------------------------------------------------------
@@ -39,23 +41,24 @@ CbmFindPrimaryVertex::CbmFindPrimaryVertex(CbmPrimaryVertexFinder* pvFinder)
   , fTracks(nullptr)
   , fPrimVert(nullptr)
   , fNofEvents(0)
-  , fTimeTot(0.) {
+  , fTimeTot(0.)
+{
   fName = "FindPrimaryVertex";
 }
 // -------------------------------------------------------------------------
 
 
 // -----  Constructor with name and title  ---------------------------------
-CbmFindPrimaryVertex::CbmFindPrimaryVertex(const char* name,
-                                           const char*,
-                                           CbmPrimaryVertexFinder* finder)
+CbmFindPrimaryVertex::CbmFindPrimaryVertex(const char* name, const char*, CbmPrimaryVertexFinder* finder)
   : FairTask(name)
   , fTimer()
   , fFinder(finder)
   , fTracks(nullptr)
   , fPrimVert(nullptr)
   , fNofEvents(0)
-  , fTimeTot(0.) {}
+  , fTimeTot(0.)
+{
+}
 // -------------------------------------------------------------------------
 
 
@@ -65,7 +68,8 @@ CbmFindPrimaryVertex::~CbmFindPrimaryVertex() {}
 
 
 // -----   Public method Init   --------------------------------------------
-InitStatus CbmFindPrimaryVertex::Init() {
+InitStatus CbmFindPrimaryVertex::Init()
+{
 
   // Check for vertex finder
   if (!fFinder) {
@@ -89,13 +93,24 @@ InitStatus CbmFindPrimaryVertex::Init() {
     return kERROR;
   }
 
-  // Create and register CbmVertex object
-  fPrimVert = new CbmVertex("Primary Vertex", "Global");
-  ioman->Register("PrimaryVertex.",
-                  "Global",
-                  fPrimVert,
-                  IsOutputBranchPersistent("PrimaryVertex"));
+  // Get CbmEvent array
+  fEvents = dynamic_cast<TClonesArray*>(ioman->GetObject("Event"));
+  if (fEvents) LOG(info) << GetName() << ": Found Event branch; run event-by-event";
+  else {
+    fEvents = dynamic_cast<TClonesArray*>(ioman->GetObject("CbmEvent"));
+    if (fEvents) LOG(info) << GetName() << ": Found CbmEvent branch; run event-by-event";
+    else {
+      LOG(info) << GetName() << ": No event branch found! Run in time-based mode.";
+      LOG(warning) << GetName() << "*** The primary vertex finder is not designed to find mutiple vertices.";
+      LOG(warning) << GetName() << "*** Running it on an entire time slice will not produce sensible results.";
+    }
+  }
 
+  // Create and register CbmVertex object
+  if (!fEvents) {
+    fPrimVert = new CbmVertex("Primary Vertex", "Global");
+    ioman->Register("PrimaryVertex.", "Global", fPrimVert, IsOutputBranchPersistent("PrimaryVertex"));
+  }
 
   // Call the Init method of the vertex finder
   fFinder->Init();
@@ -106,43 +121,75 @@ InitStatus CbmFindPrimaryVertex::Init() {
 
 
 // -----   Public method Exec   --------------------------------------------
-void CbmFindPrimaryVertex::Exec(Option_t*) {
-
-  // Event number
-  Int_t iEvent = fNofEvents;
-
-  // Reset primary vertex
-  fTimer.Start();
-  fPrimVert->Reset();
-
-  // Call find method of vertex finder
-  Int_t iFind = fFinder->FindPrimaryVertex(fTracks, fPrimVert);
-  if (iFind)
-    cout << "-W- CbmFindPrimaryVertex::Exec: "
-         << "Vertex finder returned " << iFind << endl;
-
-  // --- Event log
-  fTimer.Stop();
-  fNofEvents++;
-  fTimeTot += fTimer.RealTime();
-  LOG(info) << "+ " << setw(20) << GetName() << ": Event " << setw(6) << right
-            << iEvent << ", real time " << fixed << setprecision(6)
-            << fTimer.RealTime()
-            << " s, tracks used: " << fPrimVert->GetNTracks();
-  LOG(debug) << fPrimVert->ToString();
+void CbmFindPrimaryVertex::Exec(Option_t*)
+{
+
+  // Timer
+  TStopwatch timer;
+  timer.Start();
+
+  // Local variables
+  Int_t nEvents     = 0;
+  Int_t nTracks     = fTracks->GetEntriesFast();
+  Int_t nTracksUsed = 0;
+  Int_t result      = 0;
+
+  // Time-based mode: process entire track array
+  if (!fEvents) {
+    fPrimVert->Reset();
+    nTracksUsed = fFinder->FindPrimaryVertex(fTracks, fPrimVert);
+  }
+
+  // Event-based mode
+  else {
+    nEvents = fEvents->GetEntriesFast();
+    for (Int_t iEvent = 0; iEvent < nEvents; iEvent++) {
+      CbmEvent* event = dynamic_cast<CbmEvent*>(fEvents->At(iEvent));
+      assert(event);
+      result = fFinder->FindEventVertex(event, fTracks);
+      LOG(debug) << GetName() << ": Event " << iEvent << " " << event->GetVertex()->ToString();
+      nTracksUsed += result;
+    }
+  }
+
+  // Log to screen
+  timer.Stop();
+  if (fEvents)
+    LOG(info) << std::setw(20) << std::left << GetName() << fixed << setprecision(2) << " [" << timer.RealTime() * 1000.
+              << " ms]: TS " << fNofTs << ", events " << nEvents << ", tracks used " << nTracksUsed << " / " << nTracks;
+  else
+    LOG(info) << std::setw(20) << std::left << GetName() << fixed << setprecision(2) << " [" << timer.RealTime() * 1000.
+              << " ms] TS " << fNofTs << ", vertex " << fPrimVert->ToString() << ", tracks used " << nTracksUsed
+              << " / " << nTracks;
+
+  // Counters
+  fNofTs++;
+  fNofEvents += nEvents;
+  fNofTracks += nTracks;
+  fNofTracksUsed += nTracksUsed;
+  fTimeTot += timer.RealTime();
 }
 // -------------------------------------------------------------------------
 
 
 // -----   Public method Finish   ------------------------------------------
-void CbmFindPrimaryVertex::Finish() {
-  fPrimVert->Reset();
+void CbmFindPrimaryVertex::Finish()
+{
+
   std::cout << std::endl;
   LOG(info) << "=====================================";
   LOG(info) << GetName() << ": Run summary";
-  LOG(info) << "Events processed   : " << fNofEvents;
-  LOG(info) << "Time per event     : " << setprecision(6)
-            << fTimeTot / Double_t(fNofEvents) << " s ";
+  LOG(info) << "Time slices         : " << fNofTs;
+  LOG(info) << "Tracks/ TS          : " << fixed << setprecision(2) << fNofTracks / Double_t(fNofTs);
+  LOG(info) << "Used Tracks / TS    : " << fixed << setprecision(2) << fNofTracksUsed / Double_t(fNofTs);
+  LOG(info) << "Time  / TS          : " << fixed << setprecision(2) << 1000. * fTimeTot / Double_t(fNofTs) << " ms";
+  if (fEvents) {
+    LOG(info) << "Events              : " << fNofEvents;
+    LOG(info) << "Events / TS         : " << fixed << setprecision(2) << Double_t(fNofEvents) / Double_t(fNofTs);
+    LOG(info) << "Tracks  / event     : " << fixed << setprecision(2) << Double_t(fNofTracks) / Double_t(fNofEvents);
+    LOG(info) << "Used tracks / event : " << fixed << setprecision(2)
+              << Double_t(fNofTracksUsed) / Double_t(fNofEvents);
+  }
   LOG(info) << "=====================================";
 }
 // -------------------------------------------------------------------------
diff --git a/reco/global/CbmFindPrimaryVertex.h b/reco/global/CbmFindPrimaryVertex.h
index 887ae21de8..54cd4dd5fa 100644
--- a/reco/global/CbmFindPrimaryVertex.h
+++ b/reco/global/CbmFindPrimaryVertex.h
@@ -21,7 +21,9 @@
 
 
 #include "CbmVertex.h"
+
 #include "FairTask.h"
+
 #include "TStopwatch.h"
 
 class TClonesArray;
@@ -47,9 +49,7 @@ public:
    *@param title     Title of task
    *@param pvFinder  Pointer to vertex finder concrete object
    **/
-  CbmFindPrimaryVertex(const char* name,
-                       const char* title,
-                       CbmPrimaryVertexFinder* pvFinder);
+  CbmFindPrimaryVertex(const char* name, const char* title, CbmPrimaryVertexFinder* pvFinder);
 
 
   /** Destructor **/
@@ -71,11 +71,15 @@ public:
 private:
   TStopwatch fTimer;
   CbmPrimaryVertexFinder* fFinder;
+  TClonesArray* fEvents = nullptr;
   TClonesArray* fTracks;
   CbmVertex* fPrimVert;
 
-  Int_t fNofEvents;   ///< Total number of events processed
-  Double_t fTimeTot;  ///< Total execution time [s]
+  Int_t fNofTs            = 0;   ///< Number of processed timeslices
+  Int_t fNofEvents        = 0;   ///< Number of processed events
+  Double_t fNofTracks     = 0;   ///< Number of input tracks
+  Double_t fNofTracksUsed = 0.;  ///< Number of tracks used for vertex finding
+  Double_t fTimeTot       = 0.;  ///< Total execution time [s]
 
   CbmFindPrimaryVertex(const CbmFindPrimaryVertex&);
   CbmFindPrimaryVertex& operator=(const CbmFindPrimaryVertex&);
-- 
GitLab