From 94040dab8fdf9b4d9faa3448a1a2727d0fafa01e Mon Sep 17 00:00:00 2001
From: "s.zharko@gsi.de" <s.zharko@gsi.de>
Date: Fri, 14 Jun 2024 18:24:45 +0200
Subject: [PATCH] online STS digi QA: - missed event profile vs. time and TS
 index

---
 algo/qa/Histogram.h                   | 10 ++++++++++
 algo/qa/PadConfig.h                   | 15 +++++++++++++--
 algo/qa/QaData.cxx                    | 16 ++++++++++++++--
 algo/qa/unpack/StsDigiQa.cxx          | 16 ++++++++++++++++
 algo/qa/unpack/StsDigiQa.h            |  1 +
 services/histserv/app/Application.cxx | 10 +++++++---
 services/histserv/app/Application.h   |  1 -
 7 files changed, 61 insertions(+), 8 deletions(-)

diff --git a/algo/qa/Histogram.h b/algo/qa/Histogram.h
index 852d9cf91b..1b70f3b058 100644
--- a/algo/qa/Histogram.h
+++ b/algo/qa/Histogram.h
@@ -65,6 +65,8 @@ namespace cbm::algo::qa
    public:
     using Flags_t = std::underlying_type_t<EHistFlag>;
 
+    static constexpr std::string_view ksTsIdSuffix = "_ts_id";  ///< Suffix of additional histograms vs. TS index
+
     /// \brief Default constructor
     HistogramMetadata() = default;
 
@@ -80,6 +82,14 @@ namespace cbm::algo::qa
     /// \brief Destructor
     ~HistogramMetadata() = default;
 
+    /// \brief Checks if the histogram flags configuration is valid
+    /// \return Is valid
+    bool CheckFlags() const
+    {
+      // The histogram must be plotted either vs TS, or over all TS
+      return (GetFlag(EHistFlag::StoreVsTsId) || !GetFlag(EHistFlag::OmitIntegrated));
+    }
+
     /// \brief Get flag
     /// \param key  Flag key from the EHistFlag enumeration
     bool GetFlag(EHistFlag key) const { return static_cast<bool>(fFlags & static_cast<Flags_t>(key)); }
diff --git a/algo/qa/PadConfig.h b/algo/qa/PadConfig.h
index a7dc7469d4..4d6ac5376c 100644
--- a/algo/qa/PadConfig.h
+++ b/algo/qa/PadConfig.h
@@ -82,11 +82,22 @@ namespace cbm::algo::qa
     /// \tparam Hist  Histogram class
     /// \param  hist  Histogram object
     /// \param  opt   Draw options for the histogram
-    // TODO: implement a single function
+    ///
+    /// If the histogram has EHistFlag::StoreVsTsId, then the TS dependendent histogram
+    /// will be plotted only. If both integrated and vs. TS histograms are needed, please
+    /// explicitly provide the histogram names to two separate pads using the RegisterObject
+    /// function.
     template<class Hist>
     void RegisterHistogram(const Hist* hist, std::string_view opt)
     {
-      RegisterObject(hist->GetName(), opt);
+      // NOTE: SZh 21.06.2024:
+      const auto& metadata = hist->GetMetadata();
+      if (metadata.GetFlag(EHistFlag::StoreVsTsId)) {
+        RegisterObject(hist->GetName() + std::string(HistogramMetadata::ksTsIdSuffix), opt);
+      }
+      else if (!metadata.GetFlag(EHistFlag::OmitIntegrated)) {
+        RegisterObject(hist->GetName(), opt);
+      }
     }
 
     /// \brief  Returns message config
diff --git a/algo/qa/QaData.cxx b/algo/qa/QaData.cxx
index ea184f35c1..1ead168f18 100644
--- a/algo/qa/QaData.cxx
+++ b/algo/qa/QaData.cxx
@@ -16,7 +16,7 @@ using cbm::algo::qa::Data;
 // ---------------------------------------------------------------------------------------------------------------------
 //
 void Data::Init(std::shared_ptr<HistogramSender> histSender)
