From 2237f5bb68106981170d71aacbfec0898b69fbf0 Mon Sep 17 00:00:00 2001
From: Felix Weiglhofer <weiglhofer@fias.uni-frankfurt.de>
Date: Fri, 11 Jun 2021 15:53:06 +0000
Subject: [PATCH] Digitization: Make digi timestamp relative to the beginning
 of the time slice.

---
 core/base/CbmDigitize.h                     | 20 +++++++++++++++-----
 core/data/mvd/CbmMvdDigi.h                  |  1 +
 core/data/sts/CbmStsDigi.h                  |  8 +++++++-
 mvd/CbmMvdDigitizer.cxx                     |  8 ++++----
 sim/detectors/much/CbmMuchDigitizeGem.cxx   |  2 +-
 sim/detectors/psd/CbmPsdSimpleDigitizer.cxx |  3 +--
 sim/detectors/rich/CbmRichDigitizer.cxx     |  4 ++--
 sim/detectors/sts/CbmStsDigitize.cxx        |  8 +++++---
 sim/detectors/tof/CbmTofDigitize.cxx        |  6 +++---
 sim/detectors/trd/CbmTrdDigitizer.cxx       |  8 +++++---
 sim/detectors/trd/CbmTrdModuleSimT.cxx      | 16 ++++++++--------
 11 files changed, 52 insertions(+), 32 deletions(-)

diff --git a/core/base/CbmDigitize.h b/core/base/CbmDigitize.h
index 207ab68d51..0ba33d2fe3 100644
--- a/core/base/CbmDigitize.h
+++ b/core/base/CbmDigitize.h
@@ -210,22 +210,28 @@ public:
 
   // --------------------------------------------------------------------------
   /** @brief Send a digi and the corresponding match object to the DAQ
+     ** @param time  Global time of the digi
      ** @param digi  Pointer to digi object (template parameter)
      ** @param match Pointer to match object
      **
+     ** Time is passed as a seperate parameter because the global time might
+     ** be too large for some digi classes to store internally. So digis are not
+     ** required to have a valid timestamp at this point. Later on when the
+     ** time slices are known, the timestamp is overwritten with the relative time
+     ** to the beginning of the time slice.
+     **
      ** TODO: The interface should be unique pointers, meaning
      ** that the digitisers have to create objects by unique pointers
      ** from the start.
      **/
-  void SendData(Digi* digi, CbmMatch* match = nullptr)
+  void SendData(Double_t time, Digi* digi, CbmMatch* match = nullptr)
   {
     std::unique_ptr<Digi> tmpDigi(digi);
     std::unique_ptr<CbmMatch> tmpMatch(match);
-    fDaqBuffer.insert(make_pair(digi->GetTime(), std::make_pair(std::move(tmpDigi), std::move(tmpMatch))));
+    fDaqBuffer.insert(make_pair(time, std::make_pair(std::move(tmpDigi), std::move(tmpMatch))));
   }
   // --------------------------------------------------------------------------
 
-
 private:
   TString fBranchName             = "";       ///< Output branch name
   std::vector<Digi>* fDigis       = nullptr;  //! Output array (Digi)
@@ -268,6 +274,7 @@ private:
       checkMinTime = kFALSE;
       checkMaxTime = checkLimit;
       tMax         = fillTime;
