From 59dad30e1f50bfa508664664f5d807481075c662 Mon Sep 17 00:00:00 2001 From: "P.-A. Loizeau" <p.-a.loizeau@gsi.de> Date: Thu, 17 Mar 2022 17:55:20 +0100 Subject: [PATCH] Unpacking: add BMon unpacking based on TOF one + BMon/TOF monitoring - Update Mcbm2018TofPar to map the 2022 BMon diamond - Update Mcbm2018TofPar to map the new TOF modules for the 2022 iron beams (run 2100 onward) - Add a BmonUnpackConfig class setting up the TOF unpacker to BMon mode - Add a TofUnpackMonitor class providing monitoring plots for TOF and BMon unpacking - Integrate this one in the TOF unpack algo - Fix incomplete switching for the 2021 epoch hack in the TOF unpack Algo - Add Bmon in the sterring RecoUnpack task - Add a monitoring only mode to the RecoUnpack task were data is neither time sorted nor written to disk - Add BMon in the unpacking macros - Add the TOF monitor(s) to the unpacking macros - Add BMon only unpacking macros for fast beam monitoring (especially for beam tuning) - Add parameter files for TOF and BMon in the 2022 campaign --- core/data/CbmTsEventHeader.cxx | 1 + core/data/CbmTsEventHeader.h | 10 +- core/detectors/tof/CbmMcbm2018TofPar.cxx | 54 +- core/detectors/tof/CbmMcbm2018TofPar.h | 1 + macro/beamtime/mcbm2022/mBmonCriPar.par | 34 + macro/beamtime/mcbm2022/mTofCriPar.par | 2 +- macro/run/run_unpack_online.C | 69 +- macro/run/run_unpack_online_bmon.C | 211 +++ macro/run/run_unpack_tsa.C | 72 +- macro/run/run_unpack_tsa_bmon.C | 215 +++ reco/detectors/tof/CMakeLists.txt | 3 + reco/detectors/tof/CbmTofRecoLinkDef.h | 4 +- .../tof/unpack/CbmBmonUnpackConfig.cxx | 50 + .../tof/unpack/CbmBmonUnpackConfig.h | 78 + .../detectors/tof/unpack/CbmTofUnpackAlgo.cxx | 142 +- reco/detectors/tof/unpack/CbmTofUnpackAlgo.h | 39 +- .../tof/unpack/CbmTofUnpackConfig.cxx | 4 +- .../detectors/tof/unpack/CbmTofUnpackConfig.h | 21 +- .../tof/unpack/CbmTofUnpackMonitor.cxx | 1393 +++++++++++++++++ .../tof/unpack/CbmTofUnpackMonitor.h | 287 ++++ reco/steer/CbmRecoUnpack.cxx | 26 +- reco/steer/CbmRecoUnpack.h | 68 +- 22 files changed, 2690 insertions(+), 94 deletions(-) create mode 100644 macro/beamtime/mcbm2022/mBmonCriPar.par create mode 100644 macro/run/run_unpack_online_bmon.C create mode 100644 macro/run/run_unpack_tsa_bmon.C create mode 100644 reco/detectors/tof/unpack/CbmBmonUnpackConfig.cxx create mode 100644 reco/detectors/tof/unpack/CbmBmonUnpackConfig.h create mode 100644 reco/detectors/tof/unpack/CbmTofUnpackMonitor.cxx create mode 100644 reco/detectors/tof/unpack/CbmTofUnpackMonitor.h diff --git a/core/data/CbmTsEventHeader.cxx b/core/data/CbmTsEventHeader.cxx index 5676084214..9c3bdc5fbc 100644 --- a/core/data/CbmTsEventHeader.cxx +++ b/core/data/CbmTsEventHeader.cxx @@ -19,6 +19,7 @@ void CbmTsEventHeader::Reset() fNDigisTof = 0; fNDigisTrd1D = 0; fNDigisTrd2D = 0; + fNDigisBmon = 0; } ClassImp(CbmTsEventHeader) diff --git a/core/data/CbmTsEventHeader.h b/core/data/CbmTsEventHeader.h index 32e1a72c62..3a9cbdff19 100644 --- a/core/data/CbmTsEventHeader.h +++ b/core/data/CbmTsEventHeader.h @@ -31,6 +31,8 @@ public: void AddNDigisTrd1D(uint64_t value) { fNDigisTrd1D += value; } /** @brief Add a number of digis from this Ts */ void AddNDigisTrd2D(uint64_t value) { fNDigisTrd2D += value; } + /** @brief Add a number of digis from this Ts */ + void AddNDigisBmon(uint64_t value) { fNDigisBmon += value; } /** @brief Get the number of digis in this Ts */ uint64_t GetNDigisPsd() const { return fNDigisPsd; } @@ -44,6 +46,8 @@ public: uint64_t GetNDigisTrd1D() const { return fNDigisTrd1D; } /** @brief Get the number of digis in this Ts */ uint64_t GetNDigisTrd2D() const { return fNDigisTrd2D; } + /** @brief Get the number of digis in this Ts */ + uint64_t GetNDigisBmon() const { return fNDigisBmon; } /** Get the Start time of the this Timeslice linked to this event header*/ uint64_t GetTsIndex() const { return fTsIndex; } @@ -65,6 +69,8 @@ public: void SetNDigisTrd1D(uint64_t value) { fNDigisTrd1D = value; } /** @brief Set the number of digis in this Ts */ void SetNDigisTrd2D(uint64_t value) { fNDigisTrd2D = value; } + /** @brief Set the number of digis in this Ts */ + void SetNDigisBmon(uint64_t value) { fNDigisBmon = value; } /** @brief Set the Ts Start Time @param value Start time of the TS */ void SetTsIndex(uint64_t value) { fTsIndex = value; } @@ -93,7 +99,9 @@ protected: uint64_t fNDigisTrd1D = 0; /** @brief nDigis in "this" timeslice measured by the TRD2D */ uint64_t fNDigisTrd2D = 0; + /** @brief nDigis in "this" timeslice measured by the BMON */ + uint64_t fNDigisBmon = 0; - ClassDef(CbmTsEventHeader, 5) + ClassDef(CbmTsEventHeader, 6) }; #endif diff --git a/core/detectors/tof/CbmMcbm2018TofPar.cxx b/core/detectors/tof/CbmMcbm2018TofPar.cxx index be885c97e2..271315ca45 100644 --- a/core/detectors/tof/CbmMcbm2018TofPar.cxx +++ b/core/detectors/tof/CbmMcbm2018TofPar.cxx @@ -149,6 +149,7 @@ Bool_t CbmMcbm2018TofPar::getParams(FairParamList* l) if (!l->fill("StarTriggerWinSize", &fdStarTriggerWinSize)) return kFALSE; if (!l->fill("TsDeadtimePeriod", &fdTsDeadtimePeriod)) return kFALSE; + LOG(info) << "Build TOF Channels UId Map:"; BuildChannelsUidMap(); return kTRUE; @@ -215,8 +216,9 @@ void CbmMcbm2018TofPar::BuildChannelsUidMap() UInt_t uCh = 0; for (UInt_t uGbtx = 0; uGbtx < uNrOfGbtx; ++uGbtx) { + uint32_t uCh0 = uCh; switch (fiRpcType[uGbtx]) { - case 2: // intended fall-through + case 2: // intended fall-through case 0: { // CBM modules BuildChannelsUidMapCbm(uCh, uGbtx); @@ -232,6 +234,11 @@ void CbmMcbm2018TofPar::BuildChannelsUidMap() BuildChannelsUidMapT0(uCh, uGbtx); break; } + case 99: { + /// Special Treatment for the 2022 T0 diamond, keep past behavior for older data! + BuildChannelsUidMapT0_2022(uCh, uGbtx); + break; + } case 78: { // cern-20-gap + ceramic module BuildChannelsUidMapCern(uCh, uGbtx); @@ -254,6 +261,15 @@ void CbmMcbm2018TofPar::BuildChannelsUidMap() BuildChannelsUidMapBuc(uCh, uGbtx); break; } + case 69: { + /// 2022 case: 69 is followed by 4 and 9 + BuildChannelsUidMapBuc(uCh, uGbtx); + /// Map also 4 and 9 (equivalent to fallthrough to 4 then 9 but without changing past behaviors) + uCh -= 80; // PAL, 2022/03/17: ?!? + BuildChannelsUidMapStar2(uCh, uGbtx); + uCh -= 80; // PAL, 2022/03/17: ?!? + break; + } case -1: { LOG(info) << " Found unused GBTX link at uCh = " << uCh; uCh += 160; @@ -263,11 +279,15 @@ void CbmMcbm2018TofPar::BuildChannelsUidMap() LOG(error) << "Invalid Tof Type specifier for GBTx " << std::setw(2) << uGbtx << ": " << fiRpcType[uGbtx]; } } // switch (fiRpcType[uGbtx]) + if (uCh - uCh0 != fiNrOfFeesPerGdpb * fiNrOfGet4PerFee * fiNrOfChannelsPerGet4 / 2) { + LOG(fatal) << "Tof mapping error for Gbtx " << uGbtx << ", diff = " << uCh - uCh0; + } } // for (UInt_t uGbtx = 0; uGbtx < uNrOfGbtx; ++uGbtx) } // ------------------------------------------------------------------------- void CbmMcbm2018TofPar::BuildChannelsUidMapCbm(UInt_t& uCh, UInt_t uGbtx) { + LOG(info) << " Map mTof box " << fiModuleId[uGbtx] << " at GBTX " << uGbtx << " - uCh = " << uCh; if (fiRpcSide[uGbtx] < 2) { // mTof modules LOG(debug) << " Map mTof box " << fiModuleId[uGbtx] << " at GBTX - uCh = " << uCh; const Int_t RpcMap[5] = {4, 2, 0, 3, 1}; @@ -353,6 +373,28 @@ void CbmMcbm2018TofPar::BuildChannelsUidMapT0(UInt_t& uCh, UInt_t uGbtx) } // for( UInt_t uFee = 0; uFee < kuNbChannelsPerFee; ++uFee ) } // ------------------------------------------------------------------------- +void CbmMcbm2018TofPar::BuildChannelsUidMapT0_2022(UInt_t& uCh, UInt_t uGbtx) +{ + LOG(info) << " Map 2022 diamond " << fiModuleId[uGbtx] << " at GBTX " << uGbtx << " - uCh = " << uCh; + for (UInt_t uGet4 = 0; uGet4 < kuNbGet4PerGbtx; ++uGet4) { + for (UInt_t uGet4Ch = 0; uGet4Ch < kuNbChannelsPerGet4; ++uGet4Ch) { + /// Mapping for the 2022 beamtime + if (0 == uGet4 % 4 && 0 == uGet4Ch && -1 < fiModuleId[uGbtx]) { + UInt_t uChannelT0 = uGet4 / 8; // + 4 * fiRpcSide[uGbtx]; + /// Type hard-coded to allow different parameter values to separate 2022 T0 and pre-2022 T0 + fviRpcChUId[uCh] = CbmTofAddress::GetUniqueAddress(fiModuleId[uGbtx], 0, uChannelT0, 0, 5); + LOG(info) << Form(" T0 channel: %u from GBTx %2u, " + "indx %d address %08x", + uChannelT0, uGbtx, uCh, fviRpcChUId[uCh]); + } // Valid T0 channel + else { + fviRpcChUId[uCh] = 0; + } // Invalid T0 channel + uCh++; + } // for( UInt_t uCh = 0; uCh < kuNbFeePerGbtx; ++uCh ) + } // for( UInt_t uFee = 0; uFee < kuNbChannelsPerFee; ++uFee ) +} +// ------------------------------------------------------------------------- void CbmMcbm2018TofPar::BuildChannelsUidMapCern(UInt_t& uCh, UInt_t /*uGbtx*/) { LOG(info) << " Map CERN 20 gap at GBTX - uCh = " << uCh; @@ -392,7 +434,7 @@ void CbmMcbm2018TofPar::BuildChannelsUidMapCera(UInt_t& uCh, UInt_t /*uGbtx*/) // ------------------------------------------------------------------------- void CbmMcbm2018TofPar::BuildChannelsUidMapStar2(UInt_t& uCh, UInt_t uGbtx) { - LOG(info) << " Map Star2 box " << fiModuleId[uGbtx] << " at GBTX - uCh = " << uCh; + LOG(info) << " Map Star2 box " << fiModuleId[uGbtx] << " at GBTX " << uGbtx << " - uCh = " << uCh; const Int_t iRpc[5] = {1, -1, 1, 0, 0}; const Int_t iSide[5] = {1, -1, 0, 1, 0}; for (Int_t iFeet = 0; iFeet < 5; iFeet++) { @@ -448,7 +490,7 @@ void CbmMcbm2018TofPar::BuildChannelsUidMapStar2(UInt_t& uCh, UInt_t uGbtx) // ------------------------------------------------------------------------- void CbmMcbm2018TofPar::BuildChannelsUidMapBuc(UInt_t& uCh, UInt_t uGbtx) { - LOG(info) << " Map Buc box at GBTX - uCh = " << uCh; + LOG(info) << " Map Buc box " << fiModuleId[uGbtx] << " at GBTX " << uGbtx << " - uCh = " << uCh; Int_t iModuleIdMap = fiModuleId[uGbtx]; const Int_t iRpc[5] = {0, -1, 0, 1, 1}; @@ -533,9 +575,9 @@ void CbmMcbm2018TofPar::BuildChannelsUidMapBuc(UInt_t& uCh, UInt_t uGbtx) case 4: iSideMap = -1; break; } iModuleIdMap = fiModuleId[uGbtx]; - LOG(info) << "Buc of GBTX " << uGbtx << " Ch " << uCh - << Form(", Feet %1d, Str %2d, Ind %3d, i %3d, FeetInd %1d, Rpc %1d, Side %1d, Str %2d ", iFeet, - iStr, iInd, i, iFeetInd, iRpcMap, iSideMap, iStrMap); + LOG(debug) << "Buc of GBTX " << uGbtx << " Ch " << uCh + << Form(", Feet %1d, Str %2d, Ind %3d, i %3d, FeetInd %1d, Rpc %1d, Side %1d, Str %2d ", iFeet, + iStr, iInd, i, iFeetInd, iRpcMap, iSideMap, iStrMap); } break; default:; } // switch (fiRpcSide[uGbtx]) diff --git a/core/detectors/tof/CbmMcbm2018TofPar.h b/core/detectors/tof/CbmMcbm2018TofPar.h index e134514187..901e3169a8 100644 --- a/core/detectors/tof/CbmMcbm2018TofPar.h +++ b/core/detectors/tof/CbmMcbm2018TofPar.h @@ -88,6 +88,7 @@ private: void BuildChannelsUidMapCbm(UInt_t& uCh, UInt_t uGbtx); void BuildChannelsUidMapStar(UInt_t& uCh, UInt_t uGbtx); void BuildChannelsUidMapT0(UInt_t& uCh, UInt_t uGbtx); + void BuildChannelsUidMapT0_2022(UInt_t& uCh, UInt_t uGbtx); void BuildChannelsUidMapCern(UInt_t& uCh, UInt_t uGbtx); void BuildChannelsUidMapCera(UInt_t& uCh, UInt_t uGbtx); void BuildChannelsUidMapStar2(UInt_t& uCh, UInt_t uGbtx); diff --git a/macro/beamtime/mcbm2022/mBmonCriPar.par b/macro/beamtime/mcbm2022/mBmonCriPar.par new file mode 100644 index 0000000000..98525587b7 --- /dev/null +++ b/macro/beamtime/mcbm2022/mBmonCriPar.par @@ -0,0 +1,34 @@ +#################################################################################################### +[CbmMcbm2018TofPar] +//---------------------------------------------------------------------------- +NrOfGdpbs: Int_t 4 +GdpbIdArray: Int_t \ +0xabf0 0xabf1 0xabf2 0xabf3 +NrOfFeesPerGdpb: Int_t 10 +NrOfGet4PerFee: Int_t 8 +NrOfChannelsPerGet4: Int_t 4 +NrOfGbtx: Int_t 8 +NrOfModule: Int_t 0 +NrOfRpc: Int_t \ + 1 1 1 1 +RpcType: Int_t \ + 99 -1 99 -1 99 -1 99 -1 +RpcSide: Int_t \ + 0 0 1 0 0 0 1 0 +ModuleId: Int_t \ + 1 -1 1 -1 0 -1 0 -1 +NbMsTot: Int_t 100 +NbMsOverlap: Int_t 1 +SizeMsInNs: Double_t 102400.0 +//SizeMsInNs: Double_t 1638400 +StarTriggerDeadtime: Double_t \ + 1000.0 1000.0 1000.0 1000.0 1000.0 +StarTriggerDelay: Double_t \ + 2000.0 2000.0 2000.0 2000.0 2000.0 +// 2000.0 2000.0 2000.0 2000.0 2000.0 +//-23000.0 -23000.0 -23000.0 -23000.0 -23000.0 +StarTriggerWinSize: Double_t \ + 2000.0 2000.0 2000.0 2000.0 2000.0 +TsDeadtimePeriod: Double_t 62.5 + +#################################################################################################### diff --git a/macro/beamtime/mcbm2022/mTofCriPar.par b/macro/beamtime/mcbm2022/mTofCriPar.par index 0fe3bc583b..8d928103b2 100644 --- a/macro/beamtime/mcbm2022/mTofCriPar.par +++ b/macro/beamtime/mcbm2022/mTofCriPar.par @@ -8,7 +8,7 @@ NrOfFeesPerGdpb: Int_t 10 NrOfGet4PerFee: Int_t 8 NrOfChannelsPerGet4: Int_t 4 NrOfGbtx: Int_t 16 -NrOfModule: Int_t 20 +NrOfModule: Int_t 0 NrOfRpc: Int_t \ 5 5 5 5 5 5 5 5 5 5 5 5 2 2 2 2 RpcType: Int_t \ diff --git a/macro/run/run_unpack_online.C b/macro/run/run_unpack_online.C index fd3c46a27a..0829dda8fa 100644 --- a/macro/run/run_unpack_online.C +++ b/macro/run/run_unpack_online.C @@ -34,6 +34,7 @@ std::shared_ptr<CbmTrdUnpackMonitor> GetTrdMonitor(std::string treefilename, boo std::shared_ptr<CbmTrdSpadic> GetTrdSpadic(bool useAvgBaseline = false); std::shared_ptr<CbmStsUnpackMonitor> GetStsMonitor(std::string treefilename, bool bDebugMode = false); std::shared_ptr<CbmRichUnpackMonitor> GetRichMonitor(std::string treefilename, bool bDebugMode = false); +std::shared_ptr<CbmTofUnpackMonitor> GetTofMonitor(std::string treefilename, bool bBmonMode = false); const char* defaultSetupName = "mcbm_beam_2021_07_surveyed"; void run_unpack_online(std::vector<std::string> publisher = {"tcp://localhost:5556"}, Int_t serverHttpPort = 8080, @@ -236,16 +237,35 @@ void run_unpack_online(std::vector<std::string> publisher = {"tcp://localhost:55 tofconfig->SetDoWriteOutput(); // tofconfig->SetDoWriteOptOutA("CbmTofErrors"); std::string parfilesbasepathTof = Form("%s/macro/beamtime/mcbm2021/", srcDir.Data()); - if (2060 <= runid ) { + if (2060 <= runid) { /// Additional modules added just before the 10/03/2022 Carbon run parfilesbasepathTof = Form("%s/macro/beamtime/mcbm2022/", srcDir.Data()); } tofconfig->SetParFilesBasePath(parfilesbasepathTof); tofconfig->SetSystemTimeOffset(-1220); // [ns] value to be updated - if (runid <= 1659) { + if (runid <= 1659 && runid < 2060) { /// Switch ON the -4 offset in epoch count (hack for Spring-Summer 2021) tofconfig->SetFlagEpochCountHack2021(); } + /// Enable Monitor plots + tofconfig->SetMonitor(GetTofMonitor(outfilename, false)); + } + // ------------- + + // ---- 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 + /// Enable Monitor plots + bmonconfig->SetMonitor(GetTofMonitor(outfilename, true)); } // ------------- @@ -267,6 +287,7 @@ void run_unpack_online(std::vector<std::string> publisher = {"tcp://localhost:55 unpack->SetOutputFilename(perfProfFileName); // Enable full time sorting instead sorting per FLIM link unpack->SetTimeSorting(true); + unpack->SetMonitoringOnly(true); if (psdconfig) unpack->SetUnpackConfig(psdconfig); if (richconfig) unpack->SetUnpackConfig(richconfig); @@ -274,6 +295,7 @@ void run_unpack_online(std::vector<std::string> publisher = {"tcp://localhost:55 if (trd1Dconfig) unpack->SetUnpackConfig(trd1Dconfig); if (trdfasp2dconfig) unpack->SetUnpackConfig(trdfasp2dconfig); if (tofconfig) unpack->SetUnpackConfig(tofconfig); + if (bmonconfig) unpack->SetUnpackConfig(bmonconfig); // ------------------------------------------------------------------------ @@ -475,6 +497,49 @@ std::shared_ptr<CbmRichUnpackMonitor> GetRichMonitor(std::string treefilename, b return monitor; } +/** + * @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->SetBmonMode(bBmonMode); + return monitor; +} + void run_unpack_online(std::string publisher = "tcp://localhost:5556", Int_t serverHttpPort = 8080, Int_t serverRefreshRate = 100, std::int32_t nevents = -1, UInt_t runid = 1905, const char* setupName = defaultSetupName, std::string outpath = "data/") diff --git a/macro/run/run_unpack_online_bmon.C b/macro/run/run_unpack_online_bmon.C new file mode 100644 index 0000000000..e49ed60b6f --- /dev/null +++ b/macro/run/run_unpack_online_bmon.C @@ -0,0 +1,211 @@ +/* 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 <FairSource.h> + +#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); +const char* defaultSetupName = "mcbm_beam_2022_03_09_carbon"; + +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, + const char* setupName = defaultSetupName, std::string outpath = "data/") +{ + + // ======================================================================== + // Adjust this part according to your requirements + + // --- Logger settings ---------------------------------------------------- + TString logLevel = "INFO"; + TString logVerbosity = "LOW"; + // ------------------------------------------------------------------------ + + // ----- Environment -------------------------------------------------- + TString myName = "run_unpack_online"; // 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; + 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 ----------------------------------------------------- + auto cbmsetup = CbmSetup::Instance(); + cbmsetup->LoadSetup(setupName); + // ------------------------------------------------------------------------ + + // ----- 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 + /// Enable Monitor plots + bmonconfig->SetMonitor(GetTofMonitor(outfilename, true)); + } + // ------------- + + + // ------------------------------------------------------------------------ + + // In general, the following parts need not be touched + // ======================================================================== + + // ----- Timer -------------------------------------------------------- + TStopwatch timer; + timer.Start(); + // ------------------------------------------------------------------------ + + // ----- CbmSourceTsArchive ------------------------------------------- + auto source = new CbmSourceTsArchive(publisher); + 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); + 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) run->Run(-1, 0); + else + 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; + // ------------------------------------------------------------------------ + +} // 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->SetBmonMode(bBmonMode); + return monitor; +} + +void run_unpack_online_bmon(std::string publisher = "tcp://localhost:5556", Int_t serverHttpPort = 8080, + Int_t serverRefreshRate = 100, std::int32_t nevents = -1, UInt_t runid = 1905, + const char* setupName = defaultSetupName, std::string outpath = "data/") +{ + std::vector<std::string> vPublisher = {publisher}; + return run_unpack_online_bmon(vPublisher, serverHttpPort, serverRefreshRate, nevents, runid, setupName, outpath); +} diff --git a/macro/run/run_unpack_tsa.C b/macro/run/run_unpack_tsa.C index 5fce45051b..30f4f8d9fc 100644 --- a/macro/run/run_unpack_tsa.C +++ b/macro/run/run_unpack_tsa.C @@ -32,6 +32,7 @@ std::shared_ptr<CbmTrdUnpackMonitor> GetTrdMonitor(std::string treefilename, boo std::shared_ptr<CbmTrdSpadic> GetTrdSpadic(bool useAvgBaseline = false); std::shared_ptr<CbmStsUnpackMonitor> GetStsMonitor(std::string treefilename, bool bDebugMode = false); std::shared_ptr<CbmRichUnpackMonitor> GetRichMonitor(std::string treefilename, bool bDebugMode = false); +std::shared_ptr<CbmTofUnpackMonitor> GetTofMonitor(std::string treefilename, bool bBmonMode = false); const char* defaultSetupName = "mcbm_beam_2021_07_surveyed"; void run_unpack_tsa(std::vector<std::string> infile = {"test.tsa"}, UInt_t runid = 0, @@ -248,16 +249,35 @@ void run_unpack_tsa(std::vector<std::string> infile = {"test.tsa"}, UInt_t runid tofconfig->SetDoWriteOutput(); // tofconfig->SetDoWriteOptOutA("CbmTofErrors"); std::string parfilesbasepathTof = Form("%s/macro/beamtime/mcbm2021/", srcDir.Data()); - if (2060 <= runid ) { + if (2060 <= runid) { /// Additional modules added just before the 10/03/2022 Carbon run parfilesbasepathTof = Form("%s/macro/beamtime/mcbm2022/", srcDir.Data()); } tofconfig->SetParFilesBasePath(parfilesbasepathTof); tofconfig->SetSystemTimeOffset(-1220); // [ns] value to be updated - if (runid <= 1659) { + if (runid <= 1659 && runid < 2060) { /// Switch ON the -4 offset in epoch count (hack for Spring-Summer 2021) tofconfig->SetFlagEpochCountHack2021(); } + /// Enable Monitor plots + // tofconfig->SetMonitor(GetTofMonitor(outfilename, false)); + } + // ------------- + + // ---- 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 + /// Enable Monitor plots + // bmonconfig->SetMonitor(GetTofMonitor(outfilename, true)); } // ------------- @@ -286,8 +306,10 @@ void run_unpack_tsa(std::vector<std::string> infile = {"test.tsa"}, UInt_t runid if (trd1Dconfig) unpack->SetUnpackConfig(trd1Dconfig); if (trdfasp2dconfig) unpack->SetUnpackConfig(trdfasp2dconfig); if (tofconfig) unpack->SetUnpackConfig(tofconfig); + if (bmonconfig) unpack->SetUnpackConfig(bmonconfig); // ------------------------------------------------------------------------ + // ----- FairRunAna --------------------------------------------------- auto run = new FairRunOnline(source); auto sink = new FairRootFileSink(outfilename.data()); @@ -333,7 +355,7 @@ void run_unpack_tsa(std::vector<std::string> infile = {"test.tsa"}, UInt_t runid * @brief Get the Trd Monitor. Extra function to keep default macro part more silent. * @return std::shared_ptr<CbmTrdUnpackMonitor> */ -std::shared_ptr<CbmTrdUnpackMonitor> GetTrdMonitor(std::string treefilename, bool fasp) +std::shared_ptr<CbmTrdUnpackMonitor> GetTrdMonitor(std::string treefilename, bool fasp = false) { // ----- Output filename and path ------------------------------------- std::string outpath = ""; @@ -389,7 +411,6 @@ std::shared_ptr<CbmTrdUnpackMonitor> GetTrdMonitor(std::string treefilename, boo monitor->SetActiveHistos(digihistovec); monitor->SetWriteToFile(outfilename.data()); } - return monitor; } @@ -480,6 +501,49 @@ std::shared_ptr<CbmRichUnpackMonitor> GetRichMonitor(std::string treefilename, b return monitor; } +/** + * @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->SetBmonMode(bBmonMode); + return monitor; +} + void run_unpack_tsa(std::string infile = "test.tsa", UInt_t runid = 0, const char* setupName = defaultSetupName, std::int32_t nevents = -1, std::string outpath = "data/") { diff --git a/macro/run/run_unpack_tsa_bmon.C b/macro/run/run_unpack_tsa_bmon.C new file mode 100644 index 0000000000..57c4ecd3b7 --- /dev/null +++ b/macro/run/run_unpack_tsa_bmon.C @@ -0,0 +1,215 @@ +/* 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); +const char* defaultSetupName = "mcbm_beam_2022_03_09_carbon"; + +void run_unpack_tsa_bmon(std::vector<std::string> infile = {"test.tsa"}, UInt_t runid = 0, + const char* setupName = defaultSetupName, std::int32_t nevents = -1, + std::string outpath = "data/") +{ + + // ======================================================================== + // Adjust this part according to your requirements + + // --- Logger settings ---------------------------------------------------- + TString logLevel = "INFO"; + TString logVerbosity = "LOW"; + // ------------------------------------------------------------------------ + + // ----- Environment -------------------------------------------------- + TString myName = "run_unpack_tsa"; // this macro's name for screen output + TString srcDir = gSystem->Getenv("VMCWORKDIR"); // top source directory + // ------------------------------------------------------------------------ + + + // ----- Potentially hardcode the infile ------------------------------ + + // std::string infile = srcDir + "/input/mcbm_run399_first20Ts.tsa"; + + // ------------------------------------------------------------------------ + + + // ----- Output filename ---------------------------------------------- + std::string outfilename = infile[0]; + auto filenamepos = infile[0].find_last_of("/"); + filenamepos++; + std::string filename = infile[0].substr(filenamepos); + if (filename.find("*") != infile[0].npos) filename = std::to_string(runid) + ".tsa"; + if (filename.find(";") != infile[0].npos) filename = std::to_string(runid) + "_merged" + ".tsa"; + if (outpath.empty()) { outpath = infile[0].substr(0, filenamepos); } + outfilename = outpath + filename; + outfilename.replace(outfilename.find(".tsa"), 4, ".digi.root"); + 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(".tsa"), 4, ".perf.root"); + // ------------------------------------------------------------------------ + + + // ----- CbmSetup ----------------------------------------------------- + auto cbmsetup = CbmSetup::Instance(); + cbmsetup->LoadSetup(setupName); + // ------------------------------------------------------------------------ + + // ----- 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 + /// Enable Monitor plots + bmonconfig->SetMonitor(GetTofMonitor(outfilename, true)); + } + // ------------- + + + // ------------------------------------------------------------------------ + + // In general, the following parts need not be touched + // ======================================================================== + + // ----- Timer -------------------------------------------------------- + TStopwatch timer; + timer.Start(); + // ------------------------------------------------------------------------ + + // ----- CbmSourceTsArchive ------------------------------------------- + auto source = new CbmSourceTsArchive(infile); + auto unpack = source->GetRecoUnpack(); + unpack->SetDoPerfProfiling(doPerfProfiling); + unpack->SetOutputFilename(perfProfFileName); + // Enable full time sorting instead sorting per FLIM link + unpack->SetTimeSorting(true); + + if (bmonconfig) unpack->SetUnpackConfig(bmonconfig); + // ------------------------------------------------------------------------ + + // ----- FairRunAna --------------------------------------------------- + auto run = new FairRunOnline(source); + auto sink = new FairRootFileSink(outfilename.data()); + run->SetSink(sink); + auto eventheader = new CbmTsEventHeader(); + run->SetRunId(runid); + run->SetEventHeader(eventheader); + // ------------------------------------------------------------------------ + + + // ----- 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) run->Run(-1, 0); + else + 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; + // ------------------------------------------------------------------------ + +} // 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->SetBmonMode(bBmonMode); + return monitor; +} + +void run_unpack_tsa_bmon(std::string infile = "test.tsa", UInt_t runid = 0, const char* setupName = defaultSetupName, + std::int32_t nevents = -1, std::string outpath = "data/") +{ + std::vector<std::string> vInFile = {infile}; + return run_unpack_tsa_bmon(vInFile, runid, setupName, nevents, outpath); +} diff --git a/reco/detectors/tof/CMakeLists.txt b/reco/detectors/tof/CMakeLists.txt index 1f0b6ab60f..0d5d628b84 100644 --- a/reco/detectors/tof/CMakeLists.txt +++ b/reco/detectors/tof/CMakeLists.txt @@ -16,6 +16,7 @@ set(INCLUDE_DIRECTORIES ${CBMROOT_SOURCE_DIR}/reco/base ${CBMROOT_SOURCE_DIR}/core/eventdisplay + ${CBMROOT_SOURCE_DIR}/core/qa ${CBMROOT_SOURCE_DIR}/fles/flestools # for Timeslice/Microslice printout formatting tools ) @@ -53,6 +54,8 @@ set(SRCS unpack/CbmTofUnpackAlgo.cxx unpack/CbmTofUnpackConfig.cxx + unpack/CbmBmonUnpackConfig.cxx + unpack/CbmTofUnpackMonitor.cxx ) set(LINKDEF CbmTofRecoLinkDef.h) diff --git a/reco/detectors/tof/CbmTofRecoLinkDef.h b/reco/detectors/tof/CbmTofRecoLinkDef.h index d96636bbec..40db96c5dc 100644 --- a/reco/detectors/tof/CbmTofRecoLinkDef.h +++ b/reco/detectors/tof/CbmTofRecoLinkDef.h @@ -1,6 +1,6 @@ /* Copyright (C) 2020-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt SPDX-License-Identifier: GPL-3.0-only - Authors: Florian Uhlig [committer] */ + Authors: Pierre-Alain Loizeau, Florian Uhlig [committer] */ #ifdef __CINT__ @@ -23,5 +23,7 @@ #pragma link C++ class CbmTofUnpackAlgo + ; #pragma link C++ class CbmTofUnpackConfig + ; +#pragma link C++ class CbmBmonUnpackConfig + ; +#pragma link C++ class CbmTofUnpackMonitor + ; #endif diff --git a/reco/detectors/tof/unpack/CbmBmonUnpackConfig.cxx b/reco/detectors/tof/unpack/CbmBmonUnpackConfig.cxx new file mode 100644 index 0000000000..7bd185d252 --- /dev/null +++ b/reco/detectors/tof/unpack/CbmBmonUnpackConfig.cxx @@ -0,0 +1,50 @@ +/* Copyright (C) 2022 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +#include "CbmBmonUnpackConfig.h" + +#include "CbmTofUnpackAlgo.h" + +#include <Logger.h> + +#include <Rtypes.h> +#include <RtypesCore.h> + +#include <memory> +#include <vector> + +CbmBmonUnpackConfig::CbmBmonUnpackConfig(std::string detGeoSetupTag, UInt_t runid) + : CbmTofUnpackConfig(detGeoSetupTag, runid) +{ +} + +CbmBmonUnpackConfig::~CbmBmonUnpackConfig() {} + + +/** + * @brief Register the output vectors (if needed) to the FairRoot Manager) + * FIXME: To be removed with the Manager include whenever the similar code in the CbmRecoUnpack task work as expected + * +*/ +void CbmBmonUnpackConfig::RegisterOutput(FairRootManager* ioman) +{ + if (fDoWriteOutput && fOutputVec) { + /// Instance of TOF unpacker used for Bmon unpacking + ioman->RegisterAny("T0Digi", fOutputVec, kTRUE); + LOG(info) << fName << "::registerBranchToTree(CbmBmonDigi)"; + } + + /** @todo for the optional outputs it is more complicated to check if they exist. Needs exceptions for the std::nullptr_t. Should be added at some point in time. */ + if (fDoWriteOptOutA && fOptOutAVec) { + ioman->RegisterAny(fOptoutABranchName.data(), fOptOutAVec, kTRUE); + LOG(info) << fName << "::registerBranchToTree(" << fOptoutABranchName.data() << ")"; + } + + if (fDoWriteOptOutB && fOptOutBVec) { + ioman->RegisterAny(fOptoutBBranchName.data(), fOptOutBVec, kTRUE); + LOG(info) << fName << "::registerBranchToTree(" << fOptoutBBranchName.data() << ")"; + } +} + +ClassImp(CbmBmonUnpackConfig) diff --git a/reco/detectors/tof/unpack/CbmBmonUnpackConfig.h b/reco/detectors/tof/unpack/CbmBmonUnpackConfig.h new file mode 100644 index 0000000000..5d1f2ff028 --- /dev/null +++ b/reco/detectors/tof/unpack/CbmBmonUnpackConfig.h @@ -0,0 +1,78 @@ +/* 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 CbmBmonUnpackConfig.h + * @author Pascal Raisig (praisig@ikf.uni-frankfurt.de) + * @brief Configuration class for an unpacker algorithm + * @version 0.1 + * @date 2021-04-21 + * + * @copyright Copyright (c) 2021 + * + * This is the common configuration class for unpacking algorithms + * +*/ + +#ifndef CbmBmonUnpackConfig_H +#define CbmBmonUnpackConfig_H + +#include "CbmErrorMessage.h" +#include "CbmTofDigi.h" +#include "CbmTofUnpackAlgo.h" +#include "CbmTofUnpackConfig.h" + +#include <FairLogger.h> +#include <Logger.h> + +#include <Rtypes.h> +#include <RtypesCore.h> + +#include <cstddef> +#include <cstdint> +#include <memory> +#include <vector> + +class CbmBmonUnpackConfig : public CbmTofUnpackConfig { + +public: + /** + * @brief Create the Cbm Tof Unpack Task object + * + * @param geoSetupTag Geometry setup tag for the given detector as used by CbmSetup objects + * @param runid set if unpacker is rerun on a special run with special parameters + *@remark We use the string instead of CbmSetup here, to not having to link against sim/steer... + */ + CbmBmonUnpackConfig(std::string detGeoSetupTag, UInt_t runid = 0); + + /** + * @brief Destroy the Cbm Tof Unpack Task object + * + */ + virtual ~CbmBmonUnpackConfig(); + + /** @brief Copy constructor - not implemented **/ + CbmBmonUnpackConfig(const CbmBmonUnpackConfig&) = delete; + + /** @brief Assignment operator - not implemented **/ + CbmBmonUnpackConfig& operator=(const CbmBmonUnpackConfig&) = delete; + + // Getters + + /** + * @brief Register the output vectors (if needed) to the FairRoot Manager) + * FIXME: To be removed when the T0/BMON will have its own Digi class properly exposing the right container name + * + */ + void RegisterOutput(FairRootManager* ioman); + + + // Setters + +protected: +private: + ClassDef(CbmBmonUnpackConfig, 1) +}; + +#endif // CbmBmonUnpackConfig_H diff --git a/reco/detectors/tof/unpack/CbmTofUnpackAlgo.cxx b/reco/detectors/tof/unpack/CbmTofUnpackAlgo.cxx index 9028346435..eb250a654f 100644 --- a/reco/detectors/tof/unpack/CbmTofUnpackAlgo.cxx +++ b/reco/detectors/tof/unpack/CbmTofUnpackAlgo.cxx @@ -1,6 +1,6 @@ /* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt SPDX-License-Identifier: GPL-3.0-only - Authors: Pascal Raisig [committer] */ + Authors: Pierre-Alain Loizeau, Pascal Raisig [committer] */ #include "CbmTofUnpackAlgo.h" @@ -30,7 +30,7 @@ std::vector<std::pair<std::string, std::shared_ptr<FairParGenericSet>>>* std::string temppath = ""; // // Get parameter container - temppath = basepath + "mTofCriPar.par"; + temppath = basepath + fParFileName; LOG(info) << fName << "::GetParContainerRequest - Trying to open file " << temppath; fParContVec.emplace_back(std::make_pair(temppath, std::make_shared<CbmMcbm2018TofPar>())); @@ -93,17 +93,6 @@ Bool_t CbmTofUnpackAlgo::initParSet(CbmMcbm2018TofPar* parset) fuNrOfGbtx = parset->GetNrOfGbtx(); LOG(debug) << "Nr. of GBTx: " << fuNrOfGbtx; - fviRpcType.resize(fuNrOfGbtx); - fviModuleId.resize(fuNrOfGbtx); - fviNrOfRpc.resize(fuNrOfGbtx); - fviRpcSide.resize(fuNrOfGbtx); - for (UInt_t uGbtx = 0; uGbtx < fuNrOfGbtx; ++uGbtx) { - fviNrOfRpc[uGbtx] = parset->GetNrOfRpc(uGbtx); - fviRpcType[uGbtx] = parset->GetRpcType(uGbtx); - fviRpcSide[uGbtx] = parset->GetRpcSide(uGbtx); - fviModuleId[uGbtx] = parset->GetModuleId(uGbtx); - } // for( UInt_t uGbtx = 0; uGbtx < fuNrOfGbtx; ++uGbtx) - UInt_t uNrOfChannels = fuNrOfGet4 * fuNrOfChannelsPerGet4; LOG(debug) << "Nr. of possible Tof channels: " << uNrOfChannels; @@ -114,12 +103,24 @@ Bool_t CbmTofUnpackAlgo::initParSet(CbmMcbm2018TofPar* parset) for (UInt_t uCh = 0; uCh < uNrOfChannels; ++uCh) { if (0 == uCh % 8) sPrintout += "\n"; if (0 == uCh % fuNrOfChannelsPerGdpb) sPrintout += Form("\n Gdpb %u\n", uCh / fuNrOfChannelsPerGdpb); - sPrintout += Form(" 0x%08x", fviRpcChUId[uCh]); + if (0 == fviRpcChUId[uCh]) { + /// Tricking clang to avoid one liner + sPrintout += " ----------"; + } + else { + sPrintout += Form(" 0x%08x", fviRpcChUId[uCh]); + } } // for( UInt_t i = 0; i < uNrOfChannels; ++i) - LOG(debug) << sPrintout; + LOG(info) << sPrintout; LOG(info) << fName << "::initParSetTofMcbm2018 - Successfully initialized TOF settings"; + if (fMonitor) { + fMonitor->Init(parset); + LOG(info) << fName << "::initParSetTofMcbm2018 - Successfully initialized TOF monitor"; + } + + return kTRUE; } @@ -132,6 +133,7 @@ bool CbmTofUnpackAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UI fulCurrentTsIdx = ts->index(); uint32_t uSize = msDescriptor.size; fulCurrentMsIdx = msDescriptor.idx; + fdCurrentMsTime = (1e-9) * static_cast<double>(fulCurrentMsIdx); // Double_t dMsTime = (1e-9) * static_cast<double>(fulCurrentMsIdx); LOG(debug) << "Microslice: " << fulCurrentMsIdx << " from EqId " << std::hex << fuCurrentEquipmentId << std::dec << " has size: " << uSize; @@ -164,6 +166,13 @@ bool CbmTofUnpackAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UI fuCurrentMsSysId = static_cast<unsigned int>(msDescriptor.sys_id); + if (fMonitor) { + if (0x90 == fuCurrentMsSysId) { + /// Tricking clang to avoid one liner + fMonitor->CheckBmonSpillLimits(fdCurrentMsTime); + } + } + // If not integer number of message in input buffer, print warning/error if (0 != (uSize % sizeof(critof001::Message))) LOG(error) << fName << "::unpack => " @@ -252,10 +261,31 @@ bool CbmTofUnpackAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UI } // if single chip epoch message break; } // case critof001::MSG_EPOCH: - case critof001::MSG_SLOWC: + case critof001::MSG_SLOWC: { + /// Ignored messages + /// TODO,FIXME: should be filled into fOptOutAVec as CbmErrorMessage + if (fMonitor) { + fMonitor->FillScmMonitoringHistos(fuCurrDpbIdx, fuGet4Id, pMess[uIdx].getGdpbSlcChan(), + pMess[uIdx].getGdpbSlcEdge(), pMess[uIdx].getGdpbSlcType()); + } + break; + } // case critof001::MSG_SLOWC: case critof001::MSG_SYST: { /// Ignored messages /// TODO,FIXME: should be filled into fOptOutAVec as CbmErrorMessage + if (fMonitor) { + fMonitor->FillSysMonitoringHistos(fuCurrDpbIdx, fuGet4Id, pMess[uIdx].getGdpbSysSubType()); + if (critof001::SYS_GET4_ERROR == pMess[uIdx].getGdpbSysSubType()) { + fMonitor->FillErrMonitoringHistos(fuCurrDpbIdx, fuGet4Id, pMess[uIdx].getGdpbSysErrChanId(), + pMess[uIdx].getGdpbSysErrData()); + + if (90 == fuCurrentMsSysId) { + fMonitor->FillErrBmonMonitoringHistos(fdCurrentMsTime, fuCurrDpbIdx, fuGet4Id, + critof001::GET4_V2X_ERR_LOST_EVT + == pMess[uIdx].getGdpbSysErrData()); + } // if (90 == fuCurrentMsSysId) + } // if (critof001::SYS_GET4_ERROR == pMess[uIdx].getGdpbSysSubType()) + } // if (fMonitor ) break; } // case critof001::MSG_ERROR default: @@ -264,7 +294,11 @@ bool CbmTofUnpackAlgo::unpack(const fles::Timeslice* ts, std::uint16_t icomp, UI << " not included in Get4 unpacker."; } // switch( mess.getMessageType() ) } // for (uint32_t uIdx = 0; uIdx < uNbMessages; uIdx ++) - + /* + if (0x90 == fuCurrentMsSysId && 0xabf3 == fuCurrDpbId) { + LOG(fatal) << "Last T0, stop there"; + } +*/ return true; } @@ -275,18 +309,17 @@ void CbmTofUnpackAlgo::ExtractTsStartEpoch(const uint64_t& ulTsStart) /// FIXME: seems there is an offset of +4 Epoch between data and header /// from dt to PSD, the epoch seem to be right => placed in wrong MS! - if (fulTsStartInEpoch < 4) { fulTsStartInEpoch = critof001::kulEpochCycleEp + fulTsStartInEpoch - 4; } - else { - fulTsStartInEpoch -= 4; - } + if (fbEpochCountHack2021) { + if (fulTsStartInEpoch < 4) { fulTsStartInEpoch = critof001::kulEpochCycleEp + fulTsStartInEpoch - 4; } + else { + fulTsStartInEpoch -= 4; + } + } // if (fbEpochCountHack2021) } void CbmTofUnpackAlgo::ProcessEpoch(const critof001::Message& mess, uint32_t uMesgIdx) { - /// FIXME: seems there is an offset of +4 Epoch between data and header - /// from dt to PSD, the epoch seem to be right => placed in wrong MS! ULong64_t ulEpochNr = mess.getGdpbEpEpochNb(); - //ULong64_t ulEpochNr = (mess.getGdpbEpEpochNb() + 4) % critof001::kulEpochCycleEp; if (0 == uMesgIdx) { uint64_t ulMsStartInEpoch = @@ -310,7 +343,7 @@ void CbmTofUnpackAlgo::ProcessEpoch(const critof001::Message& mess, uint32_t uMe static_cast<unsigned long long int>(mess.getData()), fuProcEpochUntilError, static_cast<size_t>(fulCurrentMsIdx / critof001::kuEpochInNs), fulCurrentMsIdx / critof001::kuEpochInNs); - LOG(error) << fName << "::ProcessEpoch => Ignoring data until next valid epoch"; + LOG(fatal) << fName << "::ProcessEpoch => Stopping there, system is not synchronized and send corrupt data"; fbLastEpochGood = false; ulEpochNr = ulMsStartInEpoch; @@ -323,9 +356,11 @@ void CbmTofUnpackAlgo::ProcessEpoch(const critof001::Message& mess, uint32_t uMe } // if( 0 < uMesgIdx ) else if (((fulCurrentEpoch + 1) % critof001::kulEpochCycleEp) != ulEpochNr) { // Cast required to silence a warning on macos (there a uint64_t is a llu) - LOG(error) << fName << "::ProcessEpoch => Error global epoch, " - << Form("last 0x%06llx, current 0x%06llx, diff %lld, raw 0x%016lx, NoErr %d", fulCurrentEpoch, ulEpochNr, - ulEpochNr - fulCurrentEpoch, static_cast<size_t>(mess.getData()), fuProcEpochUntilError); + LOG(error) << fName << "::ProcessEpoch => Error global epoch, DPB 0x" << std::setw(4) << std::hex << fuCurrDpbId + << std::dec + << Form(" last 0x%06llx, current 0x%06llx, diff %lld, raw 0x%016lx, NoErr %d", fulCurrentEpoch, + ulEpochNr, ulEpochNr - fulCurrentEpoch, static_cast<size_t>(mess.getData()), + fuProcEpochUntilError); LOG(error) << fName << "::ProcessEpoch => Ignoring data until next valid epoch"; ulEpochNr = (fulCurrentEpoch + 1) % critof001::kulEpochCycleEp; @@ -342,13 +377,19 @@ void CbmTofUnpackAlgo::ProcessEpoch(const critof001::Message& mess, uint32_t uMe else { fulEpochIndexInTs = ulEpochNr + critof001::kulEpochCycleEp - fulTsStartInEpoch; } - if (10e9 < critof001::kuEpochInNs * fulEpochIndexInTs) + if (10e9 < critof001::kuEpochInNs * fulEpochIndexInTs) { // Cast required to silence a warning on macos (there a uint64_t is a llu) LOG(debug) << fName << "::ProcessEpoch => " << Form("Raw Epoch: 0x%06llx, Epoch offset 0x%06llx, Epoch in Ts: 0x%07lx, time %f ns (%f * %lu)", ulEpochNr, static_cast<long long unsigned int>(fulTsStartInEpoch), static_cast<size_t>(fulEpochIndexInTs), critof001::kuEpochInNs * fulEpochIndexInTs, critof001::kuEpochInNs, static_cast<size_t>(fulEpochIndexInTs)); + } + + if (fMonitor) { + fMonitor->FillEpochMonitoringHistos(fuCurrDpbIdx, fuGet4Id, mess.getGdpbEpSync(), mess.getGdpbEpDataLoss(), + mess.getGdpbEpEpochLoss(), mess.getGdpbEpMissmatch()); + } } void CbmTofUnpackAlgo::ProcessHit(const critof001::Message& mess) @@ -360,19 +401,40 @@ void CbmTofUnpackAlgo::ProcessHit(const critof001::Message& mess) UInt_t uChannelNrInFee = (fuGet4Id % fuNrOfGet4PerFee) * fuNrOfChannelsPerGet4 + uChannel; UInt_t uFeeNr = (fuGet4Id / fuNrOfGet4PerFee); UInt_t uFeeNrInSys = fuCurrDpbIdx * fuNrOfFeePerGdpb + uFeeNr; - // UInt_t uRemappedChannelNr = uFeeNr * fuNrOfChannelsPerFee + fUnpackPar->Get4ChanToPadiChan(uChannelNrInFee); + UInt_t uRemappedChannelNr = uFeeNr * fuNrOfChannelsPerFee + fUnpackPar->Get4ChanToPadiChan(uChannelNrInFee); UInt_t uRemappedChannelNrInSys = fuCurrDpbIdx * fuNrOfChannelsPerGdpb + uFeeNr * fuNrOfChannelsPerFee + fUnpackPar->Get4ChanToPadiChan(uChannelNrInFee); /// Diamond FEE have straight connection from Get4 to eLink and from PADI to GET4 if (0x90 == fuCurrentMsSysId) { - // uRemappedChannelNr = uChannelNr; - uRemappedChannelNrInSys = fuCurrDpbIdx * fUnpackPar->GetNrOfChannelsPerGdpb() + uChannelNr; + uRemappedChannelNr = uChannelNr; + uRemappedChannelNrInSys = fuCurrDpbIdx * fuNrOfChannelsPerGdpb + uChannelNr; } // if(0x90 == fuCurrentMsSysId) Double_t dHitTime = mess.getMsgFullTimeD(fulEpochIndexInTs); Double_t dHitTot = uTot; // in bins + if (fMonitor) { + fMonitor->FillHitMonitoringHistos(fdCurrentMsTime, fuCurrDpbIdx, fuGet4Id, uChannelNr, uRemappedChannelNr, uTot); + if (0x90 == fuCurrentMsSysId && 0 == uChannel) { + fMonitor->FillHitBmonMonitoringHistos(fdCurrentMsTime, fuCurrDpbIdx, fuGet4Id, uTot); + } + } + + /// Diamond debug + if (0x90 == fuCurrentMsSysId) { + LOG(debug) << fName << "::unpack => " + << "T0 data item at " << std::setw(4) << uRemappedChannelNrInSys << ", from FLIM " << fuCurrDpbIdx + << ", Get4 " << std::setw(2) << fuGet4Id << ", Ch " << uChannel << ", ChNr " << std::setw(2) + << uChannelNr << ", ChNrIF " << std::setw(2) << uChannelNrInFee << ", FiS " << std::setw(2) + << uFeeNrInSys + << (fviRpcChUId.size() < uRemappedChannelNrInSys || 0 == fviRpcChUId[uRemappedChannelNrInSys] + ? " ----------" + : Form(" 0x%08x", fviRpcChUId[uRemappedChannelNrInSys])) + << " TOT " << std::setw(3) << uTot << " time " << dHitTime; + // return; + } // if(0x90 == fuCurrentMsSysId) + if (fviRpcChUId.size() < uRemappedChannelNrInSys) { LOG(fatal) << fName << "::unpack => " << "Invalid mapping index " << uRemappedChannelNrInSys << " VS " << fviRpcChUId.size() << ", from FLIM " @@ -385,10 +447,10 @@ void CbmTofUnpackAlgo::ProcessHit(const critof001::Message& mess) if (0 == uChanUId) { if (0 < fuMapWarnToPrint--) - LOG(warning) << fName << "::unpack => " - << "Unused data item at " << uRemappedChannelNrInSys << ", from FLIM " << fuCurrDpbIdx << ", Get4 " - << fuGet4Id << ", Ch " << uChannel << ", ChNr " << uChannelNr << ", ChNrIF " << uChannelNrInFee - << ", FiS " << uFeeNrInSys; + LOG(debug) << fName << "::unpack => " + << "Unused data item at " << uRemappedChannelNrInSys << ", from FLIM " << fuCurrDpbIdx << ", Get4 " + << fuGet4Id << ", Ch " << uChannel << ", ChNr " << uChannelNr << ", ChNrIF " << uChannelNrInFee + << ", FiS " << uFeeNrInSys; return; // Hit not mapped to digi } @@ -398,9 +460,11 @@ void CbmTofUnpackAlgo::ProcessHit(const critof001::Message& mess) dHitTime -= fSystemTimeOffset; } - /// FIXME: seems there is an offset of +4 Epoch between data and header - /// from dt to PSD, the epoch are probably the one off, not the MS time! - dHitTime -= 4.0 * critof001::kuEpochInNs; + if (fbEpochCountHack2021) { + /// FIXME: seems there is an offset of +4 Epoch between data and header + /// from dt to PSD, the epoch are probably the one off, not the MS time! + dHitTime -= 4.0 * critof001::kuEpochInNs; + } LOG(debug) << Form("Insert 0x%08x digi with time ", uChanUId) << dHitTime << Form(", Tot %4.0f", dHitTot) << " at epoch " << fulEpochIndexInTs; diff --git a/reco/detectors/tof/unpack/CbmTofUnpackAlgo.h b/reco/detectors/tof/unpack/CbmTofUnpackAlgo.h index 4f30f574e7..5d67958d9f 100644 --- a/reco/detectors/tof/unpack/CbmTofUnpackAlgo.h +++ b/reco/detectors/tof/unpack/CbmTofUnpackAlgo.h @@ -1,6 +1,6 @@ /* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt SPDX-License-Identifier: GPL-3.0-only - Authors: Pascal Raisig [committer] */ + Authors: Pierre-Alain Loizeau, Pascal Raisig [committer] */ /** * @file CbmTofUnpackAlgo.h @@ -25,6 +25,7 @@ #include "CbmMcbm2018TofPar.h" #include "CbmRecoUnpackAlgo.tmpl" #include "CbmTofDigi.h" +#include "CbmTofUnpackMonitor.h" #include "Timeslice.hpp" // timeslice @@ -71,13 +72,26 @@ public: */ void SetFlagEpochCountHack2021(bool bFlagin = true) { fbEpochCountHack2021 = bFlagin; } + /** + * @brief Sets the name of the parameter file to be used. + * + * @param[in] std:string, path should not be included as set in the Config class + */ + void SetParFileName(std::string sNewName) { fParFileName = sNewName; } + + /** @brief Set a predefined monitor @param monitor predefined unpacking monitor */ + void SetMonitor(std::shared_ptr<CbmTofUnpackMonitor> monitor) { fMonitor = monitor; } + protected: /** @brief Finish function for this algorithm base clase */ void finish() { finishDerived(); // Finish the monitor if we have one - // if (fMonitor) fMonitor->Finish(); + if (fMonitor) { + std::cout << "Finish Monitor" << std::endl; + fMonitor->Finish(); + } } /** @brief Function that allows special calls during Finish in the derived algos */ @@ -144,6 +158,7 @@ private: /// Settings from parameter file + std::string fParFileName = "mTofCriPar.par"; CbmMcbm2018TofPar* fUnpackPar = nullptr; //! For static/inline mapping functions /// Readout chain dimensions and mapping @@ -160,20 +175,17 @@ private: /// Detector Mapping UInt_t fuNrOfGbtx = 0; UInt_t fuNrOfModules = 0; - std::vector<Int_t> fviNrOfRpc = {}; - std::vector<Int_t> fviRpcType = {}; - std::vector<Int_t> fviRpcSide = {}; - std::vector<Int_t> fviModuleId = {}; std::vector<Int_t> fviRpcChUId = {}; /// Running indices UInt_t fuMapWarnToPrint = 100; - ULong64_t fulCurrentTsIdx = 0; //! Idx of the current TS - ULong64_t fulCurrentMsIdx = 0; //! Idx of the current MS in TS (0 to fuTotalMsNb) - size_t fuCurrentMsSysId = 0; //! SysId of the current MS in TS (0 to fuTotalMsNb) - UInt_t fuCurrentEquipmentId = 0; //! Current equipment ID, tells from which DPB the current MS is originating - UInt_t fuCurrDpbId = 0; //! Temp holder until Current equipment ID is properly filled in MS - UInt_t fuCurrDpbIdx = 0; //! Index of the DPB from which the MS currently unpacked is coming + ULong64_t fulCurrentTsIdx = 0; //! Idx of the current TS + ULong64_t fulCurrentMsIdx = 0; //! Idx of the current MS in TS (0 to fuTotalMsNb) + double fdCurrentMsTime = 0.0; //! Time of the current MS in s + size_t fuCurrentMsSysId = 0; //! SysId of the current MS in TS (0 to fuTotalMsNb) + UInt_t fuCurrentEquipmentId = 0; //! Current equipment ID, tells from which DPB the current MS is originating + UInt_t fuCurrDpbId = 0; //! Temp holder until Current equipment ID is properly filled in MS + UInt_t fuCurrDpbIdx = 0; //! Index of the DPB from which the MS currently unpacked is coming UInt_t fuGet4Id = 0; //! running number (0 to fuNrOfGet4PerGdpb) of the Get4 chip of a unique GDPB for current message UInt_t fuGet4Nr = 0; //! running number (0 to fuNrOfGet4) of the Get4 chip in the system for current message @@ -190,6 +202,9 @@ private: uint64_t fulTsStartInEpoch = 0; uint64_t fulEpochIndexInTs = 0; + /** @brief Potential (online) monitor for the unpacking process */ + std::shared_ptr<CbmTofUnpackMonitor> fMonitor = nullptr; + ClassDef(CbmTofUnpackAlgo, 2) }; diff --git a/reco/detectors/tof/unpack/CbmTofUnpackConfig.cxx b/reco/detectors/tof/unpack/CbmTofUnpackConfig.cxx index 92820a8e1e..a646cb8108 100644 --- a/reco/detectors/tof/unpack/CbmTofUnpackConfig.cxx +++ b/reco/detectors/tof/unpack/CbmTofUnpackConfig.cxx @@ -1,6 +1,6 @@ /* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt SPDX-License-Identifier: GPL-3.0-only - Authors: Pascal Raisig [committer] */ + Authors: Pierre-Alain Loizeau, Pascal Raisig [committer] */ #include "CbmTofUnpackConfig.h" @@ -26,6 +26,8 @@ void CbmTofUnpackConfig::InitAlgo() { fAlgo->SetFlagEpochCountHack2021(fbEpochCountHack2021); + if (fMonitor) { fAlgo->SetMonitor(fMonitor); } + // Now we have all information required to initialise the algorithm fAlgo->Init(); } diff --git a/reco/detectors/tof/unpack/CbmTofUnpackConfig.h b/reco/detectors/tof/unpack/CbmTofUnpackConfig.h index c99e16ae09..d6bb8313c9 100644 --- a/reco/detectors/tof/unpack/CbmTofUnpackConfig.h +++ b/reco/detectors/tof/unpack/CbmTofUnpackConfig.h @@ -1,6 +1,6 @@ /* Copyright (C) 2021 Goethe-University Frankfurt, Frankfurt SPDX-License-Identifier: GPL-3.0-only - Authors: Pascal Raisig [committer] */ + Authors: Pierre-Alain Loizeau, Pascal Raisig [committer] */ /** * @file CbmTofUnpackConfig.h @@ -22,6 +22,7 @@ #include "CbmRecoUnpackConfig.tmpl" #include "CbmTofDigi.h" #include "CbmTofUnpackAlgo.h" +#include "CbmTofUnpackMonitor.h" #include <FairLogger.h> #include <Logger.h> @@ -75,6 +76,17 @@ public: */ void SetFlagEpochCountHack2021(bool bFlagin = true) { fbEpochCountHack2021 = bFlagin; } + /** + * @brief Sets the name of the parameter file to be used. + * + * @param[in] std:string, path should not be included as set in the Config class + */ + void SetParFileName(std::string sNewName) { fsParFileName = sNewName; } + void LoadParFileName() { fAlgo->SetParFileName(fsParFileName); } + + /** @brief Add a monitor to the unpacker. @param value CbmStsUnpackMonitor */ + void SetMonitor(std::shared_ptr<CbmTofUnpackMonitor> value) { fMonitor = value; } + protected: /** * @brief Choose the derived unpacker algorithm to be used for the DAQ output to Digi translation. If algo was already set manually by the user this algorithm is used. @@ -86,8 +98,13 @@ protected: private: /// Control flags bool fbEpochCountHack2021 = false; + /// Parameter file name + std::string fsParFileName = "mTofCriPar.par"; + + /** @brief pointer to the monitor object */ + std::shared_ptr<CbmTofUnpackMonitor> fMonitor = nullptr; - ClassDef(CbmTofUnpackConfig, 2) + ClassDef(CbmTofUnpackConfig, 3) }; #endif // CbmTofUnpackConfig_H diff --git a/reco/detectors/tof/unpack/CbmTofUnpackMonitor.cxx b/reco/detectors/tof/unpack/CbmTofUnpackMonitor.cxx new file mode 100644 index 0000000000..a2879d9faa --- /dev/null +++ b/reco/detectors/tof/unpack/CbmTofUnpackMonitor.cxx @@ -0,0 +1,1393 @@ +/* Copyright (C) 2022 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +#include "CbmTofUnpackMonitor.h" + +#include "CbmFlesHistosTools.h" + +#include "MicrosliceDescriptor.hpp" + +#include <FairRun.h> +#include <FairRunOnline.h> +#include <Logger.h> + +#include "TCanvas.h" +#include <RtypesCore.h> +#include <TFile.h> +#include <TH1.h> +#include <TH2.h> +#include <THttpServer.h> +#include <TPaveStats.h> +#include <TProfile.h> + +#include <cstdint> +#include <iomanip> +#include <iostream> +#include <memory> +#include <string> +#include <vector> + +#include <cmath> + +#include "CriGet4Mess001.h" + +CbmTofUnpackMonitor::CbmTofUnpackMonitor(/* args */) : fvpAllHistoPointers() +{ + // Miscroslice component properties histos + for (UInt_t component = 0; component < kuMaxNbFlibLinks; component++) { + fvhMsSize[component] = nullptr; + fvhMsSizeTime[component] = nullptr; + } +} + +CbmTofUnpackMonitor::~CbmTofUnpackMonitor() +{ + for (auto iter = fvpAllHistoPointers.begin(); iter != fvpAllHistoPointers.end();) { + if (iter->first != nullptr) { delete iter->first; } + iter = fvpAllHistoPointers.erase(iter); + } + for (auto iter = fvpAllCanvasPointers.begin(); iter != fvpAllCanvasPointers.end();) { + if (iter->first != nullptr) { delete iter->first; } + iter = fvpAllCanvasPointers.erase(iter); + } +} + +Bool_t CbmTofUnpackMonitor::CreateHistograms() +{ + /// Avoid name collision for the histos and canvases in Root memory + std::string sSystem = "tof"; + if (fBmonMode) { + // + sSystem = "bmon"; + } + + // clang-format off + fhGet4MessType = new TH2I(Form("%sGet4MessType", sSystem.data()), + "Nb of message for each type per GET4; GET4 chip # ; Type", + fuNbOfGet4InSyst, 0., fuNbOfGet4InSyst, + 4, 0., 4.); + fhGet4MessType->GetYaxis()->SetBinLabel(1, "DATA 32b"); + fhGet4MessType->GetYaxis()->SetBinLabel(2, "EPOCH"); + fhGet4MessType->GetYaxis()->SetBinLabel(3, "S.C.M"); + fhGet4MessType->GetYaxis()->SetBinLabel(4, "ERROR"); + // fhGet4MessType->GetYaxis()->SetBinLabel( 5, "DATA 24b"); + // fhGet4MessType->GetYaxis()->SetBinLabel( 6, "STAR Trigger"); + + fhGet4EpochFlags = new TH2I(Form("%sGet4EpochFlags", sSystem.data()), + "Epoch flags per GET4; GET4 chip # ; Type", + fuNbOfGet4InSyst, 0., fuNbOfGet4InSyst, + 4, 0., 4.); + fhGet4EpochFlags->GetYaxis()->SetBinLabel(1, "SYNC"); + fhGet4EpochFlags->GetYaxis()->SetBinLabel(2, "Ep LOSS"); + fhGet4EpochFlags->GetYaxis()->SetBinLabel(3, "Da LOSS"); + fhGet4EpochFlags->GetYaxis()->SetBinLabel(4, "MISSMAT"); + + fhGet4ScmType = new TH2I(Form("%sGet4ScmType", sSystem.data()), + "SC messages per GET4 channel; GET4 channel # ; SC type", + fuNbOfGet4InSyst, 0., fuNbOfGet4InSyst, + 5, 0., 5.); + fhGet4ScmType->GetYaxis()->SetBinLabel(1, "Hit Scal"); + fhGet4ScmType->GetYaxis()->SetBinLabel(2, "Deadtime"); + fhGet4ScmType->GetYaxis()->SetBinLabel(3, "SPI"); + fhGet4ScmType->GetYaxis()->SetBinLabel(4, "SEU Scal"); + fhGet4ScmType->GetYaxis()->SetBinLabel(5, "START"); + + fhGet4SysMessType = new TH2I(Form("%sGet4SysMessType", sSystem.data()), + "Nb of system message for each type per Get4; Get4; System Type", + fuNbOfGet4InSyst, 0., fuNbOfGet4InSyst, + 1 + critof001::SYS_PATTERN, 0., 1 + critof001::SYS_PATTERN); + fhGet4SysMessType->GetYaxis()->SetBinLabel(1 + critof001::SYS_GET4_ERROR, "GET4 ERROR"); + fhGet4SysMessType->GetYaxis()->SetBinLabel(1 + critof001::SYS_GDPB_UNKWN, "UNKW GET4 MSG"); + fhGet4SysMessType->GetYaxis()->SetBinLabel(1 + critof001::SYS_GET4_SYNC_MISS, "SYS_GET4_SYNC_MISS"); + fhGet4SysMessType->GetYaxis()->SetBinLabel(1 + critof001::SYS_PATTERN, "SYS_PATTERN"); + + fhGet4ErrorsType = new TH2I(Form("%sGet4ErrorsType", sSystem.data()), + "Error messages per GET4 channel; GET4 channel # ; Error", + fuNbOfGet4InSyst, 0., fuNbOfGet4InSyst, + 22, 0., 22.); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(1, "0x00: Readout Init "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(2, "0x01: Sync "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(3, "0x02: Epoch count sync"); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(4, "0x03: Epoch "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(5, "0x04: FIFO Write "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(6, "0x05: Lost event "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(7, "0x06: Channel state "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(8, "0x07: Token Ring state"); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(9, "0x08: Token "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(10, "0x09: Error Readout "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(11, "0x0a: SPI "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(12, "0x0b: DLL Lock error "); // <- From GET4 v1.2 + fhGet4ErrorsType->GetYaxis()->SetBinLabel(13, "0x0c: DLL Reset invoc."); // <- From GET4 v1.2 + fhGet4ErrorsType->GetYaxis()->SetBinLabel(14, "0x11: Overwrite "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(15, "0x12: ToT out of range"); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(16, "0x13: Event Discarded "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(17, "0x14: Add. Rising edge"); // <- From GET4 v1.3 + fhGet4ErrorsType->GetYaxis()->SetBinLabel(18, "0x15: Unpaired Falling"); // <- From GET4 v1.3 + fhGet4ErrorsType->GetYaxis()->SetBinLabel(19, "0x16: Sequence error "); // <- From GET4 v1.3 + fhGet4ErrorsType->GetYaxis()->SetBinLabel(20, "0x7f: Unknown "); + fhGet4ErrorsType->GetYaxis()->SetBinLabel(21, "Corrupt/unsuprtd error"); + + /// Add pointers to the vector with all histo for access by steering class + std::string sFolder = "Get4InSys"; + AddHistoToVector(fhGet4MessType, sFolder); + AddHistoToVector(fhGet4EpochFlags, sFolder); + AddHistoToVector(fhGet4ScmType, sFolder); + AddHistoToVector(fhGet4SysMessType, sFolder); + AddHistoToVector(fhGet4ErrorsType, sFolder); + + for (UInt_t uComp = 0; uComp < fuNbOfComps; ++uComp) { + UInt_t uCompIndex = uComp; + + std::string sFolderComp = Form("c%02u", uCompIndex); + + /// ---> Per GET4 in Component + fvhCompGet4MessType.push_back( + new TH2I(Form("%sCompGet4MessType_c%02u", sSystem.data(), uComp), + Form("Nb of message for each type per GET4 in Comp %02u; GET4 chip # ; Type", uCompIndex), + fuNbOfGet4PerComp, 0., fuNbOfGet4PerComp, + 4, 0., 4.)); + fvhCompGet4MessType[uComp]->GetYaxis()->SetBinLabel(1, "DATA 32b"); + fvhCompGet4MessType[uComp]->GetYaxis()->SetBinLabel(2, "EPOCH"); + fvhCompGet4MessType[uComp]->GetYaxis()->SetBinLabel(3, "S.C. M"); + fvhCompGet4MessType[uComp]->GetYaxis()->SetBinLabel(4, "ERROR"); + + fvhCompGet4ChScm.push_back( + new TH2I(Form("%sCompGet4ChanScm_c%02u", sSystem.data(), uComp), + Form("SC messages per GET4 channel in Comp %02u; GET4 channel # ; SC type", uCompIndex), + 2 * fuNbOfChannelsPerComp, 0., fuNbOfChannelsPerComp, + 5, 0., 5.)); + fvhCompGet4ChScm[uComp]->GetYaxis()->SetBinLabel(1, "Hit Scal"); + fvhCompGet4ChScm[uComp]->GetYaxis()->SetBinLabel(2, "Deadtime"); + fvhCompGet4ChScm[uComp]->GetYaxis()->SetBinLabel(3, "SPI"); + fvhCompGet4ChScm[uComp]->GetYaxis()->SetBinLabel(4, "SEU Scal"); + fvhCompGet4ChScm[uComp]->GetYaxis()->SetBinLabel(5, "START"); + + fvhCompGet4ChErrors.push_back( + new TH2I(Form("%sCompGet4ChanErrors_c%02u", sSystem.data(), uComp), + Form("Error messages per GET4 channel in Comp %02u; GET4 channel # ; Error", uCompIndex), + fuNbOfChannelsPerComp, 0., fuNbOfChannelsPerComp, + 22, 0., 22.)); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(1, "0x00: Readout Init "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(2, "0x01: Sync "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(3, "0x02: Epoch count sync"); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(4, "0x03: Epoch "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(5, "0x04: FIFO Write "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(6, "0x05: Lost event "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(7, "0x06: Channel state "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(8, "0x07: Token Ring state"); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(9, "0x08: Token "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(10, "0x09: Error Readout "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(11, "0x0a: SPI "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(12, "0x0b: DLL Lock error "); // <- From GET4 v1.2 + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(13, "0x0c: DLL Reset invoc."); // <- From GET4 v1.2 + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(14, "0x11: Overwrite "); // <- From GET4 v1.0 to 1.3 + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(15, "0x12: ToT out of range"); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(16, "0x13: Event Discarded "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(17, "0x14: Add. Rising edge"); // <- From GET4 v1.3 + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(18, "0x15: Unpaired Falling"); // <- From GET4 v1.3 + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(19, "0x16: Sequence error "); // <- From GET4 v1.3 + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(20, "0x17: Epoch Overflow "); // <- From GET4 v2.0 + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(21, "0x7f: Unknown "); + fvhCompGet4ChErrors[uComp]->GetYaxis()->SetBinLabel(22, "Corrupt/unsuprtd error"); + + /// ---> Per raw channel in Component + + fvhCompRawChCount.push_back(new TH1I(Form("%sCompRawChCount_c%02u", sSystem.data(), uCompIndex), + Form("Channel counts comp. %02u raw; Channel; Hits", + uCompIndex), + fuNbOfChannelsPerComp, 0, fuNbOfChannelsPerComp)); + + fvhCompRawChRate.push_back(new TH2D(Form("%sCompRawChRate_c%02u", sSystem.data(), uCompIndex), + Form("Raw channel rate comp. %02u; Time in run [s]; Channel; " + "Rate [1/s]", + uCompIndex), + fuHistoryHistoSize, 0, fuHistoryHistoSize, + fuNbOfChannelsPerComp, 0, fuNbOfChannelsPerComp)); + + fvhCompRawChTot.push_back(new TH2I(Form("%sCompRawChTot_c%02u", sSystem.data(), uCompIndex), + Form("Raw TOT comp. %02u, raw channel; Channel; TOT [bin]", uCompIndex), + fuNbOfChannelsPerComp, 0, fuNbOfChannelsPerComp, + 256, 0, 256)); + + /// ---> Per remapped (PADI) channel in Component + fvhCompRemapChCount.push_back(new TH1I(Form("%sCompRemapChCount_c%02u", sSystem.data(), uCompIndex), + Form("PADI Channel counts comp. %02u, remapped; PADI channel; Hits", + uCompIndex), + fuNbOfChannelsPerComp, 0, fuNbOfChannelsPerComp)); + + fvhCompRemapChRate.push_back(new TH2D(Form("%sCompRemapChRate_c%02u", sSystem.data(), uCompIndex), + Form("PADI channel rate comp. %02u, remapped; Time in run [s]; PADI channel; " + "Rate [1/s]", + uCompIndex), + fuHistoryHistoSize, 0, fuHistoryHistoSize, + fuNbOfChannelsPerComp, 0, fuNbOfChannelsPerComp)); + + fvhCompRemapChTot.push_back(new TH2I(Form("%sCompRemapChTot_c%02u", sSystem.data(), uCompIndex), + Form("Raw TOT comp. %02u, remapped; PADI channel; TOT [bin]", uCompIndex), + fuNbOfChannelsPerComp, 0, fuNbOfChannelsPerComp, + 256, 0, 256)); + + // clang-format on + + /// Add pointers to the vector with all histo for access by steering class + /// Per GET4 in gDPB + AddHistoToVector(fvhCompGet4MessType[uComp], sFolderComp); + AddHistoToVector(fvhCompGet4ChScm[uComp], sFolderComp); + AddHistoToVector(fvhCompGet4ChErrors[uComp], sFolderComp); + /// ---> Per raw channel in Component + AddHistoToVector(fvhCompRawChCount[uComp], sFolderComp); + AddHistoToVector(fvhCompRawChRate[uComp], sFolderComp); + AddHistoToVector(fvhCompRawChTot[uComp], sFolderComp); + /// ---> Per remapped (PADI) channel in Component + AddHistoToVector(fvhCompRemapChCount[uComp], sFolderComp); + AddHistoToVector(fvhCompRemapChRate[uComp], sFolderComp); + AddHistoToVector(fvhCompRemapChTot[uComp], sFolderComp); + } // for( UInt_t uComp = 0; uComp < fuNbOfComps; ++uComp ) + + return kTRUE; +} + +void CbmTofUnpackMonitor::DrawCanvases() +{ + /// Avoid name collision for the histos and canvases in Root memory + std::string sSystem = "tof"; + if (fBmonMode) { + // + sSystem = "bmon"; + } + + /// General summary: Messages types per GET4 (index in system) + fcSummaryGet4s = + new TCanvas(Form("c%sSummaryGet4s", sSystem.data()), Form("GET4s message stats, %s", sSystem.data())); + fcSummaryGet4s->Divide(3, 2); + + fcSummaryGet4s->cd(1); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhGet4MessType->Draw("colz"); + + fcSummaryGet4s->cd(2); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhGet4EpochFlags->Draw("colz"); + + fcSummaryGet4s->cd(3); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhGet4ScmType->Draw("colz"); + + fcSummaryGet4s->cd(4); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhGet4SysMessType->Draw("colz"); + + fcSummaryGet4s->cd(5); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhGet4ErrorsType->Draw("colz"); + + std::string sFolder = "canvases"; + AddCanvasToVector(fcSummaryGet4s, sFolder); + ///----------------------------------------------------------------------------------------------------------------/// + + for (UInt_t uComp = 0; uComp < fuNbOfComps; ++uComp) { + + fvcSumComp.push_back(new TCanvas(Form("c%sSumComp%02u", sSystem.data(), uComp), + Form("Component %2u summary, %s", uComp, sSystem.data()))); + fvcSumComp[uComp]->Divide(3, 3); + + /// ---> Per GET4 in Component + fvcSumComp[uComp]->cd(1); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fvhCompGet4MessType[uComp]->Draw("colz"); + + fvcSumComp[uComp]->cd(2); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fvhCompGet4ChScm[uComp]->Draw("colz"); + + fvcSumComp[uComp]->cd(3); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fvhCompGet4ChErrors[uComp]->Draw("colz"); + + /// ---> Per raw channel in Component + fvcSumComp[uComp]->cd(4); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fvhCompRawChCount[uComp]->Draw("colz"); + + fvcSumComp[uComp]->cd(5); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fvhCompRawChRate[uComp]->Draw("colz"); + + fvcSumComp[uComp]->cd(6); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fvhCompRawChTot[uComp]->Draw("colz"); + + /// ---> Per remapped (PADI) channel in Component + fvcSumComp[uComp]->cd(7); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fvhCompRemapChCount[uComp]->Draw("colz"); + + fvcSumComp[uComp]->cd(8); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fvhCompRemapChRate[uComp]->Draw("colz"); + + fvcSumComp[uComp]->cd(9); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fvhCompRemapChTot[uComp]->Draw("colz"); + + AddCanvasToVector(fvcSumComp[uComp], sFolder); + } +} + +Bool_t CbmTofUnpackMonitor::CreateMsComponentSizeHistos(UInt_t component) +{ + if (nullptr == fvhMsSize[component]) { + TString sMsSizeName = Form("MsSize_c%02u", component); + TString sMsSizeTitle = Form("Size of MS for component %02u; Ms Size [bytes]", component); + fvhMsSize[component] = new TH1F(sMsSizeName.Data(), sMsSizeTitle.Data(), 30000, 0., 30000.); + fvhMsSize[component]->SetCanExtend(TH2::kAllAxes); + AddHistoToVector(fvhMsSize[component], "MsSzComp"); + } + if (nullptr == fvhMsSizeTime[component]) { + TString sMsSizeName = Form("MsSizeTime_c%02u", component); + TString sMsSizeTitle = Form("Size of MS vs time for component %02u; Time[s] ; Ms Size [bytes]", component); + fvhMsSizeTime[component] = new TProfile(sMsSizeName.Data(), sMsSizeTitle.Data(), 15000, 0., 300.); + fvhMsSizeTime[component]->SetCanExtend(TH2::kAllAxes); + AddHistoToVector(fvhMsSizeTime[component], "MsSzComp"); + } + return kTRUE; +} + +Bool_t CbmTofUnpackMonitor::ResetMsComponentSizeHistos(UInt_t component) +{ + if (nullptr != fvhMsSize[component]) { fvhMsSize[component]->Reset(); } + if (nullptr != fvhMsSizeTime[component]) { fvhMsSizeTime[component]->Reset(); } + return kTRUE; +} + +Bool_t CbmTofUnpackMonitor::ResetHistograms() +{ + fhGet4MessType->Reset(); + fhGet4ScmType->Reset(); + fhGet4ErrorsType->Reset(); + fhGet4EpochFlags->Reset(); + /// ---> Per GET4 in Component + for (UInt_t uComp = 0; uComp < fuNbOfComps; ++uComp) { + fvhCompGet4MessType[uComp]->Reset(); + fvhCompGet4ChScm[uComp]->Reset(); + fvhCompGet4ChErrors[uComp]->Reset(); + /// ---> Per raw channel in Component + fvhCompRawChCount[uComp]->Reset(); + fvhCompRawChRate[uComp]->Reset(); + fvhCompRawChTot[uComp]->Reset(); + /// ---> Per remapped (PADI) channel in Component + fvhCompRemapChCount[uComp]->Reset(); + fvhCompRemapChRate[uComp]->Reset(); + fvhCompRemapChTot[uComp]->Reset(); + } + + return kTRUE; +} + +Bool_t CbmTofUnpackMonitor::CreateBmonHistograms() +{ + /// Logarithmic bining + uint32_t iNbBinsLog = 0; + /// Parameters are NbDecadesLog, NbStepsDecade, NbSubStepsInStep + std::vector<double> dBinsLogVector = GenerateLogBinArray(4, 9, 1, iNbBinsLog); + double* dBinsLog = dBinsLogVector.data(); + // double * dBinsLog = GenerateLogBinArray( 4, 9, 1, iNbBinsLog ); + + // clang-format off + + fhBmonCompMapAll = new TH1I("hBmonCompMapAll", "Map of hits on Bmon detector; Comp.; Hits Count []", + fuNbOfComps, -0.5, fuNbOfComps - 0.5); + fhBmonCompGet4 = new TH2I("hBmonCompGet4", "Map of hits on Bmon detector; Comp.; GET4; Counts []", + fuNbOfComps*80, -0.5, fuNbOfComps*80 - 0.5, + 2*kuNbChanBmon, -0.5, 2*kuNbChanBmon - 0.5); + fhBmonGet4Map = new TH1I("hBmonGet4Map", "Map of hits on Bmon detector; GET4; Hits Count []", + fuNbOfComps*80, -0.5, fuNbOfComps*80 - 0.5); + fhBmonGet4MapEvo = new TH2I("hBmonGet4MapEvo", + "Map of hits on Bmon detector vs time in run; GET4; " + "Time in run [s]; Hits Count []", + fuHistoryHistoSize, 0, fuHistoryHistoSize, + fuNbOfComps*80, -0.5, fuNbOfComps*80 - 0.5); + fhBmonChannelMapAll = new TH1I("hChannelMapAll", "Map of hits on Bmon detector; Strip; Hits Count []", + kuNbChanBmon, -0.5, kuNbChanBmon - 0.5); + fhBmonChannelTotAll = new TH2I("hChannelTotAll", "Tot of hits on Bmon detector per channel; Strip; Tot; Hits Count []", + kuNbChanBmon, -0.5, kuNbChanBmon - 0.5, 256, -0.5, 255.5); + fhBmonHitMapEvoAll = new TH2I("hBmonHitMapEvoAll", + "Map of hits on Bmon detector vs time in run; Chan; " + "Time in run [s]; Hits Count []", + kuNbChanBmon, -0.5, kuNbChanBmon - 0.5, + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fhBmonHitTotEvoAll = new TH2I("hBmonHitTotEvoAll", + "Evolution of TOT in Bmon detector vs time in run; Time " + "in run [s]; TOT [ bin ]; Hits Count []", + fuHistoryHistoSize, 0, fuHistoryHistoSize, 256, -0.5, 255.5); + fhBmonChanHitMapAll = new TH1D("fhBmonChanHitMapAll", "Map of hits on Bmon detector; Strip; Hits Count []", + kuNbChanBmon, -0.5, kuNbChanBmon - 0.5); + fhBmonChanHitMapEvoAll = new TH2I("hBmonChanHitMapEvoAll", + "Map of hits on Bmon detector vs time in run; " + "Strip; Time in run [s]; Hits Count []", + kuNbChanBmon, 0., kuNbChanBmon, fuHistoryHistoSize, 0, fuHistoryHistoSize); + + + fhBmonCompMap = new TH1I("hBmonCompMap", "Map of hits on Bmon detector; Comp.; Hits Count []", + fuNbOfComps, -0.5, fuNbOfComps - 0.5); + fhBmonChannelMap = new TH1I("hChannelMap", "Map of hits on Bmon detector; Strip; Hits Count []", + kuNbChanBmon, -0.5, kuNbChanBmon - 0.5); + fhBmonHitMapEvo = new TH2I("hBmonHitMapEvo", + "Map of hits on Bmon detector vs time in run; Chan; " + "Time in run [s]; Hits Count []", + kuNbChanBmon, -0.5, kuNbChanBmon - 0.5, fuHistoryHistoSize, 0, fuHistoryHistoSize); + fhBmonHitTotEvo = new TH2I("hBmonHitTotEvo", + "Evolution of TOT in Bmon detector vs time in run; Time " + "in run [s]; TOT [ bin ]; Hits Count []", + fuHistoryHistoSize, 0, fuHistoryHistoSize, 256, -0.5, 255.5); + fhBmonChanHitMap = new TH1D("fhBmonChanHitMap", "Map of hits on Bmon detector; Strip; Hits Count []", + kuNbChanBmon, -0.5, kuNbChanBmon - 0.5); + fhBmonChanHitMapEvo = new TH2I("hBmonChanHitMapEvo", + "Map of hits on Bmon detector vs time in run; " + "Strip; Time in run [s]; Hits Count []", + kuNbChanBmon, 0., kuNbChanBmon, fuHistoryHistoSize, 0, fuHistoryHistoSize); + for (UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill++) { + fvhBmonCompMapSpill.push_back( + new TH1I(Form("hBmonCompMapSpill%02u", uSpill), + Form("Map of hits on Bmon detector in current spill %02u; Comp.; Hits Count []", uSpill), + fuNbOfComps, -0.5, fuNbOfComps - 0.5)); + fvhBmonChannelMapSpill.push_back(new TH1I(Form("hBmonChannelMapSpill%02u", uSpill), + Form("Map of hits on Bmon detector in current spill %02u; Strip; " + "Hits Count []", + uSpill), + kuNbChanBmon, -0.5, kuNbChanBmon - 0.5)); + } // for( UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill ++) + fhBmonHitsPerSpill = new TH1I("hBmonHitsPerSpill", "Hit count per spill; Spill; Hits Count []", 2000, 0., 2000); + + fhBmonMsgCntEvo = new TH1I("hBmonMsgCntEvo", + "Evolution of Hit & error msgs counts vs time in run; " + "Time in run [s]; Msgs Count []", + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fhBmonHitCntEvo = new TH1I("hBmonHitCntEvo", + "Evolution of Hit counts vs time in run; Time in run [s]; Hits Count []", + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fhBmonErrorCntEvo = new TH1I("hBmonErrorCntEvo", + "Evolution of Error counts vs time in run; Time in run [s]; Error Count []", + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fhBmonLostEvtCntEvo = new TH1I("hBmonLostEvtCntEvo", + "Evolution of LostEvent counts vs time in run; " + "Time in run [s]; LostEvent Count []", + fuHistoryHistoSize, 0, fuHistoryHistoSize); + + fhBmonErrorFractEvo = new TProfile("hBmonErrorFractEvo", + "Evolution of Error Fraction vs time in run; " + "Time in run [s]; Error Fract []", + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fhBmonLostEvtFractEvo = new TProfile("hBmonLostEvtFractEvo", + "Evolution of LostEvent Fraction vs time in " + "run; Time in run [s]; LostEvent Fract []", + fuHistoryHistoSize, 0, fuHistoryHistoSize); + + fhBmonMsgCntPerMsEvo = new TH2I("hBmonMsgCntPerMsEvo", + "Evolution of Hit & error msgs counts, per MS vs time in run; " + "Time in run [s]; Hits Count/MS []; MS", + fuHistoryHistoSize, 0, fuHistoryHistoSize, iNbBinsLog, dBinsLog); + fhBmonHitCntPerMsEvo = new TH2I("hBmonHitCntPerMsEvo", + "Evolution of Hit counts, per MS vs time in run; " + "Time in run [s]; Hits Count/MS []; MS", + fuHistoryHistoSize, 0, fuHistoryHistoSize, iNbBinsLog, dBinsLog); + fhBmonErrorCntPerMsEvo = new TH2I("hBmonErrorCntPerMsEvo", + "Evolution of Error counts, per MS vs time in " + "run; Time in run [s]; Error Count/MS []; MS", + fuHistoryHistoSize, 0, fuHistoryHistoSize, iNbBinsLog, dBinsLog); + fhBmonLostEvtCntPerMsEvo = new TH2I("hBmonLostEvtCntPerMsEvo", + "Evolution of LostEvent, per MS counts vs time in run; Time in " + "run [s]; LostEvent Count/MS []; MS", + fuHistoryHistoSize, 0, fuHistoryHistoSize, iNbBinsLog, dBinsLog); + + fhBmonErrorFractPerMsEvo = new TH2I("hBmonErrorFractPerMsEvo", + "Evolution of Error Fraction, per MS vs time in run; Time in run " + "[s]; Error Fract/MS []; MS", + fuHistoryHistoSize, 0, fuHistoryHistoSize, 1000, 0, 1); + fhBmonLostEvtFractPerMsEvo = new TH2I("hBmonLostEvtFractPerMsEvo", + "Evolution of LostEvent Fraction, per MS vs time in run; Time in " + "run [s]; LostEvent Fract/MS []; MS", + fuHistoryHistoSize, 0, fuHistoryHistoSize, 1000, 0, 1); + + fhBmonChannelMapPulser = new TH1I("fhBmonChannelMapPulser", "Map of pulser hits on Bmon detector; Chan; Hits Count []", + kuNbChanBmon, 0., kuNbChanBmon); + fhBmonHitMapEvoPulser = new TH2I("fhBmonHitMapEvoPulser", + "Map of hits on Bmon detector vs time in run; " + "Chan; Time in run [s]; Hits Count []", + kuNbChanBmon, 0., kuNbChanBmon, fuHistoryHistoSize, 0, fuHistoryHistoSize); + // clang-format on + + /// Add pointers to the vector with all histo for access by steering class + std::string sFolder = "All"; + AddHistoToVector(fhBmonCompMapAll, sFolder); + AddHistoToVector(fhBmonCompGet4, sFolder); + AddHistoToVector(fhBmonGet4Map, sFolder); + AddHistoToVector(fhBmonGet4MapEvo, sFolder); + AddHistoToVector(fhBmonChannelMapAll, sFolder); + AddHistoToVector(fhBmonChannelTotAll, sFolder); + AddHistoToVector(fhBmonHitMapEvoAll, sFolder); + AddHistoToVector(fhBmonHitTotEvoAll, sFolder); + AddHistoToVector(fhBmonChanHitMapAll, sFolder); + AddHistoToVector(fhBmonChanHitMapEvoAll, sFolder); + + sFolder = "NoPulser"; + AddHistoToVector(fhBmonCompMap, sFolder); + AddHistoToVector(fhBmonChannelMap, sFolder); + AddHistoToVector(fhBmonHitMapEvo, sFolder); + AddHistoToVector(fhBmonHitTotEvo, sFolder); + AddHistoToVector(fhBmonChanHitMap, sFolder); + AddHistoToVector(fhBmonChanHitMapEvo, sFolder); + sFolder = "Spills"; + for (UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill++) { + AddHistoToVector(fvhBmonCompMapSpill[uSpill], sFolder); + AddHistoToVector(fvhBmonChannelMapSpill[uSpill], sFolder); + } // for( UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill ++) + AddHistoToVector(fhBmonHitsPerSpill, sFolder); + + sFolder = "GlobRates"; + AddHistoToVector(fhBmonMsgCntEvo, sFolder); + AddHistoToVector(fhBmonHitCntEvo, sFolder); + AddHistoToVector(fhBmonErrorCntEvo, sFolder); + AddHistoToVector(fhBmonLostEvtCntEvo, sFolder); + + AddHistoToVector(fhBmonErrorFractEvo, sFolder); + AddHistoToVector(fhBmonLostEvtFractEvo, sFolder); + + sFolder = "GlobRatesMs"; + AddHistoToVector(fhBmonMsgCntPerMsEvo, sFolder); + AddHistoToVector(fhBmonHitCntPerMsEvo, sFolder); + AddHistoToVector(fhBmonErrorCntPerMsEvo, sFolder); + AddHistoToVector(fhBmonLostEvtCntPerMsEvo, sFolder); + AddHistoToVector(fhBmonErrorFractPerMsEvo, sFolder); + AddHistoToVector(fhBmonLostEvtFractPerMsEvo, sFolder); + + sFolder = "Pulser"; + AddHistoToVector(fhBmonChannelMapPulser, sFolder); + AddHistoToVector(fhBmonHitMapEvoPulser, sFolder); + + /*******************************************************************/ + sFolder = "RatePerChan"; + for (UInt_t uChan = 0; uChan < kuNbChanBmon; ++uChan) { + // clang-format off + fvhBmonMsgCntEvoChan[uChan] = new TH1I(Form("hBmonMsgCntEvoChan%02u", uChan), + Form("Evolution of Messages counts vs time in run for channel " + "%02u; Time in run [s]; Messages Count []", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fvhBmonMsgCntPerMsEvoChan[uChan] = new TH2I(Form("hBmonMsgCntPerMsEvoChan%02u", uChan), + Form("Evolution of Hit counts per MS vs time in run for channel " + "%02u; Time in run [s]; Hits Count/MS []; MS", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize, iNbBinsLog, dBinsLog); + + fvhBmonHitCntEvoChan[uChan] = new TH1I(Form("hBmonHitCntEvoChan%02u", uChan), + Form("Evolution of Hit counts vs time in run for channel %02u; " + "Time in run [s]; Hits Count []", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fvhBmonHitCntPerMsEvoChan[uChan] = new TH2I(Form("hBmonHitCntPerMsEvoChan%02u", uChan), + Form("Evolution of Hit counts per MS vs time in run for channel " + "%02u; Time in run [s]; Hits Count/MS []; MS", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize, iNbBinsLog, dBinsLog); + + fvhBmonErrorCntEvoChan[uChan] = new TH1I(Form("hBmonErrorCntEvoChan%02u", uChan), + Form("Evolution of Error counts vs time in run for channel " + "%02u; Time in run [s]; Error Count []", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fvhBmonErrorCntPerMsEvoChan[uChan] = new TH2I(Form("hBmonErrorCntPerMsEvoChan%02u", uChan), + Form("Evolution of Error counts per MS vs time in run for " + "channel %02u; Time in run [s]; Error Count/MS []; MS", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize, iNbBinsLog, dBinsLog); + + fvhBmonEvtLostCntEvoChan[uChan] = new TH1I(Form("hBmonEvtLostCntEvoChan%02u", uChan), + Form("Evolution of LostEvent counts vs time in run for channel " + "%02u; Time in run [s]; LostEvent Count []", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fvhBmonEvtLostCntPerMsEvoChan[uChan] = new TH2I(Form("hBmonEvtLostCntPerMsEvoChan%02u", uChan), + Form("Evolution of LostEvent counts per MS vs time in run for " + "channel %02u; Time in run [s]; LostEvent Count/MS []; MS", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize, iNbBinsLog, dBinsLog); + + fvhBmonErrorFractEvoChan[uChan] = new TProfile(Form("hBmonErrorFractEvoChan%02u", uChan), + Form("Evolution of Error Fraction vs time in run for " + "channel %02u; Time in run [s]; Error Fract []", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fvhBmonErrorFractPerMsEvoChan[uChan] = new TH2I(Form("hBmonErrorFractPerMsEvoChan%02u", uChan), + Form("Evolution of Error Fraction, per MS vs time in run for " + "channel %02u; Time in run [s]; Error Fract/MS []; MS", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize, 1000, 0, 1); + + fvhBmonEvtLostFractEvoChan[uChan] = new TProfile(Form("hBmonEvtLostFractEvoChan%02u", uChan), + Form("Evolution of LostEvent Fraction vs time in run for " + "channel %02u; Time in run [s]; LostEvent Fract []", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize); + fvhBmonEvtLostFractPerMsEvoChan[uChan] = + new TH2I(Form("hBmonEvtLostFractPerMsEvoChan%02u", uChan), + Form("Evolution of LostEvent Fraction, per MS vs time in run for channel " + "%02u; Time in run [s]; LostEvent Fract/MS []; MS", + uChan), + fuHistoryHistoSize, 0, fuHistoryHistoSize, 1000, 0, 1); + // clang-format on + + /// Add pointers to the vector with all histo for access by steering class + AddHistoToVector(fvhBmonMsgCntEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonMsgCntPerMsEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonHitCntEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonHitCntPerMsEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonErrorCntEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonErrorCntPerMsEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonEvtLostCntEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonEvtLostCntPerMsEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonErrorFractEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonErrorFractPerMsEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonEvtLostFractEvoChan[uChan], sFolder); + AddHistoToVector(fvhBmonEvtLostFractPerMsEvoChan[uChan], sFolder); + } // for( UInt_t uChan = 0; uChan < kuNbChanBmon; ++uChan ) + + return kTRUE; +} + +Bool_t CbmTofUnpackMonitor::ResetBmonHistograms(Bool_t bResetTime) +{ + for (UInt_t uChan = 0; uChan < kuNbChanBmon; ++uChan) { + fvhBmonMsgCntEvoChan[uChan]->Reset(); + fvhBmonMsgCntPerMsEvoChan[uChan]->Reset(); + + fvhBmonHitCntEvoChan[uChan]->Reset(); + fvhBmonHitCntPerMsEvoChan[uChan]->Reset(); + + fvhBmonErrorCntEvoChan[uChan]->Reset(); + fvhBmonErrorCntPerMsEvoChan[uChan]->Reset(); + + fvhBmonEvtLostCntEvoChan[uChan]->Reset(); + fvhBmonEvtLostCntPerMsEvoChan[uChan]->Reset(); + + fvhBmonErrorFractEvoChan[uChan]->Reset(); + fvhBmonErrorFractPerMsEvoChan[uChan]->Reset(); + + fvhBmonEvtLostFractEvoChan[uChan]->Reset(); + fvhBmonEvtLostFractPerMsEvoChan[uChan]->Reset(); + } // for( UInt_t uChan = 0; uChan < kuNbChanBmon; ++uChan ) + + fhBmonCompMap->Reset(); + fhBmonCompGet4->Reset(); + fhBmonGet4Map->Reset(); + fhBmonGet4MapEvo->Reset(); + fhBmonChannelMapAll->Reset(); + fhBmonChannelTotAll->Reset(); + fhBmonHitMapEvoAll->Reset(); + fhBmonHitTotEvoAll->Reset(); + fhBmonChanHitMapAll->Reset(); + fhBmonChanHitMapEvoAll->Reset(); + + fhBmonCompMap->Reset(); + fhBmonCompMap->Reset(); + fhBmonChannelMap->Reset(); + fhBmonHitMapEvo->Reset(); + fhBmonHitTotEvo->Reset(); + fhBmonChanHitMap->Reset(); + fhBmonChanHitMapEvo->Reset(); + for (UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill++) { + fvhBmonCompMapSpill[uSpill]->Reset(); + fvhBmonChannelMapSpill[uSpill]->Reset(); + } // for( UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill ++) + fhBmonHitsPerSpill->Reset(); + + fhBmonMsgCntEvo->Reset(); + fhBmonHitCntEvo->Reset(); + fhBmonErrorCntEvo->Reset(); + + fhBmonErrorFractEvo->Reset(); + fhBmonLostEvtFractEvo->Reset(); + + fhBmonMsgCntPerMsEvo->Reset(); + fhBmonHitCntPerMsEvo->Reset(); + fhBmonErrorCntPerMsEvo->Reset(); + fhBmonLostEvtCntPerMsEvo->Reset(); + fhBmonErrorFractPerMsEvo->Reset(); + fhBmonLostEvtFractPerMsEvo->Reset(); + + fhBmonChannelMapPulser->Reset(); + fhBmonHitMapEvoPulser->Reset(); + + if (kTRUE == bResetTime) { + /// Also reset the Start time for the evolution plots! + fdStartTime = -1.0; + + fuCurrentSpillIdx = 0; + fuCurrentSpillPlot = 0; + } // if( kTRUE == bResetTime ) + + return kTRUE; +} + +void CbmTofUnpackMonitor::DrawBmonCanvases() +{ + std::string sFolder = "canvases"; + + /*******************************************************************/ + /// General summary: Hit maps, Hit rate vs time in run, error fraction vs time un run + fcBmonSummary = new TCanvas("cBmonSummary", "Hit maps, Hit rate, Error fraction"); + fcBmonSummary->Divide(2, 2); + + fcBmonSummary->cd(1); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + fhBmonChannelMap->Draw(); + + fcBmonSummary->cd(2); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhBmonHitMapEvo->Draw("colz"); + + fcBmonSummary->cd(3); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + fhBmonHitCntEvo->Draw(); + + fcBmonSummary->cd(4); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhBmonErrorFractEvo->Draw("hist"); + + AddCanvasToVector(fcBmonSummary, sFolder); + /*******************************************************************/ + + /*******************************************************************/ + /// General summary after mapping: Hit maps, Hit rate vs time in run, error fraction vs time un run + fcBmonSummaryMap = new TCanvas("cBmonSummaryMap", "Hit maps, Hit rate, Error fraction"); + fcBmonSummaryMap->Divide(2, 2); + + fcBmonSummaryMap->cd(1); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + fhBmonChanHitMap->Draw(); + + fcBmonSummaryMap->cd(2); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhBmonChanHitMapEvo->Draw("colz"); + + fcBmonSummaryMap->cd(3); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + fhBmonHitCntEvo->Draw(); + + fcBmonSummaryMap->cd(4); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhBmonErrorFractEvo->Draw("hist"); + + AddCanvasToVector(fcBmonSummaryMap, sFolder); + /*******************************************************************/ + + /*******************************************************************/ + /// Map of hits over Bmon detector and same vs time in run + fcBmonHitMaps = new TCanvas("cBmonHitMaps", "Hit maps"); + fcBmonHitMaps->Divide(2); + + fcBmonHitMaps->cd(1); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + fhBmonChannelMap->Draw(); + + fcBmonHitMaps->cd(2); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogz(); + fhBmonHitMapEvo->Draw("colz"); + + AddCanvasToVector(fcBmonHitMaps, sFolder); + /*******************************************************************/ + + /*******************************************************************/ + /// General summary: Hit maps, Hit rate vs time in run, error fraction vs time un run + fcBmonGenCntsPerMs = + new TCanvas("cBmonGenCntsPerMs", "Messages and hit cnt per MS, Error and Evt Loss Fract. per MS "); + fcBmonGenCntsPerMs->Divide(2, 2); + + fcBmonGenCntsPerMs->cd(1); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + gPad->SetLogz(); + fhBmonMsgCntPerMsEvo->Draw("colz"); + + fcBmonGenCntsPerMs->cd(2); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + gPad->SetLogz(); + fhBmonHitCntPerMsEvo->Draw("colz"); + + fcBmonGenCntsPerMs->cd(3); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + gPad->SetLogz(); + fhBmonErrorFractPerMsEvo->Draw("colz"); + + fcBmonGenCntsPerMs->cd(4); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + gPad->SetLogz(); + fhBmonLostEvtFractPerMsEvo->Draw("colz"); + + AddCanvasToVector(fcBmonGenCntsPerMs, sFolder); + /*******************************************************************/ + + /*******************************************************************/ + /// General summary: Hit maps, Hit rate vs time in run, error fraction vs time un run + fcBmonSpillCounts = new TCanvas("cBmonSpillCounts", "Counts per spill, last 5 spills including current one"); + fcBmonSpillCounts->Divide(1, kuNbSpillPlots); + + for (UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill++) { + fcBmonSpillCounts->cd(1 + uSpill); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + // fvhChannelMapSpill[ uSpill ]->SetStats( kTRUE ); + fvhBmonChannelMapSpill[uSpill]->Draw(); + gPad->Update(); + TPaveStats* st = (TPaveStats*) fvhBmonChannelMapSpill[uSpill]->FindObject("stats"); + st->SetOptStat(10); + st->SetX1NDC(0.25); + st->SetX2NDC(0.95); + st->SetY1NDC(0.90); + st->SetY2NDC(0.95); + } // for( UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill ++) + + AddCanvasToVector(fcBmonSpillCounts, sFolder); + /*******************************************************************/ + + /*******************************************************************/ + /// General summary: Hit maps, Hit rate vs time in run, error fraction vs time un run + fcBmonSpillCountsHori = new TCanvas("cBmonSpillCountsHori", "Counts per spill, last 5 spills including current one"); + fcBmonSpillCountsHori->Divide(kuNbSpillPlots); + + for (UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill++) { + fcBmonSpillCountsHori->cd(1 + uSpill); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + fvhBmonChannelMapSpill[uSpill]->Draw(); + gPad->Update(); + TPaveStats* st = (TPaveStats*) fvhBmonChannelMapSpill[uSpill]->FindObject("stats"); + st->SetOptStat(10); + st->SetX1NDC(0.25); + st->SetX2NDC(0.95); + st->SetY1NDC(0.90); + st->SetY2NDC(0.95); + } // for( UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill ++) + + AddCanvasToVector(fcBmonSpillCountsHori, sFolder); + /*******************************************************************/ + + /*******************************************************************/ + /// General summary: Hit maps, Hit rate vs time in run, error fraction vs time un run + fcBmonSpillCompCountsHori = + new TCanvas("cBmonSpillCompCountsHori", "Counts in Comp. per spill, last 5 spills including current one"); + fcBmonSpillCompCountsHori->Divide(kuNbSpillPlots); + + for (UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill++) { + fcBmonSpillCompCountsHori->cd(1 + uSpill); + gPad->SetGridx(); + gPad->SetGridy(); + gPad->SetLogy(); + fvhBmonCompMapSpill[uSpill]->Draw(); + gPad->Update(); + TPaveStats* st = (TPaveStats*) fvhBmonCompMapSpill[uSpill]->FindObject("stats"); + st->SetOptStat(110); + st->SetX1NDC(0.25); + st->SetX2NDC(0.95); + st->SetY1NDC(0.90); + st->SetY2NDC(0.95); + } // for( UInt_t uSpill = 0; uSpill < kuNbSpillPlots; uSpill ++) + + AddCanvasToVector(fcBmonSpillCompCountsHori, sFolder); + /*******************************************************************/ +} +// ------------------------------------------------------------------------- + + +// ------------------------------------------------------------------------- +void CbmTofUnpackMonitor::FillHitMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx, + const uint32_t& uGet4Id, const uint32_t& uRawCh, + const uint32_t& uRemapCh, const uint32_t& uTot) +{ + if (-1 == fdStartTime) { + /// Initialize Start time for evolution plots + 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); +} +void CbmTofUnpackMonitor::FillEpochMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id, + const bool& bSyncFlag, // mess.getGdpbEpSync + const bool& bDataLoss, // mess.getGdpbEpDataLoss() + const bool& bEpochLoss, // mess.getGdpbEpEpochLoss() + 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); +} +void CbmTofUnpackMonitor::FillScmMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id, + const uint32_t& uCh, // mess.getGdpbSlcChan() + const uint32_t& uEdge, // mess.getGdpbSlcEdge() + const uint32_t& uType // mess.getGdpbSlcType() +) +{ + /// ---> 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) +} +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); +} +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() ) +} + + +// ------------------------------------------------------------------------- +void CbmTofUnpackMonitor::CheckBmonSpillLimits(const double_t& dMsTime) +{ + if (-1 == fdStartTime) { + /// Initialize Start time for evolution plots + 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; + } + + // 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 ) +} +void CbmTofUnpackMonitor::FillHitBmonMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx, + const uint32_t& uGet4Id, const uint32_t& uTot) +{ + if (-1 == fdStartTime) { + /// Initialize Start time for evolution plots + fdStartTime = dMsTime; + } + + /// 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) ) +} + +void CbmTofUnpackMonitor::FillErrBmonMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx, + const uint32_t& uGet4Id, const bool& bErrEvtLost) +{ + /// 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; + + 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); + fhBmonErrorCntEvo->Fill(dMsTime - fdStartTime); + fhBmonErrorFractEvo->Fill(dMsTime - fdStartTime, 1.0); + + fvhBmonErrorCntEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime); + fvhBmonErrorFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 1.0); + + fvuBmonErrorCntChanMs[uChannelBmon]++; + if (bErrEvtLost) { + fhBmonLostEvtCntEvo->Fill(dMsTime - fdStartTime); + fhBmonLostEvtFractEvo->Fill(dMsTime - fdStartTime, 1.0); + + fvhBmonEvtLostCntEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime); + fvhBmonEvtLostFractEvoChan[uChannelBmon]->Fill(dMsTime - fdStartTime, 1.0); + + fvuBmonEvtLostCntChanMs[uChannelBmon]++; + } // if( gdpbv100::GET4_V2X_ERR_LOST_EVT == mess.getGdpbSysErrData() ) +} + +// ------------------------------------------------------------------------- + +// ---- Init ---- +Bool_t CbmTofUnpackMonitor::Init(CbmMcbm2018TofPar* parset) +{ + // Get Infos from the parset + fUnpackPar = parset; + + fuNbOfComps = fUnpackPar->GetNrOfGdpbs(); + /// Other constants are defined for the AFCK/DPB in the current parameter class!!! + // FIXME: Start using again the parameter class accessors once a new CRI oriented class is brought into use + fuNbOfGet4PerComp = 80; + fuNbOfChannelsPerGet4 = 4; + fuNbOfChannelsPerComp = fuNbOfGet4PerComp * fuNbOfChannelsPerGet4; + fuNbOfGet4InSyst = fuNbOfComps * fuNbOfGet4PerComp; + + /// Trigger histo creation on all associated monitors + CreateHistograms(); + DrawCanvases(); + if (fBmonMode) { + CreateBmonHistograms(); + DrawBmonCanvases(); + } + + /// Obtain vector of pointers on each histo from the algo (+ optionally desired folder) + std::vector<std::pair<TNamed*, std::string>> vHistos = GetHistoVector(); + + /// Obtain vector of pointers on each canvas from the algo (+ optionally desired folder) + std::vector<std::pair<TCanvas*, std::string>> vCanvases = GetCanvasVector(); + + /// Register the histos and canvases in the HTTP server + std::string sSystem = "tof"; + if (fBmonMode) { + // + sSystem = "bmon"; + } + THttpServer* server = FairRunOnline::Instance()->GetHttpServer(); + if (nullptr != server) { + for (UInt_t uCanvas = 0; uCanvas < vCanvases.size(); ++uCanvas) { + server->Register(Form("/%s/%s", sSystem.data(), vCanvases[uCanvas].second.data()), vCanvases[uCanvas].first); + } + for (UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto) { + server->Register(Form("/%s/%s", sSystem.data(), vHistos[uHisto].second.data()), vHistos[uHisto].first); + } + /* + server->RegisterCommand(Form("/Reset_%s_Hist", sSystem.data()), "bMcbm2018UnpackerTaskStsResetHistos=kTRUE"); + server->Restrict("/Reset_UnpSts_Hist", "allow=admin"); +*/ + } + + return kTRUE; +} + +// ---- Finish ---- +void CbmTofUnpackMonitor::Finish() +{ + /// Obtain vector of pointers on each histo (+ optionally desired folder) + std::vector<std::pair<TNamed*, std::string>> vHistos = GetHistoVector(); + + /// Obtain vector of pointers on each canvas (+ optionally desired folder) + std::vector<std::pair<TCanvas*, std::string>> vCanvases = GetCanvasVector(); + + /// Save old global file and folder pointer to avoid messing with FairRoot + TFile* oldFile = gFile; + TDirectory* oldDir = gDirectory; + TFile* histoFile = nullptr; + + // open separate histo file in recreate mode + histoFile = new TFile(fHistoFileName, "RECREATE"); + histoFile->cd(); + + /// Write histos to output file + for (UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto) { + /// Make sure we end up in chosen folder + TString sFolder = vHistos[uHisto].second.data(); + if (nullptr == gDirectory->Get(sFolder)) gDirectory->mkdir(sFolder); + gDirectory->cd(sFolder); + + /// Write plot + vHistos[uHisto].first->Write(); + + histoFile->cd(); + } + + /// Write canvases to output file + for (UInt_t uCanvas = 0; uCanvas < vCanvases.size(); ++uCanvas) { + /// Make sure we end up in chosen folder + TString sFolder = vCanvases[uCanvas].second.data(); + if (nullptr == gDirectory->Get(sFolder)) gDirectory->mkdir(sFolder); + gDirectory->cd(sFolder); + + /// Write canvas + vCanvases[uCanvas].first->Write(); + + histoFile->cd(); + } + + /// Restore old global file and folder pointer to avoid messing with FairRoot + gFile = oldFile; + gDirectory = oldDir; + + histoFile->Close(); + delete histoFile; +} + + +ClassImp(CbmTofUnpackMonitor) diff --git a/reco/detectors/tof/unpack/CbmTofUnpackMonitor.h b/reco/detectors/tof/unpack/CbmTofUnpackMonitor.h new file mode 100644 index 0000000000..5039f6dadd --- /dev/null +++ b/reco/detectors/tof/unpack/CbmTofUnpackMonitor.h @@ -0,0 +1,287 @@ +/* Copyright (C) 2022 Facility for Antiproton and Ion Research in Europe, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Pierre-Alain Loizeau [committer] */ + +#ifndef CbmTofUnpackMonitor_H +#define CbmTofUnpackMonitor_H + +#include "CbmMcbm2018TofPar.h" + +#include "Rtypes.h" +#include "TH1.h" +#include "TH2.h" +#include "TProfile.h" +#include "TProfile2D.h" + +#include <cstdint> + +class TCanvas; + +class CbmTofUnpackMonitor { +public: + CbmTofUnpackMonitor(); + + virtual ~CbmTofUnpackMonitor(); + + /** @brief Init all required parameter informations and histograms */ + Bool_t Init(CbmMcbm2018TofPar* digiParSet); + + Bool_t CreateHistograms(); + Bool_t ResetHistograms(); + void DrawCanvases(); + + Bool_t CreateBmonHistograms(); + Bool_t ResetBmonHistograms(Bool_t bResetTime); + void DrawBmonCanvases(); + + Bool_t CreateMsComponentSizeHistos(UInt_t component); + Bool_t ResetMsComponentSizeHistos(UInt_t component); + + /** @brief Write all histograms and canvases to file */ + void Finish(); + + void SetHistoFileName(TString nameIn) { fHistoFileName = nameIn; } + + inline void SetPulserTotLimits(UInt_t uMin, UInt_t uMax) + { + fuMinTotPulser = uMin; + fuMaxTotPulser = uMax; + } + inline void SetSpillThreshold(UInt_t uCntLimit) { fuOffSpillCountLimit = uCntLimit; } + inline void SetSpillThresholdNonPulser(UInt_t uCntLimit) { fuOffSpillCountLimitNonPulser = uCntLimit; } + inline void SetSpillCheckInterval(Double_t dIntervalSec) { fdSpillCheckInterval = dIntervalSec; } + inline void SetBmonChannelMap(UInt_t uChan0, UInt_t uChan1, UInt_t uChan2, UInt_t uChan3, UInt_t uChan4, + UInt_t uChan5, UInt_t uChan6, UInt_t uChan7) + { + fuBmonChanMap[0] = uChan0; + fuBmonChanMap[1] = uChan1; + fuBmonChanMap[2] = uChan2; + fuBmonChanMap[3] = uChan3; + fuBmonChanMap[4] = uChan4; + fuBmonChanMap[5] = uChan5; + fuBmonChanMap[6] = uChan6; + fuBmonChanMap[7] = uChan7; + } + + void SetLongDurationLimits(UInt_t uDurationSeconds, UInt_t uBinSize) + { + //fbLongHistoEnable = kTRUE; + fuLongHistoNbSeconds = uDurationSeconds; + fuLongHistoBinSizeSec = uBinSize; + } + + void AddHistoToVector(TNamed* pointer, std::string sFolder = "") + { + fvpAllHistoPointers.push_back(std::pair<TNamed*, std::string>(pointer, sFolder)); + } + std::vector<std::pair<TNamed*, std::string>> GetHistoVector() { return fvpAllHistoPointers; } + + void AddCanvasToVector(TCanvas* pointer, std::string sFolder = "") + { + fvpAllCanvasPointers.push_back(std::pair<TCanvas*, std::string>(pointer, sFolder)); + } + std::vector<std::pair<TCanvas*, std::string>> GetCanvasVector() { return fvpAllCanvasPointers; } + + UInt_t GetMaxNbFlibLinks() { return kuMaxNbFlibLinks; } + + /// Fill Ms Component Size Histos + void FillMsSize(UInt_t uMsComp, UInt_t uSize) { fvhMsSize[uMsComp]->Fill(uSize); } + void FillMsSizeTime(UInt_t uMsComp, Double_t dTime, UInt_t uSize) { fvhMsSizeTime[uMsComp]->Fill(dTime, uSize); } + + + /// Fill general histograms + // void FillMsCntEvo(ULong64_t MsIdx) { fhMsCntEvo->Fill(MsIdx * 1e-9); } + void FillHitMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id, + const uint32_t& uRawCh, const uint32_t& uRemapCh, const uint32_t& uTot); + void FillEpochMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id, const bool& bSyncFlag, + const bool& bDataLoss, const bool& bEpochLoss, const bool& bMissmMatch); + void FillScmMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id, const uint32_t& uCh, + const uint32_t& uEdge, const uint32_t& uType); + void FillSysMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id, const uint32_t& uType); + void FillErrMonitoringHistos(const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id, const uint32_t& uCh, + const uint32_t& uType); + + /// Fill BMon histograms + void CheckBmonSpillLimits(const double_t& dMsTime); + void FillHitBmonMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id, + const uint32_t& uTot); + + void FillErrBmonMonitoringHistos(const double_t& dMsTime, const uint32_t& uCurrCompIdx, const uint32_t& uGet4Id, + const bool& bErrEvtLost); + + /** @brief Activate the BMon mode */ + void SetBmonMode(bool value) { fBmonMode = value; } + + /** @brief Read the Bmon mode */ + bool GetBmonMode() { return fBmonMode; } + +private: + TString fHistoFileName = "data/mon.tof.root"; + + /// Settings from parameter file + CbmMcbm2018TofPar* fUnpackPar = nullptr; + /// Readout chain dimensions and mapping + UInt_t fuNbOfComps = 0; //! Total number of Components in the system + UInt_t fuNbOfGet4PerComp = 0; //! Max number of Get4 per component + UInt_t fuNbOfChannelsPerGet4 = 0; //! Number of channels per Get4, constant + UInt_t fuNbOfChannelsPerComp = 0; //! Number of channels per Component, recalculated + UInt_t fuNbOfGet4InSyst = 0; //! Total/maximum number of Get4 in system + + /// Rate evolution histos + Double_t fdStartTime = -1.0; /** Time of first valid hit (epoch available), used as reference for evolution plots**/ + UInt_t fuHistoryHistoSize = 3600; /** Size in seconds of the evolution histograms **/ + double_t dFirstTsStartTime = 0; + //Bool_t fbLongHistoEnable; + UInt_t fuLongHistoNbSeconds = 3600; + UInt_t fuLongHistoBinSizeSec = 10; + UInt_t fuLongHistoBinNb = 1; + + /** @brief Flag if debug mode is active or not */ + bool fBmonMode = false; + + /// ---> Constants + static const UInt_t kuMaxNbFlibLinks = 32; + static const UInt_t kuBytesPerMessage = 8; + static const UInt_t kuNbChanBmon = 16; + static const UInt_t kuNbSpillPlots = 5; + + /// ---> User settings: Data correction parameters + UInt_t fuMinTotPulser = 185; + UInt_t fuMaxTotPulser = 189; + UInt_t fuOffSpillCountLimit = 200; + UInt_t fuOffSpillCountLimitNonPulser = 80; + Double_t fdSpillCheckInterval = 1.0; + /// Map from electronics channel to BMon strip + /// 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 fuBmonChanMap[kuNbChanBmon] = {8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7}; + + /// MS size histograms + TH1* fvhMsSize[kuMaxNbFlibLinks]; + TProfile* fvhMsSizeTime[kuMaxNbFlibLinks]; + + /// TOF system general histograms + /// ---> Per GET4 in system + TH2* fhGet4MessType = nullptr; + TH2* fhGet4EpochFlags = nullptr; + TH2* fhGet4ScmType = nullptr; + TH2* fhGet4SysMessType = nullptr; + TH2* fhGet4ErrorsType = nullptr; + /// ---> Per GET4 in Component + std::vector<TH2*> fvhCompGet4MessType = {}; + std::vector<TH2*> fvhCompGet4ChScm = {}; + std::vector<TH2*> fvhCompGet4ChErrors = {}; + /// ---> Per raw channel in Component + std::vector<TH1*> fvhCompRawChCount = {}; + std::vector<TH2*> fvhCompRawChRate = {}; + std::vector<TH2*> fvhCompRawChTot = {}; + /// ---> Per remapped (PADI) channel in Component + std::vector<TH1*> fvhCompRemapChCount = {}; + std::vector<TH2*> fvhCompRemapChRate = {}; + std::vector<TH2*> fvhCompRemapChTot = {}; + /// ---> Pulser + TH1* fhPulserChCounts = nullptr; + TH2* fhPulserChEvo = nullptr; + + /// BMon specific histograms + /// ---> Channel rate plots + std::vector<UInt_t> fvuBmonHitCntChanMs = std::vector<UInt_t>(kuNbChanBmon, 0); + std::vector<UInt_t> fvuBmonErrorCntChanMs = std::vector<UInt_t>(kuNbChanBmon, 0); + std::vector<UInt_t> fvuBmonEvtLostCntChanMs = std::vector<UInt_t>(kuNbChanBmon, 0); + std::vector<TH1*> fvhBmonMsgCntEvoChan = std::vector<TH1*>(kuNbChanBmon, nullptr); + std::vector<TH2*> fvhBmonMsgCntPerMsEvoChan = std::vector<TH2*>(kuNbChanBmon, nullptr); + std::vector<TH1*> fvhBmonHitCntEvoChan = std::vector<TH1*>(kuNbChanBmon, nullptr); + std::vector<TH2*> fvhBmonHitCntPerMsEvoChan = std::vector<TH2*>(kuNbChanBmon, nullptr); + std::vector<TH1*> fvhBmonErrorCntEvoChan = std::vector<TH1*>(kuNbChanBmon, nullptr); + std::vector<TH2*> fvhBmonErrorCntPerMsEvoChan = std::vector<TH2*>(kuNbChanBmon, nullptr); + std::vector<TH1*> fvhBmonEvtLostCntEvoChan = std::vector<TH1*>(kuNbChanBmon, nullptr); + std::vector<TH2*> fvhBmonEvtLostCntPerMsEvoChan = std::vector<TH2*>(kuNbChanBmon, nullptr); + std::vector<TProfile*> fvhBmonErrorFractEvoChan = std::vector<TProfile*>(kuNbChanBmon, nullptr); + std::vector<TH2*> fvhBmonErrorFractPerMsEvoChan = std::vector<TH2*>(kuNbChanBmon, nullptr); + std::vector<TProfile*> fvhBmonEvtLostFractEvoChan = std::vector<TProfile*>(kuNbChanBmon, nullptr); + std::vector<TH2*> fvhBmonEvtLostFractPerMsEvoChan = std::vector<TH2*>(kuNbChanBmon, nullptr); + /// ---> Channels maps without cuts + TH1* fhBmonCompMapAll = nullptr; + TH2* fhBmonCompGet4 = nullptr; + TH1* fhBmonGet4Map = nullptr; + TH2* fhBmonGet4MapEvo = nullptr; + TH1* fhBmonChannelMapAll = nullptr; + TH2* fhBmonChannelTotAll = nullptr; + TH2* fhBmonHitMapEvoAll = nullptr; + TH2* fhBmonHitTotEvoAll = nullptr; + TH1* fhBmonChanHitMapAll = nullptr; + TH2* fhBmonChanHitMapEvoAll = nullptr; + /// ---> No Pulser cut + TH1* fhBmonCompMap = nullptr; + TH1* fhBmonChannelMap = nullptr; + TH2* fhBmonHitMapEvo = nullptr; + TH2* fhBmonHitTotEvo = nullptr; + TH1* fhBmonChanHitMap = nullptr; + TH2* fhBmonChanHitMapEvo = nullptr; + /// ---> No Pulser cut + Spill detection + std::vector<TH1*> fvhBmonCompMapSpill = {}; + std::vector<TH1*> fvhBmonChannelMapSpill = {}; + TH1* fhBmonHitsPerSpill = nullptr; + /// ---> Global Rate + TH1* fhBmonMsgCntEvo = nullptr; + TH1* fhBmonHitCntEvo = nullptr; + TH1* fhBmonErrorCntEvo = nullptr; + TH1* fhBmonLostEvtCntEvo = nullptr; + TProfile* fhBmonErrorFractEvo = nullptr; + TProfile* fhBmonLostEvtFractEvo = nullptr; + /// ---> Global Rate per MS + TH2* fhBmonMsgCntPerMsEvo = nullptr; + TH2* fhBmonHitCntPerMsEvo = nullptr; + TH2* fhBmonErrorCntPerMsEvo = nullptr; + TH2* fhBmonLostEvtCntPerMsEvo = nullptr; + TH2* fhBmonErrorFractPerMsEvo = nullptr; + TH2* fhBmonLostEvtFractPerMsEvo = nullptr; + /// ---> Pulser + TH1* fhBmonChannelMapPulser = nullptr; + TH2* fhBmonHitMapEvoPulser = nullptr; + + /// Canvases + /// ---> Generic + TCanvas* fcSummaryGet4s = nullptr; + std::vector<TCanvas*> fvcSumComp = {}; + /// ---> BMon + TCanvas* fcBmonSummary = nullptr; + TCanvas* fcBmonSummaryMap = nullptr; + TCanvas* fcBmonHitMaps = nullptr; + TCanvas* fcBmonGenCntsPerMs = nullptr; + TCanvas* fcBmonSpillCounts = nullptr; + TCanvas* fcBmonSpillCountsHori = nullptr; + TCanvas* fcBmonSpillCompCountsHori = nullptr; + + /// Spill detection + Bool_t fbSpillOn = kTRUE; + UInt_t fuCurrentSpillIdx = 0; + UInt_t fuCurrentSpillPlot = 0; + Double_t fdStartTimeSpill = -1.0; + Double_t fdBmonLastInterTime = -1.0; + UInt_t fuBmonCountsLastInter = 0; + UInt_t fuBmonNonPulserCountsLastInter = 0; + + /// For monitoring of internal processes. + /// => Pointers should be filled with TH1*, TH2*, TProfile*, ... + /// ==> To check if object N is of type T, use "T ObjectPointer = dynamic_cast<T>( fvpAllHistoPointers[N].first );" and check for nullptr + /// ==> To get back the original class name use "fvpAllHistoPointers[N].first->ClassName()" which returns a const char * (e.g. "TH1I") + /// ===> Usage example with feeding a THttpServer: + /// ===> #include "TH2.h" + /// ===> std::string sClassName = vHistos[ uHisto ].first.ClassName(); + /// ===> if( !strncmp( sClassName, "TH1", 3 ) ) + /// ===> server->Register( vHistos[ uHisto ].second.data(), dynamic_cast< TH1 * >(vHistos[ uHisto ].first) ); + /// ===> else if( !strncmp( sClassName, "TH2", 3 ) ) + /// ===> server->Register( vHistos[ uHisto ].second.data(), dynamic_cast< TH2 * >(vHistos[ uHisto ].first) ); + std::vector<std::pair<TNamed*, std::string>> + fvpAllHistoPointers; //! Vector of pointers to histograms + optional folder name + std::vector<std::pair<TCanvas*, std::string>> + fvpAllCanvasPointers; //! Vector of pointers to canvases + optional folder name + + CbmTofUnpackMonitor(const CbmTofUnpackMonitor&); + CbmTofUnpackMonitor operator=(const CbmTofUnpackMonitor&); + + ClassDef(CbmTofUnpackMonitor, 1) +}; + +#endif diff --git a/reco/steer/CbmRecoUnpack.cxx b/reco/steer/CbmRecoUnpack.cxx index f63fbb4e81..fbed6d45f8 100644 --- a/reco/steer/CbmRecoUnpack.cxx +++ b/reco/steer/CbmRecoUnpack.cxx @@ -47,6 +47,7 @@ void CbmRecoUnpack::Finish() if (fTofConfig) fTofConfig->GetUnpacker()->Finish(); if (fTrd1DConfig) fTrd1DConfig->GetUnpacker()->Finish(); if (fTrd2DConfig) fTrd2DConfig->GetUnpacker()->Finish(); + if (fBmonConfig) fBmonConfig->GetUnpacker()->Finish(); // Create some default performance profiling histograms and write them to a file if (fDoPerfProf) performanceProfiling(); @@ -101,6 +102,7 @@ Bool_t CbmRecoUnpack::Init() fTofConfig->InitOutput(); RegisterOutputs(ioman, fTofConfig); /// Framework bound work = kept in this Task fTofConfig->SetAlgo(); + fTofConfig->LoadParFileName(); /// Needed to change the Parameter file name before it is used!!! initParContainers(fTofConfig->GetParContainerRequest()); /// Framework bound work = kept in this Task fTofConfig->InitAlgo(); initPerformanceMaps(fkFlesTof, "TOF"); @@ -135,6 +137,17 @@ Bool_t CbmRecoUnpack::Init() // The second option workaround is in in Init() to look for the fasp config and create a separate branch // for fasp created CbmTrdDigis PR 072021 + // --- Bmon + if (fBmonConfig) { + fBmonConfig->InitOutput(); + RegisterOutputs(ioman, fBmonConfig); /// Framework bound work = kept in this Task + fBmonConfig->SetAlgo(); + fBmonConfig->LoadParFileName(); /// Needed to change the Parameter file name before it is used!!! + initParContainers(fBmonConfig->GetParContainerRequest()); /// Framework bound work = kept in this Task + fBmonConfig->InitAlgo(); + initPerformanceMaps(fkFlesBmon, "Bmon"); + } + return kTRUE; } // ---------------------------------------------------------------------------- @@ -253,6 +266,8 @@ void CbmRecoUnpack::Reset() if (fTrd1DConfig) fTrd1DConfig->Reset(); // ---- Trd2D ---- if (fTrd2DConfig) fTrd2DConfig->Reset(); + // ---- Bmon ---- + if (fBmonConfig) fBmonConfig->Reset(); } // ---------------------------------------------------------------------------- @@ -317,6 +332,13 @@ void CbmRecoUnpack::Unpack(unique_ptr<Timeslice> ts) } break; } + case fkFlesBmon: { + if (fBmonConfig) { + fCbmTsEventHeader->AddNDigisBmon(unpack(systemId, ×lice, component, fBmonConfig, + fBmonConfig->GetOptOutAVec(), fBmonConfig->GetOptOutBVec())); + } + break; + } default: { if (fDoDebugPrints) LOG(error) << "Unpack: Unknown system ID " << systemId << " for component " << component; break; @@ -324,7 +346,7 @@ void CbmRecoUnpack::Unpack(unique_ptr<Timeslice> ts) } } - if (bOutputFullTimeSorting) { + if (!bMonitoringOnly && bOutputFullTimeSorting) { /// Time sort the output vectors of all unpackers present if (fPsdConfig && fPsdConfig->GetOutputVec()) { timesort(fPsdConfig->GetOutputVec()); } if (fRichConfig && fRichConfig->GetOutputVec()) { timesort(fRichConfig->GetOutputVec()); } @@ -332,6 +354,7 @@ void CbmRecoUnpack::Unpack(unique_ptr<Timeslice> ts) if (fTofConfig && fTofConfig->GetOutputVec()) { timesort(fTofConfig->GetOutputVec()); } if (fTrd1DConfig && fTrd1DConfig->GetOutputVec()) { timesort(fTrd1DConfig->GetOutputVec()); } if (fTrd2DConfig && fTrd2DConfig->GetOutputVec()) { timesort(fTrd2DConfig->GetOutputVec()); } + if (fBmonConfig && fBmonConfig->GetOutputVec()) { timesort(fBmonConfig->GetOutputVec()); } /// Time sort the output vectors of all unpackers present if (fPsdConfig && fPsdConfig->GetOptOutAVec()) { timesort(fPsdConfig->GetOptOutAVec()); } @@ -340,6 +363,7 @@ void CbmRecoUnpack::Unpack(unique_ptr<Timeslice> ts) if (fTofConfig && fTofConfig->GetOptOutAVec()) { timesort(fTofConfig->GetOptOutAVec()); } if (fTrd1DConfig && fTrd1DConfig->GetOptOutAVec()) { timesort(fTrd1DConfig->GetOptOutAVec()); } if (fTrd2DConfig && fTrd2DConfig->GetOptOutAVec()) { timesort(fTrd2DConfig->GetOptOutAVec()); } + if (fBmonConfig && fBmonConfig->GetOptOutAVec()) { timesort(fBmonConfig->GetOptOutAVec()); } } } // ---------------------------------------------------------------------------- diff --git a/reco/steer/CbmRecoUnpack.h b/reco/steer/CbmRecoUnpack.h index 0e9840c314..f8691aa096 100644 --- a/reco/steer/CbmRecoUnpack.h +++ b/reco/steer/CbmRecoUnpack.h @@ -12,6 +12,7 @@ #ifndef CBMRECOUNPACK_H #define CBMRECOUNPACK_H 1 +#include "CbmBmonUnpackConfig.h" #include "CbmPsdUnpackConfig.h" #include "CbmRichUnpackConfig.h" #include "CbmStsUnpackConfig.h" @@ -105,6 +106,13 @@ public: */ void SetTimeSorting(bool bIn = true) { bOutputFullTimeSorting = bIn; } + /** + * @brief Enable/disable the data output. If On, data unpacked and monitored but neither sorted nor written to disk. + * + * @param value + */ + void SetMonitoringOnly(bool bIn = true) { bMonitoringOnly = bIn; } + /** @brief Set the Psd Unpack Config @param config */ void SetUnpackConfig(std::shared_ptr<CbmPsdUnpackConfig> config) { fPsdConfig = config; } @@ -123,6 +131,9 @@ public: /** @brief Set the Trd2D Unpack Config @param config */ void SetUnpackConfig(std::shared_ptr<CbmTrdUnpackFaspConfig> config) { fTrd2DConfig = config; } + /** @brief Set the Bmon Unpack Config @param config */ + void SetUnpackConfig(std::shared_ptr<CbmBmonUnpackConfig> config) { fBmonConfig = config; } + /** @brief Trigger the unpacking procedure **/ void Unpack(std::unique_ptr<fles::Timeslice> ts); @@ -135,6 +146,7 @@ private: static constexpr std::uint16_t fkFlesTrd = static_cast<std::uint16_t>(fles::SubsystemIdentifier::TRD); static constexpr std::uint16_t fkFlesTrd2D = static_cast<std::uint16_t>(fles::SubsystemIdentifier::TRD2D); static constexpr std::uint16_t fkFlesTof = static_cast<std::uint16_t>(fles::SubsystemIdentifier::RPC); + static constexpr std::uint16_t fkFlesBmon = static_cast<std::uint16_t>(fles::SubsystemIdentifier::T0); /** @brief Flag if extended debug output is to be printed or not*/ bool fDoDebugPrints = false; //! @@ -277,29 +289,31 @@ private: auto digivec = algo->Unpack(ts, icomp); // Check if we want to write the output to somewhere (in pure online monitoring mode for example this can/would/should be skipped) - if (config->GetOutputVec()) { - // Lets do some time-sorting if we are not doing it later - if (!bOutputFullTimeSorting) timesort(&digivec); - - // Transfer the data from the timeslice vector to the target branch vector - // Digis/default output retrieved as offered by the algorithm - for (auto digi : digivec) - config->GetOutputVec()->emplace_back(digi); - } - if (optouttargetvecA) { - // Lets do some timesorting - if (!bOutputFullTimeSorting) timesort(&optoutAvec); - // Transfer the data from the timeslice vector to the target branch vector - for (auto optoutA : optoutAvec) - optouttargetvecA->emplace_back(optoutA); - } - if (optouttargetvecB) { - // Second opt output is not time sorted to allow non GetTime data container. - // Lets do some timesorting - timesort(&optoutAvec); - // Transfer the data from the timeslice vector to the target branch vector - for (auto optoutB : optoutBvec) - optouttargetvecB->emplace_back(optoutB); + if (!bMonitoringOnly) { + if (config->GetOutputVec()) { + // Lets do some time-sorting if we are not doing it later + if (!bOutputFullTimeSorting) timesort(&digivec); + + // Transfer the data from the timeslice vector to the target branch vector + // Digis/default output retrieved as offered by the algorithm + for (auto digi : digivec) + config->GetOutputVec()->emplace_back(digi); + } + if (optouttargetvecA) { + // Lets do some timesorting + if (!bOutputFullTimeSorting) timesort(&optoutAvec); + // Transfer the data from the timeslice vector to the target branch vector + for (auto optoutA : optoutAvec) + optouttargetvecA->emplace_back(optoutA); + } + if (optouttargetvecB) { + // Second opt output is not time sorted to allow non GetTime data container. + // Lets do some timesorting + timesort(&optoutAvec); + // Transfer the data from the timeslice vector to the target branch vector + for (auto optoutB : optoutBvec) + optouttargetvecB->emplace_back(optoutB); + } } std::clock_t cpuendtime = std::clock(); @@ -353,6 +367,9 @@ private: /** @brief Configuration of the Trd unpacker. Provides the configured algorithm */ std::shared_ptr<CbmTrdUnpackFaspConfig> fTrd2DConfig = nullptr; //! + /** @brief Configuration of the Bmon unpacker. Provides the configured algorithm */ + std::shared_ptr<CbmBmonUnpackConfig> fBmonConfig = nullptr; //! + /** @brief Pointer to the Timeslice start time used to write it to the output tree @remark since we hand this to the FairRootManager it also wants to delete it and we do not have to take care of deletion */ CbmTsEventHeader* fCbmTsEventHeader = nullptr; @@ -362,8 +379,11 @@ private: /** @brief Flag to Enable/disable a full time sorting. If off, time sorting happens per link/FLIM source */ bool bOutputFullTimeSorting = false; + /** @brief Flag to Enable/disable the output completely */ + bool bMonitoringOnly = false; + - ClassDef(CbmRecoUnpack, 1); + ClassDef(CbmRecoUnpack, 2); }; -- GitLab