From fb963b56cb893b6b8e355e29c5e73128e5e332ff Mon Sep 17 00:00:00 2001
From: P-A Loizeau <p.-a.loizeau@gsi.de>
Date: Thu, 7 Sep 2023 17:09:46 +0200
Subject: [PATCH] Add BMon Microspill monitor mode to TOF unpack Monitor

- Add optional pick starting decade and starting 0 in GenerateLogBinArray histo tool
- Reduce logs from TS source and Unpack task
---
 .../utils/flestools/CbmFlesHistosTools.cxx    |  14 +-
 .../base/utils/flestools/CbmFlesHistosTools.h |   2 +-
 .../mcbm2022/monitor_bmon_microspills.C       | 279 +++++++
 macro/run/run_unpack_online_bmon.C            |   2 +-
 macro/run/run_unpack_tsa_bmon.C               |   2 +-
 .../detectors/tof/unpack/CbmTofUnpackAlgo.cxx |   7 +-
 .../tof/unpack/CbmTofUnpackMonitor.cxx        | 789 ++++++++++++------
 .../tof/unpack/CbmTofUnpackMonitor.h          |  43 +-
 reco/steer/CbmRecoUnpack.cxx                  |   9 +-
 reco/steer/CbmSourceTsArchive.cxx             |   4 +-
 reco/steer/CbmSourceTsArchive.h               |  14 +-
 11 files changed, 886 insertions(+), 279 deletions(-)
 create mode 100644 macro/beamtime/mcbm2022/monitor_bmon_microspills.C

diff --git a/core/base/utils/flestools/CbmFlesHistosTools.cxx b/core/base/utils/flestools/CbmFlesHistosTools.cxx
index d2af075b21..5f069a96fb 100644
--- a/core/base/utils/flestools/CbmFlesHistosTools.cxx
+++ b/core/base/utils/flestools/CbmFlesHistosTools.cxx
@@ -8,7 +8,7 @@
 //#include <vector>
 
 std::vector<double> GenerateLogBinArray(uint32_t uNbDecadesLog, uint32_t uNbStepsDecade, uint32_t uNbSubStepsInStep,
-                                        uint32_t& uNbBinsLog)
+                                        uint32_t& uNbBinsLog, int32_t iStartExp, bool bAddZeroStart)
 {
   /// Logarithmic bining for self time comparison
   /// Number of log bins =
@@ -22,13 +22,13 @@ std::vector<double> GenerateLogBinArray(uint32_t uNbDecadesLog, uint32_t uNbStep
   double dBinsLog[uArrayLength];
   /// First fill sub-unit decade
   for (uint32_t uSubU = 0; uSubU < uNbStepsDecade; uSubU++) {
-    dBinsLog[uSubU] = 0.1 * (1 + uSubU);
+    dBinsLog[uSubU] = std::pow(10, iStartExp - 1) * (1 + uSubU);
   }
 
   /// Then fill the main decades
   double dSubstepSize = 1.0 / uNbSubStepsInStep;
   for (uint32_t uDecade = 0; uDecade < uNbDecadesLog; uDecade++) {
-    double dBase        = std::pow(10, uDecade);
+    double dBase        = std::pow(10, iStartExp + static_cast<int32_t>(uDecade));
     uint32_t uDecadeIdx = uNbStepsDecade + uDecade * uNbStepsDecade * uNbSubStepsInStep;
     for (uint32_t uStep = 0; uStep < uNbStepsDecade; uStep++) {
       uint32_t uStepIdx = uDecadeIdx + uStep * uNbSubStepsInStep;
@@ -37,11 +37,17 @@ std::vector<double> GenerateLogBinArray(uint32_t uNbDecadesLog, uint32_t uNbStep
       }  // for( uint32_t uSubStep = 0; uSubStep < uNbSubStepsInStep; uSubStep++ )
     }    // for( uint32_t uStep = 0; uStep < uNbStepsDecade; uStep++ )
   }      // for( uint32_t uDecade = 0; uDecade < uNbDecadesLog; uDecade ++)
-  dBinsLog[uNbBinsLog] = std::pow(10, uNbDecadesLog);
+  dBinsLog[uNbBinsLog] = std::pow(10, iStartExp + uNbDecadesLog);
 
   /// use vector instead
   std::vector<double> dBinsLogVect;
 
+  ///    + 1 optional if bin [ 0; Min [ should be added
+  if (bAddZeroStart) {
+    uNbBinsLog++;
+    dBinsLogVect.push_back(0);
+  }
+
   for (uint32_t i = 0; i < uArrayLength; ++i) {
     dBinsLogVect.push_back(dBinsLog[i]);
   }  // for( uint32_t i = 0; i < uArrayLength; ++i )
diff --git a/core/base/utils/flestools/CbmFlesHistosTools.h b/core/base/utils/flestools/CbmFlesHistosTools.h
index d25d0c6e99..c9064298d3 100644
--- a/core/base/utils/flestools/CbmFlesHistosTools.h
+++ b/core/base/utils/flestools/CbmFlesHistosTools.h
@@ -17,7 +17,7 @@
 
 /**********************************************************************/
 std::vector<double> GenerateLogBinArray(uint32_t uNbDecadesLog, uint32_t uNbStepsDecade, uint32_t uNbSubStepsInStep,
-                                        uint32_t& uNbBinsLog);
+                                        uint32_t& uNbBinsLog, int32_t iStartExp = 0, bool bAddZeroStart = false);
 /**********************************************************************/
 
 #endif  // CbmFlesHistosTools_H
diff --git a/macro/beamtime/mcbm2022/monitor_bmon_microspills.C b/macro/beamtime/mcbm2022/monitor_bmon_microspills.C
new file mode 100644
index 0000000000..f0fb0e51fc
--- /dev/null
+++ b/macro/beamtime/mcbm2022/monitor_bmon_microspills.C
@@ -0,0 +1,279 @@
+/* Copyright (C) 2022 Facility for Antiproton and Ion Research in Europe, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pierre-Alain Loizeau [committer]  */
+
+/** @file run_unpack_tsa.C
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @since May 2021
+ **/
+
+
+// --- Includes needed for IDE
+#include <RtypesCore.h>
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+#if !defined(__CLING__)
+#include <FairLogger.h>
+#include <FairRootFileSink.h>
+#include <FairRunOnline.h>
+#include <Logger.h>
+
+#include <TStopwatch.h>
+#include <TSystem.h>
+#endif
+
+std::shared_ptr<CbmTofUnpackMonitor> GetTofMonitor(std::string treefilename, bool bBmonMode = false);
+std::string defaultSetupName = "mcbm_beam_2021_07_surveyed";
+
+void monitor_bmon_microspills(std::vector<std::string> inputurl, UInt_t runid = 0, std::int32_t nevents = -1,
+                              Int_t serverHttpPort = 8090, Int_t serverRefreshRate = 1,
+                              std::string setupName = defaultSetupName, std::string outpath = "data/")
+{
+
+  // ========================================================================
+  //          Adjust this part according to your requirements
+
+  // --- Logger settings ----------------------------------------------------
+  TString logLevel     = "INFO";
+  TString logVerbosity = "LOW";
+  // ------------------------------------------------------------------------
+
+  // -----   Environment   --------------------------------------------------
+  TString myName = "monitor_bmon_microspills";     // this macro's name for screen output
+  TString srcDir = gSystem->Getenv("VMCWORKDIR");  // top source directory
+  // ------------------------------------------------------------------------
+
+  // -----   Output filename   ----------------------------------------------
+  std::string filename    = Form("online_%05d.digi.root", runid);
+  std::string outfilename = outpath + filename;
+  if (inputurl[0].npos == inputurl[0].find("tcp://")) {
+    outfilename      = inputurl[0];
+    auto filenamepos = inputurl[0].find_last_of("/");
+    if (inputurl[0].npos != filenamepos) {
+      filenamepos++;
+    }
+    else {
+      filenamepos = 0;
+    }
+    filename = inputurl[0].substr(filenamepos);
+    if (filename.find("*") != inputurl[0].npos) filename = std::to_string(runid) + ".tsa";
+    if (filename.find(";") != inputurl[0].npos) filename = std::to_string(runid) + "_merged" + ".tsa";
+    filename.replace(filename.find(".tsa"), 4, ".digi.root");
+    if (outpath.empty()) {
+      auto multi_delim = inputurl[0].find_last_of(";");
+      if (inputurl[0].npos != multi_delim) {
+        multi_delim++;
+      }
+      else {
+        multi_delim = 0;
+      }
+      outpath = inputurl[0].substr(multi_delim, filenamepos - multi_delim);
+    }
+    outfilename = outpath + filename;
+  }
+  std::cout << "-I- " << myName << ": Output file will be " << outfilename << std::endl;
+  // ------------------------------------------------------------------------
+
+
+  // -----   Performance profiling   ----------------------------------------
+  // Set to true if you want some minimal performance profiling output
+  bool doPerfProfiling = true;
+  // Define if you want a special path and name for the performance profiling output file
+  std::string perfProfFileName = outpath + filename;
+  perfProfFileName.replace(perfProfFileName.find(".digi.root"), 10, ".perf.root");
+  // ------------------------------------------------------------------------
+
+
+  // -----   CbmSetup   -----------------------------------------------------
+  /// Do automatic mapping only if not overridden by user or empty
+  if (defaultSetupName == setupName || "" == setupName) {
+    cbm::mcbm::ToForceLibLoad dummy;  /// Needed to trigger loading of the library as no fct dict in ROOT6 and CLING
+    try {
+      setupName = cbm::mcbm::GetSetupFromRunId(runid);
+    }
+    catch (const std::invalid_argument& e) {
+      std::cout << "Error in mapping from runID to setup name: " << e.what() << std::endl;
+      return;
+    }
+    if (defaultSetupName != setupName) {
+      std::cout << "Automatic setup choice for run " << runid << ": " << setupName << std::endl;
+    }
+  }
+  auto cbmsetup = CbmSetup::Instance();
+  cbmsetup->LoadSetup(setupName.c_str());
+  // ------------------------------------------------------------------------
+
+  // -----   UnpackerConfigs   ----------------------------------------------
+
+  // ---- BMON ----
+  std::shared_ptr<CbmBmonUnpackConfig> bmonconfig = nullptr;
+
+  bmonconfig = std::make_shared<CbmBmonUnpackConfig>("", runid);
+  if (bmonconfig) {
+    // bmonconfig->SetDebugState();
+    // bmonconfig->SetDoWriteOutput();
+    // bmonconfig->SetDoWriteOptOutA("CbmBmonErrors");
+    std::string parfilesbasepathBmon = Form("%s/macro/beamtime/mcbm2022/", srcDir.Data());
+    bmonconfig->SetParFilesBasePath(parfilesbasepathBmon);
+    bmonconfig->SetParFileName("mBmonCriPar.par");
+    bmonconfig->SetSystemTimeOffset(-1220);  // [ns] value to be updated
+    if (2160 <= runid) {
+      bmonconfig->SetSystemTimeOffset(-80);  // [ns] value to be updated
+    }
+    if (2350 <= runid) {
+      bmonconfig->SetSystemTimeOffset(0);  // [ns] value to be updated
+    }
+    /// Enable Monitor plots
+    bmonconfig->SetMonitor(GetTofMonitor(outfilename, true));
+    if (2337 <= runid) {
+      bmonconfig->GetMonitor()->SetSpillThreshold(250);
+      bmonconfig->GetMonitor()->SetSpillThresholdNonPulser(100);
+    }
+  }
+  // -------------
+
+
+  // ------------------------------------------------------------------------
+
+  // In general, the following parts need not be touched
+  // ========================================================================
+
+  // -----   Timer   --------------------------------------------------------
+  TStopwatch timer;
+  timer.Start();
+  // ------------------------------------------------------------------------
+
+  // -----   CbmSourceTsArchive   -------------------------------------------
+  std::unique_ptr<CbmSourceTsArchive> source = std::unique_ptr<CbmSourceTsArchive>(new CbmSourceTsArchive(inputurl));
+  //source->SetDebugPrintout();
+  auto unpack = source->GetRecoUnpack();
+  //unpack->SetDoPerfProfiling(doPerfProfiling);
+  //unpack->SetOutputFilename(perfProfFileName);
+  // Enable full time sorting instead sorting per FLIM link
+  //unpack->SetTimeSorting(true);
+  unpack->SetMonitoringOnly(true);
+
+  if (bmonconfig) unpack->SetUnpackConfig(bmonconfig);
+  // ------------------------------------------------------------------------
+
+  // -----   FairRunAna   ---------------------------------------------------
+  auto run  = new FairRunOnline(source.get());
+  auto sink = new FairRootFileSink(outfilename.data());
+  run->SetSink(sink);
+  auto eventheader = new CbmTsEventHeader();
+  run->SetRunId(runid);
+  run->SetEventHeader(eventheader);
+  // ------------------------------------------------------------------------
+
+
+  // -----   HttpServer for online monitoring   -----------------------------
+  run->ActivateHttpServer(serverRefreshRate, serverHttpPort);
+  run->GetHttpServer()->GetSniffer()->SetScanGlobalDir(kFALSE);
+  //run->SetAutoFinish(kFALSE);
+  // ------------------------------------------------------------------------
+
+
+  // -----   Logger settings   ----------------------------------------------
+  FairLogger::GetLogger()->SetLogScreenLevel(logLevel.Data());
+  FairLogger::GetLogger()->SetLogVerbosityLevel(logVerbosity.Data());
+  // ------------------------------------------------------------------------
+
+
+  // -----   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 (nevents < 0) {
+    std::cout << "-I- " << myName << ": running until end of file" << std::endl;
+    run->Run(-1, 0);
+  }
+  else {
+    std::cout << "-I- " << myName << ": running for " << nevents << " timeslices " << std::endl;
+    run->Run(0, nevents);
+  }
+  // ------------------------------------------------------------------------
+
+
+  // -----   Finish   -------------------------------------------------------
+  timer.Stop();
+  std::cout << "Macro finished successfully." << std::endl;
+  std::cout << "After CpuTime = " << timer.CpuTime() << " s RealTime = " << timer.RealTime() << " s." << std::endl;
+  // ------------------------------------------------------------------------
+
+  // --   Release all shared pointers to config before ROOT destroys things -
+  // => We need to destroy things by hand because run->Finish calls (through the FairRootManager) Source->Close which
+  //    does call the Source destructor, so due to share pointer things stay alive until out of macro scope...
+  run->SetSource(nullptr);
+  delete run;
+
+  bmonconfig.reset();
+  // ------------------------------------------------------------------------
+
+}  // End of main macro function
+
+
+/**
+ * @brief Get the Tof Monitor. Extra function to keep default macro part more silent.
+ * @return std::shared_ptr<CbmTofUnpackMonitor>
+*/
+std::shared_ptr<CbmTofUnpackMonitor> GetTofMonitor(std::string treefilename, bool bBmonMode = false)
+{
+  // -----   Output filename and path   -------------------------------------
+  std::string outpath  = "";
+  std::string filename = "";
+  auto filenamepos     = treefilename.find_last_of("/");
+  if (filenamepos != treefilename.npos) {
+    outpath  = treefilename.substr(0, filenamepos);
+    filename = treefilename.substr(filenamepos++);
+  }
+  if (outpath.empty()) outpath = gSystem->GetWorkingDirectory();
+  //std::string mydir = "/qa";
+  //outpath += mydir;
+
+  auto currentdir = gSystem->GetWorkingDirectory();
+
+  if (!gSystem->cd(outpath.data())) {
+    gSystem->MakeDirectory(outpath.data());
+  }
+  else {
+    gSystem->cd(currentdir.data());
+  }
+
+  std::string sSystemType = ".mon.tof.root";
+  if (bBmonMode) {
+    //
+    sSystemType = ".mon.bmon.root";
+  }
+
+  std::string outfilename = outpath + filename;
+  auto filetypepos        = outfilename.find(".digi.root");
+  if (filetypepos != outfilename.npos) {
+    outfilename.replace(filetypepos, 10, sSystemType);
+  }
+  else {
+    outfilename += sSystemType;
+  }
+  // ------------------------------------------------------------------------
+
+  auto monitor = std::make_shared<CbmTofUnpackMonitor>();
+  monitor->SetHistoFileName(outfilename);
+  monitor->SetBmonMicroSpillMode(bBmonMode);
+  return monitor;
+}
+
+void monitor_bmon_microspills(std::string inputurl = "tcp://localhost:5556", UInt_t runid = 0,
+                              std::int32_t nevents = -1, Int_t serverHttpPort = 8090, Int_t serverRefreshRate = 1,
+                              std::string setupName = defaultSetupName, std::string outpath = "data/")
+{
+  std::vector<std::string> vInUrl = {inputurl};
+  return monitor_bmon_microspills(vInUrl, runid, nevents, serverHttpPort, serverRefreshRate, setupName, outpath);
+}
diff --git a/macro/run/run_unpack_online_bmon.C b/macro/run/run_unpack_online_bmon.C
index fdcee3ddee..f453b7057d 100644
--- a/macro/run/run_unpack_online_bmon.C
+++ b/macro/run/run_unpack_online_bmon.C
@@ -28,7 +28,7 @@
 #endif
 
 std::shared_ptr<CbmTofUnpackMonitor> GetTofMonitor(std::string treefilename, bool bBmonMode = false);
