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