From ed707b7a261b49be6985bf03404ed9d071475acc Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 5 Aug 2025 17:35:44 +0200 Subject: [PATCH 1/8] [MCH] added averaging over SOLAR links Added computation of average quantities over SOLAR links, similar to what is already implemented for the averaging over Detection Elements --- .../MUON/MCH/include/MCH/TH2ElecMapReductor.h | 19 +++++ Modules/MUON/MCH/src/TH2ElecMapReductor.cxx | 70 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/Modules/MUON/MCH/include/MCH/TH2ElecMapReductor.h b/Modules/MUON/MCH/include/MCH/TH2ElecMapReductor.h index e8b9cccf51..4b9fd37edf 100644 --- a/Modules/MUON/MCH/include/MCH/TH2ElecMapReductor.h +++ b/Modules/MUON/MCH/include/MCH/TH2ElecMapReductor.h @@ -41,6 +41,14 @@ class TH2ElecMapReductor : public quality_control::postprocessing::ReductorTObje float getChamberValue(int chid); float getDeValue(int deid, int cathode = 2); float getOrbits() { return meanOrbits; } + + // SOLAR related accessors + float getSolarValue(int solarId); + int getSolarNumPads(int solarId); + int getSolarNumPadsBad(int solarId); + int getSolarNumPadsNoStat(int solarId); + + // DE related accessors int getNumPads(int deid, int cathode); int getNumPads(int deid) { @@ -57,8 +65,10 @@ class TH2ElecMapReductor : public quality_control::postprocessing::ReductorTObje return getNumPadsNoStat(deid, 0) + getNumPadsNoStat(deid, 1); } + private: static constexpr int sDeNum{ 156 }; + static constexpr uint32_t sSolarIndexMax{ 32 * 24 }; int checkPadMapping(uint16_t feeId, uint8_t linkId, uint8_t eLinkId, o2::mch::raw::DualSampaChannelId channel, int& cid); @@ -70,10 +80,19 @@ class TH2ElecMapReductor : public quality_control::postprocessing::ReductorTObje float mMin; float mMax; + // SOLAR related values + int solarNumPads[sSolarIndexMax]; + int solarNumPadsBad[sSolarIndexMax]; + int solarNumPadsNoStat[sSolarIndexMax]; + float solarValues[sSolarIndexMax]; + + // DE related values int deNumPads[2][sDeNum]; int deNumPadsBad[2][sDeNum]; int deNumPadsNoStat[2][sDeNum]; float deValues[3][sDeNum]; + + // chamber related values float chValues[10]; float meanOrbits; float entries; diff --git a/Modules/MUON/MCH/src/TH2ElecMapReductor.cxx b/Modules/MUON/MCH/src/TH2ElecMapReductor.cxx index 2d77c7da60..1ea30a33fb 100644 --- a/Modules/MUON/MCH/src/TH2ElecMapReductor.cxx +++ b/Modules/MUON/MCH/src/TH2ElecMapReductor.cxx @@ -107,6 +107,38 @@ int TH2ElecMapReductor::getNumPadsNoStat(int deid, int cathode) return deNumPadsNoStat[cathode][deid]; } +float TH2ElecMapReductor::getSolarValue(int solarId) +{ + if (solarId < 0 || solarId >= getNumSolar()) { + return 0; + } + return solarValues[solarId]; +} + +int TH2ElecMapReductor::getSolarNumPads(int solarId) +{ + if (solarId < 0 || solarId >= getNumSolar()) { + return 0; + } + return solarNumPads[solarId]; +} + +int TH2ElecMapReductor::getSolarNumPadsBad(int solarId) +{ + if (solarId < 0 || solarId >= getNumSolar()) { + return 0; + } + return solarNumPadsBad[solarId]; +} + +int TH2ElecMapReductor::getSolarNumPadsNoStat(int solarId) +{ + if (solarId < 0 || solarId >= getNumSolar()) { + return 0; + } + return solarNumPadsNoStat[solarId]; +} + void TH2ElecMapReductor::update(TObject* obj) { if (sDeNum != getNumDE()) { @@ -126,6 +158,19 @@ void TH2ElecMapReductor::update(TObject* obj) return; } + // cumulative numerators and denominators for the computation of + // the average value over SOLAR boards + std::vector solarValueNum(getNumSolar()); + std::vector solarValueDen(getNumSolar()); + std::fill(solarValueNum.begin(), solarValueNum.end(), 0); + std::fill(solarValueDen.begin(), solarValueDen.end(), 0); + + for (int solar = 0; solar < sSolarIndexMax; solar++) { + solarNumPads[solar] = 0; + solarNumPadsBad[solar] = 0; + solarNumPadsNoStat[solar] = 0; + } + // cumulative numerators and denominators for the computation of // the average value over detection elements and chambers std::vector deValueNum(getNumDE()); @@ -174,6 +219,17 @@ void TH2ElecMapReductor::update(TObject* obj) continue; } + auto dsElecId = mDet2ElecMapper(dsDetId); + if (!dsElecId) { + continue; + } + auto solarId = dsElecId->solarId(); + + int solarIndex = getSolarIndex(solarId); + if (solarIndex < 0) { + continue; + } + for (int j = 1; j <= nbinsy; j++) { int channel = j - 1; @@ -185,24 +241,30 @@ void TH2ElecMapReductor::update(TObject* obj) } int cathode = segment.isBendingPad(padId) ? 0 : 1; + solarNumPads[solarIndex] += 1; deNumPads[cathode][deIndex] += 1; // here we assume that if the number of bins differs between numerator and denominator, // the denominator contains a single common scaling factor in the first bin (uniform scaling) Float_t stat = (hr->getNum()->GetNcells() == hr->getDen()->GetNcells()) ? hr->getDen()->GetBinContent(i, j) : hr->getDen()->GetBinContent(1, 1); if (stat == 0) { + solarNumPadsNoStat[solarIndex] += 1; deNumPadsNoStat[cathode][deIndex] += 1; continue; } Float_t value = h->GetBinContent(i, j); if (value <= mMin || value >= mMax) { + solarNumPadsBad[solarIndex] += 1; deNumPadsBad[cathode][deIndex] += 1; } nOrbits += stat; nPads += 1; + solarValueNum[solarIndex] += value; + solarValueDen[solarIndex] += 1; + deValueNum[deIndex] += value; deValueDen[deIndex] += 1; if (cathode == 0) { @@ -222,6 +284,14 @@ void TH2ElecMapReductor::update(TObject* obj) } // update the average values + for (size_t solar = 0; solar < solarValueDen.size(); solar++) { + // integrated values + if (solarValueDen[solar] > 0) { + solarValues[solar] = solarValueNum[solar] / solarValueDen[solar]; + } else { + solarValues[solar] = 0; + } + } for (size_t de = 0; de < deValueDenB.size(); de++) { // integrated values if (deValueDenB[de] > 0) { From 098c544afcf7aa836124a026d2e3741e3e9214c4 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 5 Aug 2025 17:40:19 +0200 Subject: [PATCH 2/8] [MCH] added helper functions for handling SOLAR indexes and histogram decorations --- Modules/MUON/MCH/include/MCH/Helpers.h | 16 +- Modules/MUON/MCH/src/Helpers.cxx | 321 ++++++++++++++++++++++++- 2 files changed, 326 insertions(+), 11 deletions(-) diff --git a/Modules/MUON/MCH/include/MCH/Helpers.h b/Modules/MUON/MCH/include/MCH/Helpers.h index e44d340c4d..95cfb26802 100644 --- a/Modules/MUON/MCH/include/MCH/Helpers.h +++ b/Modules/MUON/MCH/include/MCH/Helpers.h @@ -53,6 +53,12 @@ int getDEindex(int de); constexpr int getNumDE() { return (4 * 4 + 18 * 2 + 26 * 4); } int getNumDEinChamber(int chIndex); std::pair getDEindexInChamber(int deId); +int getDEFromIndex(int index); + +int getSolarIndex(int solarId); +int getSolarIdFromIndex(int index); +constexpr int getNumSolar() { return 624; } +int getNumSolarPerChamber(int chamberId); void getThresholdsPerStation(o2::quality_control::core::CustomParameters customParameters, const o2::quality_control::core::Activity& activity, @@ -62,10 +68,16 @@ void getThresholdsPerStation(o2::quality_control::core::CustomParameters customP o2::quality_control::core::Quality checkDetectorQuality(gsl::span& deQuality); -void addChamberDelimiters(TH1F* h, float xmin = 0, float xmax = 0); -void addChamberDelimiters(TH2F* h); +void addChamberLabelsForDE(TH1* h); +void addChamberDelimiters(TH1* h, float xmin = 0, float xmax = 0); +void addChamberDelimiters(TH2* h); +void addChamberLabelsForSolar(TH1* h); +void addChamberDelimitersToSolarHistogram(TH1* h, float xmin = 0, float xmax = 0); +void addChamberDelimitersToSolarHistogram(TH2* h); +void drawThreshold(TH1* histogram, double threshold); void drawThresholdsPerStation(TH1* histogram, const std::array, 5>& thresholdsPerStation, double defaultThreshold); void addDEBinLabels(TH1* histogram); +void addSolarBinLabels(TH1* histogram); std::string getHistoPath(int deId); bool matchHistName(std::string hist, std::string name); diff --git a/Modules/MUON/MCH/src/Helpers.cxx b/Modules/MUON/MCH/src/Helpers.cxx index 9334a6d1a3..3c224b924d 100644 --- a/Modules/MUON/MCH/src/Helpers.cxx +++ b/Modules/MUON/MCH/src/Helpers.cxx @@ -21,6 +21,7 @@ #include "QualityControl/QcInfoLogger.h" #include "Common/Utils.h" #include "MCHRawElecMap/Mapper.h" +#include "MCHMappingInterface/CathodeSegmentation.h" #include #include #include @@ -149,6 +150,145 @@ int getDEindex(int deId) return idx.first + offset; } +int getDEFromIndex(int index) +{ + int deId = 0; + for (int chamber = 9; chamber >= 0; chamber--) { + int offset = getChamberOffset(chamber); + if (offset > index) { + continue; + } + + int indexInChamber = index - offset; + + int nDE = getNumDEinChamber(chamber); + if (nDE == 0) { + return 0; + } + // number of detectors in one half chamber + int nDEhc = nDE / 2; + + // minimum and maximum detector indexes for the L side + int lMin = (nDEhc + 1) / 2; + int lMax = lMin + nDEhc - 1; + if (indexInChamber < nDEhc) { + // detector on the L side, simply add lMin + // std::cout << "DE on L side, indexInChamber=" << indexInChamber << " nDEhc=" << nDEhc << std::endl; + deId = lMin + indexInChamber; + } else { + // number of detectors in one quarter of chamber + // std::cout << "DE on R side, indexInChamber=" << indexInChamber << " nDEhc=" << nDEhc << std::endl; + // detector on the R side, compute deId separately above and below middle horizontal axis + int indexInHalfChamber = indexInChamber - nDEhc; + deId = lMin - indexInHalfChamber - 1; + if (deId < 0) { + deId = lMax + (nDEhc - indexInHalfChamber); + } + /*if (indexInHalfChamber > nDEqc) { + // the DE is in the lower half of the chamber + std::cout << "DE on lower R side, indexInHalfChamber=" << indexInHalfChamber << " nDEqc=" << nDEqc << std::endl; + deId = lMax + (nDEhc - indexInHalfChamber); + } else { + // the DE is in the upper half of the chamber + std::cout << "DE on upper R side, indexInHalfChamber=" << indexInHalfChamber << " nDEqc=" << nDEqc << std::endl; + deId = lMin - indexInHalfChamber - 1; + }*/ + } + + deId += (chamber + 1) * 100; + break; + } + + return deId; +} + + +//_________________________________________________________________________________________ + +std::map buildSolarIdToSolarIndexMap() +{ + static std::map m; + if (m.empty()) { + uint32_t solarIndex{ 0 }; + // fill a sorted list of DetectionElement IDs + std::set deIds; + o2::mch::mapping::forEachDetectionElement([&](int deId) { + deIds.insert(deId); + }); + // loop over DE IDs, and add all the corresponding SOLAR IDs to the output vector + for (auto deId : deIds) { + auto solarIds = o2::mch::raw::getSolarUIDs(deId); + for (uint32_t solarId : solarIds) { + m.emplace(std::make_pair(solarId, solarIndex)); + solarIndex++; + } + } + } + return m; + +} + +std::vector buildSolarIndexToSolarIdMap() +{ + static std::vector v; + if (v.empty()) { + auto m = buildSolarIdToSolarIndexMap(); + v.resize(m.size()); + for (auto [solarId, solarIndex] : m) { + v[solarIndex] = solarId; + } + } + return v; +} + +int getSolarIndex(int solarId) +{ + static std::map m = buildSolarIdToSolarIndexMap(); + try { + return m.at(solarId); + } catch (const std::exception&) { + ILOG(Error, Support) << "Invalid Solar Id: " << solarId; + } + return -1; +} + +int getSolarIdFromIndex(int index) +{ + static std::vector v = buildSolarIndexToSolarIdMap(); + try { + return v.at(index); + } catch (const std::exception&) { + ILOG(Error, Support) << "Invalid Solar Index: " << index; + } + return -1; +} +/* +constexpr int getNumSolar() +{ + //static std::vector v = buildSolarIndexToSolarIdMap(); + //return v.size(); + return 624; +} +*/ +int getNumSolarPerChamber(int chamberId) +{ + static std::array v{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + if (v[0] == 0) { + o2::mch::mapping::forEachDetectionElement([&](int deId) { + int chId = deId / 100; + if (chId > 0 && chId <= 10) { + auto solarIds = o2::mch::raw::getSolarUIDs(deId); + v[chId - 1] += solarIds.size(); + } + }); + } + if (chamberId > 0 && chamberId <= 10) { + return v[chamberId - 1]; + } + return -1; +} + + //_________________________________________________________________________________________ void getThresholdsPerStation(o2::quality_control::core::CustomParameters customParameters, @@ -310,7 +450,7 @@ Quality QualityChecker::getQuality() //_________________________________________________________________________________________ -void addChamberDelimiters(TH1F* h, float xmin, float xmax) +void addChamberLabelsForDE(TH1* h) { if (!h) { return; @@ -327,11 +467,35 @@ void addChamberDelimiters(TH1F* h, float xmin, float xmax) xtitle->SetTextFont(42); h->GetListOfFunctions()->Add(xtitle); + // draw x-axis labels + for (int ch = 0; ch <= 9; ch += 1) { + float x1 = static_cast(getChamberOffset(ch)); + float x2 = (ch < 9) ? static_cast(getChamberOffset(ch + 1)) : h->GetXaxis()->GetXmax(); + float x0 = 0.8 * (x1 + x2) / (2 * h->GetXaxis()->GetXmax()) + 0.1; + float y0 = 0.05; + TText* label = new TText(); + label->SetNDC(); + label->SetText(x0, y0, TString::Format("%d", ch + 1)); + label->SetTextSize(10); + label->SetTextFont(42); + label->SetTextAlign(22); + h->GetListOfFunctions()->Add(label); + } +} + +//_________________________________________________________________________________________ + +void addChamberDelimiters(TH1* h, float xmin, float xmax) +{ + if (!h) { + return; + } + float scaleMin = xmin; float scaleMax = xmax; if (xmin == xmax) { - scaleMin = h->GetMinimum() * 0.95; - scaleMax = h->GetMaximum() * 1.05; + scaleMin = h->GetMinimum(); + scaleMax = h->GetMaximum(); } // draw chamber delimiters @@ -342,16 +506,38 @@ void addChamberDelimiters(TH1F* h, float xmin, float xmax) delimiter->SetLineStyle(kDashed); h->GetListOfFunctions()->Add(delimiter); } +} + +//_________________________________________________________________________________________ + +void addChamberLabelsForSolar(TH1* h) +{ + if (!h) { + return; + } + // disable ticks on horizontal axis + h->GetXaxis()->SetTickLength(0.0); + h->GetXaxis()->SetLabelSize(0.0); + h->GetYaxis()->SetTickLength(0); + + TText* xtitle = new TText(); + xtitle->SetNDC(); + xtitle->SetText(0.87, 0.03, "chamber"); + xtitle->SetTextSize(10); + xtitle->SetTextFont(42); + h->GetListOfFunctions()->Add(xtitle); // draw x-axis labels - for (int ch = 0; ch <= 9; ch += 1) { - float x1 = static_cast(getChamberOffset(ch)); - float x2 = (ch < 9) ? static_cast(getChamberOffset(ch + 1)) : h->GetXaxis()->GetXmax(); - float x0 = 0.8 * (x1 + x2) / (2 * h->GetXaxis()->GetXmax()) + 0.1; + float xMin{ 0 }; + float xMax{ 0 }; + for (int ch = 1; ch <= 10; ch += 1) { + xMin = xMax; + xMax += static_cast(getNumSolarPerChamber(ch)); + float x0 = 0.8 * (xMax + xMin) / (2 * h->GetXaxis()->GetXmax()) + 0.1; float y0 = 0.05; TText* label = new TText(); label->SetNDC(); - label->SetText(x0, y0, TString::Format("%d", ch + 1)); + label->SetText(x0, y0, TString::Format("%d", ch)); label->SetTextSize(10); label->SetTextFont(42); label->SetTextAlign(22); @@ -361,7 +547,52 @@ void addChamberDelimiters(TH1F* h, float xmin, float xmax) //_________________________________________________________________________________________ -void addChamberDelimiters(TH2F* h) +void addChamberDelimitersToSolarHistogram(TH1* h, float xmin, float xmax) +{ + if (!h) { + return; + } + + float scaleMin = xmin; + float scaleMax = xmax; + if (xmin == xmax) { + scaleMin = h->GetMinimum(); + scaleMax = h->GetMaximum(); + } + + // draw chamber delimiters + float xpos{ 0 }; + for (int ch = 1; ch <= 9; ch++) { + xpos += static_cast(getNumSolarPerChamber(ch)); + TLine* delimiter = new TLine(xpos, scaleMin, xpos, scaleMax); + delimiter->SetLineColor(kBlack); + delimiter->SetLineStyle(kDashed); + h->GetListOfFunctions()->Add(delimiter); + } + + //addChamberLabelsForSolar(h); + + // draw x-axis labels + /*float xMin{ 0 }; + float xMax{ 0 }; + for (int ch = 1; ch <= 10; ch += 1) { + xMin = xMax; + xMax += static_cast(getNumSolarPerChamber(ch)); + float x0 = 0.8 * (xMax + xMin) / (2 * h->GetXaxis()->GetXmax()) + 0.1; + float y0 = 0.05; + TText* label = new TText(); + label->SetNDC(); + label->SetText(x0, y0, TString::Format("%d", ch)); + label->SetTextSize(10); + label->SetTextFont(42); + label->SetTextAlign(22); + h->GetListOfFunctions()->Add(label); + }*/ +} + +//_________________________________________________________________________________________ + +void addChamberDelimiters(TH2* h) { if (!h) { return; @@ -408,6 +639,66 @@ void addChamberDelimiters(TH2F* h) //_________________________________________________________________________________________ +void addChamberDelimitersToSolarHistogram(TH2* h) +{ + if (!h) { + return; + } + // disable ticks on horizontal axis + h->GetXaxis()->SetTickLength(0.0); + h->GetXaxis()->SetLabelSize(0.0); + h->GetYaxis()->SetTickLength(0); + + TText* xtitle = new TText(); + xtitle->SetNDC(); + xtitle->SetText(0.87, 0.03, "chamber"); + xtitle->SetTextSize(10); + xtitle->SetTextFont(42); + h->GetListOfFunctions()->Add(xtitle); + + float scaleMin = h->GetYaxis()->GetXmin(); + float scaleMax = h->GetYaxis()->GetXmax(); + + // draw chamber delimiters + float xpos{ 0 }; + for (int ch = 1; ch <= 9; ch++) { + xpos += static_cast(getNumSolarPerChamber(ch)); + TLine* delimiter = new TLine(xpos, scaleMin, xpos, scaleMax); + delimiter->SetLineColor(kBlack); + delimiter->SetLineStyle(kDashed); + h->GetListOfFunctions()->Add(delimiter); + } + + // draw x-axis labels + float xMin{ 0 }; + float xMax{ 0 }; + for (int ch = 1; ch <= 10; ch += 1) { + xMin = xMax; + xMax += static_cast(getNumSolarPerChamber(ch)); + float x0 = 0.8 * (xMax + xMin) / (2 * h->GetXaxis()->GetXmax()) + 0.1; + float y0 = 0.05; + TText* label = new TText(); + label->SetNDC(); + label->SetText(x0, y0, TString::Format("%d", ch)); + label->SetTextSize(10); + label->SetTextFont(42); + label->SetTextAlign(22); + h->GetListOfFunctions()->Add(label); + } +} + +//_________________________________________________________________________________________ + +void drawThreshold(TH1* histogram, double threshold) +{ + TLine* l = new TLine(histogram->GetXaxis()->GetXmin(), threshold, histogram->GetXaxis()->GetXmax(), threshold); + l->SetLineColor(kBlue); + l->SetLineStyle(kDashed); + histogram->GetListOfFunctions()->Add(l); +} + +//_________________________________________________________________________________________ + void drawThresholdsPerStation(TH1* histogram, const std::array, 5>& thresholdsPerStation, double defaultThreshold) { double xmin = 0; @@ -442,6 +733,18 @@ void addDEBinLabels(TH1* histogram) //_________________________________________________________________________________________ +void addSolarBinLabels(TH1* histogram) +{ + auto solarIds = o2::mch::raw::getSolarUIDs(); + for (auto solar : solarIds) { + int bin = getSolarIndex(solar) + 1; + auto binLabel = std::string("S") + std::to_string(solar); + histogram->GetXaxis()->SetBinLabel(bin, binLabel.c_str()); + } +} + +//_________________________________________________________________________________________ + void splitDataSourceName(std::string s, std::string& type, std::string& name) { std::string delimiter = ":"; From 2d09135f75f640096232116232d1d540be03260a Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 5 Aug 2025 17:46:26 +0200 Subject: [PATCH 3/8] [MCH] updated Pedestals Task histogram decorations The changes are needed to sync with the updated helper code --- Modules/MUON/MCH/src/PedestalsCheck.cxx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/MUON/MCH/src/PedestalsCheck.cxx b/Modules/MUON/MCH/src/PedestalsCheck.cxx index a4761d3bf4..7d50ac6c9c 100644 --- a/Modules/MUON/MCH/src/PedestalsCheck.cxx +++ b/Modules/MUON/MCH/src/PedestalsCheck.cxx @@ -291,6 +291,7 @@ void PedestalsCheck::beautify(std::shared_ptr mo, Quality checkRe h->SetMaximum(1.1); addChamberDelimiters(h, 0, 1.1); + addChamberLabelsForDE(h); TLine* delimiter = new TLine(h->GetXaxis()->GetXmin(), mMaxEmptyFractionPerDE, h->GetXaxis()->GetXmax(), mMaxEmptyFractionPerDE); delimiter->SetLineColor(kBlack); @@ -314,6 +315,7 @@ void PedestalsCheck::beautify(std::shared_ptr mo, Quality checkRe h->SetMaximum(1.1); addChamberDelimiters(h, 0, 1.1); + addChamberLabelsForDE(h); TLine* delimiter = new TLine(h->GetXaxis()->GetXmin(), mMaxBadFractionPerDE, h->GetXaxis()->GetXmax(), mMaxBadFractionPerDE); delimiter->SetLineColor(kBlack); @@ -343,6 +345,7 @@ void PedestalsCheck::beautify(std::shared_ptr mo, Quality checkRe h->SetMaximum(max); addChamberDelimiters(h, min, max); + addChamberLabelsForDE(h); TLine* delimiter = new TLine(h->GetXaxis()->GetXmin(), mMinStatisticsPerDE, h->GetXaxis()->GetXmax(), mMinStatisticsPerDE); delimiter->SetLineColor(kBlack); @@ -369,6 +372,7 @@ void PedestalsCheck::beautify(std::shared_ptr mo, Quality checkRe h->SetMaximum(max); addChamberDelimiters(h, min, max); + addChamberLabelsForDE(h); } if (mo->getName().find("Pedestals_Elec") != std::string::npos) { From b900cf740db4da2aee45f72b4bb52000925c3893 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 5 Aug 2025 18:04:36 +0200 Subject: [PATCH 4/8] [MCH] added plots as function of SOLAR links The commit adds plots with quantities averaged over SOLAR links, similar to the existing ones as function of Detection Elements. It also adds comparisons of DE and SOLAR plots with reference ones, using the code from https://github.com/AliceO2Group/QualityControl/pull/2578 --- .../MCH/include/MCH/DecodingErrorsPlotter.h | 4 +- .../MCH/include/MCH/DecodingPostProcessing.h | 13 ++- .../MCH/include/MCH/DigitsPostProcessing.h | 10 +- .../MUON/MCH/include/MCH/EfficiencyPlotter.h | 1 + .../MCH/include/MCH/FECSyncStatusPlotter.h | 6 +- .../include/MCH/PreclustersPostProcessing.h | 14 ++- Modules/MUON/MCH/include/MCH/RatesPlotter.h | 2 + .../MUON/MCH/src/DecodingErrorsPlotter.cxx | 36 +++++- .../MUON/MCH/src/DecodingPostProcessing.cxx | 86 ++++++++++++++ Modules/MUON/MCH/src/DigitsPostProcessing.cxx | 105 +++++++++++++++++- Modules/MUON/MCH/src/EfficiencyPlotter.cxx | 11 ++ Modules/MUON/MCH/src/FECSyncStatusPlotter.cxx | 38 ++++++- .../MCH/src/PreclustersPostProcessing.cxx | 64 ++++++++++- Modules/MUON/MCH/src/PreclustersTask.cxx | 17 ++- Modules/MUON/MCH/src/RatesPlotter.cxx | 34 +++++- 15 files changed, 406 insertions(+), 35 deletions(-) diff --git a/Modules/MUON/MCH/include/MCH/DecodingErrorsPlotter.h b/Modules/MUON/MCH/include/MCH/DecodingErrorsPlotter.h index f032c32f30..e1cc0d1f09 100644 --- a/Modules/MUON/MCH/include/MCH/DecodingErrorsPlotter.h +++ b/Modules/MUON/MCH/include/MCH/DecodingErrorsPlotter.h @@ -53,10 +53,12 @@ class DecodingErrorsPlotter : public HistPlotter std::string mPath; - std::unique_ptr mHistogramGoodBoardsPerDE; ///< fraction of boards with errors per DE std::unique_ptr mHistogramErrorsPerDE; ///< error codes per DE std::unique_ptr mHistogramErrorsPerChamber; ///< error codes per chamber std::unique_ptr mHistogramErrorsPerFeeId; ///< error codes per FEE ID + + std::unique_ptr mHistogramGoodBoardsPerDE; ///< fraction of boards without errors per DE + std::unique_ptr mHistogramGoodBoardsPerSolar; ///< fraction of boards with errors per DE }; } // namespace muonchambers diff --git a/Modules/MUON/MCH/include/MCH/DecodingPostProcessing.h b/Modules/MUON/MCH/include/MCH/DecodingPostProcessing.h index 4c6ab1d4f1..5ae79d1950 100644 --- a/Modules/MUON/MCH/include/MCH/DecodingPostProcessing.h +++ b/Modules/MUON/MCH/include/MCH/DecodingPostProcessing.h @@ -21,12 +21,12 @@ #include "MCH/PostProcessingConfigMCH.h" #include "MCH/Helpers.h" -#include "Common/TH2Ratio.h" #include "MCH/HistoOnCycle.h" #include "MCH/DecodingErrorsPlotter.h" #include "MCH/HeartBeatPacketsPlotter.h" #include "MCH/FECSyncStatusPlotter.h" -#include "QualityControl/PostProcessingInterface.h" +#include "Common/ReferenceComparatorTask.h" +#include "Common/TH2Ratio.h" #include @@ -43,7 +43,7 @@ namespace o2::quality_control_modules::muonchambers { /// \brief A post-processing task which trends MCH hits and stores them in a TTree and produces plots. -class DecodingPostProcessing : public PostProcessingInterface +class DecodingPostProcessing : public ReferenceComparatorTask { public: DecodingPostProcessing() = default; @@ -73,6 +73,8 @@ class DecodingPostProcessing : public PostProcessingInterface static std::string hbPacketsSourceName() { return "hbpackets"; } static std::string syncStatusSourceName() { return "syncstatus"; } + TH1* getHistogram(std::string plotName); + bool mFullHistos{ false }; bool mEnableLastCycleHistos{ false }; bool mEnableTrending{ false }; @@ -96,7 +98,10 @@ class DecodingPostProcessing : public PostProcessingInterface std::unique_ptr mSyncStatusPlotter; std::unique_ptr mSyncStatusPlotterOnCycle; - std::unique_ptr mHistogramQualityPerDE; ///< quality flags for each DE, to be filled by checker task + std::unique_ptr mHistogramQualityPerDE; ///< quality flags for each DE, to be filled by checker task + std::unique_ptr mHistogramQualityPerSolar; ///< quality flags for each SOLAR, to be filled by checker task + + std::vector mHistogramsAll; }; template diff --git a/Modules/MUON/MCH/include/MCH/DigitsPostProcessing.h b/Modules/MUON/MCH/include/MCH/DigitsPostProcessing.h index e4ad45397f..cc3045bb7d 100644 --- a/Modules/MUON/MCH/include/MCH/DigitsPostProcessing.h +++ b/Modules/MUON/MCH/include/MCH/DigitsPostProcessing.h @@ -24,6 +24,7 @@ #include "MCH/RatesPlotter.h" #include "MCH/RatesTrendsPlotter.h" #include "MCH/OrbitsPlotter.h" +#include "Common/ReferenceComparatorTask.h" #include "Common/TH2Ratio.h" #include "QualityControl/PostProcessingInterface.h" @@ -40,7 +41,7 @@ namespace o2::quality_control_modules::muonchambers { /// \brief A post-processing task which processes and trends MCH digits and produces plots. -class DigitsPostProcessing : public PostProcessingInterface +class DigitsPostProcessing : public ReferenceComparatorTask { public: DigitsPostProcessing() = default; @@ -62,6 +63,8 @@ class DigitsPostProcessing : public PostProcessingInterface static std::string orbitsSourceName() { return "orbits"; } static std::string orbitsSignalSourceName() { return "orbits_signal"; } + TH1* getHistogram(std::string plotName); + bool mFullHistos{ false }; bool mEnableLastCycleHistos{ false }; bool mEnableTrending{ false }; @@ -99,7 +102,10 @@ class DigitsPostProcessing : public PostProcessingInterface std::unique_ptr mOrbitsPlotterSignal; std::unique_ptr mOrbitsPlotterSignalOnCycle; - std::unique_ptr mHistogramQualityPerDE; ///< quality flags for each DE, to be filled by checker task + std::unique_ptr mHistogramQualityPerDE; ///< quality flags for each DE, to be filled by checker task + std::unique_ptr mHistogramQualityPerSolar; ///< quality flags for each SOLAR, to be filled by checker task + + std::vector mHistogramsAll; }; } // namespace o2::quality_control_modules::muonchambers diff --git a/Modules/MUON/MCH/include/MCH/EfficiencyPlotter.h b/Modules/MUON/MCH/include/MCH/EfficiencyPlotter.h index ab276d93e8..1e72c8f3b6 100644 --- a/Modules/MUON/MCH/include/MCH/EfficiencyPlotter.h +++ b/Modules/MUON/MCH/include/MCH/EfficiencyPlotter.h @@ -69,6 +69,7 @@ class EfficiencyPlotter : public HistPlotter std::unique_ptr mElecMapReductor; std::array, 2> mHistogramMeanEfficiencyPerDE; + std::unique_ptr mHistogramMeanEfficiencyPerSolar; std::array>, 2> mHistogramEfficiencyDE; // 2D hit rate map for each DE std::array, 2> mHistogramEfficiencyGlobal; // Efficiency histogram (global XY view) diff --git a/Modules/MUON/MCH/include/MCH/FECSyncStatusPlotter.h b/Modules/MUON/MCH/include/MCH/FECSyncStatusPlotter.h index 439af50499..39afd9e7ae 100644 --- a/Modules/MUON/MCH/include/MCH/FECSyncStatusPlotter.h +++ b/Modules/MUON/MCH/include/MCH/FECSyncStatusPlotter.h @@ -49,11 +49,11 @@ class FECSyncStatusPlotter : public HistPlotter histograms().emplace_back(HistInfo{ h, drawOptions, displayHints }); } - o2::mch::raw::Elec2DetMapper mElec2DetMapper; - o2::mch::raw::FeeLink2SolarMapper mFeeLink2SolarMapper; + o2::mch::raw::Det2ElecMapper mDet2ElecMapper; std::unique_ptr mGoodBoardsFractionPerDE; ///< fraction of out-of-sync DS boards per detection element - std::unique_ptr mGoodTFFractionPerDE; ///< fraction of out-of-sync DS boards per chamber + std::unique_ptr mGoodTFFractionPerDE; ///< fraction of in-sync TFs per DS boards, averaged on detection elements + std::unique_ptr mGoodTFFractionPerSolar; ///< fraction of in-sync TFs per DS boards, averaged on SOLAR boards }; } // namespace muonchambers diff --git a/Modules/MUON/MCH/include/MCH/PreclustersPostProcessing.h b/Modules/MUON/MCH/include/MCH/PreclustersPostProcessing.h index b83db27abd..1ddb8d1bca 100644 --- a/Modules/MUON/MCH/include/MCH/PreclustersPostProcessing.h +++ b/Modules/MUON/MCH/include/MCH/PreclustersPostProcessing.h @@ -19,11 +19,8 @@ #ifndef QC_MODULE_MCH_PP_PRECLUSTERS_H #define QC_MODULE_MCH_PP_PRECLUSTERS_H -#include "QualityControl/PostProcessingInterface.h" - #include "MCH/PostProcessingConfigMCH.h" #include "MCH/Helpers.h" -#include "Common/TH2Ratio.h" #include "MCH/HistoOnCycle.h" #include "MCH/EfficiencyPlotter.h" #include "MCH/EfficiencyTrendsPlotter.h" @@ -31,6 +28,8 @@ #include "MCH/ClusterSizeTrendsPlotter.h" #include "MCH/ClusterChargePlotter.h" #include "MCH/ClusterChargeTrendsPlotter.h" +#include "Common/ReferenceComparatorTask.h" +#include "Common/TH2Ratio.h" namespace o2::quality_control::repository { @@ -45,7 +44,7 @@ namespace o2::quality_control_modules::muonchambers { /// \brief A post-processing task which processes and trends MCH pre-clusters and produces plots. -class PreclustersPostProcessing : public PostProcessingInterface +class PreclustersPostProcessing : public ReferenceComparatorTask { public: PreclustersPostProcessing() = default; @@ -73,6 +72,8 @@ class PreclustersPostProcessing : public PostProcessingInterface static std::string clusterChargeSourceName() { return "clcharge"; } static std::string clusterSizeSourceName() { return "clsize"; } + TH1* getHistogram(std::string plotName); + bool mFullHistos{ false }; bool mEnableLastCycleHistos{ false }; bool mEnableTrending{ false }; @@ -102,7 +103,10 @@ class PreclustersPostProcessing : public PostProcessingInterface std::unique_ptr mClusterChargeTrendsPlotter; std::unique_ptr mClusterSizeTrendsPlotter; - std::unique_ptr mHistogramQualityPerDE; ///< quality flags for each DE, to be filled by checker task + std::unique_ptr mHistogramQualityPerDE; ///< quality flags for each DE, to be filled by checker task + std::unique_ptr mHistogramQualityPerSolar; ///< quality flags for each SOLAR, to be filled by checker task + + std::vector mHistogramsAll; }; template diff --git a/Modules/MUON/MCH/include/MCH/RatesPlotter.h b/Modules/MUON/MCH/include/MCH/RatesPlotter.h index 2d4649a1cb..c3068c67cb 100644 --- a/Modules/MUON/MCH/include/MCH/RatesPlotter.h +++ b/Modules/MUON/MCH/include/MCH/RatesPlotter.h @@ -69,8 +69,10 @@ class RatesPlotter : public HistPlotter std::unique_ptr mHistogramRatePerStation; std::unique_ptr mHistogramMeanRatePerDE; + std::unique_ptr mHistogramMeanRatePerSolar; std::unique_ptr mHistogramGoodChannelsFractionPerDE; + std::unique_ptr mHistogramGoodChannelsFractionPerSolar; std::map> mHistogramRateDE[2]; // 2D hit rate map for each DE std::shared_ptr mHistogramRateGlobal[2]; // Rate histogram (global XY view) diff --git a/Modules/MUON/MCH/src/DecodingErrorsPlotter.cxx b/Modules/MUON/MCH/src/DecodingErrorsPlotter.cxx index 6fd55fc7bd..03080083b1 100644 --- a/Modules/MUON/MCH/src/DecodingErrorsPlotter.cxx +++ b/Modules/MUON/MCH/src/DecodingErrorsPlotter.cxx @@ -60,8 +60,14 @@ DecodingErrorsPlotter::DecodingErrorsPlotter(std::string path) : mPath(path) // Number of decoding errors, grouped by FEE ID and normalized to the number of processed TF mHistogramGoodBoardsPerDE = std::make_unique(TString::Format("%sGoodBoardsFractionPerDE", path.c_str()), "Fraction of boards not in error", getNumDE(), 0, getNumDE()); + addDEBinLabels(mHistogramGoodBoardsPerDE.get()); addHisto(mHistogramGoodBoardsPerDE.get(), false, "", ""); + mHistogramGoodBoardsPerSolar = std::make_unique(TString::Format("%sGoodBoardsFractionPerSolar", path.c_str()), + "Fraction of boards not in error per SOLAR board", getNumSolar(), 0, getNumSolar()); + addSolarBinLabels(mHistogramGoodBoardsPerSolar.get()); + addHisto(mHistogramGoodBoardsPerSolar.get(), false, "", ""); + //-------------------------------------------- // Decoding errors per chamber, DE and FEEID //-------------------------------------------- @@ -122,7 +128,8 @@ void DecodingErrorsPlotter::update(TH2F* h) mHistogramErrorsPerDE->Reset("ICES"); mHistogramErrorsPerChamber->Reset("ICES"); - std::array, getNumDE()> goodBoardsFraction; + std::array, getNumDE()> goodBoardsFractionPerDE; + std::array, getNumSolar()> goodBoardsFractionPerSolar; // loop over bins in electronics coordinates, and map the channels to the corresponding cathode pads int nbinsx = h->GetXaxis()->GetNbins(); @@ -144,9 +151,10 @@ void DecodingErrorsPlotter::update(TH2F* h) // where one bin is one physical pad // get the unique solar ID and the DS address associated to this digit int feeId = -1; + int solarId = -1; std::optional dsElecId = mDet2ElecMapper(dsDetId); if (dsElecId) { - uint32_t solarId = dsElecId->solarId(); + solarId = dsElecId->solarId(); uint32_t dsAddr = dsElecId->elinkId(); std::optional feeLinkId = mSolar2FeeLinkMapper(solarId); @@ -154,6 +162,10 @@ void DecodingErrorsPlotter::update(TH2F* h) feeId = feeLinkId->feeId(); } } + int solarIndex = (solarId >= 0) ? getSolarIndex(solarId) : -1; + if (solarIndex < 0) { + continue; + } bool hasError = false; @@ -171,21 +183,33 @@ void DecodingErrorsPlotter::update(TH2F* h) incrementBin(mHistogramErrorsPerChamber.get(), chamber, j, count); } - goodBoardsFraction[deIndex].first += 1; + goodBoardsFractionPerDE[deIndex].first += 1; + goodBoardsFractionPerSolar[solarIndex].first += 1; if (!hasError) { - goodBoardsFraction[deIndex].second += 1; + goodBoardsFractionPerDE[deIndex].second += 1; + goodBoardsFractionPerSolar[solarIndex].second += 1; } } // update fraction of good boards per DE for (int i = 0; i < getNumDE(); i++) { - if (goodBoardsFraction[i].first > 0) { - float frac = goodBoardsFraction[i].second / goodBoardsFraction[i].first; + if (goodBoardsFractionPerDE[i].first > 0) { + float frac = goodBoardsFractionPerDE[i].second / goodBoardsFractionPerDE[i].first; mHistogramGoodBoardsPerDE->SetBinContent(i + 1, frac); } else { mHistogramGoodBoardsPerDE->SetBinContent(i + 1, 0); } } + + // update fraction of good boards per Solar + for (int i = 0; i < getNumSolar(); i++) { + if (goodBoardsFractionPerSolar[i].first > 0) { + float frac = goodBoardsFractionPerSolar[i].second / goodBoardsFractionPerSolar[i].first; + mHistogramGoodBoardsPerSolar->SetBinContent(i + 1, frac); + } else { + mHistogramGoodBoardsPerSolar->SetBinContent(i + 1, 0); + } + } } } // namespace muonchambers diff --git a/Modules/MUON/MCH/src/DecodingPostProcessing.cxx b/Modules/MUON/MCH/src/DecodingPostProcessing.cxx index a53c38b3dd..92748280c2 100644 --- a/Modules/MUON/MCH/src/DecodingPostProcessing.cxx +++ b/Modules/MUON/MCH/src/DecodingPostProcessing.cxx @@ -19,6 +19,7 @@ #include "MCH/DecodingPostProcessing.h" #include "MCH/PostProcessingConfigMCH.h" #include "MUONCommon/Helpers.h" +#include "Common/ReferenceComparatorPlot.h" #include #include "QualityControl/QcInfoLogger.h" #include "QualityControl/DatabaseInterface.h" @@ -33,6 +34,8 @@ using namespace o2::mch::raw; void DecodingPostProcessing::configure(const boost::property_tree::ptree& config) { + ReferenceComparatorTask::configure(config); + mConfig = PostProcessingConfigMCH(getID(), config); } @@ -48,6 +51,13 @@ void DecodingPostProcessing::createDecodingErrorsHistos(Trigger t, repository::D mErrorsPlotter = std::make_unique("DecodingErrors/"); mErrorsPlotter->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mErrorsPlotter->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + if (mEnableLastCycleHistos) { // Helpers to extract plots from last cycle auto obj = mCcdbObjects.find(errorsSourceName()); @@ -59,6 +69,13 @@ void DecodingPostProcessing::createDecodingErrorsHistos(Trigger t, repository::D mErrorsPlotterOnCycle.reset(); mErrorsPlotterOnCycle = std::make_unique("DecodingErrors/LastCycle/"); mErrorsPlotterOnCycle->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + + for (auto& hinfo : mErrorsPlotterOnCycle->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } } } @@ -74,6 +91,13 @@ void DecodingPostProcessing::createHeartBeatPacketsHistos(Trigger t, repository: mHBPacketsPlotter = std::make_unique("HeartBeatPackets/", mFullHistos); mHBPacketsPlotter->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mHBPacketsPlotter->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + if (mEnableLastCycleHistos) { // Helpers to extract plots from last cycle auto obj = mCcdbObjects.find(hbPacketsSourceName()); @@ -85,6 +109,13 @@ void DecodingPostProcessing::createHeartBeatPacketsHistos(Trigger t, repository: mHBPacketsPlotterOnCycle.reset(); mHBPacketsPlotterOnCycle = std::make_unique("HeartBeatPackets/LastCycle/", mFullHistos); mHBPacketsPlotterOnCycle->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + + for (auto& hinfo : mHBPacketsPlotterOnCycle->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } } } @@ -100,6 +131,13 @@ void DecodingPostProcessing::createSyncStatusHistos(Trigger t, repository::Datab mSyncStatusPlotter = std::make_unique("SyncErrors/"); mSyncStatusPlotter->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mSyncStatusPlotter->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + if (mEnableLastCycleHistos) { // Helpers to extract plots from last cycle auto obj = mCcdbObjects.find(syncStatusSourceName()); @@ -111,6 +149,13 @@ void DecodingPostProcessing::createSyncStatusHistos(Trigger t, repository::Datab mSyncStatusPlotterOnCycle.reset(); mSyncStatusPlotterOnCycle = std::make_unique("SyncErrors/LastCycle/"); mSyncStatusPlotterOnCycle->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + + for (auto& hinfo : mSyncStatusPlotterOnCycle->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } } } @@ -118,6 +163,8 @@ void DecodingPostProcessing::createSyncStatusHistos(Trigger t, repository::Datab void DecodingPostProcessing::initialize(Trigger t, framework::ServiceRegistryRef services) { + ReferenceComparatorTask::initialize(t, services); + auto& qcdb = services.get(); const auto& activity = t.activity; @@ -156,6 +203,9 @@ void DecodingPostProcessing::initialize(Trigger t, framework::ServiceRegistryRef mHistogramQualityPerDE.reset(); mHistogramQualityPerDE = std::make_unique("QualityFlagPerDE", "Quality Flag vs DE", getNumDE(), 0, getNumDE(), 3, 0, 3); + addDEBinLabels(mHistogramQualityPerDE.get()); + addChamberDelimiters(mHistogramQualityPerDE.get()); + addChamberLabelsForDE(mHistogramQualityPerDE.get()); mHistogramQualityPerDE->GetYaxis()->SetBinLabel(1, "Bad"); mHistogramQualityPerDE->GetYaxis()->SetBinLabel(2, "Medium"); mHistogramQualityPerDE->GetYaxis()->SetBinLabel(3, "Good"); @@ -164,6 +214,20 @@ void DecodingPostProcessing::initialize(Trigger t, framework::ServiceRegistryRef getObjectsManager()->startPublishing(mHistogramQualityPerDE.get(), core::PublicationPolicy::ThroughStop); getObjectsManager()->setDefaultDrawOptions(mHistogramQualityPerDE.get(), "colz"); getObjectsManager()->setDisplayHint(mHistogramQualityPerDE.get(), "gridy"); + + mHistogramQualityPerSolar.reset(); + mHistogramQualityPerSolar = std::make_unique("QualityFlagPerSolar", "Quality Flag vs Solar", getNumSolar(), 0, getNumSolar(), 3, 0, 3); + addSolarBinLabels(mHistogramQualityPerSolar.get()); + addChamberDelimitersToSolarHistogram(mHistogramQualityPerSolar.get()); + addChamberLabelsForSolar(mHistogramQualityPerSolar.get()); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(1, "Bad"); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(2, "Medium"); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(3, "Good"); + mHistogramQualityPerSolar->SetOption("col"); + mHistogramQualityPerSolar->SetStats(0); + getObjectsManager()->startPublishing(mHistogramQualityPerSolar.get(), core::PublicationPolicy::ThroughStop); + getObjectsManager()->setDefaultDrawOptions(mHistogramQualityPerSolar.get(), "col"); + getObjectsManager()->setDisplayHint(mHistogramQualityPerSolar.get(), "gridy"); } //_________________________________________________________________________________________ @@ -222,6 +286,18 @@ void DecodingPostProcessing::updateSyncStatusHistos(Trigger t, repository::Datab //_________________________________________________________________________________________ +TH1* DecodingPostProcessing::getHistogram(std::string plotName) +{ + TH1* result{ nullptr }; + for (auto hist : mHistogramsAll) { + if (plotName == hist->GetName()) { + result = hist; + break; + } + } + return result; +} + void DecodingPostProcessing::update(Trigger t, framework::ServiceRegistryRef services) { auto& qcdb = services.get(); @@ -229,6 +305,16 @@ void DecodingPostProcessing::update(Trigger t, framework::ServiceRegistryRef ser updateDecodingErrorsHistos(t, &qcdb); updateHeartBeatPacketsHistos(t, &qcdb); updateSyncStatusHistos(t, &qcdb); + + auto& comparatorPlots = getComparatorPlots(); + for (auto& [plotName, plot] : comparatorPlots) { + TH1* hist = getHistogram(plotName); + if (!hist) { + continue; + } + + plot->update(hist); + } } //_________________________________________________________________________________________ diff --git a/Modules/MUON/MCH/src/DigitsPostProcessing.cxx b/Modules/MUON/MCH/src/DigitsPostProcessing.cxx index f273301cb0..8412a6562b 100644 --- a/Modules/MUON/MCH/src/DigitsPostProcessing.cxx +++ b/Modules/MUON/MCH/src/DigitsPostProcessing.cxx @@ -18,6 +18,8 @@ #include "MCH/DigitsPostProcessing.h" #include "MUONCommon/Helpers.h" +#include "Common/ReferenceComparatorPlot.h" +#include "QualityControl/ReferenceUtils.h" #include "QualityControl/QcInfoLogger.h" #include "QualityControl/DatabaseInterface.h" #include @@ -27,6 +29,8 @@ using namespace o2::quality_control_modules::muon; void DigitsPostProcessing::configure(const boost::property_tree::ptree& config) { + ReferenceComparatorTask::configure(config); + mConfig = PostProcessingConfigMCH(getID(), config); } @@ -42,10 +46,24 @@ void DigitsPostProcessing::createRatesHistos(Trigger t, repository::DatabaseInte mRatesPlotter = std::make_unique("Rates/", mChannelRateMin, mChannelRateMax, true, mFullHistos); mRatesPlotter->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mRatesPlotter->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + mRatesPlotterSignal.reset(); mRatesPlotterSignal = std::make_unique("RatesSignal/", mChannelRateMin, mChannelRateMax, true, mFullHistos); mRatesPlotterSignal->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mRatesPlotterSignal->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + //---------------------------------- // Rate plotters for last cycle //---------------------------------- @@ -68,9 +86,23 @@ void DigitsPostProcessing::createRatesHistos(Trigger t, repository::DatabaseInte mRatesPlotterOnCycle = std::make_unique("Rates/LastCycle/", mChannelRateMin, mChannelRateMax, false, mFullHistos); mRatesPlotterOnCycle->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mRatesPlotterOnCycle->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + mRatesPlotterSignalOnCycle.reset(); mRatesPlotterSignalOnCycle = std::make_unique("RatesSignal/LastCycle/", mChannelRateMin, mChannelRateMax, false, mFullHistos); mRatesPlotterSignalOnCycle->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + + for (auto& hinfo : mRatesPlotterSignalOnCycle->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } } //---------------------------------- @@ -100,10 +132,24 @@ void DigitsPostProcessing::createOrbitHistos(Trigger t, repository::DatabaseInte mOrbitsPlotter = std::make_unique("Orbits/"); mOrbitsPlotter->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mOrbitsPlotter->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + mOrbitsPlotterSignal.reset(); mOrbitsPlotterSignal = std::make_unique("OrbitsSignal/"); mOrbitsPlotterSignal->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mOrbitsPlotterSignal->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + //---------------------------------- // Orbit plotters for last cycle //---------------------------------- @@ -126,9 +172,23 @@ void DigitsPostProcessing::createOrbitHistos(Trigger t, repository::DatabaseInte mOrbitsPlotterOnCycle = std::make_unique("Orbits/LastCycle/"); mOrbitsPlotterOnCycle->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mOrbitsPlotterOnCycle->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + mOrbitsPlotterSignalOnCycle.reset(); mOrbitsPlotterSignalOnCycle = std::make_unique("OrbitsSignal/LastCycle/"); mOrbitsPlotterSignalOnCycle->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + + for (auto& hinfo : mOrbitsPlotterSignalOnCycle->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } } } @@ -136,6 +196,8 @@ void DigitsPostProcessing::createOrbitHistos(Trigger t, repository::DatabaseInte void DigitsPostProcessing::initialize(Trigger t, framework::ServiceRegistryRef services) { + ReferenceComparatorTask::initialize(t, services); + auto& qcdb = services.get(); const auto& activity = t.activity; @@ -177,14 +239,31 @@ void DigitsPostProcessing::initialize(Trigger t, framework::ServiceRegistryRef s mHistogramQualityPerDE.reset(); mHistogramQualityPerDE = std::make_unique("QualityFlagPerDE", "Quality Flag vs DE", getNumDE(), 0, getNumDE(), 3, 0, 3); + addDEBinLabels(mHistogramQualityPerDE.get()); + addChamberDelimiters(mHistogramQualityPerDE.get()); + addChamberLabelsForDE(mHistogramQualityPerDE.get()); mHistogramQualityPerDE->GetYaxis()->SetBinLabel(1, "Bad"); mHistogramQualityPerDE->GetYaxis()->SetBinLabel(2, "Medium"); mHistogramQualityPerDE->GetYaxis()->SetBinLabel(3, "Good"); - mHistogramQualityPerDE->SetOption("colz"); + mHistogramQualityPerDE->SetOption("col"); mHistogramQualityPerDE->SetStats(0); getObjectsManager()->startPublishing(mHistogramQualityPerDE.get(), core::PublicationPolicy::ThroughStop); - getObjectsManager()->setDefaultDrawOptions(mHistogramQualityPerDE.get(), "colz"); + getObjectsManager()->setDefaultDrawOptions(mHistogramQualityPerDE.get(), "col"); getObjectsManager()->setDisplayHint(mHistogramQualityPerDE.get(), "gridy"); + + mHistogramQualityPerSolar.reset(); + mHistogramQualityPerSolar = std::make_unique("QualityFlagPerSolar", "Quality Flag vs Solar", getNumSolar(), 0, getNumSolar(), 3, 0, 3); + addSolarBinLabels(mHistogramQualityPerSolar.get()); + addChamberDelimitersToSolarHistogram(mHistogramQualityPerSolar.get()); + addChamberLabelsForSolar(mHistogramQualityPerSolar.get()); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(1, "Bad"); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(2, "Medium"); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(3, "Good"); + mHistogramQualityPerSolar->SetOption("col"); + mHistogramQualityPerSolar->SetStats(0); + getObjectsManager()->startPublishing(mHistogramQualityPerSolar.get(), core::PublicationPolicy::ThroughStop); + getObjectsManager()->setDefaultDrawOptions(mHistogramQualityPerSolar.get(), "col"); + getObjectsManager()->setDisplayHint(mHistogramQualityPerSolar.get(), "gridy"); } //_________________________________________________________________________________________ @@ -269,12 +348,34 @@ void DigitsPostProcessing::updateOrbitHistos(Trigger t, repository::DatabaseInte //_________________________________________________________________________________________ +TH1* DigitsPostProcessing::getHistogram(std::string plotName) +{ + TH1* result{ nullptr }; + for (auto hist : mHistogramsAll) { + if (plotName == hist->GetName()) { + result = hist; + break; + } + } + return result; +} + void DigitsPostProcessing::update(Trigger t, framework::ServiceRegistryRef services) { auto& qcdb = services.get(); updateRateHistos(t, &qcdb); updateOrbitHistos(t, &qcdb); + + auto& comparatorPlots = getComparatorPlots(); + for (auto& [plotName, plot] : comparatorPlots) { + TH1* hist = getHistogram(plotName); + if (!hist) { + continue; + } + + plot->update(hist); + } } //_________________________________________________________________________________________ diff --git a/Modules/MUON/MCH/src/EfficiencyPlotter.cxx b/Modules/MUON/MCH/src/EfficiencyPlotter.cxx index d003a50041..fc3b64610e 100644 --- a/Modules/MUON/MCH/src/EfficiencyPlotter.cxx +++ b/Modules/MUON/MCH/src/EfficiencyPlotter.cxx @@ -47,9 +47,15 @@ EfficiencyPlotter::EfficiencyPlotter(std::string path, bool fullPlots) mHistogramMeanEfficiencyPerDE[ci] = std::make_unique(TString::Format("%sMeanEfficiency%s", path.c_str(), sc[ci].c_str()), TString::Format("Mean Efficiency vs DE (%s)", sc[ci].c_str()), getNumDE(), 0, getNumDE()); + addDEBinLabels(mHistogramMeanEfficiencyPerDE[ci].get()); addHisto(mHistogramMeanEfficiencyPerDE[ci].get(), false, "histo", "histo"); } + mHistogramMeanEfficiencyPerSolar = std::make_unique(TString::Format("%sMeanEfficiencyPerSolar", path.c_str()), "Mean Efficiency per SOLAR board", + getNumSolar(), 0, getNumSolar()); + addSolarBinLabels(mHistogramMeanEfficiencyPerSolar.get()); + addHisto(mHistogramMeanEfficiencyPerSolar.get(), false, "histo", "histo"); + //-------------------------------------------------- // Efficiency histograms in global detector coordinates //-------------------------------------------------- @@ -93,6 +99,11 @@ void EfficiencyPlotter::fillAverageHistograms() mHistogramMeanEfficiencyPerDE[ci]->SetBinError(de + 1, 0.1); } } + + for (size_t solar = 0; solar < mHistogramMeanEfficiencyPerSolar->GetXaxis()->GetNbins(); solar++) { + mHistogramMeanEfficiencyPerSolar->SetBinContent(solar + 1, mElecMapReductor->getSolarValue(solar)); + mHistogramMeanEfficiencyPerSolar->SetBinError(solar + 1, 0.1); + } } //_________________________________________________________________________________________ diff --git a/Modules/MUON/MCH/src/FECSyncStatusPlotter.cxx b/Modules/MUON/MCH/src/FECSyncStatusPlotter.cxx index 014e6c3452..a153e015b8 100644 --- a/Modules/MUON/MCH/src/FECSyncStatusPlotter.cxx +++ b/Modules/MUON/MCH/src/FECSyncStatusPlotter.cxx @@ -42,16 +42,20 @@ static void setYAxisLabels(TH2F* hErrors) FECSyncStatusPlotter::FECSyncStatusPlotter(std::string path) { - mElec2DetMapper = createElec2DetMapper(); - mFeeLink2SolarMapper = createFeeLink2SolarMapper(); + mDet2ElecMapper = o2::mch::raw::createDet2ElecMapper(); //-------------------------------------------- // Fraction of synchronized boards per DE //-------------------------------------------- - mGoodTFFractionPerDE = std::make_unique(TString::Format("%sSyncedBoardsFractionPerDE", path.c_str()), "Synchronized boards fraction", getNumDE(), 0, getNumDE()); + mGoodTFFractionPerDE = std::make_unique(TString::Format("%sSyncedBoardsFractionPerDE", path.c_str()), "Synchronized boards fraction per DE", getNumDE(), 0, getNumDE()); + addDEBinLabels(mGoodTFFractionPerDE.get()); addHisto(mGoodTFFractionPerDE.get(), false, "hist", ""); + mGoodTFFractionPerSolar = std::make_unique(TString::Format("%sSyncedBoardsFractionPerSolar", path.c_str()), "Synchronized boards fraction per SOLAR", getNumSolar(), 0, getNumSolar()); + addSolarBinLabels(mGoodTFFractionPerSolar.get()); + addHisto(mGoodTFFractionPerSolar.get(), false, "hist", ""); + mGoodBoardsFractionPerDE = std::make_unique(TString::Format("%sSyncedBoardsFractionPerDEalt", path.c_str()), "Synchronized boards fraction (v.2)", getNumDE(), 0, getNumDE()); addHisto(mGoodBoardsFractionPerDE.get(), false, "hist", ""); } @@ -72,6 +76,12 @@ void FECSyncStatusPlotter::update(TH2F* h) std::fill(deGoodBoards.begin(), deGoodBoards.end(), 0); std::fill(deGoodFrac.begin(), deGoodFrac.end(), 0); + std::vector solarNumBoards(static_cast(getNumSolar())); + std::vector solarGoodFrac(static_cast(getNumSolar())); + + std::fill(solarNumBoards.begin(), solarNumBoards.end(), 0); + std::fill(solarGoodFrac.begin(), solarGoodFrac.end(), 0); + int nbinsx = h->GetXaxis()->GetNbins(); for (int i = 1; i <= nbinsx; i++) { // address of the DS board in detector representation @@ -83,6 +93,17 @@ void FECSyncStatusPlotter::update(TH2F* h) continue; } + auto dsElecId = mDet2ElecMapper(dsDetId); + if (!dsElecId) { + continue; + } + auto solarId = dsElecId->solarId(); + + int solarIndex = getSolarIndex(solarId); + if (solarIndex < 0) { + continue; + } + auto nGood = h->GetBinContent(i, 1); auto nBad = h->GetBinContent(i, 2); auto nMissing = h->GetBinContent(i, 3); @@ -94,6 +115,9 @@ void FECSyncStatusPlotter::update(TH2F* h) deGoodBoards[deIndex] += 1; } deGoodFrac[deIndex] += goodFrac; + + solarNumBoards[solarIndex] += 1; + solarGoodFrac[solarIndex] += goodFrac; } // update the average number of out-of-sync boards @@ -106,6 +130,14 @@ void FECSyncStatusPlotter::update(TH2F* h) mGoodTFFractionPerDE->SetBinContent(i + 1, 0); } } + + for (size_t i = 0; i < solarNumBoards.size(); i++) { + if (solarNumBoards[i] > 0) { + mGoodTFFractionPerSolar->SetBinContent(i + 1, solarGoodFrac[i] / solarNumBoards[i]); + } else { + mGoodTFFractionPerSolar->SetBinContent(i + 1, 0); + } + } } } // namespace muonchambers diff --git a/Modules/MUON/MCH/src/PreclustersPostProcessing.cxx b/Modules/MUON/MCH/src/PreclustersPostProcessing.cxx index b6e5b4b14d..3c3f39344b 100644 --- a/Modules/MUON/MCH/src/PreclustersPostProcessing.cxx +++ b/Modules/MUON/MCH/src/PreclustersPostProcessing.cxx @@ -18,6 +18,8 @@ #include "MCH/PreclustersPostProcessing.h" #include "MUONCommon/Helpers.h" +#include "Common/ReferenceComparatorPlot.h" +#include "QualityControl/ReferenceUtils.h" #include "QualityControl/QcInfoLogger.h" using namespace o2::quality_control_modules::muonchambers; @@ -25,6 +27,8 @@ using namespace o2::quality_control_modules::muon; void PreclustersPostProcessing::configure(const boost::property_tree::ptree& config) { + ReferenceComparatorTask::configure(config); + mConfig = PostProcessingConfigMCH(getID(), config); } @@ -40,6 +44,13 @@ void PreclustersPostProcessing::createEfficiencyHistos(Trigger t, repository::Da mEfficiencyPlotter = std::make_unique("Efficiency/", mFullHistos); mEfficiencyPlotter->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + for (auto& hinfo : mEfficiencyPlotter->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } + if (mEnableLastCycleHistos) { // Helpers to extract plots from last cycle auto obj = mCcdbObjects.find(effSourceName()); @@ -50,6 +61,13 @@ void PreclustersPostProcessing::createEfficiencyHistos(Trigger t, repository::Da mEfficiencyPlotterOnCycle.reset(); mEfficiencyPlotterOnCycle = std::make_unique("Efficiency/LastCycle/", mFullHistos); mEfficiencyPlotterOnCycle->publish(getObjectsManager(), core::PublicationPolicy::ThroughStop); + + for (auto& hinfo : mEfficiencyPlotterOnCycle->histograms()) { + TH1* hist = dynamic_cast(hinfo.object); + if (hist) { + mHistogramsAll.push_back(hist); + } + } } //---------------------------------- @@ -139,6 +157,8 @@ void PreclustersPostProcessing::createClusterSizeHistos(Trigger t, repository::D void PreclustersPostProcessing::initialize(Trigger t, framework::ServiceRegistryRef services) { + ReferenceComparatorTask::initialize(t, services); + auto& qcdb = services.get(); const auto& activity = t.activity; @@ -172,11 +192,14 @@ void PreclustersPostProcessing::initialize(Trigger t, framework::ServiceRegistry createClusterSizeHistos(t, &qcdb); //-------------------------------------------------- - // Detector quality histogram + // Quality histogram //-------------------------------------------------- mHistogramQualityPerDE.reset(); mHistogramQualityPerDE = std::make_unique("QualityFlagPerDE", "Quality Flag vs DE", getNumDE(), 0, getNumDE(), 3, 0, 3); + addDEBinLabels(mHistogramQualityPerDE.get()); + addChamberDelimiters(mHistogramQualityPerDE.get()); + addChamberLabelsForDE(mHistogramQualityPerDE.get()); mHistogramQualityPerDE->GetYaxis()->SetBinLabel(1, "Bad"); mHistogramQualityPerDE->GetYaxis()->SetBinLabel(2, "Medium"); mHistogramQualityPerDE->GetYaxis()->SetBinLabel(3, "Good"); @@ -185,6 +208,20 @@ void PreclustersPostProcessing::initialize(Trigger t, framework::ServiceRegistry getObjectsManager()->startPublishing(mHistogramQualityPerDE.get(), core::PublicationPolicy::ThroughStop); getObjectsManager()->setDefaultDrawOptions(mHistogramQualityPerDE.get(), "colz"); getObjectsManager()->setDisplayHint(mHistogramQualityPerDE.get(), "gridy"); + + mHistogramQualityPerSolar.reset(); + mHistogramQualityPerSolar = std::make_unique("QualityFlagPerSolar", "Quality Flag vs Solar", getNumSolar(), 0, getNumSolar(), 3, 0, 3); + addSolarBinLabels(mHistogramQualityPerSolar.get()); + addChamberDelimitersToSolarHistogram(mHistogramQualityPerSolar.get()); + addChamberLabelsForSolar(mHistogramQualityPerSolar.get()); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(1, "Bad"); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(2, "Medium"); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(3, "Good"); + mHistogramQualityPerSolar->SetOption("col"); + mHistogramQualityPerSolar->SetStats(0); + getObjectsManager()->startPublishing(mHistogramQualityPerSolar.get(), core::PublicationPolicy::ThroughStop); + getObjectsManager()->setDefaultDrawOptions(mHistogramQualityPerSolar.get(), "col"); + getObjectsManager()->setDisplayHint(mHistogramQualityPerSolar.get(), "gridy"); } //_________________________________________________________________________________________ @@ -270,6 +307,18 @@ void PreclustersPostProcessing::updateClusterSizeHistos(Trigger t, repository::D //_________________________________________________________________________________________ +TH1* PreclustersPostProcessing::getHistogram(std::string plotName) +{ + TH1* result{ nullptr }; + for (auto hist : mHistogramsAll) { + if (plotName == hist->GetName()) { + result = hist; + break; + } + } + return result; +} + void PreclustersPostProcessing::update(Trigger t, framework::ServiceRegistryRef services) { auto& qcdb = services.get(); @@ -277,10 +326,21 @@ void PreclustersPostProcessing::update(Trigger t, framework::ServiceRegistryRef updateEfficiencyHistos(t, &qcdb); updateClusterChargeHistos(t, &qcdb); updateClusterSizeHistos(t, &qcdb); + + auto& comparatorPlots = getComparatorPlots(); + for (auto& [plotName, plot] : comparatorPlots) { + TH1* hist = getHistogram(plotName); + if (!hist) { + continue; + } + + plot->update(hist); + } } //_________________________________________________________________________________________ -void PreclustersPostProcessing::finalize(Trigger t, framework::ServiceRegistryRef) +void PreclustersPostProcessing::finalize(Trigger t, framework::ServiceRegistryRef services) { + ReferenceComparatorTask::finalize(t, services); } diff --git a/Modules/MUON/MCH/src/PreclustersTask.cxx b/Modules/MUON/MCH/src/PreclustersTask.cxx index 2b9bb096cd..12a4c9927d 100644 --- a/Modules/MUON/MCH/src/PreclustersTask.cxx +++ b/Modules/MUON/MCH/src/PreclustersTask.cxx @@ -91,17 +91,17 @@ void PreclustersTask::initialize(o2::framework::InitContext& /*ctx*/) publishObject(mHistogramClusterCharge.get(), "colz", false); mHistogramClusterChargePerStation[0] = std::make_unique("ClusterCharge/ClusterChargeDistributionB", - "Cluster charge distribution (B)", + "Pre-cluster charge distribution (B)", 256, 0, 256 * 50, 5, 1, 6); publishObject(mHistogramClusterChargePerStation[0].get(), "colz", false); mHistogramClusterChargePerStation[1] = std::make_unique("ClusterCharge/ClusterChargeDistributionNB", - "Cluster charge distribution (NB)", + "Pre-cluster charge distribution (NB)", 256, 0, 256 * 50, 5, 1, 6); publishObject(mHistogramClusterChargePerStation[1].get(), "colz", false); mHistogramClusterChargePerStation[2] = std::make_unique("ClusterCharge/ClusterChargeDistribution", - "Cluster charge distribution", + "Pre-cluster charge distribution", 256, 0, 256 * 50, 5, 1, 6); publishObject(mHistogramClusterChargePerStation[2].get(), "colz", false); @@ -115,17 +115,17 @@ void PreclustersTask::initialize(o2::framework::InitContext& /*ctx*/) publishObject(mHistogramClusterSize.get(), "colz", false); mHistogramClusterSizePerStation[0] = std::make_unique("ClusterSize/ClusterSizeDistributionB", - "Cluster size distribution (B)", + "Pre-cluster size distribution (B)", 50, 0, 50, 5, 1, 6); publishObject(mHistogramClusterSizePerStation[0].get(), "colz", false); mHistogramClusterSizePerStation[1] = std::make_unique("ClusterSize/ClusterSizeDistributionNB", - "Cluster size distribution (NB)", + "Pre-cluster size distribution (NB)", 50, 0, 50, 5, 1, 6); publishObject(mHistogramClusterSizePerStation[1].get(), "colz", false); mHistogramClusterSizePerStation[2] = std::make_unique("ClusterSize/ClusterSizeDistribution", - "Cluster size distribution", + "Pre-cluster size distribution", 50, 0, 50, 5, 1, 6); publishObject(mHistogramClusterSizePerStation[2].get(), "colz", false); @@ -299,6 +299,7 @@ void PreclustersTask::plotPrecluster(const o2::mch::PreCluster& preCluster, gsl: auto stationId = ((chamberId - 1) / 2) + 1; if (stationId < 1 || stationId > 5) { + ILOG(Info, Devel) << "[PreclustersTask::plotPrecluster()] wrong station ID for DE" << deId << AliceO2::InfoLogger::InfoLogger::endm; return; } const o2::mch::mapping::Segmentation& segment = o2::mch::mapping::segmentation(deId); @@ -341,6 +342,10 @@ void PreclustersTask::plotPrecluster(const o2::mch::PreCluster& preCluster, gsl: if (segment.findPadPairByPosition(Xcog, Ycog, padIdB, padIdNB)) { getFecChannel(deId, padIdB, fecIdB, channelB); getFecChannel(deId, padIdNB, fecIdNB, channelNB); + } else { + ILOG(Info, Devel) << "[PreclustersTask::plotPrecluster()] could not find pad in DE" << deId + << " for pre-cluster at (" << Xcog << "," << Ycog << ")" << AliceO2::InfoLogger::InfoLogger::endm; + return; } // criteria to define a "good" charge cluster in one cathode: diff --git a/Modules/MUON/MCH/src/RatesPlotter.cxx b/Modules/MUON/MCH/src/RatesPlotter.cxx index ff62b2f086..22e88a6229 100644 --- a/Modules/MUON/MCH/src/RatesPlotter.cxx +++ b/Modules/MUON/MCH/src/RatesPlotter.cxx @@ -45,7 +45,9 @@ RatesPlotter::RatesPlotter(std::string path, float rateMin, float rateMax, bool //---------------------------------- int nbins = 100; - auto xbins = makeLogBinning(rateMin / 10, rateMax * 10, nbins); + double xMax = rateMax * 10; + double xMin = (rateMin > 0) ? rateMin / 10 : xMax / 1000000; + auto xbins = makeLogBinning(xMin, xMax, nbins); std::vector ybins{ 1, 2, 3, 4, 5, 6 }; mHistogramRatePerStation = std::make_unique(TString::Format("%sRatesDistribution", path.c_str()), "Rates distribution", @@ -65,16 +67,28 @@ RatesPlotter::RatesPlotter(std::string path, float rateMin, float rateMax, bool mHistogramMeanRatePerDE = std::make_unique(TString::Format("%sMeanRate", path.c_str()), "Mean Rate", getNumDE(), 0, getNumDE()); + addDEBinLabels(mHistogramMeanRatePerDE.get()); addHisto(mHistogramMeanRatePerDE.get(), false, "histo", "logy"); + mHistogramMeanRatePerSolar = std::make_unique(TString::Format("%sMeanRatePerSolar", path.c_str()), "Mean Rate per SOLAR board", + getNumSolar(), 0, getNumSolar()); + addSolarBinLabels(mHistogramMeanRatePerSolar.get()); + addHisto(mHistogramMeanRatePerSolar.get(), false, "histo", "logy"); + //---------------------------------- // "Good" channels fraction histograms //---------------------------------- mHistogramGoodChannelsFractionPerDE = std::make_unique(TString::Format("%sGoodChannelsFraction", path.c_str()), "Good channels fraction", getNumDE(), 0, getNumDE()); + addDEBinLabels(mHistogramGoodChannelsFractionPerDE.get()); addHisto(mHistogramGoodChannelsFractionPerDE.get(), false, "histo", ""); + mHistogramGoodChannelsFractionPerSolar = std::make_unique(TString::Format("%sGoodChannelsFractionPerSolar", path.c_str()), + "Good channels fraction per SOLAR board", getNumSolar(), 0, getNumSolar()); + addSolarBinLabels(mHistogramGoodChannelsFractionPerSolar.get()); + addHisto(mHistogramGoodChannelsFractionPerSolar.get(), false, "histo", ""); + //-------------------------------------------------- // Rates histograms in global detector coordinates //-------------------------------------------------- @@ -131,6 +145,24 @@ void RatesPlotter::fillAverageHistos(TH2F* hRates) mHistogramGoodChannelsFractionPerDE->SetBinError(de + 1, 1); } } + + for (size_t solar = 0; solar < mHistogramMeanRatePerSolar->GetXaxis()->GetNbins(); solar++) { + mHistogramMeanRatePerSolar->SetBinContent(solar + 1, mElecMapReductor->getSolarValue(solar)); + mHistogramMeanRatePerSolar->SetBinError(solar + 1, 0.1); + } + + for (size_t solar = 0; solar < mHistogramGoodChannelsFractionPerSolar->GetXaxis()->GetNbins(); solar++) { + float nPads = mElecMapReductor->getSolarNumPads(solar); + float nPadsBad = mElecMapReductor->getSolarNumPadsBad(solar) + mElecMapReductor->getSolarNumPadsNoStat(solar); + float nPadsGood = nPads - nPadsBad; + if (nPads > 0) { + mHistogramGoodChannelsFractionPerSolar->SetBinContent(solar + 1, nPadsGood / nPads); + mHistogramGoodChannelsFractionPerSolar->SetBinError(solar + 1, 0.1); + } else { + mHistogramGoodChannelsFractionPerSolar->SetBinContent(solar + 1, 0); + mHistogramGoodChannelsFractionPerSolar->SetBinError(solar + 1, 1); + } + } } //_________________________________________________________________________________________ From 6409144c8c74b348a19bbf00cfd1188847a220c9 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 5 Aug 2025 18:18:08 +0200 Subject: [PATCH 5/8] [MCH] added checkers for SOLAR-based plots The code that checks the SOLAR-based plots is similar to that for the DE-based ones. The checkers also fill a summary plot with the overall quality of each SOLAR link, which are then aggregared by a dedicated task. --- Modules/MUON/MCH/include/MCH/DecodingCheck.h | 27 +- Modules/MUON/MCH/include/MCH/DigitsCheck.h | 45 ++- .../MUON/MCH/include/MCH/PreclustersCheck.h | 24 +- Modules/MUON/MCH/src/DecodingCheck.cxx | 267 ++++++++++++- Modules/MUON/MCH/src/DigitsCheck.cxx | 366 +++++++++++++++++- Modules/MUON/MCH/src/PreclustersCheck.cxx | 266 ++++++++++++- 6 files changed, 937 insertions(+), 58 deletions(-) diff --git a/Modules/MUON/MCH/include/MCH/DecodingCheck.h b/Modules/MUON/MCH/include/MCH/DecodingCheck.h index 21af60144d..98917fe6bd 100644 --- a/Modules/MUON/MCH/include/MCH/DecodingCheck.h +++ b/Modules/MUON/MCH/include/MCH/DecodingCheck.h @@ -47,20 +47,41 @@ class DecodingCheck : public o2::quality_control::checker::CheckInterface std::string getAcceptedType() override; private: - std::string mGoodFracHistName{ "DecodingErrors/LastCycle/GoodBoardsFractionPerDE" }; - std::string mSyncFracHistName{ "SyncErrors/LastCycle/SyncedBoardsFractionPerDE" }; + std::string mGoodFracHistName{ "DecodingErrors/GoodBoardsFractionPerDE" }; + std::string mGoodFracPerSolarHistName{ "DecodingErrors/GoodBoardsFractionPerSolar" }; + std::string mSyncFracHistName{ "SyncErrors/SyncedBoardsFractionPerDE" }; + std::string mSyncFracPerSolarHistName{ "SyncErrors/SyncedBoardsFractionPerSolar" }; + std::string mGoodFracRefCompHistName{ "DecodingErrors/RefComp/GoodBoardsFractionPerDE" }; + std::string mGoodFracPerSolarRefCompHistName{ "DecodingErrors/RefComp/GoodBoardsFractionPerSolar" }; + std::string mSyncFracRefCompHistName{ "SyncErrors/RefComp/SyncedBoardsFractionPerDE" }; + std::string mSyncFracPerSolarRefCompHistName{ "SyncErrors/RefComp/SyncedBoardsFractionPerSolar" }; int mMaxBadST12{ 2 }; int mMaxBadST345{ 3 }; double mMinGoodErrorFrac{ 0.9 }; std::array, 5> mMinGoodErrorFracPerStation; + double mMinGoodErrorFracPerSolar{ 0.5 }; + double mMinGoodErrorFracRatio{ 0.9 }; + double mMinGoodErrorFracRatioPerSolar{ 0.9 }; + double mMinGoodSyncFrac{ 0.9 }; std::array, 5> mMinGoodSyncFracPerStation; + double mMinGoodSyncFracPerSolar{ 0.5 }; + double mMinGoodSyncFracRatio{ 0.9 }; + double mMinGoodSyncFracRatioPerSolar{ 0.9 }; + double mMinHeartBeatRate{ 0 }; double mMaxHeartBeatRate{ 2 }; + double mGoodFracRatioPlotRange{ 0.2 }; + double mGoodFracRatioPerSolarPlotRange{ 0.2 }; + double mSyncFracRatioPlotRange{ 0.2 }; + double mSyncFracRatioPerSolarPlotRange{ 0.2 }; + + QualityChecker mQualityChecker; + std::array mSolarQuality; - ClassDefOverride(DecodingCheck, 1); + ClassDefOverride(DecodingCheck, 2); }; } // namespace o2::quality_control_modules::muonchambers diff --git a/Modules/MUON/MCH/include/MCH/DigitsCheck.h b/Modules/MUON/MCH/include/MCH/DigitsCheck.h index be229c5e4e..4fbad5487b 100644 --- a/Modules/MUON/MCH/include/MCH/DigitsCheck.h +++ b/Modules/MUON/MCH/include/MCH/DigitsCheck.h @@ -50,27 +50,58 @@ class DigitsCheck : public o2::quality_control::checker::CheckInterface std::string getAcceptedType() override; private: - std::array checkMeanRates(TH1F* h); - std::array checkMeanRatesRatio(TH1F* h); - std::array checkBadChannels(TH1F* h); - std::array checkBadChannelsRatio(TH1F* h); + std::array checkMeanRates(TH1* h); + std::array checkBadChannels(TH1* h); + std::array checkMeanRateRatios(TH1* h); + std::array checkBadChannelRatios(TH1* h); + void checkSolarMeanRates(TH1* h); + void checkSolarBadChannels(TH1* h); + void checkSolarMeanRateRatios(TH1* h); + void checkSolarBadChannelRatios(TH1* h); - std::string mMeanRateHistName{ "RatesSignal/LastCycle/MeanRate" }; - std::string mGoodChanFracHistName{ "RatesSignal/LastCycle/GoodChannelsFraction" }; + std::string mMeanRateHistName{ "RatesSignal/MeanRate" }; + std::string mGoodChanFracHistName{ "RatesSignal/GoodChannelsFraction" }; + std::string mMeanRatePerSolarHistName{ "RatesSignal/MeanRatePerSolar" }; + std::string mGoodChanFracPerSolarHistName{ "RatesSignal/GoodChannelsFractionPerSolar" }; + std::string mMeanRateRefCompHistName{ "RatesSignal/RefComp/MeanRate" }; + std::string mGoodChanFracRefCompHistName{ "RatesSignal/RefComp/GoodChannelsFraction" }; + std::string mMeanRatePerSolarRefCompHistName{ "RatesSignal/RefComp/MeanRatePerSolar" }; + std::string mGoodChanFracPerSolarRefCompHistName{ "RatesSignal/RefComp/GoodChannelsFractionPerSolar" }; int mMaxBadST12{ 2 }; int mMaxBadST345{ 3 }; + + // Rate lower threshold double mMinRate{ 0.001 }; std::array, 5> mMinRatePerStation; + double mMinRatePerSolar{ 0.001 }; + // Rate upper threshold double mMaxRate{ 10 }; std::array, 5> mMaxRatePerStation; + double mMaxRatePerSolar{ 10 }; + // Rate ratio threshold + double mMinRateRatio{ 0.9 }; + double mMinRateRatioPerSolar{ 0.9 }; + + // Good channels fraction threshold double mMinGoodFraction{ 0.9 }; std::array, 5> mMinGoodFractionPerStation; + double mMinGoodFractionPerSolar{ 0.5 }; + // Good channels ratio threshold + double mMinGoodFractionRatio{ 0.9 }; + double mMinGoodFractionRatioPerSolar{ 0.9 }; + + // Vertical plot ranges double mRatePlotScaleMin{ 0 }; double mRatePlotScaleMax{ 10 }; + double mRateRatioPlotScaleRange{ 0.2 }; + double mRateRatioPerSolarPlotScaleRange{ 0.2 }; + double mGoodFractionRatioPlotScaleRange{ 0.2 }; + double mGoodFractionRatioPerSolarPlotScaleRange{ 0.2 }; QualityChecker mQualityChecker; + std::array mSolarQuality; - ClassDefOverride(DigitsCheck, 2); + ClassDefOverride(DigitsCheck, 3); }; } // namespace o2::quality_control_modules::muonchambers diff --git a/Modules/MUON/MCH/include/MCH/PreclustersCheck.h b/Modules/MUON/MCH/include/MCH/PreclustersCheck.h index 907c796ed5..401e58e871 100644 --- a/Modules/MUON/MCH/include/MCH/PreclustersCheck.h +++ b/Modules/MUON/MCH/include/MCH/PreclustersCheck.h @@ -48,21 +48,33 @@ class PreclustersCheck : public o2::quality_control::checker::CheckInterface std::string getAcceptedType() override; private: - std::array checkMeanEfficiencies(TH1F* h); - std::array checkMeanEfficienciesRatio(TH1F* h); + std::array checkMeanEfficiencies(TH1* h); + std::array checkMeanEfficiencyRatios(TH1* h); + void checkSolarMeanEfficiencies(TH1* h); + void checkSolarMeanEfficiencyRatios(TH1* h); - std::string mMeanEffHistNameB{ "Efficiency/LastCycle/MeanEfficiencyB" }; - std::string mMeanEffHistNameNB{ "Efficiency/LastCycle/MeanEfficiencyNB" }; + std::string mMeanEffHistNameB{ "Efficiency/MeanEfficiencyB" }; + std::string mMeanEffHistNameNB{ "Efficiency/MeanEfficiencyNB" }; + std::string mMeanEffPerSolarHistName{ "Efficiency/MeanEfficiencyPerSolar" }; + std::string mMeanEffRefCompHistNameB{ "Efficiency/RefComp/MeanEfficiencyB" }; + std::string mMeanEffRefCompHistNameNB{ "Efficiency/RefComp/MeanEfficiencyNB" }; + std::string mMeanEffPerSolarRefCompHistName{ "Efficiency/RefComp/MeanEfficiencyPerSolar" }; int mMaxBadST12{ 2 }; int mMaxBadST345{ 3 }; double mMinEfficiency{ 0.8 }; std::array, 5> mMinEfficiencyPerStation; + double mMinEfficiencyPerSolar{ 0.5 }; + double mMinEfficiencyRatio{ 0.9 }; + double mMinEfficiencyRatioPerSolar{ 0.9 }; double mPseudoeffPlotScaleMin{ 0.0 }; - double mPseudoeffPlotScaleMax{ 1.0 }; + double mPseudoeffPlotScaleMax{ 1.05 }; + double mEfficiencyRatioScaleRange{ 0.2 }; + double mEfficiencyRatioPerSolarScaleRange{ 0.2 }; QualityChecker mQualityChecker; + std::array mSolarQuality; - ClassDefOverride(PreclustersCheck, 2); + ClassDefOverride(PreclustersCheck, 3); }; } // namespace o2::quality_control_modules::muonchambers diff --git a/Modules/MUON/MCH/src/DecodingCheck.cxx b/Modules/MUON/MCH/src/DecodingCheck.cxx index bc66e789b0..0533284267 100644 --- a/Modules/MUON/MCH/src/DecodingCheck.cxx +++ b/Modules/MUON/MCH/src/DecodingCheck.cxx @@ -18,12 +18,15 @@ #include "MCH/DecodingCheck.h" #include "MCH/Helpers.h" #include "MUONCommon/Helpers.h" +#include "QualityControl/ReferenceUtils.h" +#include "QualityControl/QcInfoLogger.h" // ROOT #include #include #include #include +#include #include #include @@ -42,9 +45,15 @@ void DecodingCheck::startOfActivity(const Activity& activity) mGoodFracHistName = getConfigurationParameter(mCustomParameters, "GoodFracHistName", mGoodFracHistName, activity); mSyncFracHistName = getConfigurationParameter(mCustomParameters, "SyncFracHistName", mSyncFracHistName, activity); + mGoodFracPerSolarHistName = getConfigurationParameter(mCustomParameters, "GoodFracPerSolarHistName", mGoodFracPerSolarHistName, activity); + mSyncFracPerSolarHistName = getConfigurationParameter(mCustomParameters, "SyncFracPerSolarHistName", mSyncFracPerSolarHistName, activity); + getThresholdsPerStation(mCustomParameters, activity, "MinGoodErrorFrac", mMinGoodErrorFracPerStation, mMinGoodErrorFrac); getThresholdsPerStation(mCustomParameters, activity, "MinGoodSyncFrac", mMinGoodSyncFracPerStation, mMinGoodSyncFrac); + mMinGoodErrorFracPerSolar = getConfigurationParameter(mCustomParameters, "MinGoodErrorFracPerSolar", mMinGoodErrorFracPerSolar, activity); + mMinGoodSyncFracPerSolar = getConfigurationParameter(mCustomParameters, "MinGoodSyncFracPerSolar", mMinGoodSyncFracPerSolar, activity); + mMaxBadST12 = getConfigurationParameter(mCustomParameters, "MaxBadDE_ST12", mMaxBadST12, activity); mMaxBadST345 = getConfigurationParameter(mCustomParameters, "MaxBadDE_ST345", mMaxBadST345, activity); mQualityChecker.mMaxBadST12 = mMaxBadST12; @@ -63,6 +72,7 @@ Quality DecodingCheck::check(std::mapgetName(), mGoodFracPerSolarHistName)) { + auto* h = dynamic_cast(mo->getObject()); + if (!h) { + return result; + } + + for (int solar = 0; solar < h->GetXaxis()->GetNbins(); solar++) { + int bin = solar + 1; + double value = h->GetBinContent(bin); + if (value >= mMinGoodErrorFracPerSolar) { + continue; + } + mSolarQuality[solar] = Quality::Bad; + } + } + if (matchHistName(mo->getName(), mSyncFracHistName)) { auto* h = dynamic_cast(mo->getObject()); if (!h) { @@ -129,6 +155,22 @@ Quality DecodingCheck::check(std::mapgetName(), mSyncFracPerSolarHistName)) { + auto* h = dynamic_cast(mo->getObject()); + if (!h) { + return result; + } + + for (int solar = 0; solar < h->GetXaxis()->GetNbins(); solar++) { + int bin = solar + 1; + double value = h->GetBinContent(bin); + if (value >= mMinGoodSyncFracPerSolar) { + continue; + } + mSolarQuality[solar] = Quality::Bad; + } + } } return mQualityChecker.getQuality(); } @@ -137,6 +179,93 @@ std::string DecodingCheck::getAcceptedType() { return "TH1"; } void DecodingCheck::beautify(std::shared_ptr mo, Quality checkResult) { + if ((mo->getName().find("RefComp/") != std::string::npos)) { + TCanvas* canvas = dynamic_cast(mo->getObject()); + if (!canvas) { + return; + } + + auto ratioPlot = o2::quality_control::checker::getRatioPlotFromCanvas(canvas); + if (!ratioPlot) { + return; + } + + std::string messages; + auto refCompPlots = o2::quality_control::checker::getPlotsFromCanvas(canvas, messages); + + double ratioPlotRange{ -1 }; + double ratioThreshold{ -1 }; + bool isSolar{ false }; + + if (matchHistName(mo->getName(), mGoodFracRefCompHistName)) { + ratioPlotRange = mGoodFracRatioPlotRange; + ratioThreshold = mMinGoodErrorFracRatio; + isSolar = false; + } else if (matchHistName(mo->getName(), mGoodFracPerSolarRefCompHistName)) { + ratioPlotRange = mGoodFracRatioPerSolarPlotRange; + ratioThreshold = mMinGoodErrorFracRatioPerSolar; + isSolar = true; + } else if (matchHistName(mo->getName(), mSyncFracRefCompHistName)) { + ratioPlotRange = mSyncFracRatioPlotRange; + ratioThreshold = mMinGoodSyncFracRatio; + isSolar = false; + } else if (matchHistName(mo->getName(), mSyncFracPerSolarRefCompHistName)) { + ratioPlotRange = mSyncFracRatioPerSolarPlotRange; + ratioThreshold = mMinGoodSyncFracRatioPerSolar; + isSolar = true; + } + + if (ratioPlotRange < 0) { + return; + } + + ratioPlot->SetMinimum(1.0 - ratioPlotRange); + ratioPlot->SetMaximum(1.0 + ratioPlotRange); + ratioPlot->GetXaxis()->SetTickLength(0); + + if (isSolar) { + addChamberDelimitersToSolarHistogram(ratioPlot); + addSolarBinLabels(ratioPlot); + } else { + addChamberDelimiters(ratioPlot); + addDEBinLabels(ratioPlot); + } + drawThreshold(ratioPlot, ratioThreshold); + + if (refCompPlots.first) { + refCompPlots.first->SetMinimum(0); + refCompPlots.first->SetMaximum(1.05); + if (isSolar) { + addChamberDelimitersToSolarHistogram(refCompPlots.first); + addChamberLabelsForSolar(refCompPlots.first); + addSolarBinLabels(refCompPlots.first); + if (refCompPlots.second) { + addSolarBinLabels(refCompPlots.second); + } + } else { + addChamberDelimiters(refCompPlots.first); + addChamberLabelsForDE(refCompPlots.first); + addDEBinLabels(refCompPlots.first); + if (refCompPlots.second) { + addDEBinLabels(refCompPlots.second); + } + } + } + + if (refCompPlots.second) { + if (checkResult == Quality::Good) { + refCompPlots.second->SetLineColor(kGreen + 2); + } else if (checkResult == Quality::Bad) { + refCompPlots.second->SetLineColor(kRed); + } else if (checkResult == Quality::Medium) { + refCompPlots.second->SetLineColor(kOrange - 3); + } else if (checkResult == Quality::Null) { + refCompPlots.second->SetLineColor(kViolet - 6); + } + } + return; + } + if (mo->getName().find("DecodingErrorsPerDE") != std::string::npos) { auto* h = dynamic_cast(mo->getObject()); if (!h) { @@ -196,7 +325,7 @@ void DecodingCheck::beautify(std::shared_ptr mo, Quality checkRes h->GetYaxis()->SetTitle("good boards fraction"); addChamberDelimiters(h, scaleMin, scaleMax); - addDEBinLabels(h); + addChamberLabelsForDE(h); // only the plot used for the check is beautified by changing the color // and adding the horizontal lines corresponding to the thresholds @@ -214,6 +343,37 @@ void DecodingCheck::beautify(std::shared_ptr mo, Quality checkRes } } + if (mo->getName().find("GoodBoardsFractionPerSolar") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + if (!h) { + return; + } + + float scaleMin{ 0 }; + float scaleMax{ 1.05 }; + h->SetMinimum(scaleMin); + h->SetMaximum(scaleMax); + h->GetYaxis()->SetTitle("good boards fraction"); + + addChamberDelimitersToSolarHistogram(h, scaleMin, scaleMax); + addChamberLabelsForSolar(h); + + // only the plot used for the check is beautified by changing the color + // and adding the horizontal lines corresponding to the thresholds + if (matchHistName(mo->getName(), mGoodFracPerSolarHistName)) { + if (checkResult == Quality::Good) { + h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + drawThreshold(h, mMinGoodErrorFracPerSolar); + } + } + if (mo->getName().find("SyncedBoardsFractionPerDE") != std::string::npos) { auto* h = dynamic_cast(mo->getObject()); if (!h) { @@ -226,7 +386,7 @@ void DecodingCheck::beautify(std::shared_ptr mo, Quality checkRes h->SetMaximum(scaleMax); addChamberDelimiters(h, scaleMin, scaleMax); - addDEBinLabels(h); + addChamberLabelsForDE(h); // only the plot used for the check is beautified by changing the color // and adding the horizontal lines corresponding to the thresholds @@ -244,6 +404,46 @@ void DecodingCheck::beautify(std::shared_ptr mo, Quality checkRes } } + if (mo->getName().find("SyncedBoardsFractionPerSolar") != std::string::npos) { + auto* h = dynamic_cast(mo->getObject()); + if (!h) { + return; + } + + float scaleMin{ 0 }; + float scaleMax{ 1.05 }; + h->SetMinimum(scaleMin); + h->SetMaximum(scaleMax); + + addChamberDelimitersToSolarHistogram(h, scaleMin, scaleMax); + addChamberLabelsForSolar(h); + + // only the plot used for the check is beautified by changing the color + // and adding the horizontal lines corresponding to the thresholds + if (matchHistName(mo->getName(), mSyncFracPerSolarHistName)) { + if (checkResult == Quality::Good) { + h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + drawThreshold(h, mMinGoodSyncFracPerSolar); + } + } + + // Normalize the heartBeat rate plots + if (mo->getName().find("HBRate_ST") != std::string::npos) { + TH2F* h = dynamic_cast(mo->getObject()); + if (!h) { + return; + } + h->SetMinimum(mMinHeartBeatRate); + h->SetMaximum(mMaxHeartBeatRate); + } + // update quality flags for each DE if (mo->getName().find("QualityFlagPerDE") != std::string::npos) { TH2F* h = dynamic_cast(mo->getObject()); @@ -251,30 +451,75 @@ void DecodingCheck::beautify(std::shared_ptr mo, Quality checkRes return; } - for (int deId = 0; deId < mQualityChecker.mQuality.size(); deId++) { + std::string badDEs; + for (int deIndex = 0; deIndex < mQualityChecker.mQuality.size(); deIndex++) { float ybin = 0; - if (mQualityChecker.mQuality[deId] == Quality::Good) { + if (mQualityChecker.mQuality[deIndex] == Quality::Good) { ybin = 3; } - if (mQualityChecker.mQuality[deId] == Quality::Medium) { + if (mQualityChecker.mQuality[deIndex] == Quality::Medium) { ybin = 2; } - if (mQualityChecker.mQuality[deId] == Quality::Bad) { + if (mQualityChecker.mQuality[deIndex] == Quality::Bad) { ybin = 1; + std::string deIdStr = std::to_string(getDEFromIndex(deIndex)); + if (badDEs.empty()) { + badDEs = deIdStr; + } else { + badDEs += std::string(" ") + deIdStr; + } } - h->SetBinContent(deId + 1, ybin, 1); + h->SetBinContent(deIndex + 1, ybin, 1); + + if (!badDEs.empty()) { + std::string text = std::string("Bad DEs: ") + badDEs; + TPaveLabel* label = new TPaveLabel(0.2, 0.8, 0.8, 0.88, text.c_str(), "blNDC"); + label->SetBorderSize(1); + h->GetListOfFunctions()->Add(label); + + ILOG(Warning, Support) << "[DecodingCheck] " << text << ENDM; + } } } - // Normalize the heartBeat rate plots - if (mo->getName().find("HBRate_ST") != std::string::npos) { + // update quality flags for each SOLAR + if (mo->getName().find("QualityFlagPerSolar") != std::string::npos) { TH2F* h = dynamic_cast(mo->getObject()); if (!h) { return; } - h->SetMinimum(mMinHeartBeatRate); - h->SetMaximum(mMaxHeartBeatRate); + + std::string badSolarBoards; + for (int solar = 0; solar < mSolarQuality.size(); solar++) { + float ybin = 0; + if (mSolarQuality[solar] == Quality::Good) { + ybin = 3; + } + if (mSolarQuality[solar] == Quality::Medium) { + ybin = 2; + } + if (mSolarQuality[solar] == Quality::Bad) { + ybin = 1; + std::string solarId = std::to_string(getSolarIdFromIndex(solar)); + if (badSolarBoards.empty()) { + badSolarBoards = solarId; + } else { + badSolarBoards += std::string(" ") + solarId; + } + } + + h->SetBinContent(solar + 1, ybin, 1); + } + + if (!badSolarBoards.empty()) { + std::string badSolarList = std::string("Bad SOLAR boards: ") + badSolarBoards; + TPaveLabel* label = new TPaveLabel(0.2, 0.8, 0.8, 0.88, badSolarList.c_str(), "blNDC"); + label->SetBorderSize(1); + h->GetListOfFunctions()->Add(label); + + ILOG(Warning, Support) << "[DecodingCheck] " << badSolarList << ENDM; + } } } diff --git a/Modules/MUON/MCH/src/DigitsCheck.cxx b/Modules/MUON/MCH/src/DigitsCheck.cxx index 4ee43ffb5a..e1a0f3b646 100644 --- a/Modules/MUON/MCH/src/DigitsCheck.cxx +++ b/Modules/MUON/MCH/src/DigitsCheck.cxx @@ -16,6 +16,7 @@ #include "MCH/DigitsCheck.h" #include "MUONCommon/Helpers.h" +#include "QualityControl/ReferenceUtils.h" #include "QualityControl/MonitorObject.h" #include "QualityControl/QcInfoLogger.h" @@ -25,6 +26,7 @@ #include #include #include +#include #include #include @@ -40,25 +42,50 @@ void DigitsCheck::configure() void DigitsCheck::startOfActivity(const Activity& activity) { + // input histogram names customization mMeanRateHistName = getConfigurationParameter(mCustomParameters, "MeanRateHistName", mMeanRateHistName, activity); mGoodChanFracHistName = getConfigurationParameter(mCustomParameters, "GoodChanFracHistName", mGoodChanFracHistName, activity); + mMeanRatePerSolarHistName = getConfigurationParameter(mCustomParameters, "MeanRatePerSolarHistName", mMeanRatePerSolarHistName, activity); + mGoodChanFracPerSolarHistName = getConfigurationParameter(mCustomParameters, "GoodChanFracPerSolarHistName", mGoodChanFracPerSolarHistName, activity); + + mMeanRateRefCompHistName = getConfigurationParameter(mCustomParameters, "MeanRateRefCompHistName", mMeanRateRefCompHistName, activity); + mGoodChanFracRefCompHistName = getConfigurationParameter(mCustomParameters, "GoodChanFracRefCompHistName", mGoodChanFracRefCompHistName, activity); + + mMeanRatePerSolarRefCompHistName = getConfigurationParameter(mCustomParameters, "MeanRatePerSolarRefCompHistName", mMeanRatePerSolarRefCompHistName, activity); + mGoodChanFracPerSolarRefCompHistName = getConfigurationParameter(mCustomParameters, "GoodChanFracPerSolarRefCompHistName", mGoodChanFracPerSolarRefCompHistName, activity); + + // threshold customization getThresholdsPerStation(mCustomParameters, activity, "MinRate", mMinRatePerStation, mMinRate); getThresholdsPerStation(mCustomParameters, activity, "MaxRate", mMaxRatePerStation, mMaxRate); + mMinRateRatio = getConfigurationParameter(mCustomParameters, "MinRateRatio", mMinRateRatio, activity); + + mMinRatePerSolar = getConfigurationParameter(mCustomParameters, "MinRatePerSolar", mMinRatePerSolar, activity); + mMaxRatePerSolar = getConfigurationParameter(mCustomParameters, "MaxRatePerSolar", mMaxRatePerSolar, activity); + mMinRateRatioPerSolar = getConfigurationParameter(mCustomParameters, "MinRateRatioPerSolar", mMinRateRatioPerSolar, activity); + getThresholdsPerStation(mCustomParameters, activity, "MinGoodFraction", mMinGoodFractionPerStation, mMinGoodFraction); + mMinGoodFractionRatio = getConfigurationParameter(mCustomParameters, "MinGoodFractionRatio", mMinGoodFractionRatio, activity); + + mMinGoodFractionPerSolar = getConfigurationParameter(mCustomParameters, "MinGoodFractionPerSolar", mMinGoodFractionPerSolar, activity); + mMinGoodFractionRatioPerSolar = getConfigurationParameter(mCustomParameters, "MinGoodFractionRatioPerSolar", mMinGoodFractionRatioPerSolar, activity); mMaxBadST12 = getConfigurationParameter(mCustomParameters, "MaxBadDE_ST12", mMaxBadST12, activity); mMaxBadST345 = getConfigurationParameter(mCustomParameters, "MaxBadDE_ST345", mMaxBadST345, activity); mRatePlotScaleMin = getConfigurationParameter(mCustomParameters, "RatePlotScaleMin", mRatePlotScaleMin, activity); mRatePlotScaleMax = getConfigurationParameter(mCustomParameters, "RatePlotScaleMax", mRatePlotScaleMax, activity); + mRateRatioPlotScaleRange = getConfigurationParameter(mCustomParameters, "RateRatioPlotScaleRange", mRateRatioPlotScaleRange, activity); + mRateRatioPerSolarPlotScaleRange = getConfigurationParameter(mCustomParameters, "RateRatioPerSolarPlotScaleRange", mRateRatioPerSolarPlotScaleRange, activity); + mGoodFractionRatioPlotScaleRange = getConfigurationParameter(mCustomParameters, "GoodFractionRatioPlotScaleRange", mGoodFractionRatioPlotScaleRange, activity); + mGoodFractionRatioPerSolarPlotScaleRange = getConfigurationParameter(mCustomParameters, "GoodFractionRatioPerSolarPlotScaleRange", mGoodFractionRatioPerSolarPlotScaleRange, activity); mQualityChecker.mMaxBadST12 = mMaxBadST12; mQualityChecker.mMaxBadST345 = mMaxBadST345; } template -std::array checkPlot(TH1F* h, Lambda check) +std::array checkPlot(TH1* h, Lambda check) { std::array result; std::fill(result.begin(), result.end(), Quality::Null); @@ -84,7 +111,7 @@ std::array checkPlot(TH1F* h, Lambda check) return result; } -std::array DigitsCheck::checkMeanRates(TH1F* h) +std::array DigitsCheck::checkMeanRates(TH1* h) { auto checkFunction = [&](double val, int station) -> bool { auto minRate = mMinRate; @@ -102,7 +129,16 @@ std::array DigitsCheck::checkMeanRates(TH1F* h) return checkPlot(h, checkFunction); } -std::array DigitsCheck::checkBadChannels(TH1F* h) +std::array DigitsCheck::checkMeanRateRatios(TH1* h) +{ + auto checkFunction = [&](double val, int /*station*/) -> bool { + auto minRateRatio = mMinRateRatio; + return (val >= minRateRatio); + }; + return checkPlot(h, checkFunction); +} + +std::array DigitsCheck::checkBadChannels(TH1* h) { auto checkFunction = [&](double val, int station) -> bool { auto minGoodFraction = mMinGoodFraction; @@ -116,6 +152,63 @@ std::array DigitsCheck::checkBadChannels(TH1F* h) return checkPlot(h, checkFunction); } +std::array DigitsCheck::checkBadChannelRatios(TH1* h) +{ + auto checkFunction = [&](double val, int /*station*/) -> bool { + auto minGoodFractionRatio = mMinGoodFractionRatio; + return (val >= minGoodFractionRatio); + }; + return checkPlot(h, checkFunction); +} + +void DigitsCheck::checkSolarMeanRates(TH1* h) +{ + for (int solar = 0; solar < h->GetXaxis()->GetNbins(); solar++) { + int bin = solar + 1; + double value = h->GetBinContent(bin); + if (value >= mMinRatePerSolar && value <= mMaxRatePerSolar) { + continue; + } + mSolarQuality[solar] = Quality::Bad; + } +} + +void DigitsCheck::checkSolarMeanRateRatios(TH1* h) +{ + for (int solar = 0; solar < h->GetXaxis()->GetNbins(); solar++) { + int bin = solar + 1; + double value = h->GetBinContent(bin); + if (value >= mMinRateRatioPerSolar) { + continue; + } + mSolarQuality[solar] = Quality::Bad; + } +} + +void DigitsCheck::checkSolarBadChannels(TH1* h) +{ + for (int solar = 0; solar < h->GetXaxis()->GetNbins(); solar++) { + int bin = solar + 1; + double value = h->GetBinContent(bin); + if (value >= mMinGoodFractionPerSolar) { + continue; + } + mSolarQuality[solar] = Quality::Bad; + } +} + +void DigitsCheck::checkSolarBadChannelRatios(TH1* h) +{ + for (int solar = 0; solar < h->GetXaxis()->GetNbins(); solar++) { + int bin = solar + 1; + double value = h->GetBinContent(bin); + if (value >= mMinGoodFractionRatioPerSolar) { + continue; + } + mSolarQuality[solar] = Quality::Bad; + } +} + template static T* getHisto(TCanvas* c, std::string hname) { @@ -151,9 +244,11 @@ static T* getHisto(std::shared_ptr mo) Quality DigitsCheck::check(std::map>* moMap) { mQualityChecker.reset(); + std::fill(mSolarQuality.begin(), mSolarQuality.end(), Quality::Good); for (auto& [moName, mo] : *moMap) { + // DE histograms if (matchHistName(mo->getName(), mMeanRateHistName)) { TH1F* h = getHisto(mo); if (h) { @@ -161,7 +256,6 @@ Quality DigitsCheck::check(std::map> mQualityChecker.addCheckResult(q); } } - if (matchHistName(mo->getName(), mGoodChanFracHistName)) { TH1F* h = getHisto(mo); if (h) { @@ -169,6 +263,60 @@ Quality DigitsCheck::check(std::map> mQualityChecker.addCheckResult(q); } } + // comparisons with reference + if (matchHistName(mo->getName(), mMeanRateRefCompHistName)) { + TCanvas* canvas = dynamic_cast(mo->getObject()); + if (canvas) { + auto ratioPlot = o2::quality_control::checker::getRatioPlotFromCanvas(canvas); + if (ratioPlot) { + auto q = checkMeanRateRatios(ratioPlot); + mQualityChecker.addCheckResult(q); + } + } + } + if (matchHistName(mo->getName(), mGoodChanFracRefCompHistName)) { + TCanvas* canvas = dynamic_cast(mo->getObject()); + if (canvas) { + auto ratioPlot = o2::quality_control::checker::getRatioPlotFromCanvas(canvas); + if (ratioPlot) { + auto q = checkBadChannelRatios(ratioPlot); + mQualityChecker.addCheckResult(q); + } + } + } + + // SOLAR histograms + if (matchHistName(mo->getName(), mMeanRatePerSolarHistName)) { + TH1F* h = getHisto(mo); + if (h) { + checkSolarMeanRates(h); + } + } + if (matchHistName(mo->getName(), mGoodChanFracPerSolarHistName)) { + TH1F* h = getHisto(mo); + if (h) { + checkSolarBadChannels(h); + } + } + // comparisons with reference + if (matchHistName(mo->getName(), mMeanRatePerSolarRefCompHistName)) { + TCanvas* canvas = dynamic_cast(mo->getObject()); + if (canvas) { + auto ratioPlot = o2::quality_control::checker::getRatioPlotFromCanvas(canvas); + if (ratioPlot) { + checkSolarMeanRateRatios(ratioPlot); + } + } + } + if (matchHistName(mo->getName(), mGoodChanFracPerSolarRefCompHistName)) { + TCanvas* canvas = dynamic_cast(mo->getObject()); + if (canvas) { + auto ratioPlot = o2::quality_control::checker::getRatioPlotFromCanvas(canvas); + if (ratioPlot) { + checkSolarBadChannelRatios(ratioPlot); + } + } + } } return mQualityChecker.getQuality(); @@ -189,6 +337,103 @@ static void updateTitle(TH1* hist, std::string suffix) void DigitsCheck::beautify(std::shared_ptr mo, Quality checkResult) { + if ((mo->getName().find("RefComp/") != std::string::npos)) { + TCanvas* canvas = dynamic_cast(mo->getObject()); + if (!canvas) { + return; + } + + auto ratioPlot = o2::quality_control::checker::getRatioPlotFromCanvas(canvas); + if (!ratioPlot) { + return; + } + + std::string messages; + auto refCompPlots = o2::quality_control::checker::getPlotsFromCanvas(canvas, messages); + + double ratioPlotRange{ -1 }; + double ratioThreshold{ -1 }; + double plotScaleMin{ -1 }; + double plotScaleMax{ -1 }; + bool isSolar{ false }; + + if (matchHistName(mo->getName(), mMeanRateRefCompHistName)) { + ratioPlotRange = mRateRatioPlotScaleRange; + ratioThreshold = mMinRateRatio; + plotScaleMin = mRatePlotScaleMin; + plotScaleMax = mRatePlotScaleMax; + isSolar = false; + } else if (matchHistName(mo->getName(), mMeanRatePerSolarRefCompHistName)) { + ratioPlotRange = mRateRatioPerSolarPlotScaleRange; + ratioThreshold = mMinRateRatioPerSolar; + plotScaleMin = mRatePlotScaleMin; + plotScaleMax = mRatePlotScaleMax; + isSolar = true; + } else if (matchHistName(mo->getName(), mGoodChanFracRefCompHistName)) { + ratioPlotRange = mGoodFractionRatioPlotScaleRange; + ratioThreshold = mMinGoodFractionRatio; + plotScaleMin = 0; + plotScaleMax = 1.05; + isSolar = false; + } else if (matchHistName(mo->getName(), mGoodChanFracPerSolarRefCompHistName)) { + ratioPlotRange = mGoodFractionRatioPerSolarPlotScaleRange; + ratioThreshold = mMinGoodFractionRatioPerSolar; + plotScaleMin = 0; + plotScaleMax = 1.05; + isSolar = true; + } + + if (ratioPlotRange < 0) { + return; + } + + ratioPlot->SetMinimum(1.0 - ratioPlotRange); + ratioPlot->SetMaximum(1.0 + ratioPlotRange); + ratioPlot->GetXaxis()->SetTickLength(0); + + if (isSolar) { + addChamberDelimitersToSolarHistogram(ratioPlot); + addSolarBinLabels(ratioPlot); + } else { + addChamberDelimiters(ratioPlot); + addDEBinLabels(ratioPlot); + } + drawThreshold(ratioPlot, ratioThreshold); + + if (refCompPlots.first) { + refCompPlots.first->SetMinimum(plotScaleMin); + refCompPlots.first->SetMaximum(plotScaleMax); + if (isSolar) { + addChamberDelimitersToSolarHistogram(refCompPlots.first); + addChamberLabelsForSolar(refCompPlots.first); + addSolarBinLabels(refCompPlots.first); + if (refCompPlots.second) { + addSolarBinLabels(refCompPlots.second); + } + } else { + addChamberDelimiters(refCompPlots.first); + addChamberLabelsForDE(refCompPlots.first); + addDEBinLabels(refCompPlots.first); + if (refCompPlots.second) { + addDEBinLabels(refCompPlots.second); + } + } + } + + if (refCompPlots.second) { + if (checkResult == Quality::Good) { + refCompPlots.second->SetLineColor(kGreen + 2); + } else if (checkResult == Quality::Bad) { + refCompPlots.second->SetLineColor(kRed); + } else if (checkResult == Quality::Medium) { + refCompPlots.second->SetLineColor(kOrange - 3); + } else if (checkResult == Quality::Null) { + refCompPlots.second->SetLineColor(kViolet - 6); + } + } + return; + } + if (mo->getName().find("Occupancy_Elec") != std::string::npos || mo->getName().find("OccupancySignal_Elec") != std::string::npos) { auto* h = dynamic_cast(mo->getObject()); @@ -232,8 +477,13 @@ void DigitsCheck::beautify(std::shared_ptr mo, Quality checkResul h->SetMaximum(scaleMax); h->GetYaxis()->SetTitle("rate (kHz)"); - addChamberDelimiters(h, scaleMin, scaleMax); - addDEBinLabels(h); + if (mo->getName().find("MeanRatePerSolar") != std::string::npos) { + addChamberDelimitersToSolarHistogram(h, scaleMin, scaleMax); + addChamberLabelsForSolar(h); + } else { + addChamberDelimiters(h, scaleMin, scaleMax); + addChamberLabelsForDE(h); + } // only the plot used for the check is beautified by changing the color // and adding the horizontal lines corresponding to the thresholds @@ -250,6 +500,21 @@ void DigitsCheck::beautify(std::shared_ptr mo, Quality checkResul drawThresholdsPerStation(h, mMinRatePerStation, mMinRate); drawThresholdsPerStation(h, mMaxRatePerStation, mMaxRate); } + + // also beautify the SOLAR plot + if (matchHistName(mo->getName(), mMeanRatePerSolarHistName)) { + if (checkResult == Quality::Good) { + h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + drawThreshold(h, mMinRatePerSolar); + drawThreshold(h, mMaxRatePerSolar); + } } if (mo->getName().find("GoodChannelsFraction") != std::string::npos) { @@ -264,8 +529,13 @@ void DigitsCheck::beautify(std::shared_ptr mo, Quality checkResul h->SetMaximum(scaleMax); h->GetYaxis()->SetTitle("fraction"); - addChamberDelimiters(h, scaleMin, scaleMax); - addDEBinLabels(h); + if (mo->getName().find("GoodChannelsFractionPerSolar") != std::string::npos) { + addChamberDelimitersToSolarHistogram(h, scaleMin, scaleMax); + addChamberLabelsForSolar(h); + } else { + addChamberDelimiters(h, scaleMin, scaleMax); + addChamberLabelsForDE(h); + } // only the plot used for the check is beautified by changing the color // and adding the horizontal lines corresponding to the thresholds @@ -281,6 +551,20 @@ void DigitsCheck::beautify(std::shared_ptr mo, Quality checkResul drawThresholdsPerStation(h, mMinGoodFractionPerStation, mMinGoodFraction); } + + // also beautify the SOLAR plot + if (matchHistName(mo->getName(), mGoodChanFracPerSolarHistName)) { + if (checkResult == Quality::Good) { + h->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + h->SetFillColor(kRed); + } else if (checkResult == Quality::Medium) { + h->SetFillColor(kOrange); + } + h->SetLineColor(kBlack); + + drawThreshold(h, mMinGoodFractionPerSolar); + } } // update quality flags for each DE @@ -290,22 +574,74 @@ void DigitsCheck::beautify(std::shared_ptr mo, Quality checkResul return; } - addChamberDelimiters(h); - addDEBinLabels(h); + std::string badDEs; + for (int deIndex = 0; deIndex < mQualityChecker.mQuality.size(); deIndex++) { + float ybin = 0; + if (mQualityChecker.mQuality[deIndex] == Quality::Good) { + ybin = 3; + } + if (mQualityChecker.mQuality[deIndex] == Quality::Medium) { + ybin = 2; + } + if (mQualityChecker.mQuality[deIndex] == Quality::Bad) { + ybin = 1; + std::string deIdStr = std::to_string(getDEFromIndex(deIndex)); + if (badDEs.empty()) { + badDEs = deIdStr; + } else { + badDEs += std::string(" ") + deIdStr; + } + } + + h->SetBinContent(deIndex + 1, ybin, 1); + } + + if (!badDEs.empty()) { + std::string text = std::string("Bad DEs: ") + badDEs; + TPaveLabel* label = new TPaveLabel(0.2, 0.8, 0.8, 0.88, text.c_str(), "blNDC"); + label->SetBorderSize(1); + h->GetListOfFunctions()->Add(label); + + ILOG(Warning, Support) << "[DecodingCheck] " << text << ENDM; + } + } + + // update quality flags for each SOLAR + if (mo->getName().find("QualityFlagPerSolar") != std::string::npos) { + TH2F* h = getHisto(mo); + if (!h) { + return; + } - for (int deId = 0; deId < mQualityChecker.mQuality.size(); deId++) { + std::string badSolarBoards; + for (int solar = 0; solar < mSolarQuality.size(); solar++) { float ybin = 0; - if (mQualityChecker.mQuality[deId] == Quality::Good) { + if (mSolarQuality[solar] == Quality::Good) { ybin = 3; } - if (mQualityChecker.mQuality[deId] == Quality::Medium) { + if (mSolarQuality[solar] == Quality::Medium) { ybin = 2; } - if (mQualityChecker.mQuality[deId] == Quality::Bad) { + if (mSolarQuality[solar] == Quality::Bad) { ybin = 1; + std::string solarId = std::to_string(getSolarIdFromIndex(solar)); + if (badSolarBoards.empty()) { + badSolarBoards = solarId; + } else { + badSolarBoards += std::string(" ") + solarId; + } } - h->SetBinContent(deId + 1, ybin, 1); + h->SetBinContent(solar + 1, ybin, 1); + } + + if (!badSolarBoards.empty()) { + std::string badSolarList = std::string("Bad SOLAR boards: ") + badSolarBoards; + TPaveLabel* label = new TPaveLabel(0.2, 0.8, 0.8, 0.88, badSolarList.c_str(), "blNDC"); + label->SetBorderSize(1); + h->GetListOfFunctions()->Add(label); + + ILOG(Warning, Support) << "[DigitsCheck] " << badSolarList << ENDM; } } } diff --git a/Modules/MUON/MCH/src/PreclustersCheck.cxx b/Modules/MUON/MCH/src/PreclustersCheck.cxx index 29a5c259c7..74e022f8d6 100644 --- a/Modules/MUON/MCH/src/PreclustersCheck.cxx +++ b/Modules/MUON/MCH/src/PreclustersCheck.cxx @@ -16,6 +16,7 @@ #include "MCH/PreclustersCheck.h" #include "MCH/Helpers.h" #include "MUONCommon/Helpers.h" +#include "QualityControl/ReferenceUtils.h" #include "QualityControl/QcInfoLogger.h" #include "QualityControl/MonitorObject.h" @@ -25,6 +26,7 @@ #include #include #include +#include #include #include @@ -40,13 +42,25 @@ void PreclustersCheck::configure() void PreclustersCheck::startOfActivity(const Activity& activity) { + mMeanEffHistNameB = getConfigurationParameter(mCustomParameters, "MeanEffHistNameB", mMeanEffHistNameB, activity); + mMeanEffHistNameNB = getConfigurationParameter(mCustomParameters, "MeanEffHistNameNB", mMeanEffHistNameNB, activity); + mMeanEffPerSolarHistName = getConfigurationParameter(mCustomParameters, "MeanEffPerSolarHistName", mMeanEffPerSolarHistName, activity); + + mMeanEffRefCompHistNameB = getConfigurationParameter(mCustomParameters, "MeanEffRefCompHistNameB", mMeanEffRefCompHistNameB, activity); + mMeanEffRefCompHistNameNB = getConfigurationParameter(mCustomParameters, "MeanEffRefCompHistNameNB", mMeanEffRefCompHistNameNB, activity); + mMeanEffPerSolarRefCompHistName = getConfigurationParameter(mCustomParameters, "MeanEffPerSolarRefCompHistName", mMeanEffPerSolarRefCompHistName, activity); + getThresholdsPerStation(mCustomParameters, activity, "MinEfficiency", mMinEfficiencyPerStation, mMinEfficiency); + mMinEfficiencyPerSolar = getConfigurationParameter(mCustomParameters, "MinEfficiencyPerSolar", mMinEfficiencyPerSolar, activity); + + mMinEfficiencyRatio = getConfigurationParameter(mCustomParameters, "MinEfficiencyRatio", mMinEfficiencyRatio, activity); + mMinEfficiencyRatioPerSolar = getConfigurationParameter(mCustomParameters, "MinEfficiencyRatioPerSolar", mMinEfficiencyRatioPerSolar, activity); mPseudoeffPlotScaleMin = getConfigurationParameter(mCustomParameters, "PseudoeffPlotScaleMin", mPseudoeffPlotScaleMin, activity); mPseudoeffPlotScaleMax = getConfigurationParameter(mCustomParameters, "PseudoeffPlotScaleMax", mPseudoeffPlotScaleMax, activity); - mMeanEffHistNameB = getConfigurationParameter(mCustomParameters, "MeanEffHistNameB", mMeanEffHistNameB, activity); - mMeanEffHistNameNB = getConfigurationParameter(mCustomParameters, "MeanEffHistNameNB", mMeanEffHistNameNB, activity); + mEfficiencyRatioScaleRange = getConfigurationParameter(mCustomParameters, "EfficiencyRatioScaleRange", mEfficiencyRatioScaleRange, activity); + mEfficiencyRatioPerSolarScaleRange = getConfigurationParameter(mCustomParameters, "EfficiencyRatioPerSolarScaleRange", mEfficiencyRatioPerSolarScaleRange, activity); mMaxBadST12 = getConfigurationParameter(mCustomParameters, "MaxBadDE_ST12", mMaxBadST12, activity); mMaxBadST345 = getConfigurationParameter(mCustomParameters, "MaxBadDE_ST345", mMaxBadST345, activity); @@ -88,11 +102,15 @@ static T* getHisto(std::shared_ptr mo) } template -std::array checkPlot(TH1F* h, Lambda check) +std::array checkPlot(TH1* h, Lambda check) { std::array result; std::fill(result.begin(), result.end(), Quality::Null); + if (h->GetEntries() == 0) { + return result; + } + for (auto de : o2::mch::constants::deIdsForAllMCH) { int chamberId = (de - 100) / 100; int stationId = chamberId / 2; @@ -114,7 +132,7 @@ std::array checkPlot(TH1F* h, Lambda check) return result; } -std::array PreclustersCheck::checkMeanEfficiencies(TH1F* h) +std::array PreclustersCheck::checkMeanEfficiencies(TH1* h) { auto checkFunction = [&](double val, int station) -> bool { auto minEfficiency = mMinEfficiency; @@ -128,25 +146,89 @@ std::array PreclustersCheck::checkMeanEfficiencies(TH1F* h) return checkPlot(h, checkFunction); } +std::array PreclustersCheck::checkMeanEfficiencyRatios(TH1* h) +{ + auto checkFunction = [&](double val, int /*station*/) -> bool { + auto minEfficiency = mMinEfficiencyRatio; + return (val >= minEfficiency); + }; + return checkPlot(h, checkFunction); +} + +void PreclustersCheck::checkSolarMeanEfficiencies(TH1* h) +{ + for (int solar = 0; solar < h->GetXaxis()->GetNbins(); solar++) { + int bin = solar + 1; + double value = h->GetBinContent(bin); + if (value >= mMinEfficiencyPerSolar) { + continue; + } + mSolarQuality[solar] = Quality::Bad; + } +} + +void PreclustersCheck::checkSolarMeanEfficiencyRatios(TH1* h) +{ + for (int solar = 0; solar < h->GetXaxis()->GetNbins(); solar++) { + int bin = solar + 1; + double value = h->GetBinContent(bin); + if (value >= mMinEfficiencyRatio) { + continue; + } + mSolarQuality[solar] = Quality::Bad; + } +} + Quality PreclustersCheck::check(std::map>* moMap) { ILOG(Debug, Devel) << "Entered PreclustersCheck::check" << ENDM; ILOG(Debug, Devel) << " received a list of size : " << moMap->size() << ENDM; - for (const auto& item : *moMap) { - ILOG(Debug, Devel) << "Object: " << item.second->getName() << ENDM; + for (auto& [moName, mo] : *moMap) { + ILOG(Debug, Devel) << "Object: " << moName << " | " << mo->getName() << ENDM; } mQualityChecker.reset(); + std::fill(mSolarQuality.begin(), mSolarQuality.end(), Quality::Good); for (auto& [moName, mo] : *moMap) { - if (matchHistName(mo->getName(), mMeanEffHistNameB) || matchHistName(mo->getName(), mMeanEffHistNameNB)) { + if (matchHistName(moName, mMeanEffHistNameB) || matchHistName(moName, mMeanEffHistNameNB)) { TH1F* h = getHisto(mo); if (h) { auto q = checkMeanEfficiencies(h); mQualityChecker.addCheckResult(q); } } + + if (matchHistName(moName, mMeanEffPerSolarHistName)) { + TH1F* h = getHisto(mo); + if (h) { + checkSolarMeanEfficiencies(h); + } + } + + // Ratios with reference + if (matchHistName(moName, mMeanEffRefCompHistNameB) || matchHistName(moName, mMeanEffRefCompHistNameNB)) { + TCanvas* canvas = dynamic_cast(mo->getObject()); + if (canvas) { + auto ratioPlot = o2::quality_control::checker::getRatioPlotFromCanvas(canvas); + if (ratioPlot) { + auto q = checkMeanEfficiencyRatios(ratioPlot); + mQualityChecker.addCheckResult(q); + } + } + } + + if (matchHistName(moName, mMeanEffPerSolarRefCompHistName)) { + TCanvas* canvas = dynamic_cast(mo->getObject()); + if (canvas) { + auto ratioPlot = o2::quality_control::checker::getRatioPlotFromCanvas(canvas); + if (ratioPlot) { + ILOG(Debug, Devel) << "Checking eff ratio for SOLAR:" << ENDM; + checkSolarMeanEfficiencyRatios(ratioPlot); + } + } + } } return mQualityChecker.getQuality(); @@ -156,6 +238,92 @@ std::string PreclustersCheck::getAcceptedType() { return "TH1"; } void PreclustersCheck::beautify(std::shared_ptr mo, Quality checkResult) { + if ((mo->getName().find("RefComp/") != std::string::npos)) { + TCanvas* canvas = dynamic_cast(mo->getObject()); + if (!canvas) { + return; + } + + auto ratioPlot = o2::quality_control::checker::getRatioPlotFromCanvas(canvas); + if (!ratioPlot) { + return; + } + + std::string messages; + auto refCompPlots = o2::quality_control::checker::getPlotsFromCanvas(canvas, messages); + + double ratioPlotRange{ -1 }; + double ratioThreshold{ -1 }; + double plotScaleMin{ -1 }; + double plotScaleMax{ -1 }; + bool isSolar{ false }; + + if (matchHistName(mo->getName(), mMeanEffRefCompHistNameB) || + matchHistName(mo->getName(), mMeanEffRefCompHistNameNB)) { + ratioPlotRange = mEfficiencyRatioScaleRange; + ratioThreshold = mMinEfficiencyRatio; + plotScaleMin = mPseudoeffPlotScaleMin; + plotScaleMax = mPseudoeffPlotScaleMax; + isSolar = false; + } else if (matchHistName(mo->getName(), mMeanEffPerSolarRefCompHistName)) { + ratioPlotRange = mEfficiencyRatioPerSolarScaleRange; + ratioThreshold = mMinEfficiencyRatioPerSolar; + plotScaleMin = mPseudoeffPlotScaleMin; + plotScaleMax = mPseudoeffPlotScaleMax; + isSolar = true; + } + + if (ratioPlotRange < 0) { + return; + } + + ratioPlot->SetMinimum(1.0 - ratioPlotRange); + ratioPlot->SetMaximum(1.0 + ratioPlotRange); + ratioPlot->GetXaxis()->SetTickLength(0); + + if (isSolar) { + addChamberDelimitersToSolarHistogram(ratioPlot); + addSolarBinLabels(ratioPlot); + } else { + addChamberDelimiters(ratioPlot); + addDEBinLabels(ratioPlot); + } + drawThreshold(ratioPlot, ratioThreshold); + + if (refCompPlots.first) { + refCompPlots.first->SetMinimum(plotScaleMin); + refCompPlots.first->SetMaximum(plotScaleMax); + if (isSolar) { + addChamberDelimitersToSolarHistogram(refCompPlots.first); + addChamberLabelsForSolar(refCompPlots.first); + addSolarBinLabels(refCompPlots.first); + if (refCompPlots.second) { + addSolarBinLabels(refCompPlots.second); + } + } else { + addChamberDelimiters(refCompPlots.first); + addChamberLabelsForDE(refCompPlots.first); + addDEBinLabels(refCompPlots.first); + if (refCompPlots.second) { + addDEBinLabels(refCompPlots.second); + } + } + } + + if (refCompPlots.second) { + if (checkResult == Quality::Good) { + refCompPlots.second->SetLineColor(kGreen + 2); + } else if (checkResult == Quality::Bad) { + refCompPlots.second->SetLineColor(kRed); + } else if (checkResult == Quality::Medium) { + refCompPlots.second->SetLineColor(kOrange - 3); + } else if (checkResult == Quality::Null) { + refCompPlots.second->SetLineColor(kViolet - 6); + } + } + return; + } + if ((mo->getName().find("ChargeMPV") != std::string::npos)) { TH1F* h = getHisto(mo); if (!h) { @@ -197,12 +365,19 @@ void PreclustersCheck::beautify(std::shared_ptr mo, Quality check h->SetMaximum(1.05 * h->GetMaximum()); } - addChamberDelimiters(h, h->GetMinimum(), h->GetMaximum()); - addDEBinLabels(h); + if (mo->getName().find("MeanEfficiencyPerSolar") != std::string::npos) { + addChamberDelimitersToSolarHistogram(h, h->GetMinimum(), h->GetMaximum()); + addChamberLabelsForSolar(h); + } else { + addChamberDelimiters(h, h->GetMinimum(), h->GetMaximum()); + addChamberLabelsForDE(h); + } // only the plot used for the check is beautified by changing the color // and adding the horizontal lines corresponding to the thresholds - if (matchHistName(mo->getName(), mMeanEffHistNameB) || matchHistName(mo->getName(), mMeanEffHistNameNB)) { + if (matchHistName(mo->getName(), mMeanEffHistNameB) || + matchHistName(mo->getName(), mMeanEffHistNameNB) || + matchHistName(mo->getName(), mMeanEffPerSolarHistName)) { if (checkResult == Quality::Good) { h->SetFillColor(kGreen); } else if (checkResult == Quality::Bad) { @@ -212,7 +387,11 @@ void PreclustersCheck::beautify(std::shared_ptr mo, Quality check } h->SetLineColor(kBlack); - drawThresholdsPerStation(h, mMinEfficiencyPerStation, mMinEfficiency); + if (matchHistName(mo->getName(), mMeanEffPerSolarHistName)) { + drawThreshold(h, mMinEfficiencyPerSolar); + } else { + drawThresholdsPerStation(h, mMinEfficiencyPerStation, mMinEfficiency); + } } } @@ -236,19 +415,74 @@ void PreclustersCheck::beautify(std::shared_ptr mo, Quality check return; } - for (int deId = 0; deId < mQualityChecker.mQuality.size(); deId++) { + std::string badDEs; + for (int deIndex = 0; deIndex < mQualityChecker.mQuality.size(); deIndex++) { float ybin = 0; - if (mQualityChecker.mQuality[deId] == Quality::Good) { + if (mQualityChecker.mQuality[deIndex] == Quality::Good) { ybin = 3; } - if (mQualityChecker.mQuality[deId] == Quality::Medium) { + if (mQualityChecker.mQuality[deIndex] == Quality::Medium) { ybin = 2; } - if (mQualityChecker.mQuality[deId] == Quality::Bad) { + if (mQualityChecker.mQuality[deIndex] == Quality::Bad) { ybin = 1; + std::string deIdStr = std::to_string(getDEFromIndex(deIndex)); + if (badDEs.empty()) { + badDEs = deIdStr; + } else { + badDEs += std::string(" ") + deIdStr; + } } - h->SetBinContent(deId + 1, ybin, 1); + h->SetBinContent(deIndex + 1, ybin, 1); + } + + if (!badDEs.empty()) { + std::string text = std::string("Bad DEs: ") + badDEs; + TPaveLabel* label = new TPaveLabel(0.2, 0.85, 0.8, 0.92, text.c_str(), "blNDC"); + label->SetBorderSize(1); + h->GetListOfFunctions()->Add(label); + + ILOG(Warning, Support) << "[PreclustersCheck] " << text << ENDM; + } + } + + // update quality flags for each SOLAR + if (mo->getName().find("QualityFlagPerSolar") != std::string::npos) { + TH2F* h = getHisto(mo); + if (!h) { + return; + } + + std::string badSolarBoards; + for (int solar = 0; solar < mSolarQuality.size(); solar++) { + float ybin = 0; + if (mSolarQuality[solar] == Quality::Good) { + ybin = 3; + } + if (mSolarQuality[solar] == Quality::Medium) { + ybin = 2; + } + if (mSolarQuality[solar] == Quality::Bad) { + ybin = 1; + std::string solarId = std::to_string(getSolarIdFromIndex(solar)); + if (badSolarBoards.empty()) { + badSolarBoards = solarId; + } else { + badSolarBoards += std::string(" ") + solarId; + } + } + + h->SetBinContent(solar + 1, ybin, 1); + } + + if (!badSolarBoards.empty()) { + std::string badSolarList = std::string("Bad SOLAR boards: ") + badSolarBoards; + TPaveLabel* label = new TPaveLabel(0.2, 0.85, 0.8, 0.92, badSolarList.c_str(), "blNDC"); + label->SetBorderSize(1); + h->GetListOfFunctions()->Add(label); + + ILOG(Warning, Support) << "[PreclustersCheck] " << badSolarList << ENDM; } } } From 9ccfc80c56054b5925ebb83a4022b30d20d07711 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 5 Aug 2025 18:34:55 +0200 Subject: [PATCH 6/8] [MCH] added aggregator task for DE and SOLAR qualities The task combines the summary qualities for each DE and SOLAR link, and uploads a CCDB object with the list of bad DE and SOLAR IDs. The CCDB objects will be used to automatically reconfigure the bad links during the data taking. --- Modules/MUON/MCH/CMakeLists.txt | 3 + Modules/MUON/MCH/include/MCH/LinkDef.h | 1 + .../MCH/include/MCH/QualityAggregatorTask.h | 70 +++ .../MUON/MCH/src/QualityAggregatorTask.cxx | 397 ++++++++++++++++++ 4 files changed, 471 insertions(+) create mode 100644 Modules/MUON/MCH/include/MCH/QualityAggregatorTask.h create mode 100644 Modules/MUON/MCH/src/QualityAggregatorTask.cxx diff --git a/Modules/MUON/MCH/CMakeLists.txt b/Modules/MUON/MCH/CMakeLists.txt index 4cc5211cda..39f1785ab8 100644 --- a/Modules/MUON/MCH/CMakeLists.txt +++ b/Modules/MUON/MCH/CMakeLists.txt @@ -35,6 +35,7 @@ set(SRCS src/DecodingPostProcessing.cxx src/DigitsPostProcessing.cxx src/PreclustersPostProcessing.cxx + src/QualityAggregatorTask.cxx src/PostProcessingConfigMCH.cxx src/TrendingTracks.cxx src/ClustersTask.cxx @@ -76,6 +77,7 @@ set(HEADERS include/MCH/DedodingPostProcessing.h include/MCH/DigitsPostProcessing.h include/MCH/PreclustersPostProcessing.h + include/MCH/QualityAggregatorTask.h include/MCH/PostProcessingConfigMCH.h include/MCH/TrendingTracks.h include/MCH/ClustersTask.h @@ -161,6 +163,7 @@ add_root_dictionary(${MODULE_NAME} include/MCH/DecodingPostProcessing.h include/MCH/DigitsPostProcessing.h include/MCH/PreclustersPostProcessing.h + include/MCH/QualityAggregatorTask.h include/MCH/PostProcessingConfigMCH.h include/MCH/TrendingTracks.h include/MCH/ClustersTask.h diff --git a/Modules/MUON/MCH/include/MCH/LinkDef.h b/Modules/MUON/MCH/include/MCH/LinkDef.h index 1f8433bc6c..d23c1a2b2d 100644 --- a/Modules/MUON/MCH/include/MCH/LinkDef.h +++ b/Modules/MUON/MCH/include/MCH/LinkDef.h @@ -17,6 +17,7 @@ #pragma link C++ class o2::quality_control_modules::muonchambers::DecodingPostProcessing + ; #pragma link C++ class o2::quality_control_modules::muonchambers::DigitsPostProcessing + ; #pragma link C++ class o2::quality_control_modules::muonchambers::PreclustersPostProcessing + ; +#pragma link C++ class o2::quality_control_modules::muonchambers::QualityAggregatorTask + ; // Trending #pragma link C++ class o2::quality_control_modules::muonchambers::TrendingTracks + ; // Checks diff --git a/Modules/MUON/MCH/include/MCH/QualityAggregatorTask.h b/Modules/MUON/MCH/include/MCH/QualityAggregatorTask.h new file mode 100644 index 0000000000..27f107d111 --- /dev/null +++ b/Modules/MUON/MCH/include/MCH/QualityAggregatorTask.h @@ -0,0 +1,70 @@ +// 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 QualityAggregatorTask.h +/// \author Andrea Ferrero andrea.ferrero@cern.ch +/// \brief Post-processing of the MCH pre-clusters +/// \since 21/06/2022 +/// + +#ifndef QC_MODULE_MCH_PP_QUALITY_H +#define QC_MODULE_MCH_PP_QUALITY_H + +#include "QualityControl/PostProcessingInterface.h" +#include "CCDB/CcdbApi.h" + +#include + +using namespace o2::framework; + +using namespace o2::quality_control; +using namespace o2::quality_control::postprocessing; + +class TH2F; + +namespace o2::quality_control_modules::muonchambers +{ + +/// \brief A post-processing task which processes and trends MCH pre-clusters and produces plots. +class QualityAggregatorTask : public PostProcessingInterface +{ + public: + using CcdbApi = o2::ccdb::CcdbApi; + + QualityAggregatorTask() = default; + ~QualityAggregatorTask() override = default; + + void configure(const boost::property_tree::ptree& config) override; + void initialize(Trigger, framework::ServiceRegistryRef) override; + void update(Trigger, framework::ServiceRegistryRef) override; + void finalize(Trigger, framework::ServiceRegistryRef) override; + + private: + CcdbApi mAPI; + std::string mCCDBpath{ "http://ccdb-test.cern.ch:8080" }; // CCDB path + + std::string mObjectPathBadDE{ "MCH/Calib/BadDE" }; + std::string mObjectPathBadSOLAR{ "MCH/Calib/BadSOLAR" }; + + std::vector mDEPlotPaths; + std::optional> mPreviousBadDEs; + + std::vector mSOLARPlotPaths; + std::optional> mPreviousBadSolarBoards; + + std::unique_ptr mHistogramQualityPerDE; ///< quality flags for each DE, to be filled by checker task + std::unique_ptr mHistogramQualityPerSolar; ///< quality flags for each SOLAR, to be filled by checker task +}; + +} // namespace o2::quality_control_modules::muonchambers + +#endif // QC_MODULE_MCH_PP_QUALITY_H diff --git a/Modules/MUON/MCH/src/QualityAggregatorTask.cxx b/Modules/MUON/MCH/src/QualityAggregatorTask.cxx new file mode 100644 index 0000000000..8b30402481 --- /dev/null +++ b/Modules/MUON/MCH/src/QualityAggregatorTask.cxx @@ -0,0 +1,397 @@ +// 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 QualityAggregatorTask.cxx +/// \author Andrea Ferrero andrea.ferrero@cern.ch +/// \brief Post-processing of the MCH pre-clusters +/// \since 21/06/2022 +/// + +#include "MCH/QualityAggregatorTask.h" +#include "MCH/Helpers.h" +#include "QualityControl/QcInfoLogger.h" +#include "QualityControl/DatabaseInterface.h" +#include "QualityControl/ActivityHelpers.h" +#include "QualityControl/ReferenceUtils.h" +#include "Common/Utils.h" +#include "CCDB/CcdbObjectInfo.h" +#include "CommonUtils/MemFileHelper.h" +#include + +#include + +#include +#include + +using namespace o2::quality_control::core; +using namespace o2::quality_control::repository; +using namespace o2::quality_control_modules::common; +using namespace o2::quality_control_modules::muonchambers; + +template +o2::ccdb::CcdbObjectInfo createCcdbInfo(const T& object, uint64_t timeStamp, std::string_view reason) +{ + auto clName = o2::utils::MemFileHelper::getClassName(object); + auto flName = o2::ccdb::CcdbApi::generateFileName(clName); + std::map md; + md["upload-reason"] = reason; + constexpr auto fiveDays = 5 * o2::ccdb::CcdbObjectInfo::DAY; + return o2::ccdb::CcdbObjectInfo("MCH/Calib/BadDE", clName, flName, md, timeStamp, timeStamp + fiveDays); +} + +/* +std::string toCSV(const std::set& deIds) +{ + std::stringstream csv; + csv << fmt::format("deid\n"); + + for (auto deId : deIds) { + csv << fmt::format("{}\n", deId); + } + + return csv.str(); +} +*/ +//_________________________________________________________________________________________ +// Helper function for retrieving a MonitorObject from the QCDB, in the form of a std::pair, bool> +// A non-null MO is returned in the first element of the pair if the MO is found in the QCDB +// The second element of the pair is set to true if the MO has a time stamp more recent than a user-supplied threshold + +static std::pair, bool> getMO(DatabaseInterface& qcdb, const std::string& fullPath, Trigger trigger, long notOlderThan) +{ + // find the time-stamp of the most recent object matching the current activity + // if ignoreActivity is true the activity matching criteria are not applied + auto objectTimestamp = trigger.timestamp; + const auto filterMetadata = activity_helpers::asDatabaseMetadata(trigger.activity, false); + const auto objectValidity = qcdb.getLatestObjectValidity(trigger.activity.mProvenance + "/" + fullPath, filterMetadata); + if (objectValidity.isValid()) { + objectTimestamp = objectValidity.getMax() - 1; + } else { + ILOG(Warning, Devel) << "Could not find the object '" << fullPath << "' for activity " << trigger.activity << ENDM; + return { nullptr, false }; + } + + auto [success, path, name] = o2::quality_control::core::RepoPathUtils::splitObjectPath(fullPath); + if (!success) { + return { nullptr, false }; + } + // retrieve QO from CCDB + auto qo = qcdb.retrieveMO(path, name, objectTimestamp, trigger.activity); + if (!qo) { + return { nullptr, false }; + } + + long elapsed = static_cast(trigger.timestamp) - objectTimestamp; + // check if the object is not older than a given number of milliseconds + if (elapsed > notOlderThan) { + ILOG(Warning, Devel) << "Object '" << fullPath << "' for activity " << trigger.activity << " is too old: " << elapsed << " > " << notOlderThan << ENDM; + return { qo, false }; + } + + return { qo, true }; +} + +void QualityAggregatorTask::configure(const boost::property_tree::ptree& config) +{ + // input plots + if (const auto& inputs = config.get_child_optional("qc.postprocessing." + getID() + ".inputsDE"); inputs.has_value()) { + for (const auto& input : inputs.value()) { + mDEPlotPaths.push_back(input.second.get_value()); + } + } + if (const auto& inputs = config.get_child_optional("qc.postprocessing." + getID() + ".inputsSOLAR"); inputs.has_value()) { + for (const auto& input : inputs.value()) { + mSOLARPlotPaths.push_back(input.second.get_value()); + } + } +} + +//_________________________________________________________________________________________ + +void QualityAggregatorTask::initialize(Trigger t, framework::ServiceRegistryRef services) +{ + mCCDBpath = getFromExtendedConfig(t.activity, mCustomParameters, "CCDBpath", mCCDBpath); + mAPI.init(mCCDBpath); + + mObjectPathBadDE = getFromExtendedConfig(t.activity, mCustomParameters, "objectPathBadDE", mObjectPathBadDE); + mObjectPathBadSOLAR = getFromExtendedConfig(t.activity, mCustomParameters, "objectPathBadSOLAR", mObjectPathBadSOLAR); + + //-------------------------------------------------- + // Quality histogram + //-------------------------------------------------- + + mHistogramQualityPerDE.reset(); + mHistogramQualityPerDE = std::make_unique("QualityFlagPerDE", "Quality Flag vs DE", getNumDE(), 0, getNumDE(), 3, 0, 3); + addDEBinLabels(mHistogramQualityPerDE.get()); + addChamberDelimiters(mHistogramQualityPerDE.get()); + addChamberLabelsForDE(mHistogramQualityPerDE.get()); + mHistogramQualityPerDE->GetYaxis()->SetBinLabel(1, "Bad"); + mHistogramQualityPerDE->GetYaxis()->SetBinLabel(2, "Medium"); + mHistogramQualityPerDE->GetYaxis()->SetBinLabel(3, "Good"); + mHistogramQualityPerDE->SetOption("colz"); + mHistogramQualityPerDE->SetStats(0); + getObjectsManager()->startPublishing(mHistogramQualityPerDE.get(), core::PublicationPolicy::ThroughStop); + getObjectsManager()->setDefaultDrawOptions(mHistogramQualityPerDE.get(), "colz"); + getObjectsManager()->setDisplayHint(mHistogramQualityPerDE.get(), "gridy"); + + mHistogramQualityPerSolar.reset(); + mHistogramQualityPerSolar = std::make_unique("QualityFlagPerSolar", "Quality Flag vs Solar", getNumSolar(), 0, getNumSolar(), 3, 0, 3); + addSolarBinLabels(mHistogramQualityPerSolar.get()); + addChamberDelimitersToSolarHistogram(mHistogramQualityPerSolar.get()); + addChamberLabelsForSolar(mHistogramQualityPerSolar.get()); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(1, "Bad"); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(2, "Medium"); + mHistogramQualityPerSolar->GetYaxis()->SetBinLabel(3, "Good"); + mHistogramQualityPerSolar->SetOption("col"); + mHistogramQualityPerSolar->SetStats(0); + getObjectsManager()->startPublishing(mHistogramQualityPerSolar.get(), core::PublicationPolicy::ThroughStop); + getObjectsManager()->setDefaultDrawOptions(mHistogramQualityPerSolar.get(), "col"); + getObjectsManager()->setDisplayHint(mHistogramQualityPerSolar.get(), "gridy"); +} + +//_________________________________________________________________________________________ + +void QualityAggregatorTask::update(Trigger trigger, framework::ServiceRegistryRef services) +{ + ILOG(Info, Devel) << "QualityAggregatorTask::update() called" << ENDM; + auto& qcdb = services.get(); + + // =================== + // Detection elements + // =================== + + std::set badDEs; + std::array deQuality; + std::fill(deQuality.begin(), deQuality.end(), 3); + // fill vector of bad DEs + for (auto plotPath : mDEPlotPaths) { + auto [mo, success] = getMO(qcdb, plotPath, trigger, 600000); + if (!success || !mo) { + ILOG(Warning, Devel) << "Could not retrieve object " << plotPath << ENDM; + continue; + } + + TH2F* hist = dynamic_cast(mo->getObject()); + if (!hist) { + ILOG(Warning, Devel) << "Could not cast the object '" << plotPath << "' to TH2F" << ENDM; + continue; + } + + if (hist->GetXaxis()->GetNbins() != getNumDE()) { + ILOG(Warning, Devel) << "Wrong number of bins for object '" << plotPath << "': " + << hist->GetXaxis()->GetNbins() << " while " << getNumDE() << " were expected" << ENDM; + continue; + } + + for (int index = 0; index < hist->GetXaxis()->GetNbins(); index++) { + int q = 0; + for (int qindex = 1; qindex <= hist->GetYaxis()->GetNbins(); qindex++) { + if (hist->GetBinContent(index + 1, qindex) != 0) { + q = qindex; + break; + } + } + if (q < deQuality[index]) { + deQuality[index] = q; + } + + bool isBad = (q == 1); + if (!isBad) { + continue; + } + + int deId = getDEFromIndex(index); + badDEs.insert(deId); + + ILOG(Debug, Devel) << "Bad detection element DE" << deId << " found in \'" << plotPath << "\'" << ENDM; + } + } + mHistogramQualityPerDE->Reset(); + for (int index = 0; index < mHistogramQualityPerDE->GetXaxis()->GetNbins(); index++) { + mHistogramQualityPerDE->SetBinContent(index + 1, deQuality[index], 1); + } + + std::string badDEsStr; + for (auto deId : badDEs) { + if (badDEsStr.empty()) { + badDEsStr = std::to_string(deId); + } else { + badDEsStr += std::string(" ") + std::to_string(deId); + } + } + if (!badDEsStr.empty()) { + std::string badDEList = std::string("Bad DEs: ") + badDEsStr; + TPaveLabel* label = new TPaveLabel(0.2, 0.8, 0.8, 0.88, badDEList.c_str(), "blNDC"); + label->SetBorderSize(1); + mHistogramQualityPerDE->GetListOfFunctions()->Add(label); + + ILOG(Warning, Support) << "[QualityAggregator] " << badDEList << ENDM; + } + + // check if the list of bad DEs has changed + bool changedDEs = (!mPreviousBadDEs.has_value() || mPreviousBadDEs.value() != badDEs); + + if (changedDEs) { + std::string sBadDEs = "deid\n"; + for (auto deId : badDEs) { + sBadDEs += fmt::format("{}\n", deId); + } + TObjString badDEsObject(sBadDEs.c_str()); + + // time stamp + auto uploadTS = o2::ccdb::getCurrentTimestamp(); + + // CCDB object info + auto clName = o2::utils::MemFileHelper::getClassName(badDEsObject); + auto flName = o2::ccdb::CcdbApi::generateFileName(clName); + constexpr auto fiveDays = 5 * o2::ccdb::CcdbObjectInfo::DAY; + auto info = o2::ccdb::CcdbObjectInfo(mObjectPathBadDE, clName, flName, std::map(), uploadTS, uploadTS + fiveDays); + + // CCDB object image + auto image = o2::ccdb::CcdbApi::createObjectImage(&badDEsObject, &info); + + ILOG(Info, Devel) << "Storing object " << info.getPath() + << " of type " << info.getObjectType() + << " / " << info.getFileName() + << " and size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() + << " : " << info.getEndValidityTimestamp() << ENDM; + + int res = mAPI.storeAsBinaryFile(image->data(), image->size(), info.getFileName(), info.getObjectType(), info.getPath(), info.getMetaData(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()); + if (res) { + //LOGP(error, "uploading to {} / {} failed for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()); + ILOG(Error, Ops) << fmt::format("uploading to {} / {} failed for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()) << ENDM; + } else { + ILOG(Info, Devel) << fmt::format("uploading to {} / {} succeeded for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()) << ENDM; + mPreviousBadDEs = badDEs; + } + } + + // ============= + // SOLAR boards + // ============= + + std::set badSolarBoards; + std::array solarQuality; + std::fill(solarQuality.begin(), solarQuality.end(), 3); + // fill vector of bad Solars + for (auto plotPath : mSOLARPlotPaths) { + auto [mo, success] = getMO(qcdb, plotPath, trigger, 600000); + if (!success || !mo) { + ILOG(Warning, Devel) << "Could not retrieve object " << plotPath << ENDM; + continue; + } + + TH2F* hist = dynamic_cast(mo->getObject()); + if (!hist) { + ILOG(Warning, Devel) << "Could not cast the object '" << plotPath << "' to TH2F" << ENDM; + continue; + } + + if (hist->GetXaxis()->GetNbins() != getNumSolar()) { + ILOG(Warning, Devel) << "Wrong number of bins for object '" << plotPath << "': " + << hist->GetXaxis()->GetNbins() << " while " << getNumSolar() << " were expected" << ENDM; + continue; + } + + for (int index = 0; index < hist->GetXaxis()->GetNbins(); index++) { + int q = 0; + for (int qindex = 1; qindex <= hist->GetYaxis()->GetNbins(); qindex++) { + if (hist->GetBinContent(index + 1, qindex) != 0) { + q = qindex; + break; + } + } + if (q < solarQuality[index]) { + solarQuality[index] = q; + } + + bool isBad = (q == 1); + if (!isBad) { + continue; + } + + int solarId = getSolarIdFromIndex(index); + badSolarBoards.insert(solarId); + + ILOG(Debug, Devel) << "Bad SOLAR " << solarId << " found in \'" << plotPath << "\'" << ENDM; + } + } + + mHistogramQualityPerSolar->Reset(); + for (int index = 0; index < mHistogramQualityPerSolar->GetXaxis()->GetNbins(); index++) { + mHistogramQualityPerSolar->SetBinContent(index + 1, solarQuality[index], 1); + } + + std::string badSolarBoardsStr; + for (auto solarId : badSolarBoards) { + if (badSolarBoardsStr.empty()) { + badSolarBoardsStr = std::to_string(solarId); + } else { + badSolarBoardsStr += std::string(" ") + std::to_string(solarId); + } + } + if (!badSolarBoardsStr.empty()) { + std::string badSolarList = std::string("Bad SOLAR boards: ") + badSolarBoardsStr; + TPaveLabel* label = new TPaveLabel(0.2, 0.8, 0.8, 0.88, badSolarList.c_str(), "blNDC"); + label->SetBorderSize(1); + mHistogramQualityPerSolar->GetListOfFunctions()->Add(label); + + ILOG(Warning, Support) << "[QualityAggregator] " << badSolarList << ENDM; + } + + // check if the list of bad Solars has changed + bool changedSolarBoards = (!mPreviousBadSolarBoards.has_value() || mPreviousBadSolarBoards.value() != badSolarBoards); + + if (changedSolarBoards) { + std::string sBadSolars = "solarid\n"; + for (auto solarId : badSolarBoards) { + sBadSolars += fmt::format("{}\n", solarId); + } + TObjString badSolarBoardsObject(sBadSolars.c_str()); + + // time stamp + auto uploadTS = o2::ccdb::getCurrentTimestamp(); + + // CCDB object info + auto clName = o2::utils::MemFileHelper::getClassName(badSolarBoardsObject); + auto flName = o2::ccdb::CcdbApi::generateFileName(clName); + constexpr auto fiveDays = 5 * o2::ccdb::CcdbObjectInfo::DAY; + auto info = o2::ccdb::CcdbObjectInfo(mObjectPathBadSOLAR, clName, flName, std::map(), uploadTS, uploadTS + fiveDays); + + // CCDB object image + auto image = o2::ccdb::CcdbApi::createObjectImage(&badSolarBoardsObject, &info); + + ILOG(Info, Devel) << "Storing object " << info.getPath() + << " of type " << info.getObjectType() + << " / " << info.getFileName() + << " and size " << image->size() + << " bytes, valid for " << info.getStartValidityTimestamp() + << " : " << info.getEndValidityTimestamp() << ENDM; + ILOG(Info, Devel) << badSolarBoardsObject.String().Data() << ENDM; + + int res = mAPI.storeAsBinaryFile(image->data(), image->size(), info.getFileName(), info.getObjectType(), info.getPath(), info.getMetaData(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()); + if (res) { + //LOGP(error, "uploading to {} / {} failed for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()); + ILOG(Error, Ops) << fmt::format("uploading to {} / {} failed for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()) << ENDM; + } else { + ILOG(Info, Devel) << fmt::format("uploading to {} / {} succeeded for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()) << ENDM; + mPreviousBadSolarBoards = badSolarBoards; + } + } +} + +//_________________________________________________________________________________________ + +void QualityAggregatorTask::finalize(Trigger t, framework::ServiceRegistryRef) +{ +} From a90f0362cf40198bd61e1f523543550be2a0bd74 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Tue, 5 Aug 2025 18:44:50 +0200 Subject: [PATCH 7/8] [MCH] fixed clang errors --- Modules/MUON/MCH/include/MCH/DecodingCheck.h | 1 - Modules/MUON/MCH/include/MCH/TH2ElecMapReductor.h | 1 - Modules/MUON/MCH/src/Helpers.cxx | 5 +---- Modules/MUON/MCH/src/PreclustersTask.cxx | 2 +- Modules/MUON/MCH/src/QualityAggregatorTask.cxx | 2 -- 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/Modules/MUON/MCH/include/MCH/DecodingCheck.h b/Modules/MUON/MCH/include/MCH/DecodingCheck.h index 98917fe6bd..c317743189 100644 --- a/Modules/MUON/MCH/include/MCH/DecodingCheck.h +++ b/Modules/MUON/MCH/include/MCH/DecodingCheck.h @@ -77,7 +77,6 @@ class DecodingCheck : public o2::quality_control::checker::CheckInterface double mSyncFracRatioPlotRange{ 0.2 }; double mSyncFracRatioPerSolarPlotRange{ 0.2 }; - QualityChecker mQualityChecker; std::array mSolarQuality; diff --git a/Modules/MUON/MCH/include/MCH/TH2ElecMapReductor.h b/Modules/MUON/MCH/include/MCH/TH2ElecMapReductor.h index 4b9fd37edf..9fb185ce10 100644 --- a/Modules/MUON/MCH/include/MCH/TH2ElecMapReductor.h +++ b/Modules/MUON/MCH/include/MCH/TH2ElecMapReductor.h @@ -65,7 +65,6 @@ class TH2ElecMapReductor : public quality_control::postprocessing::ReductorTObje return getNumPadsNoStat(deid, 0) + getNumPadsNoStat(deid, 1); } - private: static constexpr int sDeNum{ 156 }; static constexpr uint32_t sSolarIndexMax{ 32 * 24 }; diff --git a/Modules/MUON/MCH/src/Helpers.cxx b/Modules/MUON/MCH/src/Helpers.cxx index 3c224b924d..06ccfee23d 100644 --- a/Modules/MUON/MCH/src/Helpers.cxx +++ b/Modules/MUON/MCH/src/Helpers.cxx @@ -202,7 +202,6 @@ int getDEFromIndex(int index) return deId; } - //_________________________________________________________________________________________ std::map buildSolarIdToSolarIndexMap() @@ -225,7 +224,6 @@ std::map buildSolarIdToSolarIndexMap() } } return m; - } std::vector buildSolarIndexToSolarIdMap() @@ -288,7 +286,6 @@ int getNumSolarPerChamber(int chamberId) return -1; } - //_________________________________________________________________________________________ void getThresholdsPerStation(o2::quality_control::core::CustomParameters customParameters, @@ -570,7 +567,7 @@ void addChamberDelimitersToSolarHistogram(TH1* h, float xmin, float xmax) h->GetListOfFunctions()->Add(delimiter); } - //addChamberLabelsForSolar(h); + // addChamberLabelsForSolar(h); // draw x-axis labels /*float xMin{ 0 }; diff --git a/Modules/MUON/MCH/src/PreclustersTask.cxx b/Modules/MUON/MCH/src/PreclustersTask.cxx index 12a4c9927d..181374144e 100644 --- a/Modules/MUON/MCH/src/PreclustersTask.cxx +++ b/Modules/MUON/MCH/src/PreclustersTask.cxx @@ -344,7 +344,7 @@ void PreclustersTask::plotPrecluster(const o2::mch::PreCluster& preCluster, gsl: getFecChannel(deId, padIdNB, fecIdNB, channelNB); } else { ILOG(Info, Devel) << "[PreclustersTask::plotPrecluster()] could not find pad in DE" << deId - << " for pre-cluster at (" << Xcog << "," << Ycog << ")" << AliceO2::InfoLogger::InfoLogger::endm; + << " for pre-cluster at (" << Xcog << "," << Ycog << ")" << AliceO2::InfoLogger::InfoLogger::endm; return; } diff --git a/Modules/MUON/MCH/src/QualityAggregatorTask.cxx b/Modules/MUON/MCH/src/QualityAggregatorTask.cxx index 8b30402481..80ba71b805 100644 --- a/Modules/MUON/MCH/src/QualityAggregatorTask.cxx +++ b/Modules/MUON/MCH/src/QualityAggregatorTask.cxx @@ -268,7 +268,6 @@ void QualityAggregatorTask::update(Trigger trigger, framework::ServiceRegistryRe int res = mAPI.storeAsBinaryFile(image->data(), image->size(), info.getFileName(), info.getObjectType(), info.getPath(), info.getMetaData(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()); if (res) { - //LOGP(error, "uploading to {} / {} failed for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()); ILOG(Error, Ops) << fmt::format("uploading to {} / {} failed for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()) << ENDM; } else { ILOG(Info, Devel) << fmt::format("uploading to {} / {} succeeded for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()) << ENDM; @@ -381,7 +380,6 @@ void QualityAggregatorTask::update(Trigger trigger, framework::ServiceRegistryRe int res = mAPI.storeAsBinaryFile(image->data(), image->size(), info.getFileName(), info.getObjectType(), info.getPath(), info.getMetaData(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()); if (res) { - //LOGP(error, "uploading to {} / {} failed for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()); ILOG(Error, Ops) << fmt::format("uploading to {} / {} failed for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()) << ENDM; } else { ILOG(Info, Devel) << fmt::format("uploading to {} / {} succeeded for [{}:{}]", mAPI.getURL(), info.getPath(), info.getStartValidityTimestamp(), info.getEndValidityTimestamp()) << ENDM; From 0056180e881919c7f4aa51d30b368a73a3929307 Mon Sep 17 00:00:00 2001 From: aferrero2707 Date: Thu, 7 Aug 2025 22:42:19 +0200 Subject: [PATCH 8/8] [MCH] added review suggestions --- .../MCH/include/MCH/DecodingPostProcessing.h | 2 +- .../MCH/include/MCH/DigitsPostProcessing.h | 2 +- .../include/MCH/PreclustersPostProcessing.h | 2 +- .../MCH/include/MCH/QualityAggregatorTask.h | 2 +- .../MUON/MCH/src/DecodingPostProcessing.cxx | 2 +- Modules/MUON/MCH/src/DigitsPostProcessing.cxx | 2 +- Modules/MUON/MCH/src/Helpers.cxx | 24 +++---------------- .../MCH/src/PreclustersPostProcessing.cxx | 2 +- .../MUON/MCH/src/QualityAggregatorTask.cxx | 2 +- 9 files changed, 11 insertions(+), 29 deletions(-) diff --git a/Modules/MUON/MCH/include/MCH/DecodingPostProcessing.h b/Modules/MUON/MCH/include/MCH/DecodingPostProcessing.h index 5ae79d1950..b9df5538e0 100644 --- a/Modules/MUON/MCH/include/MCH/DecodingPostProcessing.h +++ b/Modules/MUON/MCH/include/MCH/DecodingPostProcessing.h @@ -73,7 +73,7 @@ class DecodingPostProcessing : public ReferenceComparatorTask static std::string hbPacketsSourceName() { return "hbpackets"; } static std::string syncStatusSourceName() { return "syncstatus"; } - TH1* getHistogram(std::string plotName); + TH1* getHistogram(std::string_view plotName); bool mFullHistos{ false }; bool mEnableLastCycleHistos{ false }; diff --git a/Modules/MUON/MCH/include/MCH/DigitsPostProcessing.h b/Modules/MUON/MCH/include/MCH/DigitsPostProcessing.h index cc3045bb7d..d53a7ff1ab 100644 --- a/Modules/MUON/MCH/include/MCH/DigitsPostProcessing.h +++ b/Modules/MUON/MCH/include/MCH/DigitsPostProcessing.h @@ -63,7 +63,7 @@ class DigitsPostProcessing : public ReferenceComparatorTask static std::string orbitsSourceName() { return "orbits"; } static std::string orbitsSignalSourceName() { return "orbits_signal"; } - TH1* getHistogram(std::string plotName); + TH1* getHistogram(std::string_view plotName); bool mFullHistos{ false }; bool mEnableLastCycleHistos{ false }; diff --git a/Modules/MUON/MCH/include/MCH/PreclustersPostProcessing.h b/Modules/MUON/MCH/include/MCH/PreclustersPostProcessing.h index 1ddb8d1bca..351e4ca3d4 100644 --- a/Modules/MUON/MCH/include/MCH/PreclustersPostProcessing.h +++ b/Modules/MUON/MCH/include/MCH/PreclustersPostProcessing.h @@ -72,7 +72,7 @@ class PreclustersPostProcessing : public ReferenceComparatorTask static std::string clusterChargeSourceName() { return "clcharge"; } static std::string clusterSizeSourceName() { return "clsize"; } - TH1* getHistogram(std::string plotName); + TH1* getHistogram(std::string_view plotName); bool mFullHistos{ false }; bool mEnableLastCycleHistos{ false }; diff --git a/Modules/MUON/MCH/include/MCH/QualityAggregatorTask.h b/Modules/MUON/MCH/include/MCH/QualityAggregatorTask.h index 27f107d111..679ff623d8 100644 --- a/Modules/MUON/MCH/include/MCH/QualityAggregatorTask.h +++ b/Modules/MUON/MCH/include/MCH/QualityAggregatorTask.h @@ -12,7 +12,7 @@ /// /// \file QualityAggregatorTask.h /// \author Andrea Ferrero andrea.ferrero@cern.ch -/// \brief Post-processing of the MCH pre-clusters +/// \brief Post-processing of the MCH summary qualities /// \since 21/06/2022 /// diff --git a/Modules/MUON/MCH/src/DecodingPostProcessing.cxx b/Modules/MUON/MCH/src/DecodingPostProcessing.cxx index 92748280c2..4c0f2f3d37 100644 --- a/Modules/MUON/MCH/src/DecodingPostProcessing.cxx +++ b/Modules/MUON/MCH/src/DecodingPostProcessing.cxx @@ -286,7 +286,7 @@ void DecodingPostProcessing::updateSyncStatusHistos(Trigger t, repository::Datab //_________________________________________________________________________________________ -TH1* DecodingPostProcessing::getHistogram(std::string plotName) +TH1* DecodingPostProcessing::getHistogram(std::string_view plotName) { TH1* result{ nullptr }; for (auto hist : mHistogramsAll) { diff --git a/Modules/MUON/MCH/src/DigitsPostProcessing.cxx b/Modules/MUON/MCH/src/DigitsPostProcessing.cxx index 8412a6562b..3f3b6341fe 100644 --- a/Modules/MUON/MCH/src/DigitsPostProcessing.cxx +++ b/Modules/MUON/MCH/src/DigitsPostProcessing.cxx @@ -348,7 +348,7 @@ void DigitsPostProcessing::updateOrbitHistos(Trigger t, repository::DatabaseInte //_________________________________________________________________________________________ -TH1* DigitsPostProcessing::getHistogram(std::string plotName) +TH1* DigitsPostProcessing::getHistogram(std::string_view plotName) { TH1* result{ nullptr }; for (auto hist : mHistogramsAll) { diff --git a/Modules/MUON/MCH/src/Helpers.cxx b/Modules/MUON/MCH/src/Helpers.cxx index 06ccfee23d..5d58ae3bd2 100644 --- a/Modules/MUON/MCH/src/Helpers.cxx +++ b/Modules/MUON/MCH/src/Helpers.cxx @@ -184,15 +184,6 @@ int getDEFromIndex(int index) if (deId < 0) { deId = lMax + (nDEhc - indexInHalfChamber); } - /*if (indexInHalfChamber > nDEqc) { - // the DE is in the lower half of the chamber - std::cout << "DE on lower R side, indexInHalfChamber=" << indexInHalfChamber << " nDEqc=" << nDEqc << std::endl; - deId = lMax + (nDEhc - indexInHalfChamber); - } else { - // the DE is in the upper half of the chamber - std::cout << "DE on upper R side, indexInHalfChamber=" << indexInHalfChamber << " nDEqc=" << nDEqc << std::endl; - deId = lMin - indexInHalfChamber - 1; - }*/ } deId += (chamber + 1) * 100; @@ -245,7 +236,7 @@ int getSolarIndex(int solarId) try { return m.at(solarId); } catch (const std::exception&) { - ILOG(Error, Support) << "Invalid Solar Id: " << solarId; + ILOG(Error, Support) << "Invalid Solar Id: " << solarId << ENDM; } return -1; } @@ -256,18 +247,11 @@ int getSolarIdFromIndex(int index) try { return v.at(index); } catch (const std::exception&) { - ILOG(Error, Support) << "Invalid Solar Index: " << index; + ILOG(Error, Support) << "Invalid Solar Index: " << index << ENDM; } return -1; } -/* -constexpr int getNumSolar() -{ - //static std::vector v = buildSolarIndexToSolarIdMap(); - //return v.size(); - return 624; -} -*/ + int getNumSolarPerChamber(int chamberId) { static std::array v{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -567,8 +551,6 @@ void addChamberDelimitersToSolarHistogram(TH1* h, float xmin, float xmax) h->GetListOfFunctions()->Add(delimiter); } - // addChamberLabelsForSolar(h); - // draw x-axis labels /*float xMin{ 0 }; float xMax{ 0 }; diff --git a/Modules/MUON/MCH/src/PreclustersPostProcessing.cxx b/Modules/MUON/MCH/src/PreclustersPostProcessing.cxx index 3c3f39344b..ab10511a7e 100644 --- a/Modules/MUON/MCH/src/PreclustersPostProcessing.cxx +++ b/Modules/MUON/MCH/src/PreclustersPostProcessing.cxx @@ -307,7 +307,7 @@ void PreclustersPostProcessing::updateClusterSizeHistos(Trigger t, repository::D //_________________________________________________________________________________________ -TH1* PreclustersPostProcessing::getHistogram(std::string plotName) +TH1* PreclustersPostProcessing::getHistogram(std::string_view plotName) { TH1* result{ nullptr }; for (auto hist : mHistogramsAll) { diff --git a/Modules/MUON/MCH/src/QualityAggregatorTask.cxx b/Modules/MUON/MCH/src/QualityAggregatorTask.cxx index 80ba71b805..7dff36bc9f 100644 --- a/Modules/MUON/MCH/src/QualityAggregatorTask.cxx +++ b/Modules/MUON/MCH/src/QualityAggregatorTask.cxx @@ -12,7 +12,7 @@ /// /// \file QualityAggregatorTask.cxx /// \author Andrea Ferrero andrea.ferrero@cern.ch -/// \brief Post-processing of the MCH pre-clusters +/// \brief Post-processing of the MCH summary qualities /// \since 21/06/2022 ///