Belle II Software  release-06-02-00
DQMHistAnalysisInputRootFile.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 : DQMHistAnalysisInputRootFile.cc
10 // Description : Module for offline testing of histogram analysis code.
11 // Root file containing DQM histograms can be used as input.
12 //-
13 
14 
15 #include <dqm/analysis/modules/DQMHistAnalysisInputRootFile.h>
16 
17 #include <daq/slc/base/StringUtil.h>
18 #include <TKey.h>
19 #include <TROOT.h>
20 
21 #include <boost/regex.hpp>
22 #include <boost/algorithm/string/replace.hpp>
23 #include <iostream>
24 using namespace Belle2;
25 
26 //-----------------------------------------------------------------
27 // Register the Module
28 //-----------------------------------------------------------------
29 REG_MODULE(DQMHistAnalysisInputRootFile)
30 
31 //-----------------------------------------------------------------
32 // Implementation
33 //-----------------------------------------------------------------
34 
37 {
38  //Parameter definition
39  addParam("FileList", m_file_list, "List of input files" , std::vector<std::string> {"input_histo.root"});
40  addParam("SelectHistograms", m_histograms, "List of histogram name patterns, empty for all. Support wildcard matching (* and ?).",
41  std::vector<std::string>());
42  addParam("Experiment", m_expno, "Experiment Nr" , 7u);
43  addParam("RunList", m_run_list, "Run Number List" , std::vector<unsigned int> {1u});
44  addParam("EventsList", m_events_list, "Number of events for each run" , std::vector<unsigned int> {10u});
45  addParam("EventInterval", m_interval, "Time between events (seconds)" , 20u);
46  addParam("NullHistogramMode", m_null_histo_mode, "Test mode for null histograms" , false);
47  addParam("AutoCanvas", m_autocanvas, "Automatic creation of canvas", true);
48  B2DEBUG(1, "DQMHistAnalysisInputRootFile: Constructor done.");
49 }
50 
52 {
53  if (m_file != nullptr) delete m_file;
54  if (m_file_list.size() == 0) B2ERROR("File list is empty.");
55  if (m_run_list.size() == 0) B2ERROR("Run list is empty.");
56  if (m_events_list.size() == 0) B2ERROR("Events list is empty.");
57  if (m_run_list.size() != m_events_list.size()) B2ERROR("Run list does not have the same size as events list.");
58  if (m_run_list.size() != m_file_list.size()) B2ERROR("Run list does not have the same size as file list.");
59  m_run_idx = 0;
60  m_file = new TFile(m_file_list[m_run_idx].c_str());
61  m_eventMetaDataPtr.registerInDataStore();
62  B2INFO("DQMHistAnalysisInputRootFile: initialized.");
63 }
64 
65 bool DQMHistAnalysisInputRootFileModule::hname_pattern_match(std::string pattern, std::string text)
66 {
67  boost::replace_all(pattern, "\\", "\\\\");
68  boost::replace_all(pattern, "^", "\\^");
69  boost::replace_all(pattern, ".", "\\.");
70  boost::replace_all(pattern, "$", "\\$");
71  boost::replace_all(pattern, "|", "\\|");
72  boost::replace_all(pattern, "(", "\\(");
73  boost::replace_all(pattern, ")", "\\)");
74  boost::replace_all(pattern, "[", "\\[");
75  boost::replace_all(pattern, "]", "\\]");
76  boost::replace_all(pattern, "*", "\\*");
77  boost::replace_all(pattern, "+", "\\+");
78  boost::replace_all(pattern, "?", "\\?");
79  boost::replace_all(pattern, "/", "\\/");
80 
81  boost::replace_all(pattern, "\\?", ".");
82  boost::replace_all(pattern, "\\*", ".*");
83 
84  boost::regex bpattern(pattern);
85 
86  return regex_match(text, bpattern);
87 }
88 
90 {
91  B2INFO("DQMHistAnalysisInputRootFile: beginRun called. Run: " << m_run_list[m_run_idx]);
92 }
93 
95 {
96  B2INFO("DQMHistAnalysisInputRootFile: event called.");
97  sleep(m_interval);
98 
100  m_run_idx++;
101  if (m_run_idx == m_run_list.size()) {
102  m_eventMetaDataPtr.create();
103  m_eventMetaDataPtr->setEndOfData();
104  return;
105  }
106  m_count = 0;
107  if (m_file != nullptr) {
108  m_file->Close();
109  delete m_file;
110  }
111  m_file = new TFile(m_file_list[m_run_idx].c_str());
112  }
113 
114  if (m_null_histo_mode) {
115  m_eventMetaDataPtr.create();
116  m_eventMetaDataPtr->setExperiment(m_expno);
118  m_eventMetaDataPtr->setEvent(m_count);
119  m_eventMetaDataPtr->setTime(0);
120  B2INFO("DQMHistAnalysisInputRootFile: event finished. count: " << m_count);
121  m_count++;
122  return;
123  }
124 
125  std::vector<TH1*> hs;
126  unsigned long long int ts = 0;
127  m_file->cd();
128  TIter next(m_file->GetListOfKeys());
129  TKey* key = NULL;
130  while ((key = (TKey*)next())) {
131  TClass* cl = gROOT->GetClass(key->GetClassName());
132  if (ts == 0) ts = key->GetDatime().Convert();
133  if (!cl->InheritsFrom("TDirectory")) continue;
134  TDirectory* d = (TDirectory*)key->ReadObj();
135  std::string dirname = d->GetName();
136 
137  d->cd();
138  TIter nextd(d->GetListOfKeys());
139 
140  TKey* dkey;
141  while ((dkey = (TKey*)nextd())) {
142  TClass* dcl = gROOT->GetClass(dkey->GetClassName());
143  if (!dcl->InheritsFrom("TH1")) continue;
144  TH1* h = (TH1*)dkey->ReadObj();
145  if (h->InheritsFrom("TH2")) h->SetOption("col");
146  else h->SetOption("hist");
147  Double_t scale = 1.0 * m_count / m_events_list[m_run_idx];
148  h->Scale(scale);
149  std::string hname = h->GetName();
150 
151  bool hpass = false;
152  if (m_histograms.size() == 0) {
153  hpass = true;
154  } else {
155  for (auto& hpattern : m_histograms) {
156  if (hname_pattern_match(hpattern, dirname + "/" + hname)) {
157  hpass = true;
158  break;
159  }
160  }
161  }
162  if (!hpass) continue;
163 
164  if (hname.find("/") == std::string::npos) h->SetName((dirname + "/" + hname).c_str());
165  hs.push_back(h);
166 
167  if (m_autocanvas) {
168  std::string name = dirname + "_" + hname;
169  if (m_cs.find(name) == m_cs.end()) {
170  TCanvas* c = new TCanvas((dirname + "/c_" + hname).c_str(), ("c_" + hname).c_str());
171  m_cs.insert(std::pair<std::string, TCanvas*>(name, c));
172  }
173 
174  TCanvas* c = m_cs[name];
175  c->cd();
176  if (h->GetDimension() == 1) {
177  h->Draw("hist");
178  } else if (h->GetDimension() == 2) {
179  h->Draw("colz");
180  }
181  c->Update();
182  }
183  }
184  m_file->cd();
185  }
186 
187  // if no histograms are found in the sub-directories
188  // searc the top folder
189  if (hs.size() == 0) {
190  TIter nexth(m_file->GetListOfKeys());
191  TKey* keyh = NULL;
192  while ((keyh = (TKey*)nexth())) {
193  TClass* cl = gROOT->GetClass(keyh->GetClassName());
194  TH1* h;
195  if (!cl->InheritsFrom("TH1")) continue;
196  h = (TH1*)keyh->ReadObj();
197 
198  bool hpass = false;
199  if (m_histograms.size() == 0) {
200  hpass = true;
201  } else {
202  for (auto& hpattern : m_histograms) {
203  if (hname_pattern_match(hpattern, h->GetName())) {
204  hpass = true;
205  break;
206  }
207  }
208  }
209  if (!hpass) continue;
210 
211  hs.push_back(h);
212  Double_t scale = 1.0 * m_count / m_events_list[m_run_idx];
213  h->Scale(scale);
214  if (m_autocanvas) {
215  std::string name = h->GetName();
216  name.replace(name.find("/"), 1, "/c_");
217  if (m_cs.find(name) == m_cs.end()) {
218  TCanvas* c = new TCanvas(name.c_str(), name.c_str());
219  m_cs.insert(std::pair<std::string, TCanvas*>(name, c));
220  }
221  TCanvas* c = m_cs[name];
222  c->cd();
223  if (h->GetDimension() == 1) {
224  h->Draw("hist");
225  } else if (h->GetDimension() == 2) {
226  h->Draw("colz");
227  }
228  c->Update();
229  }
230  }
231  }
232 
233  resetHist();
234  for (size_t i = 0; i < hs.size(); i++) {
235  TH1* h = hs[i];
236  addHist("", h->GetName(), h);
237  B2DEBUG(1, "Found : " << h->GetName() << " : " << h->GetEntries());
238  }
239  m_eventMetaDataPtr.create();
240 
241  m_eventMetaDataPtr->setExperiment(m_expno);
243  m_eventMetaDataPtr->setEvent(m_count);
244  m_eventMetaDataPtr->setTime(ts * 1e9);
245  B2INFO("DQMHistAnalysisInputRootFile: event finished. count: " << m_count);
246 
247  m_count++;
248 }
249 
251 {
252  B2INFO("DQMHistAnalysisInputRootFile : endRun called");
253 }
254 
255 
257 {
258  B2INFO("terminate called");
259 }
260 
Class to read histograms from a root file for offline testing of analysis modules.
void initialize() override final
Initialize the module.
std::vector< unsigned int > m_events_list
List of total number of events for each run.
bool m_autocanvas
Whether to automatically generate canvases for histograms.
std::vector< std::string > m_histograms
List of histogram name patterns to process.
std::vector< unsigned int > m_run_list
List of runs.
std::vector< std::string > m_file_list
The list of names of the input root file.
void terminate() override final
Termination action.
bool m_null_histo_mode
Test mode for null histograms.
bool hname_pattern_match(std::string pattern, std::string text)
Pattern match for histogram name.
TFile * m_file
The TFile object for the input file.
void endRun() override final
End-of-run action.
unsigned int m_interval
Time between two events in second.
void beginRun() override final
Called when entering a new run.
std::map< std::string, TCanvas * > m_cs
The map between canvas name and canvas object.
StoreObjPtr< EventMetaData > m_eventMetaDataPtr
Global EventMetaData for run number and event number.
unsigned int m_run_idx
Index in the list of runs, events and files.
The base class for the histogram analysis module.
static void addHist(const std::string &dirname, const std::string &histname, TH1 *h)
Add histogram.
static void resetHist()
Clear and reset the list of histograms.
#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.