-std::string defaultSetupName = "mcbm_beam_2022_03_09_carbon";
+std::string defaultSetupName = "mcbm_beam_2021_07_surveyed";
 
 void run_unpack_online_bmon(std::vector<std::string> publisher = {"tcp://localhost:5556"}, Int_t serverHttpPort = 8080,
                             Int_t serverRefreshRate = 100, std::int32_t nevents = -1, UInt_t runid = 1905,
diff --git a/macro/run/run_unpack_tsa_bmon.C b/macro/run/run_unpack_tsa_bmon.C
index 7da33d24e5..e911a5e413 100644
--- a/macro/run/run_unpack_tsa_bmon.C
+++ b/macro/run/run_unpack_tsa_bmon.C
@@ -26,7 +26,7 @@
 #endif
 
 std::shared_ptr<CbmTofUnpackMonitor> GetTofMonitor(std::string treefilename, bool bBmonMode = false);
-std::string defaultSetupName = "mcbm_beam_2022_03_09_carbon";
+std::string defaultSetupName = "mcbm_beam_2021_07_surveyed";
 
 void run_unpack_tsa_bmon(std::vector<std::string> infile = {"test.tsa"}, UInt_t runid = 0,
                          std::string setupName = defaultSetupName, std::int32_t nevents = -1,
diff --git a/reco/detectors/tof/unpack/CbmTofUnpackAlgo.cxx b/reco/detectors/tof/unpack/CbmTofUnpackAlgo.cxx
index 11b6466572..cf12a3e740 100644
--- a/reco/detectors/tof/unpack/CbmTofUnpackAlgo.cxx
+++ b/reco/detectors/tof/unpack/CbmTofUnpackAlgo.cxx
@@ -129,7 +129,6 @@ Bool_t CbmTofUnpackAlgo::initParSet(CbmMcbm2018TofPar* parset)
       sPrintout += Form("\n Gdpb %u (0x%x)\n", uGdpbIdx, parset->GetGdpbId(uGdpbIdx));
     }
     if (0 == fviRpcChUId[uCh]) {
-      /// Tricking clang to avoid one liner
       sPrintout += " ----------";
     }
     else {
@@ -193,7 +192,6 @@ bool CbmTofUnpackAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UI
 
   if (fMonitor) {
     if (0x90 == fuCurrentMsSysId) {
-      /// Tricking clang to avoid one liner
       fMonitor->CheckBmonSpillLimits(fdCurrentMsTime);
     }
   }
@@ -231,7 +229,6 @@ bool CbmTofUnpackAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UI
 
     if (uNbMessages - 1 == uIdx) {
       if (pMess[uIdx].isEndOfMs()) {
-        /// Tricking clang to avoid one liner
         continue;
       }
       else {
@@ -495,6 +492,10 @@ void CbmTofUnpackAlgo::ProcessHit(const critof001::Message& mess)
   LOG(debug) << Form("Insert 0x%08x digi with time ", uChanUId) << dHitTime << Form(", Tot %4.0f", dHitTot)
              << " at epoch " << fulEpochIndexInTs;
 
+  if (fMonitor && 0x90 == fuCurrentMsSysId && 0 == uChannel) {  //
+    fMonitor->FillHitBmonMicroSpillHistos(dHitTime);
+  }
+
   /// Create output object and store it
   std::unique_ptr<CbmTofDigi> digi(new CbmTofDigi(uChanUId, dHitTime, dHitTot));
   if (digi) fOutputVec.emplace_back(*std::move(digi));
diff --git a/reco/detectors/tof/unpack/CbmTofUnpackMonitor.cxx b/reco/detectors/tof/unpack/CbmTofUnpackMonitor.cxx
index 9acaff4212..388f419bbb 100644
--- a/reco/detectors/tof/unpack/CbmTofUnpackMonitor.cxx
+++ b/reco/detectors/tof/unpack/CbmTofUnpackMonitor.cxx
@@ -5,23 +5,25 @@
 #include "CbmTofUnpackMonitor.h"
 
 #include "CbmFlesHistosTools.h"
-
+#include "CriGet4Mess001.h"
 #include "MicrosliceDescriptor.hpp"
 
 #include <FairRun.h>
 #include <FairRunOnline.h>
 #include <Logger.h>
 
-#include "TCanvas.h"
 #include <RtypesCore.h>
+#include <TCanvas.h>
 #include <TFile.h>
 #include <TH1.h>
 #include <TH2.h>
 #include <THttpServer.h>
+#include <TMath.h>
 #include <TPaveStats.h>
 #include <TProfile.h>
 #include <TROOT.h>
 
+#include <cmath>
 #include <cstdint>
 #include <iomanip>
 #include <iostream>
@@ -29,10 +31,6 @@
 #include <string>
 #include <vector>
 
-#include <cmath>
-
-#include "CriGet4Mess001.h"
-
 CbmTofUnpackMonitor::CbmTofUnpackMonitor(/* args */) : fvpAllHistoPointers()
 {
   // Miscroslice component properties histos
@@ -970,6 +968,193 @@ void CbmTofUnpackMonitor::DrawBmonCanvases()
 // -------------------------------------------------------------------------
 
 
+// -------------------------------------------------------------------------
+Bool_t CbmTofUnpackMonitor::CreateHistogramsMicroSpills()
+{
+  /// Logarithmic bining
+  uint32_t uNbBinsLog = 0;
+  /// Parameters are NbDecadesLog, NbStepsDecade, NbSubStepsInStep, start decade exponent (def 0), add [0;min[ bin flag
+  std::vector<double> dBinsLogVector = GenerateLogBinArray(6, 9, 10, uNbBinsLog, 1, true);
+  double* dBinsLog                   = dBinsLogVector.data();
+
+  uint32_t uNbBinsLogFract                = 0;
+  std::vector<double> dBinsLogVectorFract = GenerateLogBinArray(6, 9, 10, uNbBinsLogFract, -6, true);
+  double* dBinsLogFract                   = dBinsLogVectorFract.data();
+
+  fuBmonMicrospillsNbBinsTs = fdBmonMicrospillsTsLengthSec / 1e-5;
+  fArrHitCounts             = std::make_unique<double[]>(fuBmonMicrospillsNbBinsTs);
+  fArrErrCounts             = std::make_unique<double[]>(fuBmonMicrospillsNbBinsTs);
+
+  // clang-format off
+  // ==> Only internal, not for users
+  fhBmonMicrospillsDistHits = new TH1I("hBmonMicrospillsDistHits", "Hits per 10 us; Time in spill [us]; Hits nb []",
+                                       fuBmonMicrospillsNbBinsTs, -0.5, fdBmonMicrospillsTsLengthSec * 1e6 - 0.5);
+  // ==> Only internal, not for users
+  fhBmonMicrospillsDistErrs = new TH1I("hBmonMicrospillsDistErrs", "Erros per 10 us; Time in spill [us]; Errors nb []",
+                                       fuBmonMicrospillsNbBinsTs, -0.5, fdBmonMicrospillsTsLengthSec * 1e6 - 0.5);
+
+  fhBmonMicrospillsTsBinCntHits = new TH2I("hBmonMicrospillsTsBinCntHits",
+                                           "Nb 10 us bins with hit count per TS; TS []; Hits nb. []; 10 us bins []",
+                                           1000, -0.5, 999.5,
+                                           uNbBinsLog, dBinsLog);
+  fhBmonMicrospillsTsBinCntErrs = new TH2I("hBmonMicrospillsTsBinCntErrs",
+                                           "Nb 10 us bins with error count per TS; TS []; Errors nb. []; 10 us bins []",
+                                           1000, -0.5, 999.5,
+                                           uNbBinsLog, dBinsLog);
+
+  fhBmonMicrospillsTsMeanHits = new TH1I("hBmonMicrospillsTsMeanHits",
+                                         "Mean nb hits per 10 us per TS; TS []; Hits nb. []",
+                                         1000, -0.5, 999.5);
+  fhBmonMicrospillsTsMeanErrs = new TH1I("hBmonMicrospillsTsMeanErrs",
+                                         "Mean nb error per 10 us per TS; TS []; Errors nb. []",
+                                         1000, -0.5, 999.5);
+
+
+  fhBmonMicrospillsTsMedianHits = new TH1I("hBmonMicrospillsTsMedianHits",
+                                         "Median nb hits per 10 us per TS; TS []; Hits nb. []",
+                                         1000, -0.5, 999.5);
+  fhBmonMicrospillsTsMedianErrs = new TH1I("hBmonMicrospillsTsMedianErrs",
+                                         "Median nb error per 10 us per TS; TS []; Errors nb. []",
+                                         1000, -0.5, 999.5);
+
+  fhBmonMicrospillsTsBinRatioHits = new TH2I("hBmonMicrospillsTsBinRatioHits",
+                                             "Nb 10us bins with hit ratio to mean per TS; TS []; Ratio; 10 us bins []",
+                                             1000, -0.5, 999.5,
+                                             1000, -0.5, 499.5);
+  fhBmonMicrospillsTsBinRatioErrs = new TH2I("hBmonMicrospillsTsBinRatioErrs",
+                                             "Nb 10us bins with error ratio to mean per TS; TS []; Ratio; 10 us bins []",
+                                             1000, -0.5, 999.5,
+                                             1000, -0.5, 499.5);
+
+  fhBmonMicrospillsTsBinFractHits = new TH2I("hBmonMicrospillsTsBinFractHits",
+                                             "Nb 10 us bins with hit fract. per TS; TS []; Fraction; 10 us bins []",
+                                             1000, -0.5, 999.5,
+                                             uNbBinsLogFract, dBinsLogFract);
+  fhBmonMicrospillsTsBinFractErrs = new TH2I("hBmonMicrospillsTsBinFractErrs",
+                                             "Nb 10 us bins with error count per TS; TS []; Fraction; 10 us bins []",
+                                             1000, -0.5, 999.5,
+                                             uNbBinsLogFract, dBinsLogFract);
+  // clang-format on
+
+  /// Add pointers to the vector with all histo for access by steering class
+  std::string sFolder = "Microspills";
+  // AddHistoToVector(fhBmonMicrospillsDistHits, sFolder);
+  // AddHistoToVector(fhBmonMicrospillsDistErrs, sFolder);
+
+  AddHistoToVector(fhBmonMicrospillsTsBinCntHits, sFolder);
+  AddHistoToVector(fhBmonMicrospillsTsBinCntErrs, sFolder);
+
+  AddHistoToVector(fhBmonMicrospillsTsMeanHits, sFolder);
+  AddHistoToVector(fhBmonMicrospillsTsMeanErrs, sFolder);
+
+  AddHistoToVector(fhBmonMicrospillsTsMedianHits, sFolder);
+  AddHistoToVector(fhBmonMicrospillsTsMedianErrs, sFolder);
+
+  AddHistoToVector(fhBmonMicrospillsTsBinRatioHits, sFolder);
+  AddHistoToVector(fhBmonMicrospillsTsBinRatioErrs, sFolder);
+
+  AddHistoToVector(fhBmonMicrospillsTsBinFractHits, sFolder);
+  AddHistoToVector(fhBmonMicrospillsTsBinFractErrs, sFolder);
+
+  return kTRUE;
+}
+
+Bool_t CbmTofUnpackMonitor::ResetHistogramsMicroSpills(Bool_t /*bResetTime*/)
+{
+  fhBmonMicrospillsTsBinCntHits->Reset();
+  fhBmonMicrospillsTsBinCntErrs->Reset();
+  fhBmonMicrospillsTsMeanHits->Reset();
+  fhBmonMicrospillsTsMeanErrs->Reset();
+  fhBmonMicrospillsTsMedianHits->Reset();
+  fhBmonMicrospillsTsMedianErrs->Reset();
+  fhBmonMicrospillsTsBinRatioHits->Reset();
+  fhBmonMicrospillsTsBinRatioErrs->Reset();
+  fhBmonMicrospillsTsBinFractHits->Reset();
+  fhBmonMicrospillsTsBinFractErrs->Reset();
+
+  return kTRUE;
+}
+
+void CbmTofUnpackMonitor::DrawCanvasesMicroSpills()
+{
+  std::string sFolder = "canvases";
+
+  /*******************************************************************/
+  /// Count for each TS how many 10 us bins in a TS have a given number of hits/errors
+  fcBmonMicrospillsBinCnts = new TCanvas("BmonMicrospillsBinCnts", "Nb 10 us bins with hit/err counts per TS");
+  fcBmonMicrospillsBinCnts->Divide(2);
+
+  fcBmonMicrospillsBinCnts->cd(1);
+  gPad->SetGridx();
+  gPad->SetGridy();
+  gPad->SetLogy();
+  gPad->SetLogz();
+  fhBmonMicrospillsTsBinCntHits->Draw("colz");
+  fhBmonMicrospillsTsMeanHits->SetLineColor(kRed);
+  fhBmonMicrospillsTsMeanHits->Draw("HIST same");
+  fhBmonMicrospillsTsMedianHits->SetLineColor(kBlack);
+  fhBmonMicrospillsTsMedianHits->Draw("HIST same");
+
+  fcBmonMicrospillsBinCnts->cd(2);
+  gPad->SetGridx();
+  gPad->SetGridy();
+  gPad->SetLogy();
+  gPad->SetLogz();
+  fhBmonMicrospillsTsBinCntErrs->Draw("colz");
+  fhBmonMicrospillsTsMeanErrs->SetLineColor(kRed);
+  fhBmonMicrospillsTsMeanErrs->Draw("HIST same");
+  fhBmonMicrospillsTsMedianErrs->SetLineColor(kBlack);
+  fhBmonMicrospillsTsMedianErrs->Draw("HIST same");
+
+  AddCanvasToVector(fcBmonMicrospillsBinCnts, sFolder);
+  /*******************************************************************/
+
+  /*******************************************************************/
+  /// Count for each TS how many 10 us bins in a TS have a given fraction of number of hits/errors divided by TS total
+  fcBmonMicrospillsFraction =
+    new TCanvas("BmonMicrospillsFraction", "Nb 10 us bins with fraction of hit/err counts per TS/Total count per TS");
+  fcBmonMicrospillsFraction->Divide(2);
+
+  fcBmonMicrospillsFraction->cd(1);
+  gPad->SetGridx();
+  gPad->SetGridy();
+  gPad->SetLogy();
+  gPad->SetLogz();
+  fhBmonMicrospillsTsBinFractHits->Draw("colz");
+
+  fcBmonMicrospillsFraction->cd(2);
+  gPad->SetGridx();
+  gPad->SetGridy();
+  gPad->SetLogy();
+  gPad->SetLogz();
+  fhBmonMicrospillsTsBinFractErrs->Draw("colz");
+
+  AddCanvasToVector(fcBmonMicrospillsFraction, sFolder);
+  /*******************************************************************/
+
+  /*******************************************************************/
+  /// Count for each TS how many 10 us bins in a TS have a given ratio of number of hits/errors divided by TS mean
+  fcBmonMicrospillsRatios =
+    new TCanvas("BmonMicrospillsRatios", "Nb 10 us bins with ratio of hit/err counts per mean count per TS/bin");
+  fcBmonMicrospillsRatios->Divide(2);
+
+  fcBmonMicrospillsRatios->cd(1);
+  gPad->SetGridx();
+  gPad->SetGridy();
+  gPad->SetLogz();
+  fhBmonMicrospillsTsBinRatioHits->Draw("colz");
+
+  fcBmonMicrospillsRatios->cd(2);
+  gPad->SetGridx();
+  gPad->SetGridy();
+  gPad->SetLogz();
+  fhBmonMicrospillsTsBinRatioErrs->Draw("colz");
+
+  AddCanvasToVector(fcBmonMicrospillsRatios, sFolder);
+  /*******************************************************************/
+}
+// -------------------------------------------------------------------------
+
 // -------------------------------------------------------------------------
 void CbmTofUnpackMonitor::FillHitMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx,
                                                   const uint32_t& uGet4Id, const uint32_t& uRawCh,
@@ -980,19 +1165,21 @@ void CbmTofUnpackMonitor::FillHitMonitoringHistos(const double_t& dMsTime, const
     fdStartTime = dMsTime;
   }
 
-  /// ---> Per GET4 in system
-  uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
-  fhGet4MessType->Fill(uGet4InSys, 0);
-  /// ---> Per GET4 in Component
-  fvhCompGet4MessType[uCurrCompIdx]->Fill(uGet4Id, 0);
-  /// ---> Per raw channel in Component
-  fvhCompRawChCount[uCurrCompIdx]->Fill(uRawCh);
-  fvhCompRawChRate[uCurrCompIdx]->Fill(dMsTime - fdStartTime, uRawCh);
-  fvhCompRawChTot[uCurrCompIdx]->Fill(uRawCh, uTot);
-  /// ---> Per remapped (PADI) channel in Component
-  fvhCompRemapChCount[uCurrCompIdx]->Fill(uRemapCh);
-  fvhCompRemapChRate[uCurrCompIdx]->Fill(dMsTime - fdStartTime, uRemapCh);
-  fvhCompRemapChTot[uCurrCompIdx]->Fill(uRemapCh, uTot);
+  if (!fBmonMicroSpillMode) {
+    /// ---> Per GET4 in system
+    uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
+    fhGet4MessType->Fill(uGet4InSys, 0);
+    /// ---> Per GET4 in Component
+    fvhCompGet4MessType[uCurrCompIdx]->Fill(uGet4Id, 0);
+    /// ---> Per raw channel in Component
+    fvhCompRawChCount[uCurrCompIdx]->Fill(uRawCh);
+    fvhCompRawChRate[uCurrCompIdx]->Fill(dMsTime - fdStartTime, uRawCh);
+    fvhCompRawChTot[uCurrCompIdx]->Fill(uRawCh, uTot);
+    /// ---> Per remapped (PADI) channel in Component
+    fvhCompRemapChCount[uCurrCompIdx]->Fill(uRemapCh);
+    fvhCompRemapChRate[uCurrCompIdx]->Fill(dMsTime - fdStartTime, uRemapCh);
+    fvhCompRemapChTot[uCurrCompIdx]->Fill(uRemapCh, uTot);
+  }
 }
 void CbmTofUnpackMonitor::FillEpochMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id,
                                                     const bool& bSyncFlag,   // mess.getGdpbEpSync
@@ -1001,15 +1188,17 @@ void CbmTofUnpackMonitor::FillEpochMonitoringHistos(const uint32_t& uCurrCompIdx
                                                     const bool& bMissmMatch  // mess.getGdpbEpMissmatch()
 )
 {
-  /// ---> Per GET4 in system
-  uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
-  fhGet4MessType->Fill(uGet4InSys, 1);
-  if (bSyncFlag) fhGet4EpochFlags->Fill(uGet4InSys, 0);
-  if (bDataLoss) fhGet4EpochFlags->Fill(uGet4InSys, 1);
-  if (bEpochLoss) fhGet4EpochFlags->Fill(uGet4InSys, 2);
-  if (bMissmMatch) fhGet4EpochFlags->Fill(uGet4InSys, 3);
-  /// ---> Per GET4 in Component
-  fvhCompGet4MessType[uCurrCompIdx]->Fill(uGet4Id, 1);
+  if (!fBmonMicroSpillMode) {
+    /// ---> Per GET4 in system
+    uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
+    fhGet4MessType->Fill(uGet4InSys, 1);
+    if (bSyncFlag) fhGet4EpochFlags->Fill(uGet4InSys, 0);
+    if (bDataLoss) fhGet4EpochFlags->Fill(uGet4InSys, 1);
+    if (bEpochLoss) fhGet4EpochFlags->Fill(uGet4InSys, 2);
+    if (bMissmMatch) fhGet4EpochFlags->Fill(uGet4InSys, 3);
+    /// ---> Per GET4 in Component
+    fvhCompGet4MessType[uCurrCompIdx]->Fill(uGet4Id, 1);
+  }
 }
 void CbmTofUnpackMonitor::FillScmMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id,
                                                   const uint32_t& uCh,    // mess.getGdpbSlcChan()
@@ -1017,156 +1206,162 @@ void CbmTofUnpackMonitor::FillScmMonitoringHistos(const uint32_t& uCurrCompIdx,
                                                   const uint32_t& uType   // mess.getGdpbSlcType()
 )
 {
-  /// ---> Per GET4 in system
-  uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
-  fhGet4MessType->Fill(uGet4InSys, 2);
+  if (!fBmonMicroSpillMode) {
+    /// ---> Per GET4 in system
+    uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
+    fhGet4MessType->Fill(uGet4InSys, 2);
 
-  /// ---> Per GET4 in Component
-  fvhCompGet4MessType[uCurrCompIdx]->Fill(uGet4Id, 2);
-  double_t uChInComp = uCh + 0.5 * uEdge + uGet4Id * fuNbOfChannelsPerGet4;
-  if (uType == critof001::GET4_32B_SLC_START_SEU && 0 == uEdge) {
-    /// Start/SEU + Start flag is set
-    fhGet4ScmType->Fill(uGet4InSys, uType + 1);
-    fvhCompGet4ChScm[uCurrCompIdx]->Fill(uChInComp, uType + 1);
-  }  // if (uType == critof001::GET4_32B_SLC_START_SEU && 0 == uEdge)
-  else {
-    fhGet4ScmType->Fill(uGet4InSys, uType);
-    fvhCompGet4ChScm[uCurrCompIdx]->Fill(uChInComp, uType);
-  }  // else of if (uType == critof001::GET4_32B_SLC_START_SEU && 0 == uEdge)
+    /// ---> Per GET4 in Component
+    fvhCompGet4MessType[uCurrCompIdx]->Fill(uGet4Id, 2);
+    double_t uChInComp = uCh + 0.5 * uEdge + uGet4Id * fuNbOfChannelsPerGet4;
+    if (uType == critof001::GET4_32B_SLC_START_SEU && 0 == uEdge) {
+      /// Start/SEU + Start flag is set
+      fhGet4ScmType->Fill(uGet4InSys, uType + 1);
+      fvhCompGet4ChScm[uCurrCompIdx]->Fill(uChInComp, uType + 1);
+    }  // if (uType == critof001::GET4_32B_SLC_START_SEU && 0 == uEdge)
+    else {
+      fhGet4ScmType->Fill(uGet4InSys, uType);
+      fvhCompGet4ChScm[uCurrCompIdx]->Fill(uChInComp, uType);
+    }  // else of if (uType == critof001::GET4_32B_SLC_START_SEU && 0 == uEdge)
+  }
 }
 void CbmTofUnpackMonitor::FillSysMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id,
                                                   const uint32_t& uType  // mess.getGdpbSysSubType()
 )
 {
-  /// ---> Per GET4 in system
-  uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
-  fhGet4SysMessType->Fill(uGet4InSys, uType);
+  if (!fBmonMicroSpillMode) {
+    /// ---> Per GET4 in system
+    uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
+    fhGet4SysMessType->Fill(uGet4InSys, uType);
+  }
 }
 void CbmTofUnpackMonitor::FillErrMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id,
                                                   const uint32_t& uCh,   // mess.getGdpbSysErrChanId()
                                                   const uint32_t& uType  // mess.getGdpbSysErrData()
 )
 {
-  /// ---> Per GET4 in system
-  uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
-  fhGet4MessType->Fill(uGet4InSys, 3);
-  /// ---> Per GET4 in Component
-  fvhCompGet4MessType[uCurrCompIdx]->Fill(uGet4Id, 3);
-
-  uint32_t uChInComp = uCh + uGet4Id * fuNbOfChannelsPerGet4;
-  switch (uType) {
-    case critof001::GET4_V2X_ERR_READ_INIT: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 0);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 0);
-      break;
-    }  // case critof001::GET4_V2X_ERR_READ_INIT:
-    case critof001::GET4_V2X_ERR_SYNC: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 1);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 1);
-      break;
-    }  // case critof001::GET4_V2X_ERR_SYNC:
-    case critof001::GET4_V2X_ERR_EP_CNT_SYNC: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 2);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 2);
-      break;
-    }  // case critof001::GET4_V2X_ERR_EP_CNT_SYNC:
-    case critof001::GET4_V2X_ERR_EP: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 3);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 3);
-      break;
-    }  // case critof001::GET4_V2X_ERR_EP:
-    case critof001::GET4_V2X_ERR_FIFO_WRITE: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 4);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 4);
-      break;
-    }  // case critof001::GET4_V2X_ERR_FIFO_WRITE:
-    case critof001::GET4_V2X_ERR_LOST_EVT: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 5);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 5);
-      break;
-    }  // case critof001::GET4_V2X_ERR_LOST_EVT:
-    case critof001::GET4_V2X_ERR_CHAN_STATE: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 6);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 6);
-      break;
-    }  // case critof001::GET4_V2X_ERR_CHAN_STATE:
-    case critof001::GET4_V2X_ERR_TOK_RING_ST: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 7);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 7);
-      break;
-    }  // case critof001::GET4_V2X_ERR_TOK_RING_ST:
-    case critof001::GET4_V2X_ERR_TOKEN: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 8);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 8);
-      break;
-    }  // case critof001::GET4_V2X_ERR_TOKEN:
-    case critof001::GET4_V2X_ERR_READOUT_ERR: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 9);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 9);
-      break;
-    }  // case critof001::GET4_V2X_ERR_READOUT_ERR:
-    case critof001::GET4_V2X_ERR_SPI: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 10);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 10);
-      break;
-    }  // case critof001::GET4_V2X_ERR_SPI:
-    case critof001::GET4_V2X_ERR_DLL_LOCK: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 11);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 11);
-      break;
-    }  // case critof001::GET4_V2X_ERR_DLL_LOCK:
-    case critof001::GET4_V2X_ERR_DLL_RESET: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 12);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 12);
-      break;
-    }  // case critof001::GET4_V2X_ERR_DLL_RESET:
-    case critof001::GET4_V2X_ERR_TOT_OVERWRT: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 13);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 13);
-      break;
-    }  // case critof001::GET4_V2X_ERR_TOT_OVERWRT:
-    case critof001::GET4_V2X_ERR_TOT_RANGE: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 14);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 14);
-      break;
-    }  // case critof001::GET4_V2X_ERR_TOT_RANGE:
-    case critof001::GET4_V2X_ERR_EVT_DISCARD: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 15);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 15);
-      break;
-    }  // case critof001::GET4_V2X_ERR_EVT_DISCARD:
-    case critof001::GET4_V2X_ERR_ADD_RIS_EDG: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 16);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 16);
-      break;
-    }  // case critof001::GET4_V2X_ERR_ADD_RIS_EDG:
-    case critof001::GET4_V2X_ERR_UNPAIR_FALL: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 17);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 17);
-      break;
-    }  // case critof001::GET4_V2X_ERR_UNPAIR_FALL:
-    case critof001::GET4_V2X_ERR_SEQUENCE_ER: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 18);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 18);
-      break;
-    }  // case critof001::GET4_V2X_ERR_SEQUENCE_ER:
-    case critof001::GET4_V2X_ERR_EPOCH_OVERF: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 19);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 19);
-      break;
-    }  // case critof001::GET4_V2X_ERR_EPOCH_OVERF:
-    case critof001::GET4_V2X_ERR_UNKNOWN: {
-      fhGet4ErrorsType->Fill(uGet4InSys, 20);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 20);
-      break;
-    }  // case critof001::GET4_V2X_ERR_UNKNOWN:
-    default: // Corrupt error or not yet supported error
-      {
-      fhGet4ErrorsType->Fill(uGet4InSys, 21);
-      fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 21);
-      break;
-    }  //
-  }    // Switch( mess.getGdpbSysErrData() )
+  if (!fBmonMicroSpillMode) {
+    /// ---> Per GET4 in system
+    uint32_t uGet4InSys = uGet4Id + uCurrCompIdx * fuNbOfGet4PerComp;
+    fhGet4MessType->Fill(uGet4InSys, 3);
+    /// ---> Per GET4 in Component
+    fvhCompGet4MessType[uCurrCompIdx]->Fill(uGet4Id, 3);
+
+    uint32_t uChInComp = uCh + uGet4Id * fuNbOfChannelsPerGet4;
+    switch (uType) {
+      case critof001::GET4_V2X_ERR_READ_INIT: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 0);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 0);
+        break;
+      }  // case critof001::GET4_V2X_ERR_READ_INIT:
+      case critof001::GET4_V2X_ERR_SYNC: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 1);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 1);
+        break;
+      }  // case critof001::GET4_V2X_ERR_SYNC:
+      case critof001::GET4_V2X_ERR_EP_CNT_SYNC: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 2);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 2);
+        break;
+      }  // case critof001::GET4_V2X_ERR_EP_CNT_SYNC:
+      case critof001::GET4_V2X_ERR_EP: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 3);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 3);
+        break;
+      }  // case critof001::GET4_V2X_ERR_EP:
+      case critof001::GET4_V2X_ERR_FIFO_WRITE: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 4);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 4);
+        break;
+      }  // case critof001::GET4_V2X_ERR_FIFO_WRITE:
+      case critof001::GET4_V2X_ERR_LOST_EVT: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 5);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 5);
+        break;
+      }  // case critof001::GET4_V2X_ERR_LOST_EVT:
+      case critof001::GET4_V2X_ERR_CHAN_STATE: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 6);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 6);
+        break;
+      }  // case critof001::GET4_V2X_ERR_CHAN_STATE:
+      case critof001::GET4_V2X_ERR_TOK_RING_ST: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 7);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 7);
+        break;
+      }  // case critof001::GET4_V2X_ERR_TOK_RING_ST:
+      case critof001::GET4_V2X_ERR_TOKEN: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 8);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 8);
+        break;
+      }  // case critof001::GET4_V2X_ERR_TOKEN:
+      case critof001::GET4_V2X_ERR_READOUT_ERR: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 9);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 9);
+        break;
+      }  // case critof001::GET4_V2X_ERR_READOUT_ERR:
+      case critof001::GET4_V2X_ERR_SPI: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 10);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 10);
+        break;
+      }  // case critof001::GET4_V2X_ERR_SPI:
+      case critof001::GET4_V2X_ERR_DLL_LOCK: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 11);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 11);
+        break;
+      }  // case critof001::GET4_V2X_ERR_DLL_LOCK:
+      case critof001::GET4_V2X_ERR_DLL_RESET: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 12);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 12);
+        break;
+      }  // case critof001::GET4_V2X_ERR_DLL_RESET:
+      case critof001::GET4_V2X_ERR_TOT_OVERWRT: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 13);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 13);
+        break;
+      }  // case critof001::GET4_V2X_ERR_TOT_OVERWRT:
+      case critof001::GET4_V2X_ERR_TOT_RANGE: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 14);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 14);
+        break;
+      }  // case critof001::GET4_V2X_ERR_TOT_RANGE:
+      case critof001::GET4_V2X_ERR_EVT_DISCARD: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 15);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 15);
+        break;
+      }  // case critof001::GET4_V2X_ERR_EVT_DISCARD:
+      case critof001::GET4_V2X_ERR_ADD_RIS_EDG: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 16);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 16);
+        break;
+      }  // case critof001::GET4_V2X_ERR_ADD_RIS_EDG:
+      case critof001::GET4_V2X_ERR_UNPAIR_FALL: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 17);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 17);
+        break;
+      }  // case critof001::GET4_V2X_ERR_UNPAIR_FALL:
+      case critof001::GET4_V2X_ERR_SEQUENCE_ER: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 18);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 18);
+        break;
+      }  // case critof001::GET4_V2X_ERR_SEQUENCE_ER:
+      case critof001::GET4_V2X_ERR_EPOCH_OVERF: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 19);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 19);
+        break;
+      }  // case critof001::GET4_V2X_ERR_EPOCH_OVERF:
+      case critof001::GET4_V2X_ERR_UNKNOWN: {
+        fhGet4ErrorsType->Fill(uGet4InSys, 20);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 20);
+        break;
+      }  // case critof001::GET4_V2X_ERR_UNKNOWN:
+      default: // Corrupt error or not yet supported error
+        {
+        fhGet4ErrorsType->Fill(uGet4InSys, 21);
+        fvhCompGet4ChErrors[uCurrCompIdx]->Fill(uChInComp, 21);
+        break;
+      }  //
+    }    // Switch( mess.getGdpbSysErrData() )
+  }
 }
 
 
