diff --git a/Modules/TPC/include/TPC/ClusterVisualizer.h b/Modules/TPC/include/TPC/ClusterVisualizer.h index 1d08cf4abe..880a0e1f8b 100644 --- a/Modules/TPC/include/TPC/ClusterVisualizer.h +++ b/Modules/TPC/include/TPC/ClusterVisualizer.h @@ -65,6 +65,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(const o2::tpc::CalDet& calDet, TCanvas* canv); + + 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 3c0eb3bb53..f23cd65c76 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 ff6c8cc32e..3d1426d070 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", "resetAfterCycles": "5", "dataSource": { "type": "direct", @@ -41,8 +41,19 @@ "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" }, + "grpGeomRequest" : { + "geomRequest": "None", + "askGRPECS": "false", + "askGRPLHCIF": "false", + "askGRPMagField": "true", + "askMatLUT": "true", + "askTime": "false", + "askOnceAllButField": "true", + "needPropagatorD": "false" + }, "location": "local", "localMachines": [ "localhost" @@ -51,6 +62,62 @@ "remotePort": "32626", "mergingMode": "delta" } + }, + "postprocessing": { + "Clusters": { + "active": "true", + "className": "o2::quality_control_modules::tpc::ClusterVisualizer", + "moduleName": "QcTPC", + "detectorName": "TPC", + "dataSourceURL": "ccdb-test.cern.ch:8080", + "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": [ + { + } + ], + "histogramRanges_comment" : [ "nBins", "min", "max" ], + "histogramRanges": [ + { "N_Clusters" : [ "100", "0", "100" ] }, + { "Q_Max" : [ "200", "0", "200" ] }, + { "Q_Tot" : [ "600", "0", "600" ] }, + { "Sigma_Time" : [ "200", "0", "2" ] }, + { "Sigma_Pad" : [ "200", "0", "2" ] }, + { "Time_Bin" : [ "1000", "0", "100000" ] } + ], + "path_comment": "This is the path of the ClustersData object that shall be visualized.", + "path": "qc/TPC/MO/Clusters/ClusterData", + "dataType_comment": "This is the switch for 'RawDigits' or 'Clusters' task. Choose 'raw' or 'clusters'.", + "dataType": "clusters", + "initTrigger": [ + "userorcontrol" + ], + "updateTrigger_comment": "To trigger on a specific file being updated, use e.g. 'newobject:qcdb:TPC/Calib/Noise'", + "updateTrigger": [ + "newobject:ccdb:qc/TPC/MO/Clusters/ClusterData" + ], + "stopTrigger": [ + "userorcontrol" + ] + } } }, "dataSamplingPolicies": [ diff --git a/Modules/TPC/run/tpcQCSACs.json b/Modules/TPC/run/tpcQCSACs.json index 5074c112e0..1ee020eaca 100644 --- a/Modules/TPC/run/tpcQCSACs.json +++ b/Modules/TPC/run/tpcQCSACs.json @@ -40,7 +40,7 @@ "If you want to pick the latest file in the CCDB manually, you can use -1." ], "timestamps": [ - { "SACZero":"1686390443945" }, + { "SACZero":"-1" }, { "SACOne":"-1" }, { "SACDelta":"-1" }, { "SACFourierCoeffs":"-1" } diff --git a/Modules/TPC/run/tpcQCTracks_sampled.json b/Modules/TPC/run/tpcQCTracks_sampled.json index 4a20c21ea1..9a29db7ede 100644 --- a/Modules/TPC/run/tpcQCTracks_sampled.json +++ b/Modules/TPC/run/tpcQCTracks_sampled.json @@ -9,7 +9,7 @@ "name": "not_applicable" }, "Activity": { - "number": "592390" + "number": "303000" }, "monitoring": { "url": "infologger:///debug?qc" diff --git a/Modules/TPC/src/ClusterVisualizer.cxx b/Modules/TPC/src/ClusterVisualizer.cxx index 89a06455ea..359c9dd697 100644 --- a/Modules/TPC/src/ClusterVisualizer.cxx +++ b/Modules/TPC/src/ClusterVisualizer.cxx @@ -18,6 +18,7 @@ #include "TPCBase/Painter.h" #include "TPCBase/CDBInterface.h" #include "TPCQC/Helpers.h" +#include "TPCBase/CalDet.h" // QC includes #include "QualityControl/QcInfoLogger.h" @@ -120,14 +121,16 @@ void ClusterVisualizer::configure(const boost::property_tree::ptree& config) "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; @@ -153,12 +156,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, @@ -167,38 +183,30 @@ void ClusterVisualizer::update(Trigger t, framework::ServiceRegistryRef) auto& clusters = clusterData->getClusters(); - auto& calDet = clusters.getNClusters(); - auto 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.getQMax(); - 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++; - if (mIsClusters) { - calDet = clusters.getQTot(); - 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++; + ////////////-------------------------check lambda expression--- + auto fillCanvases = [&calDetIter, this](const auto& calDet) { + auto vecPtr = toVector(mCalDetCanvasVec.at(calDetIter++)); + const auto& ranges = mRanges[calDet.getName()]; + o2::tpc::painter::makeSummaryCanvases(calDet, int(ranges.at(0)), ranges.at(1), ranges.at(2), false, &vecPtr); +}; - calDet = clusters.getSigmaPad(); - 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++; + fillCanvases(clusters.getNClusters()); + fillCanvases(clusters.getQMax()); - calDet = clusters.getSigmaTime(); - 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++; + if (mIsClusters) { + fillCanvases(clusters.getQTot()); + fillCanvases(clusters.getSigmaPad()); + fillCanvases(clusters.getSigmaTime()); } - calDet = clusters.getTimeBin(); - 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++; + fillCanvases(clusters.getTimeBin()); + fillCanvases(clusters.getOccupancy()); + + + makeRadialProfile(clusters.getOccupancy(), mCalDetCanvasVec.at(calDetIter++).at(0).get()); } void ClusterVisualizer::finalize(Trigger t, framework::ServiceRegistryRef) @@ -214,4 +222,68 @@ void ClusterVisualizer::finalize(Trigger t, framework::ServiceRegistryRef) } } +template void ClusterVisualizer::makeRadialProfile(const o2::tpc::CalDet& calDet, TCanvas* canv) +{ + const std::string_view calName = calDet.getName(); + const auto& ranges = mRanges[calName.data()]; + + const int nbinsY = int(ranges.at(0)); + const float yMin = ranges.at(1); + const float yMax = ranges.at(2); + 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 fe14ab4f6b..2143d146b7 100644 --- a/Modules/TPC/src/Clusters.cxx +++ b/Modules/TPC/src/Clusters.cxx @@ -20,6 +20,8 @@ #include "DataFormatsTPC/ClusterNative.h" #include "TPCBase/Painter.h" #include "Framework/InputRecordWalker.h" +#include "DataFormatsParameters/GRPECSObject.h" +#include "DetectorsBase/GRPGeomHelper.h" // QC includes #include "QualityControl/QcInfoLogger.h" @@ -73,6 +75,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 +83,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); @@ -123,6 +127,7 @@ void Clusters::processClusterNative(InputRecord& inputs) } } } + mQCClusters.getClusters().endTF(); } void Clusters::processKrClusters(InputRecord& inputs) @@ -138,17 +143,26 @@ void Clusters::processKrClusters(InputRecord& inputs) mQCClusters.getClusters().processCluster(cl, Sector(cl.sector), int(cl.meanRow)); } } + mQCClusters.getClusters().endTF(); } void Clusters::monitorData(ProcessingContext& ctx) { mQCClusters.getClusters().denormalize(); + //get grpECS object here grpecs:GRP/GRPECS + //auto const& grpECS = ctx.inputs().get("grpecs"); + const auto nHBF = o2::base::GRPGeomHelper::instance().getNHBFPerTF(); + std::cout<<" NHBFs = ""<< nHBF" << std::endl; + std::cout<<" NHBFs = "<< nHBF << std::endl; + std::cout<<" NHBFs = ""<< nHBF" << std::endl; + mQCClusters.getClusters().setnHBFperTF(nHBF); processClusterNative(ctx.inputs()); processKrClusters(ctx.inputs()); if (!mIsMergeable) { mQCClusters.getClusters().normalize(); + mQCClusters.getClusters().normalize(); fillCanvases(mQCClusters.getClusters().getNClusters(), mNClustersCanvasVec, mCustomParameters, "NClusters"); fillCanvases(mQCClusters.getClusters().getQMax(), mQMaxCanvasVec, mCustomParameters, "Qmax"); @@ -156,12 +170,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(Debug, Devel) << "endOfCycle" << ENDM; + ILOG(Info, Support) << "endOfCycle" << ENDM; + ILOG(Info, Support) << "Processed TFs: " << mQCClusters.getClusters().getProcessedTFs() << ENDM; if (mIsMergeable) { mQCClusters.getClusters().normalize(); @@ -188,6 +204,7 @@ void Clusters::reset() clearCanvases(mSigmaTimeCanvasVec); clearCanvases(mSigmaPadCanvasVec); clearCanvases(mTimeBinCanvasVec); + clearCanvases(mOccupancyCanvasVec); } }