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