JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwHistogramHelper.cc
Go to the documentation of this file.
1/// @file QwHistogramHelper.cc
2/// @brief Handler class for histogram/tree trim parameter files and
3/// histogram and Tree branch creation
4///
5/// This class was originally written to be instantiated as a
6/// global object, which all classes containing histograms would
7/// use as an external object.
8/// It could be repurposed to have a single instance per class,
9/// but that would probably involve increasing the number of
10/// histogram parameter files.
11
12#include "QwHistogramHelper.h"
13
14// Qweak headers
15#include "QwLog.h"
16
17/// Globally defined instance of the QwHistogramHelper class.
19
20
21const Double_t QwHistogramHelper::fInvalidNumber = -1.0e7;
22const TString QwHistogramHelper::fInvalidName = "EmptyEmpty";
23
25{
26 // Define the histogram and tree options
27 options.AddOptions()
28 ("enable-tree-trim", po::value<bool>()->default_bool_value(false),
29 "enable trimmed trees");
30
31 options.AddOptions()
32 ("enable-histo-trim", po::value<bool>()->default_bool_value(false),
33 "enable trimmed histograms");
34
35 options.AddOptions()(
36 "tree-trim-file",
37 po::value<string>()->default_value("tree_trim.in"),
38 "trimmed tree file name"
39 );
40
41 // What about QwTracking ?
42 // Monday, October 18 23:19:09 EDT 2010, jhlee
43 options.AddOptions()(
44 "histo-trim-file",
45 po::value<string>()->default_value("parity_hist.in"),
46 "trimmed histo file name"
47 );
48
49}
50
52{
53 //enable the tree trim when --enable-tree-trim in offline mode or --enable-mapfile for real time mode
54 // fTrimDisable =!( options.GetValue<bool>("enable-tree-trim") || options.GetValue<bool>("enable-mapfile"));
55 // fTrimHistoEnable = options.GetValue<bool>("enable-histo-trim") || options.GetValue<bool>("enable-mapfile");
56 fTrimDisable =!( options.GetValue<bool>("enable-tree-trim"));
57 fTrimHistoEnable = options.GetValue<bool>("enable-histo-trim");
58
59 if (fTrimDisable)
60 QwMessage <<"tree-trim is disabled"<<QwLog::endl;
61 else
62 QwMessage <<"tree-trim is enabled"<<QwLog::endl;
63
65 QwMessage <<"RT Mode: histo-trim is enabled "<<QwLog::endl;
66 else
67 QwMessage <<"histo-trim is disabled "<<QwLog::endl;
68
69 // Process trim file options
70 if (options.HasValue("tree-trim-file"))
71 LoadTreeParamsFromFile(options.GetValue<string>("tree-trim-file"));
72 if (options.HasValue("histo-trim-file"))
73 LoadHistParamsFromFile(options.GetValue<string>("histo-trim-file"));
74}
75
76
78{
79 /// Decodes the histogram parameters from the current line of
80 /// a QwParameter file.
81 /// If the line cannot be decoded, the name is returned as
82 /// fInvalidName.
83 HistParams tmpstruct;
84 tmpstruct.name_title = fInvalidName;
85
86 std::string tmpname = mapstr.GetTypedNextToken<std::string>();
87 std::string tmptype = mapstr.GetTypedNextToken<std::string>();
88 if (tmptype != "TH1F" && tmptype != "TH2F"
89 && tmptype != "TProfile" && tmptype != "TProfile2D"){
90 QwError << "QwHistogramHelper::GetHistParamsFromFile: Unrecognized histogram type: "
91 << tmptype << " (tmpname==" << tmpname <<")"<< QwLog::endl;
92 } else {
93 tmpstruct.expression = tmpname;
94 tmpstruct.name_title = tmpname;
95 tmpstruct.type = tmptype;
96 tmpstruct.x_nbins = mapstr.GetTypedNextToken<Int_t>();
97 tmpstruct.x_min = mapstr.GetTypedNextToken<Float_t>();
98 tmpstruct.x_max = mapstr.GetTypedNextToken<Float_t>();
99 if (tmptype == "TH2F") {
100 tmpstruct.y_nbins = mapstr.GetTypedNextToken<Int_t>();
101 tmpstruct.y_min = mapstr.GetTypedNextToken<Float_t>();
102 tmpstruct.y_max = mapstr.GetTypedNextToken<Float_t>();
103 } else if (tmptype == "TProfile") {
104 tmpstruct.y_nbins = 0;
105 tmpstruct.y_min = mapstr.GetTypedNextToken<Float_t>();
106 tmpstruct.y_max = mapstr.GetTypedNextToken<Float_t>();
107 } else {
108 tmpstruct.y_nbins = 0;
109 tmpstruct.y_min = 0.0;
110 tmpstruct.y_max = 0.0;
111 }
112 tmpstruct.xtitle = mapstr.GetTypedNextToken<TString>();
113 tmpstruct.ytitle = mapstr.GetTypedNextToken<TString>();
114
115 std::string tmpmin = mapstr.GetTypedNextToken<std::string>();
116 if (tmpmin.find_first_not_of("-+1234567890.eE") == std::string::npos) {
117 // tmpmin is a number
118 tmpstruct.min = atof(tmpmin.c_str());
119 } else {
120 tmpstruct.min = fInvalidNumber;
121 }
122 std::string tmpmax = mapstr.GetTypedNextToken<std::string>();
123 if (tmpmax.find_first_not_of("-+1234567890.eE") == std::string::npos) {
124 // tmpmax is a number
125 tmpstruct.max = atof(tmpmax.c_str());
126 } else {
127 tmpstruct.max = fInvalidNumber;
128 }
129 }
130 return tmpstruct;
131}
132
133
134
135void QwHistogramHelper::LoadHistParamsFromFile(const std::string& filename)
136{
137 fInputFile = filename;
138
139 fDEBUG = 0;
140 //fDEBUG = 1;
141
142 if (fDEBUG) std::cout<< "file name "<<fInputFile<<std::endl;
143 //Important to empty the fHistParams to reload the real time histo definition file
145 fHistParams.clear();
146
147 // Open the file
148 QwParameterFile mapstr(filename);
149 while (mapstr.ReadNextLine()){
150 mapstr.TrimComment(); // Remove everything after a comment character.
151 mapstr.TrimWhitespace(); // Get rid of leading and trailing spaces.
152 if (mapstr.LineIsEmpty()) continue;
153
154 HistParams tmpstruct = GetHistParamsFromLine(mapstr);
155 if (tmpstruct.name_title != fInvalidName){
156 fHistParams.push_back(tmpstruct);
157 if (fDEBUG) {
158 QwMessage << fHistParams.back() << QwLog::endl;
159 }
160 }
161 }
162
163 // Sort the histogram parameter definitions
164 sort(fHistParams.begin(), fHistParams.end());
165}
166
167
169{
170 for (std::vector<HistParams>::const_iterator h = fHistParams.begin();
171 h != fHistParams.end(); ++h) {
172 QwMessage << *h << QwLog::endl;
173 }
174}
175
176
177void QwHistogramHelper::LoadTreeParamsFromFile(const std::string& filename)
178{
179 TString devicename;
180 TString moduletype;
181 TString subsystemname;
182 std::unique_ptr<QwParameterFile> section = nullptr;
183 std::unique_ptr<QwParameterFile> module = nullptr;
184 std::vector<TString> TrimmedList;//stores the list of elements for each module
185 std::vector<std::vector<TString> > ModulebyTrimmedList;//stores the list of elements for each module
186 std::vector<TString> ModuleList;//stores the list of modules for each subsystem
187 fDEBUG = 0;
188 //fDEBUG = 1;
189 if (fTrimDisable)
190 return;
191 QwMessage << "Tree trim definition file for Offline Engine"<< QwLog::endl;
192 QwParameterFile mapstr(filename.c_str()); //Open the file
193
194 fTreeTrimFileLoaded=!mapstr.IsEOF();
195 fSubsystemList.clear();
196 fModuleList.clear();
197 fVQWKTrimmedList.clear();
198
199 while ( (section=mapstr.ReadNextSection(subsystemname)) ){
200 if (subsystemname=="DEVICELIST")//done with VQWK element trimming
201 break;
202 fSubsystemList.push_back(subsystemname);
203 QwMessage <<"Subsystem found "<<subsystemname<<QwLog::endl;
204
205 ModuleList.clear();
206 ModulebyTrimmedList.clear();
207 while ( (module=section->ReadNextModule(moduletype)) ){
208
209 ModuleList.push_back(moduletype);
210 QwMessage <<"Module found "<<moduletype<<QwLog::endl;
211 TrimmedList.clear();
212 while (module->ReadNextLine()){
213 module->TrimComment('#'); // Remove everything after a '#' character.
214 module->TrimWhitespace(); // Get rid of leading and trailing spaces.
215 if (module->LineIsEmpty()) continue;
216 devicename=(module->GetLine()).c_str();
217 TrimmedList.push_back(devicename);
218 if (fDEBUG) {
219 QwMessage <<"data element "<<devicename<<QwLog::endl;
220 }
221 }
222 ModulebyTrimmedList.push_back(TrimmedList);
223
224
225 }
226 fModuleList.push_back(ModuleList);
227 fVQWKTrimmedList.push_back(ModulebyTrimmedList);
228
229
230 }
231 //Start decoding the device list in the section [DEVICELIST]
232 fTreeParams.clear();
233 while (section->ReadNextLine()){
234 section->TrimComment('#'); // Remove everything after a '#' character.
235 section->TrimWhitespace(); // Get rid of leading and trailing spaces.
236 if (section->LineIsEmpty()) continue;
237 devicename=(section->GetLine()).c_str();
238 fTreeParams.push_back(std::pair<TString,TRegexp>(devicename,devicename));
239 if (fDEBUG)
240 QwMessage <<"device name "<<devicename<<QwLog::endl;
241
242 }
243
244 //exit(1);
245
246}
247
248
250{
251 HistParams tmpstruct, matchstruct;
252 tmpstruct.name_title = fInvalidName;
253
254 std::vector<int> matches;
255 for (size_t i = 0; i < fHistParams.size(); i++) {
256 if (DoesMatch(histname,fHistParams.at(i).expression)) {
257 matchstruct = fHistParams.at(i);
258 if (tmpstruct.name_title == fInvalidName) {
259 tmpstruct = matchstruct;
260 tmpstruct.name_title = histname;
261 matches.push_back(i);
262 break; // enabled (to get warnings for multiple definitions, disable)
263 } else if (tmpstruct.nbins == matchstruct.nbins
264 && tmpstruct.min == matchstruct.min
265 && tmpstruct.max == matchstruct.max
266 && tmpstruct.x_nbins == matchstruct.x_nbins
267 && tmpstruct.x_min == matchstruct.x_min
268 && tmpstruct.x_max == matchstruct.x_max
269 && tmpstruct.y_nbins == matchstruct.y_nbins
270 && tmpstruct.y_min == matchstruct.y_min
271 && tmpstruct.y_max == matchstruct.y_max) {
272 //matches.push_back(i); // disabled (to enable, also remove break above)
273 }
274 }
275 }
276
277 // Warn when multiple identical matches were found
278 if (matches.size() > 1) {
279 QwWarning << "Multiple identical matches for histogram " << histname << ":" << QwLog::endl;
280 for (size_t i = 0; i < matches.size(); i++) {
281 QwWarning << " " << fHistParams.at(matches.at(i)).name_title << QwLog::endl;
282 }
283 }
284
285 fDEBUG = 0;
286 if (fDEBUG) {
287 QwMessage << "Finding histogram definition from: " << histname << QwLog::endl;
288 QwMessage << tmpstruct << QwLog::endl;
289 }
290 if (tmpstruct.name_title == fInvalidName && !fTrimHistoEnable) {
291 std::cerr << "GetHistParamsFromList: We haven't found a match of the histogram name: "
292 << histname << std::endl;
293 std::cerr << " Please check the input file "
294 << fInputFile << std::endl;
295 exit(1);
296 }
297 return tmpstruct;
298}
299
300
301Bool_t QwHistogramHelper::MatchDeviceParamsFromList(const std::string& devicename)
302{
303 Int_t matched;
304 matched=0;
305 if (!fTreeTrimFileLoaded || fTrimDisable){//if file is not loaded or trim tree is disable by cmd flag
306
307 return kTRUE;//return true for all devices
308 }
309 for (size_t i = 0; i < fTreeParams.size(); i++) {
310 if (DoesMatch(devicename,fTreeParams.at(i).second)) {
311 if (fDEBUG)
312 QwMessage << " Branch name found " << fTreeParams.at(i).first << QwLog::endl;
313 matched++;
314 }
315 }
316
317 // Warn when multiple identical matches were found
318 if (matched > 1) {
319 QwWarning << "Multiple identical matches for branch name " << devicename << ":" << QwLog::endl;
320 }
321 if (matched)
322 return kTRUE;
323 else
324 return kFALSE;
325}
326
328 const std::string& subsystemname,
329 const std::string& moduletype,
330 const std::string& elementname)
331{
332 Int_t matched = 0;
333 if (!fTreeTrimFileLoaded || fTrimDisable){//if file is not loaded or trim tree is disable by cmd flag
334
335 return kTRUE;//return true for all devices
336 }
337
338 for (size_t j = 0; j < fSubsystemList.size(); j++) {
339 // QwMessage << " Subsystem name "<< subsystemname<< " From List "<<fSubsystemList.at(j) << QwLog::endl;
340 if (DoesMatch(subsystemname,fSubsystemList.at(j))){
341 for (size_t i = 0; i < fModuleList.at(j).size(); i++) {
342 if (DoesMatch(moduletype,fModuleList.at(j).at(i))) {
343 for (size_t k = 0; k < fVQWKTrimmedList.at(j).at(i).size(); k++) {
344 if (DoesMatch(elementname,fVQWKTrimmedList.at(j).at(i).at(k))){
345 if (fDEBUG)
346 QwMessage << "Subsystem " << fSubsystemList.at(j)
347 << " Module Type " << fModuleList.at(j).at(i)
348 << " Element " << fVQWKTrimmedList.at(j).at(i).at(k)
349 << QwLog::endl;
350 matched++;
351 }
352 }
353 break;
354 }
355 }
356 }
357 }
358
359
360 // Warn when multiple identical matches were found
361 if (matched > 1) {
362 QwWarning << "Multiple identical matches for element name " <<elementname << ":" << QwLog::endl;
363 }
364 if (matched)
365 return kTRUE;
366 else
367 return kFALSE;
368}
369
370
372 const std::string& filename,
373 const TString& histname)
374{
375 // The idea is to look up the input file and get the needed histogram parameters
376 // For each histogram we are going to scan the input file once, which
377 // is not very efficient. But we only construct histograms once per run ...
378
379 HistParams tmpstruct;
380 tmpstruct.name_title = fInvalidName;
381
382 // Open the file
383 QwParameterFile mapstr(filename.c_str());
384 while (mapstr.ReadNextLine()) {
385 mapstr.TrimComment(); // Remove everything after a comment character
386 mapstr.TrimWhitespace(); // Get rid of leading and trailing spaces
387 if (mapstr.LineIsEmpty()) continue;
388
389 TString tmpname = mapstr.GetTypedNextToken<TString>();
390 TString tmptype = mapstr.GetTypedNextToken<TString>();
391 if (tmptype != "TH1F" && tmptype != "TH2F") {
392 QwError << "QwHistogramHelper::GetHistParamsFromFile: Unrecognized histogram type: "
393 << tmptype << " (tmpname==" << tmpname <<")"<< QwLog::endl;
394 continue;
395 }
396
397 if (DoesMatch(histname,tmpname)) {
398 // Found a match
399 mapstr.RewindToLineStart();
400 tmpstruct = GetHistParamsFromLine(mapstr);
401 tmpstruct.name_title = histname;
402 }
403 }
404
405 if (fDEBUG) {
406 QwMessage << tmpstruct << QwLog::endl;
407 }
408 if (tmpstruct.name_title == fInvalidName && !fTrimHistoEnable) {
409 QwError << "GetHistParamsFromFile: We haven't found a match of the histogram name: "
410 << histname << QwLog::endl;
411 QwError << " Please check the input file "
412 << filename << QwLog::endl;
413 exit(1);
414 }
415 return tmpstruct;
416}
417
418Bool_t QwHistogramHelper::DoesMatch(const TString& s, const TRegexp& wildcard)
419{
420 // A very quick and dirty string matching routine using root
421 // TString and TRegExp functions. Require the string and wildcard string
422 // to have the SAME length to match (much risky if we don't require this),
423 // so the only wildcard you want to use here is ".".
424
425 static Ssiz_t len = 0;
426 if (wildcard.Index(s,&len) == 0 && len == s.Length()) {
427 // found a match!
428 return kTRUE;
429 } else
430 return kFALSE;
431}
432
433/////////////////////////////////////////////////////////////////////////////////////////
434
435TH2F* QwHistogramHelper::Construct2DHist(const TString& name_title)
436{
437 HistParams tmpstruct = GetHistParamsFromList(name_title);
438 return Construct2DHist(tmpstruct);
439}
440
441/////////////////////////////////////////////////////////////////////////////////////////
442
443TH1F* QwHistogramHelper::Construct1DHist(const TString& name_title)
444{
445 HistParams tmpstruct = GetHistParamsFromList(name_title);
446 return Construct1DHist(tmpstruct);
447}
448
449/////////////////////////////////////////////////////////////////////////////////////////
450
451TProfile2D* QwHistogramHelper::Construct2DProf(const TString& name_title)
452{
453 HistParams tmpstruct = GetHistParamsFromList(name_title);
454 return Construct2DProf(tmpstruct);
455}
456
457/////////////////////////////////////////////////////////////////////////////////////////
458
459TProfile* QwHistogramHelper::Construct1DProf(const TString& name_title)
460{
461 HistParams tmpstruct = GetHistParamsFromList(name_title);
462 return Construct1DProf(tmpstruct);
463}
464
465/////////////////////////////////////////////////////////////////////////////////////////
466
467TH2F* QwHistogramHelper::Construct2DHist(const std::string& inputfile, const TString& name_title)
468{
469 HistParams tmpstruct = GetHistParamsFromFile(inputfile, name_title);
470 return Construct2DHist(tmpstruct);
471}
472
473/////////////////////////////////////////////////////////////////////////////////////////
474
475TH1F* QwHistogramHelper::Construct1DHist(const std::string& inputfile, const TString& name_title)
476{
477 HistParams tmpstruct = GetHistParamsFromFile(inputfile, name_title);
478 return Construct1DHist(tmpstruct);
479}
480
481/////////////////////////////////////////////////////////////////////////////////////////
482
483TProfile2D* QwHistogramHelper::Construct2DProf(const std::string& inputfile, const TString& name_title)
484{
485 HistParams tmpstruct = GetHistParamsFromFile(inputfile, name_title);
486 return Construct2DProf(tmpstruct);
487}
488
489/////////////////////////////////////////////////////////////////////////////////////////
490
491TProfile* QwHistogramHelper::Construct1DProf(const std::string& inputfile, const TString& name_title)
492{
493 HistParams tmpstruct = GetHistParamsFromFile(inputfile, name_title);
494 return Construct1DProf(tmpstruct);
495}
496
497/////////////////////////////////////////////////////////////////////////////////////////
498
500{
501 TH1F* h1 = 0;
502 if (fTrimHistoEnable && params.name_title == fInvalidName) {
503 return h1;
504 }
505
506 h1 = new TH1F(params.name_title,
507 params.name_title,
508 params.x_nbins,
509 Double_t(params.x_min),Double_t(params.x_max));
510 h1->SetXTitle(params.xtitle);
511 h1->SetYTitle(params.ytitle);
512 // if(params.min!=fInvalidNumber) h1->SetMinimum(params.min);
513 // if(params.max!=fInvalidNumber) h1->SetMinimum(params.max);
514 return h1;
515}
516
517/////////////////////////////////////////////////////////////////////////////////////////
518
520{
521 TH2F* h2 = 0;
522 if (fTrimHistoEnable && params.name_title == fInvalidName) {
523 return h2;
524 }
525
526 h2 = new TH2F(params.name_title,
527 params.name_title,
528 params.x_nbins,
529 Double_t(params.x_min),Double_t(params.x_max),
530 params.y_nbins,
531 Double_t(params.y_min),Double_t(params.y_max));
532 h2->SetXTitle(params.xtitle);
533 h2->SetYTitle(params.ytitle);
534 // if (params.min != fInvalidNumber) h2->SetMinimum(params.min);
535 // if (params.max != fInvalidNumber) h2->SetMinimum(params.max);
536 return h2;
537}
538
539/////////////////////////////////////////////////////////////////////////////////////////
540
542{
543 TProfile* h1 = 0;
544 if (fTrimHistoEnable && params.name_title == fInvalidName) {
545 return h1;
546 }
547
548 h1 = new TProfile(params.name_title,
549 params.name_title,
550 params.x_nbins,
551 Double_t(params.x_min),Double_t(params.x_max),
552 Double_t(params.y_min),Double_t(params.y_max));
553 h1->SetMinimum(params.y_min);
554 h1->SetMaximum(params.y_max);
555 h1->SetXTitle(params.xtitle);
556 h1->SetYTitle(params.ytitle);
557 return h1;
558}
559
560/////////////////////////////////////////////////////////////////////////////////////////
561
563{
564 TProfile2D* h2 = 0;
565 if (fTrimHistoEnable && params.name_title == fInvalidName) {
566 return h2;
567 }
568
569 h2 = new TProfile2D(params.name_title,
570 params.name_title,
571 params.x_nbins,
572 Double_t(params.x_min),Double_t(params.x_max),
573 params.y_nbins,
574 Double_t(params.y_min),Double_t(params.y_max),
575 Double_t(params.z_min),Double_t(params.z_max));
576 h2->SetMinimum(params.z_min);
577 h2->SetMaximum(params.z_max);
578 h2->SetXTitle(params.xtitle);
579 h2->SetYTitle(params.ytitle);
580 return h2;
581}
Helper functions and utilities for ROOT histogram management.
QwHistogramHelper gQwHists
Globally defined instance of the QwHistogramHelper class.
A logfile class, based on an identical class in the Hermes analyzer.
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
Utility class for histogram creation and management.
void PrintHistParams() const
void LoadHistParamsFromFile(const std::string &filename)
std::vector< HistParams > fHistParams
std::vector< TString > fSubsystemList
static const TString fInvalidName
const HistParams GetHistParamsFromFile(const std::string &filename, const TString &histname)
const HistParams GetHistParamsFromList(const TString &histname)
std::vector< std::vector< std::vector< TString > > > fVQWKTrimmedList
void LoadTreeParamsFromFile(const std::string &filename)
Bool_t MatchVQWKElementFromList(const std::string &subsystemname, const std::string &moduletype, const std::string &devicename)
std::vector< std::vector< TString > > fModuleList
static const Double_t fInvalidNumber
static void DefineOptions(QwOptions &options)
Define the configuration options.
TProfile * Construct1DProf(const TString &name_title)
const HistParams GetHistParamsFromLine(QwParameterFile &mapstr)
Bool_t MatchDeviceParamsFromList(const std::string &devicename)
TProfile2D * Construct2DProf(const TString &name_title)
void ProcessOptions(QwOptions &options)
Process the configuration options.
TH1F * Construct1DHist(const TString &inputfile, const TString &name_title)
std::vector< std::pair< TString, TRegexp > > fTreeParams
Bool_t DoesMatch(const TString &s, const TRegexp &wildcard)
TH2F * Construct2DHist(const TString &inputfile, const TString &name_title)
Histogram parameter class.
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Command-line and configuration file options processor.
Definition QwOptions.h:141
T GetValue(const std::string &key)
Get a templated value.
Definition QwOptions.h:236
bool HasValue(const std::string &key)
Has this key been defined.
Definition QwOptions.h:229
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition QwOptions.h:170
Configuration file parser with flexible tokenization and search capabilities.
T GetTypedNextToken()
Get next token into specific type.
void TrimWhitespace(TString::EStripType head_tail=TString::kBoth)
void TrimComment(const char commentchar)
std::unique_ptr< QwParameterFile > ReadNextSection(std::string &secname, const bool keep_header=false)