From 9e78e1527215d082f6ed72b4f163a098f3e498f6 Mon Sep 17 00:00:00 2001
From: Volker Friese <v.friese@gsi.de>
Date: Mon, 7 Nov 2022 14:46:03 +0100
Subject: [PATCH] Introduce BMON digitizer with a simple, parameterised
 implementation along with CbmBmonDigi data class.

---
 core/data/CMakeLists.txt               |   1 +
 core/data/CbmDataLinkDef.h             |   4 +-
 core/data/global/CbmBmonDigi.cxx       |   5 ++
 core/data/global/CbmBmonDigi.h         |  56 ++++++++++++++
 sim/detectors/CMakeLists.txt           |   1 +
 sim/detectors/bmon/CMakeLists.txt      |  33 ++++++++
 sim/detectors/bmon/CbmBmonDigitize.cxx |  99 ++++++++++++++++++++++++
 sim/detectors/bmon/CbmBmonDigitize.h   | 102 +++++++++++++++++++++++++
 sim/detectors/bmon/CbmBmonSimLinkDef.h |  14 ++++
 sim/response/CMakeLists.txt            |   1 +
 sim/response/base/CbmDigitization.cxx  |  11 ++-
 11 files changed, 324 insertions(+), 3 deletions(-)
 create mode 100644 core/data/global/CbmBmonDigi.cxx
 create mode 100644 core/data/global/CbmBmonDigi.h
 create mode 100644 sim/detectors/bmon/CMakeLists.txt
 create mode 100644 sim/detectors/bmon/CbmBmonDigitize.cxx
 create mode 100644 sim/detectors/bmon/CbmBmonDigitize.h
 create mode 100644 sim/detectors/bmon/CbmBmonSimLinkDef.h

