forked from erkcan/ROOTmacros
-
Notifications
You must be signed in to change notification settings - Fork 0
/
HistoAutoRange.C
113 lines (89 loc) · 3.66 KB
/
HistoAutoRange.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// Loop through all histos in the current gPad and make sure all of
// them are totally visible. Useful when you plot two or more histograms
// with the "same" option and some bin contents are not visible due to
// the range set automatically by the first plotted histo.
void HistoAutoRange() {
#define __HistoAutoRange__
if ( gROOT->GetListOfCanvases()->GetEntries() == 0 ) return;
TList *glist = gPad->GetListOfPrimitives();
bool islogy = gPad->GetLogy();
// First identify the current range for the y-axis
double ymin=0, ymax=0;
for (int i=0; i<glist->GetEntries(); ++i) {
TObject *obj = glist->At(i);
if ( obj->InheritsFrom("TFrame") ) {
ymin = ((TFrame*)obj)->GetY1();
ymax = ((TFrame*)obj)->GetY2();
break;
}
}
if ( islogy ) { ymin = pow(10,ymin); ymax = pow(10,ymax); }
// Now loop through histos and find the extrema
for (int i=0; i<glist->GetEntries(); ++i) {
TObject *obj = glist->At(i);
if ( obj->InheritsFrom("TH1") ) {
TH1 *histo = (TH1*)obj;
// If this is a 2D histogram, sorry, we can't do it (yet).
if ( obj->InheritsFrom("TH2") ) return;
// if log scale plot, do not modify the minimum - problems with negatives
if ( !islogy ) {
ymin = TMath::Min( ymin, histo->GetMinimum() );
ymin = TMath::Min( ymin, histo->GetBinContent(histo->GetMinimumBin()));
}
ymax = TMath::Max( ymax, (islogy ? 1.8 : 1.1) *
( histo->GetBinContent(histo->GetMaximumBin()) +
(int)(histo->GetSumw2N() != 0) *
histo->GetBinError(histo->GetMaximumBin()) ) );
}
}
// Finally set the new min/max
for (int i=0; i<glist->GetEntries(); ++i) {
TObject *obj = glist->At(i);
if ( obj->InheritsFrom("TH1") ) {
((TH1*)obj)->GetYaxis()->SetRangeUser(ymin, ymax);
((TH1*)obj)->SetMinimum(); // needed to get gPad->SetLogy() working
}
}
gPad->Modified();
}
// Loop through all histos in the current gPad and convert to log scale
// if it would look better. The "better" condition is based on comparing
// the maximum content for each histo and identifying if the quotient
// of any such maxima exceeds a certain factor. There is also a check
// against very "sharp" histograms, where the mean number of entries for
// the non-empty bins is much smaller than the max bin content.
void HistoAutoLogScale(float xfactor=20) {
if ( gROOT->GetListOfCanvases()->GetEntries() == 0 ) return;
TList *glist = gPad->GetListOfPrimitives();
if ( gPad->GetLogy() ) return;
float maxhisthi = -1;
float maxhistlo = -1;
bool sharphisto(false);
// Now loop through histos and find the extrema
for (int i=0; i<glist->GetEntries(); ++i) {
TObject *obj = glist->At(i);
if ( obj->InheritsFrom("TH1") ) {
// If this is a 2D histogram, sorry, nothing to do yet.
if ( obj->InheritsFrom("TH2") ) return;
TH1 *histo = (TH1*)obj;
// If any of the histos have negative content, sorry, nothing to do.
if ( histo->GetBinContent(histo->GetMinimumBin()) < 0 ) return;
float maxhist = histo->GetBinContent(histo->GetMaximumBin());
if ( maxhisthi < 0 )
maxhisthi = maxhistlo = maxhist;
else {
if ( maxhistlo > maxhist ) maxhistlo = maxhist;
if ( maxhisthi < maxhist ) maxhisthi = maxhist;
}
// If any of the histos have a very sharp peak
unsigned int nbinsfull = 0; float integral = 0;
for (int ib=1; ib<=histo->GetNbinsX(); ++ib)
if ( histo->GetBinContent(ib) > 0 ) {
nbinsfull++; integral += histo->GetBinContent(ib); }
if ( maxhist * nbinsfull > (integral-maxhist) * xfactor ) {
sharphisto = true; break; }
}
}
if ( maxhistlo * xfactor < maxhisthi || sharphisto ) gPad->SetLogy();
gPad->Modified();
}