From f9497aed6d70be98d2257f5ffcc66ebcf09dd65a Mon Sep 17 00:00:00 2001 From: jokonig Date: Fri, 6 Feb 2026 15:46:47 +0100 Subject: [PATCH] [EMCAL-519] Optimize QC Messages for oncall related histograms - Add online supermodule indices to multiple histograms - Add grid lines with SM borders to mw histograms --- Modules/EMCAL/CMakeLists.txt | 2 + Modules/EMCAL/include/EMCAL/DrawGridlines.h | 76 +++++++++++++++++++ .../include/EMCAL/FECRateVisualization.h | 2 + .../EMCAL/include/EMCAL/IndicesConverter.h | 65 ++++++++++++++++ Modules/EMCAL/include/EMCAL/LinkDef.h | 6 +- Modules/EMCAL/include/EMCAL/RawCheck.h | 6 ++ .../include/EMCAL/SupermoduleProjectorTask.h | 2 + Modules/EMCAL/src/CellTask.cxx | 17 ++++- Modules/EMCAL/src/FECRateVisualization.cxx | 8 ++ Modules/EMCAL/src/RawCheck.cxx | 8 +- .../EMCAL/src/SupermoduleProjectorTask.cxx | 5 +- 11 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 Modules/EMCAL/include/EMCAL/IndicesConverter.h diff --git a/Modules/EMCAL/CMakeLists.txt b/Modules/EMCAL/CMakeLists.txt index 97f7eb426c..08f45142b3 100644 --- a/Modules/EMCAL/CMakeLists.txt +++ b/Modules/EMCAL/CMakeLists.txt @@ -45,6 +45,8 @@ add_root_dictionary(O2QcEMCAL include/EMCAL/DrawGridlines.h include/EMCAL/FECRateVisualization.h include/EMCAL/NumPhysTriggCheck.h + include/EMCAL/NumPhysTriggCheck.h + include/EMCAL/IndicesConverter.h LINKDEF include/EMCAL/LinkDef.h) install(TARGETS O2QcEMCAL diff --git a/Modules/EMCAL/include/EMCAL/DrawGridlines.h b/Modules/EMCAL/include/EMCAL/DrawGridlines.h index c22d68d10e..723955432d 100644 --- a/Modules/EMCAL/include/EMCAL/DrawGridlines.h +++ b/Modules/EMCAL/include/EMCAL/DrawGridlines.h @@ -14,6 +14,7 @@ #include "TLine.h" #include "TH2D.h" +#include "QualityControl/QcInfoLogger.h" namespace o2::quality_control_modules::emcal { @@ -36,6 +37,24 @@ class DrawGridlines : public quality_control::postprocessing::PostProcessingInte if (histo == nullptr) { return; } + + // check if the gridlines are already drawn by looking for a line at the first SM boundary + auto* funcs = histo->GetListOfFunctions(); + if (!funcs) { + return; + } + + // Remove previously added grid lines + TIter it(funcs); + TObject* obj = nullptr; + while ((obj = it())) { + if (obj->InheritsFrom(TLine::Class())) { + ILOG(Debug, Support) << "Removing existing grid line from histogram " << histo->GetName() << ENDM; + funcs->Remove(obj); + delete obj; + } + } + // EMCAL for (int iside = 0; iside <= 48; iside += 24) { auto smline = new TLine(static_cast(iside) - 0.5, -0.5, static_cast(iside) - 0.5, 63.5); @@ -115,6 +134,63 @@ class DrawGridlines : public quality_control::postprocessing::PostProcessingInte } }; + /// \brief Draw the gridlines in the standard cell geometry + static void DrawSMGridInStdGeo(TH2* histo = nullptr) + { + if (histo == nullptr) { + return; + } + // EMCAL + for (int iside = 0; iside <= 96; iside += 48) { + auto smline = new TLine(static_cast(iside) - 0.5, -0.5, static_cast(iside) - 0.5, 127.5); + smline->SetLineWidth(6); + + histo->GetListOfFunctions()->Add(smline); + } + for (int iphi = 0; iphi < 120; iphi += 24) { + auto smline = new TLine(-0.5, static_cast(iphi) - 0.5, 95.5, static_cast(iphi) - 0.5); + smline->SetLineWidth(6); + + histo->GetListOfFunctions()->Add(smline); + } + for (auto iphi = 120; iphi <= 128; iphi += 8) { + auto smline = new TLine(-0.5, static_cast(iphi) - 0.5, 95.5, static_cast(iphi) - 0.5); + smline->SetLineWidth(6); + + histo->GetListOfFunctions()->Add(smline); + } + + // DCAL + for (int side = 0; side < 2; side++) { + int sideoffset = (side == 0) ? 0 : 64; + for (int isepeta = 0; isepeta < 2; isepeta++) { + int etaoffset = sideoffset + isepeta * 32; + auto smline = new TLine(static_cast(etaoffset) - 0.5, 127.5, static_cast(etaoffset) - 0.5, 199.5); + smline->SetLineWidth(6); + + histo->GetListOfFunctions()->Add(smline); + } + for (auto iphi = 152; iphi <= 176; iphi += 24) { + auto smline = new TLine(static_cast(sideoffset) - 0.5, static_cast(iphi) - 0.5, static_cast(sideoffset + 32) - 0.5, static_cast(iphi) - 0.5); + smline->SetLineWidth(6); + + histo->GetListOfFunctions()->Add(smline); + } + } + for (auto iphi = 200; iphi <= 208; iphi += 8) { + auto smline = new TLine(-0.5, static_cast(iphi) - 0.5, 95.5, static_cast(iphi) - 0.5); + smline->SetLineWidth(6); + + histo->GetListOfFunctions()->Add(smline); + } + for (auto ieta = 0; ieta <= 96; ieta += 48) { + auto smline = new TLine(static_cast(ieta) - 0.5, 199.5, static_cast(ieta) - 0.5, 207.5); + smline->SetLineWidth(6); + + histo->GetListOfFunctions()->Add(smline); + } + }; + /// \brief Draw the gridlines for the FastOR limits static void DrawFastORGrid(TH2* histo = nullptr) { diff --git a/Modules/EMCAL/include/EMCAL/FECRateVisualization.h b/Modules/EMCAL/include/EMCAL/FECRateVisualization.h index d5160bbf11..30c0d8eec0 100644 --- a/Modules/EMCAL/include/EMCAL/FECRateVisualization.h +++ b/Modules/EMCAL/include/EMCAL/FECRateVisualization.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace o2::quality_control_modules::emcal { @@ -60,6 +61,7 @@ class FECRateVisualization final : public quality_control::postprocessing::PostP private: std::array, 20> mSupermoduleCanvas; /// Canvas with FEC Rates per supermodule + o2::emcal::IndicesConverter mIndicesConverter; ///< Converter for online-offline supermodule indices double mMaxRate = 2000.; }; diff --git a/Modules/EMCAL/include/EMCAL/IndicesConverter.h b/Modules/EMCAL/include/EMCAL/IndicesConverter.h new file mode 100644 index 0000000000..d208dcf19d --- /dev/null +++ b/Modules/EMCAL/include/EMCAL/IndicesConverter.h @@ -0,0 +1,65 @@ +// 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. + +#ifndef QUALITYCONTROL_INDICESCONVERTER_H +#define QUALITYCONTROL_INDICESCONVERTER_H +#include +#include + +namespace o2::emcal +{ +class IndicesConverter +{ + public: + IndicesConverter() + { + Initialize(); + } + ~IndicesConverter() = default; + + void Initialize() + { + // Initialize the map with online and offline supermodule indices + for (int i = 0; i < 20; i++) { + std::string SMSide = "A"; + if (i % 2 != 0) { + SMSide = "C"; + } + int SMRowIndex = (i / 2) + (i >= 12 ? 3 : 0); // Adjust row index for DCAL + mOnlineToOfflineSMMap[i] = "SM" + SMSide + std::to_string(SMRowIndex); + } + } + + int GetOfflineSMIndex(const std::string& onlineSMIndex) const + { + for (const auto& pair : mOnlineToOfflineSMMap) { + if (pair.second == onlineSMIndex) { + return pair.first; + } + } + return -1; // Return -1 if no matching index is found + } + std::string GetOnlineSMIndex(const int offlineSMIndex) const + { + if (mOnlineToOfflineSMMap.find(offlineSMIndex) != mOnlineToOfflineSMMap.end()) { + return mOnlineToOfflineSMMap.at(offlineSMIndex); + } else { + return "Invalid SM Index"; + } + } + + private: + std::map mOnlineToOfflineSMMap; ///< Map for conversion between online and offline supermodule indices +}; + +} // namespace o2::emcal + +#endif // QUALITYCONTROL_INDICESCONVERTER_H \ No newline at end of file diff --git a/Modules/EMCAL/include/EMCAL/LinkDef.h b/Modules/EMCAL/include/EMCAL/LinkDef.h index aecaa3c7e5..30cad874b9 100644 --- a/Modules/EMCAL/include/EMCAL/LinkDef.h +++ b/Modules/EMCAL/include/EMCAL/LinkDef.h @@ -40,6 +40,6 @@ #pragma link C++ class o2::quality_control_modules::emcal::RawErrorCheckAll + ; #pragma link C++ class o2::quality_control_modules::emcal::DrawGridlines + ; - #pragma link C++ class o2::quality_control_modules::emcal::FECRateVisualization+; - - #endif +#pragma link C++ class o2::quality_control_modules::emcal::FECRateVisualization+; + +#endif diff --git a/Modules/EMCAL/include/EMCAL/RawCheck.h b/Modules/EMCAL/include/EMCAL/RawCheck.h index 1d24d5ca29..65c98a7808 100644 --- a/Modules/EMCAL/include/EMCAL/RawCheck.h +++ b/Modules/EMCAL/include/EMCAL/RawCheck.h @@ -13,6 +13,7 @@ #define QC_MODULE_EMCAL_EMCALRAWCHECK_H #include "QualityControl/CheckInterface.h" +#include "EMCAL/IndicesConverter.h" #include #include #include @@ -64,6 +65,11 @@ class RawCheck final : public o2::quality_control::checker::CheckInterface bool mILMessageNoisyFECCheck = false; ///< Switch for IL message for noisy FEC bool mILMessagePayloadSizeCheck = false; ///< Switch for IL message for large payload size + /************************************************ + * Conversion between online and offline indices * + ************************************************/ + o2::emcal::IndicesConverter mIndicesConverter; ///< Converter for online and offline supermodule indices + /************************************************ * sigma cuts * ************************************************/ diff --git a/Modules/EMCAL/include/EMCAL/SupermoduleProjectorTask.h b/Modules/EMCAL/include/EMCAL/SupermoduleProjectorTask.h index 3ebc2048bd..51300613cd 100644 --- a/Modules/EMCAL/include/EMCAL/SupermoduleProjectorTask.h +++ b/Modules/EMCAL/include/EMCAL/SupermoduleProjectorTask.h @@ -20,6 +20,7 @@ // QC includes #include "QualityControl/QualityObject.h" #include "QualityControl/PostProcessingInterface.h" +#include "EMCAL/IndicesConverter.h" #include #include #include @@ -98,6 +99,7 @@ class SupermoduleProjectorTask final : public quality_control::postprocessing::P std::vector mDataSources; ///< Data sources to be projected std::map mCanvasHandler; ///< Mapping between data source and output canvas std::map mAttributeHandler; ///< Customizations for canvases (i.e. axis titles) + o2::emcal::IndicesConverter mIndicesConverter; ///< Converter for online-offline supermodule indices }; } // namespace o2::quality_control_modules::emcal diff --git a/Modules/EMCAL/src/CellTask.cxx b/Modules/EMCAL/src/CellTask.cxx index 1f9ad974c6..909c1ffb33 100644 --- a/Modules/EMCAL/src/CellTask.cxx +++ b/Modules/EMCAL/src/CellTask.cxx @@ -1067,6 +1067,13 @@ void CellTask::CellHistograms::startPublishing(o2::quality_control::core::Object } }; + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancy); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyThr); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyThrBelow); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyGood); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyBad); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mIntegratedOccupancy); + publishOptional(mCellTime); publishOptional(mCellTimeCalib); publishOptional(mCellAmplitude); @@ -1091,8 +1098,6 @@ void CellTask::CellHistograms::startPublishing(o2::quality_control::core::Object publishOptional(mCellAmplitudeCalib_EMCAL); publishOptional(mCellAmplitudeCalib_DCAL); publishOptional(mCellOccupancy); - o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyThr); - o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyThrBelow); publishOptional(mCellOccupancyThr); publishOptional(mCellOccupancyThrBelow); publishOptional(mCellOccupancyGood); @@ -1169,6 +1174,14 @@ void CellTask::CellHistograms::reset() for (auto histos : mCellTimeBC) { resetOptional(histos); } + + // Draw Grid Lines + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancy); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyThr); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyThrBelow); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyGood); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mCellOccupancyBad); + o2::quality_control_modules::emcal::DrawGridlines::DrawSMGridInTriggerGeo(mIntegratedOccupancy); } void CellTask::CellHistograms::clean() diff --git a/Modules/EMCAL/src/FECRateVisualization.cxx b/Modules/EMCAL/src/FECRateVisualization.cxx index 667668b441..b7136a051e 100644 --- a/Modules/EMCAL/src/FECRateVisualization.cxx +++ b/Modules/EMCAL/src/FECRateVisualization.cxx @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -44,6 +45,7 @@ void FECRateVisualization::configure(const boost::property_tree::ptree& config) void FECRateVisualization::initialize(Trigger, framework::ServiceRegistryRef) { + mIndicesConverter.Initialize(); for (int ism = 0; ism < 20; ism++) { mSupermoduleCanvas[ism] = std::make_unique(Form("FECRatesSM%d", ism), Form("FEC rates for supermodule %d", ism), 800, 600); getObjectsManager()->startPublishing(mSupermoduleCanvas[ism].get(), PublicationPolicy::Forever); @@ -79,6 +81,7 @@ void FECRateVisualization::update(Trigger t, framework::ServiceRegistryRef servi int minfec = smID * 40; mSupermoduleCanvas[smID]->Clear(); mSupermoduleCanvas[smID]->Divide(2, 2); + mSupermoduleCanvas[smID]->SetTopMargin(0.1); int currentpad = 0; TLegend* leg = nullptr; bool isFirst = true; @@ -144,6 +147,11 @@ void FECRateVisualization::update(Trigger t, framework::ServiceRegistryRef servi } mSupermoduleCanvas[smID]->cd(); + TLatex* msg = new TLatex(0.35, 0.96, Form("Supermodule %d (%s)", smID, mIndicesConverter.GetOnlineSMIndex(smID).data())); + msg->SetNDC(); + msg->SetTextSize(0.05); + msg->SetTextFont(62); + msg->Draw(); mSupermoduleCanvas[smID]->Update(); } } diff --git a/Modules/EMCAL/src/RawCheck.cxx b/Modules/EMCAL/src/RawCheck.cxx index 809762685a..970307d553 100644 --- a/Modules/EMCAL/src/RawCheck.cxx +++ b/Modules/EMCAL/src/RawCheck.cxx @@ -57,6 +57,8 @@ void RawCheck::configure() loadConfigValueDouble("BunchMinAmpFractionSignalSM", mBunchMinCheckFractionSignalSM); loadConfigValueInt("BunchMinAmpMinEntriesFEC", mBunchMinCheckMinEntriesFEC); loadConfigValueDouble("BunchMinAmpFractionSignalFEC", mBunchMinCheckFractionSignalFEC); + + mIndicesConverter.Initialize(); } Quality RawCheck::check(std::map>* moMap) @@ -90,7 +92,7 @@ Quality RawCheck::check(std::map>* m result = Quality::Bad; std::stringstream messagebuilder; for (auto imod : badModules) { - messagebuilder << "Pedestals peak detected in SM " << imod << std::endl; + messagebuilder << "Pedestals peak detected in SM " << imod << " " << mIndicesConverter.GetOnlineSMIndex(imod) << std::endl; } message = messagebuilder.str(); } else { @@ -110,10 +112,10 @@ Quality RawCheck::check(std::map>* m std::stringstream messagebuilder; for (int ism = 0; ism < fecsPerSM.size(); ism++) { if (badsms.test(ism)) { - messagebuilder << "Pedestals not set full SM " << ism << std::endl; + messagebuilder << "Pedestals not set full SM " << ism << " " << mIndicesConverter.GetOnlineSMIndex(ism) << std::endl; } else { for (auto& fec : fecsPerSM[ism]) { - messagebuilder << "Pedestals not set SM " << ism << " FEC " << fec << std::endl; + messagebuilder << "Pedestals not set SM " << ism << " " << mIndicesConverter.GetOnlineSMIndex(ism) << " FEC " << fec << std::endl; } } } diff --git a/Modules/EMCAL/src/SupermoduleProjectorTask.cxx b/Modules/EMCAL/src/SupermoduleProjectorTask.cxx index cfa786581a..65c2bbf708 100644 --- a/Modules/EMCAL/src/SupermoduleProjectorTask.cxx +++ b/Modules/EMCAL/src/SupermoduleProjectorTask.cxx @@ -49,6 +49,7 @@ void SupermoduleProjectorTask::initialize(Trigger, framework::ServiceRegistryRef getObjectsManager()->startPublishing(plot); mCanvasHandler[datasource.name] = plot; } + mIndicesConverter.Initialize(); } void SupermoduleProjectorTask::update(Trigger t, framework::ServiceRegistryRef services) @@ -201,7 +202,7 @@ void SupermoduleProjectorTask::makeProjections(quality_control::core::MonitorObj plot.Divide(4, 5); for (int supermoduleID = 0; supermoduleID < 20; supermoduleID++) { std::string histname = std::string(inputhist->GetName()) + "_SM" + std::to_string(supermoduleID), - histtitle = "Supermodule " + std::to_string(supermoduleID); + histtitle = "Supermodule " + std::to_string(supermoduleID) + " (" + mIndicesConverter.GetOnlineSMIndex(supermoduleID) + ")"; TH1* projection = nullptr; if (xAxisSM) { projection = inputhist->ProjectionY(histname.data(), supermoduleID + 1, supermoduleID + 1); @@ -210,6 +211,8 @@ void SupermoduleProjectorTask::makeProjections(quality_control::core::MonitorObj } projection->SetStats(false); projection->SetTitle(histtitle.data()); + projection->SetTitleSize(12); + projection->SetTitleFont(43); bool logx = false; bool logy = false; if (customizations) {