Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
StandardLabels.C
Go to the documentation of this file.
1 
2 
3 
4 #include <stdio.h>
5 #include <time.h>
6 #include <iostream>
7 #include <fstream>
8 #include <cmath>
9 using namespace std;
10 
11 #include <TROOT.h>
12 #include <TLatex.h>
13 #include <TH2.h>
14 #include <TCanvas.h>
15 
16 //
17 // June 17, 2016 David Lawrence davidl@jlab.org
18 //
19 //
20 // The macros in this file can be used to add some standard labels to ROOT
21 // plots in the upper right hand corner. To use this, you should #include
22 // this file and then call StandardLabels(TH1*) passing in the currently
23 // displayed histogram (the one defining the axes). Here's an example:
24 //
25 // #include "StandardLabels.C"
26 //
27 // void MyMacro(void)
28 // {
29 // ...
30 // TH2D *hist = new TH2D("axes", ...
31 //
32 // // ... fill histogram ...
33 //
34 // hist->Draw();
35 // StandardLabels(hist, "#gammap#rightarrow#b_{1}#pi"); // second argument is optional
36 // }
37 //
38 // The labels include the date, creators initials, and svn revision number.
39 // The date and creator initials are generated automatically, but one may
40 // wish to replace that with static strings in the routines below. Similarly
41 // for the svn revision string which is always statically defined.
42 //
43 // WARNING: I've experienced problems with ROOT giving errors after running
44 // this a couple of times in the same session. Specifically, I've seen the following:
45 //
46 // !!!Fatal Error: Interpreter memory overwritten by illegal access.!!!
47 // !!!Terminate session!!!
48 //
49 // Oddly enough, this message came up on the 3rd invocation, but subsequent
50 // invocations in the same session gave no errors and everything seemed to
51 // work OK(??)
52 
53 void ConvertFromNDC1D(TLatex *obj, TH1D *h=NULL);
54 void ConvertFromNDC2D(TLatex *obj, TH2D *h=NULL);
55 
56 void StandardLabels1D(TH1D *axes=NULL, string mess1="", string mess2="", string mess3="", string mess4="");
57 void StandardLabels2D(TH2D *axes=NULL, string mess1="", string mess2="", string mess3="", string mess4="");
58 
59 
60 //----------------
61 // GetRevision
62 //----------------
63 string GetRevision(void)
64 {
65  // This will try and automatically find the svn revision number of
66  // the source pointed to by your HALLD_HOME environment variable.
67  // To fix the revision to a specific value, uncomment the following
68  // line and set it there.
69 
70  //return "git revision #c2a08eb";
71 
72  // Extract revision number using git and HALLD_HOME
73  string revision = "";
74  const char *HALLD_HOME = getenv("HALLD_HOME");
75  if(HALLD_HOME != NULL){
76  char cmd[1024];
77  sprintf(cmd, "git --git-dir=%s/.git rev-parse --short HEAD > .git_revision", HALLD_HOME);
78  system(cmd);
79  }
80  ifstream ifstr(".git_revision");
81  ifstr >> revision;
82  ifstr.close();
83 
84  return string("git revision #") + revision;
85 }
86 
87 //----------------
88 // GetDate
89 //----------------
90 string GetDate(void)
91 {
92  // uncomment the following line to use a static string for the date
93  //return string("January 4, 1970");
94 
95  clock_t t = time(NULL);
96  struct tm *tm = localtime(&t);
97  char str[256];
98  strftime(str, 256, "%B %e, %Y", tm);
99 
100  return string(str);
101 }
102 
103 //----------------
104 // GetInitials
105 //----------------
106 string GetInitials(void)
107 {
108  // uncomment the following line to use a static string for the creator's initials
109  //return string("AB");
110 
111  string initials;
112  const char *cmd = "finger $USER |grep \"Name:\" | awk '{print substr($4,1,1)substr($5,1,1)}' > .initials";
113  system(cmd);
114  ifstream ifstr(".initials");
115  ifstr >> initials;
116  ifstr.close();
117 
118  return initials;
119 }
120 
121 // <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
122 // ( you probably don't want to edit below here! )
123 // <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
124 
125 //----------------
126 // DateLabel
127 //----------------
128 void DateLabel(char *date_lab)
129 {
130  sprintf(date_lab,"%s %s", GetDate().c_str(), GetInitials().c_str());
131 }
132 
133 //----------------
134 // StandardLabels
135 //----------------
136 void StandardLabels(TH1 *h, string mess1="", string mess2="", string mess3="", string mess4="")
137 {
138  TH2D *h2d = dynamic_cast<TH2D*>(h);
139  if(h2d){
140  StandardLabels2D(h2d, mess1, mess2, mess3, mess4);
141  return;
142  }
143 
144  TH1D *h1d = dynamic_cast<TH1D*>(h);
145  if(h1d){
146  StandardLabels1D(h1d, mess1, mess2, mess3, mess4);
147  return;
148  }
149 }
150 
151 //----------------
152 // StandardLabels2D
153 //----------------
154 void StandardLabels2D(TH2D *axes, string mess1, string mess2, string mess3, string mess4)
155 {
156  // This will draw a label or two on the
157  // current plot using the NDC coordinates.
158  // It is put here to make sure all plots have
159  // a consistent labeling.
160 
161  char date_lab[256];
162  DateLabel(date_lab);
163  string rev_lab = GetRevision();
164 
165  // Date, Author
166  TLatex *lab = new TLatex(0.725, 0.7, date_lab);
167  ConvertFromNDC2D(lab, axes);
168  lab->SetTextSize(0.03);
169  lab->SetTextAlign(33);
170  lab->SetTextColor(kBlue);
171  lab->Draw();
172 
173  // SVN Revision
174  lab = new TLatex(0.725, 0.645, rev_lab.c_str());
175  ConvertFromNDC2D(lab, axes);
176  lab->SetTextSize(0.02);
177  lab->SetTextAlign(31);
178  lab->SetTextColor(kBlue);
179  lab->Draw();
180 
181  // mess1 - upper right
182  if(mess1!=""){
183  lab = new TLatex(0.7, 0.61, mess1.c_str());
184  ConvertFromNDC2D(lab, axes);
185  lab->SetTextSize(0.03);
186  lab->SetTextAlign(31);
187  lab->Draw();
188  }
189 
190  // mess2 - top, right of center
191  if(mess2!=""){
192  lab = new TLatex(0.0, 0.60, mess2.c_str());
193  ConvertFromNDC2D(lab, axes);
194  lab->SetTextSize(0.03);
195  lab->SetTextAlign(32);
196  lab->Draw();
197  }
198 
199  // mess3 - top left
200  if(mess3!=""){
201  lab = new TLatex(-0.575, 0.60, mess3.c_str());
202  ConvertFromNDC2D(lab, axes);
203  lab->SetTextSize(0.025);
204  lab->SetTextAlign(12);
205  lab->Draw();
206  }
207 
208  // mess4 - on right hand side at 90 degrees
209  if(mess4!=""){
210  lab = new TLatex(0.65, 0.0, mess4.c_str());
211  ConvertFromNDC2D(lab, axes);
212  lab->SetTextSize(0.035);
213  lab->SetTextAlign(22);
214  lab->SetTextAngle(270.0);
215  lab->Draw();
216  }
217 }
218 
219 //----------------
220 // StandardLabels1D
221 //----------------
222 void StandardLabels1D(TH1D *axes, string mess1, string mess2, string mess3, string mess4)
223 {
224  // This will draw a label or two on the
225  // current plot using the NDC coordinates.
226  // It is put here to make sure all plots have
227  // a consistent labeling.
228 
229  char date_lab[256];
230  DateLabel(date_lab);
231  string rev_lab = GetRevision();
232 
233  // Date, Author
234  TLatex *lab = new TLatex(0.7, 0.7, date_lab);
235  ConvertFromNDC1D(lab, axes);
236  lab->SetTextSize(0.03);
237  lab->SetTextAlign(33);
238  lab->SetTextColor(kBlue);
239  lab->Draw();
240 
241  // SVN Revision
242  lab = new TLatex(0.7, 0.645, rev_lab.c_str());
243  ConvertFromNDC1D(lab, axes);
244  lab->SetTextSize(0.02);
245  lab->SetTextAlign(31);
246  lab->SetTextColor(kBlue);
247  lab->Draw();
248 
249  // mess1 - upper right
250  lab = new TLatex(0.7, 0.61, mess1.c_str());
251  ConvertFromNDC1D(lab, axes);
252  lab->SetTextSize(0.03);
253  lab->SetTextAlign(31);
254  lab->Draw();
255 
256  // mess2 - top, right of center
257  lab = new TLatex(0.35, 0.675, mess2.c_str());
258  ConvertFromNDC1D(lab, axes);
259  lab->SetTextSize(0.03);
260  lab->SetTextAlign(32);
261  lab->Draw();
262 
263  // mess3 - top left
264  if(mess3!=""){
265  lab = new TLatex(-0.575, 0.60, mess3.c_str());
266  ConvertFromNDC1D(lab, axes);
267  lab->SetTextSize(0.025);
268  lab->SetTextAlign(12);
269  lab->Draw();
270  }
271 
272  // mess4 - on right hand side at 90 degrees
273  if(mess4!=""){
274  lab = new TLatex(0.65, 0.0, mess4.c_str());
275  ConvertFromNDC1D(lab, axes);
276  lab->SetTextSize(0.035);
277  lab->SetTextAlign(22);
278  lab->SetTextAngle(270.0);
279  lab->Draw();
280  }
281 }
282 
283 //----------------
284 // ConvertFromNDC
285 //----------------
286 void ConvertFromNDC2D(TLatex *obj, TH2D *h)
287 {
288  // Bugs in ROOT make it hard to plot labels consistently.
289  // For 1D plots, the histogram axes define the coordinate
290  // system. For 2D plots, we seem to be forced to use the
291  // NDC. There does not seem to be an obvious way to tell
292  // which we're using so we pass the information in in the
293  // form of the "axes" histogram. If it is not NULL, then
294  // we use it to define the limits. Otherwise, we do nothing.
295 
296  if(h==NULL)return;
297 
298  // Check if there is a TCanvas object named c1. If so,
299  // assume it is what was used to plot things and we can
300  // check on whether logy is set.
301  TCanvas *c1 = (TCanvas*)gROOT->FindObject("c1");
302  bool is_logy = false;
303  if(c1 != NULL)is_logy = c1->GetLogy();
304 
305  TAxis *xaxis = h->GetXaxis();
306  TAxis *yaxis = h->GetYaxis();
307 
308  // These seem to be sensitive to values set by "SetRangeUser" as well as pad margins
309  double xmin = xaxis->GetBinCenter(xaxis->GetFirst());
310  double xmax = xaxis->GetBinCenter(xaxis->GetLast());
311 
312  double ymin = yaxis->GetBinLowEdge(yaxis->GetFirst());
313  double ymax = yaxis->GetBinLowEdge(yaxis->GetLast()+1);
314 
315  double x = obj->GetX();
316  double y = obj->GetY();
317 
318  x = xmin + (xmax-xmin)*(0.5+x/1.15);
319 
320  // Calculate "y" based on whether y-axis is log or not
321  if(is_logy){
322  double log_ymin = ymin!=0.0 ? log(ymin):1.0;
323  double log_ymax = log(ymax);
324  double a = log_ymin + (log_ymax-log_ymin)*(0.5+y/1.15);
325  y = exp(log_ymin + (log_ymax-log_ymin)*(0.5+y/1.15));
326  }else{
327  y = ymin + (ymax-ymin)*(0.5+y/1.15);
328  }
329 
330  obj->SetX(x);
331  obj->SetY(y);
332 
333 }
334 
335 //----------------
336 // ConvertFromNDC1D
337 //----------------
338 void ConvertFromNDC1D(TLatex *obj, TH1D *h)
339 {
340  // Bugs in ROOT make it hard to plot labels consistently.
341  // For 1D plots, the histogram axes define the coordinate
342  // system. For 2D plots, we seem to be forced to use the
343  // NDC. There does not seem to be an obvious way to tell
344  // which we're using so we pass the information in the
345  // form of the "axes" histogram. If it is not NULL, then
346  // we use it to define the limits. Otherwise, we do nothing.
347  //
348  // caveat: When plotting on a log axis, there is no way to
349  // pull the lower limit from the histogram. Instead, we
350  // detect try and detect whether the y-axis is log scale
351  // by looking for a "c1" object and assuming it is a TCanvas.
352  // We then use it to determine if logy is set and if so,
353  // to get the limits of the histogram from gPad.
354 
355  if(h==NULL)return;
356 
357  // Check if there is a TCanvas object named c1. If so,
358  // assume it is what was used to plot things and we can
359  // check on whether logy is set.
360  TCanvas *c1 = (TCanvas*)gROOT->FindObject("c1");
361  bool is_logy = false;
362  if(c1 != NULL)is_logy = c1->GetLogy();
363 
364  TAxis *xaxis = h->GetXaxis();
365  double ymin = h->GetMinimum();
366  double ymax = h->GetMaximum()*1.05;
367 
368  // If y-axis is log scale then try and get limits from gPad
369  if(c1 != NULL){
370  if(is_logy){
371  c1->Update(); // force gPad to update
372  ymin = pow(10.0, gPad->GetUymin());
373  ymax = pow(10.0, gPad->GetUymax());
374  }else{
375  c1->Update();
376  ymin = gPad->GetUymin();
377  ymax = gPad->GetUymax();
378  }
379  }
380 
381  // These seem to be sensitive to values set by "SetRangeUser" as well as pad margins
382  double xmin = xaxis->GetBinCenter(xaxis->GetFirst());
383  double xmax = xaxis->GetBinCenter(xaxis->GetLast());
384 
385  //double ymin = yaxis->GetBinCenter(yaxis->GetFirst());
386  //double ymax = yaxis->GetBinCenter(yaxis->GetLast());
387 
388  double x = obj->GetX();
389  double y = obj->GetY();
390 
391  x = xmin + (xmax-xmin)*(0.5+x/1.15);
392 
393  // Calculate "y" based on whether y-axis is log or not
394  if(is_logy){
395  double log_ymin = ymin!=0.0 ? log(ymin):1.0;
396  double log_ymax = log(ymax);
397  double a = log_ymin + (log_ymax-log_ymin)*(0.5+y/1.15);
398  y = exp(log_ymin + (log_ymax-log_ymin)*(0.5+y/1.15));
399  }else{
400  y = ymin + (ymax-ymin)*(0.5+(y-ymin)/1.15);
401  }
402 
403  obj->SetX(x);
404  obj->SetY(y);
405 
406 }
407 
void StandardLabels1D(TH1D *axes=NULL, string mess1="", string mess2="", string mess3="", string mess4="")
string GetInitials(void)
char str[256]
void ConvertFromNDC1D(TLatex *obj, TH1D *h=NULL)
TH2D * axes
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
char string[256]
sprintf(text,"Post KinFit Cut")
#define y
string GetDate(void)
Double_t c1[2][NMODULES]
Definition: tw_corr.C:68
void DateLabel(char *date_lab)
void StandardLabels(TH1 *h, string mess1="", string mess2="", string mess3="", string mess4="")
void ConvertFromNDC2D(TLatex *obj, TH2D *h=NULL)
string GetRevision(void)
void StandardLabels2D(TH2D *axes=NULL, string mess1="", string mess2="", string mess3="", string mess4="")
Double_t ymin
Definition: bcal_hist_eff.C:89
Double_t ymax
Definition: bcal_hist_eff.C:91