+      tMin         = 0;  // Do not make digi time relative for these types of time slices.
     }
     else {
       LOG(fatal) << GetName() << ": Unknown time-slice type!";
@@ -294,8 +301,11 @@ private:
       // manual removal from the source vector. There might be a more
       // elegant way.
       assert(fDigis);
-      assert(it->second.first);
-      fDigis->push_back(*(it->second.first));
+      Double_t globalTime      = it->first;
+      std::unique_ptr<Digi>& d = it->second.first;
+      assert(d);
+      d->SetTime(globalTime - tMin);
+      fDigis->push_back(*d);
       if (fCreateMatches) {
         assert(fMatches);
         assert(it->second.second);
diff --git a/core/data/mvd/CbmMvdDigi.h b/core/data/mvd/CbmMvdDigi.h
index 279cb0c329..e7e5525f1c 100644
--- a/core/data/mvd/CbmMvdDigi.h
+++ b/core/data/mvd/CbmMvdDigi.h
@@ -80,6 +80,7 @@ public:
   void SetFlag(Int_t flag) { fDigiFlag = flag; }
   void SetFrameNr(Int_t frame) { fFrameNumber = frame; };
   void SetRefId(Int_t refId) { fRefId = refId; }
+  void SetTime(Double_t time) { fDigiTime = time; }
 
 private:
   Float_t fCharge;
diff --git a/core/data/sts/CbmStsDigi.h b/core/data/sts/CbmStsDigi.h
index 43d6be7375..baab836131 100644
--- a/core/data/sts/CbmStsDigi.h
+++ b/core/data/sts/CbmStsDigi.h
@@ -20,6 +20,7 @@
 #include <boost/serialization/access.hpp>
 #include <boost/serialization/base_object.hpp>
 
+#include <cassert>
 #include <string>  // for string
 
 /** @class CbmStsDigi
@@ -111,7 +112,12 @@ public:
   /** Update Time of measurement
    ** @param New Time [ns]
    **/
-  void SetTime(Double_t dNewTime) { fTime = dNewTime; }
+  void SetTime(Double_t dNewTime)
+  {
+    // Future versions of StsDigi won't be able to store negative timestamps.
+    assert(dNewTime >= 0);
+    fTime = dNewTime;
+  }
 
 
   /** String output **/
diff --git a/mvd/CbmMvdDigitizer.cxx b/mvd/CbmMvdDigitizer.cxx
index abd8fbc7f5..5e046b420a 100644
--- a/mvd/CbmMvdDigitizer.cxx
+++ b/mvd/CbmMvdDigitizer.cxx
@@ -151,7 +151,7 @@ void CbmMvdDigitizer::Exec(Option_t* /*opt*/)
       fMatchVect.push_back(match1);
 
       //digi1->SetMatch(match1);
-      SendData(digi1, match1);
+      SendData(digi1->GetTime(), digi1, match1);
       nDigis++;
     }
 
@@ -159,13 +159,13 @@ void CbmMvdDigitizer::Exec(Option_t* /*opt*/)
     /*
    for (Int_t index = 0; index < fTmpDigi->GetEntriesFast(); index++) {
 
-     LOG(info) << "Size: " << fTmpDigi->GetEntriesFast() << ", " 
+     LOG(info) << "Size: " << fTmpDigi->GetEntriesFast() << ", "
                << fTmpDigi->GetEntries();
- 
+
      CbmMvdDigi* digi = dynamic_cast<CbmMvdDigi*>(fTmpDigi->Remove(fTmpDigi->At(index)));
      digi->Print();
      fDigiVect.push_back(digi);
-        
+
      CbmMatch* match = dynamic_cast<CbmMatch*>(fTmpMatch->Remove(fTmpMatch->At(index)));
      match->Print();
      fMatchVect.push_back(match);
diff --git a/sim/detectors/much/CbmMuchDigitizeGem.cxx b/sim/detectors/much/CbmMuchDigitizeGem.cxx
index 0b74c91bf6..8dee1a47ac 100644
--- a/sim/detectors/much/CbmMuchDigitizeGem.cxx
+++ b/sim/detectors/much/CbmMuchDigitizeGem.cxx
@@ -648,7 +648,7 @@ void CbmMuchDigitizeGem::ReadAndRegister(Long_t eventTime)
       LOG(debug2) << GetName() << ": New digi: sector = " << CbmMuchAddress::GetSectorIndex(digi->GetAddress())
                   << " channel= " << CbmMuchAddress::GetChannelIndex(digi->GetAddress());
 
-      SendData(digi, digiMatch);
+      SendData(digi->GetTime(), digi, digiMatch);
       fNofDigis++;
     }
   }
diff --git a/sim/detectors/psd/CbmPsdSimpleDigitizer.cxx b/sim/detectors/psd/CbmPsdSimpleDigitizer.cxx
index 54fc20fddd..20189379d7 100644
--- a/sim/detectors/psd/CbmPsdSimpleDigitizer.cxx
+++ b/sim/detectors/psd/CbmPsdSimpleDigitizer.cxx
@@ -136,10 +136,9 @@ void CbmPsdSimpleDigitizer::Exec(Option_t*)
     Double_t eLossSmeared    = eLossMIPSmeared * 0.005;
     Double_t eNoise          = gRandom->Gaus(0, 15) / 50. * 0.005;
     eLossSmeared += eNoise;
-    // The digi time is set to MC point time [relative to event start] + Event Start time
     CbmPsdDigi* digi =
       new CbmPsdDigi(entry.second.GetAddress(), entry.second.GetTime() + fCurrentEventTime, eLossSmeared);
-    SendData(digi);
+    SendData(digi->GetTime(), digi);
     nDigis++;
     LOG(debug1) << fName << ": Digi " << nDigis << " Time " << entry.second.GetTime() + fCurrentEventTime << " Section "
                 << entry.second.GetSectionID() << " Module " << entry.second.GetModuleID() << " energy "
diff --git a/sim/detectors/rich/CbmRichDigitizer.cxx b/sim/detectors/rich/CbmRichDigitizer.cxx
index 2278c49e4c..d9319dce98 100644
--- a/sim/detectors/rich/CbmRichDigitizer.cxx
+++ b/sim/detectors/rich/CbmRichDigitizer.cxx
@@ -292,9 +292,9 @@ Int_t CbmRichDigitizer::AddDigisToOutputArray()
     CbmMatch* digiMatch = new CbmMatch(*dm.second.second);
     digi->SetTime(dm.second.first->GetTime());
     //SendDigi(digi, digiMatch);
-    if (fCreateMatches) SendData(digi, digiMatch);
+    if (fCreateMatches) SendData(digi->GetTime(), digi, digiMatch);
     else
-      SendData(digi);
+      SendData(digi->GetTime(), digi);
     nofDigis++;
   }  //# digis in map
 
diff --git a/sim/detectors/sts/CbmStsDigitize.cxx b/sim/detectors/sts/CbmStsDigitize.cxx
index 976eb973b7..8509a08e1c 100644
--- a/sim/detectors/sts/CbmStsDigitize.cxx
+++ b/sim/detectors/sts/CbmStsDigitize.cxx
@@ -150,19 +150,21 @@ string CbmStsDigitize::BufferStatus() const
 // -----   Create a digi object   ------------------------------------------
 void CbmStsDigitize::CreateDigi(Int_t address, UShort_t channel, Long64_t time, UShort_t adc, const CbmMatch& match)
 {
+  assert(time >= 0);
 
   // Update times of first and last digi
   fTimeDigiFirst = fNofDigis ? TMath::Min(fTimeDigiFirst, Double_t(time)) : time;
   fTimeDigiLast  = TMath::Max(fTimeDigiLast, Double_t(time));
 
   // Create digi and (if required) match and send them to DAQ
-  CbmStsDigi* digi = new CbmStsDigi(address, channel, time, adc);
+  // Digi time is set later, when creating the timestamp
+  CbmStsDigi* digi = new CbmStsDigi(address, channel, 0, adc);
   if (fCreateMatches) {
     CbmMatch* digiMatch = new CbmMatch(match);
-    SendData(digi, digiMatch);
+    SendData(time, digi, digiMatch);
   }
   else
-    SendData(digi);
+    SendData(time, digi);
   fNofDigis++;
 }
 // -------------------------------------------------------------------------
diff --git a/sim/detectors/tof/CbmTofDigitize.cxx b/sim/detectors/tof/CbmTofDigitize.cxx
index 6686d182fe..c8ce975ad5 100644
--- a/sim/detectors/tof/CbmTofDigitize.cxx
+++ b/sim/detectors/tof/CbmTofDigitize.cxx
@@ -1043,7 +1043,7 @@ Bool_t CbmTofDigitize::MergeSameChanDigis()
     const Double_t dHitTot = 2.;
     CbmTofDigi* tDigi      = new CbmTofDigi(uChanUId, dHitTime, dHitTot);
     CbmMatch* tMatch       = new CbmMatch();
-    SendData(tDigi, tMatch);  // Send digi to DAQ
+    SendData(tDigi->GetTime(), tDigi, tMatch);  // Send digi to DAQ
     fiNbDigis++;
     LOG(debug) << Form("Add fake diamond digis 0x%08x mode with t = %7.3f", uChanUId, dHitTime);
     //delete tDigi;
@@ -1137,7 +1137,7 @@ Bool_t CbmTofDigitize::MergeSameChanDigis()
                       new CbmMatch(*(fStorDigi[iSmType][iSm * iNbRpc + iRpc][iNbSides * iCh + iSide][iDigi0].second));
 
                     digi->SetTime(digi->GetTime() * fdDigiTimeConvFactor + fCurrentEventTime);  // ns->ps
-                    SendData(digi, match);                                                      // Send digi to DAQ
+                    SendData(digi->GetTime(), digi, match);                                     // Send digi to DAQ
                     fiNbDigis++;
 
                     // TOF QA
@@ -1176,7 +1176,7 @@ Bool_t CbmTofDigitize::MergeSameChanDigis()
               CbmMatch* match =
                 new CbmMatch(*(fStorDigi[iSmType][iSm * iNbRpc + iRpc][iNbSides * iCh + iSide][iDigi0].second));
               digi->SetTime(digi->GetTime() * fdDigiTimeConvFactor + fCurrentEventTime);  // ns->ps
-              SendData(digi, match);                                                      // Send digi to DAQ
+              SendData(digi->GetTime(), digi, match);                                     // Send digi to DAQ
               fiNbDigis++;
 
               if (fbMonitorHistos) {
diff --git a/sim/detectors/trd/CbmTrdDigitizer.cxx b/sim/detectors/trd/CbmTrdDigitizer.cxx
index bc51eaf5e6..c80773c402 100644
--- a/sim/detectors/trd/CbmTrdDigitizer.cxx
+++ b/sim/detectors/trd/CbmTrdDigitizer.cxx
@@ -211,7 +211,8 @@ void CbmTrdDigitizer::Exec(Option_t*)
     //printf("  Digits[%d] %d\n", imod->first, digis->size());
     for (std::map<Int_t, pair<CbmTrdDigi*, CbmMatch*>>::iterator it = digis->begin(); it != digis->end(); it++) {
       assert(it->second.second);
-      SendData(it->second.first, it->second.second);
+      CbmTrdDigi* digi = it->second.first;
+      SendData(digi->GetTime(), digi, it->second.second);
       nDigis++;
     }  //# modules
     digis->clear();
@@ -248,7 +249,8 @@ void CbmTrdDigitizer::FlushBuffers()
     std::map<Int_t, std::pair<CbmTrdDigi*, CbmMatch*>>* digis = imod->second->GetDigiMap();
     for (std::map<Int_t, pair<CbmTrdDigi*, CbmMatch*>>::iterator it = digis->begin(); it != digis->end(); it++) {
       assert(it->second.second);
-      SendData(it->second.first, it->second.second);
+      CbmTrdDigi* digi = it->second.first;
+      SendData(digi->GetTime(), digi, it->second.second);
       nDigis++;
     }  //# modules
     digis->clear();
@@ -278,7 +280,7 @@ CbmTrdModuleSim* CbmTrdDigitizer::AddModule(Int_t detId)
  * The trd layer is again only a container for all volumes of this layer.
  * Loop over all nodes below the top node (cave). If one of
  * the nodes contains a string trd it must be TRD detector.
- * Now loop over the layers and 
+ * Now loop over the layers and
  * then over all modules of the layer to extract in the end
  * all active regions (gas) of the complete TRD. For each
  * of the gas volumes get the information about size and
diff --git a/sim/detectors/trd/CbmTrdModuleSimT.cxx b/sim/detectors/trd/CbmTrdModuleSimT.cxx
index 85901644d7..b21a000f01 100644
--- a/sim/detectors/trd/CbmTrdModuleSimT.cxx
+++ b/sim/detectors/trd/CbmTrdModuleSimT.cxx
@@ -62,8 +62,8 @@ CbmTrdModuleSimT::~CbmTrdModuleSimT()
 //_________________________________________________________________________________
 Bool_t CbmTrdModuleSimT::MakeDigi(CbmTrdPoint* point, Double_t time, Bool_t TR)
 {
-  /**  
-  Steering routine for building digits out of the TRD hit for the triangular pad geometry. 
+  /**
+  Steering routine for building digits out of the TRD hit for the triangular pad geometry.
   1. Scan the amplification cells span by the track\n
   2. Build digits for each cell proportional with the projected energy on the cell\n
     2.1 Continuous distribution for ionisation\n
@@ -281,14 +281,14 @@ Bool_t CbmTrdModuleSimT::MakeDigi(CbmTrdPoint* point, Double_t time, Bool_t TR)
 //_________________________________________________________________________________
 Bool_t CbmTrdModuleSimT::ScanPadPlane(const Double_t* point, Double_t DX, Double_t ELoss, Double_t toff)
 {
-  /**  
+  /**
   The hit is expressed in local chamber coordinates, localized as follows:
     - Along the wire in the middle of the track projection on the closest wire
     - Across the wire on the closest anode.
-    
+
   The physical uncertainty along wires is given by the projection span (dx) and the energy from ionisation is proportional to the track projection length in the local chamber x-y plane. For the TR energy the proportionality to the total TR is given by the integral over the amplification cell span of a decay law with decay constant ...
-  
-  The class CbmTrdTrianglePRF is used to navigate the pad plane outward from the hit position until a threshold wrt to center is reached. The pad-row cross clusters are considered. Finally all digits are registered via AddDigi() function. 
+
+  The class CbmTrdTrianglePRF is used to navigate the pad plane outward from the hit position until a threshold wrt to center is reached. The pad-row cross clusters are considered. Finally all digits are registered via AddDigi() function.
 */
   if (VERBOSE)
     printf("        WirePlane : xy[%7.4f %7.4f] D[%7.4f] S[fC]=%7.4f "
@@ -563,7 +563,7 @@ void CbmTrdModuleSimT::AddDigi(Int_t address, Double_t* charge, Double_t time /*
 Int_t CbmTrdModuleSimT::FlushBuffer(ULong64_t time)
 {
   /** Flush time sorted digi buffer until requested moment in time. If time limit not specified flush all digits.
- *  Calculate timely interaction between digits which are produced either on different anode wires for the same particle or 
+ *  Calculate timely interaction between digits which are produced either on different anode wires for the same particle or
  * are produced by 2 particle close by. Also take into account FASP dead time and mark such digits correspondingly
  */
 
@@ -694,7 +694,7 @@ Int_t CbmTrdModuleSimT::FlushBuffer(ULong64_t time)
 
       if (VERBOSE) cout << "\t" << digi->ToString();
       digiMatch = iv->second;
-      fDigitizer->SendData(digi, digiMatch);
+      fDigitizer->SendData(digi->GetTime(), digi, digiMatch);
       n++;
       iv = fBuffer[localAddress].erase(iv);  // remove from saved buffer
     }
-- 
GitLab