00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "TH1.h"
00025 #include "TMath.h"
00026 #include "THLimitsFinder.h"
00027
00028 THLimitsFinder *THLimitsFinder::fgLimitsFinder = 0;
00029
00030 ClassImp(THLimitsFinder)
00031
00032
00033 THLimitsFinder::THLimitsFinder()
00034 {
00035 }
00036
00037
00038 THLimitsFinder::~THLimitsFinder()
00039 {
00040 }
00041
00042
00043
00044 Int_t THLimitsFinder::FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax)
00045 {
00046
00047
00048
00049
00050
00051
00052
00053 Int_t newbins;
00054 TAxis *xaxis = h->GetXaxis();
00055
00056 if (xmin >= xmax) {
00057 if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
00058 else {xmin -= 1; xmax += 1;}
00059 }
00060
00061 THLimitsFinder::OptimizeLimits(xaxis->GetNbins(),
00062 newbins,xmin,xmax,
00063 xaxis->TestBit(TAxis::kIsInteger));
00064
00065 h->SetBins(newbins,xmin,xmax);
00066
00067 return 0;
00068 }
00069
00070
00071 Int_t THLimitsFinder::FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax)
00072 {
00073
00074
00075
00076
00077 Int_t newbinsx,newbinsy;
00078 TAxis *xaxis = h->GetXaxis();
00079 TAxis *yaxis = h->GetYaxis();
00080
00081 if (xmin >= xmax) {
00082 if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
00083 else {xmin -= 1; xmax += 1;}
00084 }
00085 if (ymin >= ymax) {
00086 if (yaxis->GetLabels()) {ymin = 0; ymax = ymin +yaxis->GetNbins();}
00087 else {ymin -= 1; ymax += 1;}
00088 }
00089
00090 THLimitsFinder::OptimizeLimits(xaxis->GetNbins(),
00091 newbinsx,xmin,xmax,
00092 xaxis->TestBit(TAxis::kIsInteger));
00093
00094 THLimitsFinder::OptimizeLimits(yaxis->GetNbins(),
00095 newbinsy,ymin,ymax,
00096 yaxis->TestBit(TAxis::kIsInteger));
00097
00098 h->SetBins(newbinsx,xmin,xmax,newbinsy,ymin,ymax);
00099 return 0;
00100 }
00101
00102
00103 Int_t THLimitsFinder::FindGoodLimits(TH1 *h, Double_t xmin, Double_t xmax, Double_t ymin, Double_t ymax, Double_t zmin, Double_t zmax)
00104 {
00105
00106
00107
00108
00109 Int_t newbinsx,newbinsy,newbinsz;
00110 TAxis *xaxis = h->GetXaxis();
00111 TAxis *yaxis = h->GetYaxis();
00112 TAxis *zaxis = h->GetZaxis();
00113
00114 if (xmin >= xmax) {
00115 if (xaxis->GetLabels()) {xmin = 0; xmax = xmin +xaxis->GetNbins();}
00116 else {xmin -= 1; xmax += 1;}
00117 }
00118 if (ymin >= ymax) {
00119 if (yaxis->GetLabels()) {ymin = 0; ymax = ymin +yaxis->GetNbins();}
00120 else {ymin -= 1; ymax += 1;}
00121 }
00122 if (zmin >= zmax) {
00123 if (zaxis->GetLabels()) {zmin = 0; zmax = zmin +zaxis->GetNbins();}
00124 else {zmin -= 1; zmax += 1;}
00125 }
00126
00127 THLimitsFinder::OptimizeLimits(xaxis->GetNbins(),
00128 newbinsx,xmin,xmax,
00129 xaxis->TestBit(TAxis::kIsInteger));
00130
00131 THLimitsFinder::OptimizeLimits(yaxis->GetNbins(),
00132 newbinsy,ymin,ymax,
00133 yaxis->TestBit(TAxis::kIsInteger));
00134
00135 THLimitsFinder::OptimizeLimits(zaxis->GetNbins(),
00136 newbinsz,zmin,zmax,
00137 zaxis->TestBit(TAxis::kIsInteger));
00138
00139 h->SetBins(newbinsx,xmin,xmax,newbinsy,ymin,ymax,newbinsz,zmin,zmax);
00140 return 0;
00141 }
00142
00143
00144 THLimitsFinder *THLimitsFinder::GetLimitsFinder()
00145 {
00146
00147
00148
00149
00150 if (!fgLimitsFinder) fgLimitsFinder = new THLimitsFinder();
00151 return fgLimitsFinder;
00152 }
00153
00154
00155 void THLimitsFinder::SetLimitsFinder(THLimitsFinder *finder)
00156 {
00157
00158
00159
00160
00161 fgLimitsFinder = finder;
00162 }
00163
00164
00165 void THLimitsFinder::Optimize(Double_t A1, Double_t A2, Int_t nold ,Double_t &BinLow, Double_t &BinHigh,
00166 Int_t &nbins, Double_t &BinWidth, Option_t *option)
00167 {
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 Int_t lwid, kwid;
00178 Int_t ntemp = 0;
00179 Int_t jlog = 0;
00180 Double_t siground = 0;
00181 Double_t alb, awidth, sigfig;
00182 Double_t timemulti = 1;
00183 Int_t roundmode =0;
00184
00185 Int_t optionTime;
00186 if(strchr(option,'t')) optionTime = 1; else optionTime = 0;
00187
00188 nbins = nold;
00189
00190 Double_t al = TMath::Min(A1,A2);
00191 Double_t ah = TMath::Max(A1,A2);
00192 if (al == ah) ah = al+1;
00193
00194 if (nold == -1 && BinWidth > 0 ) goto L90;
00195 ntemp = TMath::Max(nold,2);
00196 if (ntemp < 1) ntemp = 1;
00197
00198 L20:
00199 awidth = (ah-al)/Double_t(ntemp);
00200 timemulti = 1;
00201 if (awidth >= FLT_MAX) goto LOK;
00202 if (awidth <= 0) goto LOK;
00203
00204
00205
00206
00207 if (optionTime && awidth>=60) {
00208
00209 awidth /= 60; timemulti *=60;
00210 roundmode = 1;
00211
00212 if (awidth>=60) {
00213 awidth /= 60; timemulti *= 60;
00214 roundmode = 2;
00215
00216 if (awidth>=24) {
00217 awidth /= 24; timemulti *= 24;
00218 roundmode = 3;
00219
00220 if (awidth>=30.43685) {
00221 awidth /= 30.43685; timemulti *= 30.43685;
00222 roundmode = 2;
00223
00224 if (awidth>=12) {
00225 awidth /= 12; timemulti *= 12;
00226 roundmode = 0;
00227 }
00228 }
00229 }
00230 }
00231 }
00232
00233
00234 jlog = Int_t(TMath::Log10(awidth));
00235 if (jlog <-200 || jlog > 200) {
00236 BinLow = 0;
00237 BinHigh = 1;
00238 BinWidth = 0.01;
00239 nbins = 100;
00240 return;
00241 }
00242 if (awidth <= 1 && (!optionTime || timemulti==1) ) jlog--;
00243 sigfig = awidth*TMath::Power(10,-jlog) -1e-10;
00244
00245
00246
00247
00248
00249 switch (roundmode) {
00250
00251
00252 case 1:
00253 if (sigfig <= 1) siground = 1;
00254 else if (sigfig <= 1.5 && jlog==1) siground = 1.5;
00255 else if (sigfig <= 2) siground = 2;
00256 else if (sigfig <= 3 && jlog ==1) siground = 3;
00257 else if (sigfig <= 5 && sigfig>3 && jlog ==0) siground = 5;
00258 else if (jlog==0) {siground = 1; jlog++;}
00259 else siground = 6;
00260 break;
00261 case 2:
00262
00263
00264 if (sigfig <= 1 && jlog==0) siground = 1;
00265 else if (sigfig <= 1.2 && jlog==1) siground = 1.2;
00266 else if (sigfig <= 2 && jlog==0) siground = 2;
00267 else if (sigfig <= 2.4 && jlog==1) siground = 2.4;
00268 else if (sigfig <= 3) siground = 3;
00269 else if (sigfig <= 6) siground = 6;
00270 else if (jlog==0) siground = 12;
00271 else siground = 2.4;
00272 break;
00273
00274
00275 case 3:
00276 if (sigfig <= 1 && jlog==0) siground = 1;
00277 else if (sigfig <= 1.4 && jlog==1) siground = 1.4;
00278 else if (sigfig <= 3 && jlog ==1) siground = 3;
00279 else siground = 7;
00280 break;
00281 default :
00282
00283
00284 if (sigfig <= 1) siground = 1;
00285 else if (sigfig <= 2) siground = 2;
00286 else if (sigfig <= 5 && (!optionTime || jlog<1)) siground = 5;
00287 else if (sigfig <= 6 && optionTime && jlog==1) siground = 6;
00288 else {siground = 1; jlog++; }
00289 break;
00290 }
00291
00292 BinWidth = siground*TMath::Power(10,jlog);
00293 if (optionTime) BinWidth *= timemulti;
00294
00295
00296
00297 L90:
00298 alb = al/BinWidth;
00299 if (TMath::Abs(alb) > 1e9) {
00300 BinLow = al;
00301 BinHigh = ah;
00302 if (nbins > 10*nold && nbins > 10000) nbins = nold;
00303 return;
00304 }
00305 lwid = Int_t(alb);
00306 if (alb < 0) lwid--;
00307 BinLow = BinWidth*Double_t(lwid);
00308 alb = ah/BinWidth + 1.00001;
00309 kwid = Int_t(alb);
00310 if (alb < 0) kwid--;
00311 BinHigh = BinWidth*Double_t(kwid);
00312 nbins = kwid - lwid;
00313 if (nold == -1) goto LOK;
00314 if (nold <= 5) {
00315 if (nold > 1 || nbins == 1)goto LOK;
00316 BinWidth = BinWidth*2;
00317 nbins = 1;
00318 goto LOK;
00319 }
00320 if (2*nbins == nold && !optionTime) {ntemp++; goto L20; }
00321
00322 LOK:
00323 Double_t oldBinLow = BinLow;
00324 Double_t oldBinHigh = BinHigh;
00325 Int_t oldnbins = nbins;
00326
00327 Double_t atest = BinWidth*0.0001;
00328
00329
00330 if (al-BinLow >= atest) { BinLow += BinWidth; nbins--; }
00331 if (BinHigh-ah >= atest) { BinHigh -= BinWidth; nbins--; }
00332 if (!optionTime && BinLow >= BinHigh) {
00333
00334 BinLow = oldBinLow;
00335 BinHigh = oldBinHigh;
00336 nbins = oldnbins;
00337 }
00338 else if (optionTime && BinLow>=BinHigh) {
00339 nbins = 2*oldnbins;
00340 BinHigh = oldBinHigh;
00341 BinLow = oldBinLow;
00342 BinWidth = (oldBinHigh - oldBinLow)/nbins;
00343 atest = BinWidth*0.0001;
00344 if (al-BinLow >= atest) { BinLow += BinWidth; nbins--; }
00345 if (BinHigh-ah >= atest) { BinHigh -= BinWidth; nbins--; }
00346 }
00347 }
00348
00349
00350 void THLimitsFinder::OptimizeLimits(Int_t nbins, Int_t &newbins, Double_t &xmin, Double_t &xmax, Bool_t isInteger)
00351 {
00352
00353
00354
00355
00356 Double_t binlow,binhigh,binwidth=0;
00357 Int_t n=0;
00358 Double_t dx = 0.1*(xmax-xmin);
00359 if (isInteger) dx = 5*(xmax-xmin)/nbins;
00360 Double_t umin = xmin - dx;
00361 Double_t umax = xmax + dx;
00362 if (umin < 0 && xmin >= 0) umin = 0;
00363 if (umax > 0 && xmax <= 0) umax = 0;
00364
00365 THLimitsFinder::Optimize(umin,umax,nbins,binlow,binhigh,n,binwidth,"");
00366
00367 if (binwidth <= 0 || binwidth > 1.e+39) {
00368 xmin = -1;
00369 xmax = 1;
00370 } else {
00371 xmin = binlow;
00372 xmax = binhigh;
00373 }
00374 if (isInteger) {
00375 Int_t ixmin = Int_t(xmin);
00376 Int_t ixmax = Int_t(xmax);
00377 Double_t dxmin = Double_t(ixmin);
00378 Double_t dxmax = Double_t(ixmax);
00379 if (xmin < 0 && xmin != dxmin) xmin = dxmin - 1;
00380 else xmin = dxmin;
00381 if (xmax > 0 && xmax != dxmax) xmax = dxmax + 1;
00382 else if (xmax ==0 && xmax == dxmax) xmax = 1;
00383 else xmax = dxmax;
00384 if (xmin >= xmax) xmax = xmin+1;
00385 Int_t bw = Int_t((xmax-xmin)/nbins);
00386 if (bw == 0) bw = 1;
00387 nbins = Int_t((xmax-xmin)/bw);
00388 if (xmin +nbins*bw < umax) {nbins++; xmax = xmin +nbins*bw;}
00389 if (xmin > umin) {nbins++; xmin = xmax -nbins*bw;}
00390 }
00391 newbins = nbins;
00392 }