@@ -1178,30 +1373,32 @@ void CbmTofUnpackMonitor::CheckBmonSpillLimits(const double_t& dMsTime)
     fdStartTime = dMsTime;
   }
 
-  /// Spill Detection
-  /// Check only every second
-  if (fdSpillCheckInterval < dMsTime - fdBmonLastInterTime) {
-    /// Spill Off detection
-    if (fbSpillOn && fuBmonCountsLastInter < fuOffSpillCountLimit
-        && fuBmonNonPulserCountsLastInter < fuOffSpillCountLimitNonPulser) {
-      fbSpillOn = kFALSE;
-      fuCurrentSpillIdx++;
-      fuCurrentSpillPlot = (fuCurrentSpillPlot + 1) % kuNbSpillPlots;
-      fdStartTimeSpill   = dMsTime;
-      fvhBmonCompMapSpill[fuCurrentSpillPlot]->Reset();
-      fvhBmonChannelMapSpill[fuCurrentSpillPlot]->Reset();
-    }  // if( fbSpillOn && fuCountsLastInter < fuOffSpillCountLimit && same for non pulser)
-    else if (fuOffSpillCountLimit < fuBmonCountsLastInter) {
-      fbSpillOn = kTRUE;
-    }
+  if (!fBmonMicroSpillMode) {
+    /// Spill Detection
+    /// Check only every second
+    if (fdSpillCheckInterval < dMsTime - fdBmonLastInterTime) {
+      /// Spill Off detection
+      if (fbSpillOn && fuBmonCountsLastInter < fuOffSpillCountLimit
+          && fuBmonNonPulserCountsLastInter < fuOffSpillCountLimitNonPulser) {
+        fbSpillOn = kFALSE;
+        fuCurrentSpillIdx++;
+        fuCurrentSpillPlot = (fuCurrentSpillPlot + 1) % kuNbSpillPlots;
+        fdStartTimeSpill   = dMsTime;
+        fvhBmonCompMapSpill[fuCurrentSpillPlot]->Reset();
+        fvhBmonChannelMapSpill[fuCurrentSpillPlot]->Reset();
+      }  // if( fbSpillOn && fuCountsLastInter < fuOffSpillCountLimit && same for non pulser)
+      else if (fuOffSpillCountLimit < fuBmonCountsLastInter) {
+        fbSpillOn = kTRUE;
+      }
 
-    //    LOG(debug) << Form("%6llu %6.4f %9u %9u %2d", fulCurrentTsIdx, dMsTime - fdLastInterTime, fuBmonCountsLastInter,
-    //                       fuBmonNonPulserCountsLastInter, fuCurrentSpillIdx);
+      //    LOG(debug) << Form("%6llu %6.4f %9u %9u %2d", fulCurrentTsIdx, dMsTime - fdLastInterTime, fuBmonCountsLastInter,
+      //                       fuBmonNonPulserCountsLastInter, fuCurrentSpillIdx);
 
-    fuBmonCountsLastInter          = 0;
-    fuBmonNonPulserCountsLastInter = 0;
-    fdBmonLastInterTime            = dMsTime;
-  }  // if( fdSpillCheckInterval < dMsTime - fdLastInterTime )
+      fuBmonCountsLastInter          = 0;
+      fuBmonNonPulserCountsLastInter = 0;
+      fdBmonLastInterTime            = dMsTime;
+    }  // if( fdSpillCheckInterval < dMsTime - fdLastInterTime )
+  }
 }
 void CbmTofUnpackMonitor::FillHitBmonMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx,
                                                       const uint32_t& uGet4Id, const uint32_t& uTot)
