From 57b89c82d9384ed0c48ad0be5cbdf37321efa920 Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Mon, 10 Feb 2025 00:28:32 +0100 Subject: [PATCH 1/4] online: processing of multiple tasks in a single qa::Data instance --- algo/qa/QaData.cxx | 52 +++++++++++++++++++++++++++------------- algo/qa/QaData.h | 42 +++++++++++++++++++++----------- algo/qa/TaskProperties.h | 33 +++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 30 deletions(-) create mode 100644 algo/qa/TaskProperties.h diff --git a/algo/qa/QaData.cxx b/algo/qa/QaData.cxx index 1ead168f18..235bb3ddbf 100644 --- a/algo/qa/QaData.cxx +++ b/algo/qa/QaData.cxx @@ -13,6 +13,7 @@ using cbm::algo::qa::Data; + // --------------------------------------------------------------------------------------------------------------------- // void Data::Init(std::shared_ptr<HistogramSender> histSender) @@ -28,20 +29,22 @@ try { nHistograms += std::distance(fHistograms.fvP2.begin(), fHistograms.fvP2.end()); vHistCfgs.reserve(nHistograms); - 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); - std::for_each(fHistograms.fvP1.begin(), fHistograms.fvP1.end(), RegHist); - std::for_each(fHistograms.fvP2.begin(), fHistograms.fvP2.end(), RegHist); + for (const auto& task: fvTaskProperties) { + 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(), task.fsName); + }; + fsTaskNames += fmt::format("{} ", task.fsName); + std::for_each(task.fRangeH1.first, task.fRangeH1.second, RegHist); + std::for_each(task.fRangeH2.first, task.fRangeH2.second, RegHist); + std::for_each(task.fRangeP1.first, task.fRangeP1.second, RegHist); + std::for_each(task.fRangeP2.first, task.fRangeP2.second, RegHist); + } // Forming a canvas config message std::vector<std::pair<std::string, std::string>> vCanvCfgs; @@ -63,10 +66,27 @@ try { } } catch (const std::exception& err) { - L_(fatal) << "cbm::algo::qa::Data for " << fsName << " fatally aborted. Reason " << err.what(); + L_(fatal) << "cbm::algo::qa::Data for " << fsTaskNames << " fatally aborted. Reason " << err.what(); assert(false); } +// --------------------------------------------------------------------------------------------------------------------- +// +void Data::RegisterNewTask(std::string_view name) +{ + auto itH1 = fHistograms.fvH1.begin(); + 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) + }); +} + // --------------------------------------------------------------------------------------------------------------------- // void Data::Send(std::shared_ptr<HistogramSender> histoSender) @@ -76,7 +96,7 @@ void Data::Send(std::shared_ptr<HistogramSender> histoSender) 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) << fsName << ": Published " << nH1 << " 1D- and " << nH2 << " 2D-histograms, " << nP1 << " 1D- and " << nP2 + L_(info) << fsTaskNames << ": Published " << nH1 << " 1D- and " << nH2 << " 2D-histograms, " << nP1 << " 1D- and " << nP2 << " 2D-profiles"; this->Reset(); } diff --git a/algo/qa/QaData.h b/algo/qa/QaData.h index 0c87df69c5..fcb1afced2 100644 --- a/algo/qa/QaData.h +++ b/algo/qa/QaData.h @@ -10,9 +10,10 @@ #pragma once #include "AlgoFairloggerCompat.h" -#include "CanvasConfig.h" -#include "HistogramContainer.h" -#include "HistogramSender.h" +#include "qa/CanvasConfig.h" +#include "qa/HistogramContainer.h" +#include "qa/TaskProperties.h" +#include "base/HistogramSender.h" #include <boost/serialization/forward_list.hpp> @@ -27,9 +28,12 @@ namespace cbm::algo::qa /// \brief Class to handle QA-objects in the online reconstruction class Data { public: + /// \brief Default constructor + Data() = default; + /// \brief Constructor /// \param name Name of the QA module (appears as the directory name in the output) - Data(std::string_view name) : fsName(name) {} + Data(std::string_view name) { RegisterNewTask(name); } /// \brief Copy constructor Data(const Data&) = default; @@ -50,9 +54,6 @@ namespace cbm::algo::qa /// \param canvas A CanvasConfig object void AddCanvasConfig(const CanvasConfig& canvas) { fvsCanvCfgs.push_back(canvas.ToString()); } - /// \brief Gets module name - std::string_view GetName() const { return fsName; } - /// \brief Sends QA initialization information to the HistogramSender /// \param histoSender A pointer to the histogram sender void Init(std::shared_ptr<HistogramSender> histoSender); @@ -73,10 +74,15 @@ namespace cbm::algo::qa /// \param timesliceId Timeslice index void SetTimesliceId(uint64_t timesliceId) { fHistograms.fTimesliceId = timesliceId; } + /// \brief Registers a new QA task + /// \param name Name of the task + void RegisterNewTask(std::string_view name); + private: - std::string fsName; ///< Name of the QA module (used as a directory name) - qa::HistogramContainer fHistograms; ///< Histograms container - std::vector<std::string> fvsCanvCfgs = {}; ///< Vector of canvas configs + qa::HistogramContainer fHistograms; ///< Histograms container + 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 }; // ------------------------------------------------------------------------------------------------------------------- @@ -85,16 +91,24 @@ namespace cbm::algo::qa Obj* Data::MakeObj(Args... args) { if constexpr (std::is_same_v<Obj, cbm::algo::qa::H1D>) { - return &(fHistograms.fvH1.emplace_front(args...)); + Obj* res = &(fHistograms.fvH1.emplace_front(args...)); + fvTaskProperties.back().fRangeH1.first = fHistograms.fvH1.begin(); + return res; } else if constexpr (std::is_same_v<Obj, cbm::algo::qa::H2D>) { - return &(fHistograms.fvH2.emplace_front(args...)); + Obj* res = &(fHistograms.fvH2.emplace_front(args...)); + fvTaskProperties.back().fRangeH2.first = fHistograms.fvH2.begin(); + return res; } else if constexpr (std::is_same_v<Obj, cbm::algo::qa::Prof1D>) { - return &(fHistograms.fvP1.emplace_front(args...)); + Obj* res = &(fHistograms.fvP1.emplace_front(args...)); + fvTaskProperties.back().fRangeP1.first = fHistograms.fvP1.begin(); + return res; } else if constexpr (std::is_same_v<Obj, cbm::algo::qa::Prof2D>) { - return &(fHistograms.fvP2.emplace_front(args...)); + Obj* res = &(fHistograms.fvP2.emplace_front(args...)); + fvTaskProperties.back().fRangeP2.first = fHistograms.fvP2.begin(); + return res; } return nullptr; } diff --git a/algo/qa/TaskProperties.h b/algo/qa/TaskProperties.h new file mode 100644 index 0000000000..377be8d777 --- /dev/null +++ b/algo/qa/TaskProperties.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file TaskProperties.h +/// \date 09.02.2025 +/// \brief QA-task properties structure +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#include "Histogram.h" // for H1D, H2D + +#include <forward_list> +#include <string> +#include <utility> + +namespace cbm::algo::qa +{ + /// \struct HistogramContainer + /// \brief Structure to keep the histograms for sending them on the histogram server + struct TaskProperties { + 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 + IteratorPair_t<qa::H1D> fRangeH1; ///< A pair (begin, end) for 1D-histograms in the task + IteratorPair_t<qa::H2D> fRangeH2; ///< A pair (begin, end) for 2D-histograms in the task + IteratorPair_t<qa::Prof1D> fRangeP1; ///< A pair (begin, end) for 1D-profiles in the task + IteratorPair_t<qa::Prof2D> fRangeP2; ///< A pair (begin, end) for 2D-profiles in the task + }; +} // namespace cbm::algo::qa + -- GitLab From 597d2276664ff8479fc403d25d117917260c2272 Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Mon, 10 Feb 2025 13:20:57 +0100 Subject: [PATCH 2/4] updates on online QA + bugfix of histogram server --- algo/qa/QaData.cxx | 44 ++++++++++++--------- algo/qa/QaData.h | 13 +++++- algo/qa/QaManager.cxx | 26 ++++++++++++ algo/qa/QaManager.h | 59 ++++++++++++++++++++++++++++ algo/qa/TaskProperties.h | 3 +- services/histserv/app/CMakeLists.txt | 2 +- 6 files changed, 124 insertions(+), 23 deletions(-) create mode 100644 algo/qa/QaManager.cxx create mode 100644 algo/qa/QaManager.h diff --git a/algo/qa/QaData.cxx b/algo/qa/QaData.cxx index 235bb3ddbf..5abee21fe5 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 fcb1afced2..9c47474401 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 0000000000..dc831fa2ec --- /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 0000000000..4a291800c5 --- /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 377be8d777..ec012b907c 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 1435a08a01..7a8ebfe9f8 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 -- GitLab 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 3/4] 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 From 9a7d6c300c4e4e1bdf177da1547f67d5097fe5c9 Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Mon, 10 Feb 2025 16:15:36 +0100 Subject: [PATCH 4/4] online-qa: moving the tracking QA on the new framework --- algo/ca/TrackingChain.cxx | 11 ++++++---- algo/ca/TrackingChain.h | 13 ++++++++---- algo/ca/qa/CaQa.cxx | 43 ++++++++++++++++++--------------------- algo/ca/qa/CaQa.h | 19 +++++++---------- algo/global/Reco.cxx | 11 +++++++--- algo/qa/QaTaskHeader.h | 17 ++++++++++++++-- 6 files changed, 66 insertions(+), 48 deletions(-) diff --git a/algo/ca/TrackingChain.cxx b/algo/ca/TrackingChain.cxx index 73b3d47f00..3810670e9f 100644 --- a/algo/ca/TrackingChain.cxx +++ b/algo/ca/TrackingChain.cxx @@ -1,4 +1,4 @@ -/* Copyright (C) 2023-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt +/* Copyright (C) 2023-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt SPDX-License-Identifier: GPL-3.0-only Authors: Sergei Zharko [committer] */ @@ -39,7 +39,10 @@ using cbm::algo::ca::constants::clrs::GNb; // grin bald text // --------------------------------------------------------------------------------------------------------------------- // -TrackingChain::TrackingChain(std::shared_ptr<cbm::algo::HistogramSender> histoSender) : fQa(Qa(histoSender)) {} +TrackingChain::TrackingChain(const std::unique_ptr<cbm::algo::qa::Manager>& qaManager, std::string_view name) + : fQa(Qa(qaManager, name)) +{ +} // --------------------------------------------------------------------------------------------------------------------- // @@ -90,7 +93,7 @@ void TrackingChain::Init() fCaFramework.Init(ca::TrackingMode::kMcbm); // ------ Initialize QA modules - if (fQa.IsSenderDefined()) { + if (fQa.IsActive()) { fQa.RegisterParameters(&fCaFramework.GetParameters()); fQa.Init(); } @@ -199,7 +202,7 @@ TrackingChain::Output_t TrackingChain::PrepareOutput() // QA - if (fQa.IsSenderDefined()) { + if (fQa.IsActive()) { fCaMonitorData.StartTimer(ca::ETimer::Qa); fQa.RegisterInputData(&fCaFramework.GetInputData()); fQa.RegisterTracks(&output.tracks); diff --git a/algo/ca/TrackingChain.h b/algo/ca/TrackingChain.h index e96735b5be..3f949d3605 100644 --- a/algo/ca/TrackingChain.h +++ b/algo/ca/TrackingChain.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt +/* Copyright (C) 2023-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt SPDX-License-Identifier: GPL-3.0-only Authors: Sergei Zharko [committer] */ @@ -15,7 +15,6 @@ #include "CaTrack.h" #include "CaTrackingMonitor.h" #include "CaVector.h" -#include "HistogramSender.h" #include "PartitionedSpan.h" #include "RecoResults.h" #include "SubChain.h" @@ -28,6 +27,11 @@ #include <memory> #include <vector> +namespace cbm::algo::qa +{ + class Manager; +} + namespace cbm::algo { /// \class cbm::algo::TrackingChain @@ -37,8 +41,9 @@ namespace cbm::algo class TrackingChain : public SubChain { public: /// \brief Constructor from parameters - /// \param histoSender A shared pointer to a histogram sender - TrackingChain(std::shared_ptr<HistogramSender> histoSender = nullptr); + /// \param pManager a QA-manager + /// \param name A name of the task (histograms directory) + TrackingChain(const std::unique_ptr<cbm::algo::qa::Manager>& qaManager = nullptr, std::string_view name = ""); /// \struct Input_t /// \brief Input to the TrackingChain diff --git a/algo/ca/qa/CaQa.cxx b/algo/ca/qa/CaQa.cxx index 2184256e92..05815198dd 100644 --- a/algo/ca/qa/CaQa.cxx +++ b/algo/ca/qa/CaQa.cxx @@ -1,4 +1,4 @@ -/* Copyright (C) 2023-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt +/* Copyright (C) 2023-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt SPDX-License-Identifier: GPL-3.0-only Authors: Sergei Zharko [committer] */ @@ -61,7 +61,7 @@ void Qa::Init() using cbm::algo::qa::Prof2D; using fmt::format; - if (!fpSender.get()) { + if (!IsActive()) { return; } @@ -122,26 +122,26 @@ void Qa::Init() auto titl = format("{} hit occupancy in XY plane for station {} ({}{});x [cm];y [cm]", setTl, iSt, kDetName[detID], iStLoc); fvphHitOccupXY[iSt][hitSet] = - fQaData.MakeObj<H2D>(name, titl, nBinsXY, vMinX[iSt], vMaxX[iSt], nBinsXY, vMinY[iSt], vMaxY[iSt]); + MakeObj<H2D>(name, titl, nBinsXY, vMinX[iSt], vMaxX[iSt], nBinsXY, vMinY[iSt], vMaxY[iSt]); } { auto name = format("hit_{}_occup_zx_sta_{}", setNm, iSt); auto titl = format("{} hit occupancy in ZX plane for station {} ({}{});z [cm];x [cm]", setTl, iSt, kDetName[detID], iStLoc); - fvphHitOccupZX[iSt][hitSet] = fQaData.MakeObj<H2D>(name, titl, nBinsZ, zMinA, zMaxA, nBinsXY, xMinA, xMaxA); + fvphHitOccupZX[iSt][hitSet] = MakeObj<H2D>(name, titl, nBinsZ, zMinA, zMaxA, nBinsXY, xMinA, xMaxA); } if (kDebug) { auto name = format("hit_{}_occup_zy_sta_{}", setNm, iSt); auto titl = format("{} hit occupancy in ZY plane for station {} ({}{});z [cm];y [cm]", setTl, iSt, kDetName[detID], iStLoc); - fvphHitOccupZY[iSt][hitSet] = fQaData.MakeObj<H2D>(name, titl, nBinsZ, zMinA, zMaxA, nBinsXY, yMinA, yMaxA); + fvphHitOccupZY[iSt][hitSet] = MakeObj<H2D>(name, titl, nBinsZ, zMinA, zMaxA, nBinsXY, yMinA, yMaxA); } } if (kDebug) { auto name = format("hit_usage_xy_sta_{}", iSt); auto titl = format("Hit usage in XY plane for station {} ({}{});x [cm];y [cm]", iSt, kDetName[detID], iStLoc); fvphHitUsageXY[iSt] = - fQaData.MakeObj<Prof2D>(name, titl, nBinsXY, vMinX[iSt], vMaxX[iSt], nBinsXY, vMinY[iSt], vMaxY[iSt], 0., 1.); + MakeObj<Prof2D>(name, titl, nBinsXY, vMinX[iSt], vMaxX[iSt], nBinsXY, vMinY[iSt], vMaxY[iSt], 0., 1.); } } if (kDebug) { @@ -152,12 +152,12 @@ void Qa::Init() { auto name = format("hit_{}_front_key_index", setNm); auto titl = format("{} hit front key index;ID_{{key}}/N_{{keys}};Count", setTl); - fvphHitFrontKeyIndex[hitSet] = fQaData.MakeObj<H1D>(name, titl, NBins, 0., 1.); + fvphHitFrontKeyIndex[hitSet] = MakeObj<H1D>(name, titl, NBins, 0., 1.); } { auto name = format("hit_{}_back_key_index", setNm); auto titl = format("{} hit back key index;ID_{{key}}/N_{{keys}};Count", setTl); - fvphHitBackKeyIndex[hitSet] = fQaData.MakeObj<H1D>(name, titl, NBins, 0., 1.); + fvphHitBackKeyIndex[hitSet] = MakeObj<H1D>(name, titl, NBins, 0., 1.); } } } @@ -173,7 +173,7 @@ void Qa::Init() auto setTl = EHitSet::Input == hitSet ? "Input" : "Used"; auto name = format("hit_{}_rel_time{}", setNm, staNm); auto titl = format("{} hit relative time{}; #delta t_{{hit}};Count", setTl, staTl); - fvphHitTime[iSt][hitSet] = fQaData.MakeObj<H1D>(name, titl, 10000, -0.1, 1.1); + fvphHitTime[iSt][hitSet] = MakeObj<H1D>(name, titl, 10000, -0.1, 1.1); } } } @@ -189,22 +189,22 @@ void Qa::Init() { auto sName = format("track_{}_theta", vsPointName[i]); auto sTitl = format("#theta at {} hit; #theta", vsPointName[i]); - fvphTrkTheta[i] = fQaData.MakeObj<H1D>(sName, sTitl, 62, 0., 90.); + fvphTrkTheta[i] = MakeObj<H1D>(sName, sTitl, 62, 0., 90.); } { auto sName = format("track_{}_phi", vsPointName[i]); auto sTitl = format("#phi at {} hit; #phi", vsPointName[i]); - fvphTrkPhi[i] = fQaData.MakeObj<H1D>(sName, sTitl, 62, -180., 180.); + fvphTrkPhi[i] = MakeObj<H1D>(sName, sTitl, 62, -180., 180.); } { auto sName = format("track_{}_thata_phi", vsPointName[i]); auto sTitl = format("#theta vs #phi at {} hit; #phi; #theta", vsPointName[i]); - fvphTrkPhiTheta[i] = fQaData.MakeObj<H2D>(sName, sTitl, 62, -180., 180., 62, 0., 90.); + fvphTrkPhiTheta[i] = MakeObj<H2D>(sName, sTitl, 62, -180., 180., 62, 0., 90.); } { auto sName = format("track_{}_chi2_ndf", vsPointName[i]); auto sTitl = format("#chi^{{2}}/NDF at {} hit; #chi^{{2}}/NDF", vsPointName[i]); - fvphTrkChi2Ndf[i] = fQaData.MakeObj<H1D>(sName, sTitl, 100, 0., 20.); + fvphTrkChi2Ndf[i] = MakeObj<H1D>(sName, sTitl, 100, 0., 20.); } } { @@ -214,9 +214,9 @@ void Qa::Init() { auto sName = "track_fst_lst_sta"; auto sTitl = "First vs. last station index;ID^{last}_{station};ID^{first}_{station}"; - fphTrkFstLstSta = fQaData.MakeObj<H2D>(sName, sTitl, nBins, xMin, xMax, nBins, xMin, xMax); + fphTrkFstLstSta = MakeObj<H2D>(sName, sTitl, nBins, xMin, xMax, nBins, xMin, xMax); } - fphTrkNofHits = fQaData.MakeObj<H1D>("n_hits", "Number of hits;N_{hit}", nBins, xMin, xMax); + fphTrkNofHits = MakeObj<H1D>("n_hits", "Number of hits;N_{hit}", nBins, xMin, xMax); } // ---- Init canvases @@ -235,7 +235,7 @@ void Qa::Init() pad.RegisterHistogram(fvphHitOccupXY[iSt][hitSet], "colz"); canv.AddPadConfig(pad); } - fQaData.AddCanvasConfig(canv); + AddCanvasConfig(canv); } { // ZX and ZY auto name = format("ca_hit_{}_occupancy_zx_zy", setNm); @@ -255,7 +255,7 @@ void Qa::Init() } canv.AddPadConfig(pad); } - fQaData.AddCanvasConfig(canv); + AddCanvasConfig(canv); } } if (kDebug) { @@ -267,7 +267,7 @@ void Qa::Init() pad.RegisterHistogram(fvphHitUsageXY[iSt], "colz"); canv.AddPadConfig(pad); } - fQaData.AddCanvasConfig(canv); + AddCanvasConfig(canv); } } @@ -294,9 +294,8 @@ void Qa::Init() pad.RegisterHistogram(fphTrkFstLstSta, "colz"); canv.AddPadConfig(pad); } - fQaData.AddCanvasConfig(canv); + AddCanvasConfig(canv); } - fQaData.Init(fpSender); } } @@ -304,7 +303,7 @@ void Qa::Init() // void Qa::Exec() { - if (!fpSender.get()) { + if (!IsActive()) { return; } @@ -375,8 +374,6 @@ void Qa::Exec() trkFirstHit += nHits; } } - - fQaData.Send(fpSender); } // --------------------------------------------------------------------------------------------------------------------- diff --git a/algo/ca/qa/CaQa.h b/algo/ca/qa/CaQa.h index f0c0175a3b..655d6fa50b 100644 --- a/algo/ca/qa/CaQa.h +++ b/algo/ca/qa/CaQa.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt +/* Copyright (C) 2023-2025 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt SPDX-License-Identifier: GPL-3.0-only Authors: Sergei Zharko [committer] */ @@ -13,7 +13,7 @@ #include "CaHit.h" // for HitIndex_t #include "CaTimesliceHeader.h" #include "CaVector.h" -#include "QaData.h" // QA data +#include "qa/QaTaskHeader.h" namespace cbm::algo { @@ -21,6 +21,7 @@ namespace cbm::algo { class H1D; class H2D; + class Manager; } // namespace qa namespace ca { @@ -36,7 +37,7 @@ namespace cbm::algo::ca /// \class cbm::algo::ca::qa::Qa /// \brief Qa class for the CA tracking QA (header) /// - class Qa { + class Qa : public qa::TaskHeader { /// \brief Hit set entries enum class EHitSet { @@ -54,8 +55,9 @@ namespace cbm::algo::ca public: /// \brief Default destructor - /// \param pSender Pointer to the histogram sender - Qa(std::shared_ptr<HistogramSender> pSender) : fQaData("CA"), fpSender(pSender) {} + /// \param pManager Pointer to the QA manager + /// \param name Name of the QA (directory) + Qa(const std::unique_ptr<qa::Manager>& pManager, std::string_view name) : qa::TaskHeader(pManager, name) {} /// \brief Constructor from the configuration object /// \param config QA configuration object @@ -87,9 +89,6 @@ namespace cbm::algo::ca /// \return false Some of are not initialized bool CheckInit() const; - /// \brief Checks, if the histogram sender is defined - bool IsSenderDefined() const { return static_cast<bool>(fpSender.get()); } - /// \brief Registers tracking input data object /// \note Call per TS void RegisterInputData(const InputData* pInputData) { fpInputData = pInputData; } @@ -122,10 +121,6 @@ namespace cbm::algo::ca double fMinHitTime = std::numeric_limits<double>::max(); double fMaxHitTime = std::numeric_limits<double>::lowest(); - // utility - qa::Data fQaData; ///< QA data - - std::shared_ptr<HistogramSender> fpSender = nullptr; ///< Histogram sender const Parameters<fvec>* fpParameters = nullptr; ///< Pointer to tracking parameters const InputData* fpInputData = nullptr; ///< Pointer to input data const Vector<Track>* fpvTracks = nullptr; ///< Pointer to tracks vector diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 28acffb8b3..e9a0a7a9a0 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -1,6 +1,6 @@ -/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main +/* Copyright (C) 2023-2025 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main SPDX-License-Identifier: GPL-3.0-only - Authors: Felix Weiglhofer [committer], P.-A. Loizeau */ + Authors: Felix Weiglhofer [committer], P.-A. Loizeau, Sergei Zharko */ #include "Reco.h" #include "AlgoFairloggerCompat.h" @@ -222,7 +222,12 @@ void Reco::Init(const Options& opts) // Tracking if (Opts().Has(Step::Tracking)) { - fTracking = std::make_unique<TrackingChain>(Opts().Has(QaStep::Tracking) ? fSender : nullptr); + if (Opts().Has(QaStep::Tracking)) { + fTracking = std::make_unique<TrackingChain>(fQaManager, "CaTimeslice"); + } + else { + fTracking = std::make_unique<TrackingChain>(); + } fTracking->RegisterSetup(pTrackingSetup); fTracking->SetContext(&fContext); fTracking->Init(); diff --git a/algo/qa/QaTaskHeader.h b/algo/qa/QaTaskHeader.h index 4038cd0d3e..ca41383152 100644 --- a/algo/qa/QaTaskHeader.h +++ b/algo/qa/QaTaskHeader.h @@ -22,7 +22,14 @@ namespace cbm::algo::qa public: /// \brief Constructor /// \param pManager a QA-manager - TaskHeader(const std::unique_ptr<Manager>& pManager) : fpData(pManager->GetData()) {} + /// \param name A name of the task (histograms directory) + TaskHeader(const std::unique_ptr<Manager>& pManager, std::string_view name) + : fpData(pManager != nullptr ? pManager->GetData() : nullptr) + { + if (fpData != nullptr) { + fpData->RegisterNewTask(name); + } + } /// \brief Copy constructor TaskHeader(const TaskHeader&) = delete; @@ -39,6 +46,12 @@ namespace cbm::algo::qa /// \brief Move assignment operator TaskHeader& operator=(TaskHeader&&) = delete; + /// \brief Checks, if the task is active + /// + /// The task can be inactive, if a nullptr qa::Manager was passed to the constructor. If it is the case, + /// the fpData instance is not defined, and no actions on the task should be performed + bool IsActive() const { return static_cast<bool>(fpData != nullptr); } + protected: /// \brief Adds a canvas configuration /// \param canvas A CanvasConfig object @@ -51,7 +64,7 @@ namespace cbm::algo::qa template<class Obj, typename... Args> Obj* MakeObj(Args... args) { - fpData->MakeObj<Obj>(args...); + return fpData->MakeObj<Obj>(args...); } private: -- GitLab