Belle II Software prerelease-10-00-00a
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.
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.
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.