Belle II Software development
DQMHistAutoCanvas.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8//+
9// File : DQMHistAutoCanvas.cc
10// Description : This module auto-plots each histogram in its canvas
11//-
12
13#include <dqm/analysis/modules/DQMHistAutoCanvas.h>
14#include <TStyle.h>
15#include <fstream>
16
17using namespace Belle2;
18
19//-----------------------------------------------------------------
20// Register the Module
21//-----------------------------------------------------------------
22REG_MODULE(DQMHistAutoCanvas);
23
24//-----------------------------------------------------------------
25// Implementation
26//-----------------------------------------------------------------
27
30{
31 //Parameter definition
32 addParam("IncludeFolders", m_inclfolders, "List of histograms to automatically create canvases, empty for all",
33 std::vector<std::string>());
34 addParam("ExcludeFolders", m_exclfolders, "List of folders to exclude from create canvases, empty for none, \"all\" for all",
35 std::vector<std::string>());
36 addParam("IncludeListFile", m_listfile,
37 "File with a list of canvas names to create and plot. Empty string for using include/exclude folder parameter",
38 std::string(""));
39 B2DEBUG(1, "DQMHistAutoCanvas: Constructor done.");
40}
41
43{
44 m_canvaslist.clear();
45 if (m_listfile != "") {
46 std::ifstream inputFile(m_listfile);
47 // Check if the file is open
48 if (!inputFile.is_open()) {
49 B2WARNING("cannot open histogram list file " << m_listfile);
50 return;
51 }
52 // Read lines from the file and store them in the vector
53 std::string line;
54
55 while (std::getline(inputFile, line)) {
56 m_canvaslist.insert(line);
57 }
58 // Close the file
59 inputFile.close();
60 }
61}
62
64{
65 m_cs.clear();
66}
67
69{
70 gStyle->SetOptStat(0);
71 gStyle->SetStatStyle(1);
72 gStyle->SetOptDate(22);// Date and Time in Bottom Right, does it work?
73
74 // There may be a more clever way instead of doing the iteration my myself here
75 // This only works because the getHistList is not const anymore
76 for (auto& it : getHistList()) {
77 bool give_canvas = false;
78 TString histoname = it.first;
79
80 // the following lines prevent any histogram outside a directory to be processed
81 auto split_result = StringSplit(histoname.Data(), '/');
82 if (split_result.size() <= 1) continue;
83 auto dirname = split_result.at(0); // extract dirname, get hist name is in histogram itself
84 std::string hname = split_result.at(1);
85 if ((dirname + "/" + hname) == "softwaretrigger/skim") hname = "skim_hlt";
86 std::string cname = dirname + "/c_" + hname;
87 std::replace(cname.begin(), cname.end(), '.', '_');
88
89 // Now find out if we want to have a canvas at all
90
91 // case 1: list file
92 if (m_listfile != "") {
93 give_canvas = m_canvaslist.find(cname) != m_canvaslist.end();
94 } else {
95 // case 2: include/exclude tname = "c_" + hname;
96
97 if (m_exclfolders.size() == 0) { //If none specified, canvases for all histograms
98 give_canvas = true;
99 } else {
100 bool in_excl_folder = false;
101 if (m_exclfolders.size() == 1 && m_exclfolders[0] == "all") {
102 in_excl_folder = true;
103 } else {
104 for (const auto& excl_folder : m_exclfolders) {
105 if (excl_folder == dirname) {
106 in_excl_folder = true;
107 break;
108 }
109 }
110 }
111
112 if (in_excl_folder) {
113 for (const auto& wanted_folder : m_inclfolders) {
114 B2DEBUG(1, "==" << wanted_folder << "==" << dirname << "==");
115 if (wanted_folder == std::string(histoname)) {
116 give_canvas = true;
117 break;
118 }
119 }
120 } else {
121 give_canvas = true;
122 }
123 }
124 }
125
126 if (give_canvas) {
127 B2DEBUG(1, "Auto Hist->Canvas for " << histoname);
128 histoname.ReplaceAll("/", "_");
129 std::string name = histoname.Data();
130 if (m_cs.find(name) == m_cs.end()) {
131 // no canvas exists yet, create one
132 TCanvas* c = new TCanvas(cname.c_str(), ("c_" + hname).c_str());
133 m_cs.insert(std::pair<std::string, std::unique_ptr<TCanvas>>(name, c));
134 B2DEBUG(1, "DQMHistAutoCanvasModule: new canvas " << c->GetName());
135 }
136
137 TCanvas* c = m_cs[name].get(); // access already created canvas
138 c->cd();
139 // Maybe we want to have it Cleared? Otherwise colored border could stay?
140 // but if, then only if histogram has changed!
141
142 // not so nice as we actually touch the histogram by iterator
143 // we could use findHist function, but then we do another lookup within iteration
144 if (auto hist = it.second.getHist(); hist != nullptr) {
145 if (hist->GetDimension() == 1) {
146 // assume users are expecting non-0-suppressed axis
147 if (hist->GetMinimum() > 0) hist->SetMinimum(0);
148 hist->Draw("hist");
149 // reference only for 1dim and only if *both* not empty
150 if (hist->Integral() != 0) { // ignore empty histogram
151 // default scaling to number of entries
152 auto refCopy = findRefHist(it.first, "", ERefScaling::c_RefScaleEntries, hist);
153 if (refCopy and abs(refCopy->Integral()) > 0) { // only if we have entries in reference
154 // Adjust the y scale to cover the reference
155 if (refCopy->GetMaximum() > hist->GetMaximum())
156 hist->SetMaximum(1.1 * refCopy->GetMaximum());
157
158 refCopy->Draw("hist,same");
159
160 /* We could consider to add some auto-comparison here later, thus adding coloring option....
161 double data = 0;
162 if (m_color) {
163 data = hist1->KolmogorovTest(hist2, ""); // returns p value (0 bad, 1 good), N - do not compare normalized
164 }
165 */
166 }
167 }
168 } else if (hist->GetDimension() == 2) {
169 // ... but not in 2d
170 hist->Draw("colz");
171 } // else 3D or others?
172 }
173
174 // set Canvas "name" update flag if histo was updated
175 // UpdateCanvas(name, findHist(histoname.Data()) != nullptr);
176 // we already have the HistObject, so we can directly get it
177 UpdateCanvas(name, it.second.isUpdated());
178
179 // Mark Canvas as repaint needed, but is this needed?
180 c->Update();
181 }
182 }
183}
static void UpdateCanvas(const std::string &name, bool updated=true)
Mark canvas as updated (or not)
static std::vector< std::string > StringSplit(const std::string &s, const char delim)
Helper function for string token split.
DQMHistAnalysisModule()
Constructor / Destructor.
static HistList & getHistList()
Get the list of the histograms.
@ c_RefScaleEntries
to number of entries (integral)
static TH1 * findRefHist(const std::string &dirname, const std::string &histname="", ERefScaling scaling=ERefScaling::c_RefScaleNone, const TH1 *hist=nullptr)
Find reference histogram.
std::vector< std::string > m_inclfolders
The list of folders for which automatically generate canvases.
std::map< std::string, std::unique_ptr< TCanvas > > m_cs
The map of histogram names to canvas pointers for buffering.
void terminate() override final
This method is called at terminate.
void event() override final
This method is called for each event.
std::set< std::string > m_canvaslist
list of wanted canvas name if included as list file
void beginRun() override final
This method is called for each run.
std::vector< std::string > m_exclfolders
The list of folders which are excluded from automatically generate canvases.
std::string m_listfile
The filename of a list canvas names to auto generate.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition Module.h:559
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition Module.h:649
Abstract base class for different kinds of events.