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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "Riostream.h"
00040
00041 #include "RooNonCentralChiSquare.h"
00042 #include "RooAbsReal.h"
00043 #include "RooAbsCategory.h"
00044 #include <math.h>
00045 #include "TMath.h"
00046
00047 #include "Math/DistFunc.h"
00048
00049
00050 #include "RooMsgService.h"
00051
00052 ClassImp(RooNonCentralChiSquare)
00053
00054 RooNonCentralChiSquare::RooNonCentralChiSquare(const char *name, const char *title,
00055 RooAbsReal& _x,
00056 RooAbsReal& _k,
00057 RooAbsReal& _lambda) :
00058 RooAbsPdf(name,title),
00059 x("x","x",this,_x),
00060 k("k","k",this,_k),
00061 lambda("lambda","lambda",this,_lambda),
00062 fErrorTol(1E-3),
00063 fMaxIters(10),
00064 fHasIssuedConvWarning(false),
00065 fHasIssuedSumWarning(false)
00066 {
00067 #ifdef R__HAS_MATHMORE
00068 ccoutD(InputArguments) << "RooNonCentralChiSquare::ctor(" << GetName() <<
00069 "MathMore Available, will use Bessel function expressions unless SetForceSum(true) "<< endl ;
00070 fForceSum = false;
00071 #else
00072 fForceSum = true;
00073 #endif
00074 }
00075
00076 RooNonCentralChiSquare::RooNonCentralChiSquare(const RooNonCentralChiSquare& other, const char* name) :
00077 RooAbsPdf(other,name),
00078 x("x",this,other.x),
00079 k("k",this,other.k),
00080 lambda("lambda",this,other.lambda),
00081 fErrorTol(other.fErrorTol),
00082 fMaxIters(other.fMaxIters),
00083 fHasIssuedConvWarning(false),
00084 fHasIssuedSumWarning(false)
00085 {
00086 #ifdef R__HAS_MATHMORE
00087 ccoutD(InputArguments) << "RooNonCentralChiSquare::ctor(" << GetName() <<
00088 "MathMore Available, will use Bessel function expressions unless SetForceSum(true) "<< endl ;
00089 fForceSum = other.fForceSum;
00090 #else
00091 fForceSum = true;
00092 #endif
00093 }
00094
00095
00096 void RooNonCentralChiSquare::SetForceSum(Bool_t flag) {
00097 fForceSum = flag;
00098 #ifndef R__HAS_MATHMORE
00099 if (!fForceSum) {
00100 ccoutD(InputArguments) << "RooNonCentralChiSquare::SetForceSum" << GetName() <<
00101 "MathMore is not available- ForceSum must be on "<< endl ;
00102 fForceSum = true;
00103 }
00104 #endif
00105
00106 }
00107
00108
00109 Double_t RooNonCentralChiSquare::evaluate() const
00110 {
00111
00112
00113
00114
00115
00116 Double_t xmin = x.min();
00117 Double_t xmax = x.max();
00118 double _x = x;
00119 if(_x<=0){
00120
00121
00122
00123 _x = xmin + 1e-3*(xmax-xmin);
00124 }
00125
00126
00127 if(lambda==0){
00128 return ROOT::Math::chisquared_pdf(_x,k);
00129 }
00130
00131
00132
00133
00134
00135
00136 if ( fForceSum ){
00137 if(!fHasIssuedSumWarning){
00138 coutI(InputArguments) << "RooNonCentralChiSquare sum being forced" << endl ;
00139 fHasIssuedSumWarning=true;
00140 }
00141 double sum = 0;
00142 double ithTerm = 0;
00143 double errorTol = fErrorTol;
00144 int MaxIters = fMaxIters;
00145 int iDominant = (int) TMath::Floor(lambda/2);
00146
00147
00148
00149
00150 for(int i = iDominant; ; ++i){
00151 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)*ROOT::Math::chisquared_pdf(_x,k+2*i)/TMath::Gamma(i+1);
00152 sum+=ithTerm;
00153
00154 if(ithTerm/sum < errorTol)
00155 break;
00156
00157 if( i>iDominant+MaxIters){
00158 if(!fHasIssuedConvWarning){
00159 fHasIssuedConvWarning=true;
00160 coutW(Eval) << "RooNonCentralChiSquare did not converge: for x=" << x <<" k="<<k
00161 << ", lambda="<<lambda << " fractional error = " << ithTerm/sum
00162 << "\n either adjust tolerance with SetErrorTolerance(tol) or max_iter with SetMaxIter(max_it)"
00163 << endl;
00164 }
00165 break;
00166 }
00167 }
00168
00169 for(int i = iDominant - 1; i >= 0; --i){
00170
00171 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)*ROOT::Math::chisquared_pdf(_x,k+2*i)/TMath::Gamma(i+1);
00172 sum+=ithTerm;
00173 }
00174
00175
00176 return sum;
00177 }
00178
00179
00180
00181 #ifdef R__HAS_MATHMORE
00182 return ROOT::Math::noncentral_chisquared_pdf(_x,k,lambda);
00183 #else
00184 coutF(Eval) << "RooNonCentralChisquare: ForceSum must be set" << endl;
00185 return 0;
00186 #endif
00187
00188 }
00189
00190
00191 Int_t RooNonCentralChiSquare::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* ) const
00192 {
00193 if (matchArgs(allVars,analVars,x)) return 1 ;
00194 return 0 ;
00195 }
00196
00197
00198
00199
00200 Double_t RooNonCentralChiSquare::analyticalIntegral(Int_t code, const char* rangeName) const
00201 {
00202 assert(code==1 );
00203
00204 Double_t xmin = x.min(rangeName);
00205 Double_t xmax = x.max(rangeName);
00206
00207
00208
00209
00210 if(lambda==0){
00211 return (ROOT::Math::chisquared_cdf(xmax,k) - ROOT::Math::chisquared_cdf(xmin,k));
00212 }
00213
00214
00215
00216
00217
00218
00219
00220 double sum = 0;
00221 double ithTerm = 0;
00222 double errorTol = fErrorTol;
00223 int MaxIters = fMaxIters;
00224
00225 int iDominant = (int) TMath::Floor(lambda/2);
00226
00227
00228 for(int i = iDominant; ; ++i){
00229 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)
00230 *( ROOT::Math::chisquared_cdf(xmax,k+2*i)/TMath::Gamma(i+1)
00231 - ROOT::Math::chisquared_cdf(xmin,k+2*i)/TMath::Gamma(i+1) );
00232 sum+=ithTerm;
00233
00234 if(ithTerm/sum < errorTol)
00235 break;
00236
00237 if( i>iDominant+MaxIters){
00238 if(!fHasIssuedConvWarning){
00239 fHasIssuedConvWarning=true;
00240 coutW(Eval) << "RooNonCentralChiSquare Normalization did not converge: for k="<<k
00241 << ", lambda="<<lambda << " fractional error = " << ithTerm/sum
00242 << "\n either adjust tolerance with SetErrorTolerance(tol) or max_iter with SetMaxIter(max_it)"
00243 << endl;
00244 }
00245 break;
00246 }
00247 }
00248
00249 for(int i = iDominant - 1; i >= 0; --i){
00250 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)
00251 *( ROOT::Math::chisquared_cdf(xmax,k+2*i)/TMath::Gamma(i+1)
00252 -ROOT::Math::chisquared_cdf(xmin,k+2*i)/TMath::Gamma(i+1) );
00253 sum+=ithTerm;
00254 }
00255 return sum;
00256 }
00257
00258
00259
00260
00261