@@ -1210,93 +1407,155 @@ void CbmTofUnpackMonitor::FillHitBmonMonitoringHistos(const double_t& dMsTime, c
     /// Initialize Start time for evolution plots
     fdStartTime = dMsTime;
   }
+  if (!fBmonMicroSpillMode) {
+    /// 2022 mapping: Y[0-3] on c0, Y[4-7] on c1, X[0-3] on c2, X[4-7] on c3
+    /// Y not cabled for diamond but pulser there
+    UInt_t uChannelBmon = (uGet4Id / 8) + 4 * uCurrCompIdx;
+
+    fhBmonGet4Map->Fill(uGet4Id + 80 * uCurrCompIdx);
+    fhBmonGet4MapEvo->Fill(dMsTime - fdStartTime, uGet4Id + 80 * uCurrCompIdx);
+    fhBmonCompGet4->Fill(uGet4Id + 80 * uCurrCompIdx, uChannelBmon);
+    if (kuNbChanBmon <= uChannelBmon) return;
+
+    fhBmonCompMapAll->Fill(uCurrCompIdx);
+    fhBmonChannelMapAll->Fill(uChannelBmon);
+    fhBmonChannelTotAll->Fill(uChannelBmon, uTot);
+    fhBmonHitMapEvoAll->Fill(uChannelBmon, dMsTime - fdStartTime);
+    fhBmonHitTotEvoAll->Fill(dMsTime - fdStartTime, uTot);
+    fhBmonChanHitMapAll->Fill(fuBmonChanMap[uChannelBmon]);
+    fhBmonChanHitMapEvoAll->Fill(fuBmonChanMap[uChannelBmon], dMsTime - fdStartTime);
+
+    /// Spill detection
+    fuBmonCountsLastInter++;
+
+    fhBmonErrorFractEvo->Fill(dMsTime - fdStartTime, 0.0);
+    fhBmonLostEvtFractEvo->Fill(dMsTime - fdStartTime, 0.0);
+    fvhBmonErrorFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 0.0);
+    fvhBmonEvtLostFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 0.0);
+
+    fhBmonMsgCntEvo->Fill(dMsTime - fdStartTime);
+    fhBmonHitCntEvo->Fill(dMsTime - fdStartTime);
+
+    fvhBmonHitCntEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime);
+
+    fvuBmonHitCntChanMs[uChannelBmon]++;
+
+    /// Do not fill the pulser hits to keep counts low for channel 0 of each Board
+    /// For now hard-code the pulser channel
+    if ((0 == uGet4Id / 8) && (fuMinTotPulser <= uTot) && (uTot <= fuMaxTotPulser)) {
+      fhBmonChannelMapPulser->Fill(uChannelBmon);
+      fhBmonHitMapEvoPulser->Fill(uChannelBmon, dMsTime - fdStartTime);
+    }  // if ( (0 == uGet4Id / 8) && (fuMinTotPulser <= uTot) && (uTot <= fuMaxTotPulser) )
+    else {
+      fuBmonNonPulserCountsLastInter++;
+
+      fhBmonCompMap->Fill(uCurrCompIdx);
+      fhBmonChannelMap->Fill(uChannelBmon);
+      fhBmonHitMapEvo->Fill(uChannelBmon, dMsTime - fdStartTime);
+      fhBmonHitTotEvo->Fill(dMsTime - fdStartTime, uTot);
+      fhBmonChanHitMap->Fill(fuBmonChanMap[uChannelBmon]);
+      fhBmonChanHitMapEvo->Fill(fuBmonChanMap[uChannelBmon], dMsTime - fdStartTime);
+
+      fvhBmonCompMapSpill[fuCurrentSpillPlot]->Fill(uCurrCompIdx);
+      fvhBmonChannelMapSpill[fuCurrentSpillPlot]->Fill(fuBmonChanMap[uChannelBmon]);
+      fhBmonHitsPerSpill->Fill(fuCurrentSpillIdx);
+    }  // else of if ( (0 == uGet4Id / 8) && (fuMinTotPulser <= uTot) && (uTot <= fuMaxTotPulser) )
+  }
+}
 
