Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] TPC QC: adds occupancy histogram in Cluster task #2124

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Modules/TPC/include/TPC/ClusterVisualizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class T>
void makeRadialProfile(const o2::tpc::CalDet<T>& calDet, TCanvas* canv);

template <class T>
void fillRadialHisto(TH2D& h2D, const o2::tpc::CalDet<T>& calDet, const o2::tpc::Side side);

private:
o2::ccdb::CcdbApi mCdbApi;
std::string mHost;
Expand Down
1 change: 1 addition & 0 deletions Modules/TPC/include/TPC/Clusters.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class Clusters /*final*/ : public TaskInterface // todo add back the "final" whe
std::vector<std::unique_ptr<TCanvas>> mSigmaTimeCanvasVec{}; ///< summary canvases of the SigmaTime object
std::vector<std::unique_ptr<TCanvas>> mSigmaPadCanvasVec{}; ///< summary canvases of the SigmaPad object
std::vector<std::unique_ptr<TCanvas>> mTimeBinCanvasVec{}; ///< summary canvases of the TimeBin object
std::vector<std::unique_ptr<TCanvas>> mOccupancyCanvasVec{}; ///< summary canvases of the Occupancy object

void processClusterNative(o2::framework::InputRecord& inputs);
void processKrClusters(o2::framework::InputRecord& inputs);
Expand Down
7 changes: 4 additions & 3 deletions Modules/TPC/run/tpcQCClusterVisualizer.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,19 @@
{ "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": [
"once"
],
"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"
Expand Down
71 changes: 69 additions & 2 deletions Modules/TPC/run/tpcQCClusters_direct.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"className": "o2::quality_control_modules::tpc::Clusters",
"moduleName": "QcTPC",
"detectorName": "TPC",
"cycleDurationSeconds": "10",
"cycleDurationSeconds": "60",
"resetAfterCycles": "5",
"dataSource": {
"type": "direct",
Expand All @@ -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"
Expand All @@ -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": [
Expand Down
2 changes: 1 addition & 1 deletion Modules/TPC/run/tpcQCSACs.json
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
2 changes: 1 addition & 1 deletion Modules/TPC/run/tpcQCTracks_sampled.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"name": "not_applicable"
},
"Activity": {
"number": "592390"
"number": "303000"
},
"monitoring": {
"url": "infologger:///debug?qc"
Expand Down
126 changes: 99 additions & 27 deletions Modules/TPC/src/ClusterVisualizer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand All @@ -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<std::unique_ptr<TCanvas>>());
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<ClustersData>(mPath,
Expand All @@ -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)
Expand All @@ -214,4 +222,68 @@ void ClusterVisualizer::finalize(Trigger t, framework::ServiceRegistryRef)
}
}

template <class T> void ClusterVisualizer::makeRadialProfile(const o2::tpc::CalDet<T>& 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 <class T>
void ClusterVisualizer::fillRadialHisto(TH2D& h2D, const o2::tpc::CalDet<T>& 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
Loading
Loading