diff --git a/Modules/TRD/CMakeLists.txt b/Modules/TRD/CMakeLists.txt index 2963fa8418..622fca1de4 100644 --- a/Modules/TRD/CMakeLists.txt +++ b/Modules/TRD/CMakeLists.txt @@ -3,7 +3,7 @@ add_library(O2QcTRD) target_sources(O2QcTRD PRIVATE src/TrackletCountCheck.cxx src/PulsePositionCheck.cxx src/TrackingTask.cxx src/PulseHeightTrackMatch.cxx src/TrackletsCheck.cxx src/TrackletsTask.cxx src/PulseHeightCheck.cxx src/RawData.cxx src/DigitsTask.cxx - src/TRDTrending.cxx src/TrendingTaskConfigTRD.cxx src/PulseHeightPostProcessing.cxx) + src/TRDTrending.cxx src/TrendingTaskConfigTRD.cxx src/PulseHeightPostProcessing.cxx src/TRDHelpers.cxx) target_include_directories( O2QcTRD @@ -26,6 +26,7 @@ add_root_dictionary(O2QcTRD include/TRD/PulseHeightTrackMatch.h include/TRD/TrackletsCheck.h include/TRD/TrackletsTask.h + include/TRD/TRDHelpers.h include/TRD/PulseHeightCheck.h include/TRD/RawData.h include/TRD/PulseHeightPostProcessing.h diff --git a/Modules/TRD/include/TRD/DigitsTask.h b/Modules/TRD/include/TRD/DigitsTask.h index bcfa961fb2..82c3d19c80 100644 --- a/Modules/TRD/include/TRD/DigitsTask.h +++ b/Modules/TRD/include/TRD/DigitsTask.h @@ -47,10 +47,7 @@ class DigitsTask final : public TaskInterface void endOfActivity(const Activity& activity) override; void reset() override; void buildHistograms(); - void drawTrdLayersGrid(TH2F* hist); void drawLinesOnPulseHeight(TH1F* h); - void fillLinesOnHistsPerLayer(int iLayer); - void drawHashOnLayers(int layer, int hcid, int col, int rowstart, int rowend); void buildChamberIgnoreBP(); private: @@ -87,7 +84,7 @@ class DigitsTask final : public TaskInterface // CCDB objects const o2::trd::NoiseStatusMCM* mNoiseMap = nullptr; - const o2::trd::HalfChamberStatusQC* mChamberStatus = nullptr; + const std::array* mChamberStatus = nullptr; }; } // namespace o2::quality_control_modules::trd diff --git a/Modules/TRD/include/TRD/LinkDef.h b/Modules/TRD/include/TRD/LinkDef.h index 82af389678..b94e1343c5 100644 --- a/Modules/TRD/include/TRD/LinkDef.h +++ b/Modules/TRD/include/TRD/LinkDef.h @@ -8,6 +8,7 @@ #pragma link C++ class o2::quality_control_modules::trd::RawData + ; #pragma link C++ class o2::quality_control_modules::trd::PulseHeightCheck + ; #pragma link C++ class o2::quality_control_modules::trd::TrackletsTask + ; +#pragma link C++ class o2::quality_control_modules::trd::TRDHelpers + ; #pragma link C++ class o2::quality_control_modules::trd::TrackletsCheck + ; #pragma link C++ class o2::quality_control::postprocessing::TRDTrending + ; #pragma link C++ class o2::quality_control::postprocessing::PulseHeightPostProcessing + ; diff --git a/Modules/TRD/include/TRD/TRDHelpers.h b/Modules/TRD/include/TRD/TRDHelpers.h new file mode 100644 index 0000000000..1ae8af7861 --- /dev/null +++ b/Modules/TRD/include/TRD/TRDHelpers.h @@ -0,0 +1,49 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file TRDHelpers.h +/// + +#ifndef QC_MODULE_TRD_TRDHELPER_H +#define QC_MODULE_TRD_TRDHELPER_H + +#include "QualityControl/TaskInterface.h" +#include "TRDQC/StatusHelper.h" + +class TH2F; + +using namespace o2::quality_control::core; + +namespace o2::quality_control_modules::trd +{ + +class TRDHelpers +{ + public: + TRDHelpers() = default; + ~TRDHelpers() = default; + + static void addChamberGridToHistogram(std::shared_ptr histogram, int unitsPerSection); + static void drawChamberStatusOnHistograms(const std::array* ptrChamber, std::shared_ptr chamberMap, std::array, o2::trd::constants::NLAYER> ptrLayersArray, int unitsPerSection); + static void drawHalfChamberMask(int halfChamberStatus, std::pair xCoords, std::pair yCoords, std::shared_ptr histogram); + static bool isHalfChamberMasked(int halfChamberId, const std::array* ptrChamber); + + private: + // Chamber status values definitions, used for masking + static const int mConfiguredChamberStatus = 3; + static const int mEmptyChamberStatus = 0; + static const int mErrorChamberStatus = 99; +}; + +} // namespace o2::quality_control_modules::trd + +#endif diff --git a/Modules/TRD/include/TRD/TrackletsTask.h b/Modules/TRD/include/TRD/TrackletsTask.h index 0be9c81acf..eb8c65db46 100644 --- a/Modules/TRD/include/TRD/TrackletsTask.h +++ b/Modules/TRD/include/TRD/TrackletsTask.h @@ -45,31 +45,26 @@ class TrackletsTask final : public TaskInterface void endOfActivity(const Activity& activity) override; void reset() override; void buildHistograms(); - void drawLinesMCM(TH2F* histo); - void drawTrdLayersGrid(TH2F* hist); - void buildTrackletLayers(); - void drawHashedOnHistsPerLayer(int layer); //, int hcid, int rowstart, int rowend); - void drawHashOnLayers(int layer, int hcid, int rowstart, int rowend); private: // settings bool mRemoveNoise{ false }; // histograms - std::array mTrackletQ; - TH1F* mTrackletSlope = nullptr; - TH1F* mTrackletHCID = nullptr; - TH1F* mTrackletPosition = nullptr; - TH1F* mTrackletsPerEvent = nullptr; - TH1F* mTrackletsPerEventPP = nullptr; - TH1F* mTrackletsPerEventPbPb = nullptr; - TH2F* mTrackletsPerHC2D = nullptr; - TH1F* mTrackletsPerTimeFrame = nullptr; - TH1F* mTriggersPerTimeFrame = nullptr; - std::array mLayers; + std::array, 3> mTrackletQ; + std::shared_ptr mTrackletSlope = nullptr; + std::shared_ptr mTrackletHCID = nullptr; + std::shared_ptr mTrackletPosition = nullptr; + std::shared_ptr mTrackletsPerEvent = nullptr; + std::shared_ptr mTrackletsPerEventPP = nullptr; + std::shared_ptr mTrackletsPerEventPbPb = nullptr; + std::shared_ptr mTrackletsPerHC2D = nullptr; + std::shared_ptr mTrackletsPerTimeFrame = nullptr; + std::shared_ptr mTriggersPerTimeFrame = nullptr; + std::array, o2::trd::constants::NLAYER> mLayers; // data to pull from CCDB const o2::trd::NoiseStatusMCM* mNoiseMap = nullptr; - const o2::trd::HalfChamberStatusQC* mChamberStatus = nullptr; + const std::array* mChamberStatus = nullptr; }; } // namespace o2::quality_control_modules::trd diff --git a/Modules/TRD/src/DigitsTask.cxx b/Modules/TRD/src/DigitsTask.cxx index 2d1e9542c2..16ac5e2208 100644 --- a/Modules/TRD/src/DigitsTask.cxx +++ b/Modules/TRD/src/DigitsTask.cxx @@ -19,6 +19,8 @@ #include #include +#include "TRD/DigitsTask.h" +#include "TRD/TRDHelpers.h" #include "DataFormatsTRD/Constants.h" #include "DataFormatsTRD/Digit.h" #include "DataFormatsTRD/HelperMethods.h" @@ -27,7 +29,6 @@ #include "QualityControl/TaskInterface.h" #include "QualityControl/QcInfoLogger.h" #include "Common/Utils.h" -#include "TRD/DigitsTask.h" #include #include #include @@ -41,143 +42,21 @@ using Helper = o2::trd::HelperMethods; namespace o2::quality_control_modules::trd { -void DigitsTask::buildChamberIgnoreBP() -{ - mChambersToIgnoreBP.reset(); - // Vector of string to save tokens - std::vector tokens; - // stringstream class check1 - std::stringstream check1(mChambersToIgnore); - std::string intermediate; - // Tokenizing w.r.t. space ',' - while (getline(check1, intermediate, ',')) { - tokens.push_back(intermediate); - } - // Printing the token vector - for (auto& token : tokens) { - // token now holds something like 16_3_0 - std::vector parts; - std::stringstream indexcheck(token); - std::string tokenpart; - // Tokenizing w.r.t. space ',' - while (getline(indexcheck, tokenpart, '_')) { - parts.push_back(tokenpart); - } - // now flip the bit related to the sector:stack:layer stored in parts. - int sector = std::stoi(parts[0]); - int stack = std::stoi(parts[1]); - int layer = std::stoi(parts[2]); - mChambersToIgnoreBP.set(Helper::getDetector(sector, stack, layer)); - } -} - -void DigitsTask::drawTrdLayersGrid(TH2F* hist) -{ - TLine* line; - for (int i = 0; i < 5; ++i) { - switch (i) { - case 0: - line = new TLine(15.5, 0, 15.5, 2592); - hist->GetListOfFunctions()->Add(line); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - break; - case 1: - line = new TLine(31.5, 0, 31.5, 2592); - hist->GetListOfFunctions()->Add(line); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - break; - case 2: - line = new TLine(43.5, 0, 43.5, 2592); - hist->GetListOfFunctions()->Add(line); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - break; - case 3: - line = new TLine(59.5, 0, 59.5, 2592); - hist->GetListOfFunctions()->Add(line); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - break; - } - } - for (int iSec = 1; iSec < 18; ++iSec) { - float yPos = iSec * 144 - 0.5; - line = new TLine(0, yPos, 76, yPos); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - hist->GetListOfFunctions()->Add(line); - } - - ILOG(Info, Support) << "Layer Grid redrawn in check for : " << hist->GetName() << ENDM; - ILOG(Info, Support) << "Layer Grid redrawn in hist has function count of : " << hist->GetListOfFunctions()->GetSize() << ENDM; -} - -void DigitsTask::drawLinesOnPulseHeight(TH1F* h) +void DigitsTask::initialize(o2::framework::InitContext& /*ctx*/) { - TLine* lmin = new TLine(mPulseHeightPeakRegion.first, 0, mPulseHeightPeakRegion.first, 1e9); - TLine* lmax = new TLine(mPulseHeightPeakRegion.second, 0, mPulseHeightPeakRegion.second, 1e9); - lmin->SetLineStyle(2); - lmax->SetLineStyle(2); - lmin->SetLineColor(kRed); - lmax->SetLineColor(kRed); - h->GetListOfFunctions()->Add(lmin); - h->GetListOfFunctions()->Add(lmax); -} + ILOG(Debug, Devel) << "initialize TRDDigitQcTask" << ENDM; // QcInfoLogger is used. FairMQ logs will go to there as well. -void DigitsTask::drawHashOnLayers(int layer, int hcid, int col, int rowstart, int rowend) -{ - // instead of using overlays, draw a simple box in red with a cross on it. - std::pair topright, bottomleft; // coordinates of box - TLine* boxlines[8]; - int det = hcid / 2; - int side = hcid % 2; - int sec = hcid / 60; - bottomleft.first = rowstart - 0.5; - bottomleft.second = (sec * 2 + side) * 72; - topright.first = rowend - 0.5; - topright.second = (sec * 2 + side) * 72 + 72; - - // LOG(info) << "Box for layer : " << layer << " hcid : " << hcid << ": " << bottomleft.first << ":" << bottomleft.second << "(" << bottomleft.second/144 << ") -- " << topright.first << ":" << topright.second << "(" << topright.second/144 << ")"; - boxlines[0] = new TLine(bottomleft.first, bottomleft.second, topright.first, bottomleft.second); // bottom - boxlines[1] = new TLine(bottomleft.first, topright.second, topright.first, topright.second); // top - boxlines[2] = new TLine(bottomleft.first, bottomleft.second, bottomleft.first, topright.second); // left - boxlines[3] = new TLine(topright.first, bottomleft.second, topright.first, topright.second); // right - boxlines[4] = new TLine(bottomleft.first, topright.second - (topright.second - bottomleft.second) / 2, topright.first, topright.second - (topright.second - bottomleft.second) / 2); // horizontal middle - boxlines[5] = new TLine(topright.first, bottomleft.second, bottomleft.first, topright.second); // backslash - boxlines[6] = new TLine(bottomleft.first, bottomleft.second, topright.first, topright.second); // forwardslash - boxlines[7] = new TLine(bottomleft.first + (topright.first - bottomleft.first) / 2, bottomleft.second, bottomleft.first + (topright.first - bottomleft.first) / 2, topright.second); // vertical middle - for (int line = 0; line < 8; ++line) { - boxlines[line]->SetLineColor(kBlack); - mLayers[layer]->GetListOfFunctions()->Add(boxlines[line]); - } -} + // this is how to get access to custom parameters defined in the config file at qc.tasks..taskParameters + mDoClusterize = getFromConfig(mCustomParameters, "doClusterize", false); + mPulseHeightPeakRegion.first = getFromConfig(mCustomParameters, "peakRegionStart", 0.f); + mPulseHeightPeakRegion.second = getFromConfig(mCustomParameters, "peakRegionEnd", 5.f); + mPulseHeightThreshold = getFromConfig(mCustomParameters, "phThreshold", 400u); + mChambersToIgnore = getFromConfig(mCustomParameters, "ignoreChambers", "16_3_0"); + mClsCutoff = getFromConfig(mCustomParameters, "clsCutoff", 1000); + mAdcBaseline = getFromConfig(mCustomParameters, "adcBaseline", 10); -void DigitsTask::fillLinesOnHistsPerLayer(int iLayer) -{ - std::bitset hciddone; - hciddone.reset(); - if (mChamberStatus == nullptr) { - // protect for if the chamber status is not pulled from the ccdb for what ever reason. - ILOG(Info, Support) << "No half chamber status object to be able to fill the mask" << ENDM; - } else { - for (int iSec = 0; iSec < 18; ++iSec) { - for (int iStack = 0; iStack < 5; ++iStack) { - int rowMax = (iStack == 2) ? 12 : 16; - for (int side = 0; side < 2; ++side) { - int det = iSec * 30 + iStack * 6 + iLayer; - int hcid = (side == 0) ? det * 2 : det * 2 + 1; - int rowstart = iStack < 3 ? iStack * 16 : 44 + (iStack - 3) * 16; // pad row within whole sector - int rowend = iStack < 3 ? rowMax + iStack * 16 : rowMax + 44 + (iStack - 3) * 16; // pad row within whole sector - if (mChamberStatus->isMasked(hcid) && (!hciddone.test(hcid))) { - drawHashOnLayers(iLayer, hcid, 0, rowstart, rowend); - hciddone.set(hcid); // to avoid mutliple instances of adding lines - } - } - } - } - } + buildChamberIgnoreBP(); + buildHistograms(); } void DigitsTask::buildHistograms() @@ -246,44 +125,19 @@ void DigitsTask::buildHistograms() getObjectsManager()->startPublishing(mPulseHeight2DperSM[iSec].get()); } + // Build digits layers + int unitsPerSection = NCOLUMN; for (int iLayer = 0; iLayer < NLAYER; ++iLayer) { - mLayers[iLayer].reset(new TH2F(Form("DigitsPerLayer_%i", iLayer), Form("Digit count per pad in layer %i;glb pad row;glb pad col", iLayer), 76, -0.5, 75.5, 2592, -0.5, 2591.5)); + mLayers[iLayer].reset(new TH2F(Form("DigitsPerLayer_%i", iLayer), Form("Digit count per pad in layer %i;glb pad row;glb pad col", iLayer), + 76, -0.5, 75.5, unitsPerSection * NSECTOR, -0.5, unitsPerSection * NSECTOR - 0.5)); mLayers[iLayer]->SetStats(0); - drawTrdLayersGrid(mLayers[iLayer].get()); - fillLinesOnHistsPerLayer(iLayer); + TRDHelpers::addChamberGridToHistogram(mLayers[iLayer], unitsPerSection); getObjectsManager()->startPublishing(mLayers[iLayer].get()); getObjectsManager()->setDefaultDrawOptions(mLayers[iLayer]->GetName(), "COLZ"); getObjectsManager()->setDisplayHint(mLayers[iLayer].get(), "logz"); } } -void DigitsTask::initialize(o2::framework::InitContext& /*ctx*/) -{ - ILOG(Debug, Devel) << "initialize TRDDigitQcTask" << ENDM; // QcInfoLogger is used. FairMQ logs will go to there as well. - - // this is how to get access to custom parameters defined in the config file at qc.tasks..taskParameters - mDoClusterize = getFromConfig(mCustomParameters, "doClusterize", false); - mPulseHeightPeakRegion.first = getFromConfig(mCustomParameters, "peakRegionStart", 0.f); - mPulseHeightPeakRegion.second = getFromConfig(mCustomParameters, "peakRegionEnd", 5.f); - mPulseHeightThreshold = getFromConfig(mCustomParameters, "phThreshold", 400u); - mChambersToIgnore = getFromConfig(mCustomParameters, "ignoreChambers", "16_3_0"); - mClsCutoff = getFromConfig(mCustomParameters, "clsCutoff", 1000); - mAdcBaseline = getFromConfig(mCustomParameters, "adcBaseline", 10); - - buildChamberIgnoreBP(); - buildHistograms(); -} - -void DigitsTask::startOfActivity(const Activity& /*activity*/) -{ - ILOG(Debug, Devel) << "startOfActivity" << ENDM; -} // set stats/stacs - -void DigitsTask::startOfCycle() -{ - ILOG(Debug, Devel) << "startOfCycle" << ENDM; -} - void DigitsTask::monitorData(o2::framework::ProcessingContext& ctx) { // Load CCDB objects (needs to be done only once) @@ -291,11 +145,20 @@ void DigitsTask::monitorData(o2::framework::ProcessingContext& ctx) auto ptr = ctx.inputs().get("noiseMap"); mNoiseMap = ptr.get(); } + if (!mChamberStatus) { - auto ptr = ctx.inputs().get("chamberStatus"); + auto ptr = ctx.inputs().get*>("fedChamberStatus"); mChamberStatus = ptr.get(); + // LB: only draw in plots if it is first instance, e.g. null ptr to non null ptr + if (mChamberStatus) { + // LB: no half chamber distribution map for Digits, pass it as null pointer + TRDHelpers::drawChamberStatusOnHistograms(mChamberStatus, nullptr, mLayers, NCOLUMN); + } else { + ILOG(Info, Support) << "Failed to retrieve ChamberStatus, so it will not show on plots" << ENDM; + } } + // fill histograms auto digits = ctx.inputs().get>("digits"); auto triggerrecords = ctx.inputs().get>("triggers"); for (auto& trigger : triggerrecords) { @@ -418,6 +281,58 @@ void DigitsTask::monitorData(o2::framework::ProcessingContext& ctx) } // loop over triggers } +void DigitsTask::drawLinesOnPulseHeight(TH1F* h) +{ + TLine* lmin = new TLine(mPulseHeightPeakRegion.first, 0, mPulseHeightPeakRegion.first, 1e9); + TLine* lmax = new TLine(mPulseHeightPeakRegion.second, 0, mPulseHeightPeakRegion.second, 1e9); + lmin->SetLineStyle(2); + lmax->SetLineStyle(2); + lmin->SetLineColor(kRed); + lmax->SetLineColor(kRed); + h->GetListOfFunctions()->Add(lmin); + h->GetListOfFunctions()->Add(lmax); +} + +void DigitsTask::buildChamberIgnoreBP() +{ + mChambersToIgnoreBP.reset(); + // Vector of string to save tokens + std::vector tokens; + // stringstream class check1 + std::stringstream check1(mChambersToIgnore); + std::string intermediate; + // Tokenizing w.r.t. space ',' + while (getline(check1, intermediate, ',')) { + tokens.push_back(intermediate); + } + // Printing the token vector + for (auto& token : tokens) { + // token now holds something like 16_3_0 + std::vector parts; + std::stringstream indexcheck(token); + std::string tokenpart; + // Tokenizing w.r.t. space ',' + while (getline(indexcheck, tokenpart, '_')) { + parts.push_back(tokenpart); + } + // now flip the bit related to the sector:stack:layer stored in parts. + int sector = std::stoi(parts[0]); + int stack = std::stoi(parts[1]); + int layer = std::stoi(parts[2]); + mChambersToIgnoreBP.set(Helper::getDetector(sector, stack, layer)); + } +} + +void DigitsTask::startOfActivity(const Activity& /*activity*/) +{ + ILOG(Debug, Devel) << "startOfActivity" << ENDM; +} // set stats/stacs + +void DigitsTask::startOfCycle() +{ + ILOG(Debug, Devel) << "startOfCycle" << ENDM; +} + void DigitsTask::endOfCycle() { ILOG(Debug, Devel) << "endOfCycle" << ENDM; diff --git a/Modules/TRD/src/TRDHelpers.cxx b/Modules/TRD/src/TRDHelpers.cxx new file mode 100644 index 0000000000..565c2371e2 --- /dev/null +++ b/Modules/TRD/src/TRDHelpers.cxx @@ -0,0 +1,117 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file TRDHelpers.cxx +/// + +#include +#include +#include +#include "TRD/TRDHelpers.h" +#include "DataFormatsTRD/HelperMethods.h" + +using namespace o2::trd::constants; +using Helper = o2::trd::HelperMethods; + +namespace o2::quality_control_modules::trd +{ +bool TRDHelpers::isHalfChamberMasked(int hcid, const std::array* ptrChamber) +{ + // LB: defined as array in case other chamber status values should be set as not masked + int GoodStatus[] = { mConfiguredChamberStatus }; + int hcstat = (*ptrChamber)[hcid / 2]; + return (std::find(std::begin(GoodStatus), std::end(GoodStatus), hcstat) == std::end(GoodStatus)); +} + +void TRDHelpers::drawChamberStatusOnHistograms(const std::array* ptrChamber, std::shared_ptr chamberMap, std::array, NLAYER> ptrLayersArray, int unitsPerSection) +{ + std::pair x, y; + for (int hcid = 0; hcid < MAXCHAMBER * 2; ++hcid) { + if (isHalfChamberMasked(hcid, ptrChamber)) { + // Chamber properties + int hcstat = (*ptrChamber)[hcid / 2]; + int side = hcid % 2; + int sec = hcid / NHCPERSEC; + int stack = Helper::getStack(hcid / 2); + int layer = Helper::getLayer(hcid / 2); + + if (chamberMap) { + // Coordinates for half chamber distribution + int stackLayer = stack * NLAYER + layer; + int sectorSide = sec * 2 + side; + x.first = sectorSide; + x.second = sectorSide + 1; + y.first = stackLayer; + y.second = stackLayer + 1; + + drawHalfChamberMask(hcstat, x, y, chamberMap); + } + + if (ptrLayersArray[layer]) { + // Chamber stack of type C0 or C1 condition + int rowstart = FIRSTROW[stack]; + int rowend = stack == 2 ? rowstart + NROWC0 : rowstart + NROWC1; + + // Coordinates for layer map + x.first = rowstart - 0.5; + x.second = rowend - 0.5; + y.first = (sec * 2 + side) * (unitsPerSection / 2) - 0.5; + y.second = y.first + (unitsPerSection / 2); + + drawHalfChamberMask(hcstat, x, y, ptrLayersArray[layer]); + } + } + } +} + +void TRDHelpers::drawHalfChamberMask(int hcstat, std::pair xCoord, std::pair yCoord, std::shared_ptr histogram) +{ + TLine* box[6]; + box[0] = new TLine(xCoord.first, yCoord.first, xCoord.second, yCoord.first); // bottom + box[1] = new TLine(xCoord.first, yCoord.second, xCoord.second, yCoord.second); // top + box[2] = new TLine(xCoord.first, yCoord.first, xCoord.first, yCoord.second); // left + box[3] = new TLine(xCoord.second, yCoord.first, xCoord.second, yCoord.second); // right + box[4] = new TLine(xCoord.first, yCoord.second, xCoord.second, yCoord.first); // backslash + box[5] = new TLine(xCoord.first, yCoord.first, xCoord.second, yCoord.second); // forwardslash + + for (int line = 0; line < 6; ++line) { + if (hcstat == mEmptyChamberStatus) { + box[line]->SetLineColor(kGray + 1); + } else if (hcstat == mErrorChamberStatus) { + box[line]->SetLineColor(kRed); + } else { + box[line]->SetLineColor(kBlack); + } + box[line]->SetLineWidth(2); + histogram->GetListOfFunctions()->Add(box[line]); + } +} + +void TRDHelpers::addChamberGridToHistogram(std::shared_ptr histogram, int unitsPerSection) +{ + TLine* line; + for (int iStack = 0; iStack < NSTACK; ++iStack) { + line = new TLine(FIRSTROW[iStack] - 0.5, 0, FIRSTROW[iStack] - 0.5, NSECTOR * unitsPerSection - 0.5); + line->SetLineStyle(kDashed); + line->SetLineColor(kBlack); + histogram->GetListOfFunctions()->Add(line); + } + + for (int iSec = 1; iSec < NSECTOR; ++iSec) { + float yPos = iSec * unitsPerSection - 0.5; + line = new TLine(-0.5, yPos, FIRSTROW[NSTACK - 1] + NROWC1 - 0.5, yPos); + line->SetLineStyle(kDashed); + line->SetLineColor(kBlack); + histogram->GetListOfFunctions()->Add(line); + } +} +} // namespace o2::quality_control_modules::trd diff --git a/Modules/TRD/src/TrackletsTask.cxx b/Modules/TRD/src/TrackletsTask.cxx index fa4b49b9bf..018ad7f0d3 100644 --- a/Modules/TRD/src/TrackletsTask.cxx +++ b/Modules/TRD/src/TrackletsTask.cxx @@ -25,6 +25,7 @@ #include "QualityControl/QcInfoLogger.h" #include "Common/Utils.h" #include "TRD/TrackletsTask.h" +#include "TRD/TRDHelpers.h" #include "TRDQC/StatusHelper.h" #include #include @@ -41,63 +42,11 @@ using Helper = o2::trd::HelperMethods; namespace o2::quality_control_modules::trd { -void TrackletsTask::drawLinesMCM(TH2F* histo) -{ - TLine* l; - Int_t nPos[NSTACK - 1] = { 16, 32, 44, 60 }; - - for (Int_t iStack = 0; iStack < NSTACK - 1; ++iStack) { - l = new TLine(nPos[iStack] - 0.5, -0.5, nPos[iStack] - 0.5, 47.5); - l->SetLineStyle(2); - histo->GetListOfFunctions()->Add(l); - } - - for (Int_t iLayer = 0; iLayer < NLAYER; ++iLayer) { - l = new TLine(-0.5, iLayer * 8 - 0.5, 75.5, iLayer * 8 - 0.5); - l = new TLine(0.5, iLayer * 8 - 0.5, 75.5, iLayer * 8 - 0.5); - l->SetLineStyle(2); - histo->GetListOfFunctions()->Add(l); - } -} - -void TrackletsTask::drawTrdLayersGrid(TH2F* hist) +void TrackletsTask::initialize(o2::framework::InitContext& /*ctx*/) { - TLine* line; - for (int i = 0; i < 5; ++i) { - switch (i) { - case 0: - line = new TLine(15.5, 0, 15.5, 143.5); - hist->GetListOfFunctions()->Add(line); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - break; - case 1: - line = new TLine(31.5, 0, 31.5, 143.5); - hist->GetListOfFunctions()->Add(line); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - break; - case 2: - line = new TLine(43.5, 0, 43.5, 143.5); - hist->GetListOfFunctions()->Add(line); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - break; - case 3: - line = new TLine(59.5, 0, 59.5, 143.5); - hist->GetListOfFunctions()->Add(line); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - break; - } - } - for (int iSec = 1; iSec < 18; ++iSec) { - float yPos = iSec * 8 - 0.5; - line = new TLine(-0.5, yPos, 75.5, yPos); - line->SetLineStyle(kDashed); - line->SetLineColor(kBlack); - hist->GetListOfFunctions()->Add(line); - } + ILOG(Debug, Devel) << "initialize TrackletsTask" << ENDM; + mRemoveNoise = getFromConfig(mCustomParameters, "removeNoise", false); + buildHistograms(); } void TrackletsTask::buildHistograms() @@ -110,26 +59,26 @@ void TrackletsTask::buildHistograms() for (int iBin = 0; iBin <= nLogBins; ++iBin) { xBins[iBin] = TMath::Power(10, xBinLogMin + iBin * logBinWidth); } - mTrackletSlope = new TH1F("trackletslope", "Tracklet inclination in natural units;pads per time bin;counts", 100, -0.15, 0.15); - getObjectsManager()->startPublishing(mTrackletSlope); + mTrackletSlope.reset(new TH1F("trackletslope", "Tracklet inclination in natural units;pads per time bin;counts", 100, -0.15, 0.15)); + getObjectsManager()->startPublishing(mTrackletSlope.get()); - mTrackletHCID = new TH1F("tracklethcid", "Tracklet distribution over Halfchambers;HalfChamber ID;counts", 1080, -0.5, 1079.5); - getObjectsManager()->startPublishing(mTrackletHCID); + mTrackletHCID.reset(new TH1F("tracklethcid", "Tracklet distribution over Halfchambers;HalfChamber ID;counts", 1080, -0.5, 1079.5)); + getObjectsManager()->startPublishing(mTrackletHCID.get()); - mTrackletPosition = new TH1F("trackletpos", "Tracklet position relative to MCM center;number of pads;counts", 200, -30, 30); - getObjectsManager()->startPublishing(mTrackletPosition); + mTrackletPosition.reset(new TH1F("trackletpos", "Tracklet position relative to MCM center;number of pads;counts", 200, -30, 30)); + getObjectsManager()->startPublishing(mTrackletPosition.get()); - mTrackletsPerEvent = new TH1F("trackletsperevent", "Number of Tracklets per event;Tracklets in Event;Counts", nLogBins, xBins); - getObjectsManager()->startPublishing(mTrackletsPerEvent); + mTrackletsPerEvent.reset(new TH1F("trackletsperevent", "Number of Tracklets per event;Tracklets in Event;Counts", nLogBins, xBins)); + getObjectsManager()->startPublishing(mTrackletsPerEvent.get()); getObjectsManager()->setDefaultDrawOptions(mTrackletsPerEvent->GetName(), "logx"); - mTrackletsPerEventPP = new TH1F("trackletspereventPP", "Number of Tracklets per event;Tracklets in Event;Counts", 1000, 0, 5000); - getObjectsManager()->startPublishing(mTrackletsPerEventPP); + mTrackletsPerEventPP.reset(new TH1F("trackletspereventPP", "Number of Tracklets per event;Tracklets in Event;Counts", 1000, 0, 5000)); + getObjectsManager()->startPublishing(mTrackletsPerEventPP.get()); - mTrackletsPerEventPbPb = new TH1F("trackletspereventPbPb", "Number of Tracklets per event;Tracklets in Event;Counts", 1000, 0, 100000); - getObjectsManager()->startPublishing(mTrackletsPerEventPbPb); + mTrackletsPerEventPbPb.reset(new TH1F("trackletspereventPbPb", "Number of Tracklets per event;Tracklets in Event;Counts", 1000, 0, 100000)); + getObjectsManager()->startPublishing(mTrackletsPerEventPbPb.get()); - mTrackletsPerHC2D = new TH2F("trackletsperHC2D", "Tracklets distribution in half-chambers;Sector_Side;Stack_Side", 36, 0, 36, 30, 0, 30); + mTrackletsPerHC2D.reset(new TH2F("trackletsperHC2D", "Tracklets distribution in half-chambers;Sector_Side;Stack_Side", 36, 0, 36, 30, 0, 30)); mTrackletsPerHC2D->SetStats(0); mTrackletsPerHC2D->GetXaxis()->SetTitle("Sector_Side"); mTrackletsPerHC2D->GetXaxis()->CenterTitle(kTRUE); @@ -142,6 +91,7 @@ void TrackletsTask::buildHistograms() mTrackletsPerHC2D->GetYaxis()->SetBinLabel(pos, label.c_str()); } } + for (int sm = 0; sm < NSECTOR; ++sm) { for (int side = 0; side < 2; ++side) { std::string label = fmt::format("{0}_{1}", sm, side == 0 ? "A" : "B"); @@ -150,137 +100,36 @@ void TrackletsTask::buildHistograms() } } - // Mask known inactive halfchambers in the active chamber map - TLine* line[6]; - std::pair x, y; - for (int iHC = 0; iHC < NCHAMBER * 2; ++iHC) { - if (mChamberStatus != nullptr) { - if (mChamberStatus->isMasked(iHC)) { - int stackLayer = Helper::getStack(iHC / 2) * NLAYER + Helper::getLayer(iHC / 2); - int sectorSide = (iHC / NHCPERSEC) * 2 + (iHC % 2); - x.first = sectorSide; - x.second = sectorSide + 1; - y.first = stackLayer; - y.second = stackLayer + 1; - - line[0] = new TLine(x.first, y.first, x.second, y.second); - line[1] = new TLine(x.second, y.first, x.first, y.second); - line[2] = new TLine(x.first, y.first, x.second, y.first); - line[3] = new TLine(x.first, y.second, x.second, y.second); - line[4] = new TLine(x.first, y.first, x.first, y.second); - line[5] = new TLine(x.second, y.first, x.second, y.second); - for (int i = 0; i < 6; ++i) { - line[i]->SetLineColor(kBlack); - mTrackletsPerHC2D->GetListOfFunctions()->Add(line[i]); - } - } - } - } - getObjectsManager()->startPublishing(mTrackletsPerHC2D); - getObjectsManager()->setDefaultDrawOptions("trackletsperHC2D", "COLZ"); + getObjectsManager()->startPublishing(mTrackletsPerHC2D.get()); + getObjectsManager()->setDefaultDrawOptions(mTrackletsPerHC2D->GetName(), "COLZ"); getObjectsManager()->setDisplayHint(mTrackletsPerHC2D->GetName(), "logz"); for (int chargeWindow = 0; chargeWindow < 3; ++chargeWindow) { - mTrackletQ[chargeWindow] = new TH1F(Form("TrackletQ%i", chargeWindow), Form("Tracklet Q%i;charge (a.u.);counts", chargeWindow), 256, -0.5, 255.5); - getObjectsManager()->startPublishing(mTrackletQ[chargeWindow]); + mTrackletQ[chargeWindow].reset(new TH1F(Form("TrackletQ%i", chargeWindow), Form("Tracklet Q%i;charge (a.u.);counts", chargeWindow), 256, -0.5, 255.5)); + getObjectsManager()->startPublishing(mTrackletQ[chargeWindow].get()); getObjectsManager()->setDefaultDrawOptions(mTrackletQ[chargeWindow]->GetName(), "logy"); } - mTrackletsPerTimeFrame = new TH1F("trackletspertimeframe", "Number of Tracklets per timeframe;Tracklets in TimeFrame;Counts", nLogBins, xBins); - getObjectsManager()->startPublishing(mTrackletsPerTimeFrame); + mTrackletsPerTimeFrame.reset(new TH1F("trackletspertimeframe", "Number of Tracklets per timeframe;Tracklets in TimeFrame;Counts", nLogBins, xBins)); + getObjectsManager()->startPublishing(mTrackletsPerTimeFrame.get()); getObjectsManager()->setDefaultDrawOptions(mTrackletsPerTimeFrame->GetName(), "logx"); - mTriggersPerTimeFrame = new TH1F("triggerspertimeframe", "Number of Triggers per timeframe;Triggers in TimeFrame;Counts", 1000, 0, 1000); - getObjectsManager()->startPublishing(mTriggersPerTimeFrame); - - buildTrackletLayers(); -} - -void TrackletsTask::drawHashOnLayers(int layer, int hcid, int rowstart, int rowend) -{ - // instead of using overlays, draw a simple box in red with a cross on it. - - std::pair topright, bottomleft; // coordinates of box - TLine* boxlines[9]; - int det = hcid / 2; - int side = hcid % 2; - int sec = hcid / 60; - bottomleft.first = rowstart - 0.5; - bottomleft.second = (sec * 2 + side) * 4 - 0.5; - topright.first = rowend - 0.5; - topright.second = (sec * 2 + side) * 4 + 4 - 0.5; + mTriggersPerTimeFrame.reset(new TH1F("triggerspertimeframe", "Number of Triggers per timeframe;Triggers in TimeFrame;Counts", 1000, 0, 1000)); + getObjectsManager()->startPublishing(mTriggersPerTimeFrame.get()); - // LOG(info) << "Box for layer : " << layer << " hcid : " << hcid << ": " << bottomleft.first << ":" << bottomleft.second << " -- " << topright.first << ":" << topright.second; - boxlines[0] = new TLine(bottomleft.first, bottomleft.second, topright.first, bottomleft.second); // bottom - boxlines[1] = new TLine(bottomleft.first, topright.second, topright.first, topright.second); // top - boxlines[2] = new TLine(bottomleft.first, bottomleft.second, bottomleft.first, topright.second); // left - boxlines[3] = new TLine(topright.first, bottomleft.second, topright.first, topright.second); // right - boxlines[4] = new TLine(bottomleft.first, topright.second - (topright.second - bottomleft.second) / 2, topright.first, topright.second - (topright.second - bottomleft.second) / 2); // horizontal middle - boxlines[5] = new TLine(topright.first, bottomleft.second, bottomleft.first, topright.second); // backslash - boxlines[6] = new TLine(bottomleft.first, bottomleft.second, topright.first, topright.second); // forwardslash - boxlines[7] = new TLine(bottomleft.first + (topright.first - bottomleft.first) / 2, bottomleft.second, bottomleft.first + (topright.first - bottomleft.first) / 2, topright.second); // vertical middle - boxlines[8] = new TLine(bottomleft.first, bottomleft.second + (topright.second - bottomleft.second) / 2, topright.first, bottomleft.second + (topright.second - bottomleft.second) / 2); // bottom - for (int line = 0; line < 9; ++line) { - boxlines[line]->SetLineColor(kBlack); - mLayers[layer]->GetListOfFunctions()->Add(boxlines[line]); - } -} - -void TrackletsTask::buildTrackletLayers() -{ + // Build tracklet layers + int unitsPerSection = NCOLUMN / NSECTOR; for (int iLayer = 0; iLayer < NLAYER; ++iLayer) { - mLayers[iLayer] = new TH2F(Form("TrackletsPerMCM_Layer%i", iLayer), Form("Tracklet count per MCM in layer %i;glb pad row;glb MCM col", iLayer), 76, -0.5, 75.5, 144, -0.5, 143.5); + mLayers[iLayer].reset(new TH2F(Form("TrackletsPerMCM_Layer%i", iLayer), Form("Tracklet count per MCM in layer %i;glb pad row;glb MCM col", iLayer), + 76, -0.5, 75.5, NCOLUMN, -0.5, NCOLUMN - 0.5)); mLayers[iLayer]->SetStats(0); - drawTrdLayersGrid(mLayers[iLayer]); - drawHashedOnHistsPerLayer(iLayer); - getObjectsManager()->startPublishing(mLayers[iLayer]); + TRDHelpers::addChamberGridToHistogram(mLayers[iLayer], unitsPerSection); + getObjectsManager()->startPublishing(mLayers[iLayer].get()); getObjectsManager()->setDefaultDrawOptions(mLayers[iLayer]->GetName(), "COLZ"); - getObjectsManager()->setDisplayHint(mLayers[iLayer], "logz"); - } -} - -void TrackletsTask::drawHashedOnHistsPerLayer(int iLayer) -{ - std::bitset<1080> hciddone; - hciddone.reset(); - if (mChamberStatus != nullptr) { - for (int iSec = 0; iSec < 18; ++iSec) { - for (int iStack = 0; iStack < 5; ++iStack) { - int rowMax = (iStack == 2) ? 12 : 16; - for (int side = 0; side < 2; ++side) { - int det = iSec * 30 + iStack * 6 + iLayer; - int hcid = (side == 0) ? det * 2 : det * 2 + 1; - int rowstart = iStack < 3 ? iStack * 16 : 44 + (iStack - 3) * 16; // pad row within whole sector - int rowend = iStack < 3 ? rowMax + iStack * 16 : rowMax + 44 + (iStack - 3) * 16; // pad row within whole sector - if (mChamberStatus->isMasked(hcid) && (!hciddone.test(hcid))) { - drawHashOnLayers(iLayer, hcid, rowstart, rowend); - hciddone.set(hcid); - } - } - } - } - } else { - ILOG(Info, Support) << " Failed to retrieve ChamberStatus, so it will be blank" << ENDM; + getObjectsManager()->setDisplayHint(mLayers[iLayer].get(), "logz"); } } -void TrackletsTask::initialize(o2::framework::InitContext& /*ctx*/) -{ - ILOG(Debug, Devel) << "initialize TrackletsTask" << ENDM; - mRemoveNoise = getFromConfig(mCustomParameters, "removeNoise", false); - buildHistograms(); -} - -void TrackletsTask::startOfActivity(const Activity& activity) -{ - ILOG(Debug, Devel) << "startOfActivity " << activity.mId << ENDM; -} - -void TrackletsTask::startOfCycle() -{ - ILOG(Debug, Devel) << "startOfCycle" << ENDM; -} - void TrackletsTask::monitorData(o2::framework::ProcessingContext& ctx) { // Load CCDB objects (needs to be done only once) @@ -288,11 +137,19 @@ void TrackletsTask::monitorData(o2::framework::ProcessingContext& ctx) auto ptr = ctx.inputs().get("noiseMap"); mNoiseMap = ptr.get(); } + if (!mChamberStatus) { - auto ptr = ctx.inputs().get("chamberStatus"); + auto ptr = ctx.inputs().get*>("fedChamberStatus"); mChamberStatus = ptr.get(); + // LB: only draw in plots if it is first instance, e.g. null ptr to non null ptr + if (mChamberStatus) { + TRDHelpers::drawChamberStatusOnHistograms(mChamberStatus, mTrackletsPerHC2D, mLayers, NCOLUMN / NSECTOR); + } else { + ILOG(Info, Support) << "Failed to retrieve ChamberStatus, so it will not show on plots" << ENDM; + } } + // Fill histograms auto tracklets = ctx.inputs().get>("tracklets"); auto triggerrecords = ctx.inputs().get>("triggers"); mTrackletsPerTimeFrame->Fill(tracklets.size()); @@ -327,6 +184,16 @@ void TrackletsTask::monitorData(o2::framework::ProcessingContext& ctx) } } +void TrackletsTask::startOfActivity(const Activity& activity) +{ + ILOG(Debug, Devel) << "startOfActivity " << activity.mId << ENDM; +} + +void TrackletsTask::startOfCycle() +{ + ILOG(Debug, Devel) << "startOfCycle" << ENDM; +} + void TrackletsTask::endOfCycle() { ILOG(Debug, Devel) << "endOfCycle" << ENDM; @@ -340,7 +207,6 @@ void TrackletsTask::endOfActivity(const Activity& /*activity*/) void TrackletsTask::reset() { // clean all the monitor objects here - ILOG(Debug, Devel) << "Resetting the histograms" << ENDM; mTrackletSlope->Reset(); mTrackletHCID->Reset();