-  /// 2022 mapping: Y[0-3] on c0, Y[4-7] on c1, X[0-3] on c2, X[4-7] on c3
-  /// Y not cabled for diamond but pulser there
-  UInt_t uChannelBmon = (uGet4Id / 8) + 4 * uCurrCompIdx;
+void CbmTofUnpackMonitor::FillErrBmonMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx,
+                                                      const uint32_t& uGet4Id, const bool& bErrEvtLost)
+{
+  if (-1 == fdStartTime) {
+    /// Initialize Start time for evolution plots
+    fdStartTime = dMsTime;
+  }
+  if (fBmonMicroSpillMode) {  //
+    fhBmonMicrospillsDistErrs->Fill((dMsTime - fdStartTime) * 1e6);
+  }
+  else {
+    /// 2022 mapping:
+    /// Y[0-3] on c0, Y[4-7] on c1, X[0-3] on c2, X[4-7] on c3
+    /// Y not cabled for diamond but pulser there
+    UInt_t uChannelBmon = (uGet4Id / 8) + 4 * uCurrCompIdx;
 
-  fhBmonGet4Map->Fill(uGet4Id + 80 * uCurrCompIdx);
-  fhBmonGet4MapEvo->Fill(dMsTime - fdStartTime, uGet4Id + 80 * uCurrCompIdx);
-  fhBmonCompGet4->Fill(uGet4Id + 80 * uCurrCompIdx, uChannelBmon);
-  if (kuNbChanBmon <= uChannelBmon) return;
+    fhBmonErrorFractEvo->Fill(dMsTime - fdStartTime, 0.0);
+    fhBmonLostEvtFractEvo->Fill(dMsTime - fdStartTime, 0.0);
+    fvhBmonErrorFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 0.0);
+    fvhBmonEvtLostFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 0.0);
 
