Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
THLimitsFinder.cxx
Go to the documentation of this file.
1// @(#)root/hist:$Id$
2// Author: Rene Brun 14/01/2002
3/*************************************************************************
4 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#include "TH1.h"
12#include "TMath.h"
13#include "THLimitsFinder.h"
14
16
17
18/** \class THLimitsFinder
19 \ingroup Histograms
20Class to compute nice axis limits.
21
22This class is called by default by the histogramming system
23and also by TTree::Draw, TTreePlayer::DrawSelect. TGaxis use it also to
24optimize axis labels.
25
26A different finder may be specified via THLimitsFinder::SetFinder.
27*/
28
29////////////////////////////////////////////////////////////////////////////////
30
34
35////////////////////////////////////////////////////////////////////////////////
36
40
41
42////////////////////////////////////////////////////////////////////////////////
43/// Compute the best axis limits for the X axis.
44///
45/// If the bit kIsInteger is set, the number of channels is also recomputed.
46/// The axis parameters are replaced by the optimized parameters.
47///
48/// Example:
49/// With the input parameters xmin=-1.467 and xmax=2.344, the function
50/// will compute better limits -1.8 and 2.7 and store them in the axis.
51
53{
55 TAxis *xaxis = h->GetXaxis();
56
57 if (xmin >= xmax) {
58 if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
59 else {xmin -= 1; xmax += 1;}
60 }
61
64 xaxis->TestBit(TAxis::kIsInteger));
65
66 h->SetBins(newbins,xmin,xmax);
67
68 return 0;
69}
70
71////////////////////////////////////////////////////////////////////////////////
72/// Compute the best axis limits for the X and Y axis.
73///
74/// If the bit kIsInteger is set, the number of channels is also recomputed.
75/// The axis parameters are replaced by the optimized parameters
76
78{
80 TAxis *xaxis = h->GetXaxis();
81 TAxis *yaxis = h->GetYaxis();
82
83 if (xmin >= xmax) {
84 if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
85 else {xmin -= 1; xmax += 1;}
86 }
87 if (ymin >= ymax) {
88 if (yaxis->GetLabels()) {ymin = 0; ymax = ymin +yaxis->GetNbins();}
89 else {ymin -= 1; ymax += 1;}
90 }
91
94 xaxis->TestBit(TAxis::kIsInteger));
95
98 yaxis->TestBit(TAxis::kIsInteger));
99
100 h->SetBins(newbinsx,xmin,xmax,newbinsy,ymin,ymax);
101 return 0;
102}
103
104////////////////////////////////////////////////////////////////////////////////
105/// Compute the best axis limits for the X, Y and Z axis.
106///
107/// If the bit kIsInteger is set, the number of channels is also recomputed.
108/// The axis parameters are replaced by the optimized parameters
109
111{
113 TAxis *xaxis = h->GetXaxis();
114 TAxis *yaxis = h->GetYaxis();
115 TAxis *zaxis = h->GetZaxis();
116
117 if (xmin >= xmax) {
118 if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
119 else {xmin -= 1; xmax += 1;}
120 }
121 if (ymin >= ymax) {
122 if (yaxis->GetLabels()) {ymin = 0; ymax = ymin +yaxis->GetNbins();}
123 else {ymin -= 1; ymax += 1;}
124 }
125 if (zmin >= zmax) {
126 if (zaxis->GetLabels()) {zmin = 0; zmax = zmin +zaxis->GetNbins();}
127 else {zmin -= 1; zmax += 1;}
128 }
129
132 xaxis->TestBit(TAxis::kIsInteger));
133
136 yaxis->TestBit(TAxis::kIsInteger));
137
139 newbinsz,zmin,zmax,
140 zaxis->TestBit(TAxis::kIsInteger));
141
142 h->SetBins(newbinsx,xmin,xmax,newbinsy,ymin,ymax,newbinsz,zmin,zmax);
143 return 0;
144}
145
146////////////////////////////////////////////////////////////////////////////////
147/// Return pointer to the current finder.
148///
149/// Create one if none exists
150/// Use SetLimitsFinder to set a user defined finder.
151
157
158////////////////////////////////////////////////////////////////////////////////
159/// This static function can be used to specify a finder derived from THLimitsFinder.
160///
161/// The finder may redefine the functions FindGoodLimits.
162/// Note that the redefined functions may call THLimitsFinder::FindGoodLimits.
163
168
169////////////////////////////////////////////////////////////////////////////////
170/// Static function to compute reasonable axis limits
171///
172/// Input parameters:
173///
174/// \param[in] A1,A2 : Original axis limits
175/// \param[in] BinLow,BinHigh : Optimized axis limits. They should be initialized by the
176/// calling method for instance to 0.
177/// \param[out] nold : Original number of divisions.
178/// \param[out] nbins : Optimized number of divisions.
179/// \param[out] BinWidth : Optimized bin width. It should be initialized by the
180/// calling method for instance to 0.
181/// \param[in] option : "T" means Time axis.
182
185 Int_t &nbins, Double_t &BinWidth,
187{
188 Int_t lwid, kwid;
189 Int_t ntemp = 0;
190 Int_t jlog = 0;
191 Double_t siground = 0;
194 Int_t roundmode =0;
195
197 if(strchr(option,'t')) optionTime = 1; else optionTime = 0;
198
199 nbins = nold;
200
203 if (al == ah) ah = al+1;
204 // if nold == -1 , program uses binwidth input from calling routine
205 if (nold == -1 && BinWidth > 0 ) goto L90;
206 ntemp = TMath::Max(nold,2);
207 if (ntemp < 1) ntemp = 1;
208
209L20:
211 timemulti = 1;
212 if (awidth >= FLT_MAX) goto LOK; //in float.h
213 if (awidth <= 0) goto LOK;
214
215// If time representation, bin width should be rounded to seconds
216// minutes, hours or days
217
218 if (optionTime && awidth>=60) { // if width in seconds, treat it as normal
219 // width in minutes
220 awidth /= 60; timemulti *=60;
221 roundmode = 1; // round minutes (60)
222 // width in hours ?
223 if (awidth>=60) {
224 awidth /= 60; timemulti *= 60;
225 roundmode = 2; // round hours (24)
226 // width in days ?
227 if (awidth>=24) {
228 awidth /= 24; timemulti *= 24;
229 roundmode = 3; // round days (30)
230 // width in months ?
231 if (awidth>=30.43685) { // Mean month length in 1900.
232 awidth /= 30.43685; timemulti *= 30.43685;
233 roundmode = 2; // round months (12)
234 // width in years ?
235 if (awidth>=12) {
236 awidth /= 12; timemulti *= 12;
237 roundmode = 0; // round years (10)
238 }
239 }
240 }
241 }
242 }
243// Get nominal bin width in exponential form
244
246 if (jlog <-200 || jlog > 200) {
247 BinLow = 0;
248 BinHigh = 1;
249 BinWidth = 0.01;
250 nbins = 100;
251 return;
252 }
253 if (awidth <= 1 && (!optionTime || timemulti==1) ) jlog--;
254 sigfig = awidth*TMath::Power(10,-jlog) -1e-10;
255 //in the above statement, it is important to subtract 1e-10
256 //to avoid precision problems if the tests below
257
258// Round mantissa
259
260 switch (roundmode) {
261
262// Round mantissa up to 1, 1.5, 2, 3, or 6 in case of minutes
263 case 1: // case 60
264 if (sigfig <= 1) siground = 1;
265 else if (sigfig <= 1.5 && jlog==1) siground = 1.5;
266 else if (sigfig <= 2) siground = 2;
267 else if (sigfig <= 3 && jlog ==1) siground = 3;
268 else if (sigfig <= 5 && sigfig>3 && jlog ==0) siground = 5; //added (Damir in 3.10/02)
269 else if (jlog==0) {siground = 1; jlog++;}
270 else siground = 6;
271 break;
272 case 2: // case 12 and 24
273
274// Round mantissa up to 1, 1.2, 2, 2.4, 3 or 6 in case of hours or months
275 if (sigfig <= 1 && jlog==0) siground = 1;
276 else if (sigfig <= 1.2 && jlog==1) siground = 1.2;
277 else if (sigfig <= 2 && jlog==0) siground = 2;
278 else if (sigfig <= 2.4 && jlog==1) siground = 2.4;
279 else if (sigfig <= 3) siground = 3;
280 else if (sigfig <= 6) siground = 6;
281 else if (jlog==0) siground = 12;
282 else siground = 2.4;
283 break;
284
285//- Round mantissa up to 1, 1.4, 2, or 7 in case of days (weeks)
286 case 3: // case 30
287 if (sigfig <= 1 && jlog==0) siground = 1;
288 else if (sigfig <= 1.4 && jlog==1) siground = 1.4;
289 else if (sigfig <= 3 && jlog ==1) siground = 3;
290 else siground = 7;
291 break;
292 default :
293
294// Round mantissa up to 1, 2, 2.5, 5, or 10 in case of decimal number
295 if (sigfig <= 1) siground = 1;
296 else if (sigfig <= 2) siground = 2;
297 else if (sigfig <= 5 && (!optionTime || jlog<1)) siground = 5;
298 else if (sigfig <= 6 && optionTime && jlog==1) siground = 6;
299 else {siground = 1; jlog++; }
300 break;
301 }
302
305
306// Get new bounds from new width BinWidth
307
308L90:
309 alb = al/BinWidth;
310 if (TMath::Abs(alb) > 1e9) {
311 BinLow = al;
312 BinHigh = ah;
313 if (nbins > 10*nold && nbins > 10000) nbins = nold;
314 return;
315 }
316 lwid = Int_t(alb);
317 if (alb < 0) lwid--;
319 alb = ah/BinWidth + 1.00001;
320 kwid = Int_t(alb);
321 if (alb < 0) kwid--;
323 nbins = kwid - lwid;
324 if (nold == -1) goto LOK;
325 if (nold <= 5) { // Request for one bin is difficult case
326 if (nold > 1 || nbins == 1)goto LOK;
327 BinWidth = BinWidth*2;
328 nbins = 1;
329 goto LOK;
330 }
331 if (2*nbins == nold && !optionTime) {ntemp++; goto L20; }
332
333LOK:
336 Int_t oldnbins = nbins;
337
338 Double_t atest = BinWidth*0.0001;
339 //if (TMath::Abs(BinLow-A1) >= atest) { BinLow += BinWidth; nbins--; } //replaced by Damir in 3.10/02
340 //if (TMath::Abs(BinHigh-A2) >= atest) { BinHigh -= BinWidth; nbins--; } //by the next two lines
341 if (al-BinLow >= atest) { BinLow += BinWidth; nbins--; }
342 if (BinHigh-ah >= atest) { BinHigh -= BinWidth; nbins--; }
343 if (!optionTime && BinLow >= BinHigh) {
344 //this case may happen when nbins <=5
347 nbins = oldnbins;
348 }
349 else if (optionTime && BinLow>=BinHigh) {
350 nbins = 2*oldnbins;
353 BinWidth = (oldBinHigh - oldBinLow)/nbins;
354 atest = BinWidth*0.0001;
355 if (al-BinLow >= atest) { BinLow += BinWidth; nbins--; }
356 if (BinHigh-ah >= atest) { BinHigh -= BinWidth; nbins--; }
357 }
358}
359
360////////////////////////////////////////////////////////////////////////////////
361/// Optimize axis limits.
362///
363/// When isInter=kTRUE, the function makes an integer binwidth
364/// and recompute the number of bins accordingly.
365
367{
369 Int_t n=0;
370 Double_t dx = 0.1*(xmax-xmin);
371 if (isInteger) dx = 5*(xmax-xmin)/nbins;
372 Double_t umin = xmin - dx;
373 Double_t umax = xmax + dx;
374 if (umin < 0 && xmin >= 0) umin = 0;
375 if (umax > 0 && xmax <= 0) umax = 0;
376
378
379 if (binwidth <= 0 || binwidth > 1.e+39) {
380 xmin = -1;
381 xmax = 1;
382 } else {
383 xmin = binlow;
384 xmax = binhigh;
385 }
386 if (isInteger) {
391 if (xmin < 0 && xmin != dxmin) xmin = dxmin - 1;
392 else xmin = dxmin;
393 if (xmax > 0 && xmax != dxmax) xmax = dxmax + 1;
394 else if (xmax ==0 && xmax == dxmax) xmax = 1;
395 else xmax = dxmax;
396 if (xmin >= xmax) xmax = xmin+1;
397 Long64_t bw = Long64_t((xmax-xmin)/nbins);
398 if (bw == 0) bw = 1;
399 nbins = Int_t((xmax-xmin)/bw);
400 if (xmin +nbins*bw < umax) {nbins++; xmax = xmin +nbins*bw;}
401 if (xmin > umin) {nbins++; xmin = xmax -nbins*bw;}
402 }
403 newbins = nbins;
404}
#define h(i)
Definition RSha256.hxx:106
#define e(i)
Definition RSha256.hxx:103
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:59
double Double_t
Double 8 bytes.
Definition RtypesCore.h:73
long long Long64_t
Portable signed long integer 8 bytes.
Definition RtypesCore.h:83
const char Option_t
Option string (const char)
Definition RtypesCore.h:80
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t option
float xmin
float ymin
float xmax
float ymax
Class to manage histogram axis.
Definition TAxis.h:32
@ kIsInteger
Definition TAxis.h:76
TH1 is the base class of all histogram classes in ROOT.
Definition TH1.h:109
Class to compute nice axis limits.
static void SetLimitsFinder(THLimitsFinder *finder)
This static function can be used to specify a finder derived from THLimitsFinder.
~THLimitsFinder() override
static THLimitsFinder * GetLimitsFinder()
Return pointer to the current finder.
static void OptimizeLimits(Int_t nbins, Int_t &newbins, Double_t &xmin, Double_t &xmax, Bool_t isInteger)
Optimize axis limits.
static THLimitsFinder * fgLimitsFinder
! Pointer to hist limits finder
virtual Int_t FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax)
Compute the best axis limits for the X axis.
static void Optimize(Double_t A1, Double_t A2, Int_t nold, Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BWID, Option_t *option="")
Static function to compute reasonable axis limits.
const Int_t n
Definition legend1.C:16
Short_t Max(Short_t a, Short_t b)
Returns the largest of a and b.
Definition TMathBase.h:251
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Returns x raised to the power y.
Definition TMath.h:732
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Definition TMathBase.h:199
Double_t Log10(Double_t x)
Returns the common (base-10) logarithm of x.
Definition TMath.h:773
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.
Definition TMathBase.h:124