Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JGizmoToolkit.hh
Go to the documentation of this file.
1 #ifndef __JGIZMOTOOLKIT__
2 #define __JGIZMOTOOLKIT__
3 
4 #include <string>
5 #include <map>
6 #include <cmath>
7 
8 #include "TError.h"
9 #include "TFile.h"
10 #include "TClass.h"
11 #include "TObject.h"
12 #include "TKey.h"
13 #include "TH1.h"
14 #include "TH2.h"
15 #include "TGraph.h"
16 #include "TGraph2D.h"
17 #include "TString.h"
18 #include "TRegexp.h"
19 #include "TFormula.h"
20 #include "TIterator.h"
21 #include "TMethod.h"
22 #include "TMethodCall.h"
23 #include "TAxis.h"
24 #include "TMath.h"
25 
26 #include "JLang/JException.hh"
27 #include "JGizmo/JRootObjectID.hh"
28 
30 
31 
32 /**
33  * \author mdejong
34  */
35 
36 namespace JGIZMO {}
37 namespace JPP { using namespace JGIZMO; }
38 
39 /**
40  * Auxiliary applications for use of ROOT and more.
41  */
42 namespace JGIZMO {
43 
44  using JLANG::JParseError;
47 
48 
49  /**
50  * Auxiliary data structure for JOpera1D.cc and JOpera2D.cc applications.
51  */
52  struct JOpera {
53  //
54  // Histogram name.
55  //
56  static const char* const SAME_AS_OPERATION() { return "%"; } //!< Set name of output histogram to name of operation
57  static const char* const SAME_AS_INPUT() { return "="; } //!< Set name of output histogram to name of input histogram
58 
59  //
60  // Histogram operations.
61  //
62  static const char* const Add() { return "Add"; } //!< ROOT TH1::Add
63  static const char* const add() { return "add"; } //!< Add contents with lookup bin in second histogram
64  static const char* const Subtract() { return "Subtract"; } //!< ROOT TH1::Subtract
65  static const char* const subtract() { return "subtract"; } //!< Subtract contents with lookup bin in second histogram
66  static const char* const Multiply() { return "Multiply"; } //!< ROOT TH1::Multiply
67  static const char* const multiply() { return "multiply"; } //!< Multiply contents with lookup bin in second histogram
68  static const char* const Divide() { return "Divide"; } //!< ROOT TH1::Divide
69  static const char* const divide() { return "divide"; } //!< Divide contents with lookup bin in second histogram
70  static const char* const efficiency() { return "efficiency"; } //!< Divide contents and multiply errors with inefficiency
71  static const char* const stdev() { return "stdev"; } //!< Set contents to standard deviation
72  static const char* const sqrt() { return "sqrt"; } //!< Set contents to signed difference between squares
73  };
74 
75 
76  /**
77  * Get TFile pointer.\n
78  * The TFile pointer of an already opened file is recovered, else a new file is opened.
79  *
80  * \param file_name file name
81  * \param option TFile::Open option
82  * \return pointer to TFile
83  */
84  inline TFile* getFile(const std::string& file_name, const std::string& option = "exist")
85  {
86  using namespace std;
87 
88  gErrorIgnoreLevel = kError;
89 
90  static map<string, TFile*> zmap;
91 
92  map<string, TFile*>::iterator i = zmap.find(file_name);
93 
94  if (i == zmap.end() || i->second == NULL || !i->second->IsOpen()) {
95 
96  TFile* file = TFile::Open(file_name.c_str(), option.c_str());
97 
98  zmap[file_name] = file;
99 
100  return file;
101 
102  } else {
103 
104  return i->second;
105  }
106  }
107 
108 
109  /**
110  * Get TDirectory pointer.\n
111  * The TFile pointer of an already opened file is recovered, else a new file is opened.
112  *
113  * \param id identifier
114  * \return pointer to TDirectory
115  */
116  inline TDirectory* getDirectory(const JRootObjectID& id)
117  {
118  TFile* in = getFile(id.getFilename().c_str(), "exist");
119 
120  if (in == NULL || !in->IsOpen()) {
121  return NULL;
122  }
123 
124  if (id.getDirectory() != "")
125  return in->GetDirectory(id.getDirectory());
126  else
127  return in;
128  }
129 
130 
131  /**
132  * Get TObject.
133  *
134  * \param id identifier
135  * \return pointer to TObject (or NULL)
136  */
137  inline TObject* getObject(const JRootObjectID& id)
138  {
139  TDirectory* dir = getDirectory(id);
140 
141  if (dir != NULL) {
142 
143  const TRegexp regexp(id.getObjectName());
144 
145  TIter iter(dir->GetListOfKeys());
146 
147  for (TKey* key; (key = (TKey*) iter.Next()) != NULL; ) {
148 
149  const TString tag(key->GetName());
150 
151  // option match
152 
153  if (tag.Index(regexp) != -1) {
154  return key->ReadObj();
155  }
156  }
157  }
158 
159  return NULL;
160  }
161 
162 
163  /**
164  * Get drawing option of TH1.
165  *
166  * \param object pointer to TObject
167  * \return true if TH1 looks a line; else false
168  */
169  inline bool isTAttLine(const TObject* object)
170  {
171  const TH1* h1 = dynamic_cast<const TH1*>(object);
172 
173  if (h1 != NULL) {
174 
175  if (h1->GetSumw2N()) {
176 
177  for (Int_t i = 1; i <= h1->GetNbinsX(); ++i) {
178 
179  if (h1->GetBinError(i) != 0.0) {
180  return false;
181  }
182  }
183  }
184 
185  return true;
186 
187  } else {
188 
189  return false;
190  }
191  }
192 
193 
194  /**
195  * Get result of given textual formula.\n
196  * The formula may contain names of member methods of the object pointed to.
197  * These methods should have no arguments and the return type <tt>Double_t</tt>.
198  * Example:
199  * <pre>
200  * getResult("1.0/GetEntries", TH1*);
201  * </pre>
202  *
203  * \param text text
204  * \param object pointer to object
205  * \return value
206  */
207  inline Double_t getResult(const TString& text, TObject* object = NULL)
208  {
209  TString buffer(text);
210 
211  if (object != NULL) {
212 
213  TClass* p = TClass::GetClass(object->ClassName());
214 
215  if (p != NULL) {
216 
217  TIterator* iter = p->GetListOfAllPublicMethods()->MakeIterator();
218 
219  for (TMethod* method; (method = (TMethod*) iter->Next()) != NULL; ) {
220 
221  if (buffer.Contains(method->GetName())) {
222 
223  Double_t value;
224 
225  TMethodCall(p, method->GetName(), NULL).Execute(object, value);
226 
227  buffer.ReplaceAll(method->GetName(), TString::Format("%f", value));
228  }
229  }
230  }
231  }
232 
233  return TFormula("/tmp", buffer.Data()).Eval(0.0);
234  }
235 
236 
237  /**
238  * Get result of given textual formula.\n
239  * The formula may contain names of member methods of the object pointed to.
240  * These methods should have no arguments and the return type <tt>Double_t</tt>.
241  * Example:
242  * <pre>
243  * getResult("1.0/GetEntries", TH1*);
244  * </pre>
245  *
246  * \param text text
247  * \param object pointer to object
248  * \return value
249  */
250  inline Double_t getResult(const std::string& text, TObject* object = NULL)
251  {
252  return getResult(TString(text.c_str()), object);
253  }
254 
255 
256  /**
257  * Get parameter number from text string.\n
258  * The number corresponds to the value <tt>[0-9]*</tt> in the expression <tt>"p[0-9]* = .."</tt>.
259  *
260  * \param text text
261  * \return parameter number
262  */
263  inline int getParameter(const std::string& text)
264  {
265  const char* regexp("p[0-9]* *=");
266 
267  TString buffer(text.c_str());
268 
269  buffer = buffer(TRegexp(regexp));
270  buffer = buffer(1, buffer.Length() - 2);
271 
272  if (!buffer.IsDigit()) {
273  THROW(JParseError, "Text is not a number " << text << ' ' << regexp);
274  }
275 
276  return buffer.Atoi();
277  }
278 
279 
280  /**
281  * Get parameter value from text string.\n
282  * The formula may contain names of member methods of the object pointed to.
283  * These methods should have no arguments and the return type <tt>Double_t</tt>.
284  * Example:
285  * <pre>
286  * getValue("p[..] = 2*GetMaximum", TH1*);
287  * </pre>
288  *
289  * \param text text
290  * \param object pointer to object
291  * \return value
292  */
293  inline Double_t getValue(const std::string& text, TObject* object = NULL)
294  {
295  const char* regexp("=.*");
296 
297  TString buffer(text.c_str());
298 
299  buffer = buffer(TRegexp(regexp));
300  buffer = buffer(1, buffer.Length() - 1);
301 
302  return getResult(std::string(buffer), object);
303  }
304 
305 
306  /**
307  * Make axis logarithmic (e.g. after filling with log10()).
308  *
309  * \param axis axis
310  */
311  inline void setLogarithm(TAxis* axis)
312  {
313  if (axis != NULL) {
314 
315  const int N = axis->GetNbins();
316  Double_t buffer[N+1];
317 
318  buffer[0] = TMath::Power(10.0, axis->GetBinLowEdge(1));
319 
320  for (int i = 1; i <= N; ++i) {
321  buffer[i] = TMath::Power(10.0, axis->GetBinLowEdge(i) + axis->GetBinWidth(i));
322  }
323 
324  axis->Set(N, buffer);
325  }
326  }
327 
328 
329  /**
330  * Convert 1D histogram to PDF.
331  *
332  * Possible options are:
333  * - N normalise to histogram contents;
334  * - W divide by bin width;
335  * - E convert also bin errors.
336  *
337  * \param h1 histogram
338  * \param option option
339  * \param factor scaling factor
340  */
341  inline void convertToPDF(TH1& h1, const std::string& option = "NW", const double factor = 1.0)
342  {
343  using namespace std;
344 
345  const bool normalise = (option.find('N') != string::npos || option.find('n') != string::npos);
346  const bool bin_width = (option.find('W') != string::npos || option.find('w') != string::npos);
347  const bool use_error = (option.find('E') != string::npos || option.find('e') != string::npos);
348 
349  Double_t W = 1.0;
350 
351  if (normalise) {
352 
353  W = 0.0;
354 
355  for (Int_t i = 1; i <= h1.GetXaxis()->GetNbins(); ++i) {
356  W += h1.GetBinContent(i);
357  }
358  }
359 
360  if (W != 0.0) {
361 
362  for (Int_t i = 1; i <= h1.GetXaxis()->GetNbins(); ++i) {
363 
364  const Double_t w = W * (bin_width ? h1.GetXaxis()->GetBinWidth(i) : 1.0);
365 
366  h1.SetBinContent(i, h1.GetBinContent(i) * factor / w);
367 
368  if (use_error) {
369  h1.SetBinError(i, h1.GetBinError(i) * factor / w);
370  }
371  }
372  }
373  }
374 
375 
376  /**
377  * Convert 2D histogram to PDF.
378  *
379  * Possible options are:
380  * - N normalise to histogram contents;
381  * - X convert x-axis to PDF;
382  * - Y convert y-axis to PDF;
383  * - W divide by bin width;
384  * - E convert also bin errors.
385  *
386  * \param h2 histogram
387  * \param option option
388  * \param factor scaling factor
389  */
390  inline void convertToPDF(TH2& h2, const std::string& option = "NXYW", const double factor = 1.0)
391  {
392  using namespace std;
393 
394  const bool normalise = (option.find('N') != string::npos || option.find('n') != string::npos);
395  const bool X = (option.find('X') != string::npos || option.find('x') != string::npos);
396  const bool Y = (option.find('Y') != string::npos || option.find('y') != string::npos);
397  const bool bin_width = (option.find('W') != string::npos || option.find('w') != string::npos);
398  const bool use_error = (option.find('E') != string::npos || option.find('e') != string::npos);
399 
400  Double_t W = 1.0;
401 
402  if (X && Y) {
403 
404  if (normalise) {
405 
406  W = 0.0;
407 
408  for (Int_t i = 1; i <= h2.GetXaxis()->GetNbins(); ++i) {
409  for (Int_t j = 1; j <= h2.GetYaxis()->GetNbins(); ++j) {
410  W += h2.GetBinContent(i,j);
411  }
412  }
413  }
414 
415  if (W != 0.0) {
416 
417  for (Int_t i = 1; i <= h2.GetXaxis()->GetNbins(); ++i) {
418  for (Int_t j = 1; j <= h2.GetYaxis()->GetNbins(); ++j) {
419 
420  const Double_t w = W * (bin_width ? h2.GetXaxis()->GetBinWidth(i) * h2.GetYaxis()->GetBinWidth(j) : 1.0);
421 
422  h2.SetBinContent(i, j, h2.GetBinContent(i,j) * factor / w);
423 
424  if (use_error) {
425  h2.SetBinError(i, j, h2.GetBinError(i,j) * factor / w);
426  }
427  }
428  }
429  }
430 
431  } else if (X) {
432 
433  for (Int_t j = 1; j <= h2.GetYaxis()->GetNbins(); ++j) {
434 
435  if (normalise) {
436 
437  W = 0.0;
438 
439  for (Int_t i = 1; i <= h2.GetXaxis()->GetNbins(); ++i) {
440  W += h2.GetBinContent(i,j);
441  }
442  }
443 
444  if (W != 0.0) {
445 
446  for (Int_t i = 1; i <= h2.GetXaxis()->GetNbins(); ++i) {
447 
448  const Double_t w = W * (bin_width ? h2.GetXaxis()->GetBinWidth(i) : 1.0);
449 
450  h2.SetBinContent(i, j, h2.GetBinContent(i,j) * factor / w);
451 
452  if (use_error) {
453  h2.SetBinError(i, j, h2.GetBinError(i,j) * factor / w);
454  }
455  }
456  }
457  }
458 
459  } else if (Y) {
460 
461  for (Int_t i = 1; i <= h2.GetXaxis()->GetNbins(); ++i) {
462 
463  if (normalise) {
464 
465  W = 0.0;
466 
467  for (Int_t j = 1; j <= h2.GetYaxis()->GetNbins(); ++j) {
468  W += h2.GetBinContent(i,j);
469  }
470  }
471 
472  if (W != 0.0) {
473 
474  for (Int_t j = 1; j <= h2.GetYaxis()->GetNbins(); ++j) {
475 
476  const Double_t w = W * (bin_width ? h2.GetYaxis()->GetBinWidth(j) : 1.0);
477 
478  h2.SetBinContent(i, j, h2.GetBinContent(i,j) / w);
479 
480  if (use_error) {
481  h2.SetBinError(i, j, h2.GetBinError(i,j) / w);
482  }
483  }
484  }
485  }
486  }
487  }
488 
489 
490  /**
491  * Set limits of TGraph.
492  *
493  * \param g1 graph
494  */
495  inline void setLimits(TGraph& g1)
496  {
497  using namespace std;
498 
499  Double_t ymin = +numeric_limits<Double_t>::max();
500  Double_t ymax = -numeric_limits<Double_t>::max();
501 
502  for (Int_t i = 0; i != g1.GetN(); ++i) {
503 
504  const Double_t y = g1.GetY()[i];
505 
506  if (y > ymax) { ymax = y; }
507  if (y < ymin) { ymin = y; }
508  }
509 
510  g1.SetMinimum(ymin);
511  g1.SetMaximum(ymax);
512  }
513 
514 
515  /**
516  * Set limits of TGraph2D.
517  *
518  * \param g2 graph
519  */
520  inline void setLimits(TGraph2D& g2)
521  {
522  using namespace std;
523 
524  Double_t zmin = +numeric_limits<Double_t>::max();
525  Double_t zmax = -numeric_limits<Double_t>::max();
526 
527  for (Int_t i = 0; i != g2.GetN(); ++i) {
528 
529  const Double_t z = g2.GetZ()[i];
530 
531  if (z > zmax) { zmax = z; }
532  if (z < zmin) { zmin = z; }
533  }
534 
535  g2.SetMinimum(zmin);
536  g2.SetMaximum(zmax);
537  }
538 
539 
540  /**
541  * Set axis range.
542  *
543  * \param xmin lower limit (I/O)
544  * \param xmax upper limit (I/O)
545  * \param logx logarithmic
546  */
547  inline void setRange(double& xmin,
548  double& xmax,
549  const bool logx)
550  {
551  if (logx) {
552  xmin = log(xmin);
553  xmax = log(xmax);
554  }
555 
556  double dx = (xmax - xmin) * 0.1;
557 
558  if (xmin > dx || xmin < 0.0)
559  xmin -= dx;
560  else
561  xmin = 0.0;
562 
563  xmax += dx;
564 
565  if (logx) {
566  xmin = exp(xmin);
567  xmax = exp(xmax);
568  }
569  }
570 
571 
572  /**
573  * initialize axis with PMT address labels
574  *
575  * \param axis axis
576  * \param memo default module address map
577  */
578  inline void setAxisLabels(TAxis *axis, const JModuleAddressMap& memo)
579  {
580  using namespace JPP;
581 
582  if (axis->GetNbins() == (int) memo.size()) {
583 
584  for (int i = 0; i < axis->GetNbins(); i++) {
585 
586  const JPMTPhysicalAddress& pmtAddress = memo[i];
587 
588  axis->SetBinLabel(i + 1, TString(pmtAddress.toString()));
589  }
590 
591  } else {
592 
593  THROW(JValueOutOfRange, "Number of bins " << axis->GetNbins() << " != " << memo.size());
594  }
595  }
596 }
597 
598 #endif
static const char *const sqrt()
Set contents to signed difference between squares.
Exceptions.
TObject * getObject(const JRootObjectID &id)
Get TObject.
double getValue(const JScale_t scale)
Get numerical value corresponding to scale.
Definition: JScale.hh:47
int getParameter(const std::string &text)
Get parameter number from text string.
static const char *const Divide()
ROOT TH1::Divide.
static const char *const Subtract()
ROOT TH1::Subtract.
static const char *const SAME_AS_INPUT()
Set name of output histogram to name of input histogram.
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:633
Definition: JRoot.hh:19
void setLimits(TGraph &g1)
Set limits of TGraph.
static const char *const subtract()
Subtract contents with lookup bin in second histogram.
Auxiliary class to handle file name, ROOT directory and object name.
static const char *const stdev()
Set contents to standard deviation.
void setLogarithm(TAxis *axis)
Make axis logarithmic (e.g.
bool isTAttLine(const TObject *object)
Get drawing option of TH1.
static const char *const efficiency()
Divide contents and multiply errors with inefficiency.
static const char *const Add()
ROOT TH1::Add.
Lookup table for PMT addresses in optical module.
static const char *const multiply()
Multiply contents with lookup bin in second histogram.
TFile * getFile(const std::string &file_name, const std::string &option="exist")
Get TFile pointer.
static const char *const add()
Add contents with lookup bin in second histogram.
Auxiliary data structure for JOpera1D.cc and JOpera2D.cc applications.
Double_t getResult(const TString &text, TObject *object=NULL)
Get result of given textual formula.
void convertToPDF(TH1 &h1, const std::string &option="NW", const double factor=1.0)
Convert 1D histogram to PDF.
void setAxisLabels(TAxis *axis, const JModuleAddressMap &memo)
initialize axis with PMT address labels
static const char *const Multiply()
ROOT TH1::Multiply.
static const char *const SAME_AS_OPERATION()
Set name of output histogram to name of operation.
void setRange(double &xmin, double &xmax, const bool logx)
Set axis range.
static const char *const divide()
Divide contents with lookup bin in second histogram.
Exception for parsing value.
Definition: JException.hh:162
TDirectory * getDirectory(const JRootObjectID &id)
Get TDirectory pointer.
std::string getFilename(const std::string &file_name)
Get file name part, i.e.
Definition: JeepToolkit.hh:85
Exception for accessing a value in a collection that is outside of its range.
Definition: JException.hh:144
Double_t g1(const Double_t x)
Function.
Definition: JQuantiles.cc:25