Logo ROOT   6.08/07
Reference Guide
RooNonCentralChiSquare.cxx
Go to the documentation of this file.
1 /*****************************************************************************
2  * Project: RooFit *
3  * Package: RooFitModels *
4  * @(#)root/roofit:$Id: RooNonCentralChiSquare *
5  * Authors: *
6  * Kyle Cranmer
7  * *
8  *****************************************************************************/
9 
10 /**
11 \file RooNonCentralChiSquare.cxx
12 \class RooNonCentralChiSquare
13 \ingroup Roofit
14 
15 The PDF of the Non-Central Chi Square distribution for n degrees of freedom.
16 It is the asymptotic distribution of the profile likeihood ratio test q_mu
17 when a different mu' is true. It is Wald's generalization of Wilks' Theorem.
18 
19 See:
20  Asymptotic formulae for likelihood-based tests of new physics
21  By Glen Cowan, Kyle Cranmer, Eilam Gross, Ofer Vitells
22  http://arXiv.org/abs/arXiv:1007.1727
23 
24  Wikipedia:
25  http://en.wikipedia.org/wiki/Noncentral_chi-square_distribution#Approximation
26 
27 It requires MathMore to evaluate for non-integer degrees of freedom, k.
28 
29 When the Mathmore library is available we can use the MathMore libraries impelmented using GSL.
30 It makes use of the modified Bessel function of the first kind (for k > 2). For k < 2 it uses
31 the hypergeometric function 0F1.
32 When is not available we use explicit summation of normal chi-squared distributions
33 The usage of the sum can be forced by calling SetForceSum(true);
34 
35 This implementation could be improved. BOOST has a nice implementation:
36 http://live.boost.org/doc/libs/1_42_0/libs/math/doc/sf_and_dist/html/math_toolkit/dist/dist_ref/dists/nc_chi_squared_dist.html
37 http://wesnoth.repositoryhosting.com/trac/wesnoth_wesnoth/browser/trunk/include/boost/math/distributions/non_central_chi_squared.hpp?rev=6
38 **/
39 
40 #include "Riostream.h"
41 
42 #include "RooNonCentralChiSquare.h"
43 #include "RooAbsReal.h"
44 #include "RooAbsCategory.h"
45 #include <math.h>
46 #include "TMath.h"
47 //#include "RooNumber.h"
48 #include "Math/DistFunc.h"
49 
50 
51 #include "RooMsgService.h"
52 
53 #include "TError.h"
54 
55 using namespace std;
56 
58 
59 RooNonCentralChiSquare::RooNonCentralChiSquare(const char *name, const char *title,
60  RooAbsReal& _x,
61  RooAbsReal& _k,
62  RooAbsReal& _lambda) :
63  RooAbsPdf(name,title),
64  x("x","x",this,_x),
65  k("k","k",this,_k),
66  lambda("lambda","lambda",this,_lambda),
67  fErrorTol(1E-3),
68  fMaxIters(10),
69  fHasIssuedConvWarning(false),
70  fHasIssuedSumWarning(false)
71 {
72 #ifdef R__HAS_MATHMORE
73  ccoutD(InputArguments) << "RooNonCentralChiSquare::ctor(" << GetName() <<
74  "MathMore Available, will use Bessel function expressions unless SetForceSum(true) "<< endl ;
75  fForceSum = false;
76 #else
77  fForceSum = true;
78 #endif
79 }
80 
82  RooAbsPdf(other,name),
83  x("x",this,other.x),
84  k("k",this,other.k),
85  lambda("lambda",this,other.lambda),
86  fErrorTol(other.fErrorTol),
87  fMaxIters(other.fMaxIters),
88  fHasIssuedConvWarning(false),
89  fHasIssuedSumWarning(false)
90 {
91 #ifdef R__HAS_MATHMORE
92  ccoutD(InputArguments) << "RooNonCentralChiSquare::ctor(" << GetName() <<
93  "MathMore Available, will use Bessel function expressions unless SetForceSum(true) "<< endl ;
94  fForceSum = other.fForceSum;
95 #else
96  fForceSum = true;
97 #endif
98 }
99 
100 
102  fForceSum = flag;
103 #ifndef R__HAS_MATHMORE
104  if (!fForceSum) {
105  ccoutD(InputArguments) << "RooNonCentralChiSquare::SetForceSum" << GetName() <<
106  "MathMore is not available- ForceSum must be on "<< endl ;
107  fForceSum = true;
108  }
109 #endif
110 
111 }
112 
113 
115 {
116  // ENTER EXPRESSION IN TERMS OF VARIABLE ARGUMENTS HERE
117 
118 
119  // chi^2(0,k) gives inf and causes various problems
120  // truncate
121  Double_t xmin = x.min();
122  Double_t xmax = x.max();
123  double _x = x;
124  if(_x<=0){
125  // options for dealing with this
126  // return 0; // gives a funny dip
127  // _x = 1./RooNumber::infinity(); // too tall
128  _x = xmin + 1e-3*(xmax-xmin); // very small fraction of range
129  }
130 
131  // special case (form below doesn't work when lambda==0)
132  if(lambda==0){
133  return ROOT::Math::chisquared_pdf(_x,k);
134  }
135 
136  // three forms
137  // FIRST FORM
138  // \sum_i=0^\infty exp(-lambda/2) (\lamda/2)^i chi2(x,k+2i) / i!
139  // could truncate sum
140 
141  if ( fForceSum ){
143  coutI(InputArguments) << "RooNonCentralChiSquare sum being forced" << endl ;
145  }
146  double sum = 0;
147  double ithTerm = 0;
148  double errorTol = fErrorTol;
149  int MaxIters = fMaxIters;
150  int iDominant = (int) TMath::Floor(lambda/2);
151  // cout <<"iDominant: " << iDominant << endl;
152 
153  // do 0th term last
154  // if(iDominant==0) iDominant = 1;
155  for(int i = iDominant; ; ++i){
156  ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)*ROOT::Math::chisquared_pdf(_x,k+2*i)/TMath::Gamma(i+1);
157  sum+=ithTerm;
158  // cout <<"progress: " << i << " " << ithTerm/sum << endl;
159  if(ithTerm/sum < errorTol)
160  break;
161 
162  if( i>iDominant+MaxIters){
165  coutW(Eval) << "RooNonCentralChiSquare did not converge: for x=" << x <<" k="<<k
166  << ", lambda="<<lambda << " fractional error = " << ithTerm/sum
167  << "\n either adjust tolerance with SetErrorTolerance(tol) or max_iter with SetMaxIter(max_it)"
168  << endl;
169  }
170  break;
171  }
172  }
173 
174  for(int i = iDominant - 1; i >= 0; --i){
175  // cout <<"Progress: " << i << " " << ithTerm/sum << endl;
176  ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)*ROOT::Math::chisquared_pdf(_x,k+2*i)/TMath::Gamma(i+1);
177  sum+=ithTerm;
178  }
179 
180 
181  return sum;
182  }
183 
184  // SECOND FORM (use MathMore function based on Bessel function (if k>2) or
185  // or regularized confluent hypergeometric limit function.
186 #ifdef R__HAS_MATHMORE
188 #else
189  coutF(Eval) << "RooNonCentralChisquare: ForceSum must be set" << endl;
190  return 0;
191 #endif
192 
193 }
194 
195 ////////////////////////////////////////////////////////////////////////////////
196 
197 Int_t RooNonCentralChiSquare::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const
198 {
199  if (matchArgs(allVars,analVars,x)) return 1 ;
200  return 0 ;
201 }
202 
203 
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 
207 Double_t RooNonCentralChiSquare::analyticalIntegral(Int_t code, const char* rangeName) const
208 {
209  R__ASSERT(code==1 );
210  // cout << "evaluating analytic integral" << endl;
211  Double_t xmin = x.min(rangeName);
212  Double_t xmax = x.max(rangeName);
213 
214  // if xmin~0 and xmax big, then can return 1. b/c evaluate is normalized.
215 
216  // special case (form below doesn't work when lambda==0)
217  if(lambda==0){
219  }
220 
221  // three forms
222  // FIRST FORM
223  // \sum_i=0^\infty exp(-lambda/2) (\lamda/2)^i chi2(x,k+2i) / i!
224  // could truncate sum
225 
226 
227  double sum = 0;
228  double ithTerm = 0;
229  double errorTol = fErrorTol; // for nomralization allow slightly larger error
230  int MaxIters = fMaxIters; // for normalization use more terms
231 
232  int iDominant = (int) TMath::Floor(lambda/2);
233  // cout <<"iDominant: " << iDominant << endl;
234  // iDominant=0;
235  for(int i = iDominant; ; ++i){
236  ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)
237  *( ROOT::Math::chisquared_cdf(xmax,k+2*i)/TMath::Gamma(i+1)
238  - ROOT::Math::chisquared_cdf(xmin,k+2*i)/TMath::Gamma(i+1) );
239  sum+=ithTerm;
240  // cout <<"progress: " << i << " " << ithTerm << " " << sum << endl;
241  if(ithTerm/sum < errorTol)
242  break;
243 
244  if( i>iDominant+MaxIters){
247  coutW(Eval) << "RooNonCentralChiSquare Normalization did not converge: for k="<<k
248  << ", lambda="<<lambda << " fractional error = " << ithTerm/sum
249  << "\n either adjust tolerance with SetErrorTolerance(tol) or max_iter with SetMaxIter(max_it)"
250  << endl;
251  }
252  break;
253  }
254  }
255 
256  for(int i = iDominant - 1; i >= 0; --i){
257  ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)
258  *( ROOT::Math::chisquared_cdf(xmax,k+2*i)/TMath::Gamma(i+1)
259  -ROOT::Math::chisquared_cdf(xmin,k+2*i)/TMath::Gamma(i+1) );
260  sum+=ithTerm;
261  }
262  return sum;
263 }
264 
265 
266 
267 
268 
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
std::string GetName(const std::string &scope_name)
Definition: Cppyy.cxx:140
static long int sum(long int i)
Definition: Factory.cxx:1786
float xmin
Definition: THbookFile.cxx:93
Double_t Floor(Double_t x)
Definition: TMath.h:473
double chisquared_pdf(double x, double r, double x0=0)
Probability density function of the distribution with degrees of freedom.
Bool_t matchArgs(const RooArgSet &allDeps, RooArgSet &numDeps, const RooArgProxy &a) const
Utility function for use in getAnalyticalIntegral().
#define coutI(a)
Definition: RooMsgService.h:32
#define R__ASSERT(e)
Definition: TError.h:98
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Double_t Gamma(Double_t z)
Computation of gamma(z) for all z.
Definition: TMath.cxx:352
STL namespace.
#define coutW(a)
Definition: RooMsgService.h:34
The PDF of the Non-Central Chi Square distribution for n degrees of freedom.
Double_t x[n]
Definition: legend1.C:17
double pow(double, double)
Double_t E()
Definition: TMath.h:54
float xmax
Definition: THbookFile.cxx:93
#define coutF(a)
Definition: RooMsgService.h:36
double noncentral_chisquared_pdf(double x, double r, double lambda)
Probability density function of the non central distribution with degrees of freedom and the noon-c...
#define ClassImp(name)
Definition: Rtypes.h:279
Double_t min(const char *rname=0) const
Definition: RooRealProxy.h:56
double Double_t
Definition: RtypesCore.h:55
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:53
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
Double_t max(const char *rname=0) const
Definition: RooRealProxy.h:57
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &analVars, const char *rangeName=0) const
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported...
RooAbsPdf is the abstract interface for all probability density functions The class provides hybrid a...
Definition: RooAbsPdf.h:41
Double_t analyticalIntegral(Int_t code, const char *rangeName=0) const
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral. ...
double chisquared_cdf(double x, double r, double x0=0)
Cumulative distribution function of the distribution with degrees of freedom (lower tail)...
double exp(double)
#define ccoutD(a)
Definition: RooMsgService.h:38
char name[80]
Definition: TGX11.cxx:109