From e039c1c04c551b900eb5b10a79e98eb75eb7ca99 Mon Sep 17 00:00:00 2001 From: Thomas Klemenz Date: Thu, 26 Jan 2023 09:11:56 +0100 Subject: [PATCH] TPC: add occupancy plot to Cluster task --- Modules/TPC/include/TPC/ClusterVisualizer.h | 6 ++ Modules/TPC/include/TPC/Clusters.h | 1 + Modules/TPC/run/tpcQCClusterVisualizer.json | 7 +- Modules/TPC/run/tpcQCClusters_direct.json | 5 +- Modules/TPC/src/ClusterVisualizer.cxx | 87 ++++++++++++++++++++- Modules/TPC/src/Clusters.cxx | 7 ++ 6 files changed, 106 insertions(+), 7 deletions(-) diff --git a/Modules/TPC/include/TPC/ClusterVisualizer.h b/Modules/TPC/include/TPC/ClusterVisualizer.h index a310d868dd..e17569d464 100644 --- a/Modules/TPC/include/TPC/ClusterVisualizer.h +++ b/Modules/TPC/include/TPC/ClusterVisualizer.h @@ -66,6 +66,12 @@ class ClusterVisualizer final : public quality_control::postprocessing::PostProc /// \param services Interface containing optional interfaces, for example DatabaseInterface void finalize(quality_control::postprocessing::Trigger, framework::ServiceRegistryRef) override; + template + void makeRadialProfile(o2::tpc::CalDet& calDet, TCanvas* canv, int nbinsY, float yMin, float yMax); + + template + void fillRadialHisto(TH2D& h2D, const o2::tpc::CalDet& calDet, const o2::tpc::Side side); + private: o2::ccdb::CcdbApi mCdbApi; std::string mHost; diff --git a/Modules/TPC/include/TPC/Clusters.h b/Modules/TPC/include/TPC/Clusters.h index 38a31637a2..20d80bf69e 100644 --- a/Modules/TPC/include/TPC/Clusters.h +++ b/Modules/TPC/include/TPC/Clusters.h @@ -63,6 +63,7 @@ class Clusters /*final*/ : public TaskInterface // todo add back the "final" whe std::vector> mSigmaTimeCanvasVec{}; ///< summary canvases of the SigmaTime object std::vector> mSigmaPadCanvasVec{}; ///< summary canvases of the SigmaPad object std::vector> mTimeBinCanvasVec{}; ///< summary canvases of the TimeBin object + std::vector> mOccupancyCanvasVec{}; ///< summary canvases of the Occupancy object void processClusterNative(o2::framework::InputRecord& inputs); void processKrClusters(o2::framework::InputRecord& inputs); diff --git a/Modules/TPC/run/tpcQCClusterVisualizer.json b/Modules/TPC/run/tpcQCClusterVisualizer.json index b9d19a0a1b..d51fb1f55f 100644 --- a/Modules/TPC/run/tpcQCClusterVisualizer.json +++ b/Modules/TPC/run/tpcQCClusterVisualizer.json @@ -60,10 +60,11 @@ { "Q_Tot" : [ "600", "0", "600" ] }, { "Sigma_Time" : [ "200", "0", "2" ] }, { "Sigma_Pad" : [ "200", "0", "2" ] }, - { "Time_Bin" : [ "1000", "0", "100000" ] } + { "Time_Bin" : [ "1000", "0", "100000" ] }, + { "Occupancy" : [ "100", "0", "0.001" ] } ], "path_comment": "This is the path of the ClustersData object that shall be visualized.", - "path": "TPC/MO/Clusters/ClusterData", + "path": "qc/TPC/MO/Clusters/ClusterData", "dataType_comment": "This is the switch for 'RawDigits' or 'Clusters' task. Choose 'raw' or 'clusters'.", "dataType": "clusters", "initTrigger": [ @@ -71,7 +72,7 @@ ], "updateTrigger_comment": "To trigger on a specific file being updated, use e.g. 'newobject:qcdb:TPC/Calib/Noise'", "updateTrigger": [ - "newobject:qcdb:TPC/MO/Clusters/ClusterData" + "newobject:ccdb:qc/TPC/MO/Clusters/ClusterData" ], "stopTrigger": [ "userorcontrol" diff --git a/Modules/TPC/run/tpcQCClusters_direct.json b/Modules/TPC/run/tpcQCClusters_direct.json index 2125743bf0..e8444598e2 100644 --- a/Modules/TPC/run/tpcQCClusters_direct.json +++ b/Modules/TPC/run/tpcQCClusters_direct.json @@ -28,7 +28,7 @@ "className": "o2::quality_control_modules::tpc::Clusters", "moduleName": "QcTPC", "detectorName": "TPC", - "cycleDurationSeconds": "10", + "cycleDurationSeconds": "60", "maxNumberCycles": "-1", "resetAfterCycles": "5", "dataSource": { @@ -42,7 +42,8 @@ "QtotNBins": "600", "QtotXMin": "0", "QtotXMax": "600", "SigmaPadNBins": "200", "SigmaPadXMin": "0", "SigmaPadXMax": "2", "SigmaTimeNBins": "200", "SigmaTimeXMin": "0", "SigmaTimeXMax": "2", - "TimeBinNBins": "1000", "TimeBinXMin": "0", "TimeBinXMax": "100000" + "TimeBinNBins": "1000", "TimeBinXMin": "0", "TimeBinXMax": "100000", + "OccupancyNBins": "1000", "OccupancyXMin": "0", "OccupancyXMax": "0.00001" }, "location": "local", "localMachines": [ diff --git a/Modules/TPC/src/ClusterVisualizer.cxx b/Modules/TPC/src/ClusterVisualizer.cxx index ae43f4fc69..f4d09e4983 100644 --- a/Modules/TPC/src/ClusterVisualizer.cxx +++ b/Modules/TPC/src/ClusterVisualizer.cxx @@ -118,14 +118,16 @@ void ClusterVisualizer::configure(std::string name, const boost::property_tree:: "Q_Tot", "Sigma_Pad", "Sigma_Time", - "Time_Bin" + "Time_Bin", + "Occupancy" }; } else if (type == "raw") { mIsClusters = false; mObservables = { "N_RawDigits", "Q_Max", - "Time_Bin" + "Time_Bin", + "Occupancy" }; } else { ILOG(Error, Support) << "No valid data type given. 'dataType' has to be either 'clusters' or 'raw'." << ENDM; @@ -147,12 +149,25 @@ void ClusterVisualizer::initialize(Trigger, framework::ServiceRegistryRef) mStoreMaps.size() > 1 ? mStoreMaps.at(calDetIter) : mStoreMaps.at(0)); calDetIter++; } + if (mIsClusters) { + mCalDetCanvasVec.emplace_back(std::vector>()); + addAndPublish(getObjectsManager(), + mCalDetCanvasVec.back(), + { "c_radial_profile_Occupancy" }, + mStoreMaps.size() > 1 ? mStoreMaps.at(calDetIter) : mStoreMaps.at(0)); + } } void ClusterVisualizer::update(Trigger t, framework::ServiceRegistryRef) { ILOG(Info, Support) << "Trigger type is: " << t.triggerType << ", the timestamp is " << t.timestamp << ENDM; + for (auto& vec : mCalDetCanvasVec) { + for (auto& canvas : vec) { + canvas.get()->Clear(); + } + } + auto calDetIter = 0; auto clusterData = mCdbApi.retrieveFromTFileAny(mPath, @@ -192,6 +207,14 @@ void ClusterVisualizer::update(Trigger t, framework::ServiceRegistryRef) vecPtr = toVector(mCalDetCanvasVec.at(calDetIter)); o2::tpc::painter::makeSummaryCanvases(calDet, int(mRanges[calDet.getName()].at(0)), mRanges[calDet.getName()].at(1), mRanges[calDet.getName()].at(2), false, &vecPtr); calDetIter++; + + calDet = clusters.getOccupancy(); + vecPtr = toVector(mCalDetCanvasVec.at(calDetIter)); + o2::tpc::painter::makeSummaryCanvases(calDet, int(mRanges[calDet.getName()].at(0)), mRanges[calDet.getName()].at(1), mRanges[calDet.getName()].at(2), false, &vecPtr); + calDetIter++; + vecPtr = toVector(mCalDetCanvasVec.at(calDetIter)); + makeRadialProfile(calDet, vecPtr.at(0), int(mRanges[calDet.getName()].at(0)), mRanges[calDet.getName()].at(1), mRanges[calDet.getName()].at(2)); + calDetIter++; } void ClusterVisualizer::finalize(Trigger t, framework::ServiceRegistryRef) @@ -203,4 +226,64 @@ void ClusterVisualizer::finalize(Trigger t, framework::ServiceRegistryRef) } } +template +void ClusterVisualizer::makeRadialProfile(o2::tpc::CalDet& calDet, TCanvas* canv, int nbinsY, float yMin, float yMax) +{ + const std::string_view calName = calDet.getName(); + const auto radialBinning = o2::tpc::painter::getRowBinningCM(); + + auto hAside2D = new TH2D(fmt::format("h_{}_radialProfile_Aside", calName).data(), fmt::format("{}: Radial profile (A-Side)", calName).data(), radialBinning.size() - 1, radialBinning.data(), nbinsY, yMin, yMax); + hAside2D->GetXaxis()->SetTitle("x (cm)"); + hAside2D->GetYaxis()->SetTitle(fmt::format("{}", calName).data()); + hAside2D->SetTitleOffset(1.05, "XY"); + hAside2D->SetTitleSize(0.05, "XY"); + hAside2D->SetStats(0); + + auto hCside2D = new TH2D(fmt::format("h_{}_radialProfile_Cside", calName).data(), fmt::format("{}: Radial profile (C-Side)", calName).data(), radialBinning.size() - 1, radialBinning.data(), nbinsY, yMin, yMax); + hCside2D->GetXaxis()->SetTitle("x (cm)"); + hCside2D->GetYaxis()->SetTitle(fmt::format("{}", calName).data()); + hCside2D->SetTitleOffset(1.05, "XY"); + hCside2D->SetTitleSize(0.05, "XY"); + hCside2D->SetStats(0); + + fillRadialHisto(*hAside2D, calDet, o2::tpc::Side::A); + fillRadialHisto(*hCside2D, calDet, o2::tpc::Side::C); + + canv->Divide(1, 2); + canv->cd(1); + hAside2D->Draw("colz"); + hAside2D->SetStats(0); + hAside2D->ProfileX("profile_ASide", 1, -1, "d,same"); + + canv->cd(2); + hCside2D->Draw("colz"); + hCside2D->ProfileX("profile_CSide", 1, -1, "d,same"); + hAside2D->SetStats(0); + + hAside2D->SetBit(TObject::kCanDelete); + hCside2D->SetBit(TObject::kCanDelete); +} + +template +void ClusterVisualizer::fillRadialHisto(TH2D& h2D, const o2::tpc::CalDet& calDet, const o2::tpc::Side side) +{ + const o2::tpc::Mapper& mapper = o2::tpc::Mapper::instance(); + + for (o2::tpc::ROC roc; !roc.looped(); ++roc) { + if (roc.side() != side) { + continue; + } + const int nrows = mapper.getNumberOfRowsROC(roc); + for (int irow = 0; irow < nrows; ++irow) { + const int npads = mapper.getNumberOfPadsInRowROC(roc, irow); + const int globalRow = irow + (roc >= o2::tpc::Mapper::getNumberOfIROCs()) * o2::tpc::Mapper::getNumberOfRowsInIROC(); + for (int ipad = 0; ipad < npads; ++ipad) { + const auto val = calDet.getValue(roc, irow, ipad); + const o2::tpc::LocalPosition2D pos = mapper.getPadCentre(o2::tpc::PadPos(globalRow, ipad)); + h2D.Fill(pos.X(), val); + } + } + } +} + } // namespace o2::quality_control_modules::tpc diff --git a/Modules/TPC/src/Clusters.cxx b/Modules/TPC/src/Clusters.cxx index 8209649e44..2ed669e4f7 100644 --- a/Modules/TPC/src/Clusters.cxx +++ b/Modules/TPC/src/Clusters.cxx @@ -73,6 +73,7 @@ void Clusters::initialize(InitContext& /*ctx*/) mWrapperVector.emplace_back(&mQCClusters.getClusters().getSigmaTime()); mWrapperVector.emplace_back(&mQCClusters.getClusters().getSigmaPad()); mWrapperVector.emplace_back(&mQCClusters.getClusters().getTimeBin()); + mWrapperVector.emplace_back(&mQCClusters.getClusters().getOccupancy()); addAndPublish(getObjectsManager(), mNClustersCanvasVec, { "c_Sides_N_Clusters", "c_ROCs_N_Clusters_1D", "c_ROCs_N_Clusters_2D" }); addAndPublish(getObjectsManager(), mQMaxCanvasVec, { "c_Sides_Q_Max", "c_ROCs_Q_Max_1D", "c_ROCs_Q_Max_2D" }); @@ -80,6 +81,7 @@ void Clusters::initialize(InitContext& /*ctx*/) addAndPublish(getObjectsManager(), mSigmaTimeCanvasVec, { "c_Sides_Sigma_Time", "c_ROCs_Sigma_Time_1D", "c_ROCs_Sigma_Time_2D" }); addAndPublish(getObjectsManager(), mSigmaPadCanvasVec, { "c_Sides_Sigma_Pad", "c_ROCs_Sigma_Pad_1D", "c_ROCs_Sigma_Pad_2D" }); addAndPublish(getObjectsManager(), mTimeBinCanvasVec, { "c_Sides_Time_Bin", "c_ROCs_Time_Bin_1D", "c_ROCs_Time_Bin_2D" }); + addAndPublish(getObjectsManager(), mOccupancyCanvasVec, { "c_Sides_Occupancy", "c_ROCs_Occupancy_1D", "c_ROCs_Occupancy_2D" }); for (auto& wrapper : mWrapperVector) { getObjectsManager()->startPublishing(&wrapper); @@ -113,6 +115,7 @@ void Clusters::processClusterNative(InputRecord& inputs) } } } + mQCClusters.getClusters().endTF(); } void Clusters::processKrClusters(InputRecord& inputs) @@ -128,6 +131,7 @@ void Clusters::processKrClusters(InputRecord& inputs) mQCClusters.getClusters().processCluster(cl, Sector(cl.sector), int(cl.meanRow)); } } + mQCClusters.getClusters().endTF(); } void Clusters::monitorData(ProcessingContext& ctx) @@ -146,12 +150,14 @@ void Clusters::monitorData(ProcessingContext& ctx) fillCanvases(mQCClusters.getClusters().getSigmaTime(), mSigmaTimeCanvasVec, mCustomParameters, "SigmaPad"); fillCanvases(mQCClusters.getClusters().getSigmaPad(), mSigmaPadCanvasVec, mCustomParameters, "SigmaTime"); fillCanvases(mQCClusters.getClusters().getTimeBin(), mTimeBinCanvasVec, mCustomParameters, "TimeBin"); + fillCanvases(mQCClusters.getClusters().getTimeBin(), mOccupancyCanvasVec, mCustomParameters, "Occupancy"); } } void Clusters::endOfCycle() { ILOG(Info, Support) << "endOfCycle" << ENDM; + ILOG(Info, Support) << "Processed TFs: " << mQCClusters.getClusters().getProcessedTFs() << ENDM; if (mIsMergeable) { mQCClusters.getClusters().normalize(); @@ -178,6 +184,7 @@ void Clusters::reset() clearCanvases(mSigmaTimeCanvasVec); clearCanvases(mSigmaPadCanvasVec); clearCanvases(mTimeBinCanvasVec); + clearCanvases(mOccupancyCanvasVec); } }