From db2b64f94d0edc90afd68f6c13b41b78e1740177 Mon Sep 17 00:00:00 2001
From: Dominik Smith <smith@th.physik.uni-frankfurt.de>
Date: Mon, 22 Feb 2021 17:56:38 +0100
Subject: [PATCH] CbmAlgoBuildRawEvents: Implemented option of using explicit
 seed times.

---
 .../digis/CbmAlgoBuildRawEvents.cxx           | 105 ++++++++++++++----
 .../digis/CbmAlgoBuildRawEvents.h             |  18 +++
 .../digis/CbmTaskBuildRawEvents.cxx           |  12 ++
 .../digis/CbmTaskBuildRawEvents.h             |  20 ++++
 4 files changed, 135 insertions(+), 20 deletions(-)

diff --git a/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.cxx b/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.cxx
index e43e8ae189..f748a36cca 100644
--- a/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.cxx
+++ b/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.cxx
@@ -31,6 +31,9 @@
 #include "TH2.h"
 #include "THttpServer.h"
 
+template<>
+void CbmAlgoBuildRawEvents::LoopOnSeeds<Double_t>();
+
 Bool_t CbmAlgoBuildRawEvents::InitAlgo()
 {
   LOG(info) << "CbmAlgoBuildRawEvents::InitAlgo => Starting sequence";
@@ -38,8 +41,21 @@ Bool_t CbmAlgoBuildRawEvents::InitAlgo()
   // Get a handle from the IO manager
   FairRootManager* ioman = FairRootManager::Instance();
 
-  /// Check if reference detector data are available
-  if (kFALSE == CheckDataAvailable(fRefDet)) { LOG(fatal) << "No digi input for reference detector, stopping there!"; }
+  /// Check if reference detector is set and seed data are available,
+  /// otherwise look for explicit seed times
+  if (fRefDet.detId == ECbmModuleId::kNotExist) {
+    if (fSeedTimes == nullptr) {
+      LOG(fatal) << "No reference detector set and no seed times supplied, stopping there!";
+    }
+  }
+  else {
+    if (fSeedTimes != nullptr) {
+      LOG(fatal) << "Cannot have explicit seed times and reference detector, stopping there!";
+    }
+    if (kFALSE == CheckDataAvailable(fRefDet)) {
+      LOG(fatal) << "Reference detector set but no digi input found, stopping there!";
+    }
+  }
 
   /// Check if data for detectors in selection list are available
   for (std::vector<RawEventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) {
@@ -106,9 +122,12 @@ void CbmAlgoBuildRawEvents::ProcessTs()
 void CbmAlgoBuildRawEvents::InitTs()
 {
   /// Reset TS based variables (analysis per TS = no building over the border)
+
   /// Reference detector
-  fRefDet.fuStartIndex = 0;
-  fRefDet.fuEndIndex   = 0;
+  if (fRefDet.detId != ECbmModuleId::kNotExist) {
+    fRefDet.fuStartIndex = 0;
+    fRefDet.fuEndIndex   = 0;
+  }
   /// Loop on detectors in selection list
   for (std::vector<RawEventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) {
     (*det).fuStartIndex = 0;
@@ -189,6 +208,10 @@ void CbmAlgoBuildRawEvents::BuildEvents()
       LoopOnSeeds<CbmTofDigi>();
       break;
     }
+    case ECbmModuleId::kNotExist: {  //explicit seed times
+      LoopOnSeeds<Double_t>();
+      break;
+    }
     default: {
       LOG(fatal) << "CbmAlgoBuildRawEvents::BuildEvents => "
                  << "Trying to search event seeds with unsupported det: " << fRefDet.sName;
@@ -197,6 +220,30 @@ void CbmAlgoBuildRawEvents::BuildEvents()
   }
 }
 
+template<>
+void CbmAlgoBuildRawEvents::LoopOnSeeds<Double_t>()
+{
+  if (ECbmModuleId::kNotExist == fRefDet.detId) {
+    const UInt_t uNbSeeds = fSeedTimes->size();
+    /// Loop on size of vector
+    for (UInt_t uSeed = 0; uSeed < uNbSeeds; ++uSeed) {
+      LOG(debug) << Form("Checking seed %6u / %6u", uSeed, uNbSeeds);
+      Double_t dTime = fSeedTimes->at(uSeed);
+
+      /// Check if seed in acceptance window (is this needed here?)
+      if (dTime < fdSeedWindowBeg) { continue; }
+      else if (fdSeedWindowEnd < dTime) {
+        break;
+      }
+      /// Check Seed and build event if needed
+      CheckSeed(dTime, uSeed);
+    }
+  }
+  else {
+    LOG(fatal) << "Trying to read explicit seeds while reference detector is set.";
+  }
+}
+
 template<class DigiSeed>
 void CbmAlgoBuildRawEvents::LoopOnSeeds()
 {
@@ -229,12 +276,20 @@ void CbmAlgoBuildRawEvents::LoopOnSeeds()
   }
 }
 
+Double_t CbmAlgoBuildRawEvents::GetSeedTimeWinRange()
+{
+  if (ECbmModuleId::kNotExist != fRefDet.detId) { return fRefDet.GetTimeWinRange(); }
+  else {
+    return fdSeedTimeWinEnd - fdSeedTimeWinBeg;
+  }
+}
+
 void CbmAlgoBuildRawEvents::CheckSeed(Double_t dSeedTime, UInt_t uSeedDigiIdx)
 {
   /// If previous event valid and event overlap not allowed, check if we are in overlap
   /// and react accordingly
   if (nullptr != fCurrentEvent
-      && (EOverlapModeRaw::AllowOverlap != fOverMode || dSeedTime - fdPrevEvtTime < fRefDet.GetTimeWinRange())
+      && (EOverlapModeRaw::AllowOverlap != fOverMode || dSeedTime - fdPrevEvtTime < GetSeedTimeWinRange())
       && dSeedTime - fdPrevEvtTime < fdWidestTimeWinRange) {
     /// Within overlap range
     switch (fOverMode) {
@@ -270,15 +325,17 @@ void CbmAlgoBuildRawEvents::CheckSeed(Double_t dSeedTime, UInt_t uSeedDigiIdx)
     fCurrentEvent = new CbmEvent(fuCurEv, dSeedTime, 0.);
   }  // else of if( prev Event exists and mode forbiden overlap present )
 
-  /// If window open for reference detector, search for other reference Digis matching it
-  /// Otherwise only add the current seed
-  if (fRefDet.fdTimeWinBeg < fRefDet.fdTimeWinEnd) {
-    SearchMatches(dSeedTime, fRefDet);
-    /// Also add the seed if the window starts after the seed
-    if (0 < fRefDet.fdTimeWinBeg) AddDigiToEvent(fRefDet, uSeedDigiIdx);
-  }
-  else {
-    AddDigiToEvent(fRefDet, uSeedDigiIdx);
+  if (fRefDet.detId != ECbmModuleId::kNotExist) {
+    /// If window open for reference detector, search for other reference Digis matching it
+    /// Otherwise only add the current seed
+    if (fRefDet.fdTimeWinBeg < fRefDet.fdTimeWinEnd) {
+      SearchMatches(dSeedTime, fRefDet);
+      /// Also add the seed if the window starts after the seed
+      if (0 < fRefDet.fdTimeWinBeg) AddDigiToEvent(fRefDet, uSeedDigiIdx);
+    }
+    else {
+      AddDigiToEvent(fRefDet, uSeedDigiIdx);
+    }
   }
 
   /// Search for matches for each detector in selection list
@@ -413,7 +470,7 @@ void CbmAlgoBuildRawEvents::CheckTriggerCondition(Double_t dSeedTime)
     /// from end of current window in order to save CPU and avoid duplicating
     if (EOverlapModeRaw::NoOverlap == fOverMode || EOverlapModeRaw::MergeOverlap == fOverMode) {
       /// Update reference detector
-      fRefDet.fuStartIndex = fRefDet.fuEndIndex;
+      if (fRefDet.detId != ECbmModuleId::kNotExist) { fRefDet.fuStartIndex = fRefDet.fuEndIndex; }
       /// Loop on selection detectors
       for (std::vector<RawEventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) {
         (*det).fuStartIndex = (*det).fuEndIndex;
@@ -430,7 +487,9 @@ void CbmAlgoBuildRawEvents::CheckTriggerCondition(Double_t dSeedTime)
 Bool_t CbmAlgoBuildRawEvents::HasTrigger(CbmEvent* event)
 {
   /// Check first reference detector
-  if (kFALSE == CheckTriggerConditions(event, fRefDet)) { return kFALSE; }
+  if (fRefDet.detId != ECbmModuleId::kNotExist) {
+    if (kFALSE == CheckTriggerConditions(event, fRefDet)) { return kFALSE; }
+  }
   /// Loop on selection detectors
   for (std::vector<RawEventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) {
     if (kFALSE == CheckTriggerConditions(event, *det)) return kFALSE;
@@ -844,9 +903,15 @@ void CbmAlgoBuildRawEvents::SetTriggerWindow(ECbmModuleId selDet, Double_t dWinB
 
 void CbmAlgoBuildRawEvents::UpdateTimeWinBoundariesExtrema()
 {
-  /// Initialize with reference detector
-  fdEarliestTimeWinBeg = fRefDet.fdTimeWinBeg;
-  fdLatestTimeWinEnd   = fRefDet.fdTimeWinEnd;
+  /// Initialize with reference detector or explicit times
+  if (fRefDet.detId != ECbmModuleId::kNotExist) {
+    fdEarliestTimeWinBeg = fRefDet.fdTimeWinBeg;
+    fdLatestTimeWinEnd   = fRefDet.fdTimeWinEnd;
+  }
+  else {
+    fdEarliestTimeWinBeg = fdSeedTimeWinBeg;
+    fdLatestTimeWinEnd   = fdSeedTimeWinEnd;
+  }
 
   /// Loop on selection detectors
   for (std::vector<RawEventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) {
@@ -858,7 +923,7 @@ void CbmAlgoBuildRawEvents::UpdateTimeWinBoundariesExtrema()
 void CbmAlgoBuildRawEvents::UpdateWidestTimeWinRange()
 {
   /// Initialize with reference detector
-  fdWidestTimeWinRange = fRefDet.fdTimeWinEnd - fRefDet.fdTimeWinBeg;
+  fdWidestTimeWinRange = GetSeedTimeWinRange();
 
   /// Loop on selection detectors
   for (std::vector<RawEventBuilderDetector>::iterator det = fvDets.begin(); det != fvDets.end(); ++det) {
diff --git a/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.h b/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.h
index 1af66f824d..7ab53eb48c 100644
--- a/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.h
+++ b/reco/eventbuilder/digis/CbmAlgoBuildRawEvents.h
@@ -151,6 +151,14 @@ public:
     fdTsOverLength = dTsOverLength;
   }
 
+  void SetSeedTimeWindow(Double_t timeWinBeg, Double_t timeWinEnd)
+  {
+    fdSeedTimeWinBeg = timeWinBeg;
+    fdSeedTimeWinEnd = timeWinEnd;
+    UpdateTimeWinBoundariesExtrema();
+    UpdateWidestTimeWinRange();
+  }
+
   /// Control flags
   void SetEventOverlapMode(EOverlapModeRaw mode) { fOverMode = mode; }
   void SetIgnoreTsOverlap(Bool_t bFlagIn = kTRUE) { fbIgnoreTsOverlap = bFlagIn; }
@@ -182,6 +190,8 @@ public:
     fMuchBeamTimeDigis = MuchBeamTimeDigis;
   }
 
+  void SetSeedTimes(std::vector<Double_t>* SeedTimes) { fSeedTimes = SeedTimes; }
+
   /// Data output access
   std::vector<CbmEvent*>& GetEventVector() { return fEventVector; }
   void ClearEventVector();
@@ -198,6 +208,7 @@ private:
 
   template<class DigiSeed>
   void LoopOnSeeds();
+
   void CheckSeed(Double_t dSeedTime, UInt_t uSeedDigiIdx);
   void CheckTriggerCondition(Double_t dSeedTime);
 
@@ -259,11 +270,18 @@ private:
   const std::vector<CbmRichDigi>* fRichDigis                 = nullptr;
   const std::vector<CbmPsdDigi>* fPsdDigis                   = nullptr;
 
+  // If explicit seed times are supplied.
+  const std::vector<Double_t>* fSeedTimes = nullptr;
+  Double_t fdSeedTimeWinBeg               = -100.0;
+  Double_t fdSeedTimeWinEnd               = 100.0;
+
   bool CheckDataAvailable(ECbmModuleId detId);
   UInt_t GetNofDigis(ECbmModuleId detId);
   template<class Digi>
   const Digi* GetDigi(UInt_t uDigi);
 
+  Double_t GetSeedTimeWinRange();
+
   /// Data ouptut
   CbmEvent* fCurrentEvent             = nullptr;  //! pointer to the event which is currently build
   std::vector<CbmEvent*> fEventVector = {};       //! vector with all created events
diff --git a/reco/eventbuilder/digis/CbmTaskBuildRawEvents.cxx b/reco/eventbuilder/digis/CbmTaskBuildRawEvents.cxx
index 67e642bb4b..23445eda84 100644
--- a/reco/eventbuilder/digis/CbmTaskBuildRawEvents.cxx
+++ b/reco/eventbuilder/digis/CbmTaskBuildRawEvents.cxx
@@ -113,6 +113,7 @@ InitStatus CbmTaskBuildRawEvents::Init()
     return kFATAL;
 }
 
+
 InitStatus CbmTaskBuildRawEvents::ReInit() { return kSUCCESS; }
 
 void CbmTaskBuildRawEvents::Exec(Option_t* /*option*/)
@@ -122,12 +123,16 @@ void CbmTaskBuildRawEvents::Exec(Option_t* /*option*/)
   //as the digi manager can return -1, which would be casted to +1
   //during comparison, leading to an error.
 
+  //Reset explicit seed times if set
+  if (fSeedTimeDet != kRawEventBuilderDetUndef) { fSeedTimes->clear(); }
+
   //Read STS digis
   if (fDigiMan->IsPresent(ECbmModuleId::kSts)) {
     fStsDigis->clear();
     for (Int_t i = 0; i < fDigiMan->GetNofDigis(ECbmModuleId::kSts); i++) {
       const CbmStsDigi* Digi = fDigiMan->Get<CbmStsDigi>(i);
       fStsDigis->push_back(*Digi);
+      if (fSeedTimeDet.detId == ECbmModuleId::kSts) { fSeedTimes->push_back(Digi->GetTime()); }
     }
     LOG(debug) << "Read: " << fStsDigis->size() << " STS digis.";
     LOG(debug) << "In DigiManager: " << fDigiMan->GetNofDigis(ECbmModuleId::kSts) << " STS digis.";
@@ -140,6 +145,7 @@ void CbmTaskBuildRawEvents::Exec(Option_t* /*option*/)
       for (Int_t i = 0; i < fDigiMan->GetNofDigis(ECbmModuleId::kMuch); i++) {
         const CbmMuchBeamTimeDigi* Digi = fDigiMan->Get<CbmMuchBeamTimeDigi>(i);
         fMuchBeamTimeDigis->push_back(*Digi);
+        if (fSeedTimeDet.detId == ECbmModuleId::kMuch) { fSeedTimes->push_back(Digi->GetTime()); }
       }
       LOG(debug) << "Read: " << fDigiMan->GetNofDigis(ECbmModuleId::kMuch) << " MUCH digis.";
       LOG(debug) << "In DigiManager: " << fMuchBeamTimeDigis->size() << " MUCH digis.";
@@ -149,6 +155,7 @@ void CbmTaskBuildRawEvents::Exec(Option_t* /*option*/)
       for (Int_t i = 0; i < fDigiMan->GetNofDigis(ECbmModuleId::kMuch); i++) {
         const CbmMuchDigi* Digi = fDigiMan->Get<CbmMuchDigi>(i);
         fMuchDigis->push_back(*Digi);
+        if (fSeedTimeDet.detId == ECbmModuleId::kMuch) { fSeedTimes->push_back(Digi->GetTime()); }
       }
       LOG(debug) << "Read: " << fDigiMan->GetNofDigis(ECbmModuleId::kMuch) << " MUCH digis.";
       LOG(debug) << "In DigiManager: " << fMuchDigis->size() << " MUCH digis.";
@@ -161,6 +168,7 @@ void CbmTaskBuildRawEvents::Exec(Option_t* /*option*/)
     for (Int_t i = 0; i < fDigiMan->GetNofDigis(ECbmModuleId::kTrd); i++) {
       const CbmTrdDigi* Digi = fDigiMan->Get<CbmTrdDigi>(i);
       fTrdDigis->push_back(*Digi);
+      if (fSeedTimeDet.detId == ECbmModuleId::kTrd) { fSeedTimes->push_back(Digi->GetTime()); }
     }
     LOG(debug) << "Read: " << fDigiMan->GetNofDigis(ECbmModuleId::kTrd) << " TRD digis.";
     LOG(debug) << "In DigiManager: " << fTrdDigis->size() << " TRD digis.";
@@ -172,6 +180,7 @@ void CbmTaskBuildRawEvents::Exec(Option_t* /*option*/)
     for (Int_t i = 0; i < fDigiMan->GetNofDigis(ECbmModuleId::kTof); i++) {
       const CbmTofDigi* Digi = fDigiMan->Get<CbmTofDigi>(i);
       fTofDigis->push_back(*Digi);
+      if (fSeedTimeDet.detId == ECbmModuleId::kTof) { fSeedTimes->push_back(Digi->GetTime()); }
     }
     LOG(debug) << "Read: " << fDigiMan->GetNofDigis(ECbmModuleId::kTof) << " TOF digis.";
     LOG(debug) << "In DigiManager: " << fTofDigis->size() << " TOF digis.";
@@ -183,6 +192,7 @@ void CbmTaskBuildRawEvents::Exec(Option_t* /*option*/)
     for (Int_t i = 0; i < fDigiMan->GetNofDigis(ECbmModuleId::kRich); i++) {
       const CbmRichDigi* Digi = fDigiMan->Get<CbmRichDigi>(i);
       fRichDigis->push_back(*Digi);
+      if (fSeedTimeDet.detId == ECbmModuleId::kRich) { fSeedTimes->push_back(Digi->GetTime()); }
     }
     LOG(debug) << "Read: " << fDigiMan->GetNofDigis(ECbmModuleId::kRich) << " RICH digis.";
     LOG(debug) << "In DigiManager: " << fRichDigis->size() << " RICH digis.";
@@ -194,10 +204,12 @@ void CbmTaskBuildRawEvents::Exec(Option_t* /*option*/)
     for (Int_t i = 0; i < fDigiMan->GetNofDigis(ECbmModuleId::kPsd); i++) {
       const CbmPsdDigi* Digi = fDigiMan->Get<CbmPsdDigi>(i);
       fPsdDigis->push_back(*Digi);
+      if (fSeedTimeDet.detId == ECbmModuleId::kPsd) { fSeedTimes->push_back(Digi->GetTime()); }
     }
     LOG(debug) << "Read: " << fDigiMan->GetNofDigis(ECbmModuleId::kPsd) << " PSD digis.";
     LOG(debug) << "In DigiManager: " << fPsdDigis->size() << " PSD digis.";
   }
+
   /// Call Algo ProcessTs method
   fpAlgo->ProcessTs();
 
diff --git a/reco/eventbuilder/digis/CbmTaskBuildRawEvents.h b/reco/eventbuilder/digis/CbmTaskBuildRawEvents.h
index e736d634a2..267fa86141 100644
--- a/reco/eventbuilder/digis/CbmTaskBuildRawEvents.h
+++ b/reco/eventbuilder/digis/CbmTaskBuildRawEvents.h
@@ -114,6 +114,22 @@ public:
     if (nullptr != fpAlgo) fpAlgo->ChangeMuchBeamtimeDigiFlag(bFlagIn);
     fbUseMuchBeamtimeDigi = bFlagIn;
   }
+  void SetSeedTimeFiller(RawEventBuilderDetector seedDet)
+  {
+    fSeedTimeDet = seedDet;
+    if (fSeedTimeDet != kRawEventBuilderDetUndef) {
+      if (fSeedTimes == nullptr) { fSeedTimes = new std::vector<Double_t>; }
+    }
+    else {
+      if (fSeedTimes != nullptr) {
+        fSeedTimes->clear();
+        delete fSeedTimes;
+        fSeedTimes = nullptr;
+      }
+    }
+    fpAlgo->SetSeedTimes(fSeedTimes);
+  }
+  void SetSeedTimeWindow(Double_t beg, Double_t end) { fpAlgo->SetSeedTimeWindow(beg, end); }
 
 private:
   void FillOutput();
@@ -129,8 +145,12 @@ private:
   std::vector<CbmRichDigi>* fRichDigis                 = nullptr;
   std::vector<CbmPsdDigi>* fPsdDigis                   = nullptr;
 
+  std::vector<Double_t>* fSeedTimes = nullptr;
+
   Bool_t fbUseMuchBeamtimeDigi = kTRUE;  //! Switch between MUCH digi classes
 
+  RawEventBuilderDetector fSeedTimeDet = kRawEventBuilderDetUndef;
+
   CbmAlgoBuildRawEvents* fpAlgo = nullptr;
 
   TClonesArray* fEvents = nullptr;  //! output container of CbmEvents
-- 
GitLab