From 7a9c615cb9868ffd54375f1b8abd506e38af6e05 Mon Sep 17 00:00:00 2001 From: jokonig Date: Tue, 29 Jul 2025 13:08:32 +0200 Subject: [PATCH 1/2] [EMCAL-1039]: Add checker for number of physics triggers - Number of triggers per TF is a good indication to check if detector is (partially) busy - New checker checks if last entry in trending histogram is below a settable fraction times the maximum observed number of triggers per TF - Data quality good or bad is now indicated in the TCanvas --- Modules/EMCAL/CMakeLists.txt | 3 +- Modules/EMCAL/include/EMCAL/LinkDef.h | 1 + .../EMCAL/include/EMCAL/NumPhysTriggCheck.h | 61 ++++++++++ Modules/EMCAL/src/NumPhysTriggCheck.cxx | 115 ++++++++++++++++++ 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 Modules/EMCAL/include/EMCAL/NumPhysTriggCheck.h create mode 100644 Modules/EMCAL/src/NumPhysTriggCheck.cxx diff --git a/Modules/EMCAL/CMakeLists.txt b/Modules/EMCAL/CMakeLists.txt index fff820816b..97f7eb426c 100644 --- a/Modules/EMCAL/CMakeLists.txt +++ b/Modules/EMCAL/CMakeLists.txt @@ -2,7 +2,7 @@ add_library(O2QcEMCAL) -target_sources(O2QcEMCAL PRIVATE src/FECRateVisualization.cxx src/TriggerTask.cxx src/PedestalTask.cxx src/BCTask.cxx src/RawErrorCheck.cxx src/RawTask.cxx src/RawCheck.cxx src/CellTask.cxx src/CellCheck.cxx src/DigitsQcTask.cxx src/DigitCheck.cxx src/OccupancyReductor.cxx src/OccupancyToFECReductor.cxx src/ClusterTask.cxx src/RawErrorTask.cxx src/CalibMonitoringTask.cxx src/SupermoduleProjectorTask.cxx src/BadChannelMapReductor.cxx src/TimeCalibParamReductor.cxx src/SupermoduleProjectionReductor.cxx src/SubdetectorProjectionReductor.cxx src/BCVisualization.cxx src/CalibCheck.cxx src/NumPatchesPerFastORCheck.cxx src/PedestalChannelCheck.cxx src/PayloadPerEventDDLCheck.cxx src/RawErrorCheckAll.cxx src/CellTimeCalibCheck.cxx src/CellAmpCheck.cxx src/TrendGraphCheck.cxx) +target_sources(O2QcEMCAL PRIVATE src/FECRateVisualization.cxx src/TriggerTask.cxx src/PedestalTask.cxx src/BCTask.cxx src/RawErrorCheck.cxx src/RawTask.cxx src/RawCheck.cxx src/CellTask.cxx src/CellCheck.cxx src/DigitsQcTask.cxx src/DigitCheck.cxx src/OccupancyReductor.cxx src/OccupancyToFECReductor.cxx src/ClusterTask.cxx src/RawErrorTask.cxx src/CalibMonitoringTask.cxx src/SupermoduleProjectorTask.cxx src/BadChannelMapReductor.cxx src/TimeCalibParamReductor.cxx src/SupermoduleProjectionReductor.cxx src/SubdetectorProjectionReductor.cxx src/BCVisualization.cxx src/CalibCheck.cxx src/NumPatchesPerFastORCheck.cxx src/PedestalChannelCheck.cxx src/PayloadPerEventDDLCheck.cxx src/RawErrorCheckAll.cxx src/CellTimeCalibCheck.cxx src/CellAmpCheck.cxx src/TrendGraphCheck.cxx src/NumPhysTriggCheck.cxx) target_include_directories( O2QcEMCAL @@ -44,6 +44,7 @@ add_root_dictionary(O2QcEMCAL include/EMCAL/TrendGraphCheck.h include/EMCAL/DrawGridlines.h include/EMCAL/FECRateVisualization.h + include/EMCAL/NumPhysTriggCheck.h LINKDEF include/EMCAL/LinkDef.h) install(TARGETS O2QcEMCAL diff --git a/Modules/EMCAL/include/EMCAL/LinkDef.h b/Modules/EMCAL/include/EMCAL/LinkDef.h index 018da50d1f..aecaa3c7e5 100644 --- a/Modules/EMCAL/include/EMCAL/LinkDef.h +++ b/Modules/EMCAL/include/EMCAL/LinkDef.h @@ -29,6 +29,7 @@ #pragma link C++ class o2::quality_control_modules::emcal::TriggerTask + ; #pragma link C++ class o2::quality_control_modules::emcal::NumPatchesPerFastORCheck + ; #pragma link C++ class o2::quality_control_modules::emcal::PedestalChannelCheck + ; +#pragma link C++ class o2::quality_control_modules::emcal::NumPhysTriggCheck + ; #pragma link C++ class o2::quality_control_modules::emcal::PayloadPerEventDDLCheck + ; diff --git a/Modules/EMCAL/include/EMCAL/NumPhysTriggCheck.h b/Modules/EMCAL/include/EMCAL/NumPhysTriggCheck.h new file mode 100644 index 0000000000..bec6093ea4 --- /dev/null +++ b/Modules/EMCAL/include/EMCAL/NumPhysTriggCheck.h @@ -0,0 +1,61 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file NumPhysTriggCheck.h +/// \author Joshua Koenig +/// + +#ifndef QC_MODULE_EMCAL_EMCALNUMPHYSTRIGCHECK_HH +#define QC_MODULE_EMCAL_EMCALNUMPHYSTRIGCHECK_HH + +#include "QualityControl/CheckInterface.h" + +namespace o2::quality_control_modules::emcal +{ + +/// \brief Check whether a plot is empty or not. +/// +/// \author Barthelemy von Haller +class NumPhysTriggCheck : public o2::quality_control::checker::CheckInterface +{ + public: + /// \brief Default constructor + NumPhysTriggCheck() = default; + /// \brief Destructor + ~NumPhysTriggCheck() override = default; + + /// \brief Configure checker setting thresholds from taskParameters where specified + void configure() override; + + /// \brief Check whether the number of physics triggers for the current trigger falls below a certain threshold copared to the maximum in the time range + /// \param moMap List of histos to check + /// \return Quality of the selection + Quality check(std::map>* moMap) override; + + /// \brief Beautify the monitoring objects + /// \param mo Monitoring object to beautify + /// \param checkResult Quality status of this checker + void beautify(std::shared_ptr mo, Quality checkResult = Quality::Null) override; + + /// \brief Accept only TH1 histograms as input + /// \return Name of the accepted object: TH1 + std::string getAcceptedType() override; + + ClassDefOverride(NumPhysTriggCheck, 1); + + private: + double mFracToMaxGood = 0.5; ///< Thresholds for minimum fraction of physics triggers compared to maximum +}; + +} // namespace o2::quality_control_modules::emcal + +#endif // QC_MODULE_EMCAL_EMCALNUMPHYSTRIGCHECK_HH diff --git a/Modules/EMCAL/src/NumPhysTriggCheck.cxx b/Modules/EMCAL/src/NumPhysTriggCheck.cxx new file mode 100644 index 0000000000..db14d461c3 --- /dev/null +++ b/Modules/EMCAL/src/NumPhysTriggCheck.cxx @@ -0,0 +1,115 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +#include "EMCAL/NumPhysTriggCheck.h" +#include "QualityControl/MonitorObject.h" +#include "QualityControl/Quality.h" +#include "QualityControl/QcInfoLogger.h" +// ROOT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace o2::quality_control_modules::emcal +{ + +void NumPhysTriggCheck::configure() +{ + // configure threshold-based checkers for bad quality + auto fracToMaxGood = mCustomParameters.find("FracToMaxGood"); + if (fracToMaxGood != mCustomParameters.end()) { + try { + mFracToMaxGood = std::stof(fracToMaxGood->second); + } catch (std::exception& e) { + ILOG(Error, Support) << fmt::format("Value {} not a float", fracToMaxGood->second.data()) << ENDM; + } + } +} + +Quality NumPhysTriggCheck::check(std::map>* moMap) +{ + auto mo = moMap->begin()->second; + Quality result = Quality::Good; + + if (mo->getName().find("NPhysTriggersTFSlice") != std::string::npos) { + auto Can = dynamic_cast(mo->getObject()); + if (Can == nullptr) { + return Quality::Null; + } + TGraph* gr = nullptr; + TList* primitives = Can->GetListOfPrimitives(); + for (TObject* obj : *primitives) { + if (obj->InheritsFrom("TGraph")) { + gr = (TGraph*)obj; + break; + } + } + if (gr == nullptr) { + return Quality::Null; + } + if (gr->GetN() == 0) { + return Quality::Bad; + } + double maxVal = 0.; + for (int i = 0; i < gr->GetN(); ++i) { + if (gr->GetPointY(i) > maxVal) { + maxVal = gr->GetPointY(i); + } + } + double currentVal = gr->GetPointY(gr->GetN() - 1); + if (currentVal < mFracToMaxGood * maxVal) { + result = Quality::Bad; + } + } + + return result; +} + +std::string NumPhysTriggCheck::getAcceptedType() { return "TCanvas"; } + +void NumPhysTriggCheck::beautify(std::shared_ptr mo, Quality checkResult) +{ + if (mo->getName().find("NPhysTriggersTFSlice") != std::string::npos) { + auto Can = dynamic_cast(mo->getObject()); + if (Can == nullptr) { + return; + } + + Can->cd(); + TPaveText* msg = new TPaveText(0.17, 0.2, 0.5, 0.3, "NDC"); + msg->SetName(Form("%s_msg", mo->GetName())); + + if (checkResult == Quality::Good) { + // + msg->Clear(); + msg->AddText("Data quality: GOOD"); + msg->SetFillColor(kGreen); + msg->Draw("same"); + Can->Update(); + } else if (checkResult == Quality::Bad) { + ILOG(Debug, Devel) << "Quality::Bad"; + msg->Clear(); + msg->AddText("Data quality: BAD"); + msg->SetFillColor(kRed); + msg->Draw("same"); + Can->Update(); + } + } +} +} // namespace o2::quality_control_modules::emcal From d9666f29d3fc415465d79201ff90fc150311b219 Mon Sep 17 00:00:00 2001 From: Joshua Koenig Date: Tue, 29 Jul 2025 17:45:35 +0200 Subject: [PATCH 2/2] Update Modules/EMCAL/src/NumPhysTriggCheck.cxx Co-authored-by: Piotr Konopka --- Modules/EMCAL/src/NumPhysTriggCheck.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/EMCAL/src/NumPhysTriggCheck.cxx b/Modules/EMCAL/src/NumPhysTriggCheck.cxx index db14d461c3..84022e088b 100644 --- a/Modules/EMCAL/src/NumPhysTriggCheck.cxx +++ b/Modules/EMCAL/src/NumPhysTriggCheck.cxx @@ -103,7 +103,7 @@ void NumPhysTriggCheck::beautify(std::shared_ptr mo, Quality chec msg->Draw("same"); Can->Update(); } else if (checkResult == Quality::Bad) { - ILOG(Debug, Devel) << "Quality::Bad"; + ILOG(Debug, Devel) << "Quality::Bad << ENDM"; msg->Clear(); msg->AddText("Data quality: BAD"); msg->SetFillColor(kRed);