-{
+try {
   if (histSender.get()) {
     // Forming a histogram config message
     std::vector<std::pair<std::string, std::string>> vHistCfgs;
@@ -28,7 +28,15 @@ void Data::Init(std::shared_ptr<HistogramSender> histSender)
     nHistograms += std::distance(fHistograms.fvP2.begin(), fHistograms.fvP2.end());
     vHistCfgs.reserve(nHistograms);
 
-    auto RegHist = [&](const auto& h) { vHistCfgs.emplace_back(h.GetName() + "!" + h.GetMetadataString(), fsName); };
+    auto RegHist = [&](const auto& h) {
+      if (!h.GetMetadata().CheckFlags()) {
+        std::stringstream msg;
+        msg << "attempt to pass a histogram " << h.GetName()
+            << " with inconsistent flags (see HistogramMetadata::CheckFlags for detailes)";
+        throw std::runtime_error(msg.str());
+      }
+      vHistCfgs.emplace_back(h.GetName() + "!" + h.GetMetadataString(), fsName);
+    };
 
     std::for_each(fHistograms.fvH1.begin(), fHistograms.fvH1.end(), RegHist);
     std::for_each(fHistograms.fvH2.begin(), fHistograms.fvH2.end(), RegHist);
@@ -54,6 +62,10 @@ void Data::Init(std::shared_ptr<HistogramSender> histSender)
     histSender->PrepareAndSendMsg(qa::HistogramContainer{}, zmq::send_flags::none);
   }
 }
+catch (const std::exception& err) {
+  L_(fatal) << "cbm::algo::qa::Data for " << fsName << " fatally aborted. Reason " << err.what();
+  assert(false);
+}
 
 // ---------------------------------------------------------------------------------------------------------------------
 //
diff --git a/algo/qa/unpack/StsDigiQa.cxx b/algo/qa/unpack/StsDigiQa.cxx
index 8cb7a9ce0b..7c502536c4 100644
--- a/algo/qa/unpack/StsDigiQa.cxx
+++ b/algo/qa/unpack/StsDigiQa.cxx
@@ -56,6 +56,7 @@ void DigiQa::Init()
     if (fbAux) {
       fvphAddressChannelElink.resize(nModules);
       fvppAddressChannelMissedEvt.resize(nModules);
+      fvppAddressTimeMissedEvt.resize(nModules);
     }
     for (int iM = 0; iM < nModules; ++iM) {
       int32_t address       = fpReadoutSetup->modules.at(iM).address;
@@ -110,6 +111,20 @@ void DigiQa::Init()
           pad.RegisterHistogram(fvppAddressChannelMissedEvt[iM], "");
           canv.AddPadConfig(pad);
         }
+        {
+          auto pad  = PadConfig();
+          auto name = format("sts_digi_{}_time_missed_evt", aName);
+          auto titl =
+            format("STS digi missed event ratio for module {};time [ms]; N_{{w/ missed events}} / N_{{tot.}}", aTitl);
+          constexpr double timeMin     = 0.;    // [ms]
+          constexpr double timeMax     = 150.;  // [ms]
+          int timeBins                 = std::ceil(timeMax - timeMin);
+          fvppAddressTimeMissedEvt[iM] = fQaData.MakeObj<Prof1D>(name, titl, timeBins, timeMin, timeMax, 0., 1.);
+          fvppAddressTimeMissedEvt[iM]->SetFlag(EHistFlag::StoreVsTsId);
+          fvppAddressTimeMissedEvt[iM]->SetFlag(EHistFlag::OmitIntegrated);
+          pad.RegisterHistogram(fvppAddressTimeMissedEvt[iM], "");
+          canv.AddPadConfig(pad);
+        }
       }
 
       fQaData.AddCanvasConfig(canv);
@@ -161,6 +176,7 @@ void DigiQa::Exec()
         fvphAddressChannelElink[iM]->Fill(static_cast<double>(auxDigi.elink), static_cast<double>(auxDigi.channel));
         fvppAddressChannelMissedEvt[iM]->Fill(static_cast<double>(auxDigi.channel),
                                               static_cast<double>(auxDigi.missedEvent));
+        fvppAddressTimeMissedEvt[iM]->Fill(auxDigi.time * 1.e-6, static_cast<double>(auxDigi.missedEvent));
       }
     }
   }
diff --git a/algo/qa/unpack/StsDigiQa.h b/algo/qa/unpack/StsDigiQa.h
index 9b3787b6de..1e70c3d026 100644
--- a/algo/qa/unpack/StsDigiQa.h
+++ b/algo/qa/unpack/StsDigiQa.h
@@ -59,6 +59,7 @@ namespace cbm::algo::sts
     std::vector<qa::H2D*> fvphAddressChannelElink;   ///< hist: digi channel (vs. eling (AUX)
 
     std::vector<qa::Prof1D*> fvppAddressChannelMissedEvt;  ///< prof: missed event ratio vs. channel (AUX)
