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
15#include <algorithm>
16
18
19
20/** \class THLimitsFinder
21 \ingroup Histograms
22Class to compute nice axis limits.
23
24This class is called by default by the histogramming system
25and also by TTree::Draw, TTreePlayer::DrawSelect. TGaxis use it also to
26optimize axis labels.
27
28A different finder may be specified via THLimitsFinder::SetFinder.
29*/
30
31////////////////////////////////////////////////////////////////////////////////
32
36
37////////////////////////////////////////////////////////////////////////////////
38
42
43
44////////////////////////////////////////////////////////////////////////////////
45/// Compute the best axis limits for the X axis.
46///
47/// If the bit kIsInteger is set, the number of channels is also recomputed.
48/// The axis parameters are replaced by the optimized parameters.
49///
50/// Example:
51/// With the input parameters xmin=-1.467 and xmax=2.344, the function
52/// will compute better limits -1.8 and 2.7 and store them in the axis.
53
55{
57 TAxis *xaxis = h->GetXaxis();
58
59 if (xmin >= xmax) {
60 if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
61 else {xmin -= 1; xmax += 1;}
62 }
63
66 xaxis->TestBit(TAxis::kIsInteger));
67
68 h->SetBins(newbins,xmin,xmax);
69
70 return 0;
71}
72
73////////////////////////////////////////////////////////////////////////////////
74/// Compute the best axis limits for the X and Y axis.
75///
76/// If the bit kIsInteger is set, the number of channels is also recomputed.
77/// The axis parameters are replaced by the optimized parameters
78
80{
82 TAxis *xaxis = h->GetXaxis();
83 TAxis *yaxis = h->GetYaxis();
84
85 if (xmin >= xmax) {
86 if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
87 else {xmin -= 1; xmax += 1;}
88 }
89 if (ymin >= ymax) {
90 if (yaxis->GetLabels()) {ymin = 0; ymax = ymin +yaxis->GetNbins();}
91 else {ymin -= 1; ymax += 1;}
92 }
93
96 xaxis->TestBit(TAxis::kIsInteger));
97
100 yaxis->TestBit(TAxis::kIsInteger));
101
102 h->SetBins(newbinsx,xmin,xmax,newbinsy,ymin,ymax);
103 return 0;
104}
105
106////////////////////////////////////////////////////////////////////////////////
107/// Compute the best axis limits for the X, Y and Z axis.
108///
109/// If the bit kIsInteger is set, the number of channels is also recomputed.
110/// The axis parameters are replaced by the optimized parameters
111
113{
115 TAxis *xaxis = h->GetXaxis();
116 TAxis *yaxis = h->GetYaxis();
117 TAxis *zaxis = h->GetZaxis();
118
119 if (xmin >= xmax) {
120 if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
121 else {xmin -= 1; xmax += 1;}
122 }
123 if (ymin >= ymax) {
124 if (yaxis->GetLabels()) {ymin = 0; ymax = ymin +yaxis->GetNbins();}
125 else {ymin -= 1; ymax += 1;}
126 }
127 if (zmin >= zmax) {
128 if (zaxis->GetLabels()) {zmin = 0; zmax = zmin +zaxis->GetNbins();}
129 else {zmin -= 1; zmax += 1;}
130 }
131
134 xaxis->TestBit(TAxis::kIsInteger));
135
138 yaxis->TestBit(TAxis::kIsInteger));
139
141 newbinsz,zmin,zmax,
142 zaxis->TestBit(TAxis::kIsInteger));
143
144 h->SetBins(newbinsx,xmin,xmax,newbinsy,ymin,ymax,newbinsz,zmin,zmax);
145 return 0;
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Return pointer to the current finder.
150///
151/// Create one if none exists
152/// Use SetLimitsFinder to set a user defined finder.
153
159
160////////////////////////////////////////////////////////////////////////////////
161/// This static function can be used to specify a finder derived from THLimitsFinder.
162///
163/// The finder may redefine the functions FindGoodLimits.
164/// Note that the redefined functions may call THLimitsFinder::FindGoodLimits.
165
170
171////////////////////////////////////////////////////////////////////////////////
172/// Static function to compute reasonable axis limits
173///
174/// Input parameters:
175///
176/// \param[in] A1,A2 : Original axis limits
177/// \param[in] BinLow,BinHigh : Optimized axis limits. They should be initialized by the
178/// calling method for instance to 0.
179/// \param[out] nold : Original number of divisions.
180/// \param[out] nbins : Optimized number of divisions.
181/// \param[out] BinWidth : Optimized bin width. It should be initialized by the
182/// calling method for instance to 0.
183/// \param[in] option : "T" means Time axis.
184
187 Int_t &nbins, Double_t &BinWidth,
189{
190 Int_t lwid, kwid;
191 Int_t ntemp = 0;
192 Int_t jlog = 0;
193 Double_t siground = 0;
196 Int_t roundmode =0;
197
199 if(strchr(option,'t')) optionTime = 1; else optionTime = 0;
200
201 nbins = nold;
202
205 if (al == ah) ah = al+1;
206 // if nold == -1 , program uses binwidth input from calling routine
207 if (nold == -1 && BinWidth > 0 ) goto L90;
208 ntemp = TMath::Max(nold,2);
209 if (ntemp < 1) ntemp = 1;
210
211L20:
213 timemulti = 1;
214 if (awidth >= FLT_MAX) goto LOK; //in float.h
215 if (awidth <= 0) goto LOK;
216
217// If time representation, bin width should be rounded to seconds
218// minutes, hours or days
219
220 if (optionTime && awidth>=60) { // if width in seconds, treat it as normal
221 // width in minutes
222 awidth /= 60; timemulti *=60;
223 roundmode = 1; // round minutes (60)
224 // width in hours ?
225 if (awidth>=60) {
226 awidth /= 60; timemulti *= 60;
227 roundmode = 2; // round hours (24)
228 // width in days ?
229 if (awidth>=24) {
230 awidth /= 24; timemulti *= 24;
231 roundmode = 3; // round days (30)
232 // width in months ?
233 if (awidth>=30.43685) { // Mean month length in 1900.
234 awidth /= 30.43685; timemulti *= 30.43685;
235 roundmode = 2; // round months (12)
236 // width in years ?
237 if (awidth>=12) {
238 awidth /= 12; timemulti *= 12;
239 roundmode = 0; // round years (10)
240 }
241 }
242 }
243 }
244 }
245// Get nominal bin width in exponential form
246
248 if (jlog <-200 || jlog > 200) {
249 BinLow = 0;
250 BinHigh = 1;
251 BinWidth = 0.01;
252 nbins = 100;
253 return;
254 }
255 if (awidth <= 1 && (!optionTime || timemulti==1) ) jlog--;
256 sigfig = awidth*TMath::Power(10,-jlog) -1e-10;
257 //in the above statement, it is important to subtract 1e-10
258 //to avoid precision problems if the tests below
259
260// Round mantissa
261
262 switch (roundmode) {
263
264// Round mantissa up to 1, 1.5, 2, 3, or 6 in case of minutes
265 case 1: // case 60
266 if (sigfig <= 1) siground = 1;
267 else if (sigfig <= 1.5 && jlog==1) siground = 1.5;
268 else if (sigfig <= 2) siground = 2;
269 else if (sigfig <= 3 && jlog ==1) siground = 3;
270 else if (sigfig <= 5 && sigfig>3 && jlog ==0) siground = 5; //added (Damir in 3.10/02)
271 else if (jlog==0) {siground = 1; jlog++;}
272 else siground = 6;
273 break;
274 case 2: // case 12 and 24
275
276// Round mantissa up to 1, 1.2, 2, 2.4, 3 or 6 in case of hours or months
277 if (sigfig <= 1 && jlog==0) siground = 1;
278 else if (sigfig <= 1.2 && jlog==1) siground = 1.2;
279 else if (sigfig <= 2 && jlog==0) siground = 2;
280 else if (sigfig <= 2.4 && jlog==1) siground = 2.4;
281 else if (sigfig <= 3) siground = 3;
282 else if (sigfig <= 6) siground = 6;
283 else if (jlog==0) siground = 12;
284 else siground = 2.4;
285 break;
286
287//- Round mantissa up to 1, 1.4, 2, or 7 in case of days (weeks)
288 case 3: // case 30
289 if (sigfig <= 1 && jlog==0) siground = 1;
290 else if (sigfig <= 1.4 && jlog==1) siground = 1.4;
291 else if (sigfig <= 3 && jlog ==1) siground = 3;
292 else siground = 7;
293 break;
294 default :
295
296// Round mantissa up to 1, 2, 2.5, 5, or 10 in case of decimal number
297 if (sigfig <= 1) siground = 1;
298 else if (sigfig <= 2) siground = 2;
299 else if (sigfig <= 5 && (!optionTime || jlog<1)) siground = 5;
300 else if (sigfig <= 6 && optionTime && jlog==1) siground = 6;
301 else {siground = 1; jlog++; }
302 break;
303 }
304
307
308// Get new bounds from new width BinWidth
309
310L90:
311 alb = al/BinWidth;
312 if (TMath::Abs(alb) > 1e9) {
313 BinLow = al;
314 BinHigh = ah;
315 if (nbins > 10*nold && nbins > 10000) nbins = nold;
316 return;
317 }
318 lwid = Int_t(alb);
319 if (alb < 0) lwid--;
321 alb = ah/BinWidth + 1.00001;
322 kwid = Int_t(alb);
323 if (alb < 0) kwid--;
325 nbins = kwid - lwid;
326 if (nold == -1) goto LOK;
327 if (nold <= 5) { // Request for one bin is difficult case
328 if (nold > 1 || nbins == 1)goto LOK;
329 BinWidth = BinWidth*2;
330 nbins = 1;
331 goto LOK;
332 }
333 if (2*nbins == nold && !optionTime) {ntemp++; goto L20; }
334
335LOK:
338 Int_t oldnbins = nbins;
339
340 Double_t atest = BinWidth*0.0001;
341 //if (TMath::Abs(BinLow-A1) >= atest) { BinLow += BinWidth; nbins--; } //replaced by Damir in 3.10/02
342 //if (TMath::Abs(BinHigh-A2) >= atest) { BinHigh -= BinWidth; nbins--; } //by the next two lines
343 if (al-BinLow >= atest) { BinLow += BinWidth; nbins--; }
344 if (BinHigh-ah >= atest) { BinHigh -= BinWidth; nbins--; }
345 if (!optionTime && BinLow >= BinHigh) {
346 //this case may happen when nbins <=5
349 nbins = oldnbins;
350 }
351 else if (optionTime && BinLow>=BinHigh) {
352 nbins = 2*oldnbins;
355 BinWidth = (oldBinHigh - oldBinLow)/nbins;
356 atest = BinWidth*0.0001;
357 if (al-BinLow >= atest) { BinLow += BinWidth; nbins--; }
358 if (BinHigh-ah >= atest) { BinHigh -= BinWidth; nbins--; }
359 }
360}
361
362////////////////////////////////////////////////////////////////////////////////
363/// Optimize axis limits.
364///
365/// When isInter=kTRUE, the function makes an integer binwidth
366/// and recompute the number of bins accordingly.
367
369{
371 Int_t n=0;
372 Double_t dx = 0.1*(xmax-xmin);
373 if (isInteger) dx = 5*(xmax-xmin)/nbins;
374 Double_t umin = xmin - dx;
375 Double_t umax = xmax + dx;
376 if (umin < 0 && xmin >= 0) umin = 0;
377 if (umax > 0 && xmax <= 0) umax = 0;
378
380
381 if (binwidth <= 0 || binwidth > 1.e+39) {
382 xmin = -1;
383 xmax = 1;
384 } else {
385 xmin = std::min(binlow, xmin - 0.01 * (xmax - xmin));
386 xmax = std::max(binhigh, xmax + 0.01 * (xmax - xmin));
387 }
388 if (isInteger) {
393 if (xmin < 0 && xmin != dxmin) xmin = dxmin - 1;
394 else xmin = dxmin;
395 if (xmax > 0 && xmax != dxmax) xmax = dxmax + 1;
396 else if (xmax ==0 && xmax == dxmax) xmax = 1;
397 else xmax = dxmax;
398 if (xmin >= xmax) xmax = xmin+1;
399 Long64_t bw = Long64_t((xmax-xmin)/nbins);
400 if (bw == 0) bw = 1;
401 nbins = Int_t((xmax-xmin)/bw);
402 if (xmin +nbins*bw < umax) {nbins++; xmax = xmin +nbins*bw;}
403 if (xmin > umin) {nbins++; xmin = xmax -nbins*bw;}
404 }
405 newbins = nbins;
406}
#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