Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TPaveStats.cxx
Go to the documentation of this file.
1 // @(#)root/graf:$Id$
2 // Author: Rene Brun 15/03/99
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 
16 #include "Riostream.h"
17 #include "TROOT.h"
18 #include "TPaveStats.h"
19 #include "TPaveLabel.h"
20 #include "TVirtualPad.h"
21 #include "TStyle.h"
22 #include "TClass.h"
23 #include "TLatex.h"
24 
25 ClassImp(TPaveStats);
26 
27 /** \class TPaveStats
28 \ingroup BasicGraphics
29 
30 The histogram statistics painter class.
31 
32 To draw histogram statistics and fit parameters.
33 
34 - [Statistics Display](#PS01)
35 - [Fit Statistics](#PS02)
36 - [Statistics box editing](#PS03)
37 
38 ## <a name="PS01"></a> Statistics Display
39 
40 The type of information shown in the histogram statistics box can be selected
41 with:
42 ~~~ {.cpp}
43  gStyle->SetOptStat(mode);
44 ~~~
45 
46 The "`mode`" has up to nine digits that can be set to on (1 or 2), off (0).
47 ~~~ {.cpp}
48  mode = ksiourmen (default = 000001111)
49  k = 1; kurtosis printed
50  k = 2; kurtosis and kurtosis error printed
51  s = 1; skewness printed
52  s = 2; skewness and skewness error printed
53  i = 1; integral of bins printed
54  o = 1; number of overflows printed
55  u = 1; number of underflows printed
56  r = 1; rms printed
57  r = 2; rms and rms error printed
58  m = 1; mean value printed
59  m = 2; mean and mean error values printed
60  e = 1; number of entries printed
61  n = 1; name of histogram is printed
62 ~~~
63 
64 For example:
65 ~~~ {.cpp}
66  gStyle->SetOptStat(11);
67 ~~~
68 displays only the name of histogram and the number of entries, whereas:
69 ~~~ {.cpp}
70  gStyle->SetOptStat(1101);
71 ~~~
72 displays the name of histogram, mean value and RMS.
73 
74 <b>WARNING 1:</b> never do:
75 ~~~ {.cpp}
76  gStyle->SetOptStat(0001111);
77 ~~~
78 but instead do:
79 ~~~ {.cpp}
80  gStyle->SetOptStat(1111);
81 ~~~
82 because `0001111` will be taken as an octal number!
83 
84 <b>WARNING 2:</b> for backward compatibility with older versions
85 ~~~ {.cpp}
86  gStyle->SetOptStat(1);
87 ~~~
88 is taken as:
89 ~~~ {.cpp}
90  gStyle->SetOptStat(1111)
91 ~~~
92 To print only the name of the histogram do:
93 ~~~ {.cpp}
94  gStyle->SetOptStat(1000000001);
95 ~~~
96 
97 <b>NOTE</b> that in case of 2D histograms, when selecting only underflow
98 (10000) or overflow (100000), the statistics box will show all combinations
99 of underflow/overflows and not just one single number.
100 
101 The parameter mode can be any combination of the letters `kKsSiourRmMen`
102 ~~~ {.cpp}
103  k : kurtosis printed
104  K : kurtosis and kurtosis error printed
105  s : skewness printed
106  S : skewness and skewness error printed
107  i : integral of bins printed
108  o : number of overflows printed
109  u : number of underflows printed
110  r : rms printed
111  R : rms and rms error printed
112  m : mean value printed
113  M : mean value mean error values printed
114  e : number of entries printed
115  n : name of histogram is printed
116 ~~~
117 
118 For example, to print only name of histogram and number of entries do:
119 ~~~ {.cpp}
120  gStyle->SetOptStat("ne");
121 ~~~
122 
123 To print only the name of the histogram do:
124 ~~~ {.cpp}
125  gStyle->SetOptStat("n");
126 ~~~
127 
128 The default value is:
129 ~~~ {.cpp}
130  gStyle->SetOptStat("nemr");
131 ~~~
132 
133 When a histogram is painted, a `TPaveStats` object is created and added
134 to the list of functions of the histogram. If a `TPaveStats` object
135 already exists in the histogram list of functions, the existing object is just
136 updated with the current histogram parameters.
137 
138 Once a histogram is painted, the statistics box can be accessed using
139 `h->FindObject("stats")`. In the command line it is enough to do:
140 ~~~ {.cpp}
141  Root > h->Draw()
142  Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
143 ~~~
144 
145 because after `h->Draw()` the histogram is automatically painted. But
146 in a script file the painting should be forced using `gPad->Update()`
147 in order to make sure the statistics box is created:
148 ~~~ {.cpp}
149  h->Draw();
150  gPad->Update();
151  TPaveStats *st = (TPaveStats*)h->FindObject("stats");
152 ~~~
153 
154 Without `gPad->Update()` the line `h->FindObject("stats")`
155 returns a null pointer.
156 
157 When a histogram is drawn with the option "`SAME`", the statistics box
158 is not drawn. To force the statistics box drawing with the option
159 "`SAME`", the option "`SAMES`" must be used.
160 If the new statistics box hides the previous statistics box, one can change
161 its position with these lines ("`h`" being the pointer to the histogram):
162 ~~~ {.cpp}
163  Root > TPaveStats *st = (TPaveStats*)h->FindObject("stats")
164  Root > st->SetX1NDC(newx1); //new x start position
165  Root > st->SetX2NDC(newx2); //new x end position
166 ~~~
167 
168 To change the type of information for an histogram with an existing
169 `TPaveStats` one should do:
170 ~~~ {.cpp}
171  st->SetOptStat(mode);
172 ~~~
173 Where "`mode`" has the same meaning than when calling
174 `gStyle->SetOptStat(mode)` (see above).
175 
176 One can delete the statistics box for a histogram `TH1* h` with:
177 ~~~ {.cpp}
178  h->SetStats(0)
179 ~~~
180 
181 and activate it again with:
182 ~~~ {.cpp}
183  h->SetStats(1).
184 ~~~
185 
186 ## <a name="PS02"></a> Fit Statistics
187 
188 The type of information about fit parameters printed in the histogram statistics
189 box can be selected via the parameter mode. The parameter mode can be
190 `= pcev` (default `= 0111`)
191 ~~~ {.cpp}
192  p = 1; print Probability
193  c = 1; print Chisquare/Number of degrees of freedom
194  e = 1; print errors (if e=1, v must be 1)
195  v = 1; print name/values of parameters
196 ~~~
197 Example:
198 ~~~ {.cpp}
199  gStyle->SetOptFit(1011);
200 ~~~
201 print fit probability, parameter names/values and errors.
202 
203  1. When `"v" = 1` is specified, only the non-fixed parameters are
204  shown.
205  2. When `"v" = 2` all parameters are shown.
206 
207 Note: `gStyle->SetOptFit(1)` means "default value", so it is equivalent
208 to `gStyle->SetOptFit(111)`
209 
210 ## <a name="PS03"></a> Statistics box editing
211 
212 The following example show how to remove and add a line in a statistics box.
213 
214 Begin_Macro(source)
215 ../../../tutorials/hist/statsEditing.C
216 End_Macro
217 */
218 
219 
220 const UInt_t kTakeStyle = BIT(17); //see TStyle::SetOptFit/Stat
221 
222 ////////////////////////////////////////////////////////////////////////////////
223 /// TPaveStats default constructor.
224 
225 TPaveStats::TPaveStats(): TPaveText()
226 {
227  fParent = 0;
228  fOptFit = gStyle->GetOptFit();
229  fOptStat = gStyle->GetOptStat();
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// TPaveStats normal constructor.
234 
235 TPaveStats::TPaveStats(Double_t x1, Double_t y1,Double_t x2, Double_t y2, Option_t *option)
236  :TPaveText(x1,y1,x2,y2,option)
237 {
238  fParent = 0;
239  fOptFit = gStyle->GetOptFit();
240  fOptStat = gStyle->GetOptStat();
241  SetFitFormat(gStyle->GetFitFormat());
242  SetStatFormat(gStyle->GetStatFormat());
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// TPaveStats default destructor.
247 
248 TPaveStats::~TPaveStats()
249 {
250  if ( fParent && !fParent->TestBit(kInvalidObject)) fParent->RecursiveRemove(this);
251 }
252 
253 ////////////////////////////////////////////////////////////////////////////////
254 /// Return the fit option.
255 
256 Int_t TPaveStats::GetOptFit() const
257 {
258  if (TestBit(kTakeStyle)) return gStyle->GetOptFit();
259  return fOptFit;
260 }
261 
262 ////////////////////////////////////////////////////////////////////////////////
263 /// Return the stat option.
264 
265 Int_t TPaveStats::GetOptStat() const
266 {
267  if (TestBit(kTakeStyle)) return gStyle->GetOptStat();
268  return fOptStat;
269 }
270 
271 ////////////////////////////////////////////////////////////////////////////////
272 /// Save This TPaveStats options in current style.
273 
274 void TPaveStats::SaveStyle()
275 {
276  gStyle->SetOptFit(fOptFit);
277  gStyle->SetOptStat(fOptStat);
278  gStyle->SetFitFormat(fFitFormat.Data());
279  gStyle->SetStatFormat(fStatFormat.Data());
280 }
281 
282 ////////////////////////////////////////////////////////////////////////////////
283 /// Change (i.e. set) the format for printing fit parameters in statistics box.
284 
285 void TPaveStats::SetFitFormat(const char *form)
286 {
287  fFitFormat = form;
288 }
289 
290 ////////////////////////////////////////////////////////////////////////////////
291 /// Set the fit option.
292 
293 void TPaveStats::SetOptFit(Int_t fit)
294 {
295  fOptFit = fit;
296  ResetBit(kTakeStyle);
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// Set the stat option.
301 
302 void TPaveStats::SetOptStat(Int_t stat)
303 {
304  fOptStat = stat;
305  ResetBit(kTakeStyle);
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Change (i.e. set) the format for printing statistics.
310 
311 void TPaveStats::SetStatFormat(const char *form)
312 {
313  fStatFormat = form;
314 }
315 
316 ////////////////////////////////////////////////////////////////////////////////
317 /// Paint the pave stat.
318 
319 void TPaveStats::Paint(Option_t *option)
320 {
321  TPave::ConvertNDCtoPad();
322  TPave::PaintPave(fX1,fY1,fX2,fY2,GetBorderSize(),option);
323 
324  if (!fLines) return;
325  TString typolabel;
326  Double_t y2ref = TMath::Max(fY1,fY2);
327  Double_t x1ref = TMath::Min(fX1,fX2);
328  Double_t x2ref = TMath::Max(fX1,fX2);
329  Double_t dx = TMath::Abs(fX2 - fX1);
330  Double_t dy = TMath::Abs(fY2 - fY1);
331  Double_t titlesize=0;
332  Double_t textsize = GetTextSize();
333  Int_t nlines = GetSize();
334  if (nlines == 0) nlines = 5;
335  Int_t print_name = fOptStat%10;
336 
337  // Evaluate text size as a function of the number of lines
338  Double_t y1 = gPad->GetY1();
339  Double_t y2 = gPad->GetY2();
340  Float_t margin = fMargin*dx;
341  Double_t yspace = dy/Double_t(nlines);
342  Double_t textsave = textsize;
343  TObject *line;
344  TLatex *latex, *latex_tok;
345  TIter next(fLines);
346  Double_t longest = 0, titlelength = 0;
347  Double_t w, wtok[2];
348  char *st, *sl=0;
349  if (textsize == 0) {
350  textsize = 0.92*yspace/(y2 - y1);
351  titlesize = textsize;
352  wtok[0] = 0; wtok[1] = 0;
353  while ((line = (TObject*) next())) {
354  if (line->IsA() == TLatex::Class()) {
355  latex = (TLatex*)line;
356  Int_t nchs = strlen(latex->GetTitle());
357  sl = new char[nchs+1];
358  strlcpy(sl, latex->GetTitle(),nchs+1);
359  if (strpbrk(sl, "=") !=0 && print_name == 0) {
360  st = strtok(sl, "=");
361  Int_t itok = 0;
362  while ( st !=0 ) {
363  latex_tok = new TLatex(0.,0.,st);
364  Style_t tfont = latex->GetTextFont();
365  if (tfont == 0) tfont = GetTextFont();
366  latex_tok->SetTextFont(tfont);
367  latex_tok->SetTextSize(textsize);
368  w = latex_tok->GetXsize();
369  if (w > wtok[itok]) wtok[itok] = w;
370  st = strtok(0, "=");
371  ++itok;
372  delete latex_tok;
373  }
374  } else if (strpbrk(sl, "|") !=0) {
375  } else {
376  print_name = 0;
377  Style_t tfont = latex->GetTextFont();
378  if (tfont == 0) latex->SetTextFont(GetTextFont());
379  latex->SetTextSize(titlesize);
380  titlelength = latex->GetXsize()+2.*margin;
381  if (titlelength > 0.98*dx) titlesize *= 0.98*dx/titlelength;
382  latex->SetTextFont(tfont);
383  }
384  delete [] sl; sl = 0;
385  }
386  }
387  longest = wtok[0]+wtok[1]+2.*margin;
388  if (longest > 0.98*dx) textsize *= 0.98*dx/longest;
389  SetTextSize(textsize);
390  } else {
391  titlesize = textsize;
392  }
393  Double_t ytext = y2ref + 0.5*yspace;
394  Double_t xtext = 0;
395  print_name = fOptStat%10;
396 
397  // Iterate over all lines
398  // Copy pavetext attributes to line attributes if line attributes not set
399  next.Reset();
400  while ((line = (TObject*) next())) {
401  if (line->IsA() == TLatex::Class()) {
402  latex = (TLatex*)line;
403  ytext -= yspace;
404  Double_t xl = latex->GetX();
405  Double_t yl = latex->GetY();
406  Short_t talign = latex->GetTextAlign();
407  Color_t tcolor = latex->GetTextColor();
408  Style_t tfont = latex->GetTextFont();
409  Size_t tsize = latex->GetTextSize();
410  if (tcolor == 0) latex->SetTextColor(GetTextColor());
411  if (tfont == 0) latex->SetTextFont(GetTextFont());
412  if (tsize == 0) latex->SetTextSize(GetTextSize());
413 
414  Int_t nchs = strlen(latex->GetTitle());
415  sl = new char[nchs+1];
416  strlcpy(sl, latex->GetTitle(),nchs+1);
417  // Draw all the histogram stats except the 2D under/overflow
418  if (strpbrk(sl, "=") !=0 && print_name == 0) {
419  st = strtok(sl, "=");
420  Int_t halign = 12;
421  while ( st !=0 ) {
422  typolabel = st;
423  latex->SetTextAlign(halign);
424  if (halign == 12) xtext = x1ref + margin;
425  if (halign == 32) {
426  xtext = x2ref - margin;
427  typolabel = typolabel.Strip();
428  typolabel.ReplaceAll("-","#minus");
429  }
430  latex->PaintLatex(xtext,ytext,latex->GetTextAngle(),
431  latex->GetTextSize(),
432  typolabel.Data());
433  st = strtok(0, "=");
434  halign = 32;
435  }
436  // Draw the 2D under/overflow
437  } else if (strpbrk(sl, "|") !=0) {
438  Double_t yline1 = ytext+yspace/2.;
439  Double_t yline2 = ytext-yspace/2.;
440  Double_t xline1 = dx/3+x1ref;
441  Double_t xline2 = 2*dx/3+x1ref;
442  gPad->PaintLine(x1ref,yline1,x2ref,yline1);
443  gPad->PaintLine(xline1,yline1,xline1,yline2);
444  gPad->PaintLine(xline2,yline1,xline2,yline2);
445  st = strtok(sl, "|");
446  Int_t theIndex = 0;
447  while ( st !=0 ) {
448  latex->SetTextAlign(22);
449  if (theIndex == 0) xtext = 0.5*(x1ref+xline1);
450  if (theIndex == 1) xtext = 0.5*(x1ref+x2ref);
451  if (theIndex == 2) xtext = 0.5*(xline2+x2ref);
452  typolabel = st;
453  typolabel.ReplaceAll("-", "#minus");
454  latex->PaintLatex(xtext,ytext,latex->GetTextAngle(),
455  latex->GetTextSize(),
456  typolabel.Data());
457  theIndex++;
458  st = strtok(0, "|");
459  }
460  // Draw the histogram identifier
461  } else {
462  print_name = 0;
463  latex->SetTextAlign(22);
464  xtext = 0.5*(x1ref+x2ref);
465  latex->PaintLatex(xtext,ytext,latex->GetTextAngle(),
466  titlesize,
467  sl);
468  gPad->PaintLine(x1ref,y2ref-yspace,x2ref,y2ref-yspace);
469  }
470  delete [] sl;
471 
472  latex->SetTextAlign(talign);
473  latex->SetTextColor(tcolor);
474  latex->SetTextFont(tfont);
475  latex->SetTextSize(tsize);
476  latex->SetX(xl); //paintlatex modifies fX and fY
477  latex->SetY(yl);
478  }
479  }
480  SetTextSize(textsave);
481 
482  // if a label create & paint a pavetext title
483  if (fLabel.Length() > 0) {
484  Double_t x1,x2;
485  dy = gPad->GetY2() - gPad->GetY1();
486  x1 = x1ref + 0.25*dx;
487  x2 = x2ref - 0.25*dx;
488  y1 = y2ref - 0.02*dy;
489  y2 = y2ref + 0.02*dy;
490  TPaveLabel *title = new TPaveLabel(x1,y1,x2,y2,fLabel.Data(),GetDrawOption());
491  title->SetFillColor(GetFillColor());
492  title->SetTextColor(GetTextColor());
493  title->SetTextFont(GetTextFont());
494  title->Paint();
495  delete title;
496  }
497 }
498 
499 ////////////////////////////////////////////////////////////////////////////////
500 /// Save primitive as a C++ statement(s) on output stream out.
501 
502 void TPaveStats::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
503 {
504  char quote = '"';
505  out<<" "<<std::endl;
506  Bool_t saved = gROOT->ClassSaved(TPaveStats::Class());
507  if (saved) {
508  out<<" ";
509  } else {
510  out<<" "<<ClassName()<<" *";
511  }
512  if (fOption.Contains("NDC")) {
513  out<<"ptstats = new "<<ClassName()<<"("<<fX1NDC<<","<<fY1NDC<<","<<fX2NDC<<","<<fY2NDC
514  <<","<<quote<<fOption<<quote<<");"<<std::endl;
515  } else {
516  out<<"ptstats = new "<<ClassName()<<"("<<fX1<<","<<fY1<<","<<fX2<<","<<fY2
517  <<","<<quote<<fOption<<quote<<");"<<std::endl;
518  }
519  if (strcmp(GetName(),"TPave")) {
520  out<<" ptstats->SetName("<<quote<<GetName()<<quote<<");"<<std::endl;
521  }
522  if (fBorderSize != 4) {
523  out<<" ptstats->SetBorderSize("<<fBorderSize<<");"<<std::endl;
524  }
525  SaveFillAttributes(out,"ptstats",19,1001);
526  SaveLineAttributes(out,"ptstats",1,1,1);
527  SaveTextAttributes(out,"ptstats",22,0,1,62,0);
528  SaveLines(out,"ptstats",saved);
529  out<<" ptstats->SetOptStat("<<GetOptStat()<<");"<<std::endl;
530  out<<" ptstats->SetOptFit("<<GetOptFit()<<");"<<std::endl;
531  out<<" ptstats->Draw();"<<std::endl;
532 }
533 
534 ////////////////////////////////////////////////////////////////////////////////
535 /// Stream an object of class TPaveStats.
536 
537 void TPaveStats::Streamer(TBuffer &R__b)
538 {
539  if (R__b.IsReading()) {
540  UInt_t R__s, R__c;
541  Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
542  if (R__v > 2) {
543  R__b.ReadClassBuffer(TPaveStats::Class(), this, R__v, R__s, R__c);
544  return;
545  }
546  //====process old versions before automatic schema evolution
547  TPaveText::Streamer(R__b);
548  R__b >> fOptFit;
549  R__b >> fOptStat;
550  if (R__v > 1 || R__b.GetVersionOwner() == 22304) {
551  fFitFormat.Streamer(R__b);
552  fStatFormat.Streamer(R__b);
553  } else {
554  SetFitFormat();
555  SetStatFormat();
556  }
557  R__b.CheckByteCount(R__s, R__c, TPaveStats::IsA());
558  //====end of old versions
559 
560  } else {
561  R__b.WriteClassBuffer(TPaveStats::Class(),this);
562  }
563 }
564 
565 ////////////////////////////////////////////////////////////////////////////////
566 /// Replace current attributes by current style.
567 
568 void TPaveStats::UseCurrentStyle()
569 {
570  if (gStyle->IsReading()) {
571  SetOptStat(gStyle->GetOptStat());
572  SetOptFit(gStyle->GetOptFit());
573  SetStatFormat(gStyle->GetStatFormat());
574  SetFitFormat(gStyle->GetFitFormat());
575  SetBorderSize(gStyle->GetStatBorderSize());
576  SetFillColor(gStyle->GetStatColor());
577  SetFillStyle(gStyle->GetStatStyle());
578  SetTextFont(gStyle->GetStatFont());
579  SetTextSize(gStyle->GetStatFontSize());
580  SetTextColor(gStyle->GetStatTextColor());
581  SetX2NDC(gStyle->GetStatX());
582  SetY2NDC(gStyle->GetStatY());
583  SetX1NDC(gStyle->GetStatX()-gStyle->GetStatW());
584  SetY1NDC(gStyle->GetStatY()-gStyle->GetStatH());
585  } else {
586  gStyle->SetOptStat(GetOptStat());
587  gStyle->SetOptFit(GetOptFit());
588  gStyle->SetStatFormat(GetStatFormat());
589  gStyle->SetFitFormat(GetFitFormat());
590  gStyle->SetStatBorderSize(GetBorderSize());
591  gStyle->SetTextColor(GetTextColor());
592  gStyle->SetStatColor(GetFillColor());
593  gStyle->SetStatStyle(GetFillStyle());
594  gStyle->SetTextFont(GetTextFont());
595  gStyle->SetStatFontSize(GetTextSize());
596  gStyle->SetStatTextColor(GetTextColor());
597  gStyle->SetStatX(GetX2NDC());
598  gStyle->SetStatY(GetY2NDC());
599  gStyle->SetStatW(GetX2NDC()-GetX1NDC());
600  gStyle->SetStatH(GetY2NDC()-GetY1NDC());
601  }
602 }