-  fhBmonCompMapAll->Fill(uCurrCompIdx);
-  fhBmonChannelMapAll->Fill(uChannelBmon);
-  fhBmonChannelTotAll->Fill(uChannelBmon, uTot);
-  fhBmonHitMapEvoAll->Fill(uChannelBmon, dMsTime - fdStartTime);
-  fhBmonHitTotEvoAll->Fill(dMsTime - fdStartTime, uTot);
-  fhBmonChanHitMapAll->Fill(fuBmonChanMap[uChannelBmon]);
-  fhBmonChanHitMapEvoAll->Fill(fuBmonChanMap[uChannelBmon], dMsTime - fdStartTime);
+    fhBmonMsgCntEvo->Fill(dMsTime - fdStartTime);
+    fhBmonErrorCntEvo->Fill(dMsTime - fdStartTime);
+    fhBmonErrorFractEvo->Fill(dMsTime - fdStartTime, 1.0);
 
-  /// Spill detection
-  fuBmonCountsLastInter++;
+    fvhBmonErrorCntEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime);
+    fvhBmonErrorFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 1.0);
 
-  fhBmonErrorFractEvo->Fill(dMsTime - fdStartTime, 0.0);
-  fhBmonLostEvtFractEvo->Fill(dMsTime - fdStartTime, 0.0);
-  fvhBmonErrorFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 0.0);
-  fvhBmonEvtLostFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 0.0);
+    fvuBmonErrorCntChanMs[uChannelBmon]++;
+    if (bErrEvtLost) {
+      fhBmonLostEvtCntEvo->Fill(dMsTime - fdStartTime);
+      fhBmonLostEvtFractEvo->Fill(dMsTime - fdStartTime, 1.0);
 
-  fhBmonMsgCntEvo->Fill(dMsTime - fdStartTime);
-  fhBmonHitCntEvo->Fill(dMsTime - fdStartTime);
+      fvhBmonEvtLostCntEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime);
+      fvhBmonEvtLostFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 1.0);
 
