From 21c35d1b9f5e9f82496711baa1359ef013d8c9e3 Mon Sep 17 00:00:00 2001
From: "P.-A. Loizeau" <p.-a.loizeau@gsi.de>
Date: Sat, 11 May 2024 07:46:00 +0200
Subject: [PATCH] Add two analysis tools for online digievent rra files

---
 analysis/CMakeLists.txt                       |   2 +
 analysis/mcbm/CMakeLists.txt                  |  27 ++
 analysis/mcbm/CbmMcbm2024CheckBmonScvd.cxx    | 209 +++++++++++++
 analysis/mcbm/CbmMcbm2024CheckBmonScvd.h      |  83 ++++++
 analysis/mcbm/CbmMcbm2024CheckEventsDt.cxx    | 276 ++++++++++++++++++
 analysis/mcbm/CbmMcbm2024CheckEventsDt.h      |  91 ++++++
 analysis/mcbm/CbmMcbmAnaLinkDef.h             |  10 +
 .../beamtime/mcbm2024/check_bmon_digis_scvd.C |  93 ++++++
 macro/beamtime/mcbm2024/check_events_dt.C     |  93 ++++++
 9 files changed, 884 insertions(+)
 create mode 100644 analysis/mcbm/CMakeLists.txt
 create mode 100644 analysis/mcbm/CbmMcbm2024CheckBmonScvd.cxx
 create mode 100644 analysis/mcbm/CbmMcbm2024CheckBmonScvd.h
 create mode 100644 analysis/mcbm/CbmMcbm2024CheckEventsDt.cxx
 create mode 100644 analysis/mcbm/CbmMcbm2024CheckEventsDt.h
 create mode 100644 analysis/mcbm/CbmMcbmAnaLinkDef.h
 create mode 100644 macro/beamtime/mcbm2024/check_bmon_digis_scvd.C
 create mode 100644 macro/beamtime/mcbm2024/check_events_dt.C

diff --git a/analysis/CMakeLists.txt b/analysis/CMakeLists.txt
index fd38d028ee..7f7fb73eae 100644
--- a/analysis/CMakeLists.txt
+++ b/analysis/CMakeLists.txt
@@ -16,5 +16,7 @@ add_subdirectory (common/at_kfpf_interface)
 
 add_subdirectory (detectors)
 
