diff --git a/Modules/TPC/CMakeLists.txt b/Modules/TPC/CMakeLists.txt index 2d61786523..022560b3e8 100644 --- a/Modules/TPC/CMakeLists.txt +++ b/Modules/TPC/CMakeLists.txt @@ -10,6 +10,7 @@ target_sources(O2QcTPC PRIVATE src/PID.cxx src/ROCReductor.cxx src/Clusters.cxx src/CalDetPublisher.cxx + src/PadCalibrationCheck2D.cxx src/Utility.cxx src/RawDigits.cxx) @@ -36,6 +37,7 @@ add_root_dictionary(O2QcTPC include/TPC/ROCReductor.h include/TPC/Clusters.h include/TPC/CalDetPublisher.h + include/TPC/PadCalibrationCheck2D.h include/TPC/Utility.h include/TPC/RawDigits.h LINKDEF include/TPC/LinkDef.h @@ -94,6 +96,7 @@ install(FILES run/tpcQCPID_sampled.json run/tpcQCClusters_direct.json run/tpcQCTrackingFromExternal_direct.json run/tpcQCCalDetPublisher.json + run/tpcQCPadCalibrationCheck2D.json run/tpcQCRawDigits_direct.json run/tpcQCTasks_multinode.json DESTINATION etc) diff --git a/Modules/TPC/include/TPC/LinkDef.h b/Modules/TPC/include/TPC/LinkDef.h index 723f6990a9..a1a8bee145 100644 --- a/Modules/TPC/include/TPC/LinkDef.h +++ b/Modules/TPC/include/TPC/LinkDef.h @@ -3,17 +3,18 @@ #pragma link off all classes; #pragma link off all functions; -#pragma link C++ class o2::quality_control_modules::tpc::PID+; +#pragma link C++ class o2::quality_control_modules::tpc::PID + ; #pragma link C++ class o2::quality_control_modules::tpc::Tracking + ; -#pragma link C++ class o2::quality_control_modules::tpc::Tracks+; -#pragma link C++ class o2::quality_control_modules::tpc::PIDClusterCheck+; -#pragma link C++ class o2::quality_control_modules::tpc::TrackClusterCheck+; -#pragma link C++ class o2::quality_control_modules::tpc::ROCReductor+; -#pragma link C++ class o2::quality_control_modules::tpc::Clusters+; -#pragma link C++ class o2::quality_control_modules::tpc::CalDetPublisher+; -#pragma link C++ class o2::quality_control_modules::tpc::RawDigits+; +#pragma link C++ class o2::quality_control_modules::tpc::Tracks + ; +#pragma link C++ class o2::quality_control_modules::tpc::PIDClusterCheck + ; +#pragma link C++ class o2::quality_control_modules::tpc::TrackClusterCheck + ; +#pragma link C++ class o2::quality_control_modules::tpc::ROCReductor + ; +#pragma link C++ class o2::quality_control_modules::tpc::Clusters + ; +#pragma link C++ class o2::quality_control_modules::tpc::CalDetPublisher + ; +#pragma link C++ class o2::quality_control_modules::tpc::PadCalibrationCheck2D + ; +#pragma link C++ class o2::quality_control_modules::tpc::RawDigits + ; -#pragma link C++ function o2::quality_control_modules::tpc::addAndPublish+; -#pragma link C++ function o2::quality_control_modules::tpc::toVector+; -#pragma link C++ function o2::quality_control_modules::tpc::clusterHandler+; +#pragma link C++ function o2::quality_control_modules::tpc::addAndPublish + ; +#pragma link C++ function o2::quality_control_modules::tpc::toVector + ; +#pragma link C++ function o2::quality_control_modules::tpc::clusterHandler + ; #endif diff --git a/Modules/TPC/include/TPC/PadCalibrationCheck2D.h b/Modules/TPC/include/TPC/PadCalibrationCheck2D.h new file mode 100644 index 0000000000..87cc4cf8e4 --- /dev/null +++ b/Modules/TPC/include/TPC/PadCalibrationCheck2D.h @@ -0,0 +1,50 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// 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 PadCalibrationCheck2D.h +/// \author Laura Serksnyte +/// + +#ifndef QC_MODULE_TPC_PadCalibrationCheck2D_H +#define QC_MODULE_TPC_PadCalibrationCheck2D_H + +#include "QualityControl/CheckInterface.h" + +namespace o2::quality_control_modules::tpc +{ + +/// \brief Check whether the cluster number for a track is smaller than 40 or 20 in Track task. +/// +/// \author Laura Serksnyte +class PadCalibrationCheck2D : public o2::quality_control::checker::CheckInterface +{ + + public: + /// Default constructor + PadCalibrationCheck2D() = default; + /// Destructor + ~PadCalibrationCheck2D() override = default; + + // Override interface + void configure(std::string name) override; + Quality check(std::map>* moMap) override; + void beautify(std::shared_ptr mo, Quality checkResult = Quality::Null) override; + std::string getAcceptedType() override; + + private: + ClassDefOverride(PadCalibrationCheck2D, 1); + std::vector badSectorsName; + std::vector badSectorsQuality; +}; + +} // namespace o2::quality_control_modules::tpc + +#endif // QC_MODULE_TPC_PadCalibrationCheck2D_H \ No newline at end of file diff --git a/Modules/TPC/run/tpcQCPadCalibrationCheck2D.json b/Modules/TPC/run/tpcQCPadCalibrationCheck2D.json new file mode 100644 index 0000000000..d8b612d955 --- /dev/null +++ b/Modules/TPC/run/tpcQCPadCalibrationCheck2D.json @@ -0,0 +1,123 @@ +{ + "qc": { + "config": { + "database": { + "implementation": "CCDB", + "host": "ccdb-test.cern.ch:8080", + "username": "not_applicable", + "password": "not_applicable", + "name": "not_applicable" + }, + "Activity": { + "number": "42", + "type": "2" + }, + "monitoring": { + "url": "infologger:///debug?qc" + }, + "consul": { + "url": "http://consul-test.cern.ch:8500" + }, + "conditionDB": { + "url": "ccdb-test.cern.ch:8080" + } + }, + "postprocessing": { + "Calibration": { + "active": "true", + "className": "o2::quality_control_modules::tpc::CalDetPublisher", + "moduleName": "QcTPC", + "detectorName": "TPC", + "outputCalPadMaps_comment" : [ "CalDet objects that are stored in std::unordered_map> need to go here.", + "This needs to be the last part of the CCDB path, e.g. Pulser or CE." ], + "outputCalPadMaps": [ + "CE", + "Pulser" + ], + "outputCalPads_comment" : [ "CalDet objects that are stored as plain o2::tpc::CalDet objects need to go here.", + "This needs to be the last part of the CCDB path, e.g. Pedestal or Noise." ], + "outputCalPads": [ + "Pedestal", + "Noise" + ], + "timestamps_comment": [ "Put the timestamp of the corresponding file you want to look for in the timestamps array.", + "You can either put a timestamp for every object or leave the array empty to take the latest file from the CCDB.", + "An empty array to get the the latest version will be the main use case.", + "The array is mapped to the output objects sequentially", + "If you want to pick the latest file in the CCDB manually, you can use -1." + ], + "timestamps": [ + ], + "lookupMetaData_comment": [ "With this array you can filter your search via meta data.", + "The array is mapped sequentially to the output objects.", + "If you leave only one entry in the array this is used for all objects in outputCalPadMaps and outputCalPads.", + "If you want no meta data simply remove 'keys' and 'values' completely and leave only {}", + "Every entry above (outputCalPads.size() + outputCalPadMaps.size()) is ignored.", + "The keys and values that are set by default are only there to serve as an example." + ], + "lookupMetaData": [ + { + } + ], + "storeMetaData_comment": "For how-to, see 'lookupMetaData_comment'.", + "storeMetaData": [ + { + }, + { + "keys": [ "key1", "key2" ], + "values": [ "value1", "value2" ] + }, + { + "keys": [ "key" ], + "values": [ "value" ] + }, + { + } + ], + "histogramRanges_comment" : [ "nBins", "min", "max" ], + "histogramRanges": [ + { "Pedestals" : [ "240", "0", "120" ] }, + { "Noise" : [ "200", "0", "2" ] }, + { "PulserQtot" : [ "600", "0", "300" ] }, + { "PulserT0" : [ "100", "239", "240" ] }, + { "PulserWidth" : [ "100", "0", "1" ] }, + { "CEQtot" : [ "600", "0", "300" ] }, + { "CET0" : [ "200", "400", "500" ] }, + { "CEWidth" : [ "100", "0", "1" ] } + ], + "checkZSCalibration": { + "check": "false", + "initRefCalibTimestamp": "-1", + "initRefPedestalTimestamp": "-1", + "initRefNoiseTimestamp": "-1" + }, + "initTrigger": [ + "once" + ], + "updateTrigger_comment": "To trigger on a specific file being updated, use e.g. 'newobject:ccdb:TPC/Calib/Noise'", + "updateTrigger": [ + "once" + ], + "stopTrigger_comment": [ "To keep the task running until it is stopped manually set the trigger on the update of a non-existing object, e.g. 'newobject:ccdb:TPC/ThisDoesNotExist'", + "There will be a end of run trigger implemented so the above workaround can be abandoned later." ], + "stopTrigger": [ + "once" + ] + } + }, + "checks":{ + "PadCalibrationCheck2D": { + "active" : "true", + "className" : "o2::quality_control_modules::tpc::PadCalibrationCheck2D", + "moduleName" : "QcTPC", + "policy" : "OnEachSeparately", + "detectorName" : "TPC", + "dataSource" : [{ + "type" : "PostProcessing", + "name" : "Calibration", + "MOs" : ["c_ROCs_Pedestal_2D"] + }] + } + } + } +} diff --git a/Modules/TPC/src/PadCalibrationCheck2D.cxx b/Modules/TPC/src/PadCalibrationCheck2D.cxx new file mode 100644 index 0000000000..023ffdee4d --- /dev/null +++ b/Modules/TPC/src/PadCalibrationCheck2D.cxx @@ -0,0 +1,155 @@ +// Copyright CERN and copyright holders of ALICE O2. This software is +// distributed under the terms of the GNU General Public License v3 (GPL +// Version 3), copied verbatim in the file "COPYING". +// +// See http://alice-o2.web.cern.ch/license for full licensing information. +// +// 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 PadCalibrationCheck2D.cxx +/// \author Laura Serksnyte +/// + +#include "TPC/PadCalibrationCheck2D.h" +#include "QualityControl/MonitorObject.h" +#include "QualityControl/Quality.h" + +#include +// ROOT +#include +#include +#include +#include +#include + +namespace o2::quality_control_modules::tpc +{ + +void PadCalibrationCheck2D::configure(std::string) {} +Quality PadCalibrationCheck2D::check(std::map>* moMap) +{ + + auto mo = moMap->begin()->second; + Quality result = Quality::Null; + if (mo->getName() == "c_ROCs_Pedestal_2D") { + result = Quality::Good; + auto* canv = (TCanvas*)mo->getObject(); + // Check all histograms in the canvas + for (int tpads = 1; tpads <= 72; tpads++) { + const auto padName = fmt::format("c_ROCs_Pedestal_2D_{:d}", tpads); + const auto histName = fmt::format("h_Pedestals_ROC_{:02d}", tpads - 1); + TPad* pad = (TPad*)canv->GetListOfPrimitives()->FindObject(padName.data()); + if (!pad) { + badSectorsName.push_back("notitle"); + badSectorsQuality.push_back(Quality::Null); + continue; + } + TH2F* h = (TH2F*)pad->GetListOfPrimitives()->FindObject(histName.data()); + if (!h) { + badSectorsName.push_back("notitle"); + badSectorsQuality.push_back(Quality::Null); + continue; + } + const std::string titleh = h->GetTitle(); + + //check if we are dealing with IROC or OROC + int totalPads = 0; + if (titleh.find("IROC") != std::string::npos) { + totalPads = 5280; + } else if (titleh.find("OROC") != std::string::npos) { + totalPads = 9280; + } else { + return Quality::Null; + } + + const int NX = h->GetNbinsX(); + const int NY = h->GetNbinsY(); + + // Check how many of the pads are non zero + int sum = 0; + for (int i = 1; i <= NX; i++) { + for (int j = 1; j <= NY; j++) { + int val = h->GetBinContent(i, j); + if (val > 0) { + sum += 1; + } + } + } + + // Check how many are off + const float mediumLimit = 0.7; + const float badLimit = 0.4; + if (sum > badLimit * totalPads && sum < mediumLimit * totalPads) { + if (result == Quality::Good) { + result = Quality::Medium; + } + badSectorsName.push_back(titleh); + badSectorsQuality.push_back(Quality::Medium); + } else if (sum < badLimit * totalPads) { + result = Quality::Bad; + badSectorsName.push_back(titleh); + badSectorsQuality.push_back(Quality::Bad); + } else { + badSectorsName.push_back(titleh); + badSectorsQuality.push_back(Quality::Good); + } + } + } + return result; +} + +std::string PadCalibrationCheck2D::getAcceptedType() { return "TCanvas"; } + +void PadCalibrationCheck2D::beautify(std::shared_ptr mo, Quality) +{ + + auto* canv = (TCanvas*)mo->getObject(); + // Loop over all histograms and beautify accordingly to specific quality object + for (int tpads = 1; tpads <= 72; tpads++) { + const auto padName = fmt::format("c_ROCs_Pedestal_2D_{:d}", tpads); + const auto histName = fmt::format("h_Pedestals_ROC_{:02d}", tpads - 1); + TPad* pad = (TPad*)canv->GetListOfPrimitives()->FindObject(padName.data()); + if (!pad) { + continue; + } + pad->cd(); + TH2F* h = (TH2F*)pad->GetListOfPrimitives()->FindObject(histName.data()); + if (!h) { + continue; + } + const std::string titleh = h->GetTitle(); + auto it = std::find(badSectorsName.begin(), badSectorsName.end(), titleh); + if (it == badSectorsName.end()) { + continue; + } + TPaveText* msg = new TPaveText(0.1, 0.9, 0.9, 0.95, "NDC"); + msg->SetBorderSize(1); + const int index = std::distance(badSectorsName.begin(), it); + Quality qualitySpecial = badSectorsQuality[index]; + msg->SetName(Form("%s_msg", mo->GetName())); + + if (qualitySpecial == Quality::Good) { + msg->Clear(); + msg->AddText("Good"); + msg->SetFillColor(kGreen); + } else if (qualitySpecial == Quality::Bad) { + msg->Clear(); + msg->AddText("Bad"); + msg->SetFillColor(kRed); + } else if (qualitySpecial == Quality::Medium) { + msg->Clear(); + msg->AddText("Medium"); + msg->SetFillColor(kOrange); + } else if (qualitySpecial == Quality::Null) { + h->SetFillColor(0); + } + h->SetLineColor(kBlack); + + msg->Draw("same"); + } +} + +} // namespace o2::quality_control_modules::tpc \ No newline at end of file