-  fvhBmonHitCntEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime);
+      fvuBmonEvtLostCntChanMs[uChannelBmon]++;
+    }  // if( gdpbv100::GET4_V2X_ERR_LOST_EVT == mess.getGdpbSysErrData() )
+  }
+}
+// -------------------------------------------------------------------------
 
-  fvuBmonHitCntChanMs[uChannelBmon]++;
+// -------------------------------------------------------------------------
+void CbmTofUnpackMonitor::FillHitBmonMicroSpillHistos(const double_t& dTime)
+{
 
-  /// Do not fill the pulser hits to keep counts low for channel 0 of each Board
-  /// For now hard-code the pulser channel
-  if ((0 == uGet4Id / 8) && (fuMinTotPulser <= uTot) && (uTot <= fuMaxTotPulser)) {
-    fhBmonChannelMapPulser->Fill(uChannelBmon);
-    fhBmonHitMapEvoPulser->Fill(uChannelBmon, dMsTime - fdStartTime);
-  }  // if ( (0 == uGet4Id / 8) && (fuMinTotPulser <= uTot) && (uTot <= fuMaxTotPulser) )
-  else {
-    fuBmonNonPulserCountsLastInter++;
-
-    fhBmonCompMap->Fill(uCurrCompIdx);
-    fhBmonChannelMap->Fill(uChannelBmon);
-    fhBmonHitMapEvo->Fill(uChannelBmon, dMsTime - fdStartTime);
-    fhBmonHitTotEvo->Fill(dMsTime - fdStartTime, uTot);
-    fhBmonChanHitMap->Fill(fuBmonChanMap[uChannelBmon]);
-    fhBmonChanHitMapEvo->Fill(fuBmonChanMap[uChannelBmon], dMsTime - fdStartTime);
-
-    fvhBmonCompMapSpill[fuCurrentSpillPlot]->Fill(uCurrCompIdx);
-    fvhBmonChannelMapSpill[fuCurrentSpillPlot]->Fill(fuBmonChanMap[uChannelBmon]);
-    fhBmonHitsPerSpill->Fill(fuCurrentSpillIdx);
-  }  // else of if ( (0 == uGet4Id / 8) && (fuMinTotPulser <= uTot) && (uTot <= fuMaxTotPulser) )
+  if (-1 == fdStartTime) {
+    /// Initialize Start time for evolution plots
+    fdStartTime = dTime * 1e-9;
+  }
+  if (fBmonMicroSpillMode) {
+    fhBmonMicrospillsDistHits->Fill(dTime / 1e3);
+  }
 }
 
-void CbmTofUnpackMonitor::FillErrBmonMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx,
-                                                      const uint32_t& uGet4Id, const bool& bErrEvtLost)
+void CbmTofUnpackMonitor::FinalizeTsBmonMicroSpillHistos()
 {
-  /// 2022 mapping:
-  /// Y[0-3] on c0, Y[4-7] on c1, X[0-3] on c2, X[4-7] on c3
-  /// Y not cabled for diamond but pulser there
-  UInt_t uChannelBmon = (uGet4Id / 8) + 4 * uCurrCompIdx;
+  if (fBmonMicroSpillMode) {
+    uint32_t uNbHitsTs  = fhBmonMicrospillsDistHits->GetEntries();
+    uint32_t uNbErrsTs  = fhBmonMicrospillsDistErrs->GetEntries();
+    double dMeanHitsBin = static_cast<double>(uNbHitsTs) / fuBmonMicrospillsNbBinsTs;
+    double dMeanErrsBin = static_cast<double>(uNbErrsTs) / fuBmonMicrospillsNbBinsTs;
+    fhBmonMicrospillsTsMeanHits->Fill(fuNbTsMicrospills, dMeanHitsBin);
+    fhBmonMicrospillsTsMeanErrs->Fill(fuNbTsMicrospills, dMeanErrsBin);
+
+    for (uint32_t uBin = 0; uBin < fuBmonMicrospillsNbBinsTs; ++uBin) {
+      double dNbHitsInBin = fhBmonMicrospillsDistHits->GetBinContent(uBin + 1);
+      double dNbErrsInBin = fhBmonMicrospillsDistErrs->GetBinContent(uBin + 1);
 
-  fhBmonErrorFractEvo->Fill(dMsTime - fdStartTime, 0.0);
-  fhBmonLostEvtFractEvo->Fill(dMsTime - fdStartTime, 0.0);
-  fvhBmonErrorFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 0.0);
-  fvhBmonEvtLostFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 0.0);
+      fArrHitCounts[uBin] = dNbHitsInBin;
+      fArrErrCounts[uBin] = dNbErrsInBin;
 
-  fhBmonMsgCntEvo->Fill(dMsTime - fdStartTime);
-  fhBmonErrorCntEvo->Fill(dMsTime - fdStartTime);
-  fhBmonErrorFractEvo->Fill(dMsTime - fdStartTime, 1.0);
+      fhBmonMicrospillsTsBinCntHits->Fill(fuNbTsMicrospills, dNbHitsInBin);
+      fhBmonMicrospillsTsBinCntErrs->Fill(fuNbTsMicrospills, dNbErrsInBin);
 
-  fvhBmonErrorCntEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime);
-  fvhBmonErrorFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 1.0);
+      fhBmonMicrospillsTsBinRatioHits->Fill(fuNbTsMicrospills, dNbHitsInBin / dMeanHitsBin);
+      fhBmonMicrospillsTsBinRatioErrs->Fill(fuNbTsMicrospills, dNbErrsInBin / dMeanErrsBin);
 
-  fvuBmonErrorCntChanMs[uChannelBmon]++;
-  if (bErrEvtLost) {
-    fhBmonLostEvtCntEvo->Fill(dMsTime - fdStartTime);
-    fhBmonLostEvtFractEvo->Fill(dMsTime - fdStartTime, 1.0);
+      fhBmonMicrospillsTsBinFractHits->Fill(fuNbTsMicrospills, dNbHitsInBin / uNbHitsTs);
+      fhBmonMicrospillsTsBinFractErrs->Fill(fuNbTsMicrospills, dNbErrsInBin / uNbErrsTs);
+    }
+    fhBmonMicrospillsTsMedianHits->Fill(fuNbTsMicrospills,
+                                        TMath::Median(fuBmonMicrospillsNbBinsTs, fArrHitCounts.get()));
+    fhBmonMicrospillsTsMedianErrs->Fill(fuNbTsMicrospills,
+                                        TMath::Median(fuBmonMicrospillsNbBinsTs, fArrErrCounts.get()));
 
-    fvhBmonEvtLostCntEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime);
-    fvhBmonEvtLostFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 1.0);
+    fhBmonMicrospillsDistHits->Reset();
+    fhBmonMicrospillsDistErrs->Reset();
+    fdStartTime = -1;  // Make sure Error times are still set in "Time in TS", not compatible w/ standard moni histos!
 