diff --git a/core/data/CMakeLists.txt b/core/data/CMakeLists.txt
index 3e9bd576f3..1bbd0817e1 100644
--- a/core/data/CMakeLists.txt
+++ b/core/data/CMakeLists.txt
@@ -98,6 +98,7 @@ set(SRCS
   psd/CbmPsdAddress.cxx
   psd/CbmPsdMCbmHit.cxx
 
+  global/CbmBmonDigi.cxx
   global/CbmGlobalTrack.cxx
   global/CbmVertex.cxx
   global/CbmTofTrack.cxx
diff --git a/core/data/CbmDataLinkDef.h b/core/data/CbmDataLinkDef.h
index ecec751d79..6024d55f93 100644
--- a/core/data/CbmDataLinkDef.h
+++ b/core/data/CbmDataLinkDef.h
@@ -28,7 +28,7 @@
 #pragma link C++ class CbmErrorMessage + ;
 #pragma link C++ class CbmRawEvent + ;
 #pragma link C++ class CbmTsEventHeader + ;
-#pragma link C++ class std::vector<CbmErrorMessage> + ;
+#pragma link C++ class std::vector < CbmErrorMessage> + ;
 
 // ---In base
 #pragma link C++ class CbmDigiBranchBase + ;
@@ -91,6 +91,7 @@
 #pragma link C++ class CbmPsdMCbmHit;
 
 // --- data/global
+#pragma link C++ class CbmBmonDigi + ;
 #pragma link C++ class CbmGlobalTrack + ;
 #pragma link C++ class CbmTofTrack + ;
 #pragma link C++ class CbmVertex + ;
@@ -116,6 +117,7 @@
 #pragma link C++ enum ECbmModuleId;
 #pragma link C++ enum ECbmDataType;
 
+#pragma link C++ class vector < CbmBmonDigi> + ;
 #pragma link C++ class vector < CbmMvdDigi> + ;
 #pragma link C++ class vector < CbmStsDigi> + ;
 #pragma link C++ class vector < CbmRichDigi> + ;
diff --git a/core/data/global/CbmBmonDigi.cxx b/core/data/global/CbmBmonDigi.cxx
new file mode 100644
index 0000000000..7f261adc8f
--- /dev/null
+++ b/core/data/global/CbmBmonDigi.cxx
@@ -0,0 +1,5 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+#include "CbmBmonDigi.h"
diff --git a/core/data/global/CbmBmonDigi.h b/core/data/global/CbmBmonDigi.h
new file mode 100644
index 0000000000..25c5157837
--- /dev/null
+++ b/core/data/global/CbmBmonDigi.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+
+#ifndef CBMBMONDIGI_H
+#define CBMBMONDIGI_H 1
+
+/** @class CbmBmonDigi
+ ** @brief Data class for a signal in the BMON detector
+ **
+ ** The current implementation is a placeholder, storing just the event time. To be replaced
+ ** with a real detector measurement model once available.
+ **/
+class CbmBmonDigi {
+
+public:
+  /** @brief Constructor
+   ** @param time Measurement time [ns]
+   **/
+  CbmBmonDigi(double time = -1.) { fTime = time; };
+
+
+  /** @brief Destructor **/
+  virtual ~CbmBmonDigi() {};
+
+
+  /** @brief Get the desired name of the branch for this objects in the cbm output tree  (static)
+   ** @return "BmonDigi"
+   **/
+  static const char* GetBranchName() { return "BmonDigi"; }
+
+
+  /** @brief Class name (static)
+   ** @return CbmBmonDigi
+   **/
+  static const char* GetClassName() { return "CbmBmonDigi"; }
+
+
+  /** @brief Time
+   ** @return Time of measurement [ns]
+   **/
+  double GetTime() const { return fTime; }
+
+
+  /** @brief Set the measurement time
+   ** @param time Measurement time [ns]
+   **/
+  void SetTime(double time) { fTime = time; }
+
+
+private:
+  double fTime;  ///! Time of signal in BMON [ns]
+};
+
+#endif /* CBMBMONDIGI_H */
diff --git a/sim/detectors/CMakeLists.txt b/sim/detectors/CMakeLists.txt
index fed93c0fba..1efd0c361e 100644
--- a/sim/detectors/CMakeLists.txt
+++ b/sim/detectors/CMakeLists.txt
@@ -7,4 +7,5 @@ add_subdirectory(rich)
 add_subdirectory(sts)
 add_subdirectory(tof)
 add_subdirectory(trd)
+add_subdirectory(bmon)
 
diff --git a/sim/detectors/bmon/CMakeLists.txt b/sim/detectors/bmon/CMakeLists.txt
new file mode 100644
index 0000000000..5f4ea051f1
--- /dev/null
+++ b/sim/detectors/bmon/CMakeLists.txt
@@ -0,0 +1,33 @@
+set(INCLUDE_DIRECTORIES
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  )
+
+
+set(SRCS
+  CbmBmonDigitize.cxx
+  )
+
+
+set(LIBRARY_NAME CbmBmonSim)
+set(LINKDEF ${LIBRARY_NAME}LinkDef.h)
+set(PUBLIC_DEPENDENCIES
+  CbmBase
+  CbmData
+  FairRoot::Base
+  ROOT::Core
+  ROOT::Hist
+  ROOT::MathCore
+  )
+
+set(PRIVATE_DEPENDENCIES
+  CbmSimBase
+  FairRoot::ParBase
+  ROOT::EG
+  ROOT::Geom
+  ROOT::Gpad
+  ROOT::Physics
+  ROOT::RIO
+  )
+
+generate_cbm_library()
+
diff --git a/sim/detectors/bmon/CbmBmonDigitize.cxx b/sim/detectors/bmon/CbmBmonDigitize.cxx
new file mode 100644
index 0000000000..eaf9f66cb5
--- /dev/null
+++ b/sim/detectors/bmon/CbmBmonDigitize.cxx
@@ -0,0 +1,99 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+/** @file CbmBmonDigitize.cxx
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @date 07.11.2022
+ **/
+
+#include "CbmBmonDigitize.h"
+
+#include "TRandom.h"
+
+#include <iomanip>
+
+using std::fixed;
+using std::left;
+using std::setprecision;
+using std::setw;
+
+
+// -----   Standard constructor   ------------------------------------------
+CbmBmonDigitize::CbmBmonDigitize(double sigma) : CbmDigitize<CbmBmonDigi>("BmonDigitize"), fResolution(sigma) {}
+// -------------------------------------------------------------------------
+
+
+// -----   Destructor   ----------------------------------------------------
+CbmBmonDigitize::~CbmBmonDigitize() {}
+// -------------------------------------------------------------------------
+
+
+// -----   Task execution   ------------------------------------------------
+void CbmBmonDigitize::Exec(Option_t*)
+{
+
+  // --- Start timer and reset counters
+  TStopwatch timer;
+  timer.Start();
+
+  // --- Get event time
+  GetEventInfo();
+
+  // --- Create digi and send it to DAQ
+  double digiTime   = fCurrentEventTime + gRandom->Gaus(0., fResolution);
+  CbmBmonDigi* digi = new CbmBmonDigi(digiTime);
+  if (fCreateMatches) {
+    CbmMatch* digiMatch = new CbmMatch();
+    SendData(digiTime, digi, digiMatch);
+  }
+  else
+    SendData(digiTime, digi);
+
+  // --- Event log
+  LOG(info) << left << setw(15) << GetName() << "[" << fixed << setprecision(3) << timer.RealTime() << " s]"
+            << " event time: " << fCurrentEventTime << " ns, measurement time " << digiTime << " ns";
+
+  // --- Monitor
+  timer.Stop();
+  fNofEvents++;
+  fTimeTot += timer.RealTime();
+}
+// -------------------------------------------------------------------------
+
+
+// -----   Finish run    ---------------------------------------------------
+void CbmBmonDigitize::Finish()
+{
+  std::cout << std::endl;
+  LOG(info) << "=====================================";
+  LOG(info) << GetName() << ": Run summary";
+  LOG(info) << "Events processed       : " << fNofEvents;
+  LOG(info) << "Real time per event    : " << fTimeTot / Double_t(fNofEvents) << " s";
+  LOG(info) << "=====================================";
+}
+// -------------------------------------------------------------------------
+
+
+// -----   Initialisation    -----------------------------------------------
+InitStatus CbmBmonDigitize::Init()
+{
+  std::cout << std::endl;
+  LOG(info) << "==========================================================";
+  LOG(info) << GetName() << ": Initialisation";
+  LOG(info) << "Time resolution is " << fResolution << " [ns]";
+  RegisterOutput();
+  LOG(info) << GetName() << ": Initialisation successful";
+  LOG(info) << "==========================================================";
+  std::cout << std::endl;
+  return kSUCCESS;
+}
+// -------------------------------------------------------------------------
+
+
+// -----   Private method ReInit   -----------------------------------------
+InitStatus CbmBmonDigitize::ReInit() { return kSUCCESS; }
+// -------------------------------------------------------------------------
+
+
+ClassImp(CbmBmonDigitize)
diff --git a/sim/detectors/bmon/CbmBmonDigitize.h b/sim/detectors/bmon/CbmBmonDigitize.h
new file mode 100644
index 0000000000..8d0041204a
--- /dev/null
+++ b/sim/detectors/bmon/CbmBmonDigitize.h
@@ -0,0 +1,102 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+/** @file CbmBmonDigitize.h
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @date 07.11.2022
+ **/
+
+#ifndef CBMBMONDIGITIZE_H
+#define CBMBMONDIGITIZE_H 1
+
+#include "CbmBmonDigi.h"
+#include "CbmDefs.h"
+#include "CbmDigitize.h"
+
+#include "TStopwatch.h"
+
+#include <map>
+
+class TClonesArray;
+class CbmStsPoint;
+class CbmStsParAsic;
+class CbmStsParModule;
+class CbmStsParSensor;
+class CbmStsParSensorCond;
+class CbmStsParSetModule;
+class CbmStsParSetSensor;
+class CbmStsParSetSensorCond;
+class CbmStsParSim;
+class CbmStsSetup;
+class CbmStsSimSensorFactory;
+
+
+/** @class CbmBmonDigitize
+ ** @brief Task class for simulating the detector response of the BMON
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @since 07.11.2022
+ ** @version 1.0
+ **
+ ** The current implementation of the BMON simulation is a placeholder until a realistic
+ ** detector response model is available. It smears the MC event time with a Gaussian resolution.
+ **/
+class CbmBmonDigitize : public CbmDigitize<CbmBmonDigi> {
+
+public:
+  /** Constructor **/
+  CbmBmonDigitize(double fResolution = 0.025);
+
+
+  /** Destructor **/
+  virtual ~CbmBmonDigitize();
+
+
+  /** Create a digi and send it for further processing
+   ** @param address   Unique channel address
+   ** @param time      Absolute time [ns]
+   ** @param adc       Digitised charge [ADC channels]
+   ** @param match    MC Match object
+   **/
+  void CreateDigi(Int_t address, UShort_t channel, Long64_t time, UShort_t adc, const CbmMatch& match);
+
+
+  /** @brief Detector system ID
+   ** @return kSts
+   **/
+  ECbmModuleId GetSystemId() const { return ECbmModuleId::kT0; }
+
+
+  /** Execution **/
+  virtual void Exec(Option_t* opt);
+
+
+  /** Re-initialisation **/
+  virtual InitStatus ReInit();
+
+
+  /** Set the time resolution **/
+  void SetResolution(double sigma) { fResolution = sigma; }
+
+
+private:
+  // --- Parameters
+  double fResolution = 0.025;  ///< Time resolution [ns]
+
+  // --- Run counters
+  size_t fNofEvents = 0;   ///< Total number of procesed events
+  Double_t fTimeTot = 0.;  ///< Total execution time
+
+
+  /** End-of-run action **/
+  virtual void Finish();
+
+
+  /** Initialisation **/
+  virtual InitStatus Init();
+
+
+  ClassDef(CbmBmonDigitize, 1);
+};
+
+#endif
diff --git a/sim/detectors/bmon/CbmBmonSimLinkDef.h b/sim/detectors/bmon/CbmBmonSimLinkDef.h
new file mode 100644
index 0000000000..1241fc96ca
--- /dev/null
+++ b/sim/detectors/bmon/CbmBmonSimLinkDef.h
@@ -0,0 +1,14 @@
+/* Copyright (C) 2022 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese [committer] */
+
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class CbmDigitize < CbmBmonDigi> + ;
+#pragma link C++ class CbmBmonDigitize + ;
+
+#endif /* __CINT__ */
diff --git a/sim/response/CMakeLists.txt b/sim/response/CMakeLists.txt
index dc7028155e..17898caaf5 100644
--- a/sim/response/CMakeLists.txt
+++ b/sim/response/CMakeLists.txt
@@ -21,6 +21,7 @@ set(PUBLIC_DEPENDENCIES
   )
 
 set(PRIVATE_DEPENDENCIES
+  CbmBmonSim
   CbmMuchSim
   CbmMvd
   CbmPsdSim
diff --git a/sim/response/base/CbmDigitization.cxx b/sim/response/base/CbmDigitization.cxx
index 641599131c..5c64e630a9 100644
--- a/sim/response/base/CbmDigitization.cxx
+++ b/sim/response/base/CbmDigitization.cxx
@@ -9,6 +9,7 @@
 
 #include "CbmDigitization.h"
 
+#include "CbmBmonDigitize.h"
 #include "CbmDigitizationSource.h"
 #include "CbmMuchDigitizeGem.h"
 #include "CbmMvdDigitizer.h"
@@ -151,8 +152,8 @@ Int_t CbmDigitization::CreateDefaultDigitizers()
     // --- Skip if marked inactive
     if (!it->second->IsActive()) continue;
 
-    // --- Skip if MC data branch is not present
-    if (!it->second->IsPresent()) continue;
+    // --- Skip if MC data branch is not present. Exception: BMON does not need an input branch.
+    if (it->first != ECbmModuleId::kT0 && !it->second->IsPresent()) continue;
 
     // --- Skip if a digitizer was set explicitly
     if (it->second->GetDigitizer() != nullptr) continue;
@@ -202,6 +203,11 @@ Int_t CbmDigitization::CreateDefaultDigitizers()
         ss << "PSD ";
         nDigis++;
         break;
+      case ECbmModuleId::kT0:
+        fDigitizers[system]->SetDigitizer(new CbmBmonDigitize());
+        ss << "BMON ";
+        nDigis++;
+        break;
       default: LOG(fatal) << fName << ": Unknown system " << system; break;
     }  //? system
   }    //# present systems
@@ -491,6 +497,7 @@ void CbmDigitization::SetDefaultBranches()
   fDigitizers[ECbmModuleId::kTrd]  = new CbmDigitizeInfo(ECbmModuleId::kTrd, "TrdPoint");
   fDigitizers[ECbmModuleId::kTof]  = new CbmDigitizeInfo(ECbmModuleId::kTof, "TofPoint");
   fDigitizers[ECbmModuleId::kPsd]  = new CbmDigitizeInfo(ECbmModuleId::kPsd, "PsdPoint");
+  fDigitizers[ECbmModuleId::kT0]   = new CbmDigitizeInfo(ECbmModuleId::kT0, "");
 }
 // --------------------------------------------------------------------------
 
-- 
GitLab