From e3d000c155b613b2781c3ebe14a7378d1b4ed3f3 Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Mon, 20 Nov 2023 22:01:26 +0100 Subject: [PATCH] ca: QA module for online reconstruction --- algo/CMakeLists.txt | 11 +++++ algo/ca/TrackingChain.cxx | 38 ++++++++++++++++ algo/ca/TrackingChain.h | 18 ++++++-- algo/ca/core/CMakeLists.txt | 3 ++ algo/ca/core/data/CaHit.h | 1 + algo/ca/qa/CaQaBuilder.cxx | 67 ++++++++++++++++++++++++++++ algo/ca/qa/CaQaBuilder.h | 85 ++++++++++++++++++++++++++++++++++++ algo/ca/qa/CaQaConfig.cxx | 84 +++++++++++++++++++++++++++++++++++ algo/ca/qa/CaQaConfig.h | 61 ++++++++++++++++++++++++++ algo/ca/qa/CaQaData.cxx | 38 ++++++++++++++++ algo/ca/qa/CaQaData.h | 63 ++++++++++++++++++++++++++ algo/ca/qa/CaQaDefinitions.h | 59 +++++++++++++++++++++++++ algo/global/Reco.cxx | 9 ++-- algo/global/Reco.h | 2 +- 14 files changed, 530 insertions(+), 9 deletions(-) create mode 100644 algo/ca/qa/CaQaBuilder.cxx create mode 100644 algo/ca/qa/CaQaBuilder.h create mode 100644 algo/ca/qa/CaQaConfig.cxx create mode 100644 algo/ca/qa/CaQaConfig.h create mode 100644 algo/ca/qa/CaQaData.cxx create mode 100644 algo/ca/qa/CaQaData.h create mode 100644 algo/ca/qa/CaQaDefinitions.h diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt index 01de74a9e6..b57bfe43b8 100644 --- a/algo/CMakeLists.txt +++ b/algo/CMakeLists.txt @@ -111,6 +111,9 @@ set(SRCS qa/DigiEventQa.cxx qa/Histo1D.cxx ca/TrackingChain.cxx + ca/qa/CaQaBuilder.cxx + ca/qa/CaQaConfig.cxx + ca/qa/CaQaData.cxx ) set(BUILD_INFO_CXX ${CMAKE_CURRENT_BINARY_DIR}/base/BuildInfo.cxx) @@ -142,6 +145,7 @@ target_include_directories(Algo ${CMAKE_CURRENT_SOURCE_DIR}/unpack ${CMAKE_CURRENT_SOURCE_DIR}/detectors ${CMAKE_CURRENT_SOURCE_DIR}/qa + ${CMAKE_CURRENT_SOURCE_DIR}/ca/qa ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/core/data/global ) @@ -202,6 +206,7 @@ install(DIRECTORY detectors/sts TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY detectors/tof TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY detectors/trd TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY detectors/trd2d TYPE INCLUDE FILES_MATCHING PATTERN "*.h") +install(DIRECTORY ca/qa TYPE INCLUDE FILES_MATCHING PATTERN "*.h") install(DIRECTORY ca TYPE INCLUDE FILES_MATCHING PATTERN "*.h") @@ -221,6 +226,12 @@ install( global/RecoResultsOutputArchive.h global/StorableRecoResults.h ca/TrackingChain.h + # NOTE: SZh 20.11.2023: + # The ca/qa directory depends on the online qa classes, so for now it has to be a part of the Algo library. + ca/qa/CaQaBuilder.h + ca/qa/CaQaConfig.h + ca/qa/CaQaData.h + ca/qa/CaQaDefinitions.h DESTINATION include/ ) diff --git a/algo/ca/TrackingChain.cxx b/algo/ca/TrackingChain.cxx index e38cf8977a..ee7774c52b 100644 --- a/algo/ca/TrackingChain.cxx +++ b/algo/ca/TrackingChain.cxx @@ -33,6 +33,27 @@ using cbm::algo::ca::Track; using cbm::algo::ca::constants::clrs::CL; // clear text using cbm::algo::ca::constants::clrs::GNb; // grin bald text +// --------------------------------------------------------------------------------------------------------------------- +// +TrackingChain::TrackingChain(std::shared_ptr<HistogramSender> histoSender) : fpSender(histoSender) +{ + // ------ Initialize the histogram sender + if (fpSender) { + auto histCfgs = fQaBuilder.GetConfig().GetHistogramConfigs(); + auto canvCfgs = fQaBuilder.GetConfig().GetCanvasConfigs(); + fpSender->PrepareAndSendMsg(std::pair<uint32_t, uint32_t>(histCfgs.size(), canvCfgs.size()), + zmq::send_flags::sndmore); + for (const auto& cfg : histCfgs) { + fpSender->PrepareAndSendMsg(cfg, zmq::send_flags::sndmore); + } + for (const auto& cfg : canvCfgs) { + fpSender->PrepareAndSendMsg(cfg, zmq::send_flags::sndmore); + } + // Histograms serialization and emission to close multi-part message + fpSender->PrepareAndSendMsg(std::vector<Histo1D> {}, zmq::send_flags::none); + } +} + // --------------------------------------------------------------------------------------------------------------------- // void TrackingChain::Init() @@ -51,6 +72,9 @@ void TrackingChain::Init() fCaMonitor.Reset(); fCaFramework.Init(ca::Framework::TrackingMode::kMcbm); fCaFramework.ReceiveParameters(std::move(parameters)); + + // ------ Initialize QA builder + fQaBuilder.RegisterParameters(&fCaFramework.GetParameters()); } // --------------------------------------------------------------------------------------------------------------------- @@ -133,6 +157,19 @@ TrackingChain::Output_t TrackingChain::PrepareOutput() fCaMonitor.AddMonitorData(fCaMonitorData); output.monitorData = fCaMonitorData; + + // QA + if (fpSender) { + fQaBuilder.RegisterInputData(&fCaFramework.GetInputData()); + fQaBuilder.RegisterTracks(&output.tracks); + fQaBuilder.RegisterRecoHitIndices(&fCaFramework.fRecoHits); + auto qaData = fQaBuilder.Build(); + L_(info) << "TrackingChain: " << qaData.ToString(); + fpSender->PrepareAndSendMsg(qaData.VectorOfH1(), zmq::send_flags::none); + L_(info) << "TrackingChain: Published " << qaData.VectorOfH1().size() << " 1D-histograms"; + } + + return output; } @@ -199,6 +236,7 @@ void TrackingChain::ReadHits(PartitionedSpan<const ca::HitTypes_t::at<DetID>> hi caHit.SetRangeX(3.5 * hit.Dx()); caHit.SetRangeY(3.5 * hit.Dy()); caHit.SetRangeT(3.5 * hit.TimeError()); + //L_(info) << ">>>>>>>>>>>> " << iStActive; caHit.SetStation(iStActive); caHit.SetId(fCaDataManager.GetNofHits()); if (caHit.Check()) { diff --git a/algo/ca/TrackingChain.h b/algo/ca/TrackingChain.h index b85ff45614..c750d9d7ce 100644 --- a/algo/ca/TrackingChain.h +++ b/algo/ca/TrackingChain.h @@ -12,13 +12,17 @@ #include "TrackingDefs.h" #include "tof/Hit.h" +#include <memory> #include <vector> #include "CaDataManager.h" #include "CaFramework.h" +#include "CaQaBuilder.h" +#include "CaQaConfig.h" #include "CaTrack.h" #include "CaTrackingMonitor.h" #include "CaVector.h" +#include "HistogramSender.h" #include "PartitionedSpan.h" #include "RecoResults.h" #include "SubChain.h" @@ -32,6 +36,10 @@ namespace cbm::algo /// The class executes a tracking algorithm in the online data reconstruction chain. 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); + /// \struct Input_t /// \brief Input to the TrackingChain struct Input_t { @@ -94,10 +102,12 @@ namespace cbm::algo // ************************* // ** Framework variables - ca::TrackingMonitor fCaMonitor {}; ///< CA internal monitor (debug purposes) - ca::TrackingMonitorData fCaMonitorData {}; ///< CA monitor data object - ca::Framework fCaFramework {}; ///< CA framework instance - ca::DataManager fCaDataManager {}; ///< CA data manager + ca::TrackingMonitor fCaMonitor {}; ///< CA internal monitor (debug purposes) + ca::TrackingMonitorData fCaMonitorData {}; ///< CA monitor data object + ca::Framework fCaFramework {}; ///< CA framework instance + ca::DataManager fCaDataManager {}; ///< CA data manager + ca::qa::Builder fQaBuilder {ca::qa::Config()}; ///< CA QA builder + std::shared_ptr<HistogramSender> fpSender; ///< Histogram sender // ************************ // ** Auxilary variables diff --git a/algo/ca/core/CMakeLists.txt b/algo/ca/core/CMakeLists.txt index 544b54bd64..36d86f93bc 100644 --- a/algo/ca/core/CMakeLists.txt +++ b/algo/ca/core/CMakeLists.txt @@ -2,6 +2,7 @@ set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/utils ${CMAKE_CURRENT_SOURCE_DIR}/pars + ${CMAKE_CURRENT_SOURCE_DIR}/qa ${CMAKE_CURRENT_SOURCE_DIR}/data ${CMAKE_CURRENT_SOURCE_DIR}/tracking ) @@ -45,6 +46,7 @@ target_include_directories(CaCore PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/data ${CMAKE_CURRENT_SOURCE_DIR}/utils ${CMAKE_CURRENT_SOURCE_DIR}/pars + ${CMAKE_CURRENT_SOURCE_DIR}/qa ${CMAKE_CURRENT_SOURCE_DIR}/tracking ${CMAKE_CURRENT_SOURCE_DIR} ) @@ -91,6 +93,7 @@ install( pars/CaSearchWindow.h pars/CaStation.h pars/CaStationInitializer.h + utils/CaTrackingMonitor.h utils/CaEnumArray.h utils/CaMonitor.h diff --git a/algo/ca/core/data/CaHit.h b/algo/ca/core/data/CaHit.h index 0020fd809c..1a9c17e6a6 100644 --- a/algo/ca/core/data/CaHit.h +++ b/algo/ca/core/data/CaHit.h @@ -17,6 +17,7 @@ namespace cbm::algo::ca { + // FIXME: Move typedefs to another header (potential problems with dependencies) using HitIndex_t = unsigned int; ///< Index of ca::Hit using HitKeyIndex_t = unsigned int; ///< Index of the hit key (e.g. front / back cluster id for STS) diff --git a/algo/ca/qa/CaQaBuilder.cxx b/algo/ca/qa/CaQaBuilder.cxx new file mode 100644 index 0000000000..38b3651594 --- /dev/null +++ b/algo/ca/qa/CaQaBuilder.cxx @@ -0,0 +1,67 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CaQaBuilder.cxx +/// \date 20.11.2023 +/// \brief A QA module for CA tracking (implementation) +/// \author S.Zharko <s.zharko@gsi.de> + +#include "CaQaBuilder.h" + +#include "CaConstants.h" +#include "CaInputData.h" +#include "CaParameters.h" +#include "CaTrack.h" + +using cbm::algo::ca::constants::math::Pi; +using cbm::algo::ca::qa::Builder; +using cbm::algo::ca::qa::Config; +using cbm::algo::ca::qa::Data; +using cbm::algo::ca::qa::H1Key; + +// --------------------------------------------------------------------------------------------------------------------- +// +Data Builder::Build() +{ + Data res(fConfig); + + if (!fpParameters) { + LOG(error) << "cbm::algo::ca::qa::Builder::Build(): parameters object is undefined"; + return res; + } + if (!fpInputData) { + LOG(error) << "cbm::algo::ca::qa::Builder::Build(): input data object is undefined"; + return res; + } + if (!fpvTracks) { + LOG(error) << "cbm::algo::ca::qa::Builder::Build(): tracks vector is undefined"; + return res; + } + if (!fpvRecoHits) { + LOG(error) << "cbm::algo::ca::qa::Builder::Build(): reco hit indices vector is undefined"; + return res; + } + + // Fill track histograms + int trkFirstHit = 0; // Index of hit in fpvRecoHits + int iTr = 0; + for (auto& track : (*fpvTracks)) { + int nHits = track.fNofHits; + // Indices of hits in fpInputData->GetHits() + int iFstHit = (*fpvRecoHits)[trkFirstHit]; + int iLstHit = (*fpvRecoHits)[trkFirstHit + nHits - 1]; + + //res.H1(H1Key::TrackFirstTx).Add(track.fParFirst.GetTx()); + //res.H1(H1Key::TrackFirstTy).Add(track.fParFirst.GetTy()); + res.H1(H1Key::FstTrkTheta).Add(track.fParFirst.GetTheta() * 180. / Pi); + res.H1(H1Key::FstTrkPhi).Add(track.fParFirst.GetPhi() * 180. / Pi); + res.H1(H1Key::FstChi2Ndf).Add(track.fParFirst.GetChiSq() / track.fParFirst.GetNdf()); + res.H1(H1Key::FstHitSta).Add(fpInputData->GetHit(iFstHit).Station()); + res.H1(H1Key::LstHitSta).Add(fpInputData->GetHit(iLstHit).Station()); + res.H1(H1Key::TrkNofHits).Add(nHits); + trkFirstHit += nHits; + } + + return res; +} diff --git a/algo/ca/qa/CaQaBuilder.h b/algo/ca/qa/CaQaBuilder.h new file mode 100644 index 0000000000..26615bc76e --- /dev/null +++ b/algo/ca/qa/CaQaBuilder.h @@ -0,0 +1,85 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CaQaBuilder.h +/// \date 20.11.2023 +/// \brief A QA module for CA tracking (header) +/// \author S.Zharko <s.zharko@gsi.de> + +#pragma once + +#include "CaHit.h" // for HitIndex_t +#include "CaQaBuilder.h" +#include "CaQaData.h" +#include "CaVector.h" + +namespace cbm::algo::ca +{ + class Parameters; + class InputData; + class Track; +} // namespace cbm::algo::ca + +namespace cbm::algo::ca::qa +{ + /// \class cbm::algo::ca::qa::Builder + /// \brief Builder class for the CA tracking QA (header) + /// + class Builder { + public: + using TrackV_t = ca::Vector<ca::Track>; + using HitIndexV_t = ca::Vector<std::vector<std::pair<uint32_t, uint32_t>>>; + + /// \brief Default destructor + Builder() = delete; + + /// \brief Constructor from the configuration object + /// \param config QA configuration object + Builder(const Config& config) : fConfig(config) {} + + /// \brief Copy constructor + Builder(const Builder&) = delete; + + /// \brief Move constructor + Builder(Builder&&) = delete; + + /// \brief Destructor + ~Builder() = default; + + /// \brief Copy assignment operator + Builder& operator=(const Builder&) = delete; + + /// \brief Move assignment operator + Builder& operator=(Builder&&) = delete; + + /// \brief QA execution function + Data Build(); + + /// \brief Gets QA config + const Config& GetConfig() const { return fConfig; } + + /// \brief Registers tracking input data + /// \note Call per TS + void RegisterInputData(const InputData* pInputData) { fpInputData = pInputData; } + + /// \brief Registers track vector + /// \note Call per TS + void RegisterTracks(const Vector<Track>* pvTracks) { fpvTracks = pvTracks; } + + /// \brief Registers reco hits indices + /// \note Call per TS + void RegisterRecoHitIndices(const Vector<HitIndex_t>* pvRecoHits) { fpvRecoHits = pvRecoHits; } + + /// \brief Registers tracking parameters object + /// \note Call per run + void RegisterParameters(const Parameters* pParameters) { fpParameters = pParameters; } + + private: + Config fConfig; ///< QA configuration + const Parameters* fpParameters = nullptr; ///< Pointer to tracking parameters + const Vector<Track>* fpvTracks = nullptr; ///< Pointer to tracks vector + const InputData* fpInputData = nullptr; ///< Pointer to input data + const Vector<HitIndex_t>* fpvRecoHits = nullptr; ///< Pointer to reco hit indices + }; +} // namespace cbm::algo::ca::qa diff --git a/algo/ca/qa/CaQaConfig.cxx b/algo/ca/qa/CaQaConfig.cxx new file mode 100644 index 0000000000..bea2d565e6 --- /dev/null +++ b/algo/ca/qa/CaQaConfig.cxx @@ -0,0 +1,84 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CaQaConfig.cxx +/// \date 20.11.2023 +/// \brief A configuration class for the QA module of the CA tracking (implementation) +/// \author Sergei Zharko <s.zharko@gsi.de> + +#include "CaQaConfig.h" + +using cbm::algo::ca::qa::Config; + +// --------------------------------------------------------------------------------------------------------------------- +// +Config::Config() +{ + // Parameters initialization + // TODO: SZh 20.11.2023: Read from YAML + /* clang-format off */ + fvH1Pars[H1Key::FstTrkTheta] = { "track_first_theta", "#theta at first hit;#theta" , 62, 0., +90. }; + fvH1Pars[H1Key::FstTrkPhi] = { "track_first_phi" , "#phi at first hit;#phi" , 62, -180., +180. }; + fvH1Pars[H1Key::FstChi2Ndf] = { "track_first_chi2_ndf", "#chi^{2}/NDF at first hit;#chi^{2}/NDF", 100, 0., +20. }; + fvH1Pars[H1Key::FstHitSta] = { "first_hit_station", "Station of first hit;ID_{sta}" , 11, -0.5, 10.5 }; + fvH1Pars[H1Key::LstHitSta] = { "last_hit_station", "Station of last hit;ID_{sta}" , 11, -0.5, 10.5 }; + fvH1Pars[H1Key::TrkNofHits] = { "n_hits", "Number of hits;N_{hit}" , 11, -0.5, 10.5 }; + /* clang-format on */ + + // QA Canvas +} + +// --------------------------------------------------------------------------------------------------------------------- +// +std::vector<std::pair<std::string, std::string>> Config::GetHistogramConfigs() const +{ + std::vector<std::pair<std::string, std::string>> res; + auto nHistos = fvH1Pars.size(); + res.reserve(nHistos); + for (const auto& par : fvH1Pars) { + res.emplace_back(par.fName, fsQaName); + } + return res; +} + +// --------------------------------------------------------------------------------------------------------------------- +// +std::vector<std::pair<std::string, std::string>> Config::GetCanvasConfigs() const +{ + std::vector<std::pair<std::string, std::string>> res; + res.reserve(1); + { + std::string sConfig = "caQaSummary;CA QA Summary;3;2;"; + //sConfig += GetPadConfig({fvH1Pars[H1Key::FstTrkTx].fName}, 0, 1); + //sConfig += GetPadConfig({fvH1Pars[H1Key::FstTrkTy].fName}, 0, 1); + sConfig += GetPadConfig({fvH1Pars[H1Key::FstTrkTheta].fName}, 0, 1); + sConfig += GetPadConfig({fvH1Pars[H1Key::FstTrkPhi].fName}, 0, 1); + sConfig += GetPadConfig({fvH1Pars[H1Key::FstChi2Ndf].fName}, 0, 1); + sConfig += GetPadConfig({fvH1Pars[H1Key::FstHitSta].fName}, 0, 1); + sConfig += GetPadConfig({fvH1Pars[H1Key::LstHitSta].fName}, 0, 1); + sConfig += GetPadConfig({fvH1Pars[H1Key::TrkNofHits].fName}, 0, 1); + res.emplace_back("caQaSummary", sConfig); + } + return res; +} + +// --------------------------------------------------------------------------------------------------------------------- +// +std::string Config::GetPadConfig(const std::vector<std::string>& vHistNames, bool bLogX, bool bLogY) +{ + constexpr bool bGridX = true; + constexpr bool bGridY = true; + constexpr bool bLogZ = false; + + std::stringstream config; + config << bGridX << ',' << bGridY << ',' << bLogX << ',' << bLogY << ',' << bLogZ; + if (vHistNames.empty()) { config << ','; } + else { + for (auto& name : vHistNames) { + config << ",(" << name << ",hist)"; + } + } + config << ';'; + return config.str(); +} diff --git a/algo/ca/qa/CaQaConfig.h b/algo/ca/qa/CaQaConfig.h new file mode 100644 index 0000000000..7f59533574 --- /dev/null +++ b/algo/ca/qa/CaQaConfig.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CaQaConfig.h +/// \date 20.11.2023 +/// \brief A configuration class for the QA module of the CA tracking (header) +/// \author Sergei Zharko <s.zharko@gsi.de> + +#pragma once + +#include <string> +#include <vector> + +#include "CaQaDefinitions.h" + +namespace cbm::algo::ca::qa +{ + /// \brief Configuration structure for QA of the tracking + /// \struct cbm::algo::ca::qa::Config + class Config { + public: + /// \brief Default constructor + Config(); + + /// \brief Copy constructor + Config(const Config&) = default; + + /// \brief Move constructor + Config(Config&&) = default; + + /// \brief Destructor + ~Config() = default; + + /// \brief Access to 1D-histogram parameters + const H1KeyArray_t<H1Pars>& GetH1Pars() const { return fvH1Pars; } + + /// \brief Gets histograms configuration vector + /// \return A histogram configuration vector + /// + /// The returned configuration vector is a std::vector of std::pair of two strings. The first string is the + /// histogram name and the second string is the QA name (common for all the histograms within the QA module). + std::vector<std::pair<std::string, std::string>> GetHistogramConfigs() const; + + /// \brief Gets canvas configuration vector + /// \return A canvas configuration vector + /// + /// The returned configuration vector is a std::vector of std::pair of two strings. The first string is the + /// histogram name and the second string is the QA name (common for all the histograms within the QA module). + std::vector<std::pair<std::string, std::string>> GetCanvasConfigs() const; + + private: + /// \brief Gets pad configuration string + static std::string GetPadConfig(const std::vector<std::string>& vHistNames, bool bLogX, bool bLogY); + + std::string fsQaName = "CaQa"; ///< Name of the QA module + + H1KeyArray_t<H1Pars> fvH1Pars; ///< Parameters of 1D-histograms + std::string fsCanvasConfig = ""; ///< QA canvas configuration + }; +} // namespace cbm::algo::ca::qa diff --git a/algo/ca/qa/CaQaData.cxx b/algo/ca/qa/CaQaData.cxx new file mode 100644 index 0000000000..da495021f2 --- /dev/null +++ b/algo/ca/qa/CaQaData.cxx @@ -0,0 +1,38 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CaQaData.h +/// \date 20.11.2023 +/// \brief A data structure for the QA module of the CA tracking (header) +/// \author S.Zharko <s.zharko@gsi.de> + +#include "CaQaData.h" + +#include <sstream> + +using cbm::algo::ca::qa::Config; +using cbm::algo::ca::qa::Data; + +// --------------------------------------------------------------------------------------------------------------------- +// +Data::Data(const Config& config) +{ + // 1D-histograms initialization + fvH1.reserve(static_cast<size_t>(H1Key::kEND)); + for (auto& par : config.GetH1Pars()) { + fvH1.emplace_back(par.fNumBins, par.fMinValue, par.fMaxValue, par.fName, par.fTitle); + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// +std::string Data::ToString() const +{ + std::stringstream msg; + msg << "CA QA histogram status:"; + for (const auto& hist : fvH1) { + msg << '\n' << hist.ToString(); + } + return msg.str(); +} diff --git a/algo/ca/qa/CaQaData.h b/algo/ca/qa/CaQaData.h new file mode 100644 index 0000000000..d44a8b8a5b --- /dev/null +++ b/algo/ca/qa/CaQaData.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CaQaData.h +/// \date 20.11.2023 +/// \brief A data structure for the QA module of the CA tracking (header) +/// \author S.Zharko <s.zharko@gsi.de> + +#pragma once + +#include <string> +#include <vector> + +#include "CaQaConfig.h" +#include "CaQaDefinitions.h" +#include "Histo1D.h" + +namespace cbm::algo::ca::qa +{ + /// \class cbm::algo::ca::qa::Data + /// \brief QA data structure for CA tracking + class Data { + public: + /// \brief Default constructor + Data() = delete; + + /// \brief Constructor from parameters + /// \param config QA configuration object + Data(const Config& config); + + /// \brief Copy constructor + Data(const Data&) = default; + + /// \brief Move constructor + Data(Data&&) = default; + + /// \brief Copy assignment operator + Data& operator=(const Data&) = default; + + /// \brief Move assignment operator + Data& operator=(Data&&) = default; + + /// \brief Destructor + ~Data() = default; + + /// \brief Accesses 1D-histogram + const Histo1D& H1(H1Key key) const { return fvH1[static_cast<size_t>(key)]; } + + /// \brief Accesses 1D-histogram (mutable) + Histo1D& H1(H1Key key) { return fvH1[static_cast<size_t>(key)]; } + + /// \brief Accesses the full histogram vector + const std::vector<Histo1D>& VectorOfH1() const { return fvH1; } + + /// \brief String representation of the data status + std::string ToString() const; + + private: + std::vector<Histo1D> fvH1 = {}; ///< Vector of 1D-histograms, indexed by H1Key + }; + +} // namespace cbm::algo::ca::qa diff --git a/algo/ca/qa/CaQaDefinitions.h b/algo/ca/qa/CaQaDefinitions.h new file mode 100644 index 0000000000..d5129dd506 --- /dev/null +++ b/algo/ca/qa/CaQaDefinitions.h @@ -0,0 +1,59 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CaQaDefinitions.h +/// \date 20.11.2023 +/// \brief Definitions (enums and structures) for the cbm::algo::ca::qa namespace +/// \author S.Zharko <s.zharko@gsi.de> + +#pragma once + +#include <iomanip> +#include <sstream> + +#include "CaEnumArray.h" + +namespace cbm::algo::ca::qa +{ + /// \struct H1Pars + /// \brief Parameters of the 1D-histograms + /// + struct H1Pars { + std::string fName; ///< Histogram name + std::string fTitle; ///< Histogram title + uint32_t fNumBins; ///< Number of bins in histogram + double fMinValue; ///< Minimal value + double fMaxValue; ///< Maximal value + + /// \brief String representation of the object + std::string ToString() const + { + using std::setw; + std::stringstream msg; + msg << "nbins " << setw(8) << fNumBins << ", min " << setw(15) << fMinValue << ", max " << setw(15) << fMaxValue; + return msg.str(); + }; + }; + + /// \enum H1Key + /// \brief Keys for the 1D-histograms + /// + enum class H1Key + { + //TrackFstTx, ///< First hit: Slope of the track along x-axis + //TrackFstTy, ///< First hit: Slope of the track along y-axis + FstTrkTheta, ///< First hit: Polar angle of the track + FstTrkPhi, ///< First hit: Azimuthal angle of the track + FstChi2Ndf, ///< First hit: chi2 / NDF + FstHitSta, ///< Station index of first hit + LstHitSta, ///< Station index of last hit + TrkNofHits, ///< Number of hits in track + kEND ///< END + }; + + /// \brief Alias to array, indexed by H1Key + template<typename T> + using H1KeyArray_t = EnumArray<H1Key, T>; + +} // namespace cbm::algo::ca::qa diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx index 3e6badfdaf..56be1fbbc7 100644 --- a/algo/global/Reco.cxx +++ b/algo/global/Reco.cxx @@ -54,7 +54,6 @@ void Reco::Init(const Options& opts) fStsHitFinder.SetContext(&fContext); fTofCalibrator.SetContext(&fContext); fTofHitFinder.SetContext(&fContext); - fTracking.SetContext(&fContext); if (Opts().HistogramUri() != "") { fSender = std::make_shared<HistogramSender>(Opts().HistogramUri()); @@ -98,7 +97,9 @@ void Reco::Init(const Options& opts) fTofCalibrator.Init(); // Tracking - fTracking.Init(); + fTracking = std::make_unique<TrackingChain>(fSender); + fTracking->SetContext(&fContext); + fTracking->Init(); fInitialized = true; @@ -175,7 +176,7 @@ RecoResults Reco::Run(const fles::Timeslice& ts) .stsHits = stsHits, .tofHits = tofHits, }; - TrackingChain::Output_t trackingOutput = fTracking.Run(input); + TrackingChain::Output_t trackingOutput = fTracking->Run(input); if (Opts().HasOutput(RecoData::Track)) { results.tracks = std::move(trackingOutput.tracks); results.trackStsHitIndices = std::move(trackingOutput.stsHitIndices); @@ -200,7 +201,7 @@ RecoResults Reco::Run(const fles::Timeslice& ts) void Reco::Finalize() { fStsHitFinder.Finalize(); - fTracking.Finalize(); + fTracking->Finalize(); // Pop timer that was started in Init() xpu::timings t = xpu::pop_timer(); diff --git a/algo/global/Reco.h b/algo/global/Reco.h index f0a7c2b6d6..e34c9d8836 100644 --- a/algo/global/Reco.h +++ b/algo/global/Reco.h @@ -65,7 +65,7 @@ namespace cbm::algo std::unique_ptr<evbuild::EventbuildChain> fEventBuild; // Tracking - TrackingChain fTracking; + std::unique_ptr<TrackingChain> fTracking; void Validate(const Options& opts); -- GitLab