Belle II Software development
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 <TROOT.h>
18#include <TKey.h>
19
20#include <boost/regex.hpp>
21#include <boost/algorithm/string/replace.hpp>
22
23using namespace Belle2;
24
25//-----------------------------------------------------------------
26// Register the Module
27//-----------------------------------------------------------------
28REG_MODULE(DQMHistAnalysisInputRootFile);
29
30//-----------------------------------------------------------------
31// Implementation
32//-----------------------------------------------------------------
33
36{
37 setDescription("DQM framework core module for reading histograms from (offline) root file, e.g. for MiraBelle");
38 // This module CAN NOT be run in parallel!
39
40 //Parameter definition
41 addParam("FileList", m_fileList, "List of input files", std::vector<std::string> {"input_histo.root"});
42 addParam("SelectHistograms", m_histograms, "List of histogram name patterns, empty for all. Support wildcard matching (* and ?).",
43 std::vector<std::string>());
44 addParam("EventsList", m_eventsList, "Number of events for each run", std::vector<int>());
45 addParam("Experiment", m_expno, "Experiment Nr override", 0);
46 addParam("RunList", m_runList, "Run Number List", std::vector<int>());
47 addParam("RunType", m_runType, "Run Type override", std::string(""));
48 addParam("FillNEvent", m_fillNEvent, "NEvent override", 0);
49 addParam("EventInterval", m_interval, "Time between events (seconds)", 20u);
50 addParam("EnableRunInfo", m_enable_run_info, "Enable Run Info", false);
51 B2DEBUG(1, "DQMHistAnalysisInputRootFile: Constructor done.");
52}
53
55{
56 if (m_fileList.size() == 0) B2FATAL("File list is empty.");
57 if (m_eventsList.size() == 0) {
58 m_eventsList.resize(m_fileList.size(), 1); // default one events per file
59 }
60 if (m_fileList.size() != m_eventsList.size()) B2ERROR("File list does not have the same size as events list.");
61 if (m_runList.size() != 0 and m_runList.size() != m_fileList.size()) B2ERROR("Run list does not have the same size as file list.");
62 m_run_idx = 0;
63 m_file = new TFile(m_fileList[m_run_idx].c_str());
64 m_eventMetaDataPtr.registerInDataStore();
65
67 m_c_info = new TCanvas("DQMInfo/c_info", "");
68 m_c_info->SetTitle("");
69 }
70 if (m_expno > 0) m_h_expno = new TH1F("DQMInfo/expno", "", 1, 0, 1);
71 if (m_runList.size() != 0) m_h_runno = new TH1F("DQMInfo/runno", "", 1, 0, 1);
72 if (m_runType != "") m_h_rtype = new TH1F("DQMInfo/rtype", m_runType.c_str(), 1, 0, 1);
73 if (m_fillNEvent > 0) {
74 m_h_fillNEvent = new TH1F("DAQ/Nevent", "", 1, 0, 1);
76 m_h_fillNEvent->SetEntries(m_fillNEvent);
77 }
78 B2INFO("DQMHistAnalysisInputRootFile: initialized.");
79}
80
81bool DQMHistAnalysisInputRootFileModule::hnamePatternMatch(std::string pattern, const std::string& text)
82{
83 boost::replace_all(pattern, "\\", "\\\\");
84 boost::replace_all(pattern, "^", "\\^");
85 boost::replace_all(pattern, ".", "\\.");
86 boost::replace_all(pattern, "$", "\\$");
87 boost::replace_all(pattern, "|", "\\|");
88 boost::replace_all(pattern, "(", "\\(");
89 boost::replace_all(pattern, ")", "\\)");
90 boost::replace_all(pattern, "[", "\\[");
91 boost::replace_all(pattern, "]", "\\]");
92 boost::replace_all(pattern, "*", "\\*");
93 boost::replace_all(pattern, "+", "\\+");
94 boost::replace_all(pattern, "?", "\\?");
95 boost::replace_all(pattern, "/", "\\/");
96
97 boost::replace_all(pattern, "\\?", ".");
98 boost::replace_all(pattern, "\\*", ".*");
99
100 boost::regex bpattern(pattern);
101
102 return regex_match(text, bpattern);
103}
104
106{
107 B2INFO("DQMHistAnalysisInputRootFile: beginRun called.");
108 clearRefList();
109}
110
111void DQMHistAnalysisInputRootFileModule::addToHistList(std::vector<TH1*>& inputHistList, const std::string& dirname, TKey* key)
112{
113 TH1* h = dynamic_cast<TH1*>(key->ReadObj());
114 if (h == nullptr) return; // would be strange, but better check
115 std::string hname = h->GetName();
116
117 if (hname.find("/") == std::string::npos) {
118 if (dirname != "") {
119 hname = dirname + "/" + hname;
120 h->SetName(hname.c_str());
121 } else {
122 // histo in root dir without prefix -> do not keep!
123 delete h;
124 return;
125 }
126 }
127
128 bool hpass = false;
129 if (m_histograms.size() == 0) {// workaround for run info???
130 hpass = true;
131 } else {
132 for (const auto& hpattern : m_histograms) {
133 if (hnamePatternMatch(hpattern, h->GetName())) {
134 hpass = true;
135 break;
136 }
137 }
138 }
139 if (!hpass) {
140 delete h;
141 return;
142 }
143
144 // Remove ":" from folder name, workaround!
145 // Is this really needed?
146 if (hname.find(":") != std::string::npos) {
147 B2ERROR("histogram or folder name with : is problematic");
148 }
149 TString a = h->GetName();
150 a.ReplaceAll(":", "");
151 h->SetName(a);
152 B2DEBUG(1, "DQMHistAnalysisInput2: get histo " << a.Data());
153
154
155 Double_t scale = 1.0 * m_count / m_eventsList[m_run_idx];
156 h->Scale(scale);
157 h->SetEntries(h->GetEntries()*scale); // empty hists are not marked for update!
158
159 // Histograms in the inputHistList list will be taken care of later (delete)
160 inputHistList.push_back(h);
161}
162
164{
165 B2INFO("DQMHistAnalysisInputRootFile: event called.");
166 TH1::AddDirectory(false);
167
168 if (m_count == 0) {
169 // special handling for 1 event to get proper max scaling
170 if (m_eventsList[m_run_idx] == 1) m_count++;
171 else m_eventsList[m_run_idx]--;
172 } else {
173 sleep(m_interval);
174 }
175
176 // Check for run change
178 m_run_idx++;
179 if (m_run_idx == m_fileList.size()) {
180 m_eventMetaDataPtr.create();
181 m_eventMetaDataPtr->setEndOfData();
182 return;
183 }
184 m_count = 0;
185 // special handling for 1 event to get proper max scaling
186 if (m_eventsList[m_run_idx] == 1) m_count = 1;
187 else m_eventsList[m_run_idx]--;
188 // open next file
189 if (m_file != nullptr) {
190 m_file->Close();
191 delete m_file;
192 }
193 m_file = new TFile(m_fileList[m_run_idx].c_str());
194 }
195
196 // Clear only after EndOfRun check, otherwise we won't have any histograms for MiraBelle
197 // which expects analysis run in endRun function
199
201 std::vector<TH1*> inputHistList;
202
203 unsigned long long int ts = 0;
204 m_file->cd();
205 TIter next(m_file->GetListOfKeys());
206 while (auto key = dynamic_cast<TKey*>(next())) {
207 TClass* cl = gROOT->GetClass(key->GetClassName());
208 if (ts == 0) ts = key->GetDatime().Convert();
209 if (cl->InheritsFrom("TDirectory")) {
210 TDirectory* d = static_cast<TDirectory*>(key->ReadObj());
211 std::string dirname = d->GetName();
212
213 d->cd();
214 TIter nextd(d->GetListOfKeys());
215
216 while (auto dkey = dynamic_cast<TKey*>(nextd())) {
217 if (gROOT->GetClass(dkey->GetClassName())->InheritsFrom("TH1")) {
218 addToHistList(inputHistList, dirname, dkey);
219 }
220 }
221 m_file->cd();
222 } else if (cl->InheritsFrom("TH1")) {
223 addToHistList(inputHistList, "", key);
224 }
225 }
226
227 auto expno = m_expno;
228 auto runno = m_runList.size() ? m_runList[m_run_idx] : 0;
229 auto rtype = m_runType;
230
231 if (m_h_expno) {
232 m_h_expno->SetTitle(std::to_string(expno).c_str());
233 inputHistList.push_back(dynamic_cast<TH1*>(m_h_expno->Clone()));
234 }
235 if (m_h_runno) {
236 m_h_runno->SetTitle(std::to_string(runno).c_str());
237 inputHistList.push_back(dynamic_cast<TH1*>(m_h_runno->Clone()));
238 }
239 if (m_h_rtype) {
240 m_h_rtype->SetTitle(rtype.c_str());
241 inputHistList.push_back(dynamic_cast<TH1*>(m_h_rtype->Clone()));
242 }
243 if (m_fillNEvent > 0) {
244 inputHistList.push_back(dynamic_cast<TH1*>(m_h_fillNEvent->Clone()));
245 }
246 // check for no-override
247 for (auto& h : inputHistList) {
248 if (std::string(h->GetName()) == std::string("DQMInfo/expno")) {
249 if (expno == 0) {
250 expno = atoi(h->GetTitle());
251 } else {
252 h->SetTitle(std::to_string(expno).c_str());
253 }
254 }
255 if (std::string(h->GetName()) == std::string("DQMInfo/runno")) {
256 if (runno == 0) {
257 runno = atoi(h->GetTitle());
258 } else {
259 h->SetTitle(std::to_string(runno).c_str());
260 }
261 }
262 if (std::string(h->GetName()) == std::string("DQMInfo/rtype")) {
263 if (rtype == "") {
264 rtype = h->GetTitle();
265 } else {
266 h->SetTitle(rtype.c_str());
267 }
268 }
269 if (std::string(h->GetName()) == std::string("DAQ/Nevent")) {
270 if (m_fillNEvent > 0) {
271 Double_t scale = 1.0 * m_count / m_eventsList[m_run_idx];
272 h->Scale(scale);
273 h->SetEntries(h->GetEntries()*scale); // empty hists are not marked for update!
274 }
275 }
276 }
277
278 if (m_c_info != nullptr) m_c_info->SetTitle(("OFFLINE: Exp " + std::to_string(expno) + ", Run " + std::to_string(
279 runno) + ", RunType " + rtype + ", Last Changed NEVER, Last Updated NEVER, Last DQM event NEVER").c_str());
280
281 m_count++;
282 m_eventMetaDataPtr.create();
283 m_eventMetaDataPtr->setExperiment(expno);
284 m_eventMetaDataPtr->setRun(runno);
285 m_eventMetaDataPtr->setEvent(m_count);
286 m_eventMetaDataPtr->setTime(ts * 1e9);
287
288 ExtractRunType(inputHistList);
289 ExtractNEvent(inputHistList);
290
291 if (m_lastRun != runno or m_lastExp != expno) {
292 // Run change detected
293 m_lastRun = runno;
294 m_lastExp = expno;
295 // we cannot do that in beginRun(), otherwise all histos are cleare before first event
297 }
298
299 // this code must be run after "event processed" has been extracted
300 for (size_t i = 0; i < inputHistList.size(); i++) {
301 TH1* h = inputHistList[i];
302 addHist("", h->GetName(), h);
303 B2DEBUG(1, "Found : " << h->GetName() << " : " << h->GetEntries());
304 }
305
306 B2INFO("DQMHistAnalysisInputRootFile: event finished. count: " << m_count);
307}
TH1F * m_h_runno
emulated histogram from runcontrol, runno
void initialize() override final
Initialize the module.
TH1F * m_h_fillNEvent
emulated histogram from daq, nevent
std::vector< std::string > m_fileList
The list of names of the input root file.
bool m_enable_run_info
Whether to enable the run info to be displayed.
std::vector< std::string > m_histograms
List of histogram name patterns to process.
TH1F * m_h_expno
emulated histogram from runcontrol, expno
TH1F * m_h_rtype
emulated histogram from runcontrol, runtype
void addToHistList(std::vector< TH1 * > &inputHistList, const std::string &dirname, TKey *key)
Read histogram from key and add to list vector.
TFile * m_file
The TFile object for the input file.
std::vector< int > m_eventsList
List of total number of events for each run.
unsigned int m_interval
Time between two events in second.
void beginRun() override final
Called when entering a new run.
StoreObjPtr< EventMetaData > m_eventMetaDataPtr
Global EventMetaData for run number and event number.
TCanvas * m_c_info
The canvas hold the basic DQM info.
static bool hnamePatternMatch(std::string pattern, const std::string &text)
Pattern match for histogram name.
unsigned int m_run_idx
Index in the list of runs, events and files.
static void ExtractNEvent(std::vector< TH1 * > &hs)
Extract event processed from daq histogram, called from input module.
static void clearHistList(void)
Clears the list of histograms.
static void clearRefList(void)
Clears the list of ref histograms.
DQMHistAnalysisModule()
Constructor / Destructor.
static bool addHist(const std::string &dirname, const std::string &histname, TH1 *h)
Add histogram.
static void ExtractRunType(std::vector< TH1 * > &hs)
Extract Run Type from histogram title, called from input module.
static void initHistListBeforeEvent(void)
Reset the list of histograms.
void setDescription(const std::string &description)
Sets the description of the module.
Definition Module.cc:214
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.