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 std;
18using namespace Belle2;
19
20//-----------------------------------------------------------------
21// Register the Module
22//-----------------------------------------------------------------
23REG_MODULE(DQMHistAutoCanvas);
24
25//-----------------------------------------------------------------
26// Implementation
27//-----------------------------------------------------------------
28
31{
32 //Parameter definition
33 addParam("IncludeFolders", m_inclfolders, "List of histograms to automatically create canvases, empty for all",
34 std::vector<std::string>());
35 addParam("ExcludeFolders", m_exclfolders, "List of folders to exclude from create canvases, empty for none, \"all\" for all",
36 std::vector<std::string>());
37 addParam("IncludeListFile", m_listfile, "List canvases to create canvases from, empty for using include/exclide 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 cname;
85 std::string hname;
86 if (split_result.size() > 1) { // checked above already
87 hname = split_result.at(1);
88 if ((dirname + "/" + hname) == "softwaretrigger/skim") hname = "skim_hlt";
89 cname = dirname + "/c_" + hname;
90 } else {
91 hname = histoname.Data();
92 cname = "c_" + hname;
93 }
94 std::replace(cname.begin(), cname.end(), '.', '_');
95
96 // Now find out if we want to have a canvas at all
97
98 // case 1: list file
99 if (m_listfile != "") {
100 give_canvas = m_canvaslist.find(cname) != m_canvaslist.end();
101 } else {
102 // case 2: include/exclude tname = "c_" + hname;
103
104 if (m_exclfolders.size() == 0) { //If none specified, canvases for all histograms
105 give_canvas = true;
106 } else {
107 bool in_excl_folder = false;
108 if (m_exclfolders.size() == 1 && m_exclfolders[0] == "all") {
109 in_excl_folder = true;
110 } else {
111 for (auto& excl_folder : m_exclfolders) {
112 if (excl_folder == dirname) {
113 in_excl_folder = true;
114 break;
115 }
116 }
117 }
118
119 if (in_excl_folder) {
120 for (auto& wanted_folder : m_inclfolders) {
121 B2DEBUG(1, "==" << wanted_folder << "==" << dirname << "==");
122 if (wanted_folder == std::string(histoname)) {
123 give_canvas = true;
124 break;
125 }
126 }
127 } else {
128 give_canvas = true;
129 }
130 }
131 }
132
133 if (give_canvas) {
134 B2DEBUG(1, "Auto Hist->Canvas for " << histoname);
135 histoname.ReplaceAll("/", "_");
136 std::string name = histoname.Data();
137 if (m_cs.find(name) == m_cs.end()) {
138 // no canvas exists yet, create one
139 TCanvas* c = new TCanvas(cname.c_str(), ("c_" + hname).c_str());
140 m_cs.insert(std::pair<std::string, std::unique_ptr<TCanvas>>(name, c));
141 B2DEBUG(1, "DQMHistAutoCanvasModule: new canvas " << c->GetName());
142 }
143
144 TCanvas* c = m_cs[name].get(); // access already created canvas
145 c->cd();
146 // Maybe we want to have it Cleared? Otherwise colored border could stay?
147 // but if, then only if histogram has changed!
148
149 // not so nice as we actually touch the histogram by iterator
150 // we could use findHist function, but then we do another lookup within iteration
151 auto hist = it.second.getHist();
152 if (hist) {
153 if (hist->GetDimension() == 1) {
154 // assume users are expecting non-0-suppressed axis
155 if (hist->GetMinimum() > 0) hist->SetMinimum(0);
156 hist->Draw("hist");
157 // reference only for 1dim and only if *both* not empty
158 if (hist->Integral() != 0) { // ignore empty histogram
159 // default scaling to number of entries
160 auto refCopy = findRefHist(it.first, ERefScaling::c_RefScaleEntries, hist);
161 if (refCopy and abs(refCopy->Integral()) > 0) { // only if we have entries in reference
162 // Adjust the y scale to cover the reference
163 if (refCopy->GetMaximum() > hist->GetMaximum())
164 hist->SetMaximum(1.1 * refCopy->GetMaximum());
165
166 refCopy->Draw("hist,same");
167
168 /* We could consider to add some auto-comparison here later, thus adding coloring option....
169 double data = 0;
170 if (m_color) {
171 data = hist1->KolmogorovTest(hist2, ""); // returns p value (0 bad, 1 good), N - do not compare normalized
172 }
173 */
174 }
175 }
176 } else if (hist->GetDimension() == 2) {
177 // ... but not in 2d
178 hist->Draw("colz");
179 } // else 3D or others?
180 }
181
182 // set Canvas "name" update flag if histo was updated
183 // UpdateCanvas(name, findHist(histoname.Data()) != nullptr);
184 // we already have the HistObject, so we can directly get it
185 UpdateCanvas(name, it.second.isUpdated());
186
187 // Mark Canvas as repaint needed, but is this needed?
188 c->Update();
189 }
190 }
191}
The base class for the histogram analysis module.
static TH1 * findRefHist(const std::string &histname, ERefScaling scaling=ERefScaling::c_RefScaleNone, const TH1 *hist=nullptr)
Get referencehistogram from list (no other search).
std::vector< std::string > StringSplit(const std::string &s, const char delim)
Helper function for string token split.
static HistList & getHistList()
Get the list of the histograms.
@ c_RefScaleEntries
to number of entries (integral)
void UpdateCanvas(std::string name, bool updated=true)
Mark canvas as updated (or not)
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:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
Abstract base class for different kinds of events.
STL namespace.