-    fvuBmonEvtLostCntChanMs[uChannelBmon]++;
-  }  // if( gdpbv100::GET4_V2X_ERR_LOST_EVT == mess.getGdpbSysErrData() )
+    fuNbTsMicrospills++;
+  }
 }
-
 // -------------------------------------------------------------------------
 
 // ---- Init ----
@@ -1319,11 +1578,17 @@ Bool_t CbmTofUnpackMonitor::Init(CbmMcbm2018TofPar* parset)
   gROOT->cd();
 
   /// Trigger histo creation on all associated monitors
-  CreateHistograms();
-  DrawCanvases();
-  if (fBmonMode) {
-    CreateBmonHistograms();
-    DrawBmonCanvases();
+  if (fBmonMicroSpillMode) {
+    CreateHistogramsMicroSpills();
+    DrawCanvasesMicroSpills();
+  }
+  else {
+    CreateHistograms();
+    DrawCanvases();
+    if (fBmonMode) {
+      CreateBmonHistograms();
+      DrawBmonCanvases();
+    }
   }
 
   /// Restore old global file and folder pointer to avoid messing with FairRoot
@@ -1338,7 +1603,7 @@ Bool_t CbmTofUnpackMonitor::Init(CbmMcbm2018TofPar* parset)
 
   /// Register the histos and canvases in the HTTP server
   std::string sSystem = "tof";
-  if (fBmonMode) {
+  if (fBmonMode || fBmonMicroSpillMode) {
     //
     sSystem = "bmon";
   }
diff --git a/reco/detectors/tof/unpack/CbmTofUnpackMonitor.h b/reco/detectors/tof/unpack/CbmTofUnpackMonitor.h
index bf0c7ede20..34580a6e2d 100644
--- a/reco/detectors/tof/unpack/CbmTofUnpackMonitor.h
+++ b/reco/detectors/tof/unpack/CbmTofUnpackMonitor.h
@@ -36,6 +36,10 @@ public:
   Bool_t ResetBmonHistograms(Bool_t bResetTime);
   void DrawBmonCanvases();
 
+  Bool_t CreateHistogramsMicroSpills();
+  Bool_t ResetHistogramsMicroSpills(Bool_t bResetTime);
+  void DrawCanvasesMicroSpills();
+
   Bool_t CreateMsComponentSizeHistos(UInt_t component);
   Bool_t ResetMsComponentSizeHistos(UInt_t component);
 
@@ -106,6 +110,17 @@ public:
   /** @brief Read the Bmon mode */
   bool GetBmonMode() { return fBmonMode; }
 
+  /// Fill BMon Microspill histograms
+  void FillHitBmonMicroSpillHistos(const double_t& dTime);
+  /// Finalize BMon Microspill histograms
+  void FinalizeTsBmonMicroSpillHistos();
+
+  /** @brief Activate the BMon mode */
+  void SetBmonMicroSpillMode(bool value) { fBmonMicroSpillMode = value; }
+
+  /** @brief Read the Bmon mode */
+  bool GetBmonMicroSpillMode() { return fBmonMicroSpillMode; }
+
   /** @brief Activate/de-activate the internal histo serve mode */
   void SetInternalHttpMode(bool value) { fbInternalHttp = value; }
 
@@ -140,8 +155,9 @@ private:
   UInt_t fuLongHistoBinNb      = 1;
 
   /** @brief Flag if debug mode is active or not */
-  bool fBmonMode      = false;
-  bool fbInternalHttp = true;
+  bool fBmonMode           = false;
+  bool fBmonMicroSpillMode = false;
+  bool fbInternalHttp      = true;
 
   /// ---> Constants
   static const UInt_t kuMaxNbFlibLinks  = 32;
@@ -244,6 +260,25 @@ private:
   TH1* fhBmonChannelMapPulser = nullptr;
   TH2* fhBmonHitMapEvoPulser  = nullptr;
 
+  /// BMon micro-spills monitoring histograms
+  double_t fdBmonMicrospillsTsLengthSec = 0.128;  // 128 ms
+  uint32_t fuBmonMicrospillsNbBinsTs    = 0;
+  uint32_t fuNbTsMicrospills            = 0;
+  std::unique_ptr<double[]> fArrHitCounts;
+  std::unique_ptr<double[]> fArrErrCounts;
+  TH1* fhBmonMicrospillsDistHits       = nullptr;  // Only internal, not for users
+  TH1* fhBmonMicrospillsDistErrs       = nullptr;  // Only internal, not for users
+  TH2* fhBmonMicrospillsTsBinCntHits   = nullptr;
+  TH2* fhBmonMicrospillsTsBinCntErrs   = nullptr;
+  TH1* fhBmonMicrospillsTsMeanHits     = nullptr;
+  TH1* fhBmonMicrospillsTsMeanErrs     = nullptr;
+  TH1* fhBmonMicrospillsTsMedianHits   = nullptr;
+  TH1* fhBmonMicrospillsTsMedianErrs   = nullptr;
+  TH2* fhBmonMicrospillsTsBinRatioHits = nullptr;
+  TH2* fhBmonMicrospillsTsBinRatioErrs = nullptr;
+  TH2* fhBmonMicrospillsTsBinFractHits = nullptr;
+  TH2* fhBmonMicrospillsTsBinFractErrs = nullptr;
+
   /// Canvases
   /// ---> Generic
   TCanvas* fcSummaryGet4s          = nullptr;
@@ -256,6 +291,10 @@ private:
   TCanvas* fcBmonSpillCounts         = nullptr;
   TCanvas* fcBmonSpillCountsHori     = nullptr;
   TCanvas* fcBmonSpillCompCountsHori = nullptr;
+  /// ---> BMon Microspills monitoring
+  TCanvas* fcBmonMicrospillsBinCnts  = nullptr;
+  TCanvas* fcBmonMicrospillsRatios   = nullptr;
+  TCanvas* fcBmonMicrospillsFraction = nullptr;
 
   /// Spill detection
   Bool_t fbSpillOn                      = kTRUE;
diff --git a/reco/steer/CbmRecoUnpack.cxx b/reco/steer/CbmRecoUnpack.cxx
index c50a56159b..33d89d996a 100644
--- a/reco/steer/CbmRecoUnpack.cxx
+++ b/reco/steer/CbmRecoUnpack.cxx
@@ -491,8 +491,9 @@ void CbmRecoUnpack::Unpack(unique_ptr<Timeslice> ts)
   fTimeSlice->SetStartTime(ts->start_time());
 
   uint64_t nComponents = ts->num_components();
-  // if (fDoDebugPrints) LOG(info) << "Unpack: TS index " << ts->index() << " components " << nComponents;
-  LOG(info) << "Unpack: TS index " << ts->index() << " components " << nComponents;
+  if (fDoDebugPrints || 0 == ts->index() % 100) {
+    LOG(info) << "Unpack: TS index " << ts->index() << " components " << nComponents;
+  }
 
   for (uint64_t component = 0; component < nComponents; component++) {
 
@@ -586,6 +587,10 @@ void CbmRecoUnpack::Unpack(unique_ptr<Timeslice> ts)
     if (fBmonConfig && fBmonConfig->GetOptOutAVec()) { timesort(fBmonConfig->GetOptOutAVec()); }
   }
 
+  if (fBmonConfig && fBmonConfig->GetMonitor()) {  //
+    fBmonConfig->GetMonitor()->FinalizeTsBmonMicroSpillHistos();
+  }
+
   if (fDoPerfProfPerTs) {
     fTimerTs->Stop();
     performanceProfilingPerTs();
diff --git a/reco/steer/CbmSourceTsArchive.cxx b/reco/steer/CbmSourceTsArchive.cxx
index 20de26d0cf..79edb63bde 100644
--- a/reco/steer/CbmSourceTsArchive.cxx
+++ b/reco/steer/CbmSourceTsArchive.cxx
@@ -76,7 +76,9 @@ Int_t CbmSourceTsArchive::ReadEvent(UInt_t)
     LOG(info) << "SourceTsArchive: End of archive reached; stopping run.";
     return 1;
   }
-  LOG(info) << "SourceTsArchive: Reading time slice " << fTsCounter << " (index " << ts->index() << ")";
+  if (fDoDebugPrints || 0 == fTsCounter % 100) {
+    LOG(info) << "SourceTsArchive: Reading time slice " << fTsCounter << " (index " << ts->index() << ")";
+  }
 
   fUnpack.Unpack(std::move(ts));
 
diff --git a/reco/steer/CbmSourceTsArchive.h b/reco/steer/CbmSourceTsArchive.h
index 3ff171c078..f696703b89 100644
--- a/reco/steer/CbmSourceTsArchive.h
+++ b/reco/steer/CbmSourceTsArchive.h
@@ -25,7 +25,7 @@
  **/
 class CbmSourceTsArchive : public FairSource {
 
-public:
+ public:
   /** @brief Constructor
    ** @param fileName  Name of (single) input file.
    **
@@ -54,6 +54,13 @@ public:
   /** @brief Assignment operator - not implemented **/
   CbmSourceTsArchive& operator=(const CbmSourceTsArchive&) = delete;
 
+  /**
+   * @brief Set the Debug Printout Flag
+   *
+   * @param value
+  */
+  void SetDebugPrintout(bool value = true) { fDoDebugPrints = value; }
+
 
   /** @brief Add an input file
    ** @param fileName  Input file name
@@ -107,7 +114,10 @@ public:
   /** @brief Provide dummy implementation of this virtual function as not relevant in our case **/
   Bool_t SpecifyRunId() { return kTRUE; }
 
-private:
+ private:
+  /** @brief Flag if extended debug output is to be printed or not*/
+  bool fDoDebugPrints = false;  //!
+
   /** List of input file names **/
   std::vector<std::string> fFileNames = {};
 
-- 
GitLab