From acdbdb9cb9c958f37f416ecf7fedd3e05070d34c Mon Sep 17 00:00:00 2001 From: dskora Date: Tue, 28 Feb 2023 21:56:45 +0100 Subject: [PATCH 01/33] Add mHistGateTimeRatio2Ch monitoring object to DigitQcTask Extend GenericCheck with check of ratio of bins behind given value. Add specific check for TriggersSoftwareVsTCM MO. --- Modules/FIT/FV0/include/FV0/DigitQcTask.h | 1 + Modules/FIT/FV0/include/FV0/GenericCheck.h | 2 ++ Modules/FIT/FV0/src/DigitQcTask.cxx | 16 ++++++++++- Modules/FIT/FV0/src/GenericCheck.cxx | 31 ++++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Modules/FIT/FV0/include/FV0/DigitQcTask.h b/Modules/FIT/FV0/include/FV0/DigitQcTask.h index 38f316e6d6..a860a3ff9b 100644 --- a/Modules/FIT/FV0/include/FV0/DigitQcTask.h +++ b/Modules/FIT/FV0/include/FV0/DigitQcTask.h @@ -157,6 +157,7 @@ class DigitQcTask final : public TaskInterface std::unique_ptr mHistAverageTimeC; std::unique_ptr mHistChannelID; std::unique_ptr mHistCFDEff; + std::unique_ptr mHistGateTimeRatio; // std::unique_ptr mHistTimeSum2Diff; std::unique_ptr mHistTriggersCorrelation; std::unique_ptr mHistCycleDuration; diff --git a/Modules/FIT/FV0/include/FV0/GenericCheck.h b/Modules/FIT/FV0/include/FV0/GenericCheck.h index cbb73dbc39..18abb7b289 100644 --- a/Modules/FIT/FV0/include/FV0/GenericCheck.h +++ b/Modules/FIT/FV0/include/FV0/GenericCheck.h @@ -108,6 +108,8 @@ class GenericCheck : public o2::quality_control::checker::CheckInterface private: SingleCheck getCheckFromConfig(std::string); + SingleCheck mCheckMaxEdgeIntegralRatioY; + SingleCheck mCheckMaxOverflowIntegralRatio; SingleCheck mCheckMinMeanX; diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index a8f5089f40..8d0383718a 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -262,7 +262,7 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistBCvsFEEmodules->GetYaxis()->SetBinLabel(entry.second + 1, entry.first.c_str()); mHistOrbitVsFEEmodules->GetYaxis()->SetBinLabel(entry.second + 1, entry.first.c_str()); } - + mHistGateTimeRatio2Ch = std::make_unique("HistGateTimeRatio2Ch", "Ratio of measurements between time -192 and 192", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); // mHistTimeSum2Diff = std::make_unique("timeSumVsDiff", "time A/C side: sum VS diff;(TOC-TOA)/2 [ns];(TOA+TOC)/2 [ns]", 400, -52.08, 52.08, 400, -52.08, 52.08); // range of 52.08 ns = 4000*13.02ps = 4000 channels mHistNumADC = std::make_unique("HistNumADC", "HistNumADC", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); mHistNumCFD = std::make_unique("HistNumCFD", "HistNumCFD", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); @@ -327,6 +327,7 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) rebinFromConfig(); // after all histos are created // 1-dim hists + getObjectsManager()->startPublishing(mHistGateTimeRatio2Ch.get()); getObjectsManager()->startPublishing(mHistCFDEff.get()); getObjectsManager()->startPublishing(mHistBC.get()); getObjectsManager()->startPublishing(mHistNchA.get()); @@ -385,6 +386,7 @@ void DigitQcTask::startOfActivity(Activity& activity) mHistAmp2Ch->Reset(); mHistBC->Reset(); mHistChDataBits->Reset(); + mHistGateTimeRatio2Ch->Reset(); mHistCFDEff->Reset(); mHistNumADC->Reset(); mHistNumCFD->Reset(); @@ -641,6 +643,17 @@ void DigitQcTask::endOfCycle() ILOG(Debug, Support) << "adding last TF creation time: " << mTFcreationTime << ENDM; getObjectsManager()->getMonitorObject(mHistBCvsTrg->GetName())->addOrUpdateMetadata("TFcreationTime", std::to_string(mTFcreationTime)); + // =============================== Zadanie =============================== + for (int i = 1; i <= sNCHANNELS_FV0_PLUSREF; i++) { + int count = 0; + for (int j = 1; j <= mHistTime2Ch->GetNbinsY(); j++) { + if (mHistTime2Ch->GetYaxis()->GetBinLowEdge(j) >= -192 && mHistTime2Ch->GetYaxis()->GetBinUpEdge(j) <= 192) { + count += mHistTime2Ch->GetBinContent(i, j); + } + } + mHistGateTimeRatio2Ch->SetBinContent(i, (float) count / mHistTime2Ch->Integral(i, i)); + } + // one has to set num. of entries manually because // default TH1Reductor gets only mean,stddev and entries (no integral) mHistCFDEff->Divide(mHistNumADC.get(), mHistNumCFD.get()); @@ -661,6 +674,7 @@ void DigitQcTask::endOfActivity(Activity& /*activity*/) void DigitQcTask::reset() { // clean all the monitor objects here + mHistGateTimeRatio2Ch->Reset(); mHistTime2Ch->Reset(); mHistAmp2Ch->Reset(); mHistBC->Reset(); diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index 321f4ee911..d28cd464b2 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -66,6 +66,7 @@ SingleCheck GenericCheck::getCheckFromConfig(std::string paramName) void GenericCheck::configure() { + mCheckMaxEdgeIntegralRatioY = getCheckFromConfig("MaxEdgeIntegralRatioY"); mCheckMaxOverflowIntegralRatio = getCheckFromConfig("MaxOverflowIntegralRatio"); @@ -118,6 +119,25 @@ Quality GenericCheck::check(std::map ILOG(Error, Support) << "MO " << moName << " not found" << ENDM; continue; } + + // =============================== Zadanie =============================== + if (mo->getName() == "TriggersSoftwareVsTCM") { + auto h2 = (TH2*)mo->getObject(); + int numXBins = h2->GetNbinsX(); + int numYBins = h2->GetNbinsY(); + + for (int i = 1; i <= numXBins; i++) { + + if ((h2->GetBinContent(i, 3) && !h2->GetBinContent(i, 4)) || (!h2->GetBinContent(i, 3) && h2->GetBinContent(i, 4))) { + result.set(Quality::Bad); + result.addReason(FlagReasonFactory::Unknown(), + "CFD eff. < \"Error\" threshold in channel " + std::to_string(chId)); + break; + } + + } + } + if (std::strcmp(mo->getObject()->ClassName(), "TCanvas") == 0) { auto g = (TGraph*)((TCanvas*)mo->getObject())->GetListOfPrimitives()->FindObject(mNameObjOnCanvas.c_str()); @@ -154,6 +174,17 @@ Quality GenericCheck::check(std::map continue; } + // =============================== Zadanie =============================== + if (mCheckMaxEdgeIntegralRatioY.isActive()) { + int nBinsX = h->GetNbinsX(); + float sumRatio = 0; + for (int iBinX = 1; iBinX <= nBinsX; iBinX++) { + sumRatio += h->GetBinContent(iBinX); + } + float meanRatio = sumRatio / nBinsX; + mCheckMaxEdgeIntegralRatioY.doCheck(result, meanRatio); + } + if (mCheckMinMeanX.isActive()) mCheckMinMeanX.doCheck(result, h->GetMean()); if (mCheckMaxMeanX.isActive()) From d272277b1d9b635a2829f7d757633808fcf14354 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Sat, 4 Mar 2023 17:58:32 +0100 Subject: [PATCH 02/33] Fix build errors --- Modules/FIT/FV0/include/FV0/DigitQcTask.h | 2 +- Modules/FIT/FV0/src/DigitQcTask.cxx | 14 ++++++++------ Modules/FIT/FV0/src/GenericCheck.cxx | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Modules/FIT/FV0/include/FV0/DigitQcTask.h b/Modules/FIT/FV0/include/FV0/DigitQcTask.h index a860a3ff9b..3c927566c0 100644 --- a/Modules/FIT/FV0/include/FV0/DigitQcTask.h +++ b/Modules/FIT/FV0/include/FV0/DigitQcTask.h @@ -157,7 +157,7 @@ class DigitQcTask final : public TaskInterface std::unique_ptr mHistAverageTimeC; std::unique_ptr mHistChannelID; std::unique_ptr mHistCFDEff; - std::unique_ptr mHistGateTimeRatio; + std::unique_ptr mHistGateTimeRatio2Ch; // std::unique_ptr mHistTimeSum2Diff; std::unique_ptr mHistTriggersCorrelation; std::unique_ptr mHistCycleDuration; diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index 8d0383718a..0eaeece8b5 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -644,14 +644,16 @@ void DigitQcTask::endOfCycle() getObjectsManager()->getMonitorObject(mHistBCvsTrg->GetName())->addOrUpdateMetadata("TFcreationTime", std::to_string(mTFcreationTime)); // =============================== Zadanie =============================== - for (int i = 1; i <= sNCHANNELS_FV0_PLUSREF; i++) { - int count = 0; - for (int j = 1; j <= mHistTime2Ch->GetNbinsY(); j++) { - if (mHistTime2Ch->GetYaxis()->GetBinLowEdge(j) >= -192 && mHistTime2Ch->GetYaxis()->GetBinUpEdge(j) <= 192) { - count += mHistTime2Ch->GetBinContent(i, j); + for (int channel = 1; channel <= sNCHANNELS_FV0_PLUSREF; channel++) { + int bins_in_range = 0; + int bins_per_channel = 0; + for (int y_bin_num = 1; y_bin_num <= mHistTime2Ch->GetNbinsY(); y_bin_num++) { + if (mHistTime2Ch->GetYaxis()->GetBinLowEdge(y_bin_num) >= -192 && mHistTime2Ch->GetYaxis()->GetBinUpEdge(y_bin_num) <= 192) { + bins_in_range += mHistTime2Ch->GetBinContent(channel, y_bin_num); } + bins_per_channel += mHistTime2Ch->GetBinContent(channel, y_bin_num); } - mHistGateTimeRatio2Ch->SetBinContent(i, (float) count / mHistTime2Ch->Integral(i, i)); + mHistGateTimeRatio2Ch->SetBinContent(channel, (float) bins_in_range / (float) bins_per_channel); } // one has to set num. of entries manually because diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index d28cd464b2..699ecef859 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -131,7 +131,7 @@ Quality GenericCheck::check(std::map if ((h2->GetBinContent(i, 3) && !h2->GetBinContent(i, 4)) || (!h2->GetBinContent(i, 3) && h2->GetBinContent(i, 4))) { result.set(Quality::Bad); result.addReason(FlagReasonFactory::Unknown(), - "CFD eff. < \"Error\" threshold in channel " + std::to_string(chId)); + "TriggersSoftwareVsTCM. < \"Error\" threshold in channel " + std::to_string(i)); break; } From 063041563f2bd3fc6cc1fe277abc373965decf47 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Sun, 5 Mar 2023 22:48:26 +0100 Subject: [PATCH 03/33] Add check for MO TriggersSoftwareVsTCM and improve code --- Modules/FIT/FV0/CMakeLists.txt | 4 +- Modules/FIT/FV0/include/FV0/DigitQcTask.h | 2 + Modules/FIT/FV0/include/FV0/GenericCheck.h | 32 +++- Modules/FIT/FV0/include/FV0/LinkDef.h | 1 + .../FV0/include/FV0/TriggersSwVsTcmCheck.h | 48 ++++++ Modules/FIT/FV0/src/DigitQcTask.cxx | 4 +- Modules/FIT/FV0/src/GenericCheck.cxx | 62 ++++---- Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx | 141 ++++++++++++++++++ 8 files changed, 258 insertions(+), 36 deletions(-) create mode 100644 Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h create mode 100644 Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx diff --git a/Modules/FIT/FV0/CMakeLists.txt b/Modules/FIT/FV0/CMakeLists.txt index f5da472e8f..23355145e7 100644 --- a/Modules/FIT/FV0/CMakeLists.txt +++ b/Modules/FIT/FV0/CMakeLists.txt @@ -8,7 +8,8 @@ target_sources(O2QcFV0 PRIVATE src/TH1ReductorLaser.cxx src/GenericCheck.cxx src/CFDEffCheck.cxx src/PostProcTask.cxx - src/OutOfBunchCollCheck.cxx) + src/OutOfBunchCollCheck.cxx + src/TriggersSwVsTcmCheck.cxx) target_include_directories( O2QcFV0 @@ -35,6 +36,7 @@ add_root_dictionary(O2QcFV0 include/FV0/CFDEffCheck.h include/FV0/OutOfBunchCollCheck.h include/FV0/GenericCheck.h + include/FV0/TriggersSwVsTcmCheck.h LINKDEF include/FV0/LinkDef.h) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/FV0 diff --git a/Modules/FIT/FV0/include/FV0/DigitQcTask.h b/Modules/FIT/FV0/include/FV0/DigitQcTask.h index 3c927566c0..25e7d3d644 100644 --- a/Modules/FIT/FV0/include/FV0/DigitQcTask.h +++ b/Modules/FIT/FV0/include/FV0/DigitQcTask.h @@ -81,6 +81,8 @@ class DigitQcTask final : public TaskInterface long mTFcreationTime = 0; + int mTimeGate = 192; + template ::value || std::is_same::value || (std::is_integral::value && !std::is_same::value)>::type> diff --git a/Modules/FIT/FV0/include/FV0/GenericCheck.h b/Modules/FIT/FV0/include/FV0/GenericCheck.h index 18abb7b289..d23b56e9d5 100644 --- a/Modules/FIT/FV0/include/FV0/GenericCheck.h +++ b/Modules/FIT/FV0/include/FV0/GenericCheck.h @@ -38,6 +38,7 @@ class SingleCheck mThresholdError = thresholdError; mShouldBeLower = shouldBeLower; mIsActive = isActive; + mBinNumberX = 0; }; bool isActive() { return mIsActive; }; @@ -47,16 +48,17 @@ class SingleCheck return; std::string log = Form("%s : comparing value = %f with thresholds = %f, %f", mCheckName.c_str(), checkedValue, mThresholdWarning, mThresholdError); + std::string reason; if (mShouldBeLower) { if (checkedValue > mThresholdError) { if (result.isBetterThan(Quality::Bad)) result.set(Quality::Bad); - result.addReason(o2::quality_control::FlagReasonFactory::Unknown(), Form("%.3f > %.3f (%s error limit)", checkedValue, mThresholdError, mCheckName.c_str())); + reason = Form("%.3f > %.3f (%s error limit)", checkedValue, mThresholdError, mCheckName.c_str()); log += "-> Bad"; } else if (checkedValue > mThresholdWarning) { if (result.isBetterThan(Quality::Medium)) result.set(Quality::Medium); - result.addReason(o2::quality_control::FlagReasonFactory::Unknown(), Form("%.3f > %.3f (%s warning limit)", checkedValue, mThresholdWarning, mCheckName.c_str())); + reason = Form("%.3f > %.3f (%s warning limit)", checkedValue, mThresholdWarning, mCheckName.c_str()); log += "-> Medium"; } else { log += "-> OK"; @@ -65,20 +67,39 @@ class SingleCheck if (checkedValue < mThresholdError) { if (result.isBetterThan(Quality::Bad)) result.set(Quality::Bad); - result.addReason(o2::quality_control::FlagReasonFactory::Unknown(), Form("%.3f < %.3f (%s error limit)", checkedValue, mThresholdError, mCheckName.c_str())); + reason = Form("%.3f < %.3f (%s error limit)", checkedValue, mThresholdError, mCheckName.c_str()); log += "-> Bad"; } else if (checkedValue < mThresholdWarning) { if (result.isBetterThan(Quality::Medium)) result.set(Quality::Medium); - result.addReason(o2::quality_control::FlagReasonFactory::Unknown(), Form("%.3f < %.3f (%s warning limit)", checkedValue, mThresholdWarning, mCheckName.c_str())); + reason = Form("%.3f < %.3f (%s warning limit)", checkedValue, mThresholdWarning, mCheckName.c_str()); log += "-> Medium"; } else { log += "-> OK"; } } + + if (reason.length()) { + if (mBinNumberX) { + reason += Form(" for channel %d", mBinNumberX); + } + result.addReason(o2::quality_control::FlagReasonFactory::Unknown(), reason); + } + ILOG(Debug, Support) << log << ENDM; } + float getThresholdWarning() { + return mThresholdWarning; + } + + float getThresholdError() { + return mThresholdError; + } + + public: + int mBinNumberX; + private: std::string mCheckName; float mThresholdWarning; @@ -108,7 +129,8 @@ class GenericCheck : public o2::quality_control::checker::CheckInterface private: SingleCheck getCheckFromConfig(std::string); - SingleCheck mCheckMaxEdgeIntegralRatioY; + SingleCheck mCheckMaxThresholdY; + SingleCheck mCheckMinThresholdY; SingleCheck mCheckMaxOverflowIntegralRatio; diff --git a/Modules/FIT/FV0/include/FV0/LinkDef.h b/Modules/FIT/FV0/include/FV0/LinkDef.h index 8f7ffc9b85..39af5efa15 100644 --- a/Modules/FIT/FV0/include/FV0/LinkDef.h +++ b/Modules/FIT/FV0/include/FV0/LinkDef.h @@ -8,6 +8,7 @@ #pragma link C++ class o2::quality_control_modules::fv0::CFDEffCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::OutOfBunchCollCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::GenericCheck+; +#pragma link C++ class o2::quality_control_modules::fv0::TriggersSwVsTcmCheck + ; //#pragma link C++ class o2::quality_control_modules::fv0::CalibrationTask + ; //#pragma link C++ class o2::quality_control_modules::fv0::ChannelTimeCalibrationCheck + ; diff --git a/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h b/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h new file mode 100644 index 0000000000..06ca63f1ef --- /dev/null +++ b/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h @@ -0,0 +1,48 @@ +// Copyright 2023 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 TriggersSwVsTcmCheck.h +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +/// + +#ifndef QC_MODULE_FV0_TRIGGERSSWVSTCMCHECK_H +#define QC_MODULE_FV0_TRIGGERSSWVSTCMCHECK_H + +#include "QualityControl/CheckInterface.h" + +#include "FV0Base/Constants.h" + +namespace o2::quality_control_modules::fv0 +{ + +/// \brief This check provide xnor (exclusive nor) operation on SW and HW triggers +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +class TriggersSwVsTcmCheck : public o2::quality_control::checker::CheckInterface +{ + public: + TriggersSwVsTcmCheck() = default; + ~TriggersSwVsTcmCheck() override = default; + + void configure() override; + Quality check(std::map>* moMap) override; + void beautify(std::shared_ptr mo, Quality checkResult = Quality::Null) override; + std::string getAcceptedType() override; + + ClassDefOverride(TriggersSwVsTcmCheck, 2); + + private: + std::array mPositionMsgBox; +}; + +} // namespace o2::quality_control_modules::fv0 + +#endif // QC_MODULE_FV0_TRIGGERSSWVSTCMCHECK_H \ No newline at end of file diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index 0eaeece8b5..60fd926693 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -262,7 +262,7 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistBCvsFEEmodules->GetYaxis()->SetBinLabel(entry.second + 1, entry.first.c_str()); mHistOrbitVsFEEmodules->GetYaxis()->SetBinLabel(entry.second + 1, entry.first.c_str()); } - mHistGateTimeRatio2Ch = std::make_unique("HistGateTimeRatio2Ch", "Ratio of measurements between time -192 and 192", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); + mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", "Ratio of events between time -192 and 192", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); // mHistTimeSum2Diff = std::make_unique("timeSumVsDiff", "time A/C side: sum VS diff;(TOC-TOA)/2 [ns];(TOA+TOC)/2 [ns]", 400, -52.08, 52.08, 400, -52.08, 52.08); // range of 52.08 ns = 4000*13.02ps = 4000 channels mHistNumADC = std::make_unique("HistNumADC", "HistNumADC", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); mHistNumCFD = std::make_unique("HistNumCFD", "HistNumCFD", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); @@ -644,7 +644,7 @@ void DigitQcTask::endOfCycle() getObjectsManager()->getMonitorObject(mHistBCvsTrg->GetName())->addOrUpdateMetadata("TFcreationTime", std::to_string(mTFcreationTime)); // =============================== Zadanie =============================== - for (int channel = 1; channel <= sNCHANNELS_FV0_PLUSREF; channel++) { + for (int channel = 1; channel <= sNCHANNELS_FV0_PLUSREF-1; channel++) { int bins_in_range = 0; int bins_per_channel = 0; for (int y_bin_num = 1; y_bin_num <= mHistTime2Ch->GetNbinsY(); y_bin_num++) { diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index 699ecef859..1c3a770bb8 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -25,7 +25,7 @@ #include #include #include -// #include +#include #include #include @@ -66,7 +66,8 @@ SingleCheck GenericCheck::getCheckFromConfig(std::string paramName) void GenericCheck::configure() { - mCheckMaxEdgeIntegralRatioY = getCheckFromConfig("MaxEdgeIntegralRatioY"); + mCheckMaxThresholdY = getCheckFromConfig("MaxThresholdY"); + mCheckMinThresholdY = getCheckFromConfig("MinThresholdY"); mCheckMaxOverflowIntegralRatio = getCheckFromConfig("MaxOverflowIntegralRatio"); @@ -120,24 +121,6 @@ Quality GenericCheck::check(std::map continue; } - // =============================== Zadanie =============================== - if (mo->getName() == "TriggersSoftwareVsTCM") { - auto h2 = (TH2*)mo->getObject(); - int numXBins = h2->GetNbinsX(); - int numYBins = h2->GetNbinsY(); - - for (int i = 1; i <= numXBins; i++) { - - if ((h2->GetBinContent(i, 3) && !h2->GetBinContent(i, 4)) || (!h2->GetBinContent(i, 3) && h2->GetBinContent(i, 4))) { - result.set(Quality::Bad); - result.addReason(FlagReasonFactory::Unknown(), - "TriggersSoftwareVsTCM. < \"Error\" threshold in channel " + std::to_string(i)); - break; - } - - } - } - if (std::strcmp(mo->getObject()->ClassName(), "TCanvas") == 0) { auto g = (TGraph*)((TCanvas*)mo->getObject())->GetListOfPrimitives()->FindObject(mNameObjOnCanvas.c_str()); @@ -174,15 +157,22 @@ Quality GenericCheck::check(std::map continue; } - // =============================== Zadanie =============================== - if (mCheckMaxEdgeIntegralRatioY.isActive()) { - int nBinsX = h->GetNbinsX(); - float sumRatio = 0; - for (int iBinX = 1; iBinX <= nBinsX; iBinX++) { - sumRatio += h->GetBinContent(iBinX); + if (mCheckMinThresholdY.isActive()) { + int numberOfBinsX = h->GetNbinsX(); + float minValue = h->GetBinContent(1); + for (int channel = 1; channel < numberOfBinsX; ++channel) { + if (minValue > h->GetBinContent(channel)) { + minValue = h->GetBinContent(channel); + mCheckMinThresholdY.mBinNumberX = channel; + } } - float meanRatio = sumRatio / nBinsX; - mCheckMaxEdgeIntegralRatioY.doCheck(result, meanRatio); + mCheckMinThresholdY.doCheck(result, minValue); + } + + if (mCheckMaxThresholdY.isActive()) { + mCheckMaxThresholdY.mBinNumberX = h->GetMaximumBin(); + float maxValue = h->GetBinContent(mCheckMaxThresholdY.mBinNumberX); + mCheckMaxThresholdY.doCheck(result, maxValue); } if (mCheckMinMeanX.isActive()) @@ -249,6 +239,22 @@ void GenericCheck::beautify(std::shared_ptr mo, Quality checkResu return; } h->GetListOfFunctions()->Add(msg); + + // add threshold lines + if(mCheckMinThresholdY.isActive()) { + Double_t xMin = h->GetXaxis()->GetXmin(); + Double_t xMax = h->GetXaxis()->GetXmax(); + auto* lineMinError = new TLine(xMin, mCheckMinThresholdY.getThresholdError(), xMax, mCheckMinThresholdY.getThresholdError()); + auto* lineMinWarning = new TLine(xMin, mCheckMinThresholdY.getThresholdWarning(), xMax, mCheckMinThresholdY.getThresholdWarning()); + lineMinError->SetLineWidth(3); + lineMinWarning->SetLineWidth(3); + lineMinError->SetLineStyle(kDashed); + lineMinWarning->SetLineStyle(kDashed); + lineMinError->SetLineColor(kRed); + lineMinWarning->SetLineColor(kOrange); + h->GetListOfFunctions()->Add(lineMinError); + h->GetListOfFunctions()->Add(lineMinWarning); + } } msg->SetName(Form("%s_msg", mo->GetName())); diff --git a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx new file mode 100644 index 0000000000..e402520155 --- /dev/null +++ b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx @@ -0,0 +1,141 @@ +// Copyright 2023 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 TriggersSwVsTcmCheck.cxx +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +/// + +#include "FV0/TriggersSwVsTcmCheck.h" +#include "QualityControl/MonitorObject.h" +#include "QualityControl/Quality.h" +#include "QualityControl/QcInfoLogger.h" +// ROOT +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace o2::quality_control; + +namespace o2::quality_control_modules::fv0 +{ + +constexpr int kBinSwOnly = 1; +constexpr int kBinTcmOnly = 2; + +void TriggersSwVsTcmCheck::configure() { + if (auto param = mCustomParameters.find("ccdbUrl"); param != mCustomParameters.end()) { + setCcdbUrl(param->second); + ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, configured url = " << param->second << ENDM; + } else { + setCcdbUrl("o2-ccdb.internal"); + ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, default url = " + << "o2-ccdb.internal" << ENDM; + } + + mPositionMsgBox = { 0.15, 0.75, 0.85, 0.9 }; + if (auto param = mCustomParameters.find("positionMsgBox"); param != mCustomParameters.end()) { + stringstream ss(param->second); + int i = 0; + while (ss.good()) { + if (i > 4) { + ILOG(Info, Support) << "Skipping next values provided for positionMsgBox" << ENDM; + break; + } + string substr; + getline(ss, substr, ','); + mPositionMsgBox[i] = std::stod(substr); + i++; + } + float minHeight = 0.09, minWidth = 0.19; + if (mPositionMsgBox[2] - mPositionMsgBox[0] < minWidth || mPositionMsgBox[3] - mPositionMsgBox[1] < minHeight) { + mPositionMsgBox = { 0.15, 0.75, 0.85, 0.9 }; + ILOG(Info, Support) << "MsgBox too small: returning to default" << ENDM; + } + } +} + +Quality TriggersSwVsTcmCheck::check(std::map>* moMap) +{ + Quality result = Quality::Null; + int mNumErrors = 0; + for (auto& [moName, mo] : *moMap) { + (void)moName; + if (mo->getName() == "TriggersSoftwareVsTCM") { + auto* histogram = dynamic_cast(mo->getObject()); + result = Quality::Good; + int numberOfBinsX = histogram->GetNbinsX(); + for (int binId = 1; binId <= numberOfBinsX; binId++) { + if ((bool)(histogram->GetBinContent(binId, kBinSwOnly)) || (bool)(histogram->GetBinContent(binId, kBinTcmOnly))) { + mNumErrors++; + if (result.isBetterThan(Quality::Bad)) { + result.set(Quality::Bad); + } + if ((bool)(histogram->GetBinContent(binId, kBinSwOnly))) { + result.addReason(FlagReasonFactory::Unknown(), + Form("TriggersSoftwareVsTCM. < \"Error\" Only SW trigger was activated for bin nr %d", binId)); + } else { + result.addReason(FlagReasonFactory::Unknown(), + Form("TriggersSoftwareVsTCM. < \"Error\" Only TCM trigger was activated for bin nr %d", binId)); + } + } + } + } + } + result.addMetadata("nErrors", std::to_string(mNumErrors)); + return result; +} + +std::string TriggersSwVsTcmCheck::getAcceptedType() { return "TH2"; } + +void TriggersSwVsTcmCheck::beautify(std::shared_ptr mo, Quality checkResult) +{ + if (mo->getName() == "TriggersSoftwareVsTCM") { + auto* histogram = dynamic_cast(mo->getObject()); + + TPaveText* msg = new TPaveText(mPositionMsgBox[0], mPositionMsgBox[1], mPositionMsgBox[2], mPositionMsgBox[3], "NDC"); + histogram->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + msg->Clear(); + auto reasons = checkResult.getReasons(); + for (int i = 0; i < int(reasons.size()); i++) { + msg->AddText(reasons[i].second.c_str()); + if (i > 4) { + msg->AddText("et al ... "); + break; + } + } + int color = kBlack; + if (checkResult == Quality::Good) { + color = kGreen + 1; + msg->AddText(">> Quality::Good <<"); + } else if (checkResult == Quality::Medium) { + color = kOrange - 1; + msg->AddText(">> Quality::Medium <<"); + } else if (checkResult == Quality::Bad) { + color = kRed; + msg->AddText(">> Quality::Bad <<"); + } + msg->SetFillStyle(1); + msg->SetLineWidth(3); + msg->SetLineColor(color); + msg->SetShadowColor(color); + msg->SetTextColor(color); + msg->SetMargin(0.0); + } +} + +} // namespace o2::quality_control_modules::fv0 \ No newline at end of file From e56283e5cf2b42670818b026d27d4bec905bfd8b Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Sun, 5 Mar 2023 23:55:40 +0100 Subject: [PATCH 04/33] Upload changes during work on TriggersSwVsTcmCheck --- Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx | 81 +++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx index e402520155..3fedef9400 100644 --- a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx +++ b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx @@ -33,6 +33,7 @@ using namespace o2::quality_control; namespace o2::quality_control_modules::fv0 { +<<<<<<< HEAD:Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx constexpr int kBinSwOnly = 1; constexpr int kBinTcmOnly = 2; @@ -71,11 +72,34 @@ void TriggersSwVsTcmCheck::configure() { Quality TriggersSwVsTcmCheck::check(std::map>* moMap) { Quality result = Quality::Null; +======= +constexpr int kBinSwOnly = 0; +constexpr int kBinTcmOnly = 1; + +void TriggersSwVsTcm::configure() { + if (auto param = mCustomParameters.find("ccdbUrl"); param != mCustomParameters.end()) { + setCcdbUrl(param->second); + ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, configured url = " << param->second << ENDM; + } else { + setCcdbUrl("o2-ccdb.internal"); + ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, default url = " + << "o2-ccdb.internal" << ENDM; + } +} + +Quality TriggersSwVsTcm::check(std::map>* moMap) +{ + Quality result = Quality::Null; + result.set(Quality::Medium); + result.addReason(FlagReasonFactory::Unknown(), + "Test Warning"); +>>>>>>> c8a05a9e (Upload changes during work on TriggersSwVsTcmCheck):Modules/FV0/src/TriggersSwVsTcmCheck.cxx int mNumErrors = 0; for (auto& [moName, mo] : *moMap) { (void)moName; if (mo->getName() == "TriggersSoftwareVsTCM") { auto* histogram = dynamic_cast(mo->getObject()); +<<<<<<< HEAD:Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx result = Quality::Good; int numberOfBinsX = histogram->GetNbinsX(); for (int binId = 1; binId <= numberOfBinsX; binId++) { @@ -92,20 +116,49 @@ Quality TriggersSwVsTcmCheck::check(std::mapGetNbinsX(); + int numYBins = histogram->GetNbinsY(); + + for (int i = 0; i < numXBins; i++) { + if ((bool)histogram->GetBinContent(i, kBinSwOnly) == (bool)histogram->GetBinContent(i, kBinTcmOnly)) { + mNumErrors++; + if (result.isBetterThan(Quality::Bad)) { + result.set(Quality::Bad); + result.addReason(FlagReasonFactory::Unknown(), + "TriggersSoftwareVsTCM. < \"Error\" threshold in channel " + std::to_string(i)); + } + } +>>>>>>> c8a05a9e (Upload changes during work on TriggersSwVsTcmCheck):Modules/FV0/src/TriggersSwVsTcmCheck.cxx } } } result.addMetadata("nErrors", std::to_string(mNumErrors)); +<<<<<<< HEAD:Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx return result; } std::string TriggersSwVsTcmCheck::getAcceptedType() { return "TH2"; } void TriggersSwVsTcmCheck::beautify(std::shared_ptr mo, Quality checkResult) +======= + result.addMetadata("nWarnings", std::to_string(0)); + + return result; +} + +std::string TriggersSwVsTcm::getAcceptedType() { return "TH2"; } + +void TriggersSwVsTcm::beautify(std::shared_ptr mo, Quality checkResult) +>>>>>>> c8a05a9e (Upload changes during work on TriggersSwVsTcmCheck):Modules/FV0/src/TriggersSwVsTcmCheck.cxx { if (mo->getName() == "TriggersSoftwareVsTCM") { auto* histogram = dynamic_cast(mo->getObject()); +<<<<<<< HEAD:Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx TPaveText* msg = new TPaveText(mPositionMsgBox[0], mPositionMsgBox[1], mPositionMsgBox[2], mPositionMsgBox[3], "NDC"); histogram->GetListOfFunctions()->Add(msg); msg->SetName(Form("%s_msg", mo->GetName())); @@ -138,4 +191,30 @@ void TriggersSwVsTcmCheck::beautify(std::shared_ptr mo, Quality c } } -} // namespace o2::quality_control_modules::fv0 \ No newline at end of file +} // namespace o2::quality_control_modules::fv0 +======= + TPaveText* msg = new TPaveText(0.15, 0.2, 0.85, 0.45, "NDC"); + histogram->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + msg->Clear(); + + if (checkResult == Quality::Good) { + msg->AddText(">> Quality::Good <<"); + msg->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + auto reasons = checkResult.getReasons(); + msg->SetFillColor(kRed); + msg->AddText(">> Quality::Bad <<"); + } else if (checkResult == Quality::Medium) { + auto reasons = checkResult.getReasons(); + msg->SetFillColor(kOrange); + msg->AddText(">> Quality::Medium <<"); + } else { + msg->AddText(">> Quality::Null <<"); + msg->SetFillColor(kGray); + } + } +} + +} // namespace o2::quality_control_modules::fv0 +>>>>>>> c8a05a9e (Upload changes during work on TriggersSwVsTcmCheck):Modules/FV0/src/TriggersSwVsTcmCheck.cxx From 5e45e6da7c07816f2c2b54e2a06d44ac1252d9ab Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Mon, 6 Mar 2023 13:00:00 +0100 Subject: [PATCH 05/33] Fix names and celan up the code --- .../FV0/include/FV0/TriggersSwVsTcmCheck.h | 3 + Modules/FIT/FV0/src/GenericCheck.cxx | 15 +++ Modules/FV0/src/TriggersSwVsTcmCheck.cxx | 115 ++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 Modules/FV0/src/TriggersSwVsTcmCheck.cxx diff --git a/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h b/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h index 06ca63f1ef..666f19df6f 100644 --- a/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h +++ b/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h @@ -38,9 +38,12 @@ class TriggersSwVsTcmCheck : public o2::quality_control::checker::CheckInterface std::string getAcceptedType() override; ClassDefOverride(TriggersSwVsTcmCheck, 2); +<<<<<<< HEAD:Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h private: std::array mPositionMsgBox; +======= +>>>>>>> b117479b (Fix names and celan up the code):Modules/FV0/include/FV0/TriggersSwVsTcmCheck.h }; } // namespace o2::quality_control_modules::fv0 diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index 1c3a770bb8..532f64c586 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -157,6 +157,7 @@ Quality GenericCheck::check(std::map continue; } +<<<<<<< HEAD:Modules/FIT/FV0/src/GenericCheck.cxx if (mCheckMinThresholdY.isActive()) { int numberOfBinsX = h->GetNbinsX(); float minValue = h->GetBinContent(1); @@ -173,6 +174,20 @@ Quality GenericCheck::check(std::map mCheckMaxThresholdY.mBinNumberX = h->GetMaximumBin(); float maxValue = h->GetBinContent(mCheckMaxThresholdY.mBinNumberX); mCheckMaxThresholdY.doCheck(result, maxValue); +======= + // =============================== Zadanie =============================== + if (mCheckMaxEdgeIntegralRatioY.isActive() || mCheckMinEdgeIntegralRatioY.isActive()) { + int numberOfBinsX = h->GetNbinsX(); + float sumOfBinsContent = 0; + for (int binIndex = 1; binIndex <= numberOfBinsX; binIndex++) { + sumOfBinsContent += h->GetBinContent(binIndex); + } + float meanValue = sumOfBinsContent / numberOfBinsX; + if (mCheckMaxEdgeIntegralRatioY.isActive()) + mCheckMaxEdgeIntegralRatioY.doCheck(result, meanValue); + if (mCheckMinEdgeIntegralRatioY.isActive()) + mCheckMinEdgeIntegralRatioY.doCheck(result, meanValue); +>>>>>>> b117479b (Fix names and celan up the code):Modules/FV0/src/GenericCheck.cxx } if (mCheckMinMeanX.isActive()) diff --git a/Modules/FV0/src/TriggersSwVsTcmCheck.cxx b/Modules/FV0/src/TriggersSwVsTcmCheck.cxx new file mode 100644 index 0000000000..1f6f40f2fe --- /dev/null +++ b/Modules/FV0/src/TriggersSwVsTcmCheck.cxx @@ -0,0 +1,115 @@ +// Copyright 2023 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 TriggersSwVsTcmCheck.cxx +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +/// + +#include "FV0/TriggersSwVsTcmCheck.h" +#include "QualityControl/MonitorObject.h" +#include "QualityControl/Quality.h" +#include "QualityControl/QcInfoLogger.h" +// ROOT +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace o2::quality_control; + +namespace o2::quality_control_modules::fv0 +{ + +constexpr int kBinSwOnly = 1; +constexpr int kBinTcmOnly = 2; + +void TriggersSwVsTcmCheck::configure() { + if (auto param = mCustomParameters.find("ccdbUrl"); param != mCustomParameters.end()) { + setCcdbUrl(param->second); + ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, configured url = " << param->second << ENDM; + } else { + setCcdbUrl("o2-ccdb.internal"); + ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, default url = " + << "o2-ccdb.internal" << ENDM; + } +} + +Quality TriggersSwVsTcmCheck::check(std::map>* moMap) +{ + Quality result = Quality::Null; + int mNumErrors = 0; + for (auto& [moName, mo] : *moMap) { + (void)moName; + if (mo->getName() == "TriggersSoftwareVsTCM") { + auto* histogram = dynamic_cast(mo->getObject()); + result = Quality::Good; + int numberOfBinsX = histogram->GetNbinsX(); + for (int i = 1; i <= numberOfBinsX; i++) { + if ((bool)(histogram->GetBinContent(i, kBinSwOnly)) == (bool)(histogram->GetBinContent(i, kBinTcmOnly))) { + mNumErrors++; + if (result.isBetterThan(Quality::Bad)) { + result.set(Quality::Bad); + } + result.addReason(FlagReasonFactory::Unknown(), + "TriggersSoftwareVsTCM. < \"Error\" Only one of the SW or TCM triggers was activated"); + } + } + } + } + result.addMetadata("nErrors", std::to_string(mNumErrors)); + return result; +} + +std::string TriggersSwVsTcmCheck::getAcceptedType() { return "TH2"; } + +void TriggersSwVsTcmCheck::beautify(std::shared_ptr mo, Quality checkResult) +{ + if (mo->getName() == "TriggersSoftwareVsTCM") { + auto* histogram = dynamic_cast(mo->getObject()); + + TPaveText* msg = new TPaveText(0.15, 0.2, 0.85, 0.45, "NDC"); + histogram->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + msg->Clear(); + auto reasons = checkResult.getReasons(); + for (int i = 0; i < int(reasons.size()); i++) { + msg->AddText(reasons[i].second.c_str()); + if (i > 4) { + msg->AddText("et al ... "); + break; + } + } + int color = kBlack; + if (checkResult == Quality::Good) { + color = kGreen + 1; + msg->AddText(">> Quality::Good <<"); + } else if (checkResult == Quality::Medium) { + color = kOrange - 1; + msg->AddText(">> Quality::Medium <<"); + } else if (checkResult == Quality::Bad) { + color = kRed; + msg->AddText(">> Quality::Bad <<"); + } + msg->SetFillStyle(1); + msg->SetLineWidth(3); + msg->SetLineColor(color); + msg->SetShadowColor(color); + msg->SetTextColor(color); + msg->SetMargin(0.0); + } +} + +} // namespace o2::quality_control_modules::fv0 From 45e2294e592a6b07df1cf09804cd36a8456461e7 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Fri, 10 Mar 2023 17:21:11 +0100 Subject: [PATCH 06/33] Extend generic check butify function and parametrize EventsInGateTime hist --- Modules/FIT/FV0/src/DigitQcTask.cxx | 19 +++++++++++-------- Modules/FIT/FV0/src/GenericCheck.cxx | 15 --------------- 2 files changed, 11 insertions(+), 23 deletions(-) diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index 60fd926693..7cea392595 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -297,6 +297,10 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mSetAllowedChIDsAmpVsTime.insert(entry); } + if (auto timeGate = mCustomParameters.find(string("gateTimeForRatioHistogram")); timeGate != mCustomParameters.end()) { + mTimeGate = stof(timeGate->second); + } + for (const auto& chID : mSetAllowedChIDs) { auto pairHistAmp = mMapHistAmp1D.insert({ chID, new TH1F(Form("Amp_channel%i", chID), Form("Amplitude, channel %i", chID), 4200, -100, 4100) }); auto pairHistTime = mMapHistTime1D.insert({ chID, new TH1F(Form("Time_channel%i", chID), Form("Time, channel %i", chID), 4100, -2050, 2050) }); @@ -643,17 +647,16 @@ void DigitQcTask::endOfCycle() ILOG(Debug, Support) << "adding last TF creation time: " << mTFcreationTime << ENDM; getObjectsManager()->getMonitorObject(mHistBCvsTrg->GetName())->addOrUpdateMetadata("TFcreationTime", std::to_string(mTFcreationTime)); - // =============================== Zadanie =============================== for (int channel = 1; channel <= sNCHANNELS_FV0_PLUSREF-1; channel++) { - int bins_in_range = 0; - int bins_per_channel = 0; - for (int y_bin_num = 1; y_bin_num <= mHistTime2Ch->GetNbinsY(); y_bin_num++) { - if (mHistTime2Ch->GetYaxis()->GetBinLowEdge(y_bin_num) >= -192 && mHistTime2Ch->GetYaxis()->GetBinUpEdge(y_bin_num) <= 192) { - bins_in_range += mHistTime2Ch->GetBinContent(channel, y_bin_num); + int events_in_range = 0; + int events_per_channel = 0; + for (int bin_on_y_axis = 1; bin_on_y_axis <= mHistTime2Ch->GetNbinsY(); bin_on_y_axis++) { + if (mHistTime2Ch->GetYaxis()->GetBinLowEdge(bin_on_y_axis) >= -mTimeGate && mHistTime2Ch->GetYaxis()->GetBinUpEdge(bin_on_y_axis) <= mTimeGate) { + events_in_range += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); } - bins_per_channel += mHistTime2Ch->GetBinContent(channel, y_bin_num); + events_per_channel += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); } - mHistGateTimeRatio2Ch->SetBinContent(channel, (float) bins_in_range / (float) bins_per_channel); + mHistGateTimeRatio2Ch->SetBinContent(channel, (float) events_in_range / (float) events_per_channel); } // one has to set num. of entries manually because diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index 532f64c586..1c3a770bb8 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -157,7 +157,6 @@ Quality GenericCheck::check(std::map continue; } -<<<<<<< HEAD:Modules/FIT/FV0/src/GenericCheck.cxx if (mCheckMinThresholdY.isActive()) { int numberOfBinsX = h->GetNbinsX(); float minValue = h->GetBinContent(1); @@ -174,20 +173,6 @@ Quality GenericCheck::check(std::map mCheckMaxThresholdY.mBinNumberX = h->GetMaximumBin(); float maxValue = h->GetBinContent(mCheckMaxThresholdY.mBinNumberX); mCheckMaxThresholdY.doCheck(result, maxValue); -======= - // =============================== Zadanie =============================== - if (mCheckMaxEdgeIntegralRatioY.isActive() || mCheckMinEdgeIntegralRatioY.isActive()) { - int numberOfBinsX = h->GetNbinsX(); - float sumOfBinsContent = 0; - for (int binIndex = 1; binIndex <= numberOfBinsX; binIndex++) { - sumOfBinsContent += h->GetBinContent(binIndex); - } - float meanValue = sumOfBinsContent / numberOfBinsX; - if (mCheckMaxEdgeIntegralRatioY.isActive()) - mCheckMaxEdgeIntegralRatioY.doCheck(result, meanValue); - if (mCheckMinEdgeIntegralRatioY.isActive()) - mCheckMinEdgeIntegralRatioY.doCheck(result, meanValue); ->>>>>>> b117479b (Fix names and celan up the code):Modules/FV0/src/GenericCheck.cxx } if (mCheckMinMeanX.isActive()) From f126f326a75957a48246a9f23136d63d7e060a4d Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Fri, 10 Mar 2023 21:50:05 +0100 Subject: [PATCH 07/33] Parametrize title of EventsInGateTime hist --- Modules/FIT/FV0/src/DigitQcTask.cxx | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index 7cea392595..e1c2b0afc3 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -262,7 +262,6 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistBCvsFEEmodules->GetYaxis()->SetBinLabel(entry.second + 1, entry.first.c_str()); mHistOrbitVsFEEmodules->GetYaxis()->SetBinLabel(entry.second + 1, entry.first.c_str()); } - mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", "Ratio of events between time -192 and 192", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); // mHistTimeSum2Diff = std::make_unique("timeSumVsDiff", "time A/C side: sum VS diff;(TOC-TOA)/2 [ns];(TOA+TOC)/2 [ns]", 400, -52.08, 52.08, 400, -52.08, 52.08); // range of 52.08 ns = 4000*13.02ps = 4000 channels mHistNumADC = std::make_unique("HistNumADC", "HistNumADC", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); mHistNumCFD = std::make_unique("HistNumCFD", "HistNumCFD", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); @@ -278,6 +277,18 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistCycleDurationNTF = std::make_unique("CycleDurationNTF", "Cycle Duration;;time [TimeFrames]", 1, 0, 2); mHistCycleDurationRange = std::make_unique("CycleDurationRange", "Cycle Duration (total cycle range);;time [ns]", 1, 0, 2); + if (auto timeGate = mCustomParameters.find(string("gateTimeForRatioHistogram")); timeGate != mCustomParameters.end()) { + mTimeGate = stof(timeGate->second); + } + char gateTimeRatioTitle[50] = "Ratio of events between time -"; + char gateTimeRatioTitle2[20] = " and "; + char timeGateChar[8]; + sprintf(timeGateChar, "%d", mTimeGate); + strcat(gateTimeRatioTitle, timeGateChar); + strcat(gateTimeRatioTitle2, timeGateChar); + strcat(gateTimeRatioTitle, gateTimeRatioTitle2); + mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", gateTimeRatioTitle, sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); + std::vector vecChannelIDs; if (auto param = mCustomParameters.find("ChannelIDs"); param != mCustomParameters.end()) { const auto chIDs = param->second; @@ -297,9 +308,7 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mSetAllowedChIDsAmpVsTime.insert(entry); } - if (auto timeGate = mCustomParameters.find(string("gateTimeForRatioHistogram")); timeGate != mCustomParameters.end()) { - mTimeGate = stof(timeGate->second); - } + for (const auto& chID : mSetAllowedChIDs) { auto pairHistAmp = mMapHistAmp1D.insert({ chID, new TH1F(Form("Amp_channel%i", chID), Form("Amplitude, channel %i", chID), 4200, -100, 4100) }); From 58e0adf6350d1cc59bafd1fcae8e2dfc39328ab9 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Fri, 10 Mar 2023 21:50:05 +0100 Subject: [PATCH 08/33] Parametrize title of EventsInGateTime hist --- Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h b/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h index 666f19df6f..06ca63f1ef 100644 --- a/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h +++ b/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h @@ -38,12 +38,9 @@ class TriggersSwVsTcmCheck : public o2::quality_control::checker::CheckInterface std::string getAcceptedType() override; ClassDefOverride(TriggersSwVsTcmCheck, 2); -<<<<<<< HEAD:Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h private: std::array mPositionMsgBox; -======= ->>>>>>> b117479b (Fix names and celan up the code):Modules/FV0/include/FV0/TriggersSwVsTcmCheck.h }; } // namespace o2::quality_control_modules::fv0 From 12ebf1a4e1dd82582c891547e1e9d0aeab2f68fe Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Mon, 20 Mar 2023 11:41:59 +0100 Subject: [PATCH 09/33] Refactor code and fix TriggersSwVsTcmCheck --- Modules/FIT/FV0/src/DigitQcTask.cxx | 18 ++-- Modules/FV0/src/TriggersSwVsTcmCheck.cxx | 115 ----------------------- 2 files changed, 6 insertions(+), 127 deletions(-) delete mode 100644 Modules/FV0/src/TriggersSwVsTcmCheck.cxx diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index e1c2b0afc3..0bfbdde840 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -25,6 +25,8 @@ #include "Framework/TimingInfo.h" #include "DataFormatsFV0/LookUpTable.h" +#include + namespace o2::quality_control_modules::fv0 { @@ -168,6 +170,7 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mTrgChargeLevelHigh = getNumericalParameter("trgChargeLevelHigh", 4095); mTrgThresholdCharge = getNumericalParameter("trgThresholdCharge", 1); mTrgThresholdNChannels = getNumericalParameter("trgThresholdNChannels", 1); + mTimeGate = getNumericalParameter("gateTimeForRatioHistogram", 192); if (mTrgModeInnerOuterThresholdVar == TrgModeThresholdVar::kAmpl) { mTrgThresholdChargeInner = getNumericalParameter("trgThresholdChargeInner", 1); @@ -277,17 +280,8 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistCycleDurationNTF = std::make_unique("CycleDurationNTF", "Cycle Duration;;time [TimeFrames]", 1, 0, 2); mHistCycleDurationRange = std::make_unique("CycleDurationRange", "Cycle Duration (total cycle range);;time [ns]", 1, 0, 2); - if (auto timeGate = mCustomParameters.find(string("gateTimeForRatioHistogram")); timeGate != mCustomParameters.end()) { - mTimeGate = stof(timeGate->second); - } - char gateTimeRatioTitle[50] = "Ratio of events between time -"; - char gateTimeRatioTitle2[20] = " and "; - char timeGateChar[8]; - sprintf(timeGateChar, "%d", mTimeGate); - strcat(gateTimeRatioTitle, timeGateChar); - strcat(gateTimeRatioTitle2, timeGateChar); - strcat(gateTimeRatioTitle, gateTimeRatioTitle2); - mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", gateTimeRatioTitle, sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); + std::string gateTimeRatioTitle = "Ratio of events between time -" + std::to_string(mTimeGate) + " and " + std::to_string(mTimeGate); + mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", gateTimeRatioTitle.c_str(), sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); std::vector vecChannelIDs; if (auto param = mCustomParameters.find("ChannelIDs"); param != mCustomParameters.end()) { @@ -660,7 +654,7 @@ void DigitQcTask::endOfCycle() int events_in_range = 0; int events_per_channel = 0; for (int bin_on_y_axis = 1; bin_on_y_axis <= mHistTime2Ch->GetNbinsY(); bin_on_y_axis++) { - if (mHistTime2Ch->GetYaxis()->GetBinLowEdge(bin_on_y_axis) >= -mTimeGate && mHistTime2Ch->GetYaxis()->GetBinUpEdge(bin_on_y_axis) <= mTimeGate) { + if (std::abs(mHistTime2Ch->GetYaxis()->GetBinLowEdge(bin_on_y_axis)) < mTimeGate) { events_in_range += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); } events_per_channel += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); diff --git a/Modules/FV0/src/TriggersSwVsTcmCheck.cxx b/Modules/FV0/src/TriggersSwVsTcmCheck.cxx deleted file mode 100644 index 1f6f40f2fe..0000000000 --- a/Modules/FV0/src/TriggersSwVsTcmCheck.cxx +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright 2023 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 TriggersSwVsTcmCheck.cxx -/// \author Dawid Skora dawid.mateusz.skora@cern.ch -/// - -#include "FV0/TriggersSwVsTcmCheck.h" -#include "QualityControl/MonitorObject.h" -#include "QualityControl/Quality.h" -#include "QualityControl/QcInfoLogger.h" -// ROOT -#include -#include -#include -#include -#include - -#include - -using namespace std; -using namespace o2::quality_control; - -namespace o2::quality_control_modules::fv0 -{ - -constexpr int kBinSwOnly = 1; -constexpr int kBinTcmOnly = 2; - -void TriggersSwVsTcmCheck::configure() { - if (auto param = mCustomParameters.find("ccdbUrl"); param != mCustomParameters.end()) { - setCcdbUrl(param->second); - ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, configured url = " << param->second << ENDM; - } else { - setCcdbUrl("o2-ccdb.internal"); - ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, default url = " - << "o2-ccdb.internal" << ENDM; - } -} - -Quality TriggersSwVsTcmCheck::check(std::map>* moMap) -{ - Quality result = Quality::Null; - int mNumErrors = 0; - for (auto& [moName, mo] : *moMap) { - (void)moName; - if (mo->getName() == "TriggersSoftwareVsTCM") { - auto* histogram = dynamic_cast(mo->getObject()); - result = Quality::Good; - int numberOfBinsX = histogram->GetNbinsX(); - for (int i = 1; i <= numberOfBinsX; i++) { - if ((bool)(histogram->GetBinContent(i, kBinSwOnly)) == (bool)(histogram->GetBinContent(i, kBinTcmOnly))) { - mNumErrors++; - if (result.isBetterThan(Quality::Bad)) { - result.set(Quality::Bad); - } - result.addReason(FlagReasonFactory::Unknown(), - "TriggersSoftwareVsTCM. < \"Error\" Only one of the SW or TCM triggers was activated"); - } - } - } - } - result.addMetadata("nErrors", std::to_string(mNumErrors)); - return result; -} - -std::string TriggersSwVsTcmCheck::getAcceptedType() { return "TH2"; } - -void TriggersSwVsTcmCheck::beautify(std::shared_ptr mo, Quality checkResult) -{ - if (mo->getName() == "TriggersSoftwareVsTCM") { - auto* histogram = dynamic_cast(mo->getObject()); - - TPaveText* msg = new TPaveText(0.15, 0.2, 0.85, 0.45, "NDC"); - histogram->GetListOfFunctions()->Add(msg); - msg->SetName(Form("%s_msg", mo->GetName())); - msg->Clear(); - auto reasons = checkResult.getReasons(); - for (int i = 0; i < int(reasons.size()); i++) { - msg->AddText(reasons[i].second.c_str()); - if (i > 4) { - msg->AddText("et al ... "); - break; - } - } - int color = kBlack; - if (checkResult == Quality::Good) { - color = kGreen + 1; - msg->AddText(">> Quality::Good <<"); - } else if (checkResult == Quality::Medium) { - color = kOrange - 1; - msg->AddText(">> Quality::Medium <<"); - } else if (checkResult == Quality::Bad) { - color = kRed; - msg->AddText(">> Quality::Bad <<"); - } - msg->SetFillStyle(1); - msg->SetLineWidth(3); - msg->SetLineColor(color); - msg->SetShadowColor(color); - msg->SetTextColor(color); - msg->SetMargin(0.0); - } -} - -} // namespace o2::quality_control_modules::fv0 From fefd7f6ffed8099bdf7edf8c0ab1d5627fc8516c Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Sat, 1 Apr 2023 18:41:12 +0200 Subject: [PATCH 10/33] Fix merge conflict --- .../FV0/include/FV0/TriggersSwVsTcmCheck.h | 2 +- Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx | 79 ------------------- 2 files changed, 1 insertion(+), 80 deletions(-) diff --git a/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h b/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h index 06ca63f1ef..beba45d950 100644 --- a/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h +++ b/Modules/FIT/FV0/include/FV0/TriggersSwVsTcmCheck.h @@ -45,4 +45,4 @@ class TriggersSwVsTcmCheck : public o2::quality_control::checker::CheckInterface } // namespace o2::quality_control_modules::fv0 -#endif // QC_MODULE_FV0_TRIGGERSSWVSTCMCHECK_H \ No newline at end of file +#endif // QC_MODULE_FV0_TRIGGERSSWVSTCMCHECK_H diff --git a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx index 3fedef9400..41e66d6407 100644 --- a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx +++ b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx @@ -33,7 +33,6 @@ using namespace o2::quality_control; namespace o2::quality_control_modules::fv0 { -<<<<<<< HEAD:Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx constexpr int kBinSwOnly = 1; constexpr int kBinTcmOnly = 2; @@ -72,34 +71,11 @@ void TriggersSwVsTcmCheck::configure() { Quality TriggersSwVsTcmCheck::check(std::map>* moMap) { Quality result = Quality::Null; -======= -constexpr int kBinSwOnly = 0; -constexpr int kBinTcmOnly = 1; - -void TriggersSwVsTcm::configure() { - if (auto param = mCustomParameters.find("ccdbUrl"); param != mCustomParameters.end()) { - setCcdbUrl(param->second); - ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, configured url = " << param->second << ENDM; - } else { - setCcdbUrl("o2-ccdb.internal"); - ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, default url = " - << "o2-ccdb.internal" << ENDM; - } -} - -Quality TriggersSwVsTcm::check(std::map>* moMap) -{ - Quality result = Quality::Null; - result.set(Quality::Medium); - result.addReason(FlagReasonFactory::Unknown(), - "Test Warning"); ->>>>>>> c8a05a9e (Upload changes during work on TriggersSwVsTcmCheck):Modules/FV0/src/TriggersSwVsTcmCheck.cxx int mNumErrors = 0; for (auto& [moName, mo] : *moMap) { (void)moName; if (mo->getName() == "TriggersSoftwareVsTCM") { auto* histogram = dynamic_cast(mo->getObject()); -<<<<<<< HEAD:Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx result = Quality::Good; int numberOfBinsX = histogram->GetNbinsX(); for (int binId = 1; binId <= numberOfBinsX; binId++) { @@ -116,49 +92,20 @@ Quality TriggersSwVsTcm::check(std::mapGetNbinsX(); - int numYBins = histogram->GetNbinsY(); - - for (int i = 0; i < numXBins; i++) { - if ((bool)histogram->GetBinContent(i, kBinSwOnly) == (bool)histogram->GetBinContent(i, kBinTcmOnly)) { - mNumErrors++; - if (result.isBetterThan(Quality::Bad)) { - result.set(Quality::Bad); - result.addReason(FlagReasonFactory::Unknown(), - "TriggersSoftwareVsTCM. < \"Error\" threshold in channel " + std::to_string(i)); - } - } ->>>>>>> c8a05a9e (Upload changes during work on TriggersSwVsTcmCheck):Modules/FV0/src/TriggersSwVsTcmCheck.cxx } } } result.addMetadata("nErrors", std::to_string(mNumErrors)); -<<<<<<< HEAD:Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx return result; } std::string TriggersSwVsTcmCheck::getAcceptedType() { return "TH2"; } void TriggersSwVsTcmCheck::beautify(std::shared_ptr mo, Quality checkResult) -======= - result.addMetadata("nWarnings", std::to_string(0)); - - return result; -} - -std::string TriggersSwVsTcm::getAcceptedType() { return "TH2"; } - -void TriggersSwVsTcm::beautify(std::shared_ptr mo, Quality checkResult) ->>>>>>> c8a05a9e (Upload changes during work on TriggersSwVsTcmCheck):Modules/FV0/src/TriggersSwVsTcmCheck.cxx { if (mo->getName() == "TriggersSoftwareVsTCM") { auto* histogram = dynamic_cast(mo->getObject()); -<<<<<<< HEAD:Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx TPaveText* msg = new TPaveText(mPositionMsgBox[0], mPositionMsgBox[1], mPositionMsgBox[2], mPositionMsgBox[3], "NDC"); histogram->GetListOfFunctions()->Add(msg); msg->SetName(Form("%s_msg", mo->GetName())); @@ -192,29 +139,3 @@ void TriggersSwVsTcm::beautify(std::shared_ptr mo, Quality checkR } } // namespace o2::quality_control_modules::fv0 -======= - TPaveText* msg = new TPaveText(0.15, 0.2, 0.85, 0.45, "NDC"); - histogram->GetListOfFunctions()->Add(msg); - msg->SetName(Form("%s_msg", mo->GetName())); - msg->Clear(); - - if (checkResult == Quality::Good) { - msg->AddText(">> Quality::Good <<"); - msg->SetFillColor(kGreen); - } else if (checkResult == Quality::Bad) { - auto reasons = checkResult.getReasons(); - msg->SetFillColor(kRed); - msg->AddText(">> Quality::Bad <<"); - } else if (checkResult == Quality::Medium) { - auto reasons = checkResult.getReasons(); - msg->SetFillColor(kOrange); - msg->AddText(">> Quality::Medium <<"); - } else { - msg->AddText(">> Quality::Null <<"); - msg->SetFillColor(kGray); - } - } -} - -} // namespace o2::quality_control_modules::fv0 ->>>>>>> c8a05a9e (Upload changes during work on TriggersSwVsTcmCheck):Modules/FV0/src/TriggersSwVsTcmCheck.cxx From 34cc68033050fef48f845a0a6b570ef8a5ebd439 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Thu, 6 Apr 2023 08:34:13 +0200 Subject: [PATCH 11/33] Enable message box on TriggersSwVsTcmCheck --- Modules/FIT/FV0/src/DigitQcTask.cxx | 2 +- Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx | 18 +++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index 0bfbdde840..6e144e7421 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -206,7 +206,7 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistTriggersSw = std::make_unique("TriggersSoftware", "Triggers from software", mMapDigitTrgNames.size(), 0, mMapDigitTrgNames.size()); mHistTriggersSoftwareVsTCM = std::make_unique("TriggersSoftwareVsTCM", "Comparison of triggers from software and TCM;;Trigger name", mMapDigitTrgNames.size(), 0, mMapDigitTrgNames.size(), 4, 0, 4); mHistTriggersSoftwareVsTCM->SetOption("colz"); - mHistTriggersSoftwareVsTCM->SetStats(0); + mHistTriggersSoftwareVsTCM->SetStats(1); for (const auto& entry : mMapDigitTrgNames) { mHistOrbitVsTrg->GetYaxis()->SetBinLabel(entry.first + 1, entry.second.c_str()); mHistTriggersCorrelation->GetXaxis()->SetBinLabel(entry.first + 1, entry.second.c_str()); diff --git a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx index 41e66d6407..b8535b6175 100644 --- a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx +++ b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx @@ -84,13 +84,8 @@ Quality TriggersSwVsTcmCheck::check(std::mapGetBinContent(binId, kBinSwOnly))) { - result.addReason(FlagReasonFactory::Unknown(), - Form("TriggersSoftwareVsTCM. < \"Error\" Only SW trigger was activated for bin nr %d", binId)); - } else { - result.addReason(FlagReasonFactory::Unknown(), - Form("TriggersSoftwareVsTCM. < \"Error\" Only TCM trigger was activated for bin nr %d", binId)); - } + result.addReason(FlagReasonFactory::Unknown(), + "Only SW or TCM trigger was activated"); } } } @@ -110,14 +105,7 @@ void TriggersSwVsTcmCheck::beautify(std::shared_ptr mo, Quality c histogram->GetListOfFunctions()->Add(msg); msg->SetName(Form("%s_msg", mo->GetName())); msg->Clear(); - auto reasons = checkResult.getReasons(); - for (int i = 0; i < int(reasons.size()); i++) { - msg->AddText(reasons[i].second.c_str()); - if (i > 4) { - msg->AddText("et al ... "); - break; - } - } + msg->AddText(checkResult.getReasons()[0].second.c_str()); int color = kBlack; if (checkResult == Quality::Good) { color = kGreen + 1; From 664f5267f856bda0051bd9b2903ec0a5977683b8 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Thu, 6 Apr 2023 10:10:42 +0200 Subject: [PATCH 12/33] Align code with clang-format --- Modules/FIT/FV0/include/FV0/CalibrationTask.h | 2 +- Modules/FIT/FV0/include/FV0/GenericCheck.h | 6 ++++-- Modules/FIT/FV0/include/FV0/LinkDef.h | 6 +++--- Modules/FIT/FV0/src/DigitQcTask.cxx | 14 ++++++-------- Modules/FIT/FV0/src/GenericCheck.cxx | 2 +- Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx | 10 +++++----- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Modules/FIT/FV0/include/FV0/CalibrationTask.h b/Modules/FIT/FV0/include/FV0/CalibrationTask.h index 9e3eae0173..fc2fd20085 100644 --- a/Modules/FIT/FV0/include/FV0/CalibrationTask.h +++ b/Modules/FIT/FV0/include/FV0/CalibrationTask.h @@ -64,4 +64,4 @@ class CalibrationTask final : public TaskInterface } // namespace o2::quality_control_modules::fv0 -#endif //QUALITYCONTROL_FV0_CALIBRATIONTASK_H +#endif // QUALITYCONTROL_FV0_CALIBRATIONTASK_H diff --git a/Modules/FIT/FV0/include/FV0/GenericCheck.h b/Modules/FIT/FV0/include/FV0/GenericCheck.h index d23b56e9d5..f88c729195 100644 --- a/Modules/FIT/FV0/include/FV0/GenericCheck.h +++ b/Modules/FIT/FV0/include/FV0/GenericCheck.h @@ -89,11 +89,13 @@ class SingleCheck ILOG(Debug, Support) << log << ENDM; } - float getThresholdWarning() { + float getThresholdWarning() + { return mThresholdWarning; } - float getThresholdError() { + float getThresholdError() + { return mThresholdError; } diff --git a/Modules/FIT/FV0/include/FV0/LinkDef.h b/Modules/FIT/FV0/include/FV0/LinkDef.h index 39af5efa15..c070f5164f 100644 --- a/Modules/FIT/FV0/include/FV0/LinkDef.h +++ b/Modules/FIT/FV0/include/FV0/LinkDef.h @@ -7,11 +7,11 @@ #pragma link C++ class o2::quality_control_modules::fv0::PostProcTask + ; #pragma link C++ class o2::quality_control_modules::fv0::CFDEffCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::OutOfBunchCollCheck + ; -#pragma link C++ class o2::quality_control_modules::fv0::GenericCheck+; +#pragma link C++ class o2::quality_control_modules::fv0::GenericCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::TriggersSwVsTcmCheck + ; //#pragma link C++ class o2::quality_control_modules::fv0::CalibrationTask + ; //#pragma link C++ class o2::quality_control_modules::fv0::ChannelTimeCalibrationCheck + ; -#pragma link C++ class o2::quality_control_modules::fv0::DigitQcTaskLaser+; -#pragma link C++ class o2::quality_control_modules::fv0::TH1ReductorLaser+; +#pragma link C++ class o2::quality_control_modules::fv0::DigitQcTaskLaser + ; +#pragma link C++ class o2::quality_control_modules::fv0::TH1ReductorLaser + ; #endif diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index 6e144e7421..d4f465902f 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -302,8 +302,6 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mSetAllowedChIDsAmpVsTime.insert(entry); } - - for (const auto& chID : mSetAllowedChIDs) { auto pairHistAmp = mMapHistAmp1D.insert({ chID, new TH1F(Form("Amp_channel%i", chID), Form("Amplitude, channel %i", chID), 4200, -100, 4100) }); auto pairHistTime = mMapHistTime1D.insert({ chID, new TH1F(Form("Time_channel%i", chID), Form("Time, channel %i", chID), 4100, -2050, 2050) }); @@ -650,16 +648,16 @@ void DigitQcTask::endOfCycle() ILOG(Debug, Support) << "adding last TF creation time: " << mTFcreationTime << ENDM; getObjectsManager()->getMonitorObject(mHistBCvsTrg->GetName())->addOrUpdateMetadata("TFcreationTime", std::to_string(mTFcreationTime)); - for (int channel = 1; channel <= sNCHANNELS_FV0_PLUSREF-1; channel++) { + for (int channel = 1; channel <= sNCHANNELS_FV0_PLUSREF - 1; channel++) { int events_in_range = 0; int events_per_channel = 0; for (int bin_on_y_axis = 1; bin_on_y_axis <= mHistTime2Ch->GetNbinsY(); bin_on_y_axis++) { - if (std::abs(mHistTime2Ch->GetYaxis()->GetBinLowEdge(bin_on_y_axis)) < mTimeGate) { - events_in_range += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); - } - events_per_channel += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); + if (std::abs(mHistTime2Ch->GetYaxis()->GetBinLowEdge(bin_on_y_axis)) < mTimeGate) { + events_in_range += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); + } + events_per_channel += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); } - mHistGateTimeRatio2Ch->SetBinContent(channel, (float) events_in_range / (float) events_per_channel); + mHistGateTimeRatio2Ch->SetBinContent(channel, (float)events_in_range / (float)events_per_channel); } // one has to set num. of entries manually because diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index 1c3a770bb8..6aae0ebb12 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -241,7 +241,7 @@ void GenericCheck::beautify(std::shared_ptr mo, Quality checkResu h->GetListOfFunctions()->Add(msg); // add threshold lines - if(mCheckMinThresholdY.isActive()) { + if (mCheckMinThresholdY.isActive()) { Double_t xMin = h->GetXaxis()->GetXmin(); Double_t xMax = h->GetXaxis()->GetXmax(); auto* lineMinError = new TLine(xMin, mCheckMinThresholdY.getThresholdError(), xMax, mCheckMinThresholdY.getThresholdError()); diff --git a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx index b8535b6175..d336eb36da 100644 --- a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx +++ b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx @@ -36,14 +36,15 @@ namespace o2::quality_control_modules::fv0 constexpr int kBinSwOnly = 1; constexpr int kBinTcmOnly = 2; -void TriggersSwVsTcmCheck::configure() { +void TriggersSwVsTcmCheck::configure() +{ if (auto param = mCustomParameters.find("ccdbUrl"); param != mCustomParameters.end()) { setCcdbUrl(param->second); ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, configured url = " << param->second << ENDM; } else { setCcdbUrl("o2-ccdb.internal"); ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, default url = " - << "o2-ccdb.internal" << ENDM; + << "o2-ccdb.internal" << ENDM; } mPositionMsgBox = { 0.15, 0.75, 0.85, 0.9 }; @@ -82,10 +83,9 @@ Quality TriggersSwVsTcmCheck::check(std::mapGetBinContent(binId, kBinSwOnly)) || (bool)(histogram->GetBinContent(binId, kBinTcmOnly))) { mNumErrors++; if (result.isBetterThan(Quality::Bad)) { - result.set(Quality::Bad); + result.set(Quality::Bad); } - result.addReason(FlagReasonFactory::Unknown(), - "Only SW or TCM trigger was activated"); + result.addReason(FlagReasonFactory::Unknown(), "Only SW or TCM trigger was activated"); } } } From 0d913f7da21450d1ee32dbb3ccf3189f1f6e8253 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Tue, 11 Apr 2023 19:13:23 +0200 Subject: [PATCH 13/33] Fix the filling of the EventInGateTime hist Add parametrization of both min and max gate time for EventInGateTime hist. --- Modules/FIT/FV0/include/FV0/DigitQcTask.h | 3 ++- Modules/FIT/FV0/src/DigitQcTask.cxx | 17 +++++++++++------ Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx | 17 +++++++++++++++-- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Modules/FIT/FV0/include/FV0/DigitQcTask.h b/Modules/FIT/FV0/include/FV0/DigitQcTask.h index 25e7d3d644..2b576cd89a 100644 --- a/Modules/FIT/FV0/include/FV0/DigitQcTask.h +++ b/Modules/FIT/FV0/include/FV0/DigitQcTask.h @@ -81,7 +81,8 @@ class DigitQcTask final : public TaskInterface long mTFcreationTime = 0; - int mTimeGate = 192; + int mMinTimeGate = -192; + int mMaxTimeGate = 192; template ::value || diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index d4f465902f..7f120003c6 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -170,7 +170,8 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mTrgChargeLevelHigh = getNumericalParameter("trgChargeLevelHigh", 4095); mTrgThresholdCharge = getNumericalParameter("trgThresholdCharge", 1); mTrgThresholdNChannels = getNumericalParameter("trgThresholdNChannels", 1); - mTimeGate = getNumericalParameter("gateTimeForRatioHistogram", 192); + mMinTimeGate = getNumericalParameter("minGateTimeForRatioHistogram", -192); + mMaxTimeGate = getNumericalParameter("maxGateTimeForRatioHistogram", 192); if (mTrgModeInnerOuterThresholdVar == TrgModeThresholdVar::kAmpl) { mTrgThresholdChargeInner = getNumericalParameter("trgThresholdChargeInner", 1); @@ -280,7 +281,7 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistCycleDurationNTF = std::make_unique("CycleDurationNTF", "Cycle Duration;;time [TimeFrames]", 1, 0, 2); mHistCycleDurationRange = std::make_unique("CycleDurationRange", "Cycle Duration (total cycle range);;time [ns]", 1, 0, 2); - std::string gateTimeRatioTitle = "Ratio of events between time -" + std::to_string(mTimeGate) + " and " + std::to_string(mTimeGate); + std::string gateTimeRatioTitle = "Ratio of events between time " + std::to_string(mMinTimeGate) + " and " + std::to_string(mMaxTimeGate); mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", gateTimeRatioTitle.c_str(), sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); std::vector vecChannelIDs; @@ -649,15 +650,19 @@ void DigitQcTask::endOfCycle() getObjectsManager()->getMonitorObject(mHistBCvsTrg->GetName())->addOrUpdateMetadata("TFcreationTime", std::to_string(mTFcreationTime)); for (int channel = 1; channel <= sNCHANNELS_FV0_PLUSREF - 1; channel++) { - int events_in_range = 0; - int events_per_channel = 0; + float events_in_range = 0; + float events_per_channel = 0; for (int bin_on_y_axis = 1; bin_on_y_axis <= mHistTime2Ch->GetNbinsY(); bin_on_y_axis++) { - if (std::abs(mHistTime2Ch->GetYaxis()->GetBinLowEdge(bin_on_y_axis)) < mTimeGate) { + if (mHistTime2Ch->GetYaxis()->GetBinLowEdge(bin_on_y_axis) > mMinTimeGate && mHistTime2Ch->GetYaxis()->GetBinLowEdge(bin_on_y_axis) < mMaxTimeGate) { events_in_range += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); } events_per_channel += mHistTime2Ch->GetBinContent(channel, bin_on_y_axis); } - mHistGateTimeRatio2Ch->SetBinContent(channel, (float)events_in_range / (float)events_per_channel); + if (events_per_channel) { + mHistGateTimeRatio2Ch->SetBinContent(channel, events_in_range / events_per_channel); + } else { + mHistGateTimeRatio2Ch->SetBinContent(channel, 0); + } } // one has to set num. of entries manually because diff --git a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx index d336eb36da..f00f5033b1 100644 --- a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx +++ b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx @@ -76,7 +76,15 @@ Quality TriggersSwVsTcmCheck::check(std::mapgetName() == "TriggersSoftwareVsTCM") { - auto* histogram = dynamic_cast(mo->getObject()); + auto* histogram = dynamic_cast(mo->getObject()); + + if (!histogram) { + ILOG(Error, Support) << "check(): MO TriggersSoftwareVsTCM not found" << ENDM; + result.addReason(FlagReasonFactory::Unknown(), "MO TriggersSoftwareVsTCM not found"); + result.set(Quality::Null); + return result; + } + result = Quality::Good; int numberOfBinsX = histogram->GetNbinsX(); for (int binId = 1; binId <= numberOfBinsX; binId++) { @@ -99,7 +107,12 @@ std::string TriggersSwVsTcmCheck::getAcceptedType() { return "TH2"; } void TriggersSwVsTcmCheck::beautify(std::shared_ptr mo, Quality checkResult) { if (mo->getName() == "TriggersSoftwareVsTCM") { - auto* histogram = dynamic_cast(mo->getObject()); + auto* histogram = dynamic_cast(mo->getObject()); + + if (!histogram) { + ILOG(Error, Support) << "beautify(): MO TriggersSoftwareVsTCM not found" << ENDM; + return; + } TPaveText* msg = new TPaveText(mPositionMsgBox[0], mPositionMsgBox[1], mPositionMsgBox[2], mPositionMsgBox[3], "NDC"); histogram->GetListOfFunctions()->Add(msg); From 008477b9127abb57d4c06281c88bd33ba768f7aa Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Tue, 11 Apr 2023 19:23:48 +0200 Subject: [PATCH 14/33] Remove unused import --- Modules/FIT/FV0/src/DigitQcTask.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index 7f120003c6..3bdc371a75 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -25,8 +25,6 @@ #include "Framework/TimingInfo.h" #include "DataFormatsFV0/LookUpTable.h" -#include - namespace o2::quality_control_modules::fv0 { From c8cdf063285a00e8e9b1b8ad77902cf78512cd63 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Thu, 13 Apr 2023 21:31:56 +0200 Subject: [PATCH 15/33] Use DeadChannelMap in GenericCheck --- Modules/FIT/FV0/include/FV0/GenericCheck.h | 8 +++ Modules/FIT/FV0/src/GenericCheck.cxx | 61 ++++++++++++++++++++-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/Modules/FIT/FV0/include/FV0/GenericCheck.h b/Modules/FIT/FV0/include/FV0/GenericCheck.h index f88c729195..6e0b75eafb 100644 --- a/Modules/FIT/FV0/include/FV0/GenericCheck.h +++ b/Modules/FIT/FV0/include/FV0/GenericCheck.h @@ -18,8 +18,11 @@ #define QC_MODULE_FV0_FV0GENERICCHECK_H #include "QualityControl/CheckInterface.h" +#include "FV0Base/Constants.h" +#include "DataFormatsFIT/DeadChannelMap.h" #include + namespace o2::quality_control_modules::fv0 { @@ -149,6 +152,11 @@ class GenericCheck : public o2::quality_control::checker::CheckInterface std::array mPositionMsgBox; std::string mNameObjOnCanvas; + + constexpr static std::size_t sNCHANNELS = o2::fv0::Constants::nFv0Channels; + o2::fit::DeadChannelMap* mDeadChannelMap; + std::string mDeadChannelMapStr; + std::string mPathDeadChannelMap; }; } // namespace o2::quality_control_modules::fv0 diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index 6aae0ebb12..c2d8408dc3 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -82,6 +82,47 @@ void GenericCheck::configure() mCheckMinGraphLastPoint = getCheckFromConfig("MinGraphLastPoint"); mCheckMaxGraphLastPoint = getCheckFromConfig("MaxGraphLastPoint"); + // Set path to ccdb to get DeadChannelMap + if (auto param = mCustomParameters.find("ccdbUrl"); param != mCustomParameters.end()) { + setCcdbUrl(param->second); + ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, configured url = " << param->second << ENDM; + } else { + setCcdbUrl("alice-ccdb.cern.ch"); + ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, default url = " + << "alice-ccdb.cern.ch" << ENDM; + } + + // Set internal path to DeadChannelMap + if (auto param = mCustomParameters.find("pathDeadChannelMap"); param != mCustomParameters.end()) { + mPathDeadChannelMap = param->second; + ILOG(Debug, Support) << "configure() : using pathDeadChannelMap: " << mPathDeadChannelMap << ENDM; + } else { + mPathDeadChannelMap = "FV0/Calib/DeadChannelMap"; + ILOG(Debug, Support) << "configure() : using default pathDeadChannelMap: " << mPathDeadChannelMap << ENDM; + } + + // Align mDeadChannelMap with downloaded one + std::map metadata; + mDeadChannelMap = retrieveConditionAny(mPathDeadChannelMap, metadata, (long)-1); + if (!mDeadChannelMap->map.size()) { + ILOG(Error, Support) << "object \"" << mPathDeadChannelMap << "\" NOT retrieved (or empty). All channels assumed to be alive!" << ENDM; + mDeadChannelMap = new o2::fit::DeadChannelMap(); + for (uint8_t chId = 0; chId < sNCHANNELS; ++chId) { + mDeadChannelMap->setChannelAlive(chId, 1); + } + } + + // Print DeadChannelMap + mDeadChannelMapStr = ""; + for (unsigned chId = 0; chId < mDeadChannelMap->map.size(); chId++) { + if (!mDeadChannelMap->isChannelAlive(chId)) { + mDeadChannelMapStr += (mDeadChannelMapStr.empty() ? "" : ",") + std::to_string(chId); + } + } + if (mDeadChannelMapStr.empty()) + mDeadChannelMapStr = "EMPTY"; + ILOG(Info, Support) << "Loaded dead channel map: " << mDeadChannelMapStr << ENDM; + mPositionMsgBox = { 0.15, 0.75, 0.85, 0.9 }; if (auto param = mCustomParameters.find("positionMsgBox"); param != mCustomParameters.end()) { stringstream ss(param->second); @@ -158,9 +199,10 @@ Quality GenericCheck::check(std::map } if (mCheckMinThresholdY.isActive()) { - int numberOfBinsX = h->GetNbinsX(); float minValue = h->GetBinContent(1); - for (int channel = 1; channel < numberOfBinsX; ++channel) { + for (int channel = 1; channel < h->GetNbinsX(); ++channel) { + if (channel >= sNCHANNELS || !mDeadChannelMap->isChannelAlive(channel)) + continue; if (minValue > h->GetBinContent(channel)) { minValue = h->GetBinContent(channel); mCheckMinThresholdY.mBinNumberX = channel; @@ -171,8 +213,19 @@ Quality GenericCheck::check(std::map if (mCheckMaxThresholdY.isActive()) { mCheckMaxThresholdY.mBinNumberX = h->GetMaximumBin(); - float maxValue = h->GetBinContent(mCheckMaxThresholdY.mBinNumberX); - mCheckMaxThresholdY.doCheck(result, maxValue); + if (mDeadChannelMap->isChannelAlive(mCheckMaxThresholdY.mBinNumberX)) { + mCheckMaxThresholdY.doCheck(result, h->GetBinContent(mCheckMaxThresholdY.mBinNumberX)); + } else { + float maxValue = h->GetBinContent(1); + for (int channel = 1; channel < h->GetNbinsX(); ++channel) { + if (channel >= sNCHANNELS || !mDeadChannelMap->isChannelAlive(channel)) + continue; + if (maxValue < h->GetBinContent(channel)) { + maxValue = h->GetBinContent(channel); + mCheckMinThresholdY.mBinNumberX = channel; + } + } + } } if (mCheckMinMeanX.isActive()) From f4d64ba94969bec39c5c62939e93c3fd37474612 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Thu, 13 Apr 2023 21:53:26 +0200 Subject: [PATCH 16/33] Add stub of a BcCheck --- Modules/FIT/FV0/CMakeLists.txt | 4 ++- Modules/FIT/FV0/include/FV0/BcCheck.h | 46 +++++++++++++++++++++++++++ Modules/FIT/FV0/include/FV0/LinkDef.h | 1 + Modules/FIT/FV0/src/BcCheck.cxx | 45 ++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 Modules/FIT/FV0/include/FV0/BcCheck.h create mode 100644 Modules/FIT/FV0/src/BcCheck.cxx diff --git a/Modules/FIT/FV0/CMakeLists.txt b/Modules/FIT/FV0/CMakeLists.txt index 23355145e7..ea4b094f38 100644 --- a/Modules/FIT/FV0/CMakeLists.txt +++ b/Modules/FIT/FV0/CMakeLists.txt @@ -9,7 +9,8 @@ target_sources(O2QcFV0 PRIVATE src/TH1ReductorLaser.cxx src/CFDEffCheck.cxx src/PostProcTask.cxx src/OutOfBunchCollCheck.cxx - src/TriggersSwVsTcmCheck.cxx) + src/TriggersSwVsTcmCheck.cxx + src/BcCheck.cxx) target_include_directories( O2QcFV0 @@ -37,6 +38,7 @@ add_root_dictionary(O2QcFV0 include/FV0/OutOfBunchCollCheck.h include/FV0/GenericCheck.h include/FV0/TriggersSwVsTcmCheck.h + include/FV0/BcCheck.h LINKDEF include/FV0/LinkDef.h) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/FV0 diff --git a/Modules/FIT/FV0/include/FV0/BcCheck.h b/Modules/FIT/FV0/include/FV0/BcCheck.h new file mode 100644 index 0000000000..f215d4a2ba --- /dev/null +++ b/Modules/FIT/FV0/include/FV0/BcCheck.h @@ -0,0 +1,46 @@ +// Copyright 2023 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 BcCheck.h +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +/// + +#ifndef QC_MODULE_FV0_BCCHECK_H +#define QC_MODULE_FV0_BCCHECK_H + +#include "QualityControl/CheckInterface.h" + +#include "FV0Base/Constants.h" + +namespace o2::quality_control_modules::fv0 +{ + +class BcCheck : public o2::quality_control::checker::CheckInterface +{ + public: + BcCheck() = default; + ~BcCheck() override = default; + + void configure() override; + Quality check(std::map>* moMap) override; + void beautify(std::shared_ptr mo, Quality checkResult = Quality::Null) override; + std::string getAcceptedType() override; + + ClassDefOverride(BcCheck, 2); + + private: + std::array mPositionMsgBox; +}; + +} // namespace o2::quality_control_modules::fv0 + +#endif // QC_MODULE_FV0_BCCHECK_H diff --git a/Modules/FIT/FV0/include/FV0/LinkDef.h b/Modules/FIT/FV0/include/FV0/LinkDef.h index c070f5164f..f59fec1468 100644 --- a/Modules/FIT/FV0/include/FV0/LinkDef.h +++ b/Modules/FIT/FV0/include/FV0/LinkDef.h @@ -9,6 +9,7 @@ #pragma link C++ class o2::quality_control_modules::fv0::OutOfBunchCollCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::GenericCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::TriggersSwVsTcmCheck + ; +#pragma link C++ class o2::quality_control_modules::fv0::BcCheck + ; //#pragma link C++ class o2::quality_control_modules::fv0::CalibrationTask + ; //#pragma link C++ class o2::quality_control_modules::fv0::ChannelTimeCalibrationCheck + ; diff --git a/Modules/FIT/FV0/src/BcCheck.cxx b/Modules/FIT/FV0/src/BcCheck.cxx new file mode 100644 index 0000000000..4460df826d --- /dev/null +++ b/Modules/FIT/FV0/src/BcCheck.cxx @@ -0,0 +1,45 @@ +// Copyright 2023 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 BcCheck.cxx +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +/// + +#include "FV0/BcCheck.h" + +using namespace std; +using namespace o2::quality_control; + +namespace o2::quality_control_modules::fv0 +{ + +constexpr int kBinSwOnly = 1; +constexpr int kBinTcmOnly = 2; + +void BcCheck::configure() +{ + +} + +Quality BcCheck::check(std::map>* moMap) +{ + +} + +std::string BcCheck::getAcceptedType() { return "TH2"; } + +void BcCheck::beautify(std::shared_ptr mo, Quality checkResult) +{ + +} + +} // namespace o2::quality_control_modules::fv0 From e5c931a38c6c9e55175494e4c644e5dc213941d2 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Thu, 13 Apr 2023 22:47:37 +0200 Subject: [PATCH 17/33] Extend BcCheck --- Modules/FIT/FV0/include/FV0/BcCheck.h | 3 +- Modules/FIT/FV0/src/BcCheck.cxx | 53 +++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/Modules/FIT/FV0/include/FV0/BcCheck.h b/Modules/FIT/FV0/include/FV0/BcCheck.h index f215d4a2ba..f795b0b69f 100644 --- a/Modules/FIT/FV0/include/FV0/BcCheck.h +++ b/Modules/FIT/FV0/include/FV0/BcCheck.h @@ -19,8 +19,6 @@ #include "QualityControl/CheckInterface.h" -#include "FV0Base/Constants.h" - namespace o2::quality_control_modules::fv0 { @@ -39,6 +37,7 @@ class BcCheck : public o2::quality_control::checker::CheckInterface private: std::array mPositionMsgBox; + TH2F* mBcPattern; }; } // namespace o2::quality_control_modules::fv0 diff --git a/Modules/FIT/FV0/src/BcCheck.cxx b/Modules/FIT/FV0/src/BcCheck.cxx index 4460df826d..556186ab1e 100644 --- a/Modules/FIT/FV0/src/BcCheck.cxx +++ b/Modules/FIT/FV0/src/BcCheck.cxx @@ -15,6 +15,10 @@ /// #include "FV0/BcCheck.h" +#include "QualityControl/QcInfoLogger.h" +#include "QualityControl/Quality.h" +#include +#include using namespace std; using namespace o2::quality_control; @@ -22,9 +26,6 @@ using namespace o2::quality_control; namespace o2::quality_control_modules::fv0 { -constexpr int kBinSwOnly = 1; -constexpr int kBinTcmOnly = 2; - void BcCheck::configure() { @@ -32,14 +33,58 @@ void BcCheck::configure() Quality BcCheck::check(std::map>* moMap) { + Quality result = Quality::Null; + for (auto& [moName, mo] : *moMap) { + (void)moName; + if (mo->getName() == "BCvsFEEmodules" || mo->getName() == "BCvsTriggers") { + auto* histogram = dynamic_cast(mo->getObject()); + + if (!histogram) { + ILOG(Error, Support) << "check(): MO " << mo->getName() << " not found" << ENDM; + result.addReason(FlagReasonFactory::Unknown(), "MO " + mo->getName() + " not found"); + result.set(Quality::Null); + return result; + } + for (int channel = 1; channel < h->GetNbinsX(); ++channel) { + + } + } + } } std::string BcCheck::getAcceptedType() { return "TH2"; } void BcCheck::beautify(std::shared_ptr mo, Quality checkResult) { + if (mo->getName() == "BCvsFEEmodules" || mo->getName() == "BCvsTriggers") { -} + auto* histogram = dynamic_cast(mo->getObject()); + + if (!histogram) { + ILOG(Error, Support) << "beautify(): MO " << mo->getName() << " not found" << ENDM; + return; + } + + TPaveText* msg = new TPaveText(0.15, 0.2, 0.85, 0.45, "NDC"); + histogram->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + msg->Clear(); + if (checkResult == Quality::Good) { + msg->AddText(">> Quality::Good <<"); + msg->SetFillColor(kGreen); + } else if (checkResult == Quality::Bad) { + auto reasons = checkResult.getReasons(); + msg->SetFillColor(kRed); + msg->AddText(">> Quality::Bad <<"); + } else if (checkResult == Quality::Medium) { + auto reasons = checkResult.getReasons(); + msg->SetFillColor(kOrange); + msg->AddText(">> Quality::Medium <<"); + } else if (checkResult == Quality::Null) { + msg->AddText(">> Quality::Null <<"); + msg->SetFillColor(kGray); + } + } } // namespace o2::quality_control_modules::fv0 From 51e16e0b33af72cf344b4e20216176818318e950 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Thu, 13 Apr 2023 22:57:25 +0200 Subject: [PATCH 18/33] Fix build errors for BcCheck --- Modules/FIT/FV0/include/FV0/BcCheck.h | 1 + Modules/FIT/FV0/src/BcCheck.cxx | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Modules/FIT/FV0/include/FV0/BcCheck.h b/Modules/FIT/FV0/include/FV0/BcCheck.h index f795b0b69f..b077b382f4 100644 --- a/Modules/FIT/FV0/include/FV0/BcCheck.h +++ b/Modules/FIT/FV0/include/FV0/BcCheck.h @@ -17,6 +17,7 @@ #ifndef QC_MODULE_FV0_BCCHECK_H #define QC_MODULE_FV0_BCCHECK_H +#include #include "QualityControl/CheckInterface.h" namespace o2::quality_control_modules::fv0 diff --git a/Modules/FIT/FV0/src/BcCheck.cxx b/Modules/FIT/FV0/src/BcCheck.cxx index 556186ab1e..c183031af9 100644 --- a/Modules/FIT/FV0/src/BcCheck.cxx +++ b/Modules/FIT/FV0/src/BcCheck.cxx @@ -14,9 +14,11 @@ /// \author Dawid Skora dawid.mateusz.skora@cern.ch /// +#include "QualityControl/MonitorObject.h" #include "FV0/BcCheck.h" #include "QualityControl/QcInfoLogger.h" #include "QualityControl/Quality.h" +#include #include #include @@ -46,7 +48,7 @@ Quality BcCheck::check(std::map>* mo return result; } - for (int channel = 1; channel < h->GetNbinsX(); ++channel) { + for (int channel = 1; channel < histogram->GetNbinsX(); ++channel) { } } @@ -87,4 +89,5 @@ void BcCheck::beautify(std::shared_ptr mo, Quality checkResult) msg->SetFillColor(kGray); } } +} } // namespace o2::quality_control_modules::fv0 From 0f0ea4f05771537d2db5a2d8b48732e066cc3379 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Sun, 16 Apr 2023 19:20:37 +0200 Subject: [PATCH 19/33] Change hist title and add axis label --- Modules/FIT/FV0/src/DigitQcTask.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index 3bdc371a75..ba8b91219f 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -279,8 +279,7 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistCycleDurationNTF = std::make_unique("CycleDurationNTF", "Cycle Duration;;time [TimeFrames]", 1, 0, 2); mHistCycleDurationRange = std::make_unique("CycleDurationRange", "Cycle Duration (total cycle range);;time [ns]", 1, 0, 2); - std::string gateTimeRatioTitle = "Ratio of events between time " + std::to_string(mMinTimeGate) + " and " + std::to_string(mMaxTimeGate); - mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", gateTimeRatioTitle.c_str(), sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); + mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", "Ratio of events in gate time;Channel ID;Ratio", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); std::vector vecChannelIDs; if (auto param = mCustomParameters.find("ChannelIDs"); param != mCustomParameters.end()) { From 2a221f997a5b67b3a2cdb09738c94f3a30803204 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Sun, 16 Apr 2023 22:56:47 +0200 Subject: [PATCH 20/33] Fix MaxTreshold in GenericCheck. Test DeadChannelMap --- Modules/FIT/FV0/src/DigitQcTask.cxx | 1 - Modules/FIT/FV0/src/GenericCheck.cxx | 11 ++++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index ba8b91219f..b48f706ebe 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -278,7 +278,6 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistCycleDuration = std::make_unique("CycleDuration", "Cycle Duration;;time [ns]", 1, 0, 2); mHistCycleDurationNTF = std::make_unique("CycleDurationNTF", "Cycle Duration;;time [TimeFrames]", 1, 0, 2); mHistCycleDurationRange = std::make_unique("CycleDurationRange", "Cycle Duration (total cycle range);;time [ns]", 1, 0, 2); - mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", "Ratio of events in gate time;Channel ID;Ratio", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); std::vector vecChannelIDs; diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index c2d8408dc3..9449ff6f05 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -18,6 +18,7 @@ #include "QualityControl/MonitorObject.h" #include "QualityControl/Quality.h" #include "QualityControl/QcInfoLogger.h" +#include // ROOT #include #include @@ -27,7 +28,6 @@ #include #include #include - #include using namespace std; @@ -212,19 +212,20 @@ Quality GenericCheck::check(std::map } if (mCheckMaxThresholdY.isActive()) { - mCheckMaxThresholdY.mBinNumberX = h->GetMaximumBin(); - if (mDeadChannelMap->isChannelAlive(mCheckMaxThresholdY.mBinNumberX)) { + if (mDeadChannelMap->isChannelAlive(h->GetMaximumBin())) { + mCheckMaxThresholdY.mBinNumberX = h->GetMaximumBin(); mCheckMaxThresholdY.doCheck(result, h->GetBinContent(mCheckMaxThresholdY.mBinNumberX)); } else { - float maxValue = h->GetBinContent(1); + float maxValue = 0; for (int channel = 1; channel < h->GetNbinsX(); ++channel) { if (channel >= sNCHANNELS || !mDeadChannelMap->isChannelAlive(channel)) continue; if (maxValue < h->GetBinContent(channel)) { maxValue = h->GetBinContent(channel); - mCheckMinThresholdY.mBinNumberX = channel; + mCheckMaxThresholdY.mBinNumberX = channel; } } + mCheckMaxThresholdY.doCheck(result, maxValue); } } From e387e56381b853ad2f121d2c4ec45d89be509631 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Tue, 18 Apr 2023 18:40:18 +0200 Subject: [PATCH 21/33] Change axis labels for EventsInGateTime --- Modules/FIT/FV0/src/DigitQcTask.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FIT/FV0/src/DigitQcTask.cxx b/Modules/FIT/FV0/src/DigitQcTask.cxx index b48f706ebe..efa9bb01e9 100644 --- a/Modules/FIT/FV0/src/DigitQcTask.cxx +++ b/Modules/FIT/FV0/src/DigitQcTask.cxx @@ -278,7 +278,7 @@ void DigitQcTask::initialize(o2::framework::InitContext& /*ctx*/) mHistCycleDuration = std::make_unique("CycleDuration", "Cycle Duration;;time [ns]", 1, 0, 2); mHistCycleDurationNTF = std::make_unique("CycleDurationNTF", "Cycle Duration;;time [TimeFrames]", 1, 0, 2); mHistCycleDurationRange = std::make_unique("CycleDurationRange", "Cycle Duration (total cycle range);;time [ns]", 1, 0, 2); - mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", "Ratio of events in gate time;Channel ID;Ratio", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); + mHistGateTimeRatio2Ch = std::make_unique("EventsInGateTime", "Fraction of events in CFD time gate per channel;Channel ID;Event fraction in CFD time gate", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); std::vector vecChannelIDs; if (auto param = mCustomParameters.find("ChannelIDs"); param != mCustomParameters.end()) { From 6895da9e4d22f924bc46ed61880d5cfb15d3ad65 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Tue, 18 Apr 2023 18:47:00 +0200 Subject: [PATCH 22/33] Remove unused files --- Modules/FIT/FV0/CMakeLists.txt | 4 +- Modules/FIT/FV0/include/FV0/BcCheck.h | 46 ----------- Modules/FIT/FV0/include/FV0/LinkDef.h | 1 - Modules/FIT/FV0/include/FV0/LinkDef.h.gch | Bin 0 -> 207932 bytes Modules/FIT/FV0/src/BcCheck.cxx | 93 ---------------------- 5 files changed, 1 insertion(+), 143 deletions(-) delete mode 100644 Modules/FIT/FV0/include/FV0/BcCheck.h create mode 100644 Modules/FIT/FV0/include/FV0/LinkDef.h.gch delete mode 100644 Modules/FIT/FV0/src/BcCheck.cxx diff --git a/Modules/FIT/FV0/CMakeLists.txt b/Modules/FIT/FV0/CMakeLists.txt index ea4b094f38..23355145e7 100644 --- a/Modules/FIT/FV0/CMakeLists.txt +++ b/Modules/FIT/FV0/CMakeLists.txt @@ -9,8 +9,7 @@ target_sources(O2QcFV0 PRIVATE src/TH1ReductorLaser.cxx src/CFDEffCheck.cxx src/PostProcTask.cxx src/OutOfBunchCollCheck.cxx - src/TriggersSwVsTcmCheck.cxx - src/BcCheck.cxx) + src/TriggersSwVsTcmCheck.cxx) target_include_directories( O2QcFV0 @@ -38,7 +37,6 @@ add_root_dictionary(O2QcFV0 include/FV0/OutOfBunchCollCheck.h include/FV0/GenericCheck.h include/FV0/TriggersSwVsTcmCheck.h - include/FV0/BcCheck.h LINKDEF include/FV0/LinkDef.h) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/FV0 diff --git a/Modules/FIT/FV0/include/FV0/BcCheck.h b/Modules/FIT/FV0/include/FV0/BcCheck.h deleted file mode 100644 index b077b382f4..0000000000 --- a/Modules/FIT/FV0/include/FV0/BcCheck.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2023 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 BcCheck.h -/// \author Dawid Skora dawid.mateusz.skora@cern.ch -/// - -#ifndef QC_MODULE_FV0_BCCHECK_H -#define QC_MODULE_FV0_BCCHECK_H - -#include -#include "QualityControl/CheckInterface.h" - -namespace o2::quality_control_modules::fv0 -{ - -class BcCheck : public o2::quality_control::checker::CheckInterface -{ - public: - BcCheck() = default; - ~BcCheck() override = default; - - void configure() override; - Quality check(std::map>* moMap) override; - void beautify(std::shared_ptr mo, Quality checkResult = Quality::Null) override; - std::string getAcceptedType() override; - - ClassDefOverride(BcCheck, 2); - - private: - std::array mPositionMsgBox; - TH2F* mBcPattern; -}; - -} // namespace o2::quality_control_modules::fv0 - -#endif // QC_MODULE_FV0_BCCHECK_H diff --git a/Modules/FIT/FV0/include/FV0/LinkDef.h b/Modules/FIT/FV0/include/FV0/LinkDef.h index f59fec1468..c070f5164f 100644 --- a/Modules/FIT/FV0/include/FV0/LinkDef.h +++ b/Modules/FIT/FV0/include/FV0/LinkDef.h @@ -9,7 +9,6 @@ #pragma link C++ class o2::quality_control_modules::fv0::OutOfBunchCollCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::GenericCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::TriggersSwVsTcmCheck + ; -#pragma link C++ class o2::quality_control_modules::fv0::BcCheck + ; //#pragma link C++ class o2::quality_control_modules::fv0::CalibrationTask + ; //#pragma link C++ class o2::quality_control_modules::fv0::ChannelTimeCalibrationCheck + ; diff --git a/Modules/FIT/FV0/include/FV0/LinkDef.h.gch b/Modules/FIT/FV0/include/FV0/LinkDef.h.gch new file mode 100644 index 0000000000000000000000000000000000000000..8b616b66a289974541b5daaf1b0e1339188fbbde GIT binary patch literal 207932 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 -#include -#include - -using namespace std; -using namespace o2::quality_control; - -namespace o2::quality_control_modules::fv0 -{ - -void BcCheck::configure() -{ - -} - -Quality BcCheck::check(std::map>* moMap) -{ - Quality result = Quality::Null; - for (auto& [moName, mo] : *moMap) { - (void)moName; - if (mo->getName() == "BCvsFEEmodules" || mo->getName() == "BCvsTriggers") { - auto* histogram = dynamic_cast(mo->getObject()); - - if (!histogram) { - ILOG(Error, Support) << "check(): MO " << mo->getName() << " not found" << ENDM; - result.addReason(FlagReasonFactory::Unknown(), "MO " + mo->getName() + " not found"); - result.set(Quality::Null); - return result; - } - - for (int channel = 1; channel < histogram->GetNbinsX(); ++channel) { - - } - } - } -} - -std::string BcCheck::getAcceptedType() { return "TH2"; } - -void BcCheck::beautify(std::shared_ptr mo, Quality checkResult) -{ - if (mo->getName() == "BCvsFEEmodules" || mo->getName() == "BCvsTriggers") { - - auto* histogram = dynamic_cast(mo->getObject()); - - if (!histogram) { - ILOG(Error, Support) << "beautify(): MO " << mo->getName() << " not found" << ENDM; - return; - } - - TPaveText* msg = new TPaveText(0.15, 0.2, 0.85, 0.45, "NDC"); - histogram->GetListOfFunctions()->Add(msg); - msg->SetName(Form("%s_msg", mo->GetName())); - msg->Clear(); - - if (checkResult == Quality::Good) { - msg->AddText(">> Quality::Good <<"); - msg->SetFillColor(kGreen); - } else if (checkResult == Quality::Bad) { - auto reasons = checkResult.getReasons(); - msg->SetFillColor(kRed); - msg->AddText(">> Quality::Bad <<"); - } else if (checkResult == Quality::Medium) { - auto reasons = checkResult.getReasons(); - msg->SetFillColor(kOrange); - msg->AddText(">> Quality::Medium <<"); - } else if (checkResult == Quality::Null) { - msg->AddText(">> Quality::Null <<"); - msg->SetFillColor(kGray); - } - } -} -} // namespace o2::quality_control_modules::fv0 From 594a4882c7f44c478e18b2b78bb7ef04a0818ae1 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Tue, 18 Apr 2023 19:05:06 +0200 Subject: [PATCH 23/33] Fix clang format error --- Modules/FIT/FV0/include/FV0/GenericCheck.h | 1 - Modules/FIT/FV0/src/GenericCheck.cxx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Modules/FIT/FV0/include/FV0/GenericCheck.h b/Modules/FIT/FV0/include/FV0/GenericCheck.h index 6e0b75eafb..b874babf8c 100644 --- a/Modules/FIT/FV0/include/FV0/GenericCheck.h +++ b/Modules/FIT/FV0/include/FV0/GenericCheck.h @@ -22,7 +22,6 @@ #include "DataFormatsFIT/DeadChannelMap.h" #include - namespace o2::quality_control_modules::fv0 { diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index 9449ff6f05..4e8ba4a851 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -89,7 +89,7 @@ void GenericCheck::configure() } else { setCcdbUrl("alice-ccdb.cern.ch"); ILOG(Debug, Support) << "configure() : using deadChannelMap from CCDB, default url = " - << "alice-ccdb.cern.ch" << ENDM; + << "alice-ccdb.cern.ch" << ENDM; } // Set internal path to DeadChannelMap From f2deb06281c4725afdf00cbb14ec9e1feeef63e3 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Tue, 18 Apr 2023 19:08:05 +0200 Subject: [PATCH 24/33] Remove unused file --- Modules/FIT/FV0/include/FV0/LinkDef.h.gch | Bin 207932 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Modules/FIT/FV0/include/FV0/LinkDef.h.gch diff --git a/Modules/FIT/FV0/include/FV0/LinkDef.h.gch b/Modules/FIT/FV0/include/FV0/LinkDef.h.gch deleted file mode 100644 index 8b616b66a289974541b5daaf1b0e1339188fbbde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 207932 zcmb?^30%zU+xI;)HPuWtMNzh!mEoMY_kVeC8a_r7O_;+*ICeBSr<`Cm@W?|WbOwO`kL|Hku#NJDyY%n5N3 z5@J@izbaSbS;F>^QjJ@YCZt}m#Jx)5mM3w;-+{h8JxjUn7r36wH9jR0 zH#`gM-uvrEc@mFGiF+>ByHw$IOT(L8tnti~c&jAtA0(c$xn3U>?wjdSp37#5r&{A# z$@M;~$!-JiW{vx11t6YANJ#fOpK`r&xgH<50C@#=Kj~R1@mMGEfB=v*U*f?w@W|7Y z$AF1i;$8LSQ;lc7!u>2X(0Da5sg^t!sDgysb%Nc#!V_XakxsBlB@hi%3ktM?ZBk)D zvS5o&xQ7Uf^8|aeg8e$3d9jUPA3hBdp3r?=D!L#OY*$n4{ygFSAmNrOL7m49vIJXf z1e>LTeLzSB1!CbQd0oU1j&Pq;pb`uB_zJf83iszS+Z2=og6<{7W~w|a9uW^25ZnqawC^8#OCu}-*AEx=wob!wC1JfTWT#n~zoK)Pa` z+8m;8QrG@SY_&Z|uth6?A-3iTwuq_vM!1drx6guv1u&*mAX+<6Ky4@%7Uc;~fPt?N zKX11Y6y*tyNClg9Lj6Yjb+V_yhM<|P@cN)}Lrg8#xGz_D!o|xq(9B8To)uLRcSP-M{I2juROU(C5fLR44}eM)o@X^7 z#qd8OL?4wOYDGk#ZPjfbc9uCP9tvQgtM5qc9 zobVOy%oC`Ha0`AG3t8YJ(({HO9=9T5rN|A$JH>55i2EWwXl$x80iEyw z5pK2-6eEa$kPEl_3JUN{)Q%=Xfzioez6AlMQ^y`c3aA7pq{7`aBm_k^bQc7}H(|72 zNBE7rpi&;(r$NQ=DCT;pBpwI>J+{)i*Olyp)=x02%Bn6b*C8m3Ze#+&*Y(2cA1Tq|*4Hs=>v9(kS`ArS_Ku zIPZ{;D#!Jzl(?-!#Y1Rt5wH3<%R4x|FD9-qK+rPw`@5x~A5)>N+ z?K>>l+-R|tc%xY4X+m0V)vrE^2Pt-!|t7^hvv4C%?>bM=e6Zg0~TDC{6GY>d*&?TZshK zt~FE&%nNR2NQhd><W1 zO*f(8MiJT^kp>1`eFcU1RV6qfqn@R)ETc_CUnRf-Jp~~;pGzw2}HyFYHf#7fFLuL0#pXQOlDd8#AUQ+ zcp<#ebIxjLa(o>E;!UVIkXX42uTpA#!{nv!f=bpQvEY`byoDMyiB=<)C<=FUHuOS$ zZ9#o4g0I6lb(qmKrUexK_1vsMcj1NWd7w}0XFubRHReX|kELD&%m5OsSK#!a2C-#2U!o4aLnLPLQPjrhiU2--ZsL476sDoS3*Z+M_G zqMaRJ_2;WEB6Vja-Z>J(poa>9I)muccWYF6Oh6Ylye=r*zSMrq z0Qx}=GvH=LYaq}K?0>Dxl@>5mC0e{O4+d+!I?!}Ocp-OdkNNhnMis4x$S)KgnCy^_ zWu_jQY~v*qv2Jf1HoxXt2abOJq{R}mNQDGScm@XW44+~?W21_@RudAU@78Dtr4Sw! z7Fvaw8i2+_6&*HF$Y6s?O?Iqtg=Y<|y|gCNX#>yLJg{7ooo+xVy#52hn`1yoJeNy6 zbJ*BgYYQG`WI95iFVl&b%f={;4@PgyDYrD)Ta2qQce$0~WM=FQMg;GGQ35PQOE*lG zUmll#d2F0#c^8a4zZrDPZyT|7>QD)q536+OLV;3|!Cv_iZ%CvcpuRp1urWN=b3)(A z*M!(r>s2&3&okfH*#dp*)q!KW3G}UR_y{J3^D4RSfo^t&k5I-gNFal~;djGGV{~Rd z3N8v}OoO_QHJ&*N)JY8Ub$pv@l&W@M@n#!7rGuJV4)&+B8m5lyRfY!|ngy)Adc&V^ zhcRcE7r9#@*E&teK_kMWL@ynCjQ)wkAv%7E#El)` zoBWq9ygv*K5Xb*1N66iO1)b$WCO5qCNY<7sdt#Twe zZbG{iO8{yJI#S_jHzeZvD|J5B`2bS8$cw^s>NkigOHTM6{_8kHZ3 zWOPMfJe`M_Z4Cmk<_AX>BQVu;!YaVvV1xO?cfQ_{8l3ys;fks!~-V_9H7FD>#DGau=XO6g@@5;%yv?G55Pp#tGL}) zu$`Ti5aT$diWVE;hPp>DWGXehi^dILUZ&7~sK~Ovz!!0%qNPRSrmA(5X==EB(jQIq zGfSNtj3Hh|+tNN+#U>Qo(QKyW)J=t|AGqHrs{UlPAA`Fuj47=)Zlm)lxPPbThFTn`)=0>f_@t+q)nEcuebVr-8rL9Gp1RCg&1 zgOXG!@yy06jr;(Fj*y z#G=O*w9G1rI~(Cp%G?8`_l%1$h$EU1z_kmuC_2xYR#SSUrKbZN>Tm~w<2v$_W-J;G zp=L2$e6pOQVop^4FUx41#f60pEs6im;(RBArV5%mb-QASgUV<|mLYX?s(q=2NgDG6 z>sld=ivNc-EaA|&=?$#j|Lo^l>&tH&RgwwNm2iaEuEQNuU31lRHV9p}i5nZeewyK# zi3~Q?QlG-0`c_`s@cPRbG`f>Up=-OXt~Gqrv@>ByfBwankPOL++kKsUzKJ1L(fl#Z zZ>9|gXJpK(IBol2B+ElVj(KKW`lYjD96&tO^|tRtqcjLwW>`0N62bK1Riz0TXVlA( zFqFa95MjLmcRZp$yBLh5ano{Jf6y4Ng^_@p;VTKs52h#_7jT+*V-#yUyI|RePz<6s z8aS(N)+zaKjgN7VL`2ak2nWgk-KrG4NhJ_XP#Ps>XIKmvaLhN?Uv(`&SMK{dx#aQR z8%6k%KVORTR@_;!Dn^}*3rGkLo1zyfaT%bG9<|PB(9P&=XpUU(z|kL#EOCZYA;9GH z^o%Bl&az!bmu}IieQ=^yW)5|TjP$K5qc|zSf@Tj8N{tLo!{~PDlpzH*w~es z7JA_z3IYP^;L609LE?`_8_@F@&T3pwl?K;9tUkH9`w5Gy*kp^zga}28`ylj+F(xZ; zGX|g!F5)URA^Yp?4-)P|FU1BjI#^;}6bbs)#b*C*MCnHa9Zh7!QAq_1K}U0JiaXK3 z03YL~kb0{Py{9SGsnkZ43MUzyXEZ#!`i4zW_v*~S@=7CivjRu3Hb!>)lkp~iz9AC{ z`x!*jc;o&`g-yk6ji}8!foQ(*xq{v-2fDR4KHR3GjYL$xzhON+tkGA6dKX~6qVscy zjz&1Vhv5;~a{!%mp>dIdo&;uVJOX_?8-egiF)qGQy9EObtPPExchjh5vS1SiH8yg5 zFe+HAK_qw;!x#-{65^r|u|xe!4->m-HfeKu7>bP{{va%@5*|H}-Ui}s9nzuneYt1H z&j`LEoqT&=!#Ye_T12Vwo`E)N#2iA9>lrva#>i%?TCfL>z^=*cst9?4z*h@I!$#;Y ze(7r#+Tn500{vUpVIv)9WCNG(`<}-oBM*%mCKsFoa+w5mczDGbd8kk%q-YLgi&1q} zqVb-?2gMEM4U|qWV!xbl=tKvB5#|V8`%wm&=|I+cxrQF{>4c@BJm|STJi*8SIR$%R zY}OySaP_sF7Jg-^ac@Mm3YPLsHm=x(Bbk`pAr2XB*hb-o@;jT}q0;v_%(iSE$w)CS zqIH1Ki)U2X6KoRLo=p2+9kH(%`Dy4_nJ4i;OT`bYt9sHw8(EDirz!8=&=4*9u{w{I zMjRt>Y=iwp1IHM(r&j~Fa7UxhO&D(Y1o)E|rv1RQO)QsW*Nq%;E24>lv& zFowaC2=YF0Mw97l8PBzm!NPdupcCw&omiV2YRIT{sGjsD!kY$$bc>Pcez}0Y4^Y!X z6UJs#Xc~)W#v52G+-PA&*%)1DT!E}bk|SYo^2Dp7BDRPPMtOUUn;8yU8m}q^f*F@J zGznl*1cORb{)bUcW8d1S6O^zntd}1{Jd8|-%KV8&73mEW&a;SD@Ic7c;urGzTYh+} z0!64y$VwdKYKMw#{5LES8@MGyp$e4kHR@x0pF-lmIu5Cyo1z4Prl5L+{&j+&^h+%L0fo$8cs6j86Q{^*xS&m4w=Vn4GEC))kI zmPdH)jziUwZ`UbNh&1r_`?_#y62nAGOVBoaKdG)UQ2X*F_=12Z zQq|C&WFPDD*oYKIyF=5Xqdkp(`bKW;tU8iw@a-XVIkc@W*E2?b0iWygLkBseBU!!b z#4qGfN!$^|f$`3R43nZh?p5ezQe4B(ca`W4NL%CWihRD2hfx%7v{xmVC11ypWeSia1EVRK738wY==A}V|{V~3dENy{j;>(BZ-Z-Nl0jg zdtgS3x^iREL!RtMX_c{Y!IyS5WZyn^780$UUq>pu4+0y_*H<05Whz#z)lo8Eu8>qvBVpEo%A0gGkvIDkRS(ei2T~~Pk!Y=?=_|L{XDV>U!u`p8Hg+o z8_dM@oQ>ASb)T&XR(r*$FkYa%>u71lMIc5)nt~`0bM*4!#nDdS-kJ&kCCj z?xXZK9#Ye99@Bz^dIIkorab+3_wbP~#!18M_syNKSyr(QBEnS0cT!)z#9MCn%>#Nl zD{;%ChIMOV^1EV)aJQWHxk5H$V$i|)7&_I`Kxu+d(ogjVpfbK1%i7`>4TXg`rN{-M z--86(aZ7^hCKMqInd~g2*J8g;YKytEAeml8pgwM^qP~JjpgbDoHeY-VnRKxu#GZri zBwN`ynDDcLWqIOY#WFKIp~NB13PLpass83ZHYWJ5{tt(k5F7eq5HSf}u%5#n$@R~S ze{*a|5dEC43Su7y8z0HBmMv!=m;m|pkKt#zO#c!6RRQ_fAH$}G-x#vaT0-PvA}9EY zHT@&zDmdm@Vsk#pF$jPUp;Zul_sor zwbn0XT3)l7;KntarcLfj@wxT0JnNf;@b~g>%0(H{qO6YE^1w>oUj9E-)^CD}$^y@Z zbhMl3D|#-qP6;aFbk&wMJ!?ZkX7|$ZLmQO_cR8CKSjy?VIlBY?R%Lf74ryG$X=?bS ztb;0~LrHnZ(%>dlS&h~BUs>bL*`0HFoiFe@E-xo0=Nn(ZX621l<(+dwI;hI)J}uJm zU;2uk>G(IGfR3N2qVnb`@MS=u)m>iCmv%#yVHME#O4Km0fT zzSjDt+WKXX^=)4g{MxYT*AI34uLgwxFrr+PkW6iAVk1t1Y`)fyq@r6=YZDvaB&q1R zSXB2z5@}Qfp17goKT=!2s=W#MU2A<8k_VY368b;tdm9rD2@B?zy%L^C z7T`t+-~1^+N5r_6Oh=NfVl&h-)C79VP$igQgGDU-qnd~}wUC+;pSYxiSf7~4DdS^& zrX;0IOihlAj`bOs9vMGAZE8qTVp>X4yidQRnDqGARG-k^;Xa{5eSO9!M#rbe#Im2m z#wSkf9y_je93h*`xz62el-tNlc}Q*wvXh`iF*&-b+6K6D(F|5v;KY znrrFkU$1$uyr8+1OJ$z3Yp}v3OMy>a7PjMj*~i+rPi5Xx)JYR;NX@J;v7n2^!6uIW ziUocC1&=*!#B%7s?FD(L$ho=7>)4BmAr6)hTP%VOmX5Bj`*Q5$VN6SN8*LCEcoNc* zI6As?H*BVtJqX%#cW|sese%rai()o$X%1z8#iGh(&QvfC->}GqNyvB1lFVId>t|;r zrYc(0gR*QTr!vp>Q5}`aEB+wuOI;NuD@VVN(#E zGq98RdhoEwFfQRJENQg0<-%?BkByy`{)aAx|0-BCcF})`zoWu!-RunE;+#duOsrhS zw{dA6!gZ9)<~jSBn%hE&9!;c<7UtX6na(!1b!nbu$ss|Eg;Z`vO6X64QR(C3)4azg zb|qxq=`9DT02%96j2w}4^I(ISPxknpU*%|L(R_m00`3Cujz?Cs7}j^?ahvtS7tMHB zlihrM=Wd@gA_5r!Jm-cl%Pp^K+kS z&WZz@%q*33XtTQDZuy-z8=Fk~>%;38b8Sb>ebtleSnt`4=TA#J2XtGLUGGzM>9HpR zdd?oR`qiRI(Pwu%{N}&&uKB)`1w)qIHs#9Ai^?a=Tow9ypvQ34^y#y&Cvcx^+8FjM zeq1Ad=Z;0shWO9xv3%~5YQ^vS=iHe(^pBl6ql)Kf-bSPk>fYw1V&L%5b?4@daJZ8@ zvB3YG@V7G)?)XZNFWxs*Fs$0cXT7Xr&(HHjQ=hg9+Yxuty(qTz!qTy+{KCS8_qwir z{&QhmG14JJxWH;sT3`A>%Y%Dbjgqgg0YDqa}V|U_|NnY z9nRg!czE{S%*aE1XTIOivGmvHb}d`HJ@eMIr%JG2@Y~IO9?RlKcuaX4`MJ6@!CKX^ z>xP5VQtWm=@HqZzPxA+#U;P<+<`CI7a&L|xzvYk>E}r{))QidvlU=TNzugFH%RjkW zD~9|0!7Ja_uiel?1BP5Uuk7DCWK}>TRoXvS*3Ht%wfo+V$+6#Er8?)46|Kwj+R>Tg z_GG~hv#?dc%i@XGAIgApE4$p-_qfkXn?V*nB?6~uk@DZO-4@Ff85`%?spNMv6$|V* zTmQLy{Pvagg>EN##On-i?(KJr|CzctDPw!(I_3TkW}&0D#PyLLc@kN5g`d^5q?!4; zk;TbHy=)Z#nv!>)}F8_0UYoDhRs>bxQ-L>`1Zi}Yw z?JfI`=%5m8^_-u1?We!HnyfKx8L-3t>00H3*Hacwc%>(g(apBmPspzJS!Vw!QqiV- zQ9{00mvHFt!JmdJ|DF@u^X^*ref<@KH+$~tI$&tzm5o{Q(1-rLQ$1=d<+gHl-0m(b zt~L)zm^`S9d-G_AkBjGfAkN)%N zz|@4Jix+K84!!AqrNgq9Ih(?I)+^_qe_@i5)4YVE4(cb5G*kO|{qDbZ;%;qPqd1o< zWk+(N*3B=B?(NWcVEHh0LNBXd{1QZ|H%-?!7GF%bX1emew&t|ZVsG0L?d069C4Ao@ z9bT@=zS82_(`qMKeutQK#o>be>Deyv{H*BJ$3@chsaD$I_bT~|S1)LDpt}F+WY1fB zpYqQKzPi`wxK-YaW~v#dg7+Sh)(Z|6E#DERS>OL;7klox&&p*kNoF6C{G4CyzU_JU z$KUUmt&eqy7`b?!=E>p3oHf^Uie$z`p3skKe+HlLBWj$b5<&j1r2O=vJii1in;Tyc()BVe^4?1yj%Cp z^EEb`?eAQ<>D@$gplOqn7mhh=LOV^2c+h{g^p7#6{R74hI&=NC)v3f*=}l%{OL{bU zQ2F)O|NNZT>gDf8W(4g$I3=~or00c+ffEv+#2r0w$} zPpquoJFUsef=5>-zO`Fa)BjxV)+Jk&TNi;AZdKmt=`yRq7NN)_BBP6D**2e8@$pS3 z#6L_4yyzSyyLhY>@8R>V<5IFCz}iry0o3TVoTgU&%V{ShOgXMS==Rh zbK&dROPiOUPg`}mOYkKZmC50Oh4x1lH}?;onEtHDbo+yK=ln0M-Vj^(yxW<)ok0Wg zCrruwjl4GY4K-P~E23bkh%U4||-eTCp%=-^hx= zCtcPT+CL57?qGhTPuawdW8FH;Sdku;x6QLYFJxE?{@mTYEG_#j%4yZ7`}Bcxa#{(x z2M%=Nj~?7CqwT4BHrsT)COLGUFrhrCYWdtO<#tP6@EC_1eIH0Z{IbtxK=_=D9d4E; zWBN(&b+KPMVCd{%voXOA4o5P5eba8sWQ8+NEPwM;kBr7!lE-vEzhp?tsCg$8u0D51 zEO_!y%^~+&PX~?gzEioyeWtl<>DV>rj*42_A6|93fhyNyxP5w>)7B3^<_4U7cdpGX z=g>9hKF^+H`*cZWhh}f%(ws$ii~AmaV>wpy&+(tf25s4p?IT_$=-O{$w|)bjw{9`H z{lWGM^DxcY|OR8N)=XEdp?M64p!sD(v2UmI)4=kI%Xm*gisjbLPi)L-JpoyVZQjh8KIzS$w+G z@WsatPK~D)=dA2K|Men|A2*E&+1KH(PNk7gqetX4b9YrXa+%oc<^o&ONe42+?Q)Ll zx+-oDo_lS_?mr@JtNowa>@Ilg=>Nv@@+ZsHBK~{3-kAeayFQ+k5`UZAom2iP|oAU zNPZ;p3AsJ+nPG|y#g8{FW@qu+JvB>`TR*9?zOCcmvax=hXMIb@f335Arm}ucMAv=k z=X<51>o`OPiQf7Oo@lLKh(%A-)=5=@CqdRP)i{8Pl4SH1E&e`8%#ze*H>9HbYU>wO ze4IOH`U?KP^S`OH#z`Ni&s#))QD8ljm}lD%j{0a{8*=pMRb4%d$xY~)$arcBjwECb zE-+mAnND(9h3pVloa<0AoXoZ5RSJk-lynHkE!6UnC;2&tv&vNK;HP}Z6}$3ZHkZd# z$UpIvxen8(k(IXDZ=Fb+C}oIAT&QJcH}YE!r_^2R=qC>}4RYmQ-6oH#Ab0J=iyV^o zbGO=N9~(;AM*03OC=9hM9L4z~r>wcBwvnGY(p2WkcWf$;uMn48C>J^OYRfrj%X{0B zw2zYCHn|sSIbkjNJEv?{eQjeu)f6tSw6lJ#FSZP|ytST0`9|5iH*v_edd)pf zGgp46FnMPOKV39eTb5JiQ(r6!wfwM}Wco(QqlGnC@^~z9%5`{gh5Jrcp)I%9V#(3n z@@@`(g&C%DO-}Gno?^RD%TE!UjlNOJ-a>~twmgrK#2xPVo!cj}g1oku30(Qhx5@`Q z_`S(ARcdm|j{Ax2LoIjA;Oy{?5as0NsXO+7gZi&c^RZ;U5An`*_%NL_A+kcf-byBP<^M5OKFYyQ?ZVS)a{LmPK$m~`HCXbe5An%$&@Ja=MpnqzSZcAvCRQGS@Yu$am*;R=IEtHuTDChz zZumy|-ZXWXXPfQgLptU<$kuUAM^=cB3uV@>{H5*WsSbW6DvlCMR#=IfhFZSpPagP2 z$;R-8&$Hz{tWP@UI&^@vzCAG>7q zAzcuYgSZbOD}uJxlZjmU$?N3Pu;jLh7E4~W5Icoh2KaE^`9_g)iyACBHh^@4E;G6B zA}eHn*4JXm%JuSD4t_OnP2?3hoDHtx=7{R192dVRa^2ivzHRo^P|`cs;Y|l_pQsA; zMv<(ZD}VS5`Hv2M`L}pVEU|MEw}4;X5)Z#9U9kD^`L?_c64E! zHhZyGsO6DeB+4&JJIT~xp>6gqPci}lGnR8YszUZ&AZy^t?>bt(A4_g=l_zsJZ5xWc zLoKIwB@_Ijlzq9wvBa@H8I|i0vx;27F3U``ShB`RehBKnG*zF>$?ESdZXIeVo5o4; zi&Fi{$;Xmkgk%hiJeoYfE}yuvhOYdl4dh4R{bHg$nNzmXOzeZO3?!LQ|30T?p)K$5 zND`6jQ1b`(9n{|{)M81OCh`-Av0EJZ&pBBEB5^>dW!y-z(JxATlIO6F7{2u-4J8<$UDC%-`D&a2v*ac z%*u60JHdGuU7=oPt;G_@B>877Y0HyWqK-L=yCY!E5EuU_RRrH*sV%Qb8!|uFA!9A4 zPfUe)kEP57f(6R!JNhY)bCi`iSwCBedxTo55{ZX@lx!+*IF^JpAPZ5Hu8@&2725Tt zS}a-KL*CHQuc{>%H*TCzTXATpWzhoSk0rOc`AcoHySb1>xegbOkO?srRgAg72MP4fD7$pEnWE^H^|#K`rX@TqWlGk z>?-aTYPrveGXd%cTMYlvmRHo1tcCYGbFW~R8zL>1bebt|k0sA}YV1<%B<>$-`S?9a z@sCnoHp|B@Rw3jkCjVGqNk!;Z`>?0ZZm_WuC7515M?l zFdmecYO%{`Kk=|o%Xd>bNBpDI)xsJqnGr?yAja%?nXwhhyBsZ+EI%NRaP(8}HkF^r z;k5J-k4Cl3;M{=vzY85!*=F~RB8PJwwDowWvE*3;S!-8*$su{FqhC!+z7k8C`H9Cg zu;UyPiMtW?T<)!Tq=Vda4hEjb0-`EVk8vi}vS7cQy+NnBB;Kvp2y;1axYS1MnX`+K z#)7@}TrFu}H)n_7kq4G5#>`>M%Z@9ALM%^?WXmUM_bJcOJ>p{dnlUDH z`TWd!{(Z1q5;~tlcUOGMwy1~YzQHbZ_q}gksju;{{LQqIeC}{*z@1rIFMGOM}sUI_D zBspUd*a`so-3khD=1*9wPNaaEevDzX_796h3Q+&koT<-$^piG&0-6k9fLQgN`8z2f z`DJ$sh~(c|UpSotRt(@%fBhhSHUAz3*nFH#0a^Ug4OO!!;N5`M6fiz$o}i-#098F& z5D!^M*}^^~m!m4s^@s&NBzSQjGF+{YSm_2j_cbN$>^f{W2{Mg$OB-Y%_rtG&+ildG zc(=+y7DPB)TErRaq1p}$aNDgA!UCp^F|wX-0E-1(*?2{X?GnX1@{6LdUEUBcD$i5C zSJ-7g>VnQ&nMTR7{SH?tKt75AY|X@rl(->pEGQ0TfRvykIqzHmkVf3%fP1p9Aq3OE6dH@D1gK=t4=cWSX|YSa_H2P0W#zd z%#TrkatZ@1HFH~1*o6WP^kk09B=2(GQh@I)X7;^iAC~B36woY;nSFZDJPS|idf7=P zWVP9c{K8lY*c--Ga@*O(tTs_Q;Me_OVA#%X!fF$_sh8UawNL#QVMG>keQj?N4l@S+ zNE~>w5a;#3kS6%G%a25bxN_3{AlYOAtHuRPrCA{7HW^hEPs4u2E*iHz+_aCk9B&A~ zh1V=la};AoJxZW}V+?T8?M-s*85+s)hZ!JGF=p7SF#u?ev&iq^UYN1v0R@B~V}N`` zr(sbPASu$PhWndYJ?2r*-m78&CAZ(m-Qy{Twt5*nlp9T#G1s4GfI>yaNZAAcxM6x3 zJk&F`e4<-iIKcoaZlA$L{QyuLV9DFV^G)W-=M<1}oB>J{GomLfrZW7xm!+p?;VaXd zR883j22gWXM?9EG0e|gbcJO-hzQ;QX==GTaD!Gp%y5<0&G1GJKdb3%*ik7=KgIKk! z;>HW!xYGdc#>!(4??V3`=V-yXx0-RN;dT{xP=KTb1Dy0$6_Ra~gEm}DeW6tx^Lcfg zs1+^^!=^hwrzsP2+$MZ1>y!7{MPZ3uy5~8{`NO3j6xRM3l~hjAYEB#yt%G`U z`QKIm)Epg1#h8r)PSFVf6fajfKQKjYvCcUC#)F5Di-=WBa>J62%9hdVDbKS%I#Zs@ zc{%=FPh*Lurz00U=X6wV3)yH5K(7l0l;=8LAOGZED8S2++f>b|k*Zs?>3&S?<#xVo zYs0mWJh;GmTxrfT8s`JY3Y44%b`P~@7IyVPB2?YoLK?|}%dCBWE9^+cX!`@plz(uN z5>kNf+R5a3DX@lDsm&9e06n5v_bbwgJbW@C!Q`ft2p41|N0u+LLf0tS8%(TJ$~?31 zc2$=N+DfO!CRG4TRZfxIu>hblFqmVeQYy{xlcoY-I-x%grVuPu&glKQ1pxO>Y$h;;gTFK&zBna>_l zKw1~ud&C;X+_MeA78$&>-sG-X?@i$4@27BveHqDws0lLL3 zPP{l8TSp2I-;ASup}Jm5pcjz(TXLmDT^US@NWaDd2h5B z{$lU%W)NfYJCrwmnkudYFO@4dou@e9_A2(6+mRJm(_2?tz zaI70MFSk|3=ip#-Z0cst%$p*)=$tu^iv7ffN+oGEx|wDg1!Rbrc_(X%oG;A<;QAFC zYFXIL*UdK)$G)B3v~)$FHP zHf=I9uk89h>%Teypd9rBHLq=hnGdRVQb20D-n_wkto7!tP^33~pAIo1PxNQe>lL?B zHi`=|;`_SMIH}awTckH<)|*WM8?Cg%sv~Kk>r`Y;0jIg4_JKnH$lBJ&3;>N+(6H(; z6mVoG1N_EaY(HWs0M2Jl^8w&`_Zk{GiUQ(ynothsCEM(Or+~;Sedrbv@3c|DlPJJ# zHv{~kIAt##1_0;50t!%g$B%hBg#te9#z5lbc7=P_{ul)myzaxHGI+;FWX+-g-JUcG z_*)@rm@yiF;KhAutJO4F#aeCFVj=Kzxy@G5R%<#s@0MhhkQT`l3%LOCaJwFf#;+Gr z+~qusulTirN|__PFuEd@dOxFeQ<|QKwa+3(BN` zULq4J(cYN{s2BDOWqu5(`QyeYApp}S zno>9QDeu>C#25gacP^v=O~8xf;Fu+ogC6}N4#=f3A?*SIs4 zRf9pie!_5X0J3(N(zKGa?e$cCiUBfgSk>Y-Tf)+6ZzGpc`3W2(#eQ#=Rz;D!R~;Tp zRLVH3wk^U|P|Iwu$D?{(B4vH~)V7scX4?#_zYf)0qsD(fikYrPH-sBO-KX^&NWGI| z)wH=Tk6NagJ^(J`_U4ud0QrXk79m#qyU9LNz#}IXAy>ptxF>}GC^Kv+pwOygMVc)S zGPI6jfIqcQHRmYc%~S>`v0B~s(H~UEzZx;X)x4M7zbQaHjR7jHN`20rpn$gx8Q?GN zXN@K8r}+g8P-C^sr}8+J;c`Q!#otvSye1SN-^2j-tPTXk{Z0W1jTqpXvS)cq3aHu4 z0B@{b1Ps4G0Som29T{96&bHXW0Oq1GZ9iP3GMvx@o(4V4E~a+Kd&PRXgQ$MjiZ>MC z;ABz-Q$N$*y)$Hg>ttaB!q003NvvaFw^tFYjl{;rwvQ;YOFZMw=#5K-wY( z(3a2hlQO{R8k!m|U3)d$KZXJhE@XgPJg3If<1thDInAtj6U8RCcyl^az2H2zyxIoE zTt00st@Z<*cAP8hMgcE>V1QS_3MjC(%i9e{{82n6p%L|o1OjR z59rVS&Nmh;?n0ZCs%KA|rMNxFHMi=Nc8|_r)=k+AHa~w_^fNl;h8@?BtmZZCmDlJD z_M$NxS?AxIx#=?nyg0!C>&*Lhns6TgiFZ?WAYD+Iaq|HM+$wdh;xvI&8`|fTTWjWO zF0R#&E-o>@;u;Wg+7JAJzr_)9Dgy>nO^4eak4;-eHGS-FN+Ywu-iWz#DWJ-i0pe^s zj2pe00zBI=K*Q?^{1X(QZQq8baE9&F*ou|Z6leXhDWr;bywP+l#!as z1$P&qLAw?v6`r8A=w*B6Q-8_Lxj!|g#!1blPWN+FB~~7#fT?;wfaclUKPe!28UqY; z^&O#(rGOGIFY5GmH!ktv7#w?(vV+W$5or$+#MYh7aUIcaZehdOrY9Gb{NTKaj<_+! zHtZ~8e%fWiLTbGPTWa1Oi>q2jZ7>JmQGI6Kd*-<=DGMl|KLeaxtn#?An*y%dGl0(A zv*DxB04RPEQv3H<^2SxOiUQR2^!A@K(uLVy;j@(4|GMjhF(s3!*q2(fBHWGpaM|&` z5W8y1e5yF7WpnSt2k7u~XeF~uq~gl5=@gKc!~o7My;@&BOaYx&F+eo;biGa#5cI=# zI{XB;yyv-eF9kTR)Za=u_GPzH8^gkrwrWN>6l|=2Lxlr~wt74} zfE3L?Jt(a&J?$pCv)Eqyrp27~^rTt!qYFKN6wl8Y6yJve`Z2(qwfP>VdniD=f&oe` zS`QNU27ue#oyGRLd!J1fP(Wp#3ybYJjR!H?a_zP=+uF7|;x>OXReb4kHWsGbc((K} zI(4hwv$5Q-)jp^Dvnb%>5(Y?%%3kKw2LN5jc2;UyshVA$Mgh~7u;bfg&9$XJvAO-Z zIjbZ!Q@fXzdzuRuboP7N^EWynSH2CQ>7%aSX{P!u4gL<@XklLvSbg_Y5e4MGWPqyr zRWobeQ@}Jmpv$CdX7eaOs~b$yM_Yf*jF{IHaIdRAeI{?X;cONeT-~aj<$QlC)xf!Y zS|Mj{+>v)oLiHLJN5y{HsiJ*MTQh)SKGW)sFc0z zKTfICQN+z1Y%Ae5`F4Q6}fiG<|P+XuKk6URcq0CO*8AW0b}ITBy~yUcOFapv=?FNjZZ8ibbrj9J}#4 z>xmiN;-i>yxbFGPNvEWMW_FCj3GO_uH@#X{_HgFV%F}v6=fWox@Up254YTXq8!OjP z8KkL92Itmy7R>kJ1F-ZY<8X81hKBPoKo*Fr86dcIhs@RYsTOUHF~IGp4f*q<0Pr2i zZaX7ecUo}RopNZe=Wuu9UCvG_r0gXVGOM-Q#OpE_ObG9+8paMdK6^+ZEFU-4>Zlzmc6!lX7lg_ju#BRYlYkc^8?SPg}R1|Fk*PbbSR=M8{o~A4g4L(@%f# z>*JC1w3I5cUhnZ|+}A7bQ)~OqU>y8>4$hz7igI|W=kS8NB)===P}LJ0@D&lVak?$O zU#*Y~8A*S`pW%%Nxy&b%dJ^&kl+cTihoJGj3Aqc3?St>mfFk=6at$;ljF3M;>-*ue z{`d?uW&l0|jgS&@2{dFNA-{tL4kF|ns2{$ca|YBqoRCwX9zzKE1=MdSA=RKE!yp1^ z%y2@kgJMSzav#)e6d{90gC{6*3?a8crICZK-WRB$jken<1-2AH48jIQaK?PK%24%X{8`!C&(w8 zko_QhZ=dkz5V8PdJs01B2Q`^Th!WI1hmb;$*L=tZ>a+lSL6U`p{0v%=ONiqlLVf}{ zFD7IQD02xRpFoN{@LdYNAiHIR}^%L&;H@?QbIpiV2n7qn;AiMq86V#*_dxDxDz@8wlgV+-ka0q*X0!y$bsQY2;2?{%cJwf3| zu_tJBDIr==%rQdlf#Q!7q64L!Amj~bx*B#UgB>)m1E@hc>;P(30Xu+No`fAht$!wD zALt_}>lEU>67deQ`UUY08hM(KTcEfzgggQzpC#l4DC1W`f`3B}f(D#JZi0qYA!k7m z)yVnt&;u0sJM;i`zW_ZzVHc4fe;^(}?w1JJ1@fyQ?(MI zBK`u;zX^E?O20j8`R`2{0&NaN5~OS*Z27Mi=eO%@GB_%BY1uSPf&}` zglq?SEy<5lF81Q$H8;hzR!YZpJ4@jE`*NACa1tloA^=DLr+(f7^Bu36ZH2$t)Wrs0H1G zN4g|8`gTQfLS#(Llo&t%4&`uP)kTZDiq#nqQ39BN=05iz89|L};g9>IgdAzNs_@T71qn=^e;U@EmMO(T#&FK8U~Fx7ZI5l69HRA_~8ph4N>TU=MvAL9$Bv6%AcH&G&wzW5;bZaFBBIG2pCN5~y`j7xmw zIYJW?8XGP!gs+-^x?Zh?;}XUvj)Tm2)lPQeIZ}++Hv7)zlUX3N^^Z%RM7f`+Pe>7> zhD$mGS?)16Pfbfnj82|PRw4Q%Fk^?HexGb=?Ghasl{$|6i6?HzE-vXTyMM>N)^iq} zu^DM8lgKc0bbEwZXW6C0)R}{OkL&?QbPw+ZFI3aqM0B+DqLK#6R4V6hxgfyPqhljr zij0WlI2yQSB0}1+0O|TKV#SlcAeK8Ab4WL(ZrS$?QzxaQ`2{4$zyo?`{Q!o4n$ZOz zMEkV)w-UtStsxR4DKaLN2EKlcE7WSs{Lxds9LX9LosdjsIKb=Jy{D{uo9~h}Iw>JJ zB{nrRZu}P}Yhjm`V8S82wX4oLe!FpMT>3aBCTWkX_GE$5M||CyZy6CLZ5MzH*IO?L z|3S%=xBlC<77KkolWz8epuqspUp8d_cYEL;&;F1|O+ii~V(LRH4jG_T{rR00CPz!(Q)Q>0SxiwzHdl zD|c#iWLjEmO3e7l0m!Dkh{6}JKbIs2K``^^Bz*V~5p^GSO#a{2k0<-F{w4EYigA4$ z`3LJCVm+6n%9{(n^8*d)$mG;7-Qy-|zY!4kU+U zX*K6+XW_W`q@T#kh_EyuIb^Q(^~Ue|K}=L~YGh2* z6q>ES!1nb2sU3&R`?nqAi8uKCgdMqLJ_*`x3$=p72lVS55)m9Sa7gb#J<#>(9~+W@ zzvpZBZ2CU(Q&S=*xABh~Pku+AS_VgR$TGD_XUdD3NE$wfcKLMJ5nr!jybiXdpyjfo zng3b-QpbIXpDieV`&h)T46-YLJN<`}T%viDo#gNYoyjuR~-y8Gf zfSB=QH56{n>d_i`@9OVb2(5)^%e4wvXVe}ZQ{|_x62_BrkT8PHQXAA=?|s)HGty#H z)5w0r`#EgJC7aZ3|N71i`Y9karVW{a86X|NP3lR5zwhX5SV&DrjL>4W6WHlYgU#B0 z5w%l;72xE^$v?0-@!X$Xt3-=bvdfV{XbUKcNK*1oU z;CA($rA=yQG96GS$3{nB42YQQ52LY|6NC)EKuRKsF+tOAc%Azce$Cj!ebaMSeo6aFh9F>|L z6M@MsHYG7Kp6o?aKf~;CL^)%@cL_6jTr?g3qLbskv`IfWm9P~@zit~xHeg$P(*>?M zu63CBU7Jb9XfhrX-S|i<`WP5s2pjuPeB}{Owtz<>cyRH5dZyK_hH&JR$dp7{MN?zb zA~IuBk|N?`6NwLC)yPPV`jgFfY4K%L!})~e25E?%)PV_H86+?Ju9PR!2`8S#;Shw^ z99Cj}BfZ~zABQPPDU;c#>IYyp1D=!HeXc!}CPpTrV@^ei_l21_>Rl75 zb))_KzDS3}jf}@(CNVmen4&)|Wg^}teoyPyVi=v2JeB4+iH7r?nVNT$es;C@WCdel zMq&~s6;cLkS;JafazALo=lZDG=mdW4B0?et4+#zJO^;T4!G$)Kt8o5(<%#(;&1yAF z{qZU(g|vcDCz((>xuoWMmm~O7qiD!JK`x$WrRSM;S6r)F(lgPFgSGxN{I$L8g#{0? z`te*H*ZjMD#MqS@Q+t@b2&->q_?NQ&8fI zx2Gb41u^s%X(A#b|KB0`jO%IlCVt8y?FjlgxQm~7Qb zqIODXg;VRa*){To)C*C-@>PBOrX9ps5;K6(qCU8x7}FX>y~y9zNC;4Z1Ze$Z14k%< zf~{bQ!9ZEPCHX*GXP>9-Sc^;d$olEIRv%AvkSUVJtT*`SLjl zgNho>bYY_kvqb=di9EhVq$|W185P#>{GbWQSj?;uw&Sl3#2VzU!5%BIj|VDiOnHV_ zqjlu*89w%&o8(F&U}M1Pxja{!$d#p%$;{8rb-Ao!Dtwqktcpn7ju)y{2(sjuVGrxV zBrjs4624>5bL8OB>A!ER39e&wd~B>~Ak+m?5b&>>xZNC~aq}`?OJt^I=ZXR>@dK7H ziU`jVDWV>hSd1kimel=}{40*&jLgX9_zkNXQ4cojC1%(TOLUArd|Vq4Op3-JI(nve zibk0JeN1lVc&=pLtCFneWoBer(sQy*q|bf^{U>1TbGiu4 z64SBUrK}ISF4;bZ(C)T6TD=|$SzO0kd%k4c&A=dXLsIO*h8_QeuZ*Hw$;4k}T@GPR zhb~XXmTzOr-Igr2NQ06_r#MU)bPgL^!+=DUbZsp$9|ga%lAyuhDJb092!qio1dB(P z!Q>RlfQbS|(M#r4s8+_2@bbxK+)$;z}{oUR=p-MLoD@ znapoPc2pf9OGs{drX@8cDPPRQlE^(3L;Ow{F6v{#ECy|8!`}V0r#pLgMv^JpmXiyQ z3%W2{I56E=)?BYFnH?v4bSXG5W@fl@^NF31!Y6vOb{b}`d{*nOk`U5}c~FE;@^r6` z-}9NoobV6J%*tTQ^b*UvwdBW+626s)ffYznsC^PV^gsL=gnh?3GevGxKD9V)2&_B+ zbFN_qbu9VWE3jjM4i*s*tr!Mu#1cKH1F~6+1uC%#$sRxFJn4FM5yh9lp-0pNi@e7R zxt6s4%{QBpqv>JOu3*!5m=SWu$C@Pe&*Vczwy26_3qcKo$SZkh139CeVhc74-`_0PZI+V51^?$B@tWP>`9F6#}-~VgFDScpPOh%k(= zQ%}o0%6Tp=*O`*-VpsYccJ?Mya6-vhFPyVdo&$ht@k|9fCeN3w4@DxpVtiwPq@}Fc zCYtl_2L{<`TQ<=ja`_pMK2csHMZASIYV#VCB3ta&#zQO+YNuVy!**Wc0aN7PJH;aW zzAk?~ZO5F)NnKc+=JaF}fCIK*Gk_?P7Gk?AG>-j^uuKBJeZh6tQL-)AnG;R`6I zcnd%c;Z=sr(>f=F*ou-Gu7keAVnwBz#)kFnHW?8XEAUxw`61+ z390Ow=4wp(Z0Leg7MuT?j}7zh(rN<6+aa9K@fP0lqmyugm<^qTgn1z6?eX1L1qGRK ziW`9lbv(52Ol-y=7Bu{Jn>J{|Y?PO556|pmwu8pDtRz!jhjv*GaR#T(F|1$S-LY;c zMStAp8_JumWM%_rwEcNaXyQc;Ypl>Jp(IznITH;2EtZ|b*j=)t?GH4K8bfkl2Hd7u zFwGA*a2dq19aEl=q>@9=nN~3v9#JfVw7TS-Xl-0YJ%d81#4*fMizVt~{kdFXDCUad zxjr5L)pp78Bm?L2ws1(Y6;@UqTN*yLBqS&unl5P+9m_;*FiTsokwJXcu;3MKq)cU% zE-L5t?LdP*FBw}^S}`v(oMQwooDNKi$8ZNEc$w+G&3i?ssDl-exrWKUGVIFL`oU(m z`riu7JAhh)_BZU8Y8xpo0khvQW_RiO7f{;{ zFgWsnAUV4Y2ToH!UUmQY9*%s!VwH1tw7^kt{7+uWieevv?qfgV-R(6zKR_08^@hxS zfQb-kz|=*?)WIeFuS-X4vYQ+q%K}`}nd*lk8%&cX_JlHWooXnfA=rd$hCv)Qe3Puj zvnyRWlZ!ZLtzVeKkCe0@^O(Zno(oaM_im-`ctl;A>YF9bH|dn+KHg^|m_;bg7RQ0& zQl{DQh65{0-Ur?Fk}0-|hS{Xl?UvH0g!%&$nm%~2Flrt*R#xb*{4BXGY1QgNq zqrmlC9`Q?LM3LllsJ9g^<+kEmpyMCrkyDQvjQBAI-^btpQDS}%R~wlb`F7D9jC%x2 zmY5S(_*a0Mknw(y>?_Pvvg4iJTIbCLAHeA};p!x!k2TRq1>+DzxP%$NL^Ck8CIr>2QjWZGtZw3- z!{P+%zB=8r9g;Ft5APH*R|pu2nNXRD1w$v4Y}d-C;<&l8og81kg&0FqUa?(wOI3-` z9)YJ|Q6muf31-^PJM|C`fj$Vt&u7GUd)kLhMnLiyM$F?8(K{c~zQhO%@bz$3LNQ6{ z6(x<3Y|cr+^(7P}0ks$0+?Iigo3KAn5&`nZ=+Y$Lb9C4Sf2@c}(KiWIA`cThGYJ7_ zYaT}cBQUHBBd7oAG3O-Y-~dBMPzB+4;r6@;Sd3!e($Vs{){&lnKu%4tP!i1NUl z&wD$l$`P8v7Q-1cgN(1wly;+r&a7pjvw7J175o{+%M;e;Ae|=JoR(&`i>>epYhbdM zeXZl<*oBGL89G5PI+hMCkJG^}aGg<@x-YITb5xO5rV zJbHd$x>q&8I>i?N_Avna>I7RAt%*y^uqqcHW|*ZIaD-7LP3X2IB*F zD>tPqFX|e0ypzQ+Eon|at*%lW-^}ccoFs=pyDfntZtO2>Lf21JCzUL>+ey8G&6AUQ z9Pyc~3Gc3zEJmJN*OLa|+bj_ZowFF+YZSRjzkE*mG_KE}C{w@4fl)mYVqT0%fG4zC zowpj)MXvE{11%lh9oYquNLh-GkHe5&>X7q{zJl(pUy-zrdd?`*K2vedxWe0>xU*tA ziEotactw7ffgg6Wj7^!KdpGKGh=ov8jhHIaCQLL*6jUQ!NhS&&9tAq5gBJ~A)`Tku z3G00Lbq%2V@6HNVX<52AOU_9WgD}JjoEyb_{b4whV3-}l=I`wOz2vWr z%qG&fpmG<1ao*!iytC8qjVVxl4;s?R)Lzv6mz@&z@^F9VwC1tYQ{(qWOz8J@O#)Uw z42}LatD7Zy>H+I!VWR6`2ZLCCx^$0BV%+M|tsvj()&#Dn^L|!5-R5g4InJ&2bF;EM zCUFC{^#kL5wLU`O!(oVx@xEc{DqTiHh8|p>V_>xLV6+Xo!VUhphCv@OTWoy#^n5*~ zk>&6JdJA}<*ppFwJmJ9alKlgJu;?h-sz12%I%faaIKb;>nG%dR8zm)MpyVEDt%TUE zOKqX@9ln~C=Tx%tc9Swqcki0FE zeA|S2#XgwGnwbyVL0D{p1skxqer4noB&7L?@$d#;WteyRnBOVxVg7KQ|Hy>EIl+`W zn3Iv~#QipO^mF(UH?gOSy{=yzF6=@443^Eo4~^pcofTzrD92Lpjr(vX+5o%5fRFFH z|9L@sYEpb=XRbrs0J{`}8I9tYuHb{e_hORD;I3m64(-*3D%kx+{5$~L?Z8_){`8Vd zvWh3rDE(uk$LWX!OaI0!{j<+GouWME?8tNevb0wg1r0{#nC(afu#0*?R6EA-Z#&~M zw5I{6$TVAePQC+r5($vZJ5`w0r@bd}iu#zOJx_9R>DD)WklB@z4P8N=S{x7`#(Z`8 zbbFiooJ#IJE^^hF&K=d*1mhrO5T&Q}t`VR{Q!&*|))v1%{cA{I5OQzYX4=Iu_!3Vu zKsUNKm>v>jN=qZHVR2=P7_ih|EZKjQ{lY1Z;}?zai$9*O@Qs!%`4(3?WKEm`EJqlH z_maZ)OKM5IPfg+b)Els)^;j*HFJ6Bn7_x(CNT$Os!mxG`gB5&ccrUF#PG`un6XYN) zwwK3Mjq=HE`AGuJdBk8arBOT<@X2yXKPdh&4$N&kATgm7g4Gd!k1f0C`xrn9QUt^2 zK}iyDUb9%w6e6^83`1V!VYLdnFVyaWg+Xzh5hyze2w&iFwI2l`^dq3_!s1^y;J*)D z(oinh;(lF^Cz*d`OdKY^bgc3ht0Xo|>8g^2;*5%BcBtg%J z%)&T>c*bH!d;oVgX>G*|kkh|evA5OztyRR}w;_y$4gqfzXrh0VFaqD$BsQr0RNRbK z=xq6PlGbl>;Yvdj(TRdQ9%OlZA?lUUL2!>V9X3pIRHe8ph9>ET{;Ry( z_&1Tohbz%FLgK*aDAS;Uu_gpEOyZOZ!1Px1+wPV>W@()QlL^T}rrdOw*>0nZ0@M{` z=41=>Nf1Brq|v&&&liKS`%%E0QN(IMa*ASrR2#pJZS+g7yZ-YQgx|gau16@Fqk)!BE_&R1`qty0nA(cF7#7FF2I&tA z7xyu&2M-&pKdha2fMM|%W)v?KOx+@F0)_%{8jhV&*+Cej<)vjwiCTMtLu*!UhFz54 zFnbf|Fo>c03w9C)Sd5+w*DJ*p!X=fLhx{W4;#ald0&HMu9`18Jr#Of8ZZY~_ZB#Xe zPIziOJh4Y#WbUB0Mdin4Euh`?*TR!QSZg?TW)MjQAKjGrNXfx*rD!8%OJERZ@lPz4 zCuG{EW@Hm5S)jY8V-xf^6soNXrg>%9ao(+13rTDUNDU(SOcveKQ;M?~492GSx(p&! zA99zd3&=lWEM*nct4q|&$V7^o)B8r30^1!y=go}v?1BbIwO)#%?j1lFD!=frns^o@ zGKf(Hm0y&!EmgW$T$pbKoLdUg7{ur^_AI)`qw{riOrO33daDTnN-8ye#ze-%1nF1kkv8eqBR9}at znAONvhOo#%T64<`%5{R?EtE_3DB057q-2a|5C$NWP!q7%4YN_rM1A0eFCz zUy#{S3zx;5o{{cA_7)PQseHcL?y+~E3o5&2k|R2 z)Vsyc{iT&oM0CtK@SyEE*bQ1-i3QBGA4IL(EE#)v^jRE7C%a6EOueubTtc21S65QG zbnGijfQW>Wxy5X?>dgLM2%+u-2-N$Svu((K#t9IyYheIF7cfJARFL6CMY<0m=MSA_ z#UNk+wUGs;#=d|gy%x@AwQE>6mVw+9HN2@bR`ETvOzdc!g6GnOVf@na%|BAqi1X9J z2?8}>)gGc!g!yq{7%+a5BvPrI`T|Yy1@OL+alfU}21EQ3iX(%Vrsyk8A&C{?E!7_1XS)uM&Zt!1&h3qaFR{FR&7y(WpWCBups3jX6Xxll3U1mjY= zF^TfeQN&&q$}Jx#$tclDDZq^fAI@dm1n&CdPwnLhHk`uhdlXoEEM_!{;N@-WO3ba^ zC2Ngl7Ir=YY!VzjLP#t~Wx`g@7&ax1f^(MQu;++zP+|+21FDp3^a6QBl;0ThVk8wJ z4(!o48v9D6ZDC(jJYy798*gqL7=###1p&wlh!SOkI8`UsJ6|y<&y%`Pg3pKGa}<4- zy9u9;FMLD@KHbNk{>LwQTp}6dA!TR4;l}-Yr>KnI)9tTOJYH_uH z86KZF)c0|j&;L!Z^|8G5rzUpu@=IYq5!u-W4b>MLH;DR;U9W}&p{&7~k)BLxPbL5| zk2liT$4{MNJAT@af7+zn!MT!wbZ2CHB9R>-vK00*icmirbBQI`*nOZS)H>cQ@hn9V zIi=q-ZF302-)yH_SpPmDi9>$2r}A+O6v10y9`r3Z+kGURh7%Jh6YWO`9g+TKOZu*D z<9$DAyi<79s&{%9oWBHrICby(t4$?3;5m}j6tUj$yJs=3o{N5Q3muwOA5D!6o}m@6 zLD(;?o`Y z)F=`fKh?+Mc5owwPVNdz^cZKXkHQ%xp|SBx8V0&3*+mH3s_A7-RQkUUhDXJ>dugX= zgGH|M(*2@eJ}G5afEUwk@CK6L`O}4pVwnQLi~X^)05M>BgJ?-P;zv{wOzDOgSO-)X zu>74m(y&Yfa`>WLoCG$@0r>-#e>_F9iNrMMWT9})1#rz*jQhl0IY*?iaKXzw@COhu z>M~#u1Fh*VN>W41rzn}yS1{vmtfdB(d;63&K!RfosmH$H!;gSMgBW5>8mN_6c!^F^ zz9T1vB0)K5H36p{-VD`NS7JeW#j1C$3@*I|Tf7lCG759_S>G5+;n4hTKzJL7G@sQ; z2B5^o=8(`myr^a3(j5}dBflXd-R^W)a;y%%g{_X&$1;NK{?s^P7!EAGpAnS2Je7|2 z+~*+X7o!FX8ak@c5CGY?cs|zpJ_+d zhu8q5Kh0|wTF>We)2yM9l<)w03b78%z&Xt*CYNgq4o%|Y&N!HgNuciJi4k&Agkl3U zM~X1;-FGYxGtN%=pTwX_?3=hQ5>)$(0iQW>Z#rAjY^Z=V8z}&#vhof%tqOxZYx(1Y zwR=|wS) zM*&7`EUff=kjNSF8=1UQ0Fkef|x2Ex`-?hu(W*;3(gazV9 zMSBMEp|9UNxnW5g9g*Hwt7jR!`S0?QvS zZ#GLxq@cQT6O<{kZ3%;|AS`ryXh6M=K27q)H~{o6)8vbZeuC4;$LkCeyoF8h4nI)l zhyp;l1W+2p&T>jdMRu}y3);#7$JQWrH-05u8?sEvO}3fxP#{ChhUW@IM=+Z~>^s}A zftDY+Hp!Hm$)y~}c&5XTw9HTjhq1SvtgnAqZn)*en=U8PTa!_ogNy|6Ba}uu6YxjB z){68CnCT;)@~4TF&T03;f}TsZ1(xMDDDV#B;iUCb-53W~Qbu9%=4}6dwLY>R6j3)A zs)M4>2JzeScH<@6szkq)e6$h_t;s{rEbsI>LHp3f78hfQZJ;i-G%<*?`oqG-4h-wS zp2oRyeRK-gImCYlymu74KXz9%i4esd3S^f8LgcQW&8j8ik4qx6)2*&>(GWmp zfQc^YZX`v-VayyrW)PS4Ve2Gz1GY{K+f{49D#;~N>+fLiL`_UqpC`Q5_|h1O#mK)$ zUA(vly1v0Ic4PUm&e~z1GBlUk3uq`b%T4gMQQV5Y^S-1m)j*P~ERb{;=s`nn6nX2a z4y-;Ns$(%QV-$Zho-@%)w5Sn^#c8#rWuR;hy?aGGApJuZgD%k<7%T@?Fo?f=98;hn z`@^5u$ntr2`FESOi;?29JCS;CLAs#`rGPdw=)LIfdq{&YyVHMCvT@mijyP4Ji}qv4 zy~feiWTxZ7bteZ*i4rbs(!hGO+_^V1eR&G`o??XUKt>Ext^Dqn^rTYBYB&R_tiw`S zv3%j0pdg0}B^*#g%iyz*0J#hzq`Y3P3Eaz6tYXD#22tr;L9WC}oC~7_x_<`p=P+U` zub9w53b?7AcGTPyRnQhf(55h9tJ(bAo8pi+8%**yuv4v2PZ7dw-2rXiV=k>8^W<_V zDyw7w@Rf<@W^F%ELq(WK35szy=d(ijFMypaVD!|oy|G<#8Qql#9+xo;XdVF=(O5C& z*I4;Z09l<>+KIGIAT^cQ%O)SFHEpNTXwwRcwOS-j_jt z+NO6V&v%GBSZD*YO{3kXbvht$?oV$7yYu+C(AYN8DQOIMzBhXt9MF%%;5zs-ik7>F z=LVsU6qihBhww89W&*)lu25=ikdY>eAb;6x!Q0w?>@LNO-4~vkz;-H7Nx^M{Xs3sR zd{F`%^kE#dkC8fdQNev%$UM=mUwfLVQ_O%H5<}n`%W9({vK*3qJnJBGS$3Y?tuF_o zVNd1}a4h-H*@9oA0AfNy-#&4k6#8V9ZLAFmMcrZ!`#wi-uSdFuO~G8<&ixy$)pKmW zV7`>Y1D#z=ykcCF3acpD4}LKv`&EXKSpn=KdFGss=|$8d5g4t8t@VgmG)Y>7Js4EO ziU%0Ah*289Tenjd`6CwK{$Iva@4|Q5(S*`nIHmB4JJ8OQuZB3??qxH;ChA@ONwCRa zmg|1!hQ3c}A_+<*z)Pl>m->NrLsbNZH=rL6@TZm_$#X!Ce_4GD{C_IF(P9y#e=^I) zi@QJ7seZAdaf~NYI2MDuVh6EV@pKquN4_<=h|Oa?rQ znfQ*v;q`UYb{5qtdDQk2sObm$C1?l@gi03|I>{&ozvuQoEE{B%v`nsVmgGTD(`nx z;S)X)Y~~Bet>E<<0N*Ia#uT-Yd`BhLmub(!4c?E?h&}K(cK1V-W~2t!V~=(w=o_}@ zK9+2m8vZD&<(~;2se;K2Vut^9UE*g9qiRdkpq#5;Ptvelapc|cUd+WpzyDn zFgGS(7RYNjMQ5zBl-F1q)3uhw*%UsY8&GW?{wAFHPO!RN7V~bROiD;KS7zbX3q3H}UXLwVhcA86L? z81pgyjAHZd&Ics7hMZ@(&fGLu%me~{1hqHodP&fZ_rTTf0v!hNscl442~u(ntzNx$ z%0t-c^3)){C`@}=!W~+9*s^nQr82S|*Pw3Wpmp&SD#C@P)0i$8>xf|a|cvTMc5LvPW zgN8rTO7V8l#SKfKz6 zMjwe;w2NZhbcyekifB_Aw{HlX0erARdeturj%Xbq8>fb2Rz@=8!EWdc5 zaS8{ZIl;>D*K___aghQ(36xD_l$}{|$k!o&a?Oa(IzoX|0qdTzo#`ma8FLxgU@+NR zU@{6B7{%G$zgE;5SEV&O=86ZJ*Mq)ibrGE=^qnTie-kWCXIZ?o5Hm_XWGT(Iw_~D?z=u&>J-7Zh zN$5QZW>zs2Fzy7wuNLZN=OUwMGe*r}#=5opT%Eum?(||8@i25zELVT7i0LFPQx@kH zVWbFncX!JsaEe}-Aetw*=NC?wFad&HfWRpJY0}W;Cph4_gozLv;3v<(Z~lofdnKeO z6j4B~;Gz2}Q9Seb6n@$kc>ZAYYYn5T(u+YX@4ZSdE3g!ou_NpvE_l7I1% z0kIc0NO5uXtO|zazJ^`F`HwTwD^&Qjm4w|)T)*ZjEjaswCr+?-2#o!YU8@NBB*vE- zoR+#B;&_z@)@Zu0gI0}LbJH>@5SMGo5!*o#O0qVf&1rg&S1yB++)ZtTB2-NffcH8K zqFx1S7fG|IF%CK^Dwe1fEX-uq2=!METPE#@4|6Un9p^%T$JGGTC>os4A14_D_rY5e z2pkIzy9Bvt(DbQxGJB94jvHLBoO?X0DwZ%bjrJVfR3(Vx_BOmL;Y0)3a&_I3<$xLU>czEk;-}8E!F^FyPIJNf#SPe4LAG_Od>6SAb0`_z%H{ z*g@B|;acXXk>vLQ$R)T9SO6f6;@R^JjZ{U{r!PG1fjyuP6JS>pMXt&w`=3Vt0ek#= z+VprF7?Ic9K{SL|9AU9|zUjsUO)U~z9xA=SOPTmrO$=>8AVoF(|7n2HVk0!bbQYl= zc7K)uTX`G!{+RLIFZN22cE@z=a^+?s2Rg@v`(MDp5;S1XH(s|xWuk^&@x|b)$vkY} zq`w+cDm`(JCtrv%AZR~V!)ZT*&%cqVX4`|m)T7}4Xat6=#1@e7vgc=q4u^SJkwMr& zKjyHZdnOf=glVE1IVse$QN0=uM)2iLfMFD`O!ECe%t#=9yb5TKu1G08|LAsDWVP=C zVyX_u8xDJ>tR+lxT$?U$5Li)i+)#H^9|AT6(;I|Ue^|I^gkdjZSb(tW4{IlyU>II8 z7xtA6eIJPV_G&NugvWp$dxiDIT27=J2v=shNQI0Luc3HmQc@@#9bb$YkQm>WPHU8r zM+6z!jlLhD4@@T!3SeI0tvT(!!Ujl9stVQeB@anEU*otouB8-4WIK{ms50U{WMdH^ zGK!Ha*Oveq%m-gP98mXlqzZ74k zflyyN3qjb%ji8;&i8&qw zIYnO}=mD@WC-(j4q+>swqw$uA#}ty3VOf*$1;$JoK2mXtMnnz9;E^1>!Cu_%| zM~-eM>R@ylk6vwWHAJEV$H=Tmg!M2#J<~xAv5aEvBd6~q>SFqIOutrNQR8I!0E+s3 zCf@oOs#$;}9AdMux#?>k(lLOkt5gCKU2`e2y#-JnX0&cu z`OYO8rPj`Q`4MfQan|yvuO?lqQXvQxb?B?x9yptZZ}4v5dHq}+N|%koDqH#YJJ0{? z_1X}Mr9@xo?bjKrdsqJbP<9o&>7`iY0}L>V{VRJ|B~7LTH#Elt>hW+IfBPrtwRLDK()&OyX!&%Wl8DN!zx zvnWg2696D*e<}!r`nHulUY3lydN=~14VZg52#wAy=U-kaX?iuR=t-}N2N+ZkYY^X0 znlVZ`be3i0v7PD&(<1N-qd2aoP7zx*W5iX=dE9;^m(GWD1J)xl5nex{Y4HPxfY;+l z<{|Wx7}B5i)ZHd+DHGlGl%D%Fq15Om3?ZfSnTI8za3A+HQQ$E+p!~wWI2F6BJY{xz zS1J>;i#YJsN8l}^DA`l7GigCSQ7BgdhgD(xIt&dfD{O5q=?&B-=Q?v7T-lSw-S!Uy zIlUle261{%?Om$Nu5@J~@!qU%xjSGpz%Z>8YJCR1#iY9Rx70Dqpf1p(a*vyf*7;#fMYC{rITu|(RTY$dfbzfvJA3f!$^a; z9=mX&j9s#hXlzUGCn|cb3HbV5#_kQfpN@khpY*oh1y*2xOmg^pZHWtP--gpcSD*%Q z`~0R7Nf=pj=@LcLFK|6z*~75>Icd|6TF%XdbFFE7u?05!ODHL$_)DKcIbs>+dI}W! zYvr>~`3_Lx@jePr7GhzlIX8&E_xw}Q-63CTF_)}jUa1x^T(Ey8VO6~@v6j7Jcm*sJ z2!&@5fkpai1xyrxl~*wnRSbqb zRfa?HEhRBTRMMLT80D9pg-=RAAWxcn7T7{^`q>E(h`U$w9C zXB5?nLf`e@t5$O>vH|R~8F;C7LHGEDsDJ?gEoOjfO#br`Zz}PXYgHTwI2Y7|cu6}Fb9R^1$Mv3qV&0H)uEJwA2e zApba9pxV%Z<+x|1=4#@wWER4BN`#n;V#EHqX@b z!lK@iVWhxPS^v*d(2YsVj-jCkf}|TEwfw|^`~W*wf_37t&G-7zldwk%K>r7m$SJKr4R}-g_o(Q%$UjqTh5c%4|TE zfO~_xyKQbzhn$Qgri`2XaIG;lsl5*?K%wHeqW$t^MYc7^Wf9k4{J&-O+&eiX!hi9b zCtWTCKS*S$>0jip{UBM3<1pI=Oz{Deb@NfcMWFzs83QsTP&bgJBI3}?56`EAu<#jZ^(#zb?@|j+8~U@ zk!D6W!>&*T@vJVBiXv*zQINu(6js4md9D>M_uTCS?i`K@xAN}XPy#%!ht4_*ByN!FN!2tiASqmX?>L}g%Nm2 z{=x~}P!<>X)CP*5!d!R@CHb<>lf3)}c?RV3d)9`p$922xixy?3Y7n+N5VSCgH}6!;I3q!_@l{tYfJLQ@3dQ7FbQ8k3oKwQurbiQzY*li)9)s6NS`QERNvnHA_v4M z8Bl{G`yptym@o(wR)^I=3)}zS&%(tL^=Hxe*~gRTu9EOhr)o5&AWki7Oku$2_Ds`F zp*j&CD9^2sfkVt8pZx#8X(yJc;N)WggV;Q|e=9AP_~D1LuAPIyf%{-0kU>?X*JhLK zOb8~c25cI|Xa7GqI*Ao39Bc5?&jL4jwGLI-o11!}HPJkfY9*6uYf(_TbQ)AbGghxI zfAorVI`hltMSnfw6u^nm)gkX)STBF!kHK<8Fc@qFGuW4VJFnEr0|RYwX1iQTu2JF| z#tdShcNER@7sO!=-4|O7W^KP~@`B1zP)u=9G;!&MnE6?Z-xd1a+-6cJ#U1c$IHVsN6}3{6!M_~37ec6>*kk(nckpig@;?aqWwsU!Kf zZuP{62tcdobg~woFw31QO4WJ!nIB&m3d{ZnbI_%@&$dh2Krt<3y|T*M?bpTRlz3|p zS10Rtnk39M0qk{{lS=m{(7VzZxyX%=!v$Y=kgRm_569%&9#m*&D~}!Y#jo45k-Qe@ z^8JLl68}4lO;qIFUQaH6ThicaRKryk)wqvYEAS3(T!?>0`hj}&!tR2C&oBtur_2I> z=xYa@%-(|NtYTu_z0mOv-i}so7wd!4A7IBu@u2Kur)Y?em*C?Ep?iLi99d5&AH`la zO+0@u^e{D7K(nNjn!6+)koW=aE;*)27+J1|lo}7mUJOMX=2MoKze z*l{*9NAQ%B<0Uk4%BokNz{*fsA21x@yIIy!&JbiV zQo^d#D2B}1?xtv^I;F;StvPVGYglbrxp-pxf0!th_we|t)`V*+wzP|yKIHv(ac#}5hlgaKI7qu~q>exo9&@8Nn2x-vck9bOoBRF-SyPsp-{ZtuL zPEi|BEo7)#Pr2}pbdqz2s5Ozd3^?bNn9k2k(Qh(IQuZ^*^gDL)OtW)dRaI!4kttTg zXa=z6X{SeNys&r|Q@B9sc0qnxOwwBSvAqVoy-xdHtQ#1lbl4MvAksZ}d!6^qlOGkJ z*A~!#G@INC5r?$~0$e-=dNKR7+d=exbdT=ihz)vnp>aJ@9@{K&ADJQCmuT!zZ*WyN z))xu;?jNV%IbAHo^h=D#WjT~|6wQfATQW=cp7P9>Ufe~cob3JZJH8K~Q{Lps`dtjV zu05>g@Z&FHF%Vl1{9zP{7k8cU1s(;cH68B91H2^6m^j5>`$t0Z4PYmZ#b`*%XoD0X zQ2cl0F3ttpG@2F8uqk_2y6ZwnmNf2mLlv8!MG!WVQpWuf6r}9JE{Z|9p-egJl+s_M zvjQJL%g!xSAbJFQFbdnMg0I}mc^VZdGMuk27yleW_&uUJOSo}|%t?1B`t=L)l))D$ z)d}jUa}rffk08rPCQFKD8&0ts+jxbyk+JG_E%^Y5AfjinJD~pn*8aIuD$CD#P-=e; zr%>hsqFRjHyj9)bpr9DnYVj@jV3nDa6wA@gmW>N0#~>!o6r0E?H^gawHKi@R)@*nU zN#d3KJ}>P_FBT1FvQO+GJ!y^B+y=ls7t0z%;l+Dr$q(t17?qKZo<-?7i4ZP0RW}&* zDDUB6lP>y??Z8gd0RQv_yBWolpn`0PQmW}pDXW;Khb?#DZ%WX|?X(dZRb#eNX@9vL z!8s!(NH4&poW-jHyL3Tq5How^6>Fu8x?dnKCl~(FP;3T?FRPyF?P0jG_Y5e|9HlN= zwV>DacQZo@ zW@8HrHS8Fd$X5`=j$xs+z2|-Y6pKV)SVB4NPbh-}N{uNLjgW`PEVw6TdY^a}EItzPtFKfdr%5PH1fW3Q+%h zHWc6Yi1|!9o6-ZvUJ;{wz`KemacqiF_l+zT(#06Miz#uu$7f@usguynXKXpj=>46lFs(%(OhCHPlTV?>J(Od zkypI7s-CZAf<&o#sxqvBW`ejp?=kvdJs@9GOQ#fUC-jZ#Wr`gT6C>uRkgj89`J>rk zxq-a$7!~`s!SK2tV#Ps(N(7^En=K`vORIilP29MZbj~`8}n8;18z2-Db6Q zYwkEWB?>X)FU*Yh_Ep~yL@yJKv}dP@O;CYxP=N+a{VtA6- zv1)M3y2KG`Qj{k;k}d)P+B?h<)q=ULP*Qe|*n|MWY2MZo&9mo7%;~O`@W^soNdHtu zdcELD$0W&epEopT;_+bA$_(1mjxXm+j-W>oE4nZhMD5P=H`_nIgA~1?TU!z;W$-yn zZNbz=5w?0;CrQU=;`T5diOFS|j=4a36A(9SzrR=1+Mx*i0pOU)jN5wZffxxdI3z%M zXj-ccg$Pmlkx{gpTB{P?Gg7O0a6AixacejAe3W!3K!T?u%|evk22JH;X6O{W={0HB zYRroK1H`PhV#njoOZDnEPkF@ypQKor`V5AFYu@R zf~%aS=`^cnuObpKbj;MjFMbG=qxL>5I zq~-vMEK<3;w9~=C%k0|OO!U$lU5i>$QbljTbdC2gZ1vl((XfY-ASn^DttbR+ZCIFx z>kkVTQ!(rr9`>sKuy$fPhEa159OCv*UMevvPOoM*P+|wXgH-9Yil?z8Eoe z>_AB)c~V>4Dl9_u$Jyi_>zGs@YdeJnYe)0i8O_Ijr_C(^ols6~6N5406DCsD{?bO2 zv*va}`VWdnC3zn%q>m?}gX){W90rje|NJ!{m~|r8ka%}GFx!e%z-#+c(QnLMo!=eL zczR0n3sm&BZcHNbY7 zr0-iloW8@ShI=6C3?{Zm7BsPyD5&+}_=N$*t-dlvEO1T5epnU3q?>bTU91%ARuh!88lgTFHm z&b>6b9^HIHZ6Hvj9(Rk0bHF-9Fhd40e}DKtfyz5tb`c5nP0uIdMCWMg=WQqUJZI}F`74)|RdJpB#HYO3)sO^`YcNZ7+{^j;YtP7wt_{$W5C1;63z zsZGT_A=h2hhksI!r+EL;4DZ8LHf)G6Lqwo5u&E^;I1z~joNoY5r29Lzzor#Lrx^i% zbo)Ak{gr^5mOH*&t^FQ3KFmcC;O(mTK0vIzn)LHhSJG(BB9fxkN1KgRlr6DapM1}q(+M({DvMe#5wa)4=+?I z9h9j<#5zcq0Xgr}YwO-wgM&Tg1XBURD1eTaS>nIfI}mbFWL1cEZRUs5@p|39NQ!!6 zwqyWl6j$O~$Pav~4OOgm8k>)CzhV3pN4@@ZGwL(xMwEbPCJ-$^T$LFNZ{vc&rh@8M z_s{&CY^ryLzv4Q^V~UNK;;Ns8V4pGSRpyT0{fuiTE?}IQ$K8lm-{rtF_u>kUq&Xl# zIdL<7S1pMJIBU|DY8wUobC2~)VC4S5|4n&UPVoS{nvPxF)Uk6em-rv-oB=F%(+{wn z#3cZm#K8U$|KIDl5XeB0GF0_`K%2$p;?C4{%X}%=bQ`@bL$CV)H{TcnXn$m#WvJ-+If?@D^Rf83K^QOpNJ-#UvOgPP%XTqv zCdx{=UjsY;eFwtR7_sxuDf9%xn~md*;h;Mmnu&Bk3Vz>MKiEO^thc zTR*$qg{yyjF^N@jlWBQZrR};SpBnFOF(|f^nW(8hOlFBfU~(xoVL;22rGB0VW5;tC z1{d?-un~v%N9p8h?=Fi^-V$1D-s5OQyOgH#$r$?p z7&D59%RA$IB82XGHI}jj2sr|TM2xWgCNsMdj<<4N{UXdgjsfm)`NX$cu{Gf#IpylC zw>j1J&}CYC2*NU^QKxC`!X-^e${~x=fjvgEGt|R+mWs#&qQ0bhNJ$9fedh&NhW}8QuazXnG#RIRhPg0z1AfSOvIBU-jljvSH_NBxD2zwM@3DO6Yf`F^$ z%bh9sM7ihUTOedSbgfaOTy7UZkpgXa$X&9~R;9r=h!3Us;eBKRO~tNPVApu5q~h?o z?v!cI^#FyA2$Du^aP;r_+;nNnN*+6$LnN?wXos8HOK|dD2T_e8YufJ*B!;JeD>)FH zCw?EKO$2(fDwb}PGRx@cG46f48f-F|HJz*CWBlr}(~+J#QXGU=K(G}>6P89+e0-T? z7?mhOS%jBjO($4-$BgLH%@=UwD=NSZ!6se-aAPj-szi8Elj#WGChmMqYya7db~^5W zdArZGkxT8Fj~);V!F=PUm0v^MU%1F*P@ly3xIQuTV%mCjJ8L3o$~UGxTxWu?qzDG- zJA))|RD5TMlwwEi(eXqO9%<9QxtoYn;cV~`-jZ!G`5L9Ms2hn*=o_g%g1uIy@-XaX z{IokKB$dE=-i6{puHHKgjrJ=~IpK0byxXSHT{jxLxOuRKI_FVv?1VKpy`O?+ff6B* zrd=RmIZ@bRhVo=KC*JLbb$=W?EgUiZynKvBWun>;ifW;L01Fka(QTVX8mu$;hvLG8 zEw06D#X8+)&Q2QTfSMTxKuQ3JK}_)lsZ&(PfIS#s6f@SGIv`y-D6JK+meN*%noPe4 z9XrF9VMYgpe8~N7pahl)nR7^c1F(b}z^w_V<-MYURQhJn4z`N7Li&|HY+mO(Vb+L;D zJmaD@pM9rYmGogIuUZ?B9po|ZuX+Cs&Mcw0oJmmGEXl`=mUQk}HsW!em%F%5%mw}P z7zniNz|UTZVR%AngcyR2_rh$;Mo9ghsF%$+;Br5{#=|5nYKP#Wg#2&2*aQ~Z4V0{^ zsNYkJcq0*B{b?+15UYFY_7tOmJHYRkdEnX>n~Np8ucQljS=n50fRj=DVHspju^Eu< z0b~ZTb=sgY5}}ld$~0CoW=X~@MzMXw2cv^vBSCVcFEoc(tpsYe9|-+jQk_t;XfK8a zBXt4sPS6nz3a0(X?@Lk~`;3DzC=WFiAof)B`3fABzP_dEsaRax?r9;;Ne%}oi(Go` z#iQphL1BCh1nyZ=W33igj|4I^6@Zz}GBX{V_6@h-$IF{&)K&zHIT>SzM!bHAJP^$- zG38{!TH%Vsb5T5%SP#7S8>^@zYla=G9ArvMGeNkNcd?^@ySBi}5kI(dq1hYCCm46% z=sGdZe9<4;r4lp7v7W2s`vRy29GR1C>1LP9;mRSw+Kx%n_!mE1KI6skbjc^K01daX z0X&=AbMv=BLHY38=v}yLIA-Mm4JSr)(Y9RKU;BKN9ly5s6ZGy?oaOG?VW#wDM5MP|G*hL zz~X2Upa*J}m<&*v^2j_%9kFwphZhw`pUF}A!@3F$0AY59`Qvx?uvZ1 z#e)l4rN+B<<>aCZDGrUhc)4pMhU-5A#d+zMuv#}p^{q7>$V)>|!7jc4gV95*D8=`D znj*I0(=q(%pFLZcymT%_5{WgcgEd+JNQ1aj@u7xllrvFN6}?H}G~}*lZl@^5+@mo! z8b|j0zNPl)pimRtY+zbk?AB{Swg&-@>_E#Iu9Uwm z9lWR;aF)44J94z3CKbK-yPs(+m$3(h`-||Bkp$7KZocCF7?Yylz zmrhoWyHLa8NTzAvbe|8m!LEs|*h47GYEa0juhb;zhq6mci25M^2`D*(s1~;H2d`vm zkIUOgWs_9M8=j&~4I4}OgTP93d~B@yLgg)WP|K!-^Z)d^d>a8Jvc{+Z0V!M{#eWX= z`Ic7b+r4L$(pw@vk^fiZt3UqdXpF2C@gR z2FON^ec0sXI?Njp?!~;5!Ef&~^EL=;G@XQkA2;@7XFF(3Ecy{#d82rGy3e=t@Vc6~ zfQhJi`qKw>Ei}|{eX#Zcj0zBq^`^3lOPH!X1~s03$5#;q-WJUlH=wa1Y0SaM^Q7`0 zy5=V-SqrQ_%~)-^Hh7@Bh!pdk?kScq5IoV=7CO7~>;x!W=6Qqd6 zm>>xgwCojjRWfDdQsufdxtz-Y@aj!?zt=Dh*P0#p9k@n-D?G$sOFr6RE9lO~V0?q?~w9M^xHzwR~tw@;;$sJrwHZp>;> zejy7&!oj=TNX~8X*!*(;$?#5@N(5ZEa3rT3NuwCHc8q*0r#u$LVb9|L@J-NgSlHUM zG8=)69m?8K8kw~fW{7nn@M#dk^@oKE8-@*J>3pQiw73`ijy#VyzlUvCxr*TcIH=S8I5KC}TFy}X%ITj2#@x!t|YU|hPG7SVv*S_#&3r`{il{HoPJ5$ zyoS@+T}H?ISN`~qv`u>^Jyzw?BrZ({%TeMKT0*WZuB4sQLR>?0)&Zrnc+ORN1|A2^ zy8x^^V_=Pc!weHr7lwHZkNq@k(yJA@)vei1&uZ2M_e8K({46ZBW?+!|m`f{soCpjd ziy`E(LMbYtKBod;721t~1{(=c-qEXEdFednY4;+EaFY6k@wqF+SNA14(^w$BM7Cbf z5{?e^I@*~6if;9p=E75?Xx!t<5e{IU{$W`RJe)cpPYP2~vPD^HRw6|B8e8ro({H9| z8O%B=-JFK!leI0sb^|GwS#G`!8&+RZkEET_T&aBMtAi~CWAXs;UDzrJ6L%{Xv%zFl zG0Asf<_eM~0$U(Pp2g>B@dCC$Pse`OtGh`SD05yiuTmeQeg+MV;#f%i5N_+27~@WP zJFYVO_Lk^*lls+F?e3J5EWbYMuC^9!L5XLW3xDX!tQ&_%E#WtVYlA#Z7Gx#S{_1Y1I!-uR3nF|AzPKF%PtFmVO z(h4@I71V_hN&49rwO2vpEsz*x0r}&=9H)8}dij`2W92%4|PYiZV7nFAZ|TM z&%%?r4RRFl*6*%eXO?nsh#{cJHJL!8MH{fh176^sKmCfyk7DvSdGc}z>)X@YNl^)r zc$H7>r0XM=*BrRuBOV+1@-3xyOQb>?sVd}31nn|t-QC&2RA*t!&PM0enLv4eMtMl3 z(|e^2X$}XT`_UBuv5)mv_j3q~td#l041V0b^~ z<)29Srk-{#lL?LfOu6YUv)x87_*hcuzo?;z#PH+bWuvH@@Zn#Qy~)a)3V?GU6MpOZ&!4#wqn4^3eu($zk~jb?VCA*}TE4tT8&h>E zwHc&0?g1^^7`nEV)(n&oO_ex`gWVVE_#;>Vg9uOX`wVJ381u@IuMxbJ4$dRnq$q~A zlbENC*eU#G6ff|sb8t4fOE`jc(iU4ECBcH-rG{fh(dE#0qqNMa_;$*{+3V>A3f5Aw zT9=kbf0pbomD7|p9=m}}+8`5nU$fE=tE;+W5=uAi4k8eeF&-H0wyxP|ty{$J$+JF( z91LM>Mkf6IffNK%Q#ePd!v7koxKXO#vhJr%v69<=;C(>O;8iRA$=I<~oR|0al{JgF(a}I+2YR@XV^99s}33WZCYS@Ybr3AgqHcE3AdL8sQAg z;jjA7Xt6+RYnCD04Sj#&9{fh{){x}0xWd5@r>PmM9nHl+ZaR*{Ciz$#& zX(7mh9&UC~9k@9NR!K=X^`YeI(b39PcG(sH>2$F<9^skRDehw0*_hTKQrG?Y8Yu*~ zh`9ahZ?Q4@2Z%5#-MzR|)WG70u((lVI2$jJvU$?*h&Mg-Jr3)3fXd03k?4gQ>h6>z z;<5HD&@Dh@CgjNOmzq|~sWW06p#K%KWnTT=_kojJEQG+iWCGaCO4Xl|aKb&ytnI^7 zayj{T2T;A5Q9bVJk}WzBLVm?aQ4Q0nK#j1Hq1+3s zUzhFU2bHesv`gfMCB&M?c=C1Yu3waFjyqeltSoah*JSQv>U~&g;8d+!;N%`Bc5w}c zcMFJs4s(a9ua>-GC7aDF`at#0)ZOsoN|9HzZg#dUEh{%eoWgc)U_x{eIP~I8X+q_; zlbXuHP$@|t)Zc6f*v23}@d+f}MFWtZ@tm8lp7y%;Wx?N!B?s`=TPocukvN(hRSky* zV5#>Qji1Srp?U+8_2J33R{G){iQ$z*HBMqz7@lr+4}*t{;)|Adwo8k<1DGylbS`x2 zZ}`O*^3uqN#?k|M=`Snwo-gsPdP31WyAp!~$^lkb+nkm6Yl&fjYdXR%CPQ}&U?cg} zp}=L54Wv_lS(;T8gzF|?L(0R9oKci8f%738!VrWCm$L#a_O*&rOvRUpyvpuF=Uv(W z0EMC~qhPizNKc|5%6@Fo$jrX?YMpeHe<7- zw+=SIkgNJx&&Z9O4*j`|k$UXV##go0nYC7q!)c?wn&MkX)%U#5pZ!gkC1zs6l96pi%1Z>Wx0_YxnM%F&Ug=?6{|}z;L7uU+ z5*M(8QN&i*$&t(^*ZeHw;x>~Td70aljwjMJq0(i~eX=N0@n1cXSn*E6HXprw%}ID{ zP0R!#k1!Z_TfX!aPOk8GkOyKH8L+#9*oVA-b<>-Yrt};`U1i76-r%z0|`TUjBX%(q3ZuIymUJ95=6%0sb69?g~*JYvyRn~3m#OGf8coeW@6v36_bxzXk za719>I1CIvyzhb6VNo$ybiBC%x^HDYS*3E#PbDS7D5aMpFjm28BVcs_Z?A^l_Oiry zEZmc~SF_ab^)2jtJ>aV!E1O!a9B6xp^aZps`T}hC5+kFI-ZJ@O8J6k6%hWymuTED; z3nD%%u*pTN5T5ib;S}4j1m*Ri)*&rAATTIpRAvSkemcldnLln)_OVmU#K%?m-x@>1B23( zr#|lhjS=j|NA_Nn?;}E;mWeQXb{g>}6~OfeXGE^IdKJ?vjWNpu-+wcDq7Lh-V&pb- z#0-a-Nut-+9w*stelo$s-6vr>hO_GGv7Y1-%qTWvCj+sQ9+g|)(JCh;I+232B!|I{ z0$OSvYY@FklW>r-W!o)w(H#4|$;e4~wDK4&ra~BQvUK$=-Tsf(#Ni4FM;v5UJ4V~k zP770xW=+`NvzSwaVX<4h*Z@B$af!}A$yR_GAO`gwRx0UqWZhBB!OQTa!8XJLutA5V zmq31-yk0KV3EXplKMV%B3APg; zhR!@aQ<6Hx#njyQl?QPtU^#TX>s{#(Nq0t+mADpMa01daw6b@(1Zn9&NaapuyI0r0 z5lHDP?z94aag^RBs;$aPXOIJh6RjTEfr^xRJxK5iEWxRz{!z+QWiA4{-_* z@2-D1NHH2c;Yn-0f!)396KJQn51_vU(C_L)(@Bg6Gz|bvfLPedUw0^Cy~&V=ldwb! zTg`4FDFfMC8!a+GnnMuHg=xO-Q_1nSVQFHP*PkVXyw}QGj!3J{hWf6_G+d-Bin&&? z0iyULbIp>-vMQ`1PR)m`N z5F&d1#2{A993mTaMZLJF3|nE`2w*qyXIXTZ@JOp`3rK@0|YVwhRhR<4|* zUqs{e`qCh%h;o42AU-N>Suq4sI$0|LSSUYATiZsPW+ns)Mjv zAxxw%4_A5U?3`puMM}>_2T!of_b{JpjZgic3HC*N=+g((5r{Yy1`WuF}P) zSIo5qp6kt0$n+;*Cxh6XcI7DvT@)NBbD?9f!7LuU=TU$-#0CICPgEGhq0%`Gq|*nv zm9DI^>kb#lkjgxA?C>vDD^ya7)Gny(5fVq+|7E6hfk`skL>=^0JLF4LF8W;?199bK zT5xkb3@H4Jh4$CVXIe|Tf(yUw-j2g!Fl`_Mbh>wq7kmjYH~#gge#&y}4BcW7XL~ol z>&YR7msKV~;ts?omc{2>lR~OqxgG$#HJu6TN}rn z^)R7%0Q2wlvD36}33gMKz?ufv<8$82{Z{R&X@SO`=+(GvU zXsiWfiVw?{bBYaEE}v&I{NDVEWU=$8w?Ue?K=Eo;eic6K@4GoT<+%tK_IZ!T1y%{a z;YVndmoivo)B!qwVz#b$q}v0JqVys&Jr#2gl?0htLewjAT;sn%bv4hnL(%+B=OH1RfmZe<3npZ<@r3JitX+mMu- zsEco?HKjo`nzi%@sd7qQEz3E-qUz^ut!Yf-KL3_o+9^l2Vd?-|0~*lu!^Pv=4Ve{Z zE|N?EYymaMKz zjvSgN8+|3IGD}2&QImPfPJVXm;+AC_c-(VGnx4=K8ZQl}u4lO-p0bHf_?TEg%8{;$Rgh1rY%em03zDQ$z#= z#ImP|$QF^k;q(7{-+PnXaB{=n=i_<4r#bhGcc1sXqx7IKpCZJ&utEw%$S)8f==ZjA zXZ50mDV#mpEPe-gOnusUwRKQ*58ch8v87;)Fo^el3y}*+xO#7T-M}f*Wh?#}MZ}c9 zd?%{2A0i%n(*VbgnDS8>t!8A>r5DL4Tyc|P#R^c)Y?e&Xen*0EF>)r4jA=6Eq68Bq zNe}fV+&a7`26y1CT1x-MLNC%9kq{^50c$b9n#B*!?0lVH%{WWy)9_P}9kM3vO0%}^ zkQ)Etr=*ofW@y!5 zoESrV4M$K#=*P{>2%qVTG`KXHVzs@z+7z!D&};)UY~dL)r!=o4$yvp)iJ=zPqAhUx z6JTZ(Su6i&U&0+<28IS=DET|f{}ip5EY@QR6#AR;+=5Ajqe7sizO16>PAOGaXM0>q z8?{OiWWng1=LZ&cF0qr(u=rw1U+*XZuB}S7ZSCOBLSnwxF(Hg_%(Xb?{63##(B+BW zvPctZD`XB-Ra`bQ;pb1$ujfRk8;<+sIo|Su(%G33Nynrm)2p$V1>AQ6AdF&>j~!b@ zAad0O<`g8{R>r{h zO_FsRZ15|J2^T?%c{7M*r6U?jl7e54z0%Vuh<6c_!^SDPrI83w*C5qi;F-7R3lGqF zeE{=U;I@$Xp-G)nl9{fCkh||~W58G$INJ|R_IxXCmwe;iWh@5cdODMbcl}Q5v$xn2 z5|iQK7N>EyPGLp6v-GBI)Zfb$;KCw`o+wRZ;UPjR#xlawiF7L_-UV0~#IDkRwkuW) z#wRIe5eVON2s7ueevXZp3LJYqlk~xV^L<6fq$W7Xu?bMeU}zz6xJiaZA~ze}+e|RM zGI2yIaDG@S;AH7)w$+PL$EpKZKo&293btX#1|eKRd_9uVIj!|JS0QK+PiiF{bOpD_@!N!*3D? zQMw_4CN($+wPl`y9}e*P|EwJGvt(`J)mZUm>;8^4u1C@CZ&A0>(ek6QacGRFY18!OZM`($Ivd(tT7#n?8zQ5eLX zmC^O3;0jl)l2wUS+6A5eJ>)5p$9?S7Dq3Qv-I>tu_v!Si&-DQXTWlJbS8)<0V*PWx z{-cDi*GgbR?>faZN9~Ctd0e4HpQ+Z=Uvmit)MVrqDM${JmUjj9x{IWv-W#y-Dx zRG%+osZeq@BnDgaTXE(_JCpVPYOSDr_ z#`ge&LZasN{|u7jM+t{zPEqKi5UA}E^jyvBH#l|JOK`@ZMzx)vC@SN?HK!K)$G0@$ zEhzK##rh_!Zxpr4jH;paIl?KcMmKPAa*E5p2WZz?w*9K*S8Q{xAz};M#%1=J=z_1bE4M{BqGGM6fo273Y*AUG zQ)dE0P{DRDvbJ#C?g1>B%yb*Fs`e&{#i_b6=g5?WC@2R!;t~4#`oqZ0tK0TvOcS>_`W4_;MRE9 zQwM}wSf!=v#O;)uA)i#wCQl* z>}1ZeCgz-y-ix$`fybyU0NQ?IT1e_UFjp%9*%$?6MiVCfpKAP`e%T|k8~%X zN=j~3eiQurJ*(){>z7B$W+c4UvB^$x32QgR)JXR&^TqdC6!ZFQ{y9Cl)?+Yy2t#3P z)7)b+v|?bqTO5Jxuzi)M9e2I?M-q0`TRZi_g-~O@r%wk7fG<6KjqHZO;A_ecz#Ti0LVs{xQ4h=gi=8ZzCqfrROw@)a z`dTxQRSd;MZ?S+_lKA^liR|h6hn^B{T~G=jKfz@G%_=`thzLWcF!U6Qs&C6InkHQj zh);3LL$(m$yA3@0n5X@&;Qk^>OqnA+Ro8a_6}6b1SNhW~xO1fA$TJyft5>~!K%(Zj zghU6fk0Y^cKW2`cG9UaSjdDg>5>m~=j=6>~XRIrzB{za1k(L~dBqe*a*b6~+2+JD9 zhJwOtB>hVE0-Bp@42G_lcL#Q`q3Q5{q~U5LhNdA#C}8y~17Kr8KQH~J)H`hpZ1!Mc z+Fl7-du!3xU7k6tA_;S> z#2mW{di%};=NobZfaiBU*$G{dpW+l(fF&n}6%wcVev>CrC@_^2L^`iOaNMhi9=Q2F&=ZUP%hL{3zWxGt5ZA|B6EU7JSbv0Q`M7#qHE}p z8Zqg3r2ZU#AAuRsEpF=7T9QbiCOvkwNzXChHIBjZzcQu&q#AhiX4t=Dmr!DWvFg$l zKvYIyu=&2`qc-tU45&pY+yC|@Er~D$tW?TF9Ki8g@ez#sJ)5Ma*_}xwJ!=a^4q_O@vv1sZN-AwU#K!4gdpL5)g3`Ee66$pdccH zsJCCQUJGfoqTtCymTUD_`xjt=r52VXrNt zr+1}i!!juK1SapM(_BO!BkZ7;)BM*!_g_)p34cAqe+>%b>!K|^#v+%$#qX?6(cd>ADFQD>a-PF4|1x@&2$Ww{uzc`%Vu@|&<^3oZ$to%v34pG zK)ZlEC%r>-?%OAPKu46fLV@-H{X_e74+jZAyD$kTi6n3C*B7CH?WYi-rvb1+qT{sp zG9)q}*rIxwC(dXS#(oCib`1DhC&ipNOZ0@^B5!iX{q>GWl9WTQ-TZeJLt~iqJBQt< zA=$ue+;~TC%m){4V~*`|D@)**cVe7;`A_cV%OEzxxJ{%!Gs%Id?4GlML=M) z05hZLK5gyWbklbggBXhH@+MJTg(&r?>prcIx1~S@KtxTT=1pMFC_!R z>*3IU;9sbZ8Dm9l%-D(P;jOUx{)*=+9oGip7V{!ARBs>CS@}J`BX6+pw2Q4Ne3>Fk zymIo(tL8~~5C}MIUJgkZZImE~3YtV7W+4glb^|(Yzh=iiljNWcw;MZ`k?9EXIt=Lc zTm445Pt+>y3fxBV8K8C_qqcuo?Uu6iR$nD)yy9%X2K26A^oCCx?)$3EDKYgSa8ejP zLu^;%j;tXg3+JoE1Z)bM{I-^Jae1MV;xWPivA7jb z!@K|fN{HKd=6Q%LBewjMGj+hK`}s`Kz9+PbBAD<;o-ppl$s5{;Jx4Oi79+3>;-n7a z+d6IR_Y#lLV}<8lzXL~21=OuKx?GoT^~zJEUCe{}p$C4{CG)kURpeqxDqo8CcN<@% z(26D)BJ&Q*QF}8#b&W_RREK1_iBlVeBTTO{5sj;jjb6Yw$Nrq9WQ%a1E#A!HOcVmo z!GhF&GEf|WhD&0@E5-j%1a)C(GAl!8v%{SwDag-vj3DLxPHcnBI*9!`{ZAYsPGMpy z6lxUdH>z?cRjx6A6JQ}}p1wNgYl#|2=4vEvORTe;>2Rd~)mn+uSk1w!jauFQ<6;O{ zOBg{ZN>{MlNMK=9Gu@&|1X&AsDcMTWms=#VmmuPdM&0qZ`+Ub4xcC^QA7uL4 zf>jj77FuBoNU>OLUamFKBNE^Yh;UdE6GRpcvK#|vHak0-#EM)L7F@alG)pCv3}Tl4 zFc{Pr_6iT1y?^>)$p%!ME9BHv9)T$G_!y`S5i8UF_ow8FNH#m{Q7C2zxpxR6ElYpp z5Rr?ODMZ>J=1v>BMv@J9Ch|6vhhyn@K+YiM=}+5A1$6W$tU1274SgcX zJEfcfP^XkK$in0UnLn1_cx9{hs-bv~(Y}|@eF=NcVid2il~#J2CsU>R`4A|*KzS>| zRz5}CH&wRtM(Xf^B>=u=9WikkT58z5w5*ndgVu@pPlObfeZA7z#% zvFyva@kJAfBo$YVha|^?@Bd-}nCsb@RSd_@jM$k$Ymo9V@mzzsGF zL!x=%oj0CwO28Jlf>VCXHp{LXAL}&1n*f}+kGKk;wU||=D7_gCHQ4nx_rewXNW3<(rM9GP!$aEMPv6dKzC<1hR z!RXxYW0O|S=(h1D58t@iKw>F=E>e9-w*j)h8Ei*x3=4RnusxPC^HFvQyFM0HARGUD z<4y9ARum{Pnh$x#R(qBtq7=`S#_w4di@nWz|1+SSP3yc;Sd5D7Ir)X^E-?B9qvG=F z%jHS!dCV=Bmv$EZ;=vDX?RrV@rS#DhWWR8+f&@f^<$=|IWfAtjfPjV4 zs~tj$k|UxV+$4~mr4^M$ao^Mj)hG&2Kg+?hQ3;M@tC$Y~F#@uwaNwKWCDQafu`2Y* zPGjm#90J4{MTw-~;gVotYt|EtCbnR=2e8``H=8w<7NE$2l$c11BPrhVViyiuZVJQW z#RCWOC2K-;v}@XTG{&_qpXEoXn>!EEj+l%h6BDf{kfI=y^5m52Y$6_*jAl%he*W+v zk%Zwf7;Y400(~})p-km$44`Z4@(w7Jnso3Vtzt=me)FW;Y{ETe8%yMX=dT_j>{xvS zCNCt)_48L-iX`(`z~BsUTrO#*cQif>KR8+!0?kp_Wx1PrrKf0;QV@?x%)J$!zrR)@ z1^bI-U{=bR(?x5lsg+_V(4_$P$qGEEa?*laNu(+-O!U+NuloTY^C_=i#n&;cVhN66 z#xV?{YSQY}5_z}^)R5{`LcdCaze1Q_UY@@2uJ#74KEB6@%0LPx#Q$pMjCoZeQ(T$c zoj}}1;B-KG32(H{0pEHM;fyI5v>$Q_eJT(9IGB7tlmboJG>Saxi*<=^s6Fv3zIO*< zkKGxtJEM3tr>a-8OIImQ_A`+ay&h(Jwd{{xhMH2sHxFF32EW418F;y=1U8kckbmfU z3mytYtYEHckn~HcmY`#jBjWM;U^Y|R74Z&^ca(S6sO*0_1+Ksbz62T?-Ar3a zCi64)I;w32iiM!2223cg>y8Q%OE9V-k7}YjDnu;Bs75?0P!B(LE`+uj2SDtR?o_SB zcbMvRo~mWpGP&B6Z+iQs%h`4ujy$7A(I)4m7}=ht+GlLw?gd1zV!<{y#ZetPQ<`?T z>5Qti&SyI7aq|pbQ;;VX*i7t$+T%sL1J4OG=sr#y@%f%&w9+TVePgf;ABwd?>PAHB5ZmygDqfFrT-2lOLkKy5X-e6Qk!(e*nF^EzAWh_|n5LkO1kXT5J z>(@3;^2ym^Yzb)6$K2l-v^p+ufsdl${4S>wHL&mp54_i1x`466$wNFfu4?YTPR#Y~m0& ziQM5I=hW+|Wn7cV^?JhZw`3$eWEJsglJA$r6s!0S++CZ+Nv7^TlEh8ygWmKFVrJm6 zt~>i8;*z1U_U!pLM|Z`#(h)lQWVCaW%jHXX~!-6nC-yGG2df(w&ylZPatg_LTC- z1}98p(9O@O{4=!-b!U#6v34#kjkU|b*qcB7AKwvzu#7EYKFo`9jQ#~K90bLPQ@}wz z;9!BCbinm*EZ8QD34DqBOQc5N%U4+ru1NaGB%2nLD4F1h~O@cGAxQ4pRfVvm*!uzIoIHOn zHx*n0XvKj$4dUSR^Hn9aLCc{-lKUoP!g~F9y<=s!HJ1;n?#?3Kk~+bDT-qC9lMCf?bFvMEL6J7Y>Ds^ldnIysOg3-mUex$^S# zj0{;QE7xXm9U`VPFLouc!*&U=oL%Hq-(xuD4Z?Yi;_tG$rKX7Bk6`9&ILhDpXSIup z7_bb>8^yKh?W3e!s_`RYAkZI;q1O&f`c^U!T#v3A)w~oMiPp!RJTRqd(PBU>b%*T$ zZ`%Y0;LW5j&Pk3|uJD1fh&W+cEM^q90$(a8xd`IerDC-}`pm<&Dq)#hIqw(Nk-M7E zQA(W}hA)ib?#&853O+Msife#v3qa)V^pmnWb2piAn{yo?Ndqu33MU@86)M4osnuHn zPQd6sjKC*1^@>&z{u;w)^dbo8Nx#h*T2P^oL4vEQS`w}jKQR}JWIceQk{1B_0sv|d zh1U2iHVDEMt+8AiCd49ogUq5W2ED=LQX=SRhLUw_RkCi|A!dR4ke0Zm2U}<=9J?j2 z@nU}+2BduKl9=X4UZqt3LkqN56&4}53M%{@j_D?2Y^mh#1Ef)k+QV$`07KNa*C?mqT;RBzNZT)XVmrR8$O^bb>=<=Vjx{nuQ83OqPLn;n6O$~ zUajh_%=h#ZZ4xI!oPkQ4$dbCcKHBV}6d*Nl>`Qiy`GCfN5i5Idpj#70rCzcENP zgOoB96dtu#Rq1bHSiN%HOKD9j^y7&#!Kj5cil!pdsJN?CeV+#mQ9n0>sDCS)>VQyK z-zw;|)%YWt0tQW;pq+;)+WiQJf@H2osSdaRTn5lzUvn>8Mh|X7$U0SAEW06WPlLM9 z%dh{M;@WFXD|h#Z8Y*2J#73Iks(H!dPKEEn?M@x4j{2`A%@$N{&U=znRoufGZ(Vs{ z@&Wz@9jsBEWVN^RRcT6rd!FbB<++Y2H~3&kwxm3%Mhjl#lPz49t{;x`E;H5}Yc7nD zw4yrz!ws!ykaJCl1A}NkLr1buYHMZ8Nf8(Z(WzYJV%lpq=O&q`E`vA(Gl8De45IUz zmw%9U%6UI-^Wzc-a|H87mo>FseF+Sy>G;e+FrIGDnJPV3qF(Jp*RUV z&x65Y3z%^NOOJv5LpMnru3Exyurr5G1!^uc^adYXS5A^O9*?-0Uu^iBviK$lkVIpM zTfOAOAi_V{#mWNL0UN6N1XswxGVjagE?PoF#aSbrA`^Igm!b3CtsiGde8o_SV7;bH zJOUG6WWboq)n6ht3UNzGN1#?t?#5TUS)#o^BWiiEVy+4h;o$oX!1(*+#(GsrRqE(w z!HlQ^ibvZ7T>%g7DFX!mf+HmM?-d}~<*8H+%3@88NLG}y6G~$$K0p@*%}%UhAa=45 zJF)5O2rM-cSat%-HXr-7ih0;?Rp!vtAU_r&^Z|L=D1aDll%PlXC6F?&rm2Wv*rKiZ zHur)4neA+du4S~1@v~vO_!JvXWwQJ*s3F}M6(@ZuoHmPB8Fz4@P7Ea9IXeS!s{k&< zoOr&siZb|q4u3x>Irgm9Rmr_7@M7N^zfNP^O+MIin`ABXi%cxJfkkiVM#^EIe9-Ad z19ZoT5xoJ^vJBJDZ+%%z%U9|Plqosdk&>Lij$&>>a)d`u^)VaDQ)0IA{QI;S@0v-o zb{YytW#9f?y7q@=g)YE<0Ya%vKi$8Ig9O?O755{Pb=I0TL$sGXZ2&#RzKVT-M*!qn z)~(THBy&8~7Q`k6Y7#q4igEK8h#LY5F^cTug}z(sP_m3L0l9Qr%J#$N<|Hu-Z2lh8 z%ltLfuSjf8_W`{AdHiRSaH=#GPzw%bczFjX2|Grd#&IS9RtVUb@%K}S>(o3Uw>m0| zsfs}yEt;|Xk^k1}8h7q?9BVVnu*H5rU>8vU0clVKegs*|P^%GN5mibgl^6-^6N)42 z(g#a?9L_4v;&2l&3WYO+X3UeYD;+`j&ncPIxc8E^@P3H+xtHd(WEN zx4p74@bsXjVm4J*nU4r^qu47=5+sUak`FM+-ZhVZ@rnhcwvsJ`9R!@t$M`kqhsu&I z;wtNf3NO&jGnhX1Nvnj2l2~O7Rxyg-X8hUYMJ}zS#$|}s_^mp4@V6NQ_DVDe!ZEvJ zX(;Np4M1L49FW#%B}!qQ53$C9gAKfdo>D8?0?zo2eqA%Rx^!7mMJSnI?ni}LkfLL- z*nt`2dPww4{wcFpv7(w#C!3jmpG4B(1>Vi7)fR-;%g3u?2)Kbu_4X$Zm7tp zyMXMkETew!-*zUsZq)EGZOAd#!v2n-{AY6Z0m)i+g?&&-El*@-2TZ#TTlurU|CklL zHl4uz@qZX@6z85d*dk70@P8P5uH2GFbU=Rr7cE30)VBp&H;9Y?nG0zXZ8)n1vs1o^ME}r=W&trSP#rUh{yf>r7t8a9e_;s?>l9 z$V?LlW!;A^XvDxOl&Mz{kgUT*Ac4xLA)+Yrtj|bFt1=(PRmS-X-~Kk6PQ|B}BI?B< z(1?wXUp{!1ZVeLB)1o!*+pjSCD`!5_9*AObs8tu~(wf19qbj*&pVP&Nclj8nZp^2y zp4<2*Nrt!`F5E;{foo5|^>2pjOSkoF_YtUyLm-@mctgru`EQrV7{hhkOI9%1oC#g}Nf@2`kNlg1qGE0rsuA}rhA@rm}+2-&%LAf_L)XZ!dfpVb>a5agApf-rs zcFN$0iH{KP;BSR6ANpwKzT94t#I&a*!jD^U2Vz&Vv8y-j|FcW>pX*^kV~H$;~v^XKgsDEMZPh0u>w0>JZ>Q_Iq$US6*nw z2md5Dq?MLKJrPeFi-xt9eIXQ69ZdLH?zg&u14}h+m@G55njCwrIK_h4DMqq16f3{L43(AJ z%ty^=M7L59p4}5_wG6mf%X`fZ@7_wHBo1=0P(gXo6wKNXn?dSHW{vGyABkd>*~~U4 ziuz*Xq5-y12a_7bf?z-XGsJK$z-G&XQ5V?nOwo#SA05FRi8j$0JVWIK4C1TX+dFAZ zE=BBGk=F#GKLQZ9WA<1Q{)w0Uuhe*^ir%lY%K64_`=3@kC<%)M%2f~#udsMnnt4Yq z<4%m@BsYs&)lk&(T!zp0epCXSO$Au}TMR~hQXjjsioy6D7eV~K^3aS~S}zOIa>B#$ zhLJF$cSKxt=fni`>`ibee-SMKo3DAptMp-mwl$c&J;P>={qw8TX1QChz8wdU2r!8V zEK9b~dC<90X{5!yPzyZukOOOAwsw-a0uRXCJ_TT3bFiO3Rtt zEW=|tmjw!TFt*p*$8?ddFeoTHBHGTb7>(9i3d^i7v%u!uCtb9nnYRzSl|%OUDKwJ_ zf9s+0&oTL^Yle7=iOHNm^%MI?%Ot+_u%gnrw;gzZAY%|eWs>=V=Eb56e8PKJ?EjqG z?GNc*=z3dFGcjm)R{$rY*pd0$uae-zGqtzAHeu{Se6zz|LhhBKif&74U<+K{_F-6S z{4yXjl?|ronAf-53)N@i{16y6b{4V02>~M?Wc{> zK0Mr@+zH}9PZVWf5Jz+MY88?OEstr-gK-VwkJ|@-^vPc#H5R%fU%9K?YiCR_wLJi{0|`#UT2YT zBUi7^A)#*qOot*YQg7y7_I>x|`AT8FDmcr{;61XJQoX2qvV7aTnwQDZvORI1{*^Ltk>!SF17^KgxHGMI1!3vuQA#S%?ueU znKnw*P9-SxG=N?nC`UR|$kR*O9WnrI@X?6M;H56uWr?*jO3Ok+`$VMJi+6#P;mm)f z4`=B#rec%3IZUvbjJ+}g#(ygrYc_s)PbMIh#dOqQ(I5iWzSu+Bgxe+HdB~tt_8knX z@&k11G!ijW7Z&PvWe^oAEESSkQmYAhlDD5?EVZ#Wh)NZ_JFt;TOoa8_4cIh_YIpX$ zsWk>7?DiDO8=(S`=w-1CIQkAasuq%RTRIQRRc~`_G>|lusqLl1pO2Eb1GsnR=(ug| zSr|{k&>(6YwhSdQr_w7BVyG)}c#iT4)ZbaCK4G-Gk- z1Yo9yz=u>5kZ6dBO#^Cg@e(BV5eNvUR@3`{^Y>XU#oRfncg;_tYyMe)z6l@6a#*i| z9)YM4z;lu1f;HrsU~#UlM*X-(GCL+#=rT@65-Jbd|3MPg267T-_TC}U6S>x?8ljh; zG84N0D{R0hk`F&AL67#``wZ-C>K)prFFo2XRT=Cw;F9cPcc@#1-HpO1gRl=Mr|+I1 zbBybfHfM;W_=TOFOPvMrNT=iQ4C%~74qVR?S2s$7_?V^tsKW(grMnTG8pfceex4mi z-i0HNx)XLuYgnPcI=!fEfbK_)FiXv~7c2Nr8JlcMQS`XQCAjMG?Y77K@kGczA*tqdNB#~>xKbUvW@9+Ur~3hYUw zaFQL6;1__1MQeYGrZv378(lf&qB%Cb2B$~K2*+D3>B6Ffx`cHJGj;9LCA4E7?3y0I zY1cDfLE(ryTl8LNsqfNKi0dq-`8ECqB1H)UXYs(iwNr#-jkBR>_jHwktBF zDd@&*vD*?+t@Rp!wTyiSKZjV7~L=CW1);rAb~IfFRq0f1FZ2LPfOre_8u^pgmdokp6- zjm1zleVBRAuia+!e<9MiO$$J=KQintg}6E@!rBtqkgL%wS1(r>eOr6WwAkII>~8G* zFmLf{h4lJb*N5FOg2#3hEx}Ukmg7R*X9AMhT=oPc ze@^lU0;wBx$gQ=POH17C&UbO!oSh*K%CXA19im&zkB-|Ji2H-(#@)jU&P#Tr=UKt7 zJS&t3ct$eD?%j#<)$ft21ftg=yi#nPKAbt}_h%hLY9LJnc#)1(1+ET*cr5xjcBHxk$alzjoDH;O5$!q}lv#z+sT2L!*2YEW^`wvWo!Wb3fs`!RC+_`3tJGVDrxB;+vwc_tN+Daf! z5F&Yx#3jh+gDj(8yPLhPChW4#y*l>k?n<%k^-P9FAPEjg4k|`x5RFpwB{Cv1DJz4b zf(_#JBf~Fh^)oF`R{UA4UVzmLiNGVeG8+!w9H96G93wC#VUX-301L#Xu#e$7xQbMB zV8x@wwKq~V<_8bjhhPy@20Nnw#@(=sUN@SEWNP-j6azkHfCL};tPB~$9KfSSrJ|}1 zi9V>CNg$+Po~ZSa+eakD;LgBtD~5Ow73nC0c;iUB0n!I*=9Q+7Xiu>7eWvSndFjCt z`>TE`Pe!u=K)Q&-w;MRFhGaIdgNdsbsKGpd)H}SJ4$bvLAt3^DpmwG)&2>xhQ_PNp z;5p1mSD$WqGct-1;7}UPBKiVQi`ZD`KC8da2FZ#Y-4|cZW$D$c;`Eggd^F~3h;oF1 zIBPB+p>ImC*CVM?fPEEc6iqt-@c#ae=oGm);uNOS@I0SQ&B)o+6}TqK@6(cI98__* z+&+gBU)=b<4Zf!^r9xtGbEP|PL|Tl92HO_}GzQPoEl)?F90Owc3BVXUtIvGtLdM-J z?RJ}(40+IxH$J4|ln5=(qv5wuvJuPx2LAtugha6$>r(zB@^+5oWELxyYKKc6B{DC- zz4409|$6N|D0wzGaL?A6e|fmWW8f#i%-1q88JM<8F$T`h9sxtif!; z4S;{Yb5B#Z{$0Crn-bbePu}gwycqr4yYeW4$=~2zjB5UxpF})X6+N+=;rPHPM$htX zM#V=7atQ4Qo<{rEdGOE71GsVl1%nvxgQjCdKA=7VfHjH5{=fvKnXVSFyf&#LX)Il(T2?a+M`*fBZfx7ONA zLcHCS8i90Aw6ckYAf-Th1d&uc+E&6-SYJF?BG<)(r{-9d@N^S9Fp6nzWr?{ApwRaC z^E5vS2hgJgM{>6s#PqvEJ4q6gyj#?P$!(2X2eiKf0u5qD#fv`D?X6B*6ijL`ax8P% z+#?M-NV6)|ohFcQDs~Xh^fT{B#ox7DsrX%>chTR$y@`<+PTePrVt&Q%Q13{o1TYIY z{Rk(XuW$O`c{>l^72yMX+5BR0$?#OOGF1PKA~hF7tNg>CEUfs~Dy`qsN61QKB1$X8 zi+0$^apsNk1;j33?;MN% zohcKVXvdJQjAduZR_r<+;79k|fsd|gMLyrkVnk6`Yma%r?!4dUNp~{PHD08GgV?18 zC8pq9z^VHY-ck>_8!^vw^rd%tXo73-V%6=pF*Zw<{j+wwMDBag)KhC z0HY|#+q*|Qk?QkwM%c`7Ttz@4HwE$vd>N*&&d*_<{eYKI>~9`9Nty>1C#T$se4K6$ zV81`F?gtX5E3O*Pd-r@S+KV~;;N1+1>|+5c!>ZMlg6n~5B9>sHFq*hdWZ0WVu~lN>4Ta@%{vYKCY88S|7E zIgz*XvczcIuFXznPB5S`f${!(o^BaA8n_R$UEzVJ^XzlA9w)}DS~FDSLR6o`e$o5* z?lhZpy=3`MDa-(e*bYc^;Z6Q^WQg9Ix$?e!33e70)HjNYM-JpkS4R>^+_?%WXccCi zh@lr#{(hjna3T0RjY+rzko7H7=;c{;#!CpJ_fD@M=1(zxJ}B(+-G=W;A{GMP<(+44 z3l^II`Wt+zn|Vf*LhdDYGQZquo?T0V2TQzIbYUV8w}jB^!1Cr1e>qUxVS(}Fh~L6( zL2$%=2l(8;9?{Y$ulg1V-&FBe>8nwesFl(9-}7cgh&pDy$+H?}`v|u{LW!shk+py? zVTEQdcp?FlL)wA}?5eLm7?%Dwynf+(>zm8qw1Kf57OtO@L>gM`#s|F^oF(tQ7K03Y4I7{|BK)4d`AYity@C!OsHlWmB+BF94TOi9n zRG8t;G<_i$q8L6eSMsgz5a&(_AEzWcDtrHq`$dSJ1O2<+_(21}DlP31x&>iymm;Bpr@Igfu$*69}#p-{rM zxNvV`5Csp){X-&h_ACX4Fw-k4Iu4B1f)C&P-i-^T3sXKGf^;KO9MQPR9mP~e(Q@{y zaS~XlCW*yelO!529E$U_TsP=%i4{pgBe>dAux16Yy@!F=D)p}dNi-=TOZb3j-GH$T zd2H+18|13Wnj#f3K)iCO;(*i<{47>YEfQVbhyb4wh`j%XT~3SH8l=LB~f5J2;E3u}0BDZxBl9Vo(hX>hZiq z;Q_^hf%sQQgjQPqwgh|ShQcw-3T)_x=>Wn*E7kZ>8V$MTt$~&R`d?x8(9|N+w8Ds@ zXYi2afHNQmcG>3)%3dvgI;u4txfn0*t$<-JE22KBx*;WS^wkDyHDD#wH`QNxL*nlP zkj;}B)ct)eY89KX=vrQMpdOf$gcD$X8DKVu;d+CdA{~QX;z93JDw6bTNYXH6rlSlSc^XIj<(MRVH$LD znS>1$cb;(3eBkaAX4c3Se(DkufNJ9Wb+B`zu-=>Qqn;ZDSDD2YoNFSqjkQIGV_ulE zTPgeU2qv*IY7;9hI-oUas1^`Pna7AmU?eAo7)4TQub>xk*c5lLLSwvU(tp6INV-?@ zvQ}DBu%;DN?*>CPS$K&Q-%D6UV=R%zL!2#IT$Z4O2Vw6>onu(Gqb;6lEfT6u zt|?Ex1rz_os&R}ijGSUOruvvQ^4JznC;GJ9HSEN|ndPX;|cCCMUgL`CKf*Xh{~W=dfo zWDXj)Rsx!8{dp>2n_vNc&EscQYCKzuYKvX1@VFP$ki>YHRY?f}K`V;A!0`tR!>rUs zM}0%bL%_j+&i8B4*C+| zjks1r>_G?&1Z0e2wd;?uVgvq2B)>X!!z>Bqu7^!qtf$ghSLo-DfEN_gm|famzcbzl z1s>7se$LT~oh9Y(^2vC7VB-PbS&a0xt}R-{R%~$)?>m3Ct5I%jjBoXMq9WR>+*)SRm$?!>4++) zw-AeApKUF6--;Z(WO6iZvVYx_jKZ1eVGqpra#T2d~Dxw%<#( zlIjpMbJ*Z?NWQOu{(_@(K9`6beme(zDX>*Ii)IH1iz+4<#QuAO170Ymxb=o(wc(7Z zgU_AAB6eYp&OFEQK^@?}q`FQqqBw3GGg%~@bpJJ0l*C_W^IuO@I$KBUd*oZZ$Bv8j za&^3wi#kD*sw78_IDpLz$VHA5x=kuIKA%cwNTao^ z>qYuMl{hGk7d0p=v@J+eEl0$tZZf=2Q0 zpuT1bf8;P(lUSi1ITbYX@4Y&{%A3O`h!jr&_#fB`yrDbFEdIl&A2G@(ZdbaBs=>s~VuaThYJ(=g}h)4N?SuvQqZGCzL;V>ds>gpC4YCR0Y3n(^Un>zdj6lUH zdk8R}jpG}|Yn6w*??=qoJ=ewB7=If7Ud#XfUFi#gfvatg+q&upXizApQ8YMKeLC5- zY84ykCk1KsK!so9pbeboy=qLcgbW1R7lWiQibnbE=14MKmDIKvN(bJ8gTIBP8p#vI zik6tD1W)w3bF&<=>dJ_U^`uObr+p=+dp+NeBLP95?Vw^eGSM}a7q*HHShzGR`rxd9 zx`Ymnl%V(scX$|S>L^Szn5Sv;oRiwcR-Cja1N9B(oX;ew#Q7;2&qXdo-7Qe$8(C+) zAWZR}A_+Xxomsh){IgZ0;O8Fr*(kbI{wiG}KPXi$4&jNf$OBoug~htvkC4-;Rbx8E zW9JTrHNBj(HR^SGRZpZRI?ZSzDzJ+~;9{cGhy2yA3SSxWU za2j?1l-Dzq`{b{GAhEG6l2Xe#frYG~H$Vc2i@3j0PBnE~plXHC&OpgMmSThRSDGZz zqZ%K8m0MRV#pr036GO6&ucp^HPYoQk%^7;%?8b(jyy2m`qk_afj7sBC!*xd?BORmC zd6Y?aR4Z`+qcV6@#Qlz(ruIx|56FgNd$KUF0}qU@{K6B73SCbguDe1@D54^KS9t%} z0o_&soEcCNLZb$QCa$I53RUD*-wnt=05hP?%CY!8+M6?10RU?ag!*pGBpzS+)~k{b zNmWZ4kY86cg*K|ktd&r?o!n8C9v<*eY!;tm&Wre$@VpIL#9nOhA*MtL)0Q(Sr3;cx zn4o`;Lh{*KhL_M@yxGK~;t&>RTy(nl4^RjL&}`0To26mgBanJ~i^otUO_^BjgJ&6J z>Qf6su-;KDmH8OGilLTLxzm>=i+QSLh}y7hTd?VtIyf#)%OlkMB*8}Q6=FD{l0u*# zK(?hi-|)IhMsjGwF8sQTMQ(b2$BEJ%&aI8zvIG6Ev7K12@~{~tZkt_Plk{-jmU0|4?6P6#vdEo zS9^^d~#eCg@LS7DX`OW=x1GDJ`A% zkilSyj~Edn4uM+7fh0b=KOv4RFHLejzhjHWkOf<@j8V++d}kF$@Ex@XnW4XCk|>Hb zx9}lm=f8T8aN8Q4sYov!z=}(SLCn#g%qfavvQ0eMT<076sk_REgcOt2l8{2- zX**O%lm0Yivw-OPVy8$0%D-!rILIZ;G=YbWA8zOKCBjw_*EElr>zjtc40*IxmQ zU+3EfN>rx2xZt|PFD_@G=ilVBe{-z1SKV%vXt=bp@{Sn?I8jj;cuTTAOPB9>T!xt{ z&agmki_u2VZ%+P$f4wYk)wwNJK>dD--J;jc{V=EGL{t2;n!w6T$g~gGNX;F5$Vsl^ z-o1waUgR~S6Gzpdt>q22wUOio7>n}syq(ata0-MSlLSZ4$@g*(n}1Sv2HO5raoz3;8Xhcan=kjj$UUMy-{XsC4(o zn*^dwgYW#M_Wi+QnPTG5ZHo?W2UQuxwyb9=CQue|4Nwb}IM_DWxl1NcfJMo4a!be4 zkRd-Zf&P3f?w_LAQ(P5_-?rOZXGd@V zKywJz#hAz-3ht}@?IL5uSuFh;zBPzLz9z;K3x15{iI2EHvx;;0tO0*^+^N&vncGku zgBq>GRC(%tj?GsD1DHo~AhiU=Eo6=R$9>=3w@BWksKBW72JQK;=O_xiqU{3C^4Lf^ zmlbx_hpEDuJW2fCw*X9emudOp{Vkum?vI28*Zr}nx_pi1wEQLKm^Kn2lbXVzpjTZ_ zg4x7NJni3=7cG<|1F^D(kxOE;3m9bowCwDSYNa6f62LtI7(p8zUjwXSDF#Ghz%A#< zXDI=(AT2~kP{KD%33u;rY9omjTmh-DrKb?VED-HDCj0-KTR$ba91c;eHp6m3hMt{? zO7GXFofWNeS8ng_vQHps*w;p+TAfZzb^09h;R#}%oC z9cY?4P~a^U>(zvGeoA}6X37JWC8|XI;3Z)>-X4#K%OGJtVahIfT%2)V7rg6*ifhor zy@7S3cyUPFH7(~6oFWrM4O~YHVVW0pCkYZaF-adx0;h=Xs1R`*qsTJ?k4W12<`P~M zk*|s1+>X-?Wx6UmXMQ?GzQdD=o|R=V&$plf^s-H>ds|X*%EK|T-#Pr|5|9uK@Rn<} zXN6B0h+)X2am&CY@Y8vqqMYtQT8X>ZKo}pS(($-D64xt5h0ugHErj`EJE*;|sC?XK z$Ybh=NPdpCfoLnw(Jk&rs)&L(Zb5=nPSYz#7lgE(SrAF}aNx>S_UYA);5_IeP;BKG zy4Cz2qLt{0VH=rctIzqcsJ0>^SJI)*eHB&qc!3SBms|Z4C;5@AW^+;so#POu`-LT8 ztp~5{(KMdx-<59hT?J0S)rRH*J;g zJN1@giJpQhKI27RofBwqceUx#6(tLLQ{@7{q^Am#xiIAliPzE=J*UVa!KMsEbOuQF zwd3n`d&=>1lm+P91R%avWp)CEjA{~u$u;HGcpRZ5i3uab73_H;@3}#mo({*$^dyMG zLX4h<$KP~H)J>OPY9vm#$g0?FHS8Ach4iS~De8lpl0e*?LTSiDg@uV|5jg@(uvBmI2gky_$Juk9LTnWS`?GMiKJBe>@9b z!twyMAp8rNGvyn%4@=FhQ*HTy00{~Ci>-(no3DRPnMb0Yp1?;@=INHt+X5chuzWBh zug&pElO=KN%7b#jQ53<%dm#ndq)oF+NaA-5v*%qS9Pp+fHe_WTZ@6F5ergyJKgNne zcwv5xS+3)pcsaHQu~%@Pbj4&;AkiRt%xV6fPa{L4Itnn|a0W!5Rws99%|*P_u|Zh| zvfvGtFJXF%+PS~uCSEi=t$!6FHh*m9jE;yCS3y9Nn8^nCTp15tSh*dqJm^8Ezhxgy za-ua=acV&hCgTvubQ)qVs|_wUM@OcNaG+wW*n-I@?PTzSKI@>QsFV45 z&2<;O0JeUc7mqmp+`5ZI?Em3|W=u9wY0s&G)H z-bejcL(sg4Yyt8&Lc|!v$h21XWm2bzb@rW~!QB7ywnq)QQ=@1xB_LO9gGe0)3NIu+ zc+m2939ck`xD1XvsJ=b`G!r=cV11jPC5gt4C$ze9V>cRTI}hxBke2hWm*txhNvU|B zf|c{JI!fd`sFzy|#W@tu&qA0IHvapB^^+FKr$PZ3Gdo$g02x65fl*A-Okfp@F+mb0 zm{es>nsg{vLMGRwOim<4hky9Ykavr z)1Ui@rByhXwIna`)g05NV#QEzG66xc;u;7d1v<8nSoGk`M#(mDy}^@hauyIf1Cm-) zrTBVsI&|sOi|w+mL&CrU1BnB`0@N*J(GWl70*U%NLN30B-N5s9{H3E(8WgB7!C?_g zuwV&H_qC2bLB#f83^~ALzGRM{dV;j(8Q`P>!|VGY^%_Yx7xfkn2aX%<3n761VIj0! zcb7@xJ8U7Aw~#YLzf>UYfXXkQ$9W7QSMNl2&UN0x)2&S#Jxr^k@bEz;r4v!j1_;~7 z{IY(?njGz2l`Sh9%;`ellx{rDhV>CQi*gY=czp(fQ4Zs4be~>dW{;FbAKs&Hf9;?O0H;lu z@y9A%{C22gwU`9ro`MhHwHvbQch_}FtxT%;#5$^1hgcLQ-8N)>oWzsv*F@FV&==%F z{a*}X`-9P(C7x_{*rP;GTvZS9-*-MJxlbk|^__?1mBQWAv9o0?v-cif={p)had;L0 zXPL~S`>JfbAene1me46wdCvG0BIzWHq~GS`?U%5ka1gLUHRdNXRtk>m*DWOKq~d8; znL78+X-l^}L?fd44AA#6WB*{4(5aGEQ(CiA)pBml-T?By306dvUH2STaSC%x<~fe1 z6-<>}ovw~VS3$1Tcmsb9nR`c)vMztGN83~dtakEh=Z4hFkx=2PY(ROyjEM|khlTSB ze{nv|U!6sQ$2kzyCychs>viia(!idW^bGI&%7aedX-#7_@K`i}-b-Zz_1gMBz25%; z;~-HTex+Z*Y3Q*%S->jVVS)BcD5ZUUhynQU6n|Lx#KpJBfgc_^tSenPDM)Cy%HzWt z(b`p7clTZGgx*=BMOBchmHD{p(BBg1cB)>ZBdpGdbi0X5oy8m-nDX7p!O9_57-6Ai#b?bG#YCK8L~L(~_?>5Zb}3Eh&1H1G@t z&IYJDo;bBpzVAhwQ=(9qU(qwIK{f-K?K)-WB-8xX-GYcLOQGdq*Nc3QN z7Peu{EPA@52QBx*Tp9ItbuEx4>tFTvx3$?lXllaE8B8`|g6vqxd^l)m^q;ZUmez*icAaGKp22jJnBw0~zig0*RB^8-d0aGGaoAKQ(s!!P8$;OQ zu${=nL@O#yC@w?_+@VH-A`W(hnMu}^J$$29s@PRZ3We4<&8LZ|I!CVG>tbN_aU_Fl zu5IQMMGkE_zj)!41kyk7-%@QEqliiW=&KR{ZIm@4VFaXQo(k2}PDq=s`uQ8KcSL|) zm8azMCGwcWaDRVj_usU#98U-Ffia>GI6aerlvwq~4GBo<715m+B23_$v%E{2uL-T9 zC?=fAJ5Ekl;1kEaZV-z1gtm-Ex zk;}7~FmMob?uQSN-rKHOP45{<_^3Iy2i<;ncTYaACmZwac3cBK~!e}tdoa! zucu`zPHv&s#4=DMI~c*AoM>@cI|N~E+~h)x#E{+?@=5lT?Ov?muq7aULzuuC8<;gR zPxQ=^ElTJj(nO;H&@2#yQOwM4{kmklvbV#-zHPB-a!<{CsPh`cj+G@4gRil*mv!QK z)euR5SA?7y#mYRp^?axsZpS7jgPdOkIcKNG=X=Ktd19Wab0^`mVml(~`K>3e)0+7Z zE($O>3~VqY_+0?RD894^{s>zmVe&wqb{3`&vniYz$+p8Jv^ zxbk7$Y-tznOdpV}_U}M&lsk)JzeA7C z_2LM6Q?@3Eir@%J)If3H6XWFapO8*)mTLQ_G{z?0U^%?G>QY(c*epRYW^oQ@qAm~y zvE|{cow9f&2;nU(p0s5+#)dOvY_002Y#~wMc*qiJRgJrK_A?RZBbsLPO7YV`3>*d&(t}5fB-`>8~0&29PzcNRn)_xU3k%>tt;zl!6eFc5|gq2 zQ&{h4b{V;4jN6H#CMSks`HA?zAWl8Zww2%p#5OLD))78|+DrmxvLBgb-it^bfrKJa z4t&n-c3a{(u0FSXXU zM3I-oHtpbv8g_=P~nM9r{ZP3L~OxZQpLDE`0}fLS(Fo`*DyoZulAj^WW^~LXrlyQBiuN z#5=_$0PQmd+RgNGP&rBo?0$gw0l?~J>x2({nlA|8fq-z!oPIE0_A~Bo`I0%vTc`>C zD$Hba+r3V#2*)~yu+Hrh*H5^fhP`tMTH+fzj0J|NLEKB9=a5u0`aDD@L_t=>SxqTu z5r@+ZV2OF(y^>W7#YzXUl2JUU`jt*M7ru$KgU$ImX!e26gCLg*2Pwh~@;Ln#x0+$R zD=7o-6iDK6EV%1r=)B+|_q7bTpYjh7fO2yETE96{ZWCf4IC3h^ zVh{~8URf%IwLepRyD`x-2%5^zq1fzPy@G_K`*uLtyvQWdY~zi>l8vs0Ig6;vCSAaJ`8T!h0;z31iiv8N>90uv1nfj9%WQg>0K=-g&yfu!DG zrYN~gZbak*y(0jF&ed%B(r~(Tk<{|o@WUarRidpu=c(iu`617DzN(* z^WngZ11-pKQ@xumKZL8_g(*Q4!lZLqvJLXNtW{jXh$g(O_2egKwKq0?za@dz79zA1 z53yw|mMd)2vh;YxyHjjh3f-khCcM}`nwO@%+9;v&+yEMJDuaQnbu22KZC+olwdavw zmW*R1o6OPHXjlUaaBJMpVkV>7hrT+;Dsfh<66!)N*JRX=+Sur{)~{hT!?O`1E@9aY zpa6sTpxReO=(epmPU0ip$BHJgK}Fc_ooLKBUz1qHRZQ|GPcq)m8SP>?#%qzCWpU@&cI(-G>Y@b?g*s8q~Facxc}~VindS!lhbg2Ju-& z$#*rL9amO^y7^i`G-gJ%^N%GBtU3!~6=#8%08x9Bs8up+>)B9L=v*VW#ABP{bbyijqJ@Yfx}i2mqt_@==W|lJEmm zynV78z;mb#-OTSRe)HMyw&9CFALD&bfN;c}2e51w6L%@|`WwLPC#tA-|olC8` znY|{M{cDzp-#ps;p7wGCa*U5oa5ydYXcPCj6~}Po^4Q5YkDgo2jrOt^)Y+SPV`-aY z&KuxM#u*iD9lFtZz8&`B0EtvcB;th-{h-7J$ih=R$#-oy=?!sOA`YtfcYwnvmJMq( zx+GiV@iDNqqD2S%R1-wFtlG1ke5oEZ^=eoGyrNfbwLhqlcH)S@W-++w;3LN8s%oZv z5{g_tH@7^W2cX$lLauIe;h{C$H$(mqBHiil=qZ-^5S$Y1{4tz z9R;#;m{ME8G%E@MKF3zTTF?Hi;sEwvi}$~NV@J+{>DsFs*!vxogg;=4*i>zY_hrqR zY>%{Zq2{S9^fqsNFi+N^^bY5(AjabOZ}aiDw0S#&l5T94C@gnC#q6712{l_!a>?ZQ zh!|nQ{t9D%TTfm+E;))+Zl0iiypkP7J6s=IMFc)Bf{%@2*Q1;*l899!bko=a+8I0B zwXvaB5+N=WQITRS$YmviXwS(3m5LX$*wf6G5n!zqm_CtN>(^>g(LTafeDui@ZGng4 zSPPfrlWG+zyDdR1fRgNuxeDfn)zhkNPf}!zm=5{=H=}!hn+soP^`jNhxbGvHr8!2N z078u7fC~y~A`07l0sBAT<8)Rr9*a`SicuV%yL_?4_F$)kXi5vD!;jeL_sv4=d~!;y^fb14*+g(Kpy2Po086y04D14u|0!Lg6%9@#2pVX~_j zX%xqO>>i=T*ga+P9G|;QuPO%_N8%j_w=`B8r#8M4DP6ZM2~jB1ZWhhKY<-yG&s6*7 z2iNV*JBqfby7h&SX$c~AaVEP|8{A$ zE=Q5ZaPh}B7=~1tHmmPTN{PgYCMK4$HKv1`3X9A7r%DnnajFFvdfC^Sv7!{V+!kwI z*1JPEEg}%`3y1W$oH1N(O6agyqbXn5>N3j~Z>bhZrD)fL&B*W$(U%Rl1 z^7yemcJa@~QWc~-ip_4dnw997$aEM+v6dKz7ztA#gpG!qkAC#xTctAh78n%;5Df-# zYuL!8Iya3NckD(-KNbHyK~R@4ro#QF4wWc zIV`{LKk|O%q@tvn;%2*HJ#Ga6P?xpZ<#Ezh)mBn&*Th0#qc_j{Uq*~v8(483I4$OA z=u*XjKrzQdSn3!aNBb;uM`4^4W=vdpmIUeJwa+{~BqviRkkQ!cFHE7vk!?f#-^4W@ z+Xq(`^Q>lyd2!^!6VeBC zIfKucll7E6)Q4#K86Uk^y=n9PzQ4tIjkC8@EYThlmn~-8sXrd?g0b4kUMOYkxA_t^h7t|6kyjX1ss;URV6PFMHEGQ;ISwFJ| ziCoP33T8Em3d3h#Q0s3&9jF?71JNA_?^|rL!s9lTeVY>A=I2lxI}*@0h>DvcI%`Eb z`76;fCmEfbonkaJ#Cm3}O4UF6S2_`L0laN!>f}q+z0m0Pv2Q;YTq=_Q?t8p;)5rZH zv}^OTl&iwpK&*WORBaT^h993v>I4mbNgKlD<4OaBrK=nrmR{s%CTGv+%zhw1nMS4BuA#BB7&$0ZQ6{_8Zs~Hi7$d=?}7(?xgdxboW&s8%=1&V zk4*C7Kuu*9>uu*H`e?zR*wE!M>VLp9vNVQoY(w#tn!H1~5ZTtbUvcum7nK&YDJS+0r$)$89aKfAA~by>$aC1d zeEAls2#_dEEMIp>kh{Fk;UiCb#RhWl88vlV$%^6a$6*1|fm79HV6fdxQ1{e5-XPwo zo>0uo?o>iLsM}3*74I$B_5SY2k6zF+Z*ro8x*=Oe#5!7uLQr&H@XGJaD>^~TmVCJ) z>5fEC4==R^#kJ;xM4S?Zi=+338pm=D@EgYPiyZmsMd=7OdbUt%$5Dks8)Q#p^?mIn z35~EZfE>|6m4W~FS&~N&ual@;Vc`djvL}nSfc+ytEV_EHW?ChubbCQvAu$36r=p|Gnp{bM9Oz>5^Nwq-&}x zRrG1xs0wz2&M6LiiHd2On=4y(9&f3xF7+FKXs_2a#z#Wgw6UH~O1tVLY@yLfe&IRd zSe=J9zJHR9aX96uSE`?Ogw=2=8hw2Ki=)+gj~qq)w4prX9?#$gny>ky_^y;Vv8vUj z&w8Px6Lt=E{O-1%W9Y z;Q}3c>T8m4W)iD(wVTtThU?F_=@aL&WOj~jCqs8iD=!WUOvXwzz)G=C=sDQoFL+`~ z6DW=y=_hS`2xEM2Vp*_^-mYgiZ9LJ3>Csn~+~}=nx&X-epX%IJXZ|O zk#EAxn|3-$-AYkXWM=)&M6T{c6swh*GT@`4BH)Jp?(aktlY-h9lR|p+Z2IcO!ll{Hjf26LB7(t&?!eY8Qow;u8 zYO>t*CxJNnMEz`JvH@Cgq@VRc|J4)J35(>~4KKJ_H%qWm*jKHk(ez=2ZVbPPv&3 z$j?ee?p2H@*)Y8ZpY@M>)~QfpmaYG}BXWew$Rt}_bbWwDFF@<|fo7uG2*8_r8)sRPTx^-o#e;lorQGz!_C2)TWI~+G;2xA4`7-hOxYj;m&UgU} zk(*K^9T3y_+IL&AV?7pW4PEN?UO-Ww-|0aKup2hbb63a#r=ppE{)lY;P>L2)&uO|F zQNGh)?iYu(!v*rpA4R@3bN%rzeHJS|J}QpoW(*1U6t4{RTheNmXCZD}k=BIf5fhJ- z`VIeCO8x2LJfNRAVI7Qeq^5$hd|O{QK0V}*@;>DoRBgy$^j05?qEpPA19rRll9oRF z=B3$2>3ROWR1=3?OXEUramc#``T6}@H8+c4eYDR@wGPuYAdib=I%vTpi$J;X!F&H5HsJ_VgoghKfhr;UQjd9v|=Gi&O6!gPTX6RdB1+c5vLn?IkNj5ic5Pp}O%iA}5Grs?_mhWK;6CrxkD zYV68UD~`B=T^v01)9TX?s_3@7X3G#a@A3PwK5fqgM4U&mX|-A=Z{T#ANZHnl?6qR* z-BquMdg?O+w1zyhs{YLSX>z;xL$>(4j`(s=q!sq3R~05D53SLzi%~B7^#8hKC3poM z-l*m5s6W=Ft8{*5o=f$THU4(b`O-h*YL0Hk-%g&8a#m8dX-!%d^l{qgXME+nnf@}t zFEaD7=(-p6k*RqUH5{aMqK3EW`S2;VuDvJCt!zFyzM-Eio4v1|l~y+%Io~eC##4Z9 zJ>t;S0#Het*1F~S`{wB__7s$_VMdd4(HHqdxV8hz>z|agoT6h6to3HYDUCjcwkvh( zzBoqIMC45FgRYXv^e!)w@g1-!r?bK2z=v;7<>rU+tkIt7*$XK3ql)YBd`mIXz_ulP zBE2@d+$i2vUIG|-?b0P#G4W|r{zuX>Q8A}3ZT#m|zlz6aEMo)6-0Y`>Jb#a~;6&I1{2ffiox7<9*$rwadLU;S6csfx-z%i&1h}Yrnl_i>ojA~dtCRP-R*aei);N3>N%XT%m1*G?Kl4R zuFXY}D(Y*S;Fe?JMUTyUP^~tbP~wx`!7Ug5#mN`*-E>jJ)ASrHbTyB#HQ$~)pWyGs5ecqZGLA^3XFBnK zXM1RCTUPKmFB;}Z{mt)j=(N3k=~TC8QO^W5eUgDrQ9<+Aepq49>5d zAVgwP+!fU+z_>3vaqK^QFORYNQwBGL3-mgHnVy*r7 zq>`_H7cPeJ=~bi>gJ(Ja$V#l^9y=sxJt+xjJo+_67 zcfMAfDN!kXN_3}`M*;bU(b)JG2TqO=LktlKXbYS6~i zMW@opUdWrX$X?Z$es~@o^Uz+}6AI8GNN55Hy}a?GLPAytk@pK?6gy%0GLVC4+Us43 zj8#+*<`*0`V?vDI>jCX9I<=1&w)77TN6rYv$)U;Arv%0M?CSXeT7RCuPJjN_0hWsb#K>_Mz2cf$viEIQ`l{;0qh0UTfqp(g z-S{7IK+n!yv;$Q0BmMc&Z%#U@hSa;1xaCOSm*+?iwUvRAL?8H|vU+m2L(lfUKDHgNH$VAc*?7#rC?w5g;TL+>7m)2^!RWQfe|HKR!OJvMPSpe)Rvl|^AZzu(`gPg(Wz z|HhltFd1T1IT0f5K)1JY343&x%s$gCVTRB@92dX(z0OlnzSt1U@-_R?eM(H9qovPXF zf*tICN}bIURuiL!SC?n0=ra0Zvte!C_LZ;dQ@3%WdW{>2ouQGanXm`_Xpv}I?X)2- z{=YA-t!t;9Bg9zRqPABL=ZTB_E5820HElQ{FH^|c-(R?1xazC;M0A4A4Cpqk&iAor z)W$RBvtl8qFW{>Z@UvcDO}$2X@@Bxdhd52@g)#3(yV|torIYS<-eYas&0&vWJ!AZ9 z{c)|_7P7Z?ldOwRrL#&7%|1i5-1?a~M0!<0g^2XI$68dSrROev5I_E@TZ+Ta6og%N$C;Ib3uibUB zh%}U=MO;MqKlPekns)zSQFP@3cVpaJN=1tj9n3B?^iQv)zG7oS{%^HPt-9qKQS8++ z(3IauueAGHqlD2)z~m>n-hGypzTj@br1$Hhge;(kTps>vXZ+au>)F;pzT!T^sq|TK zJ)TWl6`IS{cl$VI*hc$IEpMUXJhatrL$%Ys5^5WvRu6Q&oyDtx;dGxodiU87-gLS; zztaErA?EAr>Bd>92iA;Uj(1jxm$-*y4ZX|BLeXtrx@+Ib%XYn~cYc4^#L1TR3F;}= zQ0u9jmU>f%5A0gV$!gfIbB-K|a-c=uuu2}<-tUhqJH;?2T@HIAeNm4)G{9cB8Sbq` zkYVxXJ)3qgZO*gmoQrc!;ty8hu7v!k5Pwb>nDjSgr$g=qimwO?1>2dAx0K;I8aXY; zu+l+6ZG!r0Nyttk{ZU85`#LTQxOcRTHkuaLsN0w0uCfxKwI?eDc$iH)QTog8;z5?3 zOXGW6+Duxzq~6*mqX<_(n@hM-dbrb3gyYIY!if(IM$^uh&X?E8VEK0G-nMhQAnhe( zt4oufcTu_kZ7ikRLg~&&@u*^2D32qr4 z5VHCISYz(e5L30DagXnNly*Ah{Fbg$ccFN!+}w}$RXS^ z!llsj_|NxS`JC!f?j^Rf?h4p)1>`N>#Wo( z>uK5^9%_Y~OEo{OD~eiJSJZ#g)=!~^5uf`K$@po$q>)Jv^U6&+0a_606w$-Hc9RZY zMu=&5})7nCmkwW1*nmaIfx!$D&HYflpph zUDhSi4<`M0dIf$d{o#u9OiX{K(Cyav<1(H^YjcbrN{TO+EygYsQI2C5olFSd}TV2Ng8Bb6KFJ1b}?!p1i6AEL2Z?`7X zS?vtf>n_E7-|SAC4CYa;0OKgv0h)WY-hQcmM7e3rJMfH@GOq5yCe6ddIo4~k(bovSq3$9oNJ;&ep+P;FJ8NN zXj#*_J&nV+i^cs~O?htCA9rr*uiop{smecP`7x$Z{&M`Eoly(}+2^~lP89SE6_SK1 z%swaz>qNK}gi9sDmC5l?Ofnl*<4RxSVd8E)p(x(jMSJGB71Mc-wHuA!A&^T%ZliSK z3yU6FP8Ssrpo!P7^++%0pyx|f?deI4+qGvi+Ow089$JAxcUC!>bNWmdUm8dMa~(}& zm~(M4VgpK0pv;CrPTfo{j3YaHL9I6$FoGy-5d3g=bC+oTWvucvJzUWr|L#%qESH0U z0s4RC@?t&a>e^T8M}W)QxkRVyFFV~@HtamKvV+8%CSUP~Qh*=dWLQxK*~;iVC8hnt8kUuYr6!Vths8 zB{nOKK9g>_dr*^~&+_zE#EPM4x!wCcdo0`!?ngi3r?D?_zDsct-Kr zC4Gi8L>^2L_E|^wav%2E+9#8+5Di2&V?)luHj3i96{Eag)bt(te{?#1QYT?!IWF zw^lPkZq$dGp+8I3Ut3Gyw{oXU>`b2zqZ(tORyJ+q?p+C-ie&sdGN5%(5Al+6BLV&OjE)-gliRF>4Xw<`99{3t zqtktG7#59dbl; z34_jV6mNRuVN5Z(=FXC|q%uRdcawI%TIOt37+Ba5Rt`Ys#f*mNW^}Um$CW}=6*KCz zIi`Pj#uM${t3PA<{6#UuD{RLvT8oaXRVL6{JB)rH8g+{_bsJ(I$1-=o4aZK}&)@FQkfA{BV11nCO0UDQuwLTUUD5 zit@V%`g`)e^i~g^&Yd0J#^$d0i0NqTXd!8oY>S6~*=yu>xx<6-# zO(OFeYvZe~8D-yUsdvG{-qsVP;yOt&LbcN8Tqow=8|$R<-RME$s=>NURLbhgbneHi zm$75>db(?G&N&}p3e`;?el8C3ba9=z@yE}<$z&R;>SCFsL!71x`d7k@0oDHZ{b)Qd zu3ib31`X`&RK0Q+LGKmDwD>EJxUAR374L;vobDvE+~1mA*31^YX0CdF)bF)3U&-q_ z>f5<2M)wv1Hj>KgIfF6O@mh>IhBo^G?l$Y|X7+mphsp>{m9*MkPcG`7_BJ08vd zqH?8_tiJs@c#(AL)o~}C5Eo7K^9}6E98w%H;pP1WdXo4wn@#&s=FiPe|E-~qb}t|f z1Bju%J}q5?>hjPc23>Rbr>VGIOzTY6{~&`AWxm~UnqUUD>((i-r*@qRxuol?$L*il zXI?uDMNdZPxr=st##gaB-Y2j%f1~Qjo^ogLUv5@Q7^674`o$_6l?f*`@qzN4dTI%7 zM_Uz}duW3AJdv-q0<965w`qw6uNxv>-s^v>^U?0h`h1;Rc>c1$CyCR7%iP>nHtRZ5 zrH^TJ{;GfbpMg$oV4O*zJ|m~JHu4lqy(UZl<&D#FMJ`wE%bQM&8{&daE>&FM<^@GS z8_h<|ZJ@j!TFSx3%90)Pk`(kk1x@KTVmmDw5jW{Al)CJ<>}orj{{R%K5REC~KH8ci z4GS)Z$Bs=|=w7~BG*q~pUX|(0$8y$%$9~X-83zBG!D*BgpNI51&4mygnJxoV>>Q*tA+h_OIa*?9A9>AvMj|eN_^uooM zMT;`8pu8RQM;F+WJVadtF&Pi^?<0@wV8g}5al))?)v5l}dJYPvPnJSVMjBMETD@VT z$_;$#HK<&ry4YWsE0uRzHlYQ@BKEkS--v&tig!ahP{d*prCK`aEM`Dl#i1Og6>kkI z>Xxm{f_v+o=i%bM8EmZ9o$)sjjmmz-?Tyy^P`b6@%wB(Xc#e=)n^xJ!a(fh3g)M6| zr-`m=RbBXZ(1P%9uKU+?;m?sN{G00jb;_3Xb1Is7u);nI>C9^ChTd@X7Hrw2{wYlV z8a4`0pDZWUv)pKK`OOYP9^;F+sV?#ie&je4k9kdgz1ud4nC0$I?D~`?9-+GHvmpQU zmbcXUt*R}Uj@07m9$J?@mK~yiegRs2ya(gm#pi(IwS@Y&bF`1BZ;PyIln<#WAZzY2S(F+ zMU@uEfHqopu+ssz$1lBd%m~vIs$3 zoS=U&SxdwS(n24ortHZS#fKmC|4+9?U7G4Sow~>I^{_ZMAbOUtmDzKNoXt$X_@MeG zReX7szhjE;*05yJW|m#E&bfmaHyW^3HXDWGR>mQRTh@(&P^)_I?JAW!VU zg4w3cP9N1(P-00U{&+h?&wsG1+y!Wx$sONoCb9W$DmF;FPsLW%6Irn5W*et6=-Z;= ztKvM+m>nJh(35)KUA-S{`57!kBn7~+(=Azper zO&KROF%LcI*Qyu~o=7fN>b-ka+3W*U!^zrL{7t-d5B)rt_($VC%N&q%To^G+uS>OZXrF;E}wiKoSthKOl1lswujH? zm9(eqgH%pEMSsVj?>WCk4X^3*g?$nJ?*B-v+tmnaUYIOC8j!xZ^Hm(?n_>McpOKYX zlU!`oBOOhDf-h^cJ)A$kSquK^SH5hNahhJnV|%8i5@%WTjU4-*B!i?%t<^2i$+D5# z?3_B8$-Jo&HEGjM4X*v0xEM$OyOp@}k0aRTRY&5IInlMwaQO)KR<1 zBzOdN^vrEHpDEBQ>ptc$v))P04K7z#e99-lze~?PScy~QTO@p~lE}i}3%-?g>Ow*_ z^bbH_^9<$4MI)8e%W`GG_?3}6SL*Smo+4S&y{8Ae6JdS%C@fSQ`Rqpd#k23;c6)`9 zFc!He!caZ2r?%ejg;AQCAN&hVk(iQ(}DN#^A&kslLkaztfv)0jd*MnW;{U zd%}suiMWH-bj6{?M~;UpGV$4As}pxc3m4(SFCEHfx=NDnD6u%jACI2*Qf88PP}DY|`;YNVh0hc6iNL~Nhm`fG}{s7#$(NXxV!cV;G`@c93rVZjRK0N`e zo3F@rLqC^%TDCRn0H*5>Jx}s`!IuGX=ep@yLJw1TA)f=k4@klqrzjv?9f<`!5Bh|{ zM;FUzKsd3a{$HFw@uthT55S378?zY$HpU{_v}Tqf-7{@lVhEs01LKm&Age2)zclBxNbZ zqDOJn;kyHifkV>oxx`AaNHPh_k`iKRB3&Ek5emOv(zg^@Jr0Bm*B87>(t9N~e4Kw% zWiVvDC00XBRAieKS`FihzCqY%8D04pvSLyA`QtZ5@n5OX?o)L3x%NNA^T_0!P97IB zGgM=XUvKzXQg*=NXT~w{JL#W3vnk>AIrLP8H+}Xa`)rYC$ig`VK)B@+Katpw@(Go! z29-}@!L?Rs!H==RZyoLD3A|TuZiT{$=ka7Ue!kh9Z$bTtpa?ZFUer==h9~Xt6b83dfpQzBL{|*;2(@)?B_{S_}NO)QDQ|E07GfDDWEOL?1U1af#vzZB~ zu9bx!DfuXL?U6>y-Wh2&33pH*aPI)eTt{j!&``WSpe zMLtTQt)ay+(=$NE(uPl8@M1|Hl30zCqYP^`K)4~`S&}v+#_wKamtDw(Z`6O;KUV~+XH@p>P9R4Hib6B+?KN3l}riqQs~h@C~#8B--9z$W{v@vZY=aRg}(zG zuL^5Qz?Jh>EEoH8p4@guK1sow5_@kuDQf! ztYz?T6j_=YhEIURX1Ko;{uK0kg*U@^*EA^ukFxNl?>gjH6u;*RovfA_%8rY=klB3= z%1;S133|K2-+_)-+Xz=mV!^eCo&;EO)Ih{|2Zvmbt={4Zfz(*i?bH_CD!nd%<977mfKfPo(^#0$ZPfh0lpP=%rW6n-l79^j3XdG;{Ec9Pg0(@u?d+y57ul0pWUs7Xhav|3%^)eGLEl5*wWJ z?;tn+OOPLwexF=~@$BoImXLT`i6{)RjUxDGH<@~b4a z$ND*yW`GfDGKWq@$qz^4Q~jQ5#9bHM6`DYA76ZH7xe z9Ge6P*IHshPf}>XyK;MFm`72BjW)uFSw`X@iOuvv6#gvq7s(eJNq&H7fawk>v?=@7 zg-rN)j50&maUDfAUDDeXnLT9G)KlUl9L;s*;|#R$ zC*ki~WM@Q;=`B_+6F!2aDXA?r#(5J3v=JxDbgAj`b3}=R}iZJ*d#*6nd4UJtnc&0|-|S zJW|qz#QpEG{}@h9;jksn3x!WR8T$$d*F|DM&yw^TaM~%HkONfL%fc_W@JA*8UgBC) znY#hPEd&28X~BP1Xu-R3X{Wi8x|UTZY@j8482l+9LXqc~Zp3daac7CGsm?$iuK3+i zXlq!($D6@lhJpX$Dk(PZu)bcTthsW}2btLkew|(l;&gC7SglK~hEtO87TLZRFyg-p0~VeA(JrmLyYT_hc>$c{tXmSEQb(-o6+2Z?7$d;$DT(pi_9p$$9; zevL(T7CzaZTq*&WuB)U&z-JY?=`ZkSO_AAs9jPb(Ax!e+Mw}WFcb8aA zX}SxU@ZXI5Z^bVHI`axOra?DE)?LacNxZ~Gxc3%Wm6b;PITEWWZ&GCU6c&G2sy?gs=*{s}nw zcGj!F7~le6b(weACDjz#E_J55$#9dwYk)J7e*;dklk+3M|Eu#SjcqcW+Y;y9Wu)3l zVt3EjsQBNObewSK&^Z-ZfTSmb4+A$8KQrbVWXX3MTp5W?KUcUbVM3z_cK|<+J+5LJ zvaC_~{h|2vmGlBd<~~)s&j}g+;eUwtO$pOruRRTw>Zi!VpwBA&59l2Gv`9A@`Udb$ zk!9T<>8;g~^n68T`rbko_W);$fto;DASyRP`Y#3l?IvuDgGLI)B#tV*HiVg@gbP>b z%L*OmkUf=B3T>AVWdOLR-+#Lb3weiHO<$^WCs%@CfqO^UPj3T>Afl(+QT1iqw% z`=QXy?-*gXfbUD%kl23{-?h{3sIpOnX(s(bEn&`@{5{sOz<+ghWmrEY&K&3?3NO;S zrSP8j?Wxy>_EmV(XFRfviu{qJ6Fo3Ppz{hXq@69i8FIP{`59!7EbW;37=Im#$+Kk#aBaNjG6!$K*e$GJK|2tiu7T>#4{VEA(;b?+P#CHG9pu zQ9!t55)1mOLJQuNv%N8-*(6rOG(|R4k4f1FFAc z-VB@s{smN5{k_WB=^z*K5GmUQegI_tU=RPlP`*n1X$ozoRraGnwU^kGn|OvrzDeO9 zL#Oy;hBR;``0l`1U=eT!J89QD}QegF0dH`vRZo3wMqI!u6Hd z;2eMd#P5vse=l*JuSS@K;BAtAEU_6o);EJnCvj_uP5-`WjedTg*4lLiK2&TPS{~T z3BOkQU$umbV>6ypTVj!5XXxQTFmPCrKZefd@$-CDlVSRTmrD9{6!Cs2ewm^Uz{e!5#c+-*;%8Rmb)b7o{xdjNOdJ2BH{uPD zcsDq4EPGmICG8{eYH-ZhHmxXNbv`a+BFt3eJAj)m{Nu%OPDjMagS@T_zeULQ1D63? zT$|Pa5N@EvmnBZc1q_wsB@DyCTYx*jCn*zgvWTw^;=IA*fCZA*h4SZ#l*LV8&u1=Z zZ(t4Z2}qxiuVMkFn+tsmc%{fpKY@!Ul6jU`^;?eYx|GLB%!O%yH(Ip9Wa zhPf*JV`MPWEC}`ndP?35C-7`!Cl&c?NoUGv#H}E)8Ye2cGvR}QgO+$VEWAh~UM72) z1z*I%3z_M>6u({y9R__I_^QaNXExGZDDhVCO-YON3TH9=$4P8HL*QK&S?sL#Jm!&f zLq%rB?IUGd!MA|lv)SW~hF&ZAi{Q_SU)t<8tpXri7w}9;3qD-ZufeH)v!_>8(!q*M zgcoj|MV26k5w8V!qoj?Hu7B^yFiCRSpC>{VgZBc)N%;=N|6k}7x$NP)K+jZo^GV00 z?5o5%emCNHNovp zGwt*6PoykfUdLxQl>AWeBH*CK-%R6`l-JDX7=NDRk1O)0&~@_Lv|hk6z;s6x+LV1p zma~8nrapKGa0qxSW$6prv@(EjlO;Ceu7*EjkqN&Di>z)TBYu#?Gr(7Yk*|b`KaQ!7V;|d%m zWhW*62F_L7rZoiqSGU*__Z0jqMV7IIO=|=QHwe5&(&qE-NIrT==R6d&$f{ZR01I!X zDe#CW{N_l%&q|n#rEFRaz;uHYdMWfJAVz7se^G@tHf=5-+yRN7fyIEA3S6n-G|CWXHa{SEM{XpbZEHp;^9RQUUnPFBgLRRn}< z0v-w6k$jQLd`K6tx^c+XTjY1(i&rtic97T_&*Y~l{s$%f0-UI-^Rq;p0mxTLzY7w7 z0%xzrnh-GEQs}Ed;_8Mhzr@17F?1h=7qSq^9|6C#_z8d0rLJLrhLClEpAGC&EPac&a7*U4@U^ z(4P0=(48b7qR8E)zh8!V=O%29M)tH_rBM(6_P`|Ip$r?Vu}xb7Slvz+vZsnH;~&@) zz;xcwBY{m)_Ez!pY+}>;0m6lWFGyPOpP@4~wP{s>j(~67f%e1hkWyT+mY%y?I`sHY857QEQq{5qVmLW^!Wz$Lku3Q^M zJ{|g?q91BH(6W7Bd2ruzeWIPeefYb(24_~%ymHVQpb(pwan zncjcJ*Q1D=xV23y1^5H5+%_q{0*=?l9wxOyi+IBoejD@$AX{5|cvorH!he7avkLr3 z37@*1bKE)>nXlw$fx|6+FD<Us{p2JtI(!Q;85fT6u)QCiT!L^Awams;BmlO z$^R|!Cvds;MwporKan_92b)$C5N?pff?fuFR^f&0BYb9mdp?D%j^yWA(aCjukxn(~*G&mC7dl+wMYwwwUdV*|ggjvYbp~_* zCIVJ>Rm!4w=A8s!IxmGD4826*%`o4jEO!?pURCg7;I!mDy4uq-* z7m^lXyLL0um;&A=X(4~0&@sBZeojs)uM6%3tW?5XQ)rQ%I~OC+o^}mMcUEK~-fGF8 zwaB#~dt4DNhve%@Jka7V!kBJZ6nTxW2wq|GpI;eYArm=Dvhyc@ac zui`)%b~N~u5-(>jd)j3cT8-OZkxzr(DfxR6C+*D|A7~GZ1BBZuv6{|lWZC){{-q>V z{RQ1o%7=hw0mp$9efgLP&;n51G7JCB!q@L-4?j@SyA|03g;vu|)!!aZ$ctNeGpvsb z`A8{St@xdV_84HKnM>lv5}Roavhb$-XLt$mE-7)pL$@7hJZmxdUrCE}Di3ljS33)@ zK5K&X+vX-r^udm4WtRMK@Lv``k?tFdEX@$d_##YAWCMXP>37T$=B4C+9qJgjjD;6z zbw)M^I0QTbei>%O@sn7DIVS0^;N-*YX?iR4Ug$TH_a9*oBjV44-v|6_kqbZ5B^~J) z$CTHw$VW;3FNrTG{_iCnZaG#zX3eQ*wYsB z&K6$Cgqy6$Z%O*IA~Ql6zZu42-+;bAFrd2il0UD=A1id?arW>f63qMVf?S_7! z@V|~X;#QPceXgL}De|QXZ4IaLmwpoNhvMI40{s9u4+xiHqJc|;I|CynZ>Aq}67OjN z)183+pzvuY8-A4~?g(B2>;Ucoai$pl`N8491IZ_v%32W+ZZkN>H2X7zEDd}&DO;fU zos@Kr>5kz=oW?F>LM~iCH-5{d{J7%(5<1fiBmGL?&XP7#GJbDKSx=JkQ=L#+O7;|LaBo;EO>luZg8FndQ zE?dIIm}{h6LgEe*50Ur-xa>T~GKus$N?C{tzx`7744fp`F>Yb_ri!eqq!)va19ySS zAx50J5{u`pS7^ZtcVEilhuXAaKr3JzAlyQUb%vkQl7C>4oBk$_H{YJ$QqWx#UWAzk zf50MpDEa6MjJSm*Hq-nWZXZSX85X~bl7DZJCs=6Dx4Y-%Axu4>uM8U|@geX7NsGA2 z7P(HVxguW)eF4b6*mc+{$OGN@iD!(l_-$ACkI*&4Y}!y@CGazMT?rFoi4p!ciOsmR zEqq_ehk#E?`m@BIOL;z^x>go`p@kP=_aS>N zZo;U~E3%yZcffS(C4E|v@xhXQXEnHfJSoOva41wgnk@Nr2C{+&W+TV>O# z0jBEDnBQsJn?FK`og;%{78#T$ZuI>pWxH4 zvB&j=-k|Vz6jgXQ_IoMg?zaSnTYcWdD?9@tu-LrIEi&e{_I4Sd^>YUpamdY zH;Dzk0(vj-3P`)d@GlMam$V2Y+z^Eifer^=N?E*}_VO8_jo)fg?xpyLNqUzedky{j zF3v3grW*==fqwtTQOB|qWf&ahURGIb` z@J*oLLHo06E42FjLC9ACXB2;rL-u&Npc?`Gfz^s!q!I0~J)D}RO6OI=G?VlMMHU8a zJ7Uu^05yOhK)89}>{7fAd@Vi88TG{+qCSLw84emhD2s>C_Z*!>qsdb1+C3;jXi&GdhUyHb|)oDsi0cq*_%@@8CD_}+gABjOb~Z_k^VPJ0(J(@)@uKk*k~?kZuD zT(Cc*v_g+nXc5PBN2UC=#KkV!3fTnU z3h*7seZw&gAB7(Qy+-oUZaRh&>DPB58z^O)Bz_=qf?Gy>Z;3^G(`|Mkdn9E^ZaY4= zfaI%NII_)B{#fGLcZ_Frk$ASmTP1!0PH@*TAL?@iUDS>LFy!li%NGBb z_poKa&)g`&gvoG+l<+SUI^liCbn-~Pi6ZZ<(4h(~o_`AdgOp`@U{9-&q(>++YkrU7 z_Zi6f(1_PqVl&)Wh5rY-PfQuv3^abMcBJb=|TK-SBJT!fp4{IK-P_R2ACWB48xnVI$~ zMScT1%WETUHHrI5Y=&PX`K=cDBgy~z#-^1A0swbzi1eES-X`hjZ;kNX!E+_;F8*zc zf5msaV+X8mx*`jg^hx#ci_@p0fT35hy!3upwp@si9 z3t#)A5wC~DBFqwn4wrQNPxkah7^}A@Oz;j0ad@+^VUt$4-}aZlY4-^*~1B02l(w$b|0MQyQ9CCg*VeNaZnWg zC!_Ftk6-#9oCgN1uB{812s2KRFNXf2@VO$`69uepD6-AKIg8&X_;P&YTev0?n{m6q zhXR`{@+TJF3?CIPYxB@L0j666eN*9exrg1~3@30dDX(bpZv{V1%3e#HBASs#J#a5c zi!>%lI!uwBmh?wOCc>tT?x9r$f&f=;F7o}rdl&v`W4MmfTahnNXp#Ot$=|ieZ87a> zWt4OSMJD3*Q26BvE&Tphciu%hZ;<7SWzUb9c0FW^fqgFg%rNfo@39@zYhvN8@y6nR z5wOK^jF%Zc2$*S+?^F1D&@tmW#w#lMK^D3B+;viZ1)MvcV_YxzAr_e#PsK}>Fqb6# zL*ktA9n%!?e2|S*{T7GY3~9#%b1t*Ud{QmLQI=he<}N0zwo~!Y+rV=_q`^2x7e}{2U%Z*v4_5aHP}|0 zmbWEylHoROY#aWs8O;0FRyHk14A#Ls*uOCQ_T1^yWh{51OyN$L?(E;r<&K|h)Dv^i zK`9xVY@7$W#Mm^KeaG>P8|XsCQ8sPV4*vgM{2If92i{((k>3?|CrC4_d*yqIKM{H-Y&<6VAN< z&HpE+abI9go91(vcg?3X?e`YkCv}kb!NoZjKLmXNUI4v@^8TnUb(NL6n8`e|ANvH9 ze{DkUHcrnuNb2wARNlSsr%WG7iy@)|b3vL5E%q}iHQoALfc zTJl(k_p8+H`!=-m5!RAxdH490I;TClFvhP(w`zv)?r1dM3|p#co0{?c?hSl9WeR6| zj&UdERqBWG4iDm)+#Te9fqiM7oAeLbm^?m3|1O>54w3-QnxbRp8*wg^xn%O{Hm!O` z^t3GVn$fHg6Eep8qSKp6Gd}MT^Yg!z<=i>)j_-BFAm8ZR>;{}O>CV|ebhrkx!|2mu z>Z~<&)c0@hf+cR)ZuFEfCmH#@jV^YX#5eZdlBdMf_Y>|c7|%Is%6MZH|H**AnvZ&d zZbzGpi^ZNLdi;{H`$kgkzA4BVAo6s0xTalC!yRd?S7MTnqL6Pkr+65S^hdzf$*e(4W~2 zh~E*vWVBBn?mxLsndWdeANkN&$E-lllh8kNzUIG}^pjyrnbWl8|IABx20H9Z-p6jF zeW>eV=;VdsygQFYTMghFw&S?dkUsBomp19o{%#U>P z1^JG-CPn|c+@@WlJQtaNWZ6ky*-Ia~MZZB0e#^_K^AF#_(R^0{w`7{ek*yOS}K*L%C_EQYB$B6Cg(qh zMX`6AZQ7Kx=)er>5u4G1{u9vzUF(3|pr2m)%$SgZyZq20R7`u$J#J~g*tB+uv4c}N z*Ny)B55z8^U%404R~cN|GRB4#!A4_SHWlWMs%6;33fNTob-lrwmH~S=gmSew#5uk4 z=mKSJ-ix!nJiC>~dU!VHL=tjG(L3^Zj`vUp7;9Ew7pJ4|b*VeXfyuP!sdA(jLBAVIySLxPx}_EA(`Qly zv)2-#X{l?GH|p%gN6MOuGiH;?Qv&Kc6Zeg76Js3x68t1Naf0}tdJ57&sWzd*-53iW zHN`%8GuF|k7p&%fKJf0=Hmw}bd<`D!Pe1hIJXDcRnC4D z!JdF$V0+8wB;P>BzUVIXk(e?C=E4pE)1k+rx9_Nj4!apEr=xo_s1NA2^s6LEu?Kso zd+<#3bV*EXEASqj>$sZv0(Rm#eZ&75?;K;;v@whap3gZ4fu7xeMZR8B4>>qvN54#n zt+)=96J=x1Vg4KX##`25C$YQe{L4Hxtqo=PL|Z+k%*#o4Y9RHG9lV092z;I;oOvjN zeL_zPz2w|fN^CA|FaUa2FUDlrV#$8`IZ8Vd`gR@qB7JROUCzkC|BLO}kbyF0v}pw% zGv7E%{{w<(yB+kWr`YFr_t5{8oJUJV{q5zyjP#{47ukc!Ot}DW=;}WJY=1}K@;l~8 zv~6R+8#}laSPor%IN!FS50y=XT_e4q8N8cpgX}r)SML&UFK3K>ZQ3*J;AV|_&CC8N z^R;Nd(>5iT6CGq+rau?9F=oEy-kE$hZ7}6uouB8zPmhPqr>`7O!v6St>NE*@5suC3 zO&vhj#3p3CPo5SrXPC#>bBw;cm^+3h@ZIU9+^0c1eguEMz@2hDJ8MDu)B^0*M*83; zbPqa43~V~}`38MXe1P$YFkhE4m7pFQP1dwS^x;9(sW0lbXl&*|Jfl)M^3x2PLp`LR zU$$<}-W)Jl*e-wcjXKLrdtVKpU60ateYnrU16xMi!~ICJJnzb?^NgYBAok-bdYA=$ zE}n|<@(6Q?5Zd)$`pIM3=o#;8e&zo?UX+hIP5hE`Mm3q+g3mDSHoSv9EXlbtaKQ-L zHX3zWk#aW1R$s&ZU`sAhriJ7y)iBCd2^%|tevNKkT*q895o7Cj>XGti*+BnApE@sK zUe<{IcZPQAM0+wnpqjN!#YuB5|KatpY0a>of97Ru{KPmyTa?_(ST>XUG}mKCKJ$OQ z8rZz(jMK5P%gyKuzi3+aQjDXNx9Ljy!FpuWL)V??C9(?jvCVn7H=K5FK)Ro(`@YGb z^U=TRqPL-(mH34;hcPe9#T+0v_w|>ce#SG`&&(LHi|>)HB>xp@+w0hZr;O#mn3v3H zUvV}hD|?06nGfYgujz-SGSNpe(|$RT=c3NnG6t;UyOdiwH@TfTF?E0E33l=YHk&lM zJ!D?+5AFCb_U0M-cOJWiUgf>QSbr5ALC;H}PxVgPwCP2uv$Nb&a)&wYVEQcjI|aLV zdJ6MeZ{~(M7+>idr3W&P!j3#4-(3Q*Iq7NR%6wm{GxOVm=o+>#qzvN@ZI+}8IzhSC z_oofw@!#^(Htq2_+Uh*-+pe+Sc%A1jXZ#{u;+ohq;P4;hs|j{|5$}^*GNv-VgiPjt zAR&xN`RQk*G5I0$?}3cj(byv!#ysAWd}4DObm1&M`kst__l5S_jm{UmLI3T^-D8R9 zt6_|bwBhY)?5p3yMlyE(m_;8?#n=?gc^1$uTNj056z!N zo3~~@LmU5AmUNkiZ^8yVq@6}H2DYyN{g!&^OI!6pkKQwv!9KLk!5PL$>~&BdztSh$ zra@OU@otE^L&qwhYnhXh?|saH%c4`vUFxi24w;iSCU4W|+s_j4>~XBq(D{Y*+ap=H zzrG{$(U|n*V8+`Yv~dVyApLJHx>R~B^Ev9bGUIrAbmU+JZGx@o*ACsH@0=*W{019% ziFR*9{e_HX|91_2Gz=R;8+1g^J{)CyY|8v<4P$?2F-JjXLp5#XVQd%eU5k0a4W2Wh z7juHd>~oQRCv3+p+I|4~7eakp?9KnI=`%jw=o4-6lrpp=?16UJhcD>*JkGY(#zy@^ zUmn7^&& zK6(^}4wtS)|9*_lyk?vnVAGnTN0$S!&nwXP3D^d7IP)~@DEl#wnOpSwihYbAUD|Uu z?Z5px=UAR&XFd@RJqcnicK(c*ukyZ{vaDi$wt6bhU%{A!UKPgveYlLB>w?ZPzV7&l zy+B{`{?44U3c5o74C%u>SZ3%oFJk(dZAuqtQN$AB+E_y-P8MSEZdkVmAk| z9(`-Y(t+RPm3GUHiKz*(mbCGo1Y$AgW?AY36 z%u%i}o(Ho&IYu2Er>-0Ej+HPe(UU1an&FI?dFp|Cc)*okx4 z0Pw61?2*tnPG4ZG{zkt=zdMJc7rU`}TiI{H-fX38JHV~?*hmDuyol~kLRY$J+Bxui z+V$fG-Zi%*FVubA%$$$2Q6HJvXQ{(_sR??BZFx=j&hfAbzn~k8ft%7WKmHwin~ykI z7%P5b?m_)80pfM%Kc+w!eQiZ_-tT!rr{}q}>)Lhn^8?h&G3LI7H0>|SwXi<(80^Gy z#`g~7qj4a1mbSQ0USj0IHkGIT=o?4Kd+wXG{|nw*yhWc%vPPx-KL3G^wj@k*)+KET zkA93tPiN3>^XPNaTVO{MqR+|6J2t*{F8V%c#UZT#(uzx3Nocdold-kfrsY4F|ImI< z2eKzcoFc1eS8S+vO!`?cbB5B)4~RFl2X!+6|E%<@-Ly>(>H)oN!}Ge;)!0D5){mrK z7{kKGp?fE=lLMF=B&1DNQkUh>?{C=qd7RzE#uhn&exD;RM_JFGL5C?<8_IQ|4ReBY z%xTcuJ>Srei_Am5v!Bofn@d0bk%#eQ7x%QIx25kgr(cGgdHV(WTLJ9W{n+TlJ>=V% zuTG~OX0qm}h8?25A1q|wjJ|so`Gc&~?R%S+VIKLWjTVs4H_+p$<9g(~eiG&-qtW@= ztT)l$+StfsKCEk#GS;QVuHI)(o04%FdzbP9?ZVu#drH28c9OAdC-uzyY+`Emv$ik? zt;HG&-EP4gBnflIti?41{x#-8#!;LcRFOlBnvebVz_Q&R8UqZ1pZg25_5y8>4XlFg&Ag2%H2=Er0v*|EZ9zT>ms&d zQATu|I^0&$1c7r#zrk2iw8U57K#ammLabdt9Df_?-9F;5*# z9Q0@keLk2mt0M7-VRKgissCbcXAJ%K2J_q2v}YK71ijmygTA|pIX3-cG4PiD{NxmR z6QA>CfAY)+%oEV1+FiJR<8N#~T(~Zf-Ikp&TPgcPD-2=~w#4dUS;L45J*~(5hswztYE_J!Jg7f<9q${AM#}LSITzPv^*U;o0o7(tie1Kj*2x{A-z? z=A`cXF^1>G#$`hP>F%G~?W<^>j?ePulE89Qr@yn}RO;(Z3fa!@ks`?a9yCGW1LIqttoU z50qtoN#-6s(7z(sYIJ4yGU{_V^@wg|#0GoOc8h51H0@{`!e)Ggu6d!)v{#0A=pSQ~ zHl4LOb#$I~NJ#&GH;H!jWF1NVN-kjTOxe;?Ujb`r!>jDGR-rB`vY%F!`oSh9zso!v zzu%~r!RgVtw&bTK`+=XC$L*jm&!H^zmxb86(F@Tl^kQs0>;>U23}sF;nzk&=*ht$p zpluItM@JIVmpy62CbTQ|>&8LGvf9k;^E0=iZ->$3doHtI%J}rIEAxt1oTuu}nd8Td zAu-VJX4r})l=TSuIgxt)$oNDaUZT6H(3e-}*AU7brvhnh!d{@yQ>gQS)Ngb8-hm3t zZ{9NZN`wvc<{b?7Y$fFhrTzz=>xJR`6 zR_ZXAc?;vj$!P5B{*7Ir{IOFo$3({#U|+Y;k88|eengvSmsl%Mxc8r_o4mBiC)$lR z^eBsskImi&`8>h=|2A=cWh{%8fH@{{k``xu<%7Nai}h$P<^YV(?+6!EmAN5(Ya@Ic zo_8PnRBt(bA}{mn@ALusU!MA$r-{#8hPquwz4aYI8JTBfY)*NwGb7yHelDEnqnJ-jhengv<(AZm@ zOIYkmq0Q_qZKuERtfAETs-oDhIOs+;=6LC8)9j2xWl4{Ao{Uace}`>f$+$y3FTaY- zNo3Oc^dMrY|?ePEhyp(78hQX}dXm!>A2&uno-B+cORhV4Z)8v1BB6E`;%R zBk9COf2R;{EMp<<(1yMqw*hlG(#zinTSh(ZuFM<}oy>ojac2p2OTXPgIgk1?Z_LPg zwJT#F^)Yl7Iy;PhNdKHRmiy6%(C$CzD@oDCPOL|BGdD-)8&e+@$y1MxjJfplGTpHw z^n=uk&|&I%FynYd?EI{5*dh8r$5!ms^kps@w|Kq%-w8 zll=qw;w9>7j5oHHzE+m@Xp|7UOd2;2uoqaIa#v*z4t_#jTNCGUHRcWHn5Qrv+oI9$ zYBRRb_t(+KwO;Jw4#S=?Uadl3|Dq4>AI)AOx_F8<4qHLJq$Su<`o(49Q15*et@A z-$~ievPQi^ozdPNdr7A`{r&}0;W3=^X6(CMlCfY4Yh!f6)`B_tI{IBT#s<;|e@)*X z&%Re;<^&5FYm2eJPdUTx(oTig3!{%sABf!^#J)ZKB@`INb8iASVlcMFq}{&IXMjm* z&`V(XK>8ng5%?5c0Dkml-qQzrJ(Tf_{+X7#>jjKU$9xK?mW*};z7?TNMX|rtnN!Xq z4()ZN9%DB)C5Jz24a$EV{Yw0|ruF=QP0UT*(+3{xN5A9KKW;LID}o&zL)q()59%uK zbjDCG>ahoNnuF*yHvb4=*JIZ+J!5Tz>^1FIbwBoq@^_#PyQ15Bfnjx+r(I#}%0Rd! z*wavSyfr#mleI%R*5muwPs~i3HOM>dlaRiD{Wg7)`u)8vZAkvt=All%Q^%w=xHP&( z|9f7SG9ST?p`%`nsW)t0Ano<+59~oE+WIlNv6S^;Y35u!f5~j-iof%YjlLa$?eJq> z6PGeBp3gIjvgdso`&k0p{V(GEb%uQjctV|_ubH}0kLXpoe#~#Kkv{eM;wH8#9=g?m zv7WY@9zZ>izen}x+rOe~lxKKc>ask#m!0zOre9Kqm*3gDd5zwDW{kr|B%{BN=)-#K z4rA_p>@v@6a)rLsoAH;r>O}iqqa1B>GOs?y-dH>A@JD#k%5jwSGCIAd7JIz)nUl~r zAEMvS(D|X%Yo~7X=^ljbMLq|!-lf0Sp>Fn0#@?a3``{V2xmo3J4_&^h$AAaff} zU&5h#@!7Y_Jeje32J4OH%%Q2nEfdj4>U-p4_WXvU@09JI$~>3)DCNTp}ZjQL!2c$tD~XLnyc0W8@k(*UBXp9hZbfbLm2iA-P0N zE>nh_$gS3)Tz1Umyq(j_*QyQxKJEe^NAx7=9u zN;9$hqMk3w9(p-LHSg^1I0pC76?CwP-rs#90W=KHJ3r}sAWzK?kL@++$j|cI%Q(J5 z-;b;LxRpOm5B3P{$b4FeXALo2mqx9D3C>NT#TV#B5I=RofxURzI}g68 zo?RCc-z(J;=50t%FFoVDZk;ptR{EIJdeR>H02~^<0A4-djW63uip%O=yDUcMshh;d z?Jx26D>-$ue*UntQydvA_KwnzG?)yZ0WW*0S5%L_$$4ECj`4Z#T)o0y{6ia>TG#q& z)+oLb@V)F5Yu=^5!T(fR-4+kxY1@nzIJHGhz$Zyn<#YP*Vkdc+{^#tL1Mo1di{}kz zVR6m<()h(1Bj9pyr1-$~pfvSQl->mn^LFxu_dXydW_s;bA=)MO!z;;~mFc3mY6$O; z4bCv|sYAY4r~_X(j2P=Yc%^*2hL1Ly4=0a`t3mYWQ5aQ97H9QoO(XGLpl9IIkO(oK zAa8dxx7QBZR~{XkwU8z(fs+N)G06y~hBMt527k)P$IHccl@2Gx$eo~I*=a)vi?^U{SQm){m)h%&9ls`JFb-Wh# zsT>5$;Nmcsw+iZ7(>wIGm2>He^5E;RjP}`4^oKPaE%)Ny71nFAvk%tGYl%(a_MZ5P zr-A&laTQ;8rGs9JrF-Y*c=obL?RnlA=T~ZpT6m8up>g=r7pK0K7y0|c9QcU)o{j7i zhvT>EWmCjXyf~W2-_O(E4Egdu>cO?@XgTAp*?Md-no5gW?#E63eyEtfvZFPZl@Gh& zq}WS>Z^y>s=VyEPHy(H``nWn9_ad7(-)CWq)P?QTa^i9nzc;uId-putN>=owF#@<6<3p-=U8*D^>(-^@6ww`4&YXxI^=-+@Kat*`?-R1{hX_AQacRB30&JY zNL)q1)$h}+rviNTgut90wXDw1FUTqX)E9`^erIS@CHbuyjW@>o%z$unJnJ6D#P;yI zq^4%Y#p&1VhFFPqzO-_dI5^=fX0~Twi}_bPZN|rNz6|5bp?rDqZS~-8F*jGvt?b`* z9c-_3p?`hYO|suMdJ=Obdj>jcr}MZV`!?q^c=imFW8HUEtmkR`AIKleo`)abo@=9K z7wau+%W2o>%-it$UVedj%ox3YId$;{xZ_!Dq`ew{+Y%5EwMV=!0S58cJ9o)>kE#=i)>Jz!OFg&x@FP+5U4(1+6D@yP|b$;aY{GPs}(^Eg011A`ix2})nqwWvO3pbnx!}w$gJ#Gbg zk}uEW`XysrmUE1ve0WPtgvzhRl)K^)$D7D&ecIw`3XI_KbS<^T5Zd(x?Sa*Cv9?t0 zko~ziPMdR)8qD6t!lg)IX9LF8@L2qVUizr{v*oe>=%w{+2`6B(haXRhFZdz_j%toqcpD;i zyO?vieRWMk0rQOHlhU}na{(V!g^$;J%5{l&Fn+sxd?#*y6(g;!bu4>H43491EV`6E z+Sdf*3Huzr-@NPW(Kuj-@7v|-L3-oS3H>I&1iRn9ruJ(*Ps57Pn>TBiQ@v0F&e8R0 z7;IztIHHT%>>%x$!S^_xc@F-3eH9OS^TDNta(X*Guj^V(ah^SPkOshSAe_IohWo@y zI&6~EGD+p-csZ@$RXuh^eN-hrJ|Z3p=mD-@fm7$l<%WIMXiRUU#tgGQT;4)!if7@t zIUnmmL*09VwV%TM6+?XP4Z8QH-eEYOilZ{}USs>t-|8%LIjwWuXp_3|S?B+!_0Frs zEDlG0M{A8g+2fM6_7%&=>*Nz$XuwzdaHAcre$G1M&{XkT>?7Y*Dbo&#v`xDXs_A@qA)}bwu#B7@7Dl7_4$`ZT;`l z@;RNIfAyr}{nccz(`@@F!!A^%b$Iy2C$NX{&3yHXGog9g<)#eZld{K0;r5yLwE6=_ z^YkL~-P?HZBo0-OJ0HS3V@w^s{D8I^ulsq+RJ!=M_x7`2f6cS@`}wPi z^O5HC$-R!4BRHP^6_an(5qqrj>_qkSgFcg}uYt>q);MQxmH9qfJic2K&j!*nbEXYe zmoBASi)baDCU@1>i=8<%bLf})_fzULg&0%aFqYhxNisxIjJYP(u?^eSO zP&2a}_EZRti?a!0=N02bR)(f5Tq}3h!5#6R66`+m>xfnA9X>vG9GA=+OQ*+HQ|En+ zAD>z0I%k%(>D49mNhtp0(n9Y|YvZhEEj(G*h2oLbhWUxta4KIeoJd2|q#5j~2Vuyb zOj4VhcW5EC$zA8c>X_< zUyqU(@OBFBUu9z=<R+v3}L{E8?R(4%T5^hv^{}*$*mZF`W4&6JJ@c(P zL2OR_!?Qs+mnf=!Wifwyjcsv#UmQN~r;Y4Wu|MP&=TIzaD$RZHkhHboubdfYAf*gdj-g3Hf*?K<%pHUCvPo&Mdq zONX-6YpjxbV=ntB8U_pHEBh=l$#)rOM}oY6s=N5_6 zJ!7~SsO>C_rCGzf5%N8I+uoM)-%l*Zbs_s~6@<6L>EJxt_JJCQR%AOzOb&3qcMK2l zc13|Rw03IFSLkLB^YFzvp9`9eTVL46({coRK3>0$FC`B6j@B;PS5XcQ!^wefSh9NDTVy_ltzTCN7?yOQ5|h9FM*PvJw? zV-EA+RW% zqn@+lS2Qi^N6;o;MwO+4=_X*!PgDs+#3l8iSR(w-QNDJC}lV^DUH>Jkc zD^@7_&&YtH;l%@@Z+07h*M@2Y%jA Date: Thu, 20 Apr 2023 21:12:41 +0200 Subject: [PATCH 25/33] Introduce BcCheck --- Modules/FIT/FV0/include/FV0/BcCheck.h | 48 ++++++++++++ Modules/FIT/FV0/src/BcCheck.cpp | 102 ++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 Modules/FIT/FV0/include/FV0/BcCheck.h create mode 100644 Modules/FIT/FV0/src/BcCheck.cpp diff --git a/Modules/FIT/FV0/include/FV0/BcCheck.h b/Modules/FIT/FV0/include/FV0/BcCheck.h new file mode 100644 index 0000000000..0e01c2155d --- /dev/null +++ b/Modules/FIT/FV0/include/FV0/BcCheck.h @@ -0,0 +1,48 @@ +// Copyright 2023 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 BcCheck.h +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +/// + +#ifndef QC_MODULE_FV0_BCCHECK_H +#define QC_MODULE_FV0_BCCHECK_H + +#include "QualityControl/CheckInterface.h" + +#include "FV0Base/Constants.h" + +namespace o2::quality_control_modules::fv0 +{ + +/// \brief This check provide xnor (exclusive nor) operation on SW and HW triggers +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +class BcCheck : public o2::quality_control::checker::CheckInterface +{ + public: + BcCheck() = default; + ~BcCheck() override = default; + + void configure() override; + Quality check(std::map>* moMap) override; + void beautify(std::shared_ptr mo, Quality checkResult = Quality::Null) override; + std::string getAcceptedType() override; + + ClassDefOverride(BcCheck, 2); + + private: + std::array mPositionMsgBox; +}; + +} // namespace o2::quality_control_modules::fv0 + +#endif // QC_MODULE_FV0_BCCHECK_H diff --git a/Modules/FIT/FV0/src/BcCheck.cpp b/Modules/FIT/FV0/src/BcCheck.cpp new file mode 100644 index 0000000000..45a914c15f --- /dev/null +++ b/Modules/FIT/FV0/src/BcCheck.cpp @@ -0,0 +1,102 @@ +// Copyright 2023 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 BcCheck.cxx +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +/// + +#include "FV0/BcCheck.h" +#include "QualityControl/MonitorObject.h" +#include "QualityControl/Quality.h" +#include "QualityControl/QcInfoLogger.h" +// ROOT +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace o2::quality_control; + +namespace o2::quality_control_modules::fv0 +{ + +constexpr int kBinSwOnly = 1; +constexpr int kBinTcmOnly = 2; + +void BcCheck::configure() +{ + +} + +Quality BcCheck::check(std::map>* moMap) +{ + Quality result = Quality::Null; + int mNumErrors = 0; + for (auto& [moName, mo] : *moMap) { + (void)moName; + if (mo->getName() == "BCvsFEEmodules" || mo->getName() == "BCvsTriggers") { + auto* histogram = dynamic_cast(mo->getObject()); + + if (!histogram) { + ILOG(Error, Support) << "check(): MO BCvsFEEmodules nor BCvsTriggers not found" << ENDM; + result.addReason(FlagReasonFactory::Unknown(), "MO BCvsFEEmodules nor BCvsTriggers not found"); + result.set(Quality::Null); + return result; + } + } + } + + return result; +} + +std::string BcCheck::getAcceptedType() { return "TH2"; } + +void BcCheck::beautify(std::shared_ptr mo, Quality checkResult) +{ + if (mo->getName() == "BCvsFEEmodules" || mo->getName() == "BCvsTriggers") { + auto* histogram = dynamic_cast(mo->getObject()); + + if (!histogram) { + ILOG(Error, Support) << "beautify(): MO BCvsFEEmodules nor BCvsTriggers not found" << ENDM; + return; + } + + TPaveText* msg = new TPaveText(mPositionMsgBox[0], mPositionMsgBox[1], mPositionMsgBox[2], mPositionMsgBox[3], "NDC"); + histogram->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + msg->Clear(); + msg->AddText(checkResult.getReasons()[0].second.c_str()); + int color = kBlack; + if (checkResult == Quality::Good) { + color = kGreen + 1; + msg->AddText(">> Quality::Good <<"); + } else if (checkResult == Quality::Medium) { + color = kOrange - 1; + msg->AddText(">> Quality::Medium <<"); + } else if (checkResult == Quality::Bad) { + color = kRed; + msg->AddText(">> Quality::Bad <<"); + } + msg->SetFillStyle(1); + msg->SetLineWidth(3); + msg->SetLineColor(color); + msg->SetShadowColor(color); + msg->SetTextColor(color); + msg->SetMargin(0.0); + } +} + +} // namespace o2::quality_control_modules::fv0 From 83cd83b7b3f8315be382a1584fe69e63d15df0a3 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Thu, 20 Apr 2023 21:33:36 +0200 Subject: [PATCH 26/33] Introduce BcCheck --- Modules/FIT/FV0/CMakeLists.txt | 4 +++- Modules/FIT/FV0/include/FV0/BcCheck.h | 2 -- Modules/FIT/FV0/include/FV0/LinkDef.h | 1 + Modules/FIT/FV0/src/{BcCheck.cpp => BcCheck.cxx} | 0 Modules/FIT/FV0/src/GenericCheck.cxx | 9 ++++++--- 5 files changed, 10 insertions(+), 6 deletions(-) rename Modules/FIT/FV0/src/{BcCheck.cpp => BcCheck.cxx} (100%) diff --git a/Modules/FIT/FV0/CMakeLists.txt b/Modules/FIT/FV0/CMakeLists.txt index 23355145e7..ea4b094f38 100644 --- a/Modules/FIT/FV0/CMakeLists.txt +++ b/Modules/FIT/FV0/CMakeLists.txt @@ -9,7 +9,8 @@ target_sources(O2QcFV0 PRIVATE src/TH1ReductorLaser.cxx src/CFDEffCheck.cxx src/PostProcTask.cxx src/OutOfBunchCollCheck.cxx - src/TriggersSwVsTcmCheck.cxx) + src/TriggersSwVsTcmCheck.cxx + src/BcCheck.cxx) target_include_directories( O2QcFV0 @@ -37,6 +38,7 @@ add_root_dictionary(O2QcFV0 include/FV0/OutOfBunchCollCheck.h include/FV0/GenericCheck.h include/FV0/TriggersSwVsTcmCheck.h + include/FV0/BcCheck.h LINKDEF include/FV0/LinkDef.h) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/FV0 diff --git a/Modules/FIT/FV0/include/FV0/BcCheck.h b/Modules/FIT/FV0/include/FV0/BcCheck.h index 0e01c2155d..f215d4a2ba 100644 --- a/Modules/FIT/FV0/include/FV0/BcCheck.h +++ b/Modules/FIT/FV0/include/FV0/BcCheck.h @@ -24,8 +24,6 @@ namespace o2::quality_control_modules::fv0 { -/// \brief This check provide xnor (exclusive nor) operation on SW and HW triggers -/// \author Dawid Skora dawid.mateusz.skora@cern.ch class BcCheck : public o2::quality_control::checker::CheckInterface { public: diff --git a/Modules/FIT/FV0/include/FV0/LinkDef.h b/Modules/FIT/FV0/include/FV0/LinkDef.h index c070f5164f..f59fec1468 100644 --- a/Modules/FIT/FV0/include/FV0/LinkDef.h +++ b/Modules/FIT/FV0/include/FV0/LinkDef.h @@ -9,6 +9,7 @@ #pragma link C++ class o2::quality_control_modules::fv0::OutOfBunchCollCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::GenericCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::TriggersSwVsTcmCheck + ; +#pragma link C++ class o2::quality_control_modules::fv0::BcCheck + ; //#pragma link C++ class o2::quality_control_modules::fv0::CalibrationTask + ; //#pragma link C++ class o2::quality_control_modules::fv0::ChannelTimeCalibrationCheck + ; diff --git a/Modules/FIT/FV0/src/BcCheck.cpp b/Modules/FIT/FV0/src/BcCheck.cxx similarity index 100% rename from Modules/FIT/FV0/src/BcCheck.cpp rename to Modules/FIT/FV0/src/BcCheck.cxx diff --git a/Modules/FIT/FV0/src/GenericCheck.cxx b/Modules/FIT/FV0/src/GenericCheck.cxx index 4e8ba4a851..d8db1acc68 100644 --- a/Modules/FIT/FV0/src/GenericCheck.cxx +++ b/Modules/FIT/FV0/src/GenericCheck.cxx @@ -119,8 +119,9 @@ void GenericCheck::configure() mDeadChannelMapStr += (mDeadChannelMapStr.empty() ? "" : ",") + std::to_string(chId); } } - if (mDeadChannelMapStr.empty()) + if (mDeadChannelMapStr.empty()) { mDeadChannelMapStr = "EMPTY"; + } ILOG(Info, Support) << "Loaded dead channel map: " << mDeadChannelMapStr << ENDM; mPositionMsgBox = { 0.15, 0.75, 0.85, 0.9 }; @@ -201,8 +202,9 @@ Quality GenericCheck::check(std::map if (mCheckMinThresholdY.isActive()) { float minValue = h->GetBinContent(1); for (int channel = 1; channel < h->GetNbinsX(); ++channel) { - if (channel >= sNCHANNELS || !mDeadChannelMap->isChannelAlive(channel)) + if (channel >= sNCHANNELS || !mDeadChannelMap->isChannelAlive(channel)) { continue; + } if (minValue > h->GetBinContent(channel)) { minValue = h->GetBinContent(channel); mCheckMinThresholdY.mBinNumberX = channel; @@ -218,8 +220,9 @@ Quality GenericCheck::check(std::map } else { float maxValue = 0; for (int channel = 1; channel < h->GetNbinsX(); ++channel) { - if (channel >= sNCHANNELS || !mDeadChannelMap->isChannelAlive(channel)) + if (channel >= sNCHANNELS || !mDeadChannelMap->isChannelAlive(channel)) { continue; + } if (maxValue < h->GetBinContent(channel)) { maxValue = h->GetBinContent(channel); mCheckMaxThresholdY.mBinNumberX = channel; From 15269d52c5cc6bacbdf7b7065cefeecd4fc938b7 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Fri, 21 Apr 2023 14:12:34 +0200 Subject: [PATCH 27/33] Save --- Modules/FIT/FV0/include/FV0/BcCheck.h | 4 +++ Modules/FIT/FV0/src/BcCheck.cxx | 38 ++++++++++++++++++++++++--- Modules/FIT/FV0/src/PostProcTask.cxx | 9 +++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/Modules/FIT/FV0/include/FV0/BcCheck.h b/Modules/FIT/FV0/include/FV0/BcCheck.h index f215d4a2ba..0035ebddf7 100644 --- a/Modules/FIT/FV0/include/FV0/BcCheck.h +++ b/Modules/FIT/FV0/include/FV0/BcCheck.h @@ -21,6 +21,8 @@ #include "FV0Base/Constants.h" +#include + namespace o2::quality_control_modules::fv0 { @@ -39,6 +41,8 @@ class BcCheck : public o2::quality_control::checker::CheckInterface private: std::array mPositionMsgBox; + o2::ccdb::CcdbApi mCcdbApi; + std::string mPathGrpLhcIf = "GLO/Config/GRPLHCIF"; }; } // namespace o2::quality_control_modules::fv0 diff --git a/Modules/FIT/FV0/src/BcCheck.cxx b/Modules/FIT/FV0/src/BcCheck.cxx index 45a914c15f..d154cfdfb1 100644 --- a/Modules/FIT/FV0/src/BcCheck.cxx +++ b/Modules/FIT/FV0/src/BcCheck.cxx @@ -18,6 +18,8 @@ #include "QualityControl/MonitorObject.h" #include "QualityControl/Quality.h" #include "QualityControl/QcInfoLogger.h" +#include "DataFormatsParameters/GRPLHCIFData.h" + // ROOT #include #include @@ -38,24 +40,52 @@ constexpr int kBinTcmOnly = 2; void BcCheck::configure() { - + long ts = 999; + std::map metadata; + std::map headers; + auto* lhcIf = mCcdbApi.retrieveFromTFileAny(mPathGrpLhcIf, metadata, ts, &headers); + if (!lhcIf) { + ILOG(Error, Support) << "object \"" << mPathGrpLhcIf << "\" NOT retrieved. BcCheck will not produce valid QC plots." << ENDM; + return; + } + const std::string bcName = lhcIf->getInjectionScheme(); + if (bcName.size() == 8) { + if (bcName.compare("no_value")) { + ILOG(Error, Support) << "Filling scheme not set. BcCheck will not produce valid QC plots." << ENDM; + } + } else { + ILOG(Info, Support) << "Filling scheme: " << bcName.c_str() << ENDM; + } + auto bcPattern = lhcIf->getBunchFilling(); } Quality BcCheck::check(std::map>* moMap) { Quality result = Quality::Null; int mNumErrors = 0; + bool metadataFound = false; + const std::string metadataKey = "BcVsTrgIntegralBin"; + for (auto& [moName, mo] : *moMap) { (void)moName; if (mo->getName() == "BCvsFEEmodules" || mo->getName() == "BCvsTriggers") { auto* histogram = dynamic_cast(mo->getObject()); if (!histogram) { - ILOG(Error, Support) << "check(): MO BCvsFEEmodules nor BCvsTriggers not found" << ENDM; - result.addReason(FlagReasonFactory::Unknown(), "MO BCvsFEEmodules nor BCvsTriggers not found"); + ILOG(Error, Support) << "check(): MO " << mo->getName() << " not found" << ENDM; + result.addReason(FlagReasonFactory::Unknown(), "MO " + mo->getName() + " not found"); result.set(Quality::Null); return result; } + + // TO DO Recive bcPattern from hists metadata + float metadata_info = 0; + for (auto metainfo : mo->getMetadataMap()) { + if (metainfo.first == metadataKey) { + metadata_info = std::stof(metainfo.second); + metadataFound = true; + } + } } } @@ -70,7 +100,7 @@ void BcCheck::beautify(std::shared_ptr mo, Quality checkResult) auto* histogram = dynamic_cast(mo->getObject()); if (!histogram) { - ILOG(Error, Support) << "beautify(): MO BCvsFEEmodules nor BCvsTriggers not found" << ENDM; + ILOG(Error, Support) << "beautify(): MO " << mo->getName() << " not found" << ENDM; return; } diff --git a/Modules/FIT/FV0/src/PostProcTask.cxx b/Modules/FIT/FV0/src/PostProcTask.cxx index 48bf05ddce..ae3727ff5c 100644 --- a/Modules/FIT/FV0/src/PostProcTask.cxx +++ b/Modules/FIT/FV0/src/PostProcTask.cxx @@ -421,6 +421,15 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) getObjectsManager()->getMonitorObject(mHistBcTrgOutOfBunchColl->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); ILOG(Info, Support) << metadataKey << ":" << metadataValue << ENDM; } + +// // TO DO download BC hists and add to their metadata bcPattern +// auto moBcVsFeeModules = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsFEEmodules", t.timestamp, t.activity); +// auto hBcVsFeeModules = moBcVsFeeModules ? dynamic_cast(moBcVsFeeModules->getObject()) : nullptr; +// if (!hBcVsFeeModules) { +// ILOG(Error, Support) << "MO \"BCvsTriggers\" NOT retrieved!!!" << ENDM; +// return; +// } +// getObjectsManager()->getMonitorObject(hBcVsFeeModules->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); } void PostProcTask::finalize(Trigger t, framework::ServiceRegistryRef) From fba0e4dd062ca2954bbba3854fa78361b7d36274 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Tue, 25 Apr 2023 11:56:40 +0200 Subject: [PATCH 28/33] Add metadata to BcVsTriggers and BcVsFeemodules --- Modules/FIT/FV0/src/PostProcTask.cxx | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Modules/FIT/FV0/src/PostProcTask.cxx b/Modules/FIT/FV0/src/PostProcTask.cxx index ae3727ff5c..d2f8a0008f 100644 --- a/Modules/FIT/FV0/src/PostProcTask.cxx +++ b/Modules/FIT/FV0/src/PostProcTask.cxx @@ -348,6 +348,14 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) mTime->GetYaxis()->SetTitleOffset(1); } + // TO DO download BC hists and add to their metadata bcPattern + auto moBcVsFeeModules = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsFEEmodules", t.timestamp, t.activity); + auto hBcVsFeeModules = moBcVsFeeModules ? dynamic_cast(moBcVsFeeModules->getObject()) : nullptr; + if (!hBcVsFeeModules) { + ILOG(Error, Support) << "MO \"BCvsTriggers\" NOT retrieved!!!" << ENDM; + return; + } + auto moBCvsTriggers = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsTriggers", t.timestamp, t.activity); auto hBcVsTrg = moBCvsTriggers ? dynamic_cast(moBCvsTriggers->getObject()) : nullptr; if (!hBcVsTrg) { @@ -404,6 +412,14 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) } } + // TEST + for (int iBin = 0; iBin < sBCperOrbit + 1; iBin++) { + const std::string metadataKey = "Bc" + std::to_string(iBin); + const std::string metadataValue = std::to_string(mHistBcPattern->GetBinContent(iBin)); + getObjectsManager()->getMonitorObject(hBcVsFeeModules->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); + getObjectsManager()->getMonitorObject(hBcVsTrg->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); + } + mHistBcTrgOutOfBunchColl->Reset(); float vmax = hBcVsTrg->GetBinContent(hBcVsTrg->GetMaximumBin()); mHistBcTrgOutOfBunchColl->Add(hBcVsTrg, mHistBcPattern.get(), 1, -1 * vmax); @@ -422,14 +438,6 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) ILOG(Info, Support) << metadataKey << ":" << metadataValue << ENDM; } -// // TO DO download BC hists and add to their metadata bcPattern -// auto moBcVsFeeModules = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsFEEmodules", t.timestamp, t.activity); -// auto hBcVsFeeModules = moBcVsFeeModules ? dynamic_cast(moBcVsFeeModules->getObject()) : nullptr; -// if (!hBcVsFeeModules) { -// ILOG(Error, Support) << "MO \"BCvsTriggers\" NOT retrieved!!!" << ENDM; -// return; -// } -// getObjectsManager()->getMonitorObject(hBcVsFeeModules->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); } void PostProcTask::finalize(Trigger t, framework::ServiceRegistryRef) From c018556265df9e8cb30dc5988d487147b7d582a9 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Tue, 25 Apr 2023 13:41:24 +0200 Subject: [PATCH 29/33] Change approach --- Modules/FIT/FV0/src/BcCheck.cxx | 14 +++++++------- Modules/FIT/FV0/src/PostProcTask.cxx | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Modules/FIT/FV0/src/BcCheck.cxx b/Modules/FIT/FV0/src/BcCheck.cxx index d154cfdfb1..f7a8555d88 100644 --- a/Modules/FIT/FV0/src/BcCheck.cxx +++ b/Modules/FIT/FV0/src/BcCheck.cxx @@ -27,6 +27,7 @@ #include #include +#include #include using namespace std; @@ -63,8 +64,8 @@ Quality BcCheck::check(std::map>* mo { Quality result = Quality::Null; int mNumErrors = 0; - bool metadataFound = false; - const std::string metadataKey = "BcVsTrgIntegralBin"; + std::map bcPatternMap; + std::vector bcPatternVec; for (auto& [moName, mo] : *moMap) { (void)moName; @@ -78,12 +79,11 @@ Quality BcCheck::check(std::map>* mo return result; } - // TO DO Recive bcPattern from hists metadata - float metadata_info = 0; + // Recive bcPattern from hists metadata for (auto metainfo : mo->getMetadataMap()) { - if (metainfo.first == metadataKey) { - metadata_info = std::stof(metainfo.second); - metadataFound = true; + if (metainfo.first.find("Bc")) { + // bcPatternMap.emplace(metainfo.first, std::stoi(metainfo.second)); + bcPatternVec[](std::stoi(metainfo.second)); } } } diff --git a/Modules/FIT/FV0/src/PostProcTask.cxx b/Modules/FIT/FV0/src/PostProcTask.cxx index d2f8a0008f..bfae4f463a 100644 --- a/Modules/FIT/FV0/src/PostProcTask.cxx +++ b/Modules/FIT/FV0/src/PostProcTask.cxx @@ -351,6 +351,7 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) // TO DO download BC hists and add to their metadata bcPattern auto moBcVsFeeModules = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsFEEmodules", t.timestamp, t.activity); auto hBcVsFeeModules = moBcVsFeeModules ? dynamic_cast(moBcVsFeeModules->getObject()) : nullptr; + auto hBcVsFeeModulesOutOfBunch = hBcVsFeeModules; if (!hBcVsFeeModules) { ILOG(Error, Support) << "MO \"BCvsTriggers\" NOT retrieved!!!" << ENDM; return; @@ -358,6 +359,7 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) auto moBCvsTriggers = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsTriggers", t.timestamp, t.activity); auto hBcVsTrg = moBCvsTriggers ? dynamic_cast(moBCvsTriggers->getObject()) : nullptr; + auto hBcVsTrgOutOfBanch = hBcVsTrg; if (!hBcVsTrg) { ILOG(Error, Support) << "MO \"BCvsTriggers\" NOT retrieved!!!" << ENDM; return; @@ -419,14 +421,24 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) getObjectsManager()->getMonitorObject(hBcVsFeeModules->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); getObjectsManager()->getMonitorObject(hBcVsTrg->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); } + hBcVsFeeModulesOutOfBunch->Reset(); + float vmax = hBcVsFeeModules->GetBinContent(hBcVsFeeModules->GetMaximumBin()); + hBcVsFeeModulesOutOfBunch->Add(hBcVsFeeModules, mHistBcPattern.get(), 1, -1 * vmax); + for (int i = 0; i < sBCperOrbit + 1; i++) { + for (int j = 0; j < mMapDigitTrgNames.size() + 1; j++) { + if (hBcVsFeeModulesOutOfBunch->GetBinContent(i + 1, j + 1) < 0) { + hBcVsFeeModulesOutOfBunch->SetBinContent(i + 1, j + 1, 0); + } + } + } mHistBcTrgOutOfBunchColl->Reset(); - float vmax = hBcVsTrg->GetBinContent(hBcVsTrg->GetMaximumBin()); + vmax = hBcVsTrg->GetBinContent(hBcVsTrg->GetMaximumBin()); mHistBcTrgOutOfBunchColl->Add(hBcVsTrg, mHistBcPattern.get(), 1, -1 * vmax); for (int i = 0; i < sBCperOrbit + 1; i++) { for (int j = 0; j < mMapDigitTrgNames.size() + 1; j++) { if (mHistBcTrgOutOfBunchColl->GetBinContent(i + 1, j + 1) < 0) { - mHistBcTrgOutOfBunchColl->SetBinContent(i + 1, j + 1, 0); // is it too slow? + mHistBcTrgOutOfBunchColl->SetBinContent(i + 1, j + 1, 0); } } } From 36a37664643374b70e81411aab5824e792541274 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Mon, 15 May 2023 12:02:29 +0200 Subject: [PATCH 30/33] Improve and rename BcCheck to OutOfBunchCollFeeModulesCheck --- Modules/FIT/FV0/CMakeLists.txt | 4 +- Modules/FIT/FV0/include/FV0/LinkDef.h | 2 +- ...heck.h => OutOfBunchCollFeeModulesCheck.h} | 24 +-- Modules/FIT/FV0/include/FV0/PostProcTask.h | 8 + Modules/FIT/FV0/src/BcCheck.cxx | 132 --------------- .../FV0/src/OutOfBunchCollFeeModulesCheck.cxx | 159 ++++++++++++++++++ Modules/FIT/FV0/src/PostProcTask.cxx | 120 +++++++++---- Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx | 2 +- 8 files changed, 274 insertions(+), 177 deletions(-) rename Modules/FIT/FV0/include/FV0/{BcCheck.h => OutOfBunchCollFeeModulesCheck.h} (62%) delete mode 100644 Modules/FIT/FV0/src/BcCheck.cxx create mode 100644 Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx diff --git a/Modules/FIT/FV0/CMakeLists.txt b/Modules/FIT/FV0/CMakeLists.txt index ea4b094f38..d31b9d5d88 100644 --- a/Modules/FIT/FV0/CMakeLists.txt +++ b/Modules/FIT/FV0/CMakeLists.txt @@ -10,7 +10,7 @@ target_sources(O2QcFV0 PRIVATE src/TH1ReductorLaser.cxx src/PostProcTask.cxx src/OutOfBunchCollCheck.cxx src/TriggersSwVsTcmCheck.cxx - src/BcCheck.cxx) + src/OutOfBunchCollFeeModulesCheck.cxx) target_include_directories( O2QcFV0 @@ -38,7 +38,7 @@ add_root_dictionary(O2QcFV0 include/FV0/OutOfBunchCollCheck.h include/FV0/GenericCheck.h include/FV0/TriggersSwVsTcmCheck.h - include/FV0/BcCheck.h + include/FV0/OutOfBunchCollFeeModulesCheck.h LINKDEF include/FV0/LinkDef.h) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/FV0 diff --git a/Modules/FIT/FV0/include/FV0/LinkDef.h b/Modules/FIT/FV0/include/FV0/LinkDef.h index f59fec1468..69751a9930 100644 --- a/Modules/FIT/FV0/include/FV0/LinkDef.h +++ b/Modules/FIT/FV0/include/FV0/LinkDef.h @@ -9,7 +9,7 @@ #pragma link C++ class o2::quality_control_modules::fv0::OutOfBunchCollCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::GenericCheck + ; #pragma link C++ class o2::quality_control_modules::fv0::TriggersSwVsTcmCheck + ; -#pragma link C++ class o2::quality_control_modules::fv0::BcCheck + ; +#pragma link C++ class o2::quality_control_modules::fv0::OutOfBunchCollFeeModulesCheck + ; //#pragma link C++ class o2::quality_control_modules::fv0::CalibrationTask + ; //#pragma link C++ class o2::quality_control_modules::fv0::ChannelTimeCalibrationCheck + ; diff --git a/Modules/FIT/FV0/include/FV0/BcCheck.h b/Modules/FIT/FV0/include/FV0/OutOfBunchCollFeeModulesCheck.h similarity index 62% rename from Modules/FIT/FV0/include/FV0/BcCheck.h rename to Modules/FIT/FV0/include/FV0/OutOfBunchCollFeeModulesCheck.h index 0035ebddf7..3d35dd3150 100644 --- a/Modules/FIT/FV0/include/FV0/BcCheck.h +++ b/Modules/FIT/FV0/include/FV0/OutOfBunchCollFeeModulesCheck.h @@ -10,41 +10,43 @@ // or submit itself to any jurisdiction. /// -/// \file BcCheck.h +/// \file OutOfBunchCollFeeModulesCheck.h /// \author Dawid Skora dawid.mateusz.skora@cern.ch /// -#ifndef QC_MODULE_FV0_BCCHECK_H -#define QC_MODULE_FV0_BCCHECK_H +#ifndef QC_MODULE_FV0_OUTOFBUNCHCOLLFEEMODULESCHECK_H +#define QC_MODULE_FV0_OUTOFBUNCHCOLLFEEMODULESCHECK_H #include "QualityControl/CheckInterface.h" #include "FV0Base/Constants.h" +#include "CommonConstants/LHCConstants.h" #include namespace o2::quality_control_modules::fv0 { -class BcCheck : public o2::quality_control::checker::CheckInterface +class OutOfBunchCollFeeModulesCheck : public o2::quality_control::checker::CheckInterface { public: - BcCheck() = default; - ~BcCheck() override = default; + OutOfBunchCollFeeModulesCheck() = default; + ~OutOfBunchCollFeeModulesCheck() override = default; void configure() override; Quality check(std::map>* moMap) override; void beautify(std::shared_ptr mo, Quality checkResult = Quality::Null) override; std::string getAcceptedType() override; - ClassDefOverride(BcCheck, 2); + ClassDefOverride(OutOfBunchCollFeeModulesCheck, 2); private: - std::array mPositionMsgBox; - o2::ccdb::CcdbApi mCcdbApi; - std::string mPathGrpLhcIf = "GLO/Config/GRPLHCIF"; + float mThreshWarning; + float mThreshError; + float mFractionOutOfBunchColl = 0; + constexpr static std::size_t sBCperOrbit = o2::constants::lhc::LHCMaxBunches; }; } // namespace o2::quality_control_modules::fv0 -#endif // QC_MODULE_FV0_BCCHECK_H +#endif // QC_MODULE_FV0_OUTOFBUNCHCOLLFEEMODULESCHECK_H diff --git a/Modules/FIT/FV0/include/FV0/PostProcTask.h b/Modules/FIT/FV0/include/FV0/PostProcTask.h index d4d1c3b3fd..998f713976 100644 --- a/Modules/FIT/FV0/include/FV0/PostProcTask.h +++ b/Modules/FIT/FV0/include/FV0/PostProcTask.h @@ -29,6 +29,8 @@ #include #include #include +#include +#include class TH1F; class TCanvas; @@ -87,9 +89,15 @@ class PostProcTask final : public quality_control::postprocessing::PostProcessin // if storage size matters it can be replaced with TH1 // and TH2 can be created based on it on the fly, but only TH1 would be stored std::unique_ptr mHistBcPattern; + std::unique_ptr mHistBcPatternFee; std::unique_ptr mHistBcTrgOutOfBunchColl; + std::unique_ptr mHistBcFeeOutOfBunchColl; + uint8_t mTCMhash; + std::array mChID2PMhash; // map chID->hashed PM value + std::map mMapPMhash2isInner; std::map mMapTrgHistBC; + std::map mMapFEE2hash; }; } // namespace o2::quality_control_modules::fv0 diff --git a/Modules/FIT/FV0/src/BcCheck.cxx b/Modules/FIT/FV0/src/BcCheck.cxx deleted file mode 100644 index f7a8555d88..0000000000 --- a/Modules/FIT/FV0/src/BcCheck.cxx +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright 2023 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 BcCheck.cxx -/// \author Dawid Skora dawid.mateusz.skora@cern.ch -/// - -#include "FV0/BcCheck.h" -#include "QualityControl/MonitorObject.h" -#include "QualityControl/Quality.h" -#include "QualityControl/QcInfoLogger.h" -#include "DataFormatsParameters/GRPLHCIFData.h" - -// ROOT -#include -#include -#include -#include -#include - -#include -#include - -using namespace std; -using namespace o2::quality_control; - -namespace o2::quality_control_modules::fv0 -{ - -constexpr int kBinSwOnly = 1; -constexpr int kBinTcmOnly = 2; - -void BcCheck::configure() -{ - long ts = 999; - std::map metadata; - std::map headers; - auto* lhcIf = mCcdbApi.retrieveFromTFileAny(mPathGrpLhcIf, metadata, ts, &headers); - if (!lhcIf) { - ILOG(Error, Support) << "object \"" << mPathGrpLhcIf << "\" NOT retrieved. BcCheck will not produce valid QC plots." << ENDM; - return; - } - const std::string bcName = lhcIf->getInjectionScheme(); - if (bcName.size() == 8) { - if (bcName.compare("no_value")) { - ILOG(Error, Support) << "Filling scheme not set. BcCheck will not produce valid QC plots." << ENDM; - } - } else { - ILOG(Info, Support) << "Filling scheme: " << bcName.c_str() << ENDM; - } - auto bcPattern = lhcIf->getBunchFilling(); -} - -Quality BcCheck::check(std::map>* moMap) -{ - Quality result = Quality::Null; - int mNumErrors = 0; - std::map bcPatternMap; - std::vector bcPatternVec; - - for (auto& [moName, mo] : *moMap) { - (void)moName; - if (mo->getName() == "BCvsFEEmodules" || mo->getName() == "BCvsTriggers") { - auto* histogram = dynamic_cast(mo->getObject()); - - if (!histogram) { - ILOG(Error, Support) << "check(): MO " << mo->getName() << " not found" << ENDM; - result.addReason(FlagReasonFactory::Unknown(), "MO " + mo->getName() + " not found"); - result.set(Quality::Null); - return result; - } - - // Recive bcPattern from hists metadata - for (auto metainfo : mo->getMetadataMap()) { - if (metainfo.first.find("Bc")) { - // bcPatternMap.emplace(metainfo.first, std::stoi(metainfo.second)); - bcPatternVec[](std::stoi(metainfo.second)); - } - } - } - } - - return result; -} - -std::string BcCheck::getAcceptedType() { return "TH2"; } - -void BcCheck::beautify(std::shared_ptr mo, Quality checkResult) -{ - if (mo->getName() == "BCvsFEEmodules" || mo->getName() == "BCvsTriggers") { - auto* histogram = dynamic_cast(mo->getObject()); - - if (!histogram) { - ILOG(Error, Support) << "beautify(): MO " << mo->getName() << " not found" << ENDM; - return; - } - - TPaveText* msg = new TPaveText(mPositionMsgBox[0], mPositionMsgBox[1], mPositionMsgBox[2], mPositionMsgBox[3], "NDC"); - histogram->GetListOfFunctions()->Add(msg); - msg->SetName(Form("%s_msg", mo->GetName())); - msg->Clear(); - msg->AddText(checkResult.getReasons()[0].second.c_str()); - int color = kBlack; - if (checkResult == Quality::Good) { - color = kGreen + 1; - msg->AddText(">> Quality::Good <<"); - } else if (checkResult == Quality::Medium) { - color = kOrange - 1; - msg->AddText(">> Quality::Medium <<"); - } else if (checkResult == Quality::Bad) { - color = kRed; - msg->AddText(">> Quality::Bad <<"); - } - msg->SetFillStyle(1); - msg->SetLineWidth(3); - msg->SetLineColor(color); - msg->SetShadowColor(color); - msg->SetTextColor(color); - msg->SetMargin(0.0); - } -} - -} // namespace o2::quality_control_modules::fv0 diff --git a/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx b/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx new file mode 100644 index 0000000000..9c88809a42 --- /dev/null +++ b/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx @@ -0,0 +1,159 @@ +// Copyright 2023 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 OutOfBunchCollFeeModulesCheck.cxx +/// \author Dawid Skora dawid.mateusz.skora@cern.ch +/// + +#include "FV0/OutOfBunchCollFeeModulesCheck.h" +#include "QualityControl/MonitorObject.h" +#include "QualityControl/Quality.h" +#include "QualityControl/QcInfoLogger.h" +#include "DataFormatsParameters/GRPLHCIFData.h" + +// ROOT +#include +#include +#include +#include +#include + +#include +#include + +using namespace std; +using namespace o2::quality_control; + +namespace o2::quality_control_modules::fv0 +{ + +void OutOfBunchCollFeeModulesCheck::configure() +{ + if (auto param = mCustomParameters.find("thresholdWarning"); param != mCustomParameters.end()) { + mThreshWarning = stof(param->second); + ILOG(Debug, Support) << "configure() : using thresholdWarning = " << mThreshWarning << ENDM; + } else { + mThreshWarning = 1e-3; + ILOG(Debug, Support) << "configure() : using default thresholdWarning = " << mThreshWarning << ENDM; + } + + if (auto param = mCustomParameters.find("thresholdError"); param != mCustomParameters.end()) { + mThreshError = stof(param->second); + ILOG(Debug, Support) << "configure() : using thresholdError = " << mThreshError << ENDM; + } else { + mThreshError = 0.1; + ILOG(Debug, Support) << "configure() : using default thresholdError = " << mThreshError << ENDM; + } + + if(mThreshError < mThreshWarning) { + ILOG(Debug, Support) << "thresholdError lower than thresholdWarning. Swaping values." << ENDM; + std::swap(mThreshError, mThreshWarning); + } +} + +Quality OutOfBunchCollFeeModulesCheck::check(std::map>* moMap) +{ + Quality result = Quality::Null; + + for (auto& [moName, mo] : *moMap) { + (void)moName; + if (mo->getName() == "OutOfBunchColl_BCvsFeeModules") { + auto* histogram = dynamic_cast(mo->getObject()); + + if (!histogram) { + ILOG(Error, Support) << "check(): MO " << mo->getName() << " not found" << ENDM; + result.addReason(FlagReasonFactory::Unknown(), "MO " + mo->getName() + " not found"); + result.set(Quality::Null); + return result; + } + + std::vector allCollPerFeeModule(mo->getMetadataMap().size() + 1, 0); + for (auto metainfo : mo->getMetadataMap()) { + int bin = 0; + float value = 0; + try + { + bin = std::stoi(metainfo.first); + value = std::stof(metainfo.second); + } + catch(const std::invalid_argument& e) + { + continue; + } + allCollPerFeeModule[bin] = value; + } + + // Calculate out-of-bunch-coll fraction for Fee Modules + for (int binY = 1; binY <= histogram->GetNbinsY(); binY++) { + auto outOfBcCollisions = histogram->Integral(1, sBCperOrbit, binY, binY); + auto fraction = outOfBcCollisions / allCollPerFeeModule[binY]; + + if (fraction > mFractionOutOfBunchColl) { + mFractionOutOfBunchColl = fraction; + } + } + + // Check the biggest fraction of out-of-bunch-coll + if (mFractionOutOfBunchColl > mThreshError) { + result.set(Quality::Bad); + result.addReason(FlagReasonFactory::Unknown(), + Form("Fraction of out of bunch collisions (%.2e) is above \"Error\" threshold (%.2e)", + mFractionOutOfBunchColl, mThreshError)); + } else if (mFractionOutOfBunchColl > mThreshWarning) { + result.set(Quality::Medium); + result.addReason(FlagReasonFactory::Unknown(), + Form("Fraction of out of bunch collisions (%.2e) is above \"Warning\" threshold (%.2e)", + mFractionOutOfBunchColl, mThreshWarning)); + } else { + result.set(Quality::Good); + } + } + } + + return result; +} + +std::string OutOfBunchCollFeeModulesCheck::getAcceptedType() { return "TH2"; } + +void OutOfBunchCollFeeModulesCheck::beautify(std::shared_ptr mo, Quality checkResult) +{ + if (mo->getName() == "OutOfBunchColl_BCvsFeeModules") { + auto* histogram = dynamic_cast(mo->getObject()); + + if (!histogram) { + ILOG(Error, Support) << "beautify(): MO " << mo->getName() << " not found" << ENDM; + return; + } + + TPaveText* msg = new TPaveText(0.1, 0.85, 0.9, 0.9, "NDC"); + histogram->GetListOfFunctions()->Add(msg); + msg->SetName(Form("%s_msg", mo->GetName())); + msg->Clear(); + if(checkResult.isWorseThan(Quality::Good)) { + msg->AddText(checkResult.getReasons()[0].second.c_str()); + } + int color = kWhite; + if (checkResult == Quality::Good) { + color = kGreen + 1; + msg->AddText(">> Quality::Good <<"); + } else if (checkResult == Quality::Medium) { + color = kOrange - 1; + msg->AddText(">> Quality::Medium <<"); + } else if (checkResult == Quality::Bad) { + color = kRed; + msg->AddText(">> Quality::Bad <<"); + } + msg->SetFillColor(color); + } +} + +} // namespace o2::quality_control_modules::fv0 diff --git a/Modules/FIT/FV0/src/PostProcTask.cxx b/Modules/FIT/FV0/src/PostProcTask.cxx index bfae4f463a..cae65d8434 100644 --- a/Modules/FIT/FV0/src/PostProcTask.cxx +++ b/Modules/FIT/FV0/src/PostProcTask.cxx @@ -18,6 +18,7 @@ #include "QualityControl/QcInfoLogger.h" #include "CommonConstants/LHCConstants.h" #include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsFV0/LookUpTable.h" #include #include @@ -25,6 +26,8 @@ #include #include #include +#include +#include using namespace o2::quality_control::postprocessing; @@ -96,6 +99,7 @@ void PostProcTask::configure(const boost::property_tree::ptree& config) mTimestampSourceLhcIf = "trigger"; ILOG(Debug, Support) << "configure() : using default timestampSourceLhcIf = \"" << mTimestampSourceLhcIf << "\"" << ENDM; } + } void PostProcTask::initialize(Trigger, framework::ServiceRegistryRef services) @@ -175,11 +179,52 @@ void PostProcTask::initialize(Trigger, framework::ServiceRegistryRef services) getObjectsManager()->startPublishing(pairHistBC.first->second); } } + + const auto& lut = o2::fv0::SingleLUT::Instance().getVecMetadataFEE(); + auto lutSorted = lut; + std::sort(lutSorted.begin(), lutSorted.end(), [](const auto& first, const auto& second) { return first.mModuleName < second.mModuleName; }); + uint8_t binPos{ 0 }; + for (const auto& lutEntry : lutSorted) { + const auto& moduleName = lutEntry.mModuleName; + const auto& moduleType = lutEntry.mModuleType; + const auto& strChID = lutEntry.mChannelID; + const auto& pairIt = mMapFEE2hash.insert({ moduleName, binPos }); + if (pairIt.second) { + binPos++; + } + if (std::regex_match(strChID, std::regex("[[\\d]{1,3}"))) { + int chID = std::stoi(strChID); + if (chID < sNCHANNELS_FV0_PLUSREF) { + mChID2PMhash[chID] = mMapFEE2hash[moduleName]; + } else { + ILOG(Error, Support) << "Incorrect LUT entry: chID " << strChID << " | " << moduleName << ENDM; + } + } else if (moduleType != "TCM") { + ILOG(Error, Support) << "Non-TCM module w/o numerical chID: chID " << strChID << " | " << moduleName<< ENDM; + } else if (moduleType == "TCM") { + uint8_t mTCMhash = mMapFEE2hash[moduleName]; + } + } + + mHistBcPatternFee = std::make_unique("bcPatternForFeeModules", "BC pattern", sBCperOrbit, 0, sBCperOrbit, 13, 0, 13); + mHistBcFeeOutOfBunchColl = std::make_unique("OutOfBunchColl_BCvsFeeModules", "BC vs FEE Modules for out-of-bunch collisions;BC;FEE Modules", sBCperOrbit, 0, sBCperOrbit, mMapFEE2hash.size(), 0, mMapFEE2hash.size()); + + for (const auto& entry : mMapFEE2hash) { + // ILOG(Warning, Support) << "============= mMapFEE2hash.second + 1: " << entry.second + 1 + // << " mMapFEE2hash.first.c_str(): " << entry.first.c_str() << ENDM; + + mHistBcPatternFee->GetYaxis()->SetBinLabel(entry.second + 1, entry.first.c_str()); + mHistBcFeeOutOfBunchColl->GetYaxis()->SetBinLabel(entry.second + 1, entry.first.c_str()); + } getObjectsManager()->startPublishing(mHistTriggers.get()); getObjectsManager()->startPublishing(mHistBcPattern.get()); getObjectsManager()->setDefaultDrawOptions(mHistBcPattern.get(), "COLZ"); getObjectsManager()->startPublishing(mHistBcTrgOutOfBunchColl.get()); getObjectsManager()->setDefaultDrawOptions(mHistBcTrgOutOfBunchColl.get(), "COLZ"); + getObjectsManager()->startPublishing(mHistBcPatternFee.get()); + getObjectsManager()->setDefaultDrawOptions(mHistBcPatternFee.get(), "COLZ"); + getObjectsManager()->startPublishing(mHistBcFeeOutOfBunchColl.get()); + getObjectsManager()->setDefaultDrawOptions(mHistBcFeeOutOfBunchColl.get(), "COLZ"); mHistTimeUpperFraction = std::make_unique("TimeUpperFraction", "Fraction of events under time window(-+190 channels);ChID;Fraction", sNCHANNELS_FV0_PLUSREF, 0, sNCHANNELS_FV0_PLUSREF); getObjectsManager()->startPublishing(mHistTimeUpperFraction.get()); @@ -348,23 +393,13 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) mTime->GetYaxis()->SetTitleOffset(1); } - // TO DO download BC hists and add to their metadata bcPattern - auto moBcVsFeeModules = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsFEEmodules", t.timestamp, t.activity); - auto hBcVsFeeModules = moBcVsFeeModules ? dynamic_cast(moBcVsFeeModules->getObject()) : nullptr; - auto hBcVsFeeModulesOutOfBunch = hBcVsFeeModules; - if (!hBcVsFeeModules) { - ILOG(Error, Support) << "MO \"BCvsTriggers\" NOT retrieved!!!" << ENDM; - return; - } - + // Download BCvsTriggers auto moBCvsTriggers = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsTriggers", t.timestamp, t.activity); auto hBcVsTrg = moBCvsTriggers ? dynamic_cast(moBCvsTriggers->getObject()) : nullptr; - auto hBcVsTrgOutOfBanch = hBcVsTrg; if (!hBcVsTrg) { ILOG(Error, Support) << "MO \"BCvsTriggers\" NOT retrieved!!!" << ENDM; return; } - for (const auto& entry : mMapTrgHistBC) { hBcVsTrg->ProjectionX(entry.second->GetName(), entry.first + 1, entry.first + 1); } @@ -390,6 +425,8 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) } } + + // Download bcPattern std::map metadata; std::map headers; auto* lhcIf = mCcdbApi.retrieveFromTFileAny(mPathGrpLhcIf, metadata, ts, &headers); @@ -407,33 +444,56 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) } auto bcPattern = lhcIf->getBunchFilling(); - mHistBcPattern->Reset(); - for (int i = 0; i < sBCperOrbit + 1; i++) { - for (int j = 0; j < mMapDigitTrgNames.size() + 1; j++) { - mHistBcPattern->SetBinContent(i + 1, j + 1, bcPattern.testBC(i)); + + // Download histogram BCvsFEEmodules from database + auto moBcVsFeeModules = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsFEEmodules", t.timestamp, t.activity); + auto hBcVsFeeModules = moBcVsFeeModules ? dynamic_cast(moBcVsFeeModules->getObject()) : nullptr; + + + if (!hBcVsFeeModules) { + ILOG(Error, Support) << "MO \"BCvsFEEmodules\" NOT retrieved!!!" << ENDM; + return; + } else { + + // Create histogram with bc pattern for FEE modules + mHistBcPatternFee->Reset(); + for (int i = 0; i < sBCperOrbit + 1; i++) { + for (int j = 0; j < mMapFEE2hash.size() + 1; j++) { + mHistBcPatternFee->SetBinContent(i + 1, j + 1, bcPattern.testBC(i)); + } } - } + ILOG(Warning, Support) << " mHistBcPatternFee->Integral: " << mHistBcPatternFee->Integral(1, sBCperOrbit, 1, mMapFEE2hash.size()) << ENDM; - // TEST - for (int iBin = 0; iBin < sBCperOrbit + 1; iBin++) { - const std::string metadataKey = "Bc" + std::to_string(iBin); - const std::string metadataValue = std::to_string(mHistBcPattern->GetBinContent(iBin)); - getObjectsManager()->getMonitorObject(hBcVsFeeModules->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); - getObjectsManager()->getMonitorObject(hBcVsTrg->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); + mHistBcFeeOutOfBunchColl->Reset(); + float vmax = hBcVsFeeModules->GetBinContent(hBcVsFeeModules->GetMaximumBin()); + mHistBcFeeOutOfBunchColl->Add(hBcVsFeeModules, mHistBcPatternFee.get(), 1, -1 * vmax); + + for (int i = 0; i < sBCperOrbit + 1; i++) { + for (int j = 0; j < mMapFEE2hash.size() + 1; j++) { + if (mHistBcFeeOutOfBunchColl->GetBinContent(i + 1, j + 1) < 0) { + mHistBcFeeOutOfBunchColl->SetBinContent(i + 1, j + 1, 0); + } + } + } + + // Add metadata to histogram OutOfBunchColl_BCvsFeeModules + mHistBcFeeOutOfBunchColl->SetEntries(mHistBcFeeOutOfBunchColl->Integral(1, sBCperOrbit, 1, mMapFEE2hash.size())); + for (int iBin = 1; iBin <= mMapFEE2hash.size(); iBin++) { + const std::string metadataKey = std::to_string(iBin); + const std::string metadataValue = std::to_string(hBcVsFeeModules->Integral(1, sBCperOrbit, iBin, iBin)); + getObjectsManager()->getMonitorObject(mHistBcFeeOutOfBunchColl->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); + } } - hBcVsFeeModulesOutOfBunch->Reset(); - float vmax = hBcVsFeeModules->GetBinContent(hBcVsFeeModules->GetMaximumBin()); - hBcVsFeeModulesOutOfBunch->Add(hBcVsFeeModules, mHistBcPattern.get(), 1, -1 * vmax); + + mHistBcPattern->Reset(); for (int i = 0; i < sBCperOrbit + 1; i++) { for (int j = 0; j < mMapDigitTrgNames.size() + 1; j++) { - if (hBcVsFeeModulesOutOfBunch->GetBinContent(i + 1, j + 1) < 0) { - hBcVsFeeModulesOutOfBunch->SetBinContent(i + 1, j + 1, 0); - } + mHistBcPattern->SetBinContent(i + 1, j + 1, bcPattern.testBC(i)); } } mHistBcTrgOutOfBunchColl->Reset(); - vmax = hBcVsTrg->GetBinContent(hBcVsTrg->GetMaximumBin()); + float vmax = hBcVsTrg->GetBinContent(hBcVsTrg->GetMaximumBin()); mHistBcTrgOutOfBunchColl->Add(hBcVsTrg, mHistBcPattern.get(), 1, -1 * vmax); for (int i = 0; i < sBCperOrbit + 1; i++) { for (int j = 0; j < mMapDigitTrgNames.size() + 1; j++) { @@ -442,6 +502,7 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) } } } + mHistBcTrgOutOfBunchColl->SetEntries(mHistBcTrgOutOfBunchColl->Integral(1, sBCperOrbit, 1, mMapDigitTrgNames.size())); for (int iBin = 1; iBin < mMapDigitTrgNames.size() + 1; iBin++) { const std::string metadataKey = "BcVsTrgIntegralBin" + std::to_string(iBin); @@ -449,7 +510,6 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) getObjectsManager()->getMonitorObject(mHistBcTrgOutOfBunchColl->GetName())->addOrUpdateMetadata(metadataKey, metadataValue); ILOG(Info, Support) << metadataKey << ":" << metadataValue << ENDM; } - } void PostProcTask::finalize(Trigger t, framework::ServiceRegistryRef) diff --git a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx index f00f5033b1..a126c12010 100644 --- a/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx +++ b/Modules/FIT/FV0/src/TriggersSwVsTcmCheck.cxx @@ -119,7 +119,7 @@ void TriggersSwVsTcmCheck::beautify(std::shared_ptr mo, Quality c msg->SetName(Form("%s_msg", mo->GetName())); msg->Clear(); msg->AddText(checkResult.getReasons()[0].second.c_str()); - int color = kBlack; + int color = kWhite; if (checkResult == Quality::Good) { color = kGreen + 1; msg->AddText(">> Quality::Good <<"); From 59ec16b23b81a5e148856295cddad634ef693dcd Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Tue, 16 May 2023 16:50:32 +0200 Subject: [PATCH 31/33] Apply clang-format fixes in code --- .../FV0/src/OutOfBunchCollFeeModulesCheck.cxx | 23 ++++++++----------- Modules/FIT/FV0/src/PostProcTask.cxx | 10 +++----- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx b/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx index 9c88809a42..17f2dddd99 100644 --- a/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx +++ b/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx @@ -54,7 +54,7 @@ void OutOfBunchCollFeeModulesCheck::configure() ILOG(Debug, Support) << "configure() : using default thresholdError = " << mThreshError << ENDM; } - if(mThreshError < mThreshWarning) { + if (mThreshError < mThreshWarning) { ILOG(Debug, Support) << "thresholdError lower than thresholdWarning. Swaping values." << ENDM; std::swap(mThreshError, mThreshWarning); } @@ -79,14 +79,11 @@ Quality OutOfBunchCollFeeModulesCheck::check(std::map allCollPerFeeModule(mo->getMetadataMap().size() + 1, 0); for (auto metainfo : mo->getMetadataMap()) { int bin = 0; - float value = 0; - try - { + float value = 0; + try { bin = std::stoi(metainfo.first); value = std::stof(metainfo.second); - } - catch(const std::invalid_argument& e) - { + } catch (const std::invalid_argument& e) { continue; } allCollPerFeeModule[bin] = value; @@ -96,26 +93,26 @@ Quality OutOfBunchCollFeeModulesCheck::check(std::mapGetNbinsY(); binY++) { auto outOfBcCollisions = histogram->Integral(1, sBCperOrbit, binY, binY); auto fraction = outOfBcCollisions / allCollPerFeeModule[binY]; - + if (fraction > mFractionOutOfBunchColl) { mFractionOutOfBunchColl = fraction; - } + } } // Check the biggest fraction of out-of-bunch-coll if (mFractionOutOfBunchColl > mThreshError) { result.set(Quality::Bad); result.addReason(FlagReasonFactory::Unknown(), - Form("Fraction of out of bunch collisions (%.2e) is above \"Error\" threshold (%.2e)", + Form("Fraction of out of bunch collisions (%.2e) is above \"Error\" threshold (%.2e)", mFractionOutOfBunchColl, mThreshError)); } else if (mFractionOutOfBunchColl > mThreshWarning) { result.set(Quality::Medium); result.addReason(FlagReasonFactory::Unknown(), - Form("Fraction of out of bunch collisions (%.2e) is above \"Warning\" threshold (%.2e)", + Form("Fraction of out of bunch collisions (%.2e) is above \"Warning\" threshold (%.2e)", mFractionOutOfBunchColl, mThreshWarning)); } else { result.set(Quality::Good); - } + } } } @@ -138,7 +135,7 @@ void OutOfBunchCollFeeModulesCheck::beautify(std::shared_ptr mo, histogram->GetListOfFunctions()->Add(msg); msg->SetName(Form("%s_msg", mo->GetName())); msg->Clear(); - if(checkResult.isWorseThan(Quality::Good)) { + if (checkResult.isWorseThan(Quality::Good)) { msg->AddText(checkResult.getReasons()[0].second.c_str()); } int color = kWhite; diff --git a/Modules/FIT/FV0/src/PostProcTask.cxx b/Modules/FIT/FV0/src/PostProcTask.cxx index cae65d8434..4cac9759a0 100644 --- a/Modules/FIT/FV0/src/PostProcTask.cxx +++ b/Modules/FIT/FV0/src/PostProcTask.cxx @@ -99,7 +99,6 @@ void PostProcTask::configure(const boost::property_tree::ptree& config) mTimestampSourceLhcIf = "trigger"; ILOG(Debug, Support) << "configure() : using default timestampSourceLhcIf = \"" << mTimestampSourceLhcIf << "\"" << ENDM; } - } void PostProcTask::initialize(Trigger, framework::ServiceRegistryRef services) @@ -200,7 +199,7 @@ void PostProcTask::initialize(Trigger, framework::ServiceRegistryRef services) ILOG(Error, Support) << "Incorrect LUT entry: chID " << strChID << " | " << moduleName << ENDM; } } else if (moduleType != "TCM") { - ILOG(Error, Support) << "Non-TCM module w/o numerical chID: chID " << strChID << " | " << moduleName<< ENDM; + ILOG(Error, Support) << "Non-TCM module w/o numerical chID: chID " << strChID << " | " << moduleName << ENDM; } else if (moduleType == "TCM") { uint8_t mTCMhash = mMapFEE2hash[moduleName]; } @@ -208,9 +207,9 @@ void PostProcTask::initialize(Trigger, framework::ServiceRegistryRef services) mHistBcPatternFee = std::make_unique("bcPatternForFeeModules", "BC pattern", sBCperOrbit, 0, sBCperOrbit, 13, 0, 13); mHistBcFeeOutOfBunchColl = std::make_unique("OutOfBunchColl_BCvsFeeModules", "BC vs FEE Modules for out-of-bunch collisions;BC;FEE Modules", sBCperOrbit, 0, sBCperOrbit, mMapFEE2hash.size(), 0, mMapFEE2hash.size()); - + for (const auto& entry : mMapFEE2hash) { - // ILOG(Warning, Support) << "============= mMapFEE2hash.second + 1: " << entry.second + 1 + // ILOG(Warning, Support) << "============= mMapFEE2hash.second + 1: " << entry.second + 1 // << " mMapFEE2hash.first.c_str(): " << entry.first.c_str() << ENDM; mHistBcPatternFee->GetYaxis()->SetBinLabel(entry.second + 1, entry.first.c_str()); @@ -425,7 +424,6 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) } } - // Download bcPattern std::map metadata; std::map headers; @@ -444,12 +442,10 @@ void PostProcTask::update(Trigger t, framework::ServiceRegistryRef) } auto bcPattern = lhcIf->getBunchFilling(); - // Download histogram BCvsFEEmodules from database auto moBcVsFeeModules = mDatabase->retrieveMO(mPathDigitQcTask, "BCvsFEEmodules", t.timestamp, t.activity); auto hBcVsFeeModules = moBcVsFeeModules ? dynamic_cast(moBcVsFeeModules->getObject()) : nullptr; - if (!hBcVsFeeModules) { ILOG(Error, Support) << "MO \"BCvsFEEmodules\" NOT retrieved!!!" << ENDM; return; From cbe4d1afe14089bddd13f695ad99a91c1efecae3 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Sun, 4 Jun 2023 20:00:58 +0200 Subject: [PATCH 32/33] Provide fix for unreadable metadata key. --- Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx b/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx index 17f2dddd99..c3fafe3416 100644 --- a/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx +++ b/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx @@ -83,16 +83,20 @@ Quality OutOfBunchCollFeeModulesCheck::check(std::mapGetNbinsY(); binY++) { auto outOfBcCollisions = histogram->Integral(1, sBCperOrbit, binY, binY); - auto fraction = outOfBcCollisions / allCollPerFeeModule[binY]; + float fraction = 0; + if(allCollPerFeeModule[binY]){ + fraction = outOfBcCollisions / allCollPerFeeModule[binY]; + } if (fraction > mFractionOutOfBunchColl) { mFractionOutOfBunchColl = fraction; From 635db6d11b7153d51fedf778d6d9d90098a155c6 Mon Sep 17 00:00:00 2001 From: DawidSkora Date: Sun, 4 Jun 2023 20:06:11 +0200 Subject: [PATCH 33/33] Fix clang-format error --- Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx b/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx index c3fafe3416..6da41c79cb 100644 --- a/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx +++ b/Modules/FIT/FV0/src/OutOfBunchCollFeeModulesCheck.cxx @@ -94,7 +94,7 @@ Quality OutOfBunchCollFeeModulesCheck::check(std::mapGetNbinsY(); binY++) { auto outOfBcCollisions = histogram->Integral(1, sBCperOrbit, binY, binY); float fraction = 0; - if(allCollPerFeeModule[binY]){ + if (allCollPerFeeModule[binY]) { fraction = outOfBcCollisions / allCollPerFeeModule[binY]; }