Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 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
2 changes: 2 additions & 0 deletions Framework/include/QualityControl/TrendingTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ class TrendingTask : public PostProcessingInterface
static void formatTimeXAxis(TH1* background);
static void formatRunNumberXAxis(TH1* background);
static std::string deduceGraphLegendOptions(const TrendingTaskConfig::Graph& graphConfig);
static Color_t resolveColor(int idx);
static void applyStyleToGraph(TGraph* graph, const TrendingTaskConfig::GraphStyle& style);

/// returns true only if all datasources were available to update reductor
bool trendValues(const Trigger& t, repository::DatabaseInterface&);
Expand Down
28 changes: 28 additions & 0 deletions Framework/include/QualityControl/TrendingTaskConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,25 @@ struct TrendingTaskConfig : PostProcessingConfig {
TrendingTaskConfig(std::string name, const boost::property_tree::ptree& config);
~TrendingTaskConfig() = default;

// graph style configuration
// colors as defined by ROOT TColor class:
// https://root.cern/doc/master/classTColor.html
// marker colors and styles are as defined by ROOT TAttMarker class
// https://root.cern/doc/master/classTAttMarker.html
// line styles are as defined by ROOT TAttLine class
// https://root.cern/doc/master/classTAttLine.html
// WARNING: Any parameters in this struct will override colliding parameters in option
struct GraphStyle {
int lineColor = -1;
int lineStyle = -1;
int lineWidth = -1;
int markerColor = -1;
int markerStyle = -1;
float markerSize = -1.f;
int fillColor = -1;
int fillStyle = -1;
};

// this corresponds to one TTree::Draw() call, i.e. one graph or histogram drawing
struct Graph {
std::string name;
Expand All @@ -40,6 +59,14 @@ struct TrendingTaskConfig : PostProcessingConfig {
std::string selection;
std::string option; // the list of possible options are documented in TGraphPainter and THistPainter
std::string errors;
GraphStyle style;
};

// legend configuration
struct LegendConfig {
bool enabled{true};
int nColumns{1};
float x1{0.30f}, y1{0.20f}, x2{0.55f}, y2{0.35f}; // NDC coords
};

// this corresponds to one canvas which can include multiple graphs
Expand All @@ -49,6 +76,7 @@ struct TrendingTaskConfig : PostProcessingConfig {
std::string graphAxisLabel;
std::string graphYRange;
int colorPalette = 0;
LegendConfig legend;
std::vector<Graph> graphs;
};

Expand Down
107 changes: 77 additions & 30 deletions Framework/src/TrendingTask.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,31 @@ void TrendingTask::initializeTrend(o2::quality_control::repository::DatabaseInte
}
}

Color_t TrendingTask::resolveColor(int idx) {
if (idx >= 0) {
return static_cast<Color_t>(idx);
}
return static_cast<Color_t>(-1);
}

void TrendingTask::applyStyleToGraph(TGraph* graph, const TrendingTaskConfig::GraphStyle& style) {
if (!graph) { return; }
const Color_t lineColor = resolveColor(style.lineColor);
const Color_t markerColor = resolveColor(style.markerColor);
const Color_t fillColor = resolveColor(style.fillColor);

if (lineColor >= 0) { graph->SetLineColor(lineColor); }
if (style.lineStyle >= 0) { graph->SetLineStyle(style.lineStyle); }
if (style.lineWidth >= 0) { graph->SetLineWidth(style.lineWidth); }

if (markerColor >= 0) { graph->SetMarkerColor(markerColor); }
if (style.markerStyle >= 0) { graph->SetMarkerStyle(style.markerStyle); }
if (style.markerSize >= 0.f) { graph->SetMarkerSize(style.markerSize); }

if (fillColor >= 0) { graph->SetFillColor(fillColor); }
if (style.fillStyle >= 0) { graph->SetFillStyle(style.fillStyle); }
}

void TrendingTask::initialize(Trigger, framework::ServiceRegistryRef services)
{
// removing leftovers from any previous runs
Expand Down Expand Up @@ -185,7 +210,7 @@ bool TrendingTask::trendValues(const Trigger& t, repository::DatabaseInterface&
}
mMetaData.runNumber = t.activity.mId;
std::snprintf(mMetaData.runNumberStr, MaxRunNumberStringLength + 1, "%d", t.activity.mId);

bool wereAllSourcesInvoked = true;
for (auto& dataSource : mConfig.dataSources) {
if (!reductor_helpers::updateReductor(mReductors[dataSource.name].get(), t, dataSource, qcdb, *this)) {
Expand Down Expand Up @@ -310,19 +335,31 @@ std::string TrendingTask::deduceGraphLegendOptions(const TrendingTaskConfig::Gra
TCanvas* TrendingTask::drawPlot(const TrendingTaskConfig::Plot& plotConfig)
{
auto* c = new TCanvas();
auto* legend = new TLegend(0.3, 0.2);

// Legend (NDC coordinates if enabled in config)
TLegend* legend = nullptr;
if (plotConfig.legend.enabled) {
legend = new TLegend(plotConfig.legend.x1, plotConfig.legend.y1,
plotConfig.legend.x2, plotConfig.legend.y2,
/*header=*/nullptr, /*option=*/"NDC");
if (plotConfig.legend.nColumns > 0) {
legend->SetNColumns(plotConfig.legend.nColumns);
}
} else {
legend = new TLegend(0.3, 0.2);
}
legend->SetBorderSize(0);
legend->SetFillStyle(0);
legend->SetTextSize(0.03);
legend->SetMargin(0.15);

// Keep palette behavior unless user forces explicit colors via per-graph style
if (plotConfig.colorPalette != 0) {
// this will work just once until we bump ROOT to a version which contains this commit:
// https://github.com/root-project/root/commit/0acdbd5be80494cec98ff60ba9a73cfe70a9a57a
// and enable the commented out line
// perhaps JSROOT >7.7.1 will allow us to retain the palette as well.
gStyle->SetPalette(plotConfig.colorPalette);
// This makes ROOT store the selected palette for each generated plot.
// TColor::DefinedColors(1); // TODO enable when available
} else {
// we set the default palette
gStyle->SetPalette();
gStyle->SetPalette(); // default
}

// regardless whether we draw a graph or a histogram, a histogram is always used by TTree::Draw to draw axes and title
Expand All @@ -337,6 +374,7 @@ TCanvas* TrendingTask::drawPlot(const TrendingTaskConfig::Plot& plotConfig)
// having "SAME" at the first TTree::Draw() call will not work, we have to add it only in subsequent Draw calls
std::string option = firstGraphInPlot ? graphConfig.option : "SAME " + graphConfig.option;

// Draw main series
mTrend->Draw(graphConfig.varexp.c_str(), graphConfig.selection.c_str(), option.c_str());

// For graphs, we allow to draw errors if they are specified.
Expand All @@ -346,22 +384,33 @@ TCanvas* TrendingTask::drawPlot(const TrendingTaskConfig::Plot& plotConfig)
ILOG(Error, Support) << "Non empty graphErrors seen for the plotConfig '" << plotConfig.name << "', which is not a graphConfig, ignoring." << ENDM;
} else {
// We generate some 4-D points, where 2 dimensions represent graph points and 2 others are the error bars
std::string varexpWithErrors(graphConfig.varexp + ":" + graphConfig.errors);
mTrend->Draw(varexpWithErrors.c_str(), graphConfig.selection.c_str(), "goff");
graphErrors = new TGraphErrors(mTrend->GetSelectedRows(), mTrend->GetVal(1), mTrend->GetVal(0),
mTrend->GetVal(2), mTrend->GetVal(3));
graphErrors->SetName((graphConfig.name + "_errors").c_str());
graphErrors->SetTitle((graphConfig.title + " errors").c_str());
// We draw on the same plotConfig as the main graphConfig, but only error bars
graphErrors->Draw("SAME E");
std::string varexpWithErrors(graphConfig.varexp + ":" + graphConfig.errors);
mTrend->Draw(varexpWithErrors.c_str(), graphConfig.selection.c_str(), "goff");
graphErrors = new TGraphErrors(mTrend->GetSelectedRows(), mTrend->GetVal(1), mTrend->GetVal(0),
mTrend->GetVal(2), mTrend->GetVal(3));
graphErrors->SetName((graphConfig.name + "_errors").c_str());
graphErrors->SetTitle((graphConfig.title + " errors").c_str());
graphErrors->Draw("SAME E");
}
}

// Legend entry and styling for graphs
if (auto graph = dynamic_cast<TGraph*>(c->FindObject("Graph"))) {
if (plotOrder >= 2) {
// Style objects after Draw so we override palette/auto styling when requested
applyStyleToGraph(graph, graphConfig.style);
// Keep errors visually consistent with the main series
if (graphErrors) {
applyStyleToGraph(graphErrors, graphConfig.style);
}
}
graph->SetName(graphConfig.name.c_str());
graph->SetTitle(graphConfig.title.c_str());
legend->AddEntry(graph, graphConfig.title.c_str(), deduceGraphLegendOptions(graphConfig).c_str());
legend->AddEntry(graph, graphConfig.title.c_str(),
deduceGraphLegendOptions(graphConfig).c_str());
}

// Legend entry and styling for histograms
if (auto htemp = dynamic_cast<TH1*>(c->FindObject("htemp"))) {
if (plotOrder == 1) {
htemp->SetName(graphConfig.name.c_str());
Expand All @@ -370,15 +419,11 @@ TCanvas* TrendingTask::drawPlot(const TrendingTaskConfig::Plot& plotConfig)
} else {
htemp->SetName("background");
htemp->SetTitle("background");
// htemp was used by TTree::Draw only to draw axes and title, not to plot data, no need to add it to legend
}
// QCG doesn't empty the buffers before visualizing the plotConfig, nor does ROOT when saving the file,
// so we have to do it here.
htemp->BufferEmpty();
// we keep the pointer to bg histogram for later postprocessing
if (background == nullptr) {
background = htemp;
}
if (!background) { background = htemp; }
}

firstGraphInPlot = false;
Expand All @@ -387,8 +432,7 @@ TCanvas* TrendingTask::drawPlot(const TrendingTaskConfig::Plot& plotConfig)
c->SetName(plotConfig.name.c_str());
c->SetTitle(plotConfig.title.c_str());

// Postprocessing the plotConfig - adding specified titles, configuring time-based plots, flushing buffers.
// Notice that axes and title are drawn using a histogram, even in the case of graphs.
// Post-process: title, axes labels, time axis formatting, y-range
if (background) {
// The title of background histogram is printed, not the title of canvas => we set it as well.
background->SetTitle(plotConfig.title.c_str());
Expand All @@ -408,11 +452,13 @@ TCanvas* TrendingTask::drawPlot(const TrendingTaskConfig::Plot& plotConfig)
setUserAxesLabels(background->GetXaxis(), background->GetYaxis(), plotConfig.graphAxisLabel);
}

if (plotConfig.graphs.back().varexp.find(":time") != std::string::npos) {
// We have to explicitly configure showing time on x axis.
formatTimeXAxis(background);
} else if (plotConfig.graphs.back().varexp.find(":meta.runNumber") != std::string::npos) {
formatRunNumberXAxis(background);
if (!plotConfig.graphs.empty()) {
const auto& lastVar = plotConfig.graphs.back().varexp;
if (lastVar.find(":time") != std::string::npos) {
formatTimeXAxis(background);
} else if (lastVar.find(":meta.runNumber") != std::string::npos) {
formatRunNumberXAxis(background);
}
}

// Set the user-defined range on the y axis if needed.
Expand All @@ -425,11 +471,12 @@ TCanvas* TrendingTask::drawPlot(const TrendingTaskConfig::Plot& plotConfig)
ILOG(Error, Devel) << "Could not get the htemp histogram of the plotConfig '" << plotConfig.name << "'." << ENDM;
}

if (plotConfig.graphs.size() > 1) {
if (plotConfig.graphs.size() > 1 && plotConfig.legend.enabled) {
legend->Draw();
} else {
delete legend;
}

c->Modified();
c->Update();

Expand Down
32 changes: 31 additions & 1 deletion Framework/src/TrendingTaskConfig.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,56 @@ TrendingTaskConfig::TrendingTaskConfig(std::string id, const boost::property_tre
for (const auto& [_, graphConfig] : graphsConfig.value()) {
// first we use name of the graph, if absent, we use graph title, if absent, we use plot (object) name.
const auto& name = graphConfig.get<std::string>("name", graphConfig.get<std::string>("title", plotConfig.get<std::string>("name")));
GraphStyle style;
style.lineColor = graphConfig.get<int>("style.lineColor", -1);
style.lineStyle = graphConfig.get<int>("style.lineStyle", -1);
style.lineWidth = graphConfig.get<int>("style.lineWidth", -1);
style.markerColor = graphConfig.get<int>("style.markerColor", -1);
style.markerStyle = graphConfig.get<int>("style.markerStyle", -1);
style.markerSize = graphConfig.get<float>("style.markerSize", -1.f);
style.fillColor = graphConfig.get<int>("style.fillColor", -1);
style.fillStyle = graphConfig.get<int>("style.fillStyle", -1);

graphs.push_back({ name,
graphConfig.get<std::string>("title", ""),
graphConfig.get<std::string>("varexp"),
graphConfig.get<std::string>("selection", ""),
graphConfig.get<std::string>("option", ""),
graphConfig.get<std::string>("graphErrors", "") });
graphConfig.get<std::string>("graphErrors", ""),
style });
}
} else {
GraphStyle style;
style.lineColor = plotConfig.get<int>("style.lineColor", -1);
style.lineStyle = plotConfig.get<int>("style.lineStyle", -1);
style.lineWidth = plotConfig.get<int>("style.lineWidth", -1);
style.markerColor = plotConfig.get<int>("style.markerColor", -1);
style.markerStyle = plotConfig.get<int>("style.markerStyle", -1);
style.markerSize = plotConfig.get<float>("style.markerSize", -1.f);
style.fillColor = plotConfig.get<int>("style.fillColor", -1);
style.fillStyle = plotConfig.get<int>("style.fillStyle", -1);
graphs.push_back({ plotConfig.get<std::string>("name", ""),
plotConfig.get<std::string>("title", ""),
plotConfig.get<std::string>("varexp"),
plotConfig.get<std::string>("selection", ""),
plotConfig.get<std::string>("option", ""),
plotConfig.get<std::string>("graphErrors", "") });
}

LegendConfig leg;
leg.enabled = plotConfig.get<bool>("legend.enabled", false);
leg.nColumns = plotConfig.get<int>("legend.nColumns", 1);
leg.x1 = plotConfig.get<float>("legend.x1", 0.30f);
leg.y1 = plotConfig.get<float>("legend.y1", 0.20f);
leg.x2 = plotConfig.get<float>("legend.x2", 0.55f);
leg.y2 = plotConfig.get<float>("legend.y2", 0.35f);

plots.push_back({ plotConfig.get<std::string>("name"),
plotConfig.get<std::string>("title", ""),
plotConfig.get<std::string>("graphAxisLabel", ""),
plotConfig.get<std::string>("graphYRange", ""),
plotConfig.get<int>("colorPalette", 0),
leg,
graphs });
}

Expand Down
56 changes: 56 additions & 0 deletions Modules/FIT/FT0/etc/ft0-post-processing.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,33 @@
"url": ""
}
},
"tasks": {
"Digits": {
"active": "true",
"className": "o2::quality_control_modules::ft0::DigitQcTask",
"moduleName": "QcFT0",
"detectorName": "FT0",
"cycleDurationSeconds": "60",
"resetAfterCycles": "1",
"dataSource": {
"type": "direct",
"query": "digits:FT0/DIGITSBC/0;channels:FT0/DIGITSCH/0"
},
"taskParameters": {
"#ChannelIDs": "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215",
"ChannelIDsAmpVsTime": "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215",
"trgThresholdTimeLow": "-100",
"trgThresholdTimeHigh": "100",
"trgModeSide": "A+C",
"trgModeThresholdVar": "Ampl",
"trgThresholdSCenA": "20",
"trgThresholdCenA": "40",
"trgOrGate": "153",
"trgChargeLevelLow": "0",
"trgChargeLevelHigh": "4095"
}
}
},
"checks": {
"ASideInnerMIPCheck": {
"active": "true",
Expand Down Expand Up @@ -416,6 +443,7 @@
"className": "o2::quality_control::postprocessing::TrendingTask",
"moduleName": "QcFT0",
"detectorName": "FT0",
"resumeTrend": "true",
"dataSources": [
{
"type": "repository",
Expand All @@ -431,6 +459,34 @@
}
],
"plots": [
{
"name": "trend_cycle_duration_ntf_corr",
"title": "cycle duration: ns/TF;time;cycle duration [ns/TimeFrames]",
"legend": { "enabled": true, "x1": 0.70, "y1": 0.70, "x2": 0.93, "y2": 0.90, "nColumns": 1 },
"graphs": [
{
"title": "cycle duration [ns]",
"varexp": "CycleDuration.entries:time",
"selection": "",
"option": "*LP",
"style": { "lineColor": 38, "markerColor": 4, "markerStyle": 20, "lineWidth": 2 }
},
{
"title": "cycle duration [TimeFrames]",
"varexp": "CycleDurationNTF.entries:time",
"selection": "",
"option": "*LP",
"style": { "lineColor": 8, "markerColor": 3, "markerStyle": 30, "lineWidth": 2 }
},
{
"title": "cycle duration: ns/TF;time;cycle duration [ns/TimeFrames]",
"varexp": "CycleDuration.entries/CycleDurationNTF.entries:time",
"selection": "",
"option": "*LP",
"style": { "lineColor": 31, "markerColor": 30, "markerStyle": 23, "lineWidth": 2 }
}
]
},
{
"name": "trend_cycle_duration",
"title": "cycle duration [ns]",
Expand Down
2 changes: 2 additions & 0 deletions Modules/FIT/FV0/include/FV0/DigitQcTask.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ class DigitQcTask final : public TaskInterface

// Objects which will be published
std::unique_ptr<TH2F> mHistAmp2Ch;
std::unique_ptr<TH1F> mHistAmpAll;
std::array<std::unique_ptr<TH1F>, sNCHANNELS_FV0_PLUSREF> mHistAmpPerCh;
std::unique_ptr<TH2F> mHistTime2Ch;
std::unique_ptr<TH2F> mHistEventDensity2Ch;
std::unique_ptr<TH2F> mHistChDataBits;
Expand Down
Loading