From 51870329caaa2b83b3ecb7874fbd5c994644583c Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Mon, 10 Feb 2025 14:44:09 +0100 Subject: [PATCH] online qa: task header and QA-manager in the online binary --- algo/CMakeLists.txt | 1 + algo/global/Reco.cxx | 19 +++++++++++-- algo/global/Reco.h | 4 +++ algo/qa/QaData.cxx | 28 +++++++++++++------- algo/qa/QaData.h | 14 ++++++---- algo/qa/QaManager.h | 4 +-- algo/qa/QaTaskHeader.h | 60 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 111 insertions(+), 19 deletions(-) create mode 100644 algo/qa/QaTaskHeader.h diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt index 5776eeb2aa..09ee075af5 100644 --- a/algo/CMakeLists.txt +++ b/algo/CMakeLists.txt @@ -150,6 +150,7 @@ set(SRCS qa/PadConfig.cxx qa/QaData.cxx qa/RecoGeneralQa.cxx + qa/QaManager.cxx qa/unpack/StsDigiQa.cxx ca/TrackingSetup.cxx ca/TrackingChain.cxx diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 6ca23944bd..28acffb8b3 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -21,6 +21,7 @@ #include "compat/OpenMP.h" #include "evbuild/Config.h" #include "much/Unpack.h" +#include "qa/QaManager.h" #include "rich/Unpack.h" #include "sts/ChannelMaskSet.h" #include "sts/HitfinderChain.h" @@ -111,8 +112,13 @@ void Reco::Init(const Options& opts) ParFiles parFiles(opts.RunId()); L_(info) << "Using parameter files for setup " << parFiles.setup; - // General QA + // QA instantiation if (fSender != nullptr) { + // QA manager + fQaManager = std::make_unique<qa::Manager>(fSender); + fQaManager->SetContext(&fContext); + + // General QA fGeneralQa = std::make_unique<qa::RecoGeneralQa>(fRunStartTimeNs, fSender); } @@ -222,6 +228,11 @@ void Reco::Init(const Options& opts) fTracking->Init(); } + // Initialize the QA manager + if (fQaManager != nullptr) { + fQaManager->Init(); + } + fInitialized = true; L_(debug) << "CBM Reco finished initialization"; @@ -379,9 +390,13 @@ RecoResults Reco::Run(const fles::Timeslice& ts) results.trdHits = std::move(recoData.trdHits); } - // General QA + // QA if (fSender != nullptr) { (*fGeneralQa)(ts); + + // Send all the histograms, collected through the timeslice + fQaManager->SetTimesliceId(ts.index()); + fQaManager->SendHistograms(); } } PrintTimings(procMon.time); diff --git a/algo/global/Reco.h b/algo/global/Reco.h index a3fa9c2411..8e26d35271 100644 --- a/algo/global/Reco.h +++ b/algo/global/Reco.h @@ -89,6 +89,7 @@ namespace cbm::algo namespace qa { class RecoGeneralQa; + class Manager; } } // namespace cbm::algo @@ -173,6 +174,9 @@ namespace cbm::algo // Tracking std::unique_ptr<TrackingChain> fTracking; + // QA + std::unique_ptr<qa::Manager> fQaManager; + static double FilterNan(double x) { return std::isnan(x) || std::isinf(x) ? 0. : x; } void Validate(const Options& opts); diff --git a/algo/qa/QaData.cxx b/algo/qa/QaData.cxx index 5abee21fe5..520ed4e522 100644 --- a/algo/qa/QaData.cxx +++ b/algo/qa/QaData.cxx @@ -18,7 +18,18 @@ using cbm::algo::qa::Data; // void Data::Init(std::shared_ptr<HistogramSender> histSender) try { - if (histSender.get()) { + size_t nHistograms = 0; + nHistograms += fNofH1; + nHistograms += fNofH2; + nHistograms += fNofP1; + nHistograms += fNofP2; + fbNotEmpty = static_cast<bool>(nHistograms); + if (!fbNotEmpty) { + L_(warn) << "no histograms were provided to a qa::Data instance (running in an idle mode)"; + } + + if (histSender.get() && fbNotEmpty) { + // Check, if the tasks list was initialized properly: at least one task must be initialized if (fvTaskProperties.empty()) { std::stringstream msg; @@ -35,12 +46,7 @@ try { // Forming a histogram config message std::vector<std::pair<std::string, std::string>> vHistCfgs; - size_t nHistograms = 0; // NOTE: Important to keep the order of filling the histograms: 1D -> 2D -> .. - nHistograms += fNofH1; - nHistograms += fNofH2; - nHistograms += fNofP1; - nHistograms += fNofP2; vHistCfgs.reserve(nHistograms); for (const auto& task : fvTaskProperties) { @@ -103,8 +109,10 @@ void Data::RegisterNewTask(std::string_view name) // void Data::Send(std::shared_ptr<HistogramSender> histoSender) { - histoSender->PrepareAndSendMsg(fHistograms, zmq::send_flags::none); - L_(info) << fsTaskNames << ": Published " << fNofH1 << " 1D- and " << fNofH2 << " 2D-histograms, " << fNofP1 - << " 1D- and " << fNofP2 << " 2D-profiles"; - this->Reset(); + if (histoSender.get() && fbNotEmpty) { + histoSender->PrepareAndSendMsg(fHistograms, zmq::send_flags::none); + L_(info) << fsTaskNames << ": Published " << fNofH1 << " 1D- and " << fNofH2 << " 2D-histograms, " << fNofP1 + << " 1D- and " << fNofP2 << " 2D-profiles"; + this->Reset(); + } } diff --git a/algo/qa/QaData.h b/algo/qa/QaData.h index 9c47474401..8c66c445a9 100644 --- a/algo/qa/QaData.h +++ b/algo/qa/QaData.h @@ -58,7 +58,10 @@ namespace cbm::algo::qa /// \param histoSender A pointer to the histogram sender void Init(std::shared_ptr<HistogramSender> histoSender); - /// \brief Creates a QA-object and returns the pointer to it + /// \brief Creates a QA-object and returns the pointer to it + /// \tparam Obj A type of the histogram (H1D, H2D, Prof1D, Prof2D) + /// \tparam Args... A signature of the histogram constructor + /// \param args Parameters, passed to a histogram constructor template<class Obj, typename... Args> Obj* MakeObj(Args... args); @@ -84,10 +87,11 @@ namespace cbm::algo::qa std::vector<qa::TaskProperties> fvTaskProperties; ///< A vector to store properties for multiple QA-tasks std::vector<std::string> fvsCanvCfgs = {}; ///< Vector of canvas configs - uint32_t fNofH1{0}; ///< Number of 1D-histograms - uint32_t fNofH2{0}; ///< Number of 2D-histograms - uint32_t fNofP1{0}; ///< Number of 1D-profiles - uint32_t fNofP2{0}; ///< Number of 2D-profiles + uint32_t fNofH1{0}; ///< Number of 1D-histograms + uint32_t fNofH2{0}; ///< Number of 2D-histograms + uint32_t fNofP1{0}; ///< Number of 1D-profiles + uint32_t fNofP2{0}; ///< Number of 2D-profiles + bool fbNotEmpty{true}; ///< false: if no histograms were provided, do not perform initialization and sending }; // ------------------------------------------------------------------------------------------------------------------- diff --git a/algo/qa/QaManager.h b/algo/qa/QaManager.h index 4a291800c5..ab7e397c5f 100644 --- a/algo/qa/QaManager.h +++ b/algo/qa/QaManager.h @@ -30,7 +30,7 @@ namespace cbm::algo::qa Manager(Manager&&) = delete; /// \brief Destructor - ~Manager() = delete; + ~Manager() = default; /// \brief Copy assignment operator Manager& operator=(const Manager&) = delete; @@ -39,7 +39,7 @@ namespace cbm::algo::qa Manager& operator=(Manager&&) = delete; /// \brief Gets an instance of QA data - std::shared_ptr<Data> GetData() { return fpData; } + std::shared_ptr<Data> GetData() const { return fpData; } /// \brief Initializes the instance and sends the histogram and canvas configuration to the server void Init(); diff --git a/algo/qa/QaTaskHeader.h b/algo/qa/QaTaskHeader.h new file mode 100644 index 0000000000..4038cd0d3e --- /dev/null +++ b/algo/qa/QaTaskHeader.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file QaTaskHeader.h +/// \date 10.02.2025 +/// \brief A header for a particular QA task, must be inherited by a given QA task +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#include "qa/QaManager.h" + +#include <memory> + +namespace cbm::algo::qa +{ + /// \class TaskHeader + /// \brief An interface to the qa::Manager + /// \note Must be inherited by a QA task + class TaskHeader { + public: + /// \brief Constructor + /// \param pManager a QA-manager + TaskHeader(const std::unique_ptr<Manager>& pManager) : fpData(pManager->GetData()) {} + + /// \brief Copy constructor + TaskHeader(const TaskHeader&) = delete; + + /// \brief Move constructor + TaskHeader(TaskHeader&&) = delete; + + /// \brief Destructor + ~TaskHeader() = default; + + /// \brief Copy assignment operator + TaskHeader& operator=(const TaskHeader&) = delete; + + /// \brief Move assignment operator + TaskHeader& operator=(TaskHeader&&) = delete; + + protected: + /// \brief Adds a canvas configuration + /// \param canvas A CanvasConfig object + void AddCanvasConfig(const CanvasConfig& canvas) { fpData->AddCanvasConfig(canvas); } + + /// \brief Creates a QA-object and returns the pointer to it + /// \tparam Obj A type of the histogram (H1D, H2D, Prof1D, Prof2D) + /// \tparam Args... A signature of the histogram constructor + /// \param args Parameters, passed to a histogram constructor + template<class Obj, typename... Args> + Obj* MakeObj(Args... args) + { + fpData->MakeObj<Obj>(args...); + } + + private: + std::shared_ptr<Data> fpData{nullptr}; ///< An instance of the QA data (shared between different tasks) + }; +} // namespace cbm::algo::qa -- GitLab