diff --git a/algo/qa/QaData.cxx b/algo/qa/QaData.cxx index 235bb3ddbf520a14a154e4e0e7aea14f54641cb0..5abee21fe5cc2520d4dccf44b61addc2bb0e0d9a 100644 --- a/algo/qa/QaData.cxx +++ b/algo/qa/QaData.cxx @@ -19,17 +19,31 @@ using cbm::algo::qa::Data; void Data::Init(std::shared_ptr<HistogramSender> histSender) try { if (histSender.get()) { + // Check, if the tasks list was initialized properly: at least one task must be initialized + if (fvTaskProperties.empty()) { + std::stringstream msg; + msg << "a qa::Data instance was not initialized properly: no task was registered. The list of the histograms:\n"; + auto ShowName = [&](const auto& h) { msg << " - " << h.GetName() << '\n'; }; + std::for_each(fHistograms.fvH1.begin(), fHistograms.fvH1.end(), ShowName); + std::for_each(fHistograms.fvH2.begin(), fHistograms.fvH2.end(), ShowName); + std::for_each(fHistograms.fvP1.begin(), fHistograms.fvP1.end(), ShowName); + std::for_each(fHistograms.fvP2.begin(), fHistograms.fvP2.end(), ShowName); + msg << "Please, insure that you either instantiate the qa::Data with the Data(std::string_view name) constructor"; + msg << ", or provide a task name explicitly with the function Data::RegisterNewTask(std::string_view name)"; + throw std::runtime_error(msg.str()); + } + // 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 += std::distance(fHistograms.fvH1.begin(), fHistograms.fvH1.end()); - nHistograms += std::distance(fHistograms.fvH2.begin(), fHistograms.fvH2.end()); - nHistograms += std::distance(fHistograms.fvP1.begin(), fHistograms.fvP1.end()); - nHistograms += std::distance(fHistograms.fvP2.begin(), fHistograms.fvP2.end()); + nHistograms += fNofH1; + nHistograms += fNofH2; + nHistograms += fNofP1; + nHistograms += fNofP2; vHistCfgs.reserve(nHistograms); - for (const auto& task: fvTaskProperties) { + for (const auto& task : fvTaskProperties) { auto RegHist = [&](const auto& h) { if (!h.GetMetadata().CheckFlags()) { std::stringstream msg; @@ -78,13 +92,11 @@ void Data::RegisterNewTask(std::string_view name) auto itH2 = fHistograms.fvH2.begin(); auto itP1 = fHistograms.fvP1.begin(); auto itP2 = fHistograms.fvP2.begin(); - fvTaskProperties.emplace_back(TaskProperties{ - .fsName = {name.begin(), name.end()}, - .fRangeH1 = std::make_pair(itH1, itH1), - .fRangeH2 = std::make_pair(itH2, itH2), - .fRangeP1 = std::make_pair(itP1, itP1), - .fRangeP2 = std::make_pair(itP2, itP2) - }); + fvTaskProperties.emplace_back(TaskProperties{.fsName = {name.begin(), name.end()}, + .fRangeH1 = std::make_pair(itH1, itH1), + .fRangeH2 = std::make_pair(itH2, itH2), + .fRangeP1 = std::make_pair(itP1, itP1), + .fRangeP2 = std::make_pair(itP2, itP2)}); } // --------------------------------------------------------------------------------------------------------------------- @@ -92,11 +104,7 @@ void Data::RegisterNewTask(std::string_view name) void Data::Send(std::shared_ptr<HistogramSender> histoSender) { histoSender->PrepareAndSendMsg(fHistograms, zmq::send_flags::none); - auto nH1 = std::distance(fHistograms.fvH1.begin(), fHistograms.fvH1.end()); - auto nH2 = std::distance(fHistograms.fvH2.begin(), fHistograms.fvH2.end()); - auto nP1 = std::distance(fHistograms.fvP1.begin(), fHistograms.fvP1.end()); - auto nP2 = std::distance(fHistograms.fvP2.begin(), fHistograms.fvP2.end()); - L_(info) << fsTaskNames << ": Published " << nH1 << " 1D- and " << nH2 << " 2D-histograms, " << nP1 << " 1D- and " << nP2 - << " 2D-profiles"; + 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 fcb1afced29bce62d00a9136c1e769d2f808ff23..9c4747440156fe524fd87268b292b512b371e951 100644 --- a/algo/qa/QaData.h +++ b/algo/qa/QaData.h @@ -10,10 +10,10 @@ #pragma once #include "AlgoFairloggerCompat.h" +#include "base/HistogramSender.h" #include "qa/CanvasConfig.h" #include "qa/HistogramContainer.h" #include "qa/TaskProperties.h" -#include "base/HistogramSender.h" #include <boost/serialization/forward_list.hpp> @@ -79,10 +79,15 @@ namespace cbm::algo::qa void RegisterNewTask(std::string_view name); private: - qa::HistogramContainer fHistograms; ///< Histograms container + qa::HistogramContainer fHistograms; ///< A container of histograms, which forms a zmq message std::string fsTaskNames; ///< A string containing names of tasks 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 }; // ------------------------------------------------------------------------------------------------------------------- @@ -92,21 +97,25 @@ namespace cbm::algo::qa { if constexpr (std::is_same_v<Obj, cbm::algo::qa::H1D>) { Obj* res = &(fHistograms.fvH1.emplace_front(args...)); + ++fNofH1; fvTaskProperties.back().fRangeH1.first = fHistograms.fvH1.begin(); return res; } else if constexpr (std::is_same_v<Obj, cbm::algo::qa::H2D>) { Obj* res = &(fHistograms.fvH2.emplace_front(args...)); + ++fNofH2; fvTaskProperties.back().fRangeH2.first = fHistograms.fvH2.begin(); return res; } else if constexpr (std::is_same_v<Obj, cbm::algo::qa::Prof1D>) { Obj* res = &(fHistograms.fvP1.emplace_front(args...)); + ++fNofP1; fvTaskProperties.back().fRangeP1.first = fHistograms.fvP1.begin(); return res; } else if constexpr (std::is_same_v<Obj, cbm::algo::qa::Prof2D>) { Obj* res = &(fHistograms.fvP2.emplace_front(args...)); + ++fNofP2; fvTaskProperties.back().fRangeP2.first = fHistograms.fvP2.begin(); return res; } diff --git a/algo/qa/QaManager.cxx b/algo/qa/QaManager.cxx new file mode 100644 index 0000000000000000000000000000000000000000..dc831fa2ecc0f92f4c58a3c05df5c74a785908ef --- /dev/null +++ b/algo/qa/QaManager.cxx @@ -0,0 +1,26 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file QaManager.cxx +/// \date 09.02.2025 +/// \brief QA manager for the online data reconstruction +/// \author Sergei Zharko <s.zharko@gsi.de> + +#include "qa/QaManager.h" + +using cbm::algo::HistogramSender; +using cbm::algo::qa::Data; +using cbm::algo::qa::Manager; + +// --------------------------------------------------------------------------------------------------------------------- +// +Manager::Manager(std::shared_ptr<HistogramSender> histoSender) : fpSender(histoSender) {} + +// --------------------------------------------------------------------------------------------------------------------- +// +void Manager::Init() { fpData->Init(fpSender); } + +// --------------------------------------------------------------------------------------------------------------------- +// +void Manager::SendHistograms() { fpData->Send(fpSender); } diff --git a/algo/qa/QaManager.h b/algo/qa/QaManager.h new file mode 100644 index 0000000000000000000000000000000000000000..4a291800c53d2681905e1bd7ba4179e0a784cc63 --- /dev/null +++ b/algo/qa/QaManager.h @@ -0,0 +1,59 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file QaManager.h +/// \date 09.02.2025 +/// \brief QA manager for the online data reconstruction +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#include "base/HistogramSender.h" +#include "base/SubChain.h" +#include "qa/QaData.h" + +namespace cbm::algo::qa +{ + /// \class Manager + /// \brief A central class to manage the histogram storage and sending to the histogram server + class Manager : public SubChain { + public: + /// \brief Constructor + /// \param histoSender A histogram sender instance + Manager(std::shared_ptr<HistogramSender> histoSender = nullptr); + + /// \brief Copy constructor + Manager(const Manager&) = delete; + + /// \brief Move constructor + Manager(Manager&&) = delete; + + /// \brief Destructor + ~Manager() = delete; + + /// \brief Copy assignment operator + Manager& operator=(const Manager&) = delete; + + /// \brief Move assignment operator + Manager& operator=(Manager&&) = delete; + + /// \brief Gets an instance of QA data + std::shared_ptr<Data> GetData() { return fpData; } + + /// \brief Initializes the instance and sends the histogram and canvas configuration to the server + void Init(); + + /// \brief Sends a collection of histograms to the server + /// \note Resets the histograms after sending them + void SendHistograms(); + + /// \brief Sets a timeslice index + /// \param timesliceId A timeslice index + void SetTimesliceId(uint64_t timesliceId) { fpData->SetTimesliceId(timesliceId); } + + private: + std::shared_ptr<HistogramSender> fpSender{nullptr}; ///< Histogram sender + std::shared_ptr<Data> fpData{std::make_shared<Data>()}; ///< Instance of QA Data + }; +} // namespace cbm::algo::qa diff --git a/algo/qa/TaskProperties.h b/algo/qa/TaskProperties.h index 377be8d7777bc2e26e5b10afd7a77eb96bed8dde..ec012b907cd9e29c41cebfc4e9e53ded7272b451 100644 --- a/algo/qa/TaskProperties.h +++ b/algo/qa/TaskProperties.h @@ -20,7 +20,7 @@ namespace cbm::algo::qa /// \struct HistogramContainer /// \brief Structure to keep the histograms for sending them on the histogram server struct TaskProperties { - template <class H> + template<class H> using IteratorPair_t = std::pair<typename std::forward_list<H>::iterator, typename std::forward_list<H>::iterator>; std::string fsName; ///< Name of the task @@ -30,4 +30,3 @@ namespace cbm::algo::qa IteratorPair_t<qa::Prof2D> fRangeP2; ///< A pair (begin, end) for 2D-profiles in the task }; } // namespace cbm::algo::qa - diff --git a/services/histserv/app/CMakeLists.txt b/services/histserv/app/CMakeLists.txt index 1435a08a01fb108180571d30f0f8f74592a05809..7a8ebfe9f87dbd248508267785f09f0fcd21734e 100644 --- a/services/histserv/app/CMakeLists.txt +++ b/services/histserv/app/CMakeLists.txt @@ -28,7 +28,7 @@ add_executable(histserv_nofairmq ${SRCS} ${HEADERS}) target_link_libraries(histserv_nofairmq PUBLIC - Algo + AlgoOffline CbmQaBase CbmFlibFlesTools CbmServicesHistServ