+add_subdirectory (mcbm)
+
 
 
diff --git a/analysis/mcbm/CMakeLists.txt b/analysis/mcbm/CMakeLists.txt
new file mode 100644
index 0000000000..1635dc3bc1
--- /dev/null
+++ b/analysis/mcbm/CMakeLists.txt
@@ -0,0 +1,27 @@
+set(INCLUDE_DIRECTORIES
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  )
+
+set(SRCS
+  CbmMcbm2024CheckBmonScvd.cxx
+  CbmMcbm2024CheckEventsDt.cxx
+  )
+
+
+set(LIBRARY_NAME CbmMcbmAna)
+set(LINKDEF ${LIBRARY_NAME}LinkDef.h)
+set(PUBLIC_DEPENDENCIES
+  CbmBase
+  CbmData
+  FairRoot::Base
+  ROOT::Core
+  )
+
+set(PRIVATE_DEPENDENCIES
+  FairRoot::ParBase
+  ROOT::Geom
+  ROOT::Hist
+  ROOT::RIO
+  )
+
+generate_cbm_library()
diff --git a/analysis/mcbm/CbmMcbm2024CheckBmonScvd.cxx b/analysis/mcbm/CbmMcbm2024CheckBmonScvd.cxx
new file mode 100644
index 0000000000..82fe30a260
--- /dev/null
+++ b/analysis/mcbm/CbmMcbm2024CheckBmonScvd.cxx
@@ -0,0 +1,209 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pierre-Alain Loizeau [committer] */
+
+
+#include "CbmMcbm2024CheckBmonScvd.h"
+
+#include "CbmDefs.h"
+#include "CbmEvent.h"
+
+#include <FairRootManager.h>
+#include <Logger.h>
+
+#include <TCanvas.h>
+#include <TFile.h>
+#include <TH1.h>
+#include <TH2.h>
+#include <TROOT.h>
+#include <TStopwatch.h>
+
+#include <algorithm>
+#include <cassert>
+#include <iomanip>
+#include <vector>
+
+
+using namespace std;
+
+
+// -----   Constructor   -----------------------------------------------------
+CbmMcbm2024CheckBmonScvd::CbmMcbm2024CheckBmonScvd() : FairTask("MakeRecoEvents") {}
+// ---------------------------------------------------------------------------
+
+
+// -----   Destructor   ------------------------------------------------------
+CbmMcbm2024CheckBmonScvd::~CbmMcbm2024CheckBmonScvd() {}
+// ---------------------------------------------------------------------------
+
+
+// -----   Execution   -------------------------------------------------------
+void CbmMcbm2024CheckBmonScvd::Exec(Option_t*)
+{
+  // --- First TS: find boundaries of plots
+  /// TODO
+  if (0 == fNumTs) {
+    TDirectory* oldDir = gDirectory;
+    TFile* oldFile     = gFile;
+    gROOT->cd();
+
+    fHistMapBmonOld     = new TH1I("histMapBmonOld", "Channel map, old BMON; Strip []", 16, 0., 16.);
+    fHistMapBmonScvd    = new TH2I("histMapBmonScvd", "Pad map, sCVD BMON; Pad X []; Pad Y []",  //
+                                2, 0., 2., 2, 0., 2.);
+    fHistMapEvoBmonOld  = new TH2I("histMapEvoBmonOld", "Pad map, old BMON; TS []; Strip []",  //
+                                  100, 0., 1000., 16, 0., 16.);
+    fHistMapEvoBmonScvd = new TH2I("histMapEvoBmonScvd", "Pad map, sCVD BMON; TS []; Channel []",  //
+                                   100, 0., 1000., 4, 0., 4.);
+
+    fHistDtBmon    = new TH1I("histDtBmon", "Time difference old vs sCVD BMON; dt [ns]", 1000, -500., 500.);
+    fHistDtEvoBmon = new TH2I("histDtEvoBmon", "Evolution Time difference old vs sCVD BMON ; TS []; dt [ns]",  //
+                              100, 0., 1000., 1000, -500., 500.);
+    fHistDtDxBmon  = new TH2I("histDtDxBmon", "X correlation vs Time diff, old vs sCVD BMON; dt [ns]; dX []",  //
+                             1000, -500., 500., 33, -16.5, 16.5);
+    fHistDxCorBmon = new TH2I("histDxCorrBmon", "Pad map, old vs sCVD BMON; Strip []; Column []",  //
+                              16, 0., 16., 2, 0., 2.);
+
+    fCanvMap = new TCanvas("canvMap", "Channel counts mapping for old and sCVD BMON");
+    fCanvMap->Divide(2, 2);
+
+    fCanvMap->cd(1);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistMapBmonOld->Draw("hist");
+
+    fCanvMap->cd(2);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistMapBmonScvd->Draw("ColzText");
+
+    fCanvMap->cd(3);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistMapEvoBmonOld->Draw("colz");
+
+    fCanvMap->cd(4);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistMapEvoBmonScvd->Draw("colz");
+
+    fCanvCorr = new TCanvas("canvCorr", "Correlations (T, X) between old and sCVD BMON");
+    fCanvCorr->Divide(2, 2);
+
+    fCanvCorr->cd(1);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtBmon->Draw("hist");
+
+    fCanvCorr->cd(2);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtEvoBmon->Draw("colz");
+
+    fCanvCorr->cd(3);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtDxBmon->Draw("colz");
+
+    fCanvCorr->cd(4);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDxCorBmon->Draw("colz");
+
+    gFile      = oldFile;
+    gDirectory = oldDir;
+  }
+
+  size_t numEventsInTs = 0;
+  uint8_t ucScvdX[4]   = {1, 1, 0, 0};
+  uint8_t ucScvdY[4]   = {1, 0, 0, 1};
+  for (auto& event : *fEvents) {
+
+    std::vector<CbmBmonDigi> vDigisOld;
+    std::vector<CbmBmonDigi> vDigisScvd;
+    vDigisOld.reserve(event.fData.fBmon.Size());
+    vDigisScvd.reserve(event.fData.fBmon.Size());
+    for (auto& digi : event.fData.fBmon.fDigis) {
+      if (1 == CbmTofAddress::GetChannelSide(digi.GetAddress())) {
+        if (CbmTofAddress::GetChannelId(digi.GetAddress()) < 4) {
+          fHistMapBmonScvd->Fill(ucScvdX[CbmTofAddress::GetChannelId(digi.GetAddress())],
+                                 ucScvdY[CbmTofAddress::GetChannelId(digi.GetAddress())]);
+          fHistMapEvoBmonScvd->Fill(fNumTs, CbmTofAddress::GetChannelId(digi.GetAddress()));
+          vDigisScvd.push_back(digi);
+        }
+        else {
+          LOG(fatal) << "Bad sCVD channel: " << CbmTofAddress::GetChannelId(digi.GetAddress());
+        }
+      }
+      else {
+        fHistMapBmonOld->Fill(CbmTofAddress::GetChannelId(digi.GetAddress()));
+        fHistMapEvoBmonOld->Fill(fNumTs, CbmTofAddress::GetChannelId(digi.GetAddress()));
+        vDigisOld.push_back(digi);
+      }
+    }
+
+    for (auto& digiOld : vDigisOld) {
+      for (auto& digiScvd : vDigisScvd) {
+        double_t dDt = digiScvd.GetTime() - digiOld.GetTime();
+        fHistDtBmon->Fill(dDt);
+        fHistDtEvoBmon->Fill(fNumTs, dDt);
+        fHistDtDxBmon->Fill(dDt, 16 * ucScvdX[CbmTofAddress::GetChannelId(digiScvd.GetAddress())]
+                                   - CbmTofAddress::GetChannelId(digiOld.GetAddress()));
+        fHistDxCorBmon->Fill(CbmTofAddress::GetChannelId(digiOld.GetAddress()),
+                             ucScvdX[CbmTofAddress::GetChannelId(digiScvd.GetAddress())]);
+      }
+    }
+
+    numEventsInTs++;
+  }
+
+  // --- Run statistics
+  fNumTs++;
+  fNumEvents += fEvents->size();
+}
+// ----------------------------------------------------------------------------
+
+
+// -----   End-of-timeslice action   ------------------------------------------
+void CbmMcbm2024CheckBmonScvd::Finish()
+{
+  LOG(info) << "=====================================";
+  LOG(info) << GetName() << ": Run summary";
+  LOG(info) << "Timeslices : " << fNumTs;
+  LOG(info) << "Events     : " << fNumEvents;
+  LOG(info) << "=====================================";
+}
+// ----------------------------------------------------------------------------
+
+
+// -----   Initialisation   ---------------------------------------------------
+InitStatus CbmMcbm2024CheckBmonScvd::Init()
+{
+  // --- Get FairRootManager instance
+  FairRootManager* ioman = FairRootManager::Instance();
+  assert(ioman);
+
+  LOG(info) << "==================================================";
+  LOG(info) << GetName() << ": Initialising...";
+
+  // --- Input data
+  fEvents = ioman->InitObjectAs<const std::vector<CbmDigiEvent>*>("DigiEvent");
+  if (!fEvents) {
+    LOG(error) << GetName() << ": No input branch DigiEvent!";
+    return kFATAL;
+  }
+  LOG(info) << "--- Found branch DigiEvent at " << fEvents;
+
+  LOG(info) << "==================================================";
+  return kSUCCESS;
+}
+// ----------------------------------------------------------------------------
+
+ClassImp(CbmMcbm2024CheckBmonScvd)
diff --git a/analysis/mcbm/CbmMcbm2024CheckBmonScvd.h b/analysis/mcbm/CbmMcbm2024CheckBmonScvd.h
new file mode 100644
index 0000000000..cb628d988e
--- /dev/null
+++ b/analysis/mcbm/CbmMcbm2024CheckBmonScvd.h
@@ -0,0 +1,83 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pierre-Alain Loizeau [committer] */
+
+
+#ifndef CBMMCBM2024CHECKBMONSCVD_H
+#define CBMMCBM2024CHECKBMONSCVD_H 1
+
+
+#include "CbmDefs.h"
+#include "CbmDigiEvent.h"
+#include "CbmEvent.h"
+
+#include <FairTask.h>
+
+#include <gsl/span>
+#include <vector>
+
+class TCanvas;
+class TH1;
+class TH2;
+
+/** @class CbmMcbm2024CheckBmonScvd
+ ** @brief Create and fills plots of time differences to trigger in DigiEvents
+ **
+ ** Creates for each detector system two histograms, one for the time difference of each digi in DigiEvents to the event
+ ** seed time and another for the same quantity as function of TS index (~time evolution).
+ ** Fills these plots for each DigiEvent.
+ **/
+class CbmMcbm2024CheckBmonScvd : public FairTask {
+
+
+ public:
+  /** @brief Constructor **/
+  CbmMcbm2024CheckBmonScvd();
+
+
+  /** @brief Copy constructor (disabled) **/
+  CbmMcbm2024CheckBmonScvd(const CbmMcbm2024CheckBmonScvd&) = delete;
+
+
+  /** @brief Destructor **/
+  virtual ~CbmMcbm2024CheckBmonScvd();
+
+
+  /** @brief Task execution **/
+  virtual void Exec(Option_t* opt);
+
+
+  /** @brief Finish timeslice **/
+  virtual void Finish();
+
+
+  /** @brief Assignment operator (disabled) **/
+  CbmMcbm2024CheckBmonScvd& operator=(const CbmMcbm2024CheckBmonScvd&) = delete;
+
+
+ private:  // methods
+  /** @brief Task initialisation **/
+  virtual InitStatus Init();
+
+ private:                                              // members
+  const std::vector<CbmDigiEvent>* fEvents = nullptr;  //! Input data (events)
+  size_t fNumTs                            = 0;        ///< Number of processed timeslices
+  size_t fNumEvents                        = 0;        ///< Number of events
+
+  TH1* fHistMapBmonOld     = nullptr;
+  TH2* fHistMapBmonScvd    = nullptr;
+  TH2* fHistMapEvoBmonOld  = nullptr;
+  TH2* fHistMapEvoBmonScvd = nullptr;
+
+  TH1* fHistDtBmon    = nullptr;
+  TH2* fHistDtEvoBmon = nullptr;
+  TH2* fHistDtDxBmon  = nullptr;
+  TH2* fHistDxCorBmon = nullptr;
+
+  TCanvas* fCanvMap  = nullptr;
+  TCanvas* fCanvCorr = nullptr;
+
+  ClassDef(CbmMcbm2024CheckBmonScvd, 1);
+};
+
+#endif /* CBMMCBM2024CHECKBMONSCVD_H */
diff --git a/analysis/mcbm/CbmMcbm2024CheckEventsDt.cxx b/analysis/mcbm/CbmMcbm2024CheckEventsDt.cxx
new file mode 100644
index 0000000000..3a877667ab
--- /dev/null
+++ b/analysis/mcbm/CbmMcbm2024CheckEventsDt.cxx
@@ -0,0 +1,276 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pierre-Alain Loizeau [committer] */
+
+
+#include "CbmMcbm2024CheckEventsDt.h"
+
+#include "CbmDefs.h"
+#include "CbmEvent.h"
+
+#include <FairRootManager.h>
+#include <Logger.h>
+
+#include <TCanvas.h>
+#include <TFile.h>
+#include <TH1.h>
+#include <TH2.h>
+#include <TROOT.h>
+#include <TStopwatch.h>
+
+#include <algorithm>
+#include <cassert>
+#include <iomanip>
+#include <vector>
+
+
+using namespace std;
+
+
+// -----   Constructor   -----------------------------------------------------
+CbmMcbm2024CheckEventsDt::CbmMcbm2024CheckEventsDt() : FairTask("MakeRecoEvents") {}
+// ---------------------------------------------------------------------------
+
+
+// -----   Destructor   ------------------------------------------------------
+CbmMcbm2024CheckEventsDt::~CbmMcbm2024CheckEventsDt() {}
+// ---------------------------------------------------------------------------
+
+
+// -----   Execution   -------------------------------------------------------
+void CbmMcbm2024CheckEventsDt::Exec(Option_t*)
+{
+  // --- First TS: find boundaries of plots
+  /// TODO
+  if (0 == fNumTs) {
+    TDirectory* oldDir = gDirectory;
+    TFile* oldFile     = gFile;
+    gROOT->cd();
+    fHistDtBmon  = new TH1I("histDtBmon", "Time difference to event seed, BMON; dt [ns]", 1000, -500., 500.);
+    fHistDtSts   = new TH1I("histDtSts", "Time difference to event seed, STS; dt [ns]", 1000, -500., 500.);
+    fHistDtMuch  = new TH1I("histDtMuch", "Time difference to event seed, MUCH; dt [ns]", 1000, -500., 500.);
+    fHistDtTrd1d = new TH1I("histDtTrd1d", "Time difference to event seed, TRD1D; dt [ns]", 1000, -500., 500.);
+    fHistDtTrd2d = new TH1I("histDtTrd2d", "Time difference to event seed, TRD2D; dt [ns]", 1000, -500., 500.);
+    fHistDtTof   = new TH1I("histDtTof", "Time difference to event seed, TOF; dt [ns]", 1000, -500., 500.);
+    fHistDtRich  = new TH1I("histDtRich", "Time difference to event seed, RICH; dt [ns]", 1000, -500., 500.);
+    fHistDtFsd   = new TH1I("histDtFsd", "Time difference to event seed, FSD; dt [ns]", 1000, -500., 500.);
+
+    fHistDtEvoBmon  = new TH2I("histDtEvoBmon", "Time difference to event seed vs TS, BMON; TS []; dt [ns]",  //
+                              100, 0., 1000., 1000, -500., 500.);
+    fHistDtEvoSts   = new TH2I("histDtEvoSts", "Time difference to event seed vs TS, STS; TS []; dt [ns]",  //
+                             100, 0., 1000., 1000, -500., 500.);
+    fHistDtEvoMuch  = new TH2I("histDtEvoMuch", "Time difference to event seed vs TS, MUCH; TS []; dt [ns",  //
+                              100, 0., 1000., 1000, -500., 500.);
+    fHistDtEvoTrd1d = new TH2I("histDtEvoTrd1d", "Time difference to event seed vs TS, TRD1D; TS []; dt [ns]",  //
+                               100, 0., 1000., 1000, -500., 500.);
+    fHistDtEvoTrd2d = new TH2I("histDtEvoTrd2d", "Time difference to event seed vs TS, TRD2D; TS []; dt [ns]",  //
+                               100, 0., 1000., 1000, -500., 500.);
+    fHistDtEvoTof   = new TH2I("histDtEvoTof", "Time difference to event seed vs TS, TOF; TS []; dt [ns]",  //
+                             100, 0., 1000., 1000, -500., 500.);
+    fHistDtEvoRich  = new TH2I("histDtEvoRich", "Time difference to event seed vs TS, RICH; TS []; dt [ns]",  //
+                              100, 0., 1000., 1000, -500., 500.);
+    fHistDtEvoFsd   = new TH2I("histDtEvoFsd", "Time difference to event seedvs TS, FSD; TS []; dt [ns]",  //
+                             100, 0., 1000., 1000, -500., 500.);
+
+    fCanvDt = new TCanvas("canvDt", "Time differences to event seed");
+    fCanvDt->Divide(3, 3);
+
+    fCanvDt->cd(1);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtBmon->Draw("hist");
+
+    fCanvDt->cd(2);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtSts->Draw("hist");
+
+    fCanvDt->cd(3);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtMuch->Draw("hist");
+
+    fCanvDt->cd(4);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtTrd1d->Draw("hist");
+
+    fCanvDt->cd(5);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtTrd2d->Draw("hist");
+
+    fCanvDt->cd(6);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtTof->Draw("hist");
+
+    fCanvDt->cd(7);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtRich->Draw("hist");
+
+    fCanvDt->cd(8);
+    gPad->SetLogy();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtFsd->Draw("hist");
+
+    fCanvDtEvo = new TCanvas("canvDtEvo", "Time differences to event seed vs TS");
+    fCanvDtEvo->Divide(3, 3);
+
+    fCanvDtEvo->cd(1);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtEvoBmon->Draw("colz");
+
+    fCanvDtEvo->cd(2);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtEvoSts->Draw("colz");
+
+    fCanvDtEvo->cd(3);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtEvoMuch->Draw("colz");
+
+    fCanvDtEvo->cd(4);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtEvoTrd1d->Draw("colz");
+
+    fCanvDtEvo->cd(5);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtEvoTrd2d->Draw("colz");
+
+    fCanvDtEvo->cd(6);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtEvoTof->Draw("colz");
+
+    fCanvDtEvo->cd(7);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtEvoRich->Draw("colz");
+
+    fCanvDtEvo->cd(8);
+    gPad->SetLogz();
+    gPad->SetGridx();
+    gPad->SetGridy();
+    fHistDtEvoFsd->Draw("colz");
+
+    gFile      = oldFile;
+    gDirectory = oldDir;
+  }
+
+  size_t numEventsInTs = 0;
+  for (auto& event : *fEvents) {
+
+    for (auto& digi : event.fData.fBmon.fDigis) {
+      double_t dDt = digi.GetTime() - event.fTime;
+      fHistDtBmon->Fill(dDt);
+      fHistDtEvoBmon->Fill(fNumTs, dDt);
+    }
+
+    for (auto& digi : event.fData.fSts.fDigis) {
+      double_t dDt = digi.GetTime() - event.fTime;
+      fHistDtSts->Fill(dDt);
+      fHistDtEvoSts->Fill(fNumTs, dDt);
+    }
+
+    for (auto& digi : event.fData.fMuch.fDigis) {
+      double_t dDt = digi.GetTime() - event.fTime;
+      fHistDtMuch->Fill(dDt);
+      fHistDtEvoMuch->Fill(fNumTs, dDt);
+    }
+
+    for (auto& digi : event.fData.fTrd.fDigis) {
+      double_t dDt = digi.GetTime() - event.fTime;
+      fHistDtTrd1d->Fill(dDt);
+      fHistDtEvoTrd1d->Fill(fNumTs, dDt);
+    }
+
+    for (auto& digi : event.fData.fTrd2d.fDigis) {
+      double_t dDt = digi.GetTime() - event.fTime;
+      fHistDtTrd2d->Fill(dDt);
+      fHistDtEvoTrd2d->Fill(fNumTs, dDt);
+    }
+
+    for (auto& digi : event.fData.fTof.fDigis) {
+      double_t dDt = digi.GetTime() - event.fTime;
+      fHistDtTof->Fill(dDt);
+      fHistDtEvoTof->Fill(fNumTs, dDt);
+    }
+
+    for (auto& digi : event.fData.fRich.fDigis) {
+      double_t dDt = digi.GetTime() - event.fTime;
+      fHistDtRich->Fill(dDt);
+      fHistDtEvoRich->Fill(fNumTs, dDt);
+    }
+
+    for (auto& digi : event.fData.fFsd.fDigis) {
+      double_t dDt = digi.GetTime() - event.fTime;
+      fHistDtFsd->Fill(dDt);
+      fHistDtEvoFsd->Fill(fNumTs, dDt);
+    }
+    numEventsInTs++;
+  }
+
+  // --- Run statistics
+  fNumTs++;
+  fNumEvents += fEvents->size();
+}
+// ----------------------------------------------------------------------------
+
+
+// -----   End-of-timeslice action   ------------------------------------------
+void CbmMcbm2024CheckEventsDt::Finish()
+{
+  LOG(info) << "=====================================";
+  LOG(info) << GetName() << ": Run summary";
+  LOG(info) << "Timeslices : " << fNumTs;
+  LOG(info) << "Events     : " << fNumEvents;
+  LOG(info) << "=====================================";
+}
+// ----------------------------------------------------------------------------
+
+
+// -----   Initialisation   ---------------------------------------------------
+InitStatus CbmMcbm2024CheckEventsDt::Init()
+{
+  // --- Get FairRootManager instance
+  FairRootManager* ioman = FairRootManager::Instance();
+  assert(ioman);
+
+  LOG(info) << "==================================================";
+  LOG(info) << GetName() << ": Initialising...";
+
+  // --- Input data
+  fEvents = ioman->InitObjectAs<const std::vector<CbmDigiEvent>*>("DigiEvent");
+  if (!fEvents) {
+    LOG(error) << GetName() << ": No input branch DigiEvent!";
+    return kFATAL;
+  }
+  LOG(info) << "--- Found branch DigiEvent at " << fEvents;
+
+  LOG(info) << "==================================================";
+  return kSUCCESS;
+}
+// ----------------------------------------------------------------------------
+
+ClassImp(CbmMcbm2024CheckEventsDt)
diff --git a/analysis/mcbm/CbmMcbm2024CheckEventsDt.h b/analysis/mcbm/CbmMcbm2024CheckEventsDt.h
new file mode 100644
index 0000000000..ac4fdbea5f
--- /dev/null
+++ b/analysis/mcbm/CbmMcbm2024CheckEventsDt.h
@@ -0,0 +1,91 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pierre-Alain Loizeau [committer] */
+
+
+#ifndef CBMMCBM2024CHECKEVENTSDT_H
+#define CBMMCBM2024CHECKEVENTSDT_H 1
+
+
+#include "CbmDefs.h"
+#include "CbmDigiEvent.h"
+#include "CbmEvent.h"
+
+#include <FairTask.h>
+
+#include <gsl/span>
+#include <vector>
+
+class TCanvas;
+class TH1;
+class TH2;
+
+/** @class CbmMcbm2024CheckEventsDt
+ ** @brief Create and fills plots of time differences to trigger in DigiEvents
+ **
+ ** Creates for each detector system two histograms, one for the time difference of each digi in DigiEvents to the event
+ ** seed time and another for the same quantity as function of TS index (~time evolution).
+ ** Fills these plots for each DigiEvent.
+ **/
+class CbmMcbm2024CheckEventsDt : public FairTask {
+
+
+ public:
+  /** @brief Constructor **/
+  CbmMcbm2024CheckEventsDt();
+
+
+  /** @brief Copy constructor (disabled) **/
+  CbmMcbm2024CheckEventsDt(const CbmMcbm2024CheckEventsDt&) = delete;
+
+
+  /** @brief Destructor **/
+  virtual ~CbmMcbm2024CheckEventsDt();
+
+
+  /** @brief Task execution **/
+  virtual void Exec(Option_t* opt);
+
+
+  /** @brief Finish timeslice **/
+  virtual void Finish();
+
+
+  /** @brief Assignment operator (disabled) **/
+  CbmMcbm2024CheckEventsDt& operator=(const CbmMcbm2024CheckEventsDt&) = delete;
+
+
+ private:  // methods
+  /** @brief Task initialisation **/
+  virtual InitStatus Init();
+
+ private:                                              // members
+  const std::vector<CbmDigiEvent>* fEvents = nullptr;  //! Input data (events)
+  size_t fNumTs                            = 0;        ///< Number of processed timeslices
+  size_t fNumEvents                        = 0;        ///< Number of events
+
+  TH1* fHistDtBmon  = nullptr;
+  TH1* fHistDtSts   = nullptr;
+  TH1* fHistDtMuch  = nullptr;
+  TH1* fHistDtTrd1d = nullptr;
+  TH1* fHistDtTrd2d = nullptr;
+  TH1* fHistDtTof   = nullptr;
+  TH1* fHistDtRich  = nullptr;
+  TH1* fHistDtFsd   = nullptr;
+
+  TH2* fHistDtEvoBmon  = nullptr;
+  TH2* fHistDtEvoSts   = nullptr;
+  TH2* fHistDtEvoMuch  = nullptr;
+  TH2* fHistDtEvoTrd1d = nullptr;
+  TH2* fHistDtEvoTrd2d = nullptr;
+  TH2* fHistDtEvoTof   = nullptr;
+  TH2* fHistDtEvoRich  = nullptr;
+  TH2* fHistDtEvoFsd   = nullptr;
+
+  TCanvas* fCanvDt    = nullptr;
+  TCanvas* fCanvDtEvo = nullptr;
+
+  ClassDef(CbmMcbm2024CheckEventsDt, 1);
+};
+
+#endif /* CBMMCBM2024CHECKEVENTSDT_H */
diff --git a/analysis/mcbm/CbmMcbmAnaLinkDef.h b/analysis/mcbm/CbmMcbmAnaLinkDef.h
new file mode 100644
index 0000000000..aeefb0a6da
--- /dev/null
+++ b/analysis/mcbm/CbmMcbmAnaLinkDef.h
@@ -0,0 +1,10 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pierre-Alain Loizeau [committer] */
+
+#ifdef __CINT__
+
+#pragma link C++ class CbmMcbm2024CheckBmonScvd + ;
+#pragma link C++ class CbmMcbm2024CheckEventsDt + ;
+
+#endif
diff --git a/macro/beamtime/mcbm2024/check_bmon_digis_scvd.C b/macro/beamtime/mcbm2024/check_bmon_digis_scvd.C
new file mode 100644
index 0000000000..caa738430a
--- /dev/null
+++ b/macro/beamtime/mcbm2024/check_bmon_digis_scvd.C
@@ -0,0 +1,93 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pierre-Alain Loizeau [committer] */
+
+/** @brief Macro for check of sCVD BMON digis in DigiEvents
+ ** @param input          Name of input file
+ ** @param output         Name of output file
+ ** @param nTimeSlices    Number of time-slices to process
+ **/
+void check_bmon_digis_scvd(TString inputFileName, TString outputFileName, size_t numTimeslices = -1)
+{
+
+  // ========================================================================
+  //          Adjust this part according to your requirements
+
+  // --- Logger settings ----------------------------------------------------
+  TString logLevel     = "INFO";
+  TString logVerbosity = "LOW";
+  // ------------------------------------------------------------------------
+
+  // -----   Environment   --------------------------------------------------
+  TString myName = "check_events_dt";              // this macro's name for screen output
+  TString srcDir = gSystem->Getenv("VMCWORKDIR");  // top source directory
+  // ------------------------------------------------------------------------
+
+
+  // -----   Timer   --------------------------------------------------------
+  TStopwatch timer;
+  timer.Start();
+  // ------------------------------------------------------------------------
+
+
+  // -----   FairRunAna   ---------------------------------------------------
+  FairRunOnline* run = new FairRunOnline();
+  FairSource* source = new CbmSourceDigiEvents(inputFileName);
+  run->SetSource(source);
+  auto sink = new FairRootFileSink(outputFileName);
+  run->SetSink(sink);
+  run->SetGenerateRunInfo(kTRUE);
+  // ------------------------------------------------------------------------
+
+
+  // -----   Logger settings   ----------------------------------------------
+  FairLogger::GetLogger()->SetLogScreenLevel(logLevel.Data());
+  FairLogger::GetLogger()->SetLogVerbosityLevel(logVerbosity.Data());
+  // ------------------------------------------------------------------------
+
+
+  // -----   Event inspection   ---------------------------------------------
+  FairTask* inspect = new CbmMcbm2024CheckBmonScvd();
+  LOG(info) << "-I- " << myName << ": Adding task " << inspect->GetName();
+  run->AddTask(inspect);
+  // ------------------------------------------------------------------------
+
+
+  // -----   Run initialisation   -------------------------------------------
+  std::cout << std::endl;
+  std::cout << "-I- " << myName << ": Initialise run" << std::endl;
+  run->Init();
+  // ------------------------------------------------------------------------
+
+
+  // -----   Start run   ----------------------------------------------------
+  std::cout << std::endl << std::endl;
+  std::cout << "-I- " << myName << ": Starting run" << std::endl;
+  if (numTimeslices == -1)
+    run->Run(-1, 0);
+  else
+    run->Run(0, numTimeslices);
+  // ------------------------------------------------------------------------
+
+
+  // -----   Finish   -------------------------------------------------------
+  timer.Stop();
+  FairMonitor::GetMonitor()->Print();
+  Double_t rtime = timer.RealTime();
+  Double_t ctime = timer.CpuTime();
+  std::cout << std::endl << std::endl;
+  std::cout << "Macro finished successfully." << std::endl;
+  std::cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << std::endl;
+  FairSystemInfo sysInfo;
+  Float_t maxMemory = sysInfo.GetMaxMemory();
+  std::cout << "<DartMeasurement name=\"MaxMemory\" type=\"numeric/double\">";
+  std::cout << maxMemory;
+  std::cout << "</DartMeasurement>" << std::endl;
+  Float_t cpuUsage = ctime / rtime;
+  std::cout << "<DartMeasurement name=\"CpuLoad\" type=\"numeric/double\">";
+  std::cout << cpuUsage;
+  std::cout << "</DartMeasurement>" << std::endl;
+  // ------------------------------------------------------------------------
+
+
+}  // End of main macro function
diff --git a/macro/beamtime/mcbm2024/check_events_dt.C b/macro/beamtime/mcbm2024/check_events_dt.C
new file mode 100644
index 0000000000..cb5c957e28
--- /dev/null
+++ b/macro/beamtime/mcbm2024/check_events_dt.C
@@ -0,0 +1,93 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pierre-Alain Loizeau [committer] */
+
+/** @brief Macro for check of time differences in DigiEvents
+ ** @param input          Name of input file
+ ** @param output         Name of output file
+ ** @param nTimeSlices    Number of time-slices to process
+ **/
+void check_events_dt(TString inputFileName, TString outputFileName, size_t numTimeslices = -1)
+{
+
+  // ========================================================================
+  //          Adjust this part according to your requirements
+
+  // --- Logger settings ----------------------------------------------------
+  TString logLevel     = "INFO";
+  TString logVerbosity = "LOW";
+  // ------------------------------------------------------------------------
+
+  // -----   Environment   --------------------------------------------------
+  TString myName = "check_events_dt";              // this macro's name for screen output
+  TString srcDir = gSystem->Getenv("VMCWORKDIR");  // top source directory
+  // ------------------------------------------------------------------------
+
+
+  // -----   Timer   --------------------------------------------------------
+  TStopwatch timer;
+  timer.Start();
+  // ------------------------------------------------------------------------
+
+
+  // -----   FairRunAna   ---------------------------------------------------
+  FairRunOnline* run = new FairRunOnline();
+  FairSource* source = new CbmSourceDigiEvents(inputFileName);
+  run->SetSource(source);
+  auto sink = new FairRootFileSink(outputFileName);
+  run->SetSink(sink);
+  run->SetGenerateRunInfo(kTRUE);
+  // ------------------------------------------------------------------------
+
+
+  // -----   Logger settings   ----------------------------------------------
+  FairLogger::GetLogger()->SetLogScreenLevel(logLevel.Data());
+  FairLogger::GetLogger()->SetLogVerbosityLevel(logVerbosity.Data());
+  // ------------------------------------------------------------------------
+
+
+  // -----   Event inspection   ---------------------------------------------
+  FairTask* inspect = new CbmMcbm2024CheckEventsDt();
+  LOG(info) << "-I- " << myName << ": Adding task " << inspect->GetName();
+  run->AddTask(inspect);
+  // ------------------------------------------------------------------------
+
+
+  // -----   Run initialisation   -------------------------------------------
+  std::cout << std::endl;
+  std::cout << "-I- " << myName << ": Initialise run" << std::endl;
+  run->Init();
+  // ------------------------------------------------------------------------
+
+
+  // -----   Start run   ----------------------------------------------------
+  std::cout << std::endl << std::endl;
+  std::cout << "-I- " << myName << ": Starting run" << std::endl;
+  if (numTimeslices == -1)
+    run->Run(-1, 0);
+  else
+    run->Run(0, numTimeslices);
+  // ------------------------------------------------------------------------
+
+
+  // -----   Finish   -------------------------------------------------------
+  timer.Stop();
+  FairMonitor::GetMonitor()->Print();
+  Double_t rtime = timer.RealTime();
+  Double_t ctime = timer.CpuTime();
+  std::cout << std::endl << std::endl;
+  std::cout << "Macro finished successfully." << std::endl;
+  std::cout << "Real time " << rtime << " s, CPU time " << ctime << " s" << std::endl;
+  FairSystemInfo sysInfo;
+  Float_t maxMemory = sysInfo.GetMaxMemory();
+  std::cout << "<DartMeasurement name=\"MaxMemory\" type=\"numeric/double\">";
+  std::cout << maxMemory;
+  std::cout << "</DartMeasurement>" << std::endl;
+  Float_t cpuUsage = ctime / rtime;
+  std::cout << "<DartMeasurement name=\"CpuLoad\" type=\"numeric/double\">";
+  std::cout << cpuUsage;
+  std::cout << "</DartMeasurement>" << std::endl;
+  // ------------------------------------------------------------------------
+
+
+}  // End of main macro function
-- 
GitLab