Belle II Software prerelease-11-00-00a
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 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 auto hist = it.second.getHist();
145 if (hist) {
146 if (hist->GetDimension() == 1) {
147 // assume users are expecting non-0-suppressed axis
148 if (hist->GetMinimum() > 0) hist->SetMinimum(0);
149 hist->Draw("hist");
150 // reference only for 1dim and only if *both* not empty
151 if (hist->Integral() != 0) { // ignore empty histogram
152 // default scaling to number of entries
153 auto refCopy = findRefHist(it.first, ERefScaling::c_RefScaleEntries, hist);
154 if (refCopy and abs(refCopy->Integral()) > 0) { // only if we have entries in reference
155 // Adjust the y scale to cover the reference
156 if (refCopy->GetMaximum() > hist->GetMaximum())
157 hist->SetMaximum(1.1 * refCopy->GetMaximum());
158
159 refCopy->Draw("hist,same");
160
161 /* We could consider to add some auto-comparison here later, thus adding coloring option....
162 double data = 0;
163 if (m_color) {
164 data = hist1->KolmogorovTest(hist2, ""); // returns p value (0 bad, 1 good), N - do not compare normalized
165 }
166 */
167 }
168 }
169 } else if (hist->GetDimension() == 2) {
170 // ... but not in 2d
171 hist->Draw("colz");
172 } // else 3D or others?
173 }
174
175 // set Canvas "name" update flag if histo was updated
176 // UpdateCanvas(name, findHist(histoname.Data()) != nullptr);
177 // we already have the HistObject, so we can directly get it
178 UpdateCanvas(name, it.second.isUpdated());
179
180 // Mark Canvas as repaint needed, but is this needed?
181 c->Update();
182 }
183 }
184}
static TH1 * findRefHist(const std::string &histname, ERefScaling scaling=ERefScaling::c_RefScaleNone, const TH1 *hist=nullptr)
Get referencehistogram from list (no other search).
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)
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.
STL namespace.