Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
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/** \class RooNonCentralChiSquare
11 \ingroup Roofit
12
13The PDF of the Non-Central Chi Square distribution for n degrees of freedom.
14It is the asymptotic distribution of the profile likelihood ratio test q_mu
15when a different mu' is true. It is Wald's generalization of Wilks' Theorem.
16
17See:
18
19 Asymptotic formulae for likelihood-based tests of new physics
20
21 By Glen Cowan, Kyle Cranmer, Eilam Gross, Ofer Vitells
22 http://arXiv.org/abs/arXiv:1007.1727
23
24 [Wikipedia](http://en.wikipedia.org/wiki/Noncentral_chi-square_distribution#Approximation)
25
26It requires MathMore to evaluate for non-integer degrees of freedom, k.
27
28When the Mathmore library is available we can use the MathMore libraries implemented using GSL.
29It makes use of the modified Bessel function of the first kind (for k > 2). For k < 2 it uses
30the hypergeometric function 0F1.
31When is not available we use explicit summation of normal chi-squared distributions
32The usage of the sum can be forced by calling SetForceSum(true);
33
34This implementation could be improved. BOOST has a nice implementation:
35
36http://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
38http://wesnoth.repositoryhosting.com/trac/wesnoth_wesnoth/browser/trunk/include/boost/math/distributions/non_central_chi_squared.hpp?rev=6
39**/
40
41#include "Riostream.h"
42
44#include "RooAbsReal.h"
45#include "RooAbsCategory.h"
46#include <cmath>
47#include "TMath.h"
48//#include "RooNumber.h"
49#include "Math/DistFunc.h"
50
51
52#include "RooMsgService.h"
53
54#include "TError.h"
55
56using namespace std;
57
59
60////////////////////////////////////////////////////////////////////////////////
61
63 RooAbsReal& _x,
64 RooAbsReal& _k,
65 RooAbsReal& _lambda) :
66 RooAbsPdf(name,title),
67 x("x","x",this,_x),
68 k("k","k",this,_k),
69 lambda("lambda","lambda",this,_lambda),
70 fErrorTol(1E-3),
71 fMaxIters(10),
72 fHasIssuedConvWarning(false),
73 fHasIssuedSumWarning(false)
74{
75 ccoutD(InputArguments) << "RooNonCentralChiSquare::ctor(" << GetName() <<
76 "MathMore Available, will use Bessel function expressions unless SetForceSum(true) "<< endl ;
77 fForceSum = false;
78}
79
80////////////////////////////////////////////////////////////////////////////////
81
83 RooAbsPdf(other,name),
84 x("x",this,other.x),
85 k("k",this,other.k),
86 lambda("lambda",this,other.lambda),
87 fErrorTol(other.fErrorTol),
88 fMaxIters(other.fMaxIters),
89 fHasIssuedConvWarning(false),
90 fHasIssuedSumWarning(false)
91{
92 ccoutD(InputArguments) << "RooNonCentralChiSquare::ctor(" << GetName() <<
93 "MathMore Available, will use Bessel function expressions unless SetForceSum(true) "<< endl ;
94 fForceSum = other.fForceSum;
95}
96
97////////////////////////////////////////////////////////////////////////////////
98
100 fForceSum = flag;
101}
102
103////////////////////////////////////////////////////////////////////////////////
104
106{
107 // ENTER EXPRESSION IN TERMS OF VARIABLE ARGUMENTS HERE
108
109
110 // chi^2(0,k) gives inf and causes various problems
111 // truncate
112 double xmin = x.min();
113 double xmax = x.max();
114 double _x = x;
115 if(_x<=0){
116 // options for dealing with this
117 // return 0; // gives a funny dip
118 // _x = 1./RooNumber::infinity(); // too tall
119 _x = xmin + 1e-3*(xmax-xmin); // very small fraction of range
120 }
121
122 // special case (form below doesn't work when lambda==0)
123 if(lambda==0){
124 return ROOT::Math::chisquared_pdf(_x,k);
125 }
126
127 // three forms
128 // FIRST FORM
129 // \sum_i=0^\infty exp(-lambda/2) (\lamda/2)^i chi2(x,k+2i) / i!
130 // could truncate sum
131
132 if ( fForceSum ){
134 coutI(InputArguments) << "RooNonCentralChiSquare sum being forced" << endl ;
136 }
137 double sum = 0;
138 double ithTerm = 0;
139 double errorTol = fErrorTol;
140 int MaxIters = fMaxIters;
141 int iDominant = (int) TMath::Floor(lambda/2);
142 // cout <<"iDominant: " << iDominant << endl;
143
144 // do 0th term last
145 // if(iDominant==0) iDominant = 1;
146 for(int i = iDominant; ; ++i){
147 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)*ROOT::Math::chisquared_pdf(_x,k+2*i)/TMath::Gamma(i+1);
148 sum+=ithTerm;
149 // cout <<"progress: " << i << " " << ithTerm/sum << endl;
150 if(ithTerm/sum < errorTol)
151 break;
152
153 if( i>iDominant+MaxIters){
156 coutW(Eval) << "RooNonCentralChiSquare did not converge: for x=" << x <<" k="<<k
157 << ", lambda="<<lambda << " fractional error = " << ithTerm/sum
158 << "\n either adjust tolerance with SetErrorTolerance(tol) or max_iter with SetMaxIter(max_it)"
159 << endl;
160 }
161 break;
162 }
163 }
164
165 for(int i = iDominant - 1; i >= 0; --i){
166 // cout <<"Progress: " << i << " " << ithTerm/sum << endl;
167 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)*ROOT::Math::chisquared_pdf(_x,k+2*i)/TMath::Gamma(i+1);
168 sum+=ithTerm;
169 }
170
171
172 return sum;
173 }
174
175 // SECOND FORM (use MathMore function based on Bessel function (if k>2) or
176 // or regularized confluent hypergeometric limit function.
178}
179
180////////////////////////////////////////////////////////////////////////////////
181
182Int_t RooNonCentralChiSquare::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const
183{
184 if (matchArgs(allVars,analVars,x)) return 1 ;
185 return 0 ;
186}
187
188////////////////////////////////////////////////////////////////////////////////
189
190double RooNonCentralChiSquare::analyticalIntegral(Int_t code, const char* rangeName) const
191{
192 R__ASSERT(code==1 );
193 // cout << "evaluating analytic integral" << endl;
194 double xmin = x.min(rangeName);
195 double xmax = x.max(rangeName);
196
197 // if xmin~0 and xmax big, then can return 1. b/c evaluate is normalized.
198
199 // special case (form below doesn't work when lambda==0)
200 if(lambda==0){
202 }
203
204 // three forms
205 // FIRST FORM
206 // \sum_i=0^\infty exp(-lambda/2) (\lamda/2)^i chi2(x,k+2i) / i!
207 // could truncate sum
208
209
210 double sum = 0;
211 double ithTerm = 0;
212 double errorTol = fErrorTol; // for normalization allow slightly larger error
213 int MaxIters = fMaxIters; // for normalization use more terms
214
215 int iDominant = (int) TMath::Floor(lambda/2);
216 // cout <<"iDominant: " << iDominant << endl;
217 // iDominant=0;
218 for(int i = iDominant; ; ++i){
219 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)
222 sum+=ithTerm;
223 // cout <<"progress: " << i << " " << ithTerm << " " << sum << endl;
224 if(ithTerm/sum < errorTol)
225 break;
226
227 if( i>iDominant+MaxIters){
230 coutW(Eval) << "RooNonCentralChiSquare Normalization did not converge: for k="<<k
231 << ", lambda="<<lambda << " fractional error = " << ithTerm/sum
232 << "\n either adjust tolerance with SetErrorTolerance(tol) or max_iter with SetMaxIter(max_it)"
233 << endl;
234 }
235 break;
236 }
237 }
238
239 for(int i = iDominant - 1; i >= 0; --i){
240 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)
243 sum+=ithTerm;
244 }
245 return sum;
246}
#define e(i)
Definition RSha256.hxx:103
#define coutI(a)
#define coutW(a)
#define ccoutD(a)
#define ClassImp(name)
Definition Rtypes.h:377
#define R__ASSERT(e)
Definition TError.h:118
char name[80]
Definition TGX11.cxx:110
float xmin
float xmax
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
bool matchArgs(const RooArgSet &allDeps, RooArgSet &numDeps, const RooArgProxy &a) const
Utility function for use in getAnalyticalIntegral().
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
The PDF of the Non-Central Chi Square distribution for n degrees of freedom.
double evaluate() const override
Evaluate this PDF / function / constant. Needs to be overridden by all derived classes.
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &analVars, const char *rangeName=nullptr) const override
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
double analyticalIntegral(Int_t code, const char *rangeName=nullptr) const override
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
double max(const char *rname=nullptr) const
Query upper limit of range. This requires the payload to be RooAbsRealLValue or derived.
double min(const char *rname=nullptr) const
Query lower limit of range. This requires the payload to be RooAbsRealLValue or derived.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
double chisquared_pdf(double x, double r, double x0=0)
Probability density function of the distribution with degrees of freedom.
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...
double chisquared_cdf(double x, double r, double x0=0)
Cumulative distribution function of the distribution with degrees of freedom (lower tail).
Double_t x[n]
Definition legend1.C:17
Double_t Floor(Double_t x)
Rounds x downward, returning the largest integral value that is not greater than x.
Definition TMath.h:680
Double_t Gamma(Double_t z)
Computation of gamma(z) for all z.
Definition TMath.cxx:353
static uint64_t sum(uint64_t i)
Definition Factory.cxx:2345