+    std::vector<qa::Prof1D*> fvppAddressTimeMissedEvt;     ///< prof: missed event ratio vs. time (AUX)
 
     qa::H2D* fvphFebAsic = nullptr;  ///< hist: digi FEB vs ASIC
   };
diff --git a/services/histserv/app/Application.cxx b/services/histserv/app/Application.cxx
index 2e698f8b9b..5eb5362f05 100644
--- a/services/histserv/app/Application.cxx
+++ b/services/histserv/app/Application.cxx
@@ -46,6 +46,7 @@ using cbm::services::histserv::Application;
 
 using cbm::algo::qa::H1D;
 using cbm::algo::qa::H2D;
+using cbm::algo::qa::HistogramMetadata;
 using cbm::algo::qa::Prof1D;
 using cbm::algo::qa::Prof2D;
 
@@ -395,7 +396,7 @@ bool Application::ReceiveHistoConfig(zmq::message_t& msg)
   }
   if (metadata.GetFlag(EHistFlag::StoreVsTsId)) {
     // Histogram vs. TS id
-    this->RegisterHistoConfig(std::make_pair(name + std::string(ksTsIdSuffix), tempObject.second));
+    this->RegisterHistoConfig(std::make_pair(name + std::string(HistogramMetadata::ksTsIdSuffix), tempObject.second));
   }
 
   return true;
@@ -620,7 +621,7 @@ bool Application::ReadHistogramExtendedTsId(const HistoSrc& rHist, uint64_t tsIn
     using HistoDst_t = typename std::conditional<IsSrcH1D, TH2D, TProfile2D>::type;
     /* clang-format on */
 
-    std::string sHistoName = rHist.GetName() + std::string(ksTsIdSuffix);
+    std::string sHistoName = rHist.GetName() + std::string(HistogramMetadata::ksTsIdSuffix);
     int index1             = FindHistogram(sHistoName.c_str());
     if (-1 == index1) {
       // ----- Creating new histogram
@@ -642,6 +643,7 @@ bool Application::ReadHistogramExtendedTsId(const HistoSrc& rHist, uint64_t tsIn
           double maxZ = rHist.GetMaxY();
           histogram_new =
             new TProfile2D(sHistoName.c_str(), title.c_str(), nBinsX, minX, maxX, nBinsY, minY, maxY, minZ, maxZ);
+          histogram_new->Sumw2();
         }
       }
       cbm::qa::OnlineInterface::AddSlice(rHist, double(tsIndex), histogram_new);
@@ -748,8 +750,8 @@ int Application::FindHistogram(const std::string& name)
 //
 bool Application::PrepareCanvas(uint32_t uCanvIdx)
 {
-  LOG(info) << " Extracting configuration for canvas index " << uCanvIdx;
   CanvasConfig conf(ExtractCanvasConfigFromString(fvpsCanvasConfig[uCanvIdx].second));
+  LOG(info) << " Extracting configuration for canvas index " << uCanvIdx << "(name: " << conf.GetName().data() << ")";
 
   /// First check if all objects to be drawn are present
   uint32_t uNbPads(conf.GetNbPads());
@@ -760,6 +762,8 @@ bool Application::PrepareCanvas(uint32_t uCanvIdx)
       /// Check for empty pads!
       if ("nullptr" != sName) {
         if (FindHistogram(sName) < 0) {
+          LOG(warn) << "Histogram \"" << sName << "\" requested by canvas \"" << conf.GetName().data()
+                    << "\" was not found";
           return false;
         }  // if( FindHistogram( conf.GetObjName( uPadIdx, uObjIdx ) ) < 0 )
       }    // if( "nullptr" != sName )
diff --git a/services/histserv/app/Application.h b/services/histserv/app/Application.h
index 53cbdc8483..580e0dba47 100644
--- a/services/histserv/app/Application.h
+++ b/services/histserv/app/Application.h
@@ -31,7 +31,6 @@ namespace cbm::services::histserv
   };
 
   class Application {
-    static constexpr std::string_view ksTsIdSuffix = "_ts_id";  ///< Suffix of additional histograms vs. TS index
 
    public:
     /** @brief Standard constructor, initialises the application
-- 
GitLab