00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "RooFit.h"
00027
00028 #include "RooHistError.h"
00029 #include "RooBrentRootFinder.h"
00030 #include "RooMsgService.h"
00031 #include "TMath.h"
00032
00033 #include "Riostream.h"
00034 #include <assert.h>
00035
00036 ClassImp(RooHistError)
00037 ;
00038
00039
00040
00041
00042 const RooHistError &RooHistError::instance()
00043 {
00044
00045
00046
00047
00048 static RooHistError _theInstance;
00049 return _theInstance;
00050 }
00051
00052
00053
00054 RooHistError::RooHistError()
00055 {
00056
00057
00058
00059 Int_t i ;
00060 for (i=0 ; i<1000 ; i++) {
00061 getPoissonIntervalCalc(i,_poissonLoLUT[i],_poissonHiLUT[i],1.) ;
00062 }
00063
00064 }
00065
00066
00067
00068
00069 Bool_t RooHistError::getPoissonInterval(Int_t n, Double_t &mu1, Double_t &mu2, Double_t nSigma) const
00070 {
00071
00072
00073
00074
00075
00076
00077
00078
00079 if (n<1000 && nSigma==1.) {
00080 mu1=_poissonLoLUT[n] ;
00081 mu2=_poissonHiLUT[n] ;
00082 return kTRUE ;
00083 }
00084
00085
00086 Bool_t ret = getPoissonIntervalCalc(n,mu1,mu2,nSigma) ;
00087 return ret ;
00088 }
00089
00090
00091
00092
00093 Bool_t RooHistError::getPoissonIntervalCalc(Int_t n, Double_t &mu1, Double_t &mu2, Double_t nSigma) const
00094 {
00095
00096
00097
00098
00099
00100
00101
00102 if(n < 0) {
00103 oocoutE((TObject*)0,Plotting) << "RooHistError::getPoissonInterval: cannot calculate interval for n = " << n << endl;
00104 return kFALSE;
00105 }
00106
00107
00108 if(n > 100) {
00109 mu1= n - sqrt(n+0.25) + 0.5;
00110 mu2= n + sqrt(n+0.25) + 0.5;
00111 return kTRUE;
00112 }
00113
00114
00115 PoissonSum upper(n);
00116 if(n > 0) {
00117 PoissonSum lower(n-1);
00118 return getInterval(&upper,&lower,(Double_t)n,1.0,mu1,mu2,nSigma);
00119 }
00120
00121
00122 return getInterval(&upper,0,(Double_t)n,1.0,mu1,mu2,nSigma);
00123 }
00124
00125
00126
00127 Bool_t RooHistError::getBinomialIntervalAsym(Int_t n, Int_t m,
00128 Double_t &asym1, Double_t &asym2, Double_t nSigma) const
00129 {
00130
00131
00132
00133
00134 if(n < 0 || m < 0) {
00135 oocoutE((TObject*)0,Plotting) << "RooHistError::getPoissonInterval: cannot calculate interval for n,m = " << n << "," << m << endl;
00136 return kFALSE;
00137 }
00138
00139
00140 if(n == 0 && m == 0) {
00141 asym1= -1;
00142 asym2= +1;
00143 return kTRUE;
00144 }
00145
00146
00147 if ((n>100&&m>100)) {
00148 Double_t N = n ;
00149 Double_t M = m ;
00150 Double_t asym = 1.0*(N-M)/(N+M) ;
00151 Double_t approxErr = sqrt(4.0*n/(N+M)*(1-N/(N+M))/(N+M)) ;
00152
00153 asym1 = asym-nSigma*approxErr ;
00154 asym2 = asym+nSigma*approxErr ;
00155 return kTRUE ;
00156 }
00157
00158
00159 Bool_t swapped(kFALSE);
00160 if(n > m) {
00161 swapped= kTRUE;
00162 Int_t tmp(m);
00163 m= n;
00164 n= tmp;
00165 }
00166
00167
00168 Bool_t status(kFALSE);
00169 BinomialSumAsym upper(n,m);
00170 if(n > 0) {
00171 BinomialSumAsym lower(n-1,m+1);
00172 status= getInterval(&upper,&lower,(Double_t)(n-m)/(n+m),0.1,asym1,asym2,nSigma);
00173 }
00174 else {
00175 status= getInterval(&upper,0,(Double_t)(n-m)/(n+m),0.1,asym1,asym2,nSigma);
00176 }
00177
00178
00179 if(swapped) {
00180 Double_t tmp(asym1);
00181 asym1= -asym2;
00182 asym2= -tmp;
00183 }
00184
00185 return status;
00186 }
00187
00188
00189
00190 Bool_t RooHistError::getBinomialIntervalEff(Int_t n, Int_t m,
00191 Double_t &asym1, Double_t &asym2, Double_t nSigma) const
00192 {
00193
00194
00195
00196
00197 if(n < 0 || m < 0) {
00198 oocoutE((TObject*)0,Plotting) << "RooHistError::getPoissonInterval: cannot calculate interval for n,m = " << n << "," << m << endl;
00199 return kFALSE;
00200 }
00201
00202
00203 if(n == 0 && m == 0) {
00204 asym1= -1;
00205 asym2= +1;
00206 return kTRUE;
00207 }
00208
00209
00210 if ((n>80&&m>80)) {
00211 Double_t N = n ;
00212 Double_t M = m ;
00213 Double_t asym = 1.0*(N)/(N+M) ;
00214 Double_t approxErr = sqrt(4.0*n/(N+M)*(1-N/(N+M))/(N+M)) ;
00215
00216 asym1 = asym-nSigma*approxErr ;
00217 asym2 = asym+nSigma*approxErr ;
00218 return kTRUE ;
00219 }
00220
00221
00222 Bool_t swapped(kFALSE);
00223 if(n > m) {
00224 swapped= kTRUE;
00225 Int_t tmp(m);
00226 m= n;
00227 n= tmp;
00228 }
00229
00230
00231 Bool_t status(kFALSE);
00232 BinomialSumEff upper(n,m);
00233 Double_t eff = (Double_t)(n)/(n+m) ;
00234 if(n > 0) {
00235 BinomialSumEff lower(n-1,m+1);
00236 status= getInterval(&upper,&lower,eff,0.1,asym1,asym2,nSigma);
00237 }
00238 else {
00239 status= getInterval(&upper,0,eff,0.1,asym1,asym2,nSigma);
00240 }
00241
00242
00243 if(swapped) {
00244 Double_t tmp(asym1);
00245 asym1= 1-asym2;
00246 asym2= 1-tmp;
00247 }
00248
00249 return status;
00250 }
00251
00252
00253
00254
00255 Bool_t RooHistError::getInterval(const RooAbsFunc *Qu, const RooAbsFunc *Ql, Double_t pointEstimate,
00256 Double_t stepSize, Double_t &lo, Double_t &hi, Double_t nSigma) const
00257 {
00258
00259
00260
00261
00262
00263
00264 assert(0 != Qu || 0 != Ql);
00265
00266
00267 Double_t beta= TMath::Erf(nSigma/sqrt(2.));
00268 Double_t alpha= 0.5*(1-beta);
00269
00270
00271 Bool_t ok(kTRUE);
00272 Double_t loProb(1),hiProb(0);
00273 if(0 != Ql) loProb= (*Ql)(&pointEstimate);
00274 if(0 != Qu) hiProb= (*Qu)(&pointEstimate);
00275
00276 if (Qu && (0 == Ql || loProb > alpha + beta)) {
00277
00278 lo= pointEstimate;
00279 Double_t target= loProb - beta;
00280 hi= seek(*Qu,lo,+stepSize,target);
00281 RooBrentRootFinder uFinder(*Qu);
00282 ok= uFinder.findRoot(hi,hi-stepSize,hi,target);
00283 }
00284 else if(Ql && (0 == Qu || hiProb < alpha)) {
00285
00286 hi= pointEstimate;
00287 Double_t target= hiProb + beta;
00288 lo= seek(*Ql,hi,-stepSize,target);
00289 RooBrentRootFinder lFinder(*Ql);
00290 ok= lFinder.findRoot(lo,lo,lo+stepSize,target);
00291 }
00292 else if (Qu && Ql) {
00293
00294 lo= seek(*Ql,pointEstimate,-stepSize,alpha+beta);
00295 hi= seek(*Qu,pointEstimate,+stepSize,alpha);
00296 RooBrentRootFinder lFinder(*Ql),uFinder(*Qu);
00297 ok= lFinder.findRoot(lo,lo,lo+stepSize,alpha+beta);
00298 ok|= uFinder.findRoot(hi,hi-stepSize,hi,alpha);
00299 }
00300 if(!ok) oocoutE((TObject*)0,Plotting) << "RooHistError::getInterval: failed to find root(s)" << endl;
00301
00302 return ok;
00303 }
00304
00305
00306
00307 Double_t RooHistError::seek(const RooAbsFunc &f, Double_t startAt, Double_t step, Double_t value) const
00308 {
00309
00310
00311
00312 Int_t steps(1000);
00313 Double_t min(f.getMinLimit(1)),max(f.getMaxLimit(1));
00314 Double_t x(startAt), f0= f(&startAt) - value;
00315 do {
00316 x+= step;
00317 }
00318 while(steps-- && (f0*(f(&x)-value) >= 0) && ((x-min)*(max-x) >= 0));
00319 assert(0 != steps);
00320 if(x < min) x= min;
00321 if(x > max) x= max;
00322
00323 return x;
00324 }
00325
00326
00327
00328
00329 RooAbsFunc *RooHistError::createPoissonSum(Int_t n)
00330 {
00331
00332
00333 return new PoissonSum(n);
00334 }
00335
00336
00337
00338 RooAbsFunc *RooHistError::createBinomialSum(Int_t n, Int_t m, Bool_t eff)
00339 {
00340
00341 if (eff) {
00342 return new BinomialSumEff(n,m) ;
00343 } else {
00344 return new BinomialSumAsym(n,m) ;
00345 }
00346 }