diff --git a/algo/qa/Histogram.h b/algo/qa/Histogram.h index 852d9cf91bc86f3aeed64edd7ed7530aae8d3743..1b70f3b0588b3eaba2b3617ecc8333957e3d8a39 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 a7dc7469d4e8955fdea7f47cd1baefcdab78914a..4d6ac5376c121a618601111ff3aa1d6d07deba09 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 ea184f35c101a0e0ca31bc2622374e3fb9d16a96..1ead168f18ca4bd8296c2a2d97db00a91725d75d 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 8cb7a9ce0bd3f399233891e3c632cec1ae423889..7c502536c435d010cddfbb74b1fd84db6b56778e 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 9b3787b6de4a7b401d24a09ccdf8909753169e90..1e70c3d02668fbcb474f03af729825c55752f925 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 2e698f8b9b8219e45298092d8362cd2611216698..5eb5362f051fc3f34fc1108e50bd17e1adf6e4f2 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 53cbdc848397df4a36582cd393e288fc07f09253..580e0dba47ca756266273a1bde3e8b39a0eda279 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