Logo ROOT  
Reference Guide
 
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
42#include "RooAbsReal.h"
43#include "RooAbsCategory.h"
44#include <cmath>
45#include "TMath.h"
46//#include "RooNumber.h"
47#include "Math/DistFunc.h"
48
49#include "RooMsgService.h"
50
51#include "TError.h"
52
53#include <ostream>
54
55using std::endl;
56
57
58////////////////////////////////////////////////////////////////////////////////
59
61 RooAbsReal &_lambda)
62 : RooAbsPdf(name, title),
63 x("x", "x", this, _x),
64 k("k", "k", this, _k),
65 lambda("lambda", "lambda", this, _lambda),
66 fErrorTol(1E-3),
67 fMaxIters(10),
68 fForceSum(false),
69 fHasIssuedConvWarning(false),
70 fHasIssuedSumWarning(false)
71{
72 ccoutD(InputArguments) << "RooNonCentralChiSquare::ctor(" << GetName() <<
73 "MathMore Available, will use Bessel function expressions unless SetForceSum(true) "<< std::endl ;
74}
75
76////////////////////////////////////////////////////////////////////////////////
77
80 x("x", this, other.x),
81 k("k", this, other.k),
82 lambda("lambda", this, other.lambda),
83 fErrorTol(other.fErrorTol),
84 fMaxIters(other.fMaxIters),
85 fForceSum(other.fForceSum),
86 fHasIssuedConvWarning(false),
87 fHasIssuedSumWarning(false)
88{
89 ccoutD(InputArguments) << "RooNonCentralChiSquare::ctor(" << GetName() <<
90 "MathMore Available, will use Bessel function expressions unless SetForceSum(true) "<< std::endl ;
91}
92
93////////////////////////////////////////////////////////////////////////////////
94
98
99////////////////////////////////////////////////////////////////////////////////
100
102{
103 // ENTER EXPRESSION IN TERMS OF VARIABLE ARGUMENTS HERE
104
105
106 // chi^2(0,k) gives inf and causes various problems
107 // truncate
108 double xmin = x.min();
109 double xmax = x.max();
110 double _x = x;
111 if(_x<=0){
112 // options for dealing with this
113 // return 0; // gives a funny dip
114 // _x = 1./RooNumber::infinity(); // too tall
115 _x = xmin + 1e-3*(xmax-xmin); // very small fraction of range
116 }
117
118 // special case (form below doesn't work when lambda==0)
119 if(lambda==0){
120 return ROOT::Math::chisquared_pdf(_x,k);
121 }
122
123 // three forms
124 // FIRST FORM
125 // \sum_i=0^\infty exp(-lambda/2) (\lamda/2)^i chi2(x,k+2i) / i!
126 // could truncate sum
127
128 if ( fForceSum ){
130 coutI(InputArguments) << "RooNonCentralChiSquare sum being forced" << std::endl ;
132 }
133 double sum = 0;
134 double ithTerm = 0;
135 double errorTol = fErrorTol;
136 int MaxIters = fMaxIters;
137 int iDominant = (int) std::floor(lambda/2);
138 // std::cout <<"iDominant: " << iDominant << std::endl;
139
140 // do 0th term last
141 // if(iDominant==0) iDominant = 1;
142 for(int i = iDominant; ; ++i){
143 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)*ROOT::Math::chisquared_pdf(_x,k+2*i)/TMath::Gamma(i+1);
144 sum+=ithTerm;
145 // std::cout <<"progress: " << i << " " << ithTerm/sum << std::endl;
146 if(ithTerm/sum < errorTol)
147 break;
148
149 if( i>iDominant+MaxIters){
152 coutW(Eval) << "RooNonCentralChiSquare did not converge: for x=" << x <<" k="<<k
153 << ", lambda="<<lambda << " fractional error = " << ithTerm/sum
154 << "\n either adjust tolerance with SetErrorTolerance(tol) or max_iter with SetMaxIter(max_it)"
155 << std::endl;
156 }
157 break;
158 }
159 }
160
161 for(int i = iDominant - 1; i >= 0; --i){
162 // std::cout <<"Progress: " << i << " " << ithTerm/sum << std::endl;
163 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)*ROOT::Math::chisquared_pdf(_x,k+2*i)/TMath::Gamma(i+1);
164 sum+=ithTerm;
165 }
166
167
168 return sum;
169 }
170
171 // SECOND FORM (use MathMore function based on Bessel function (if k>2) or
172 // or regularized confluent hypergeometric limit function.
174}
175
176////////////////////////////////////////////////////////////////////////////////
177
179{
180 if (matchArgs(allVars,analVars,x)) return 1 ;
181 return 0 ;
182}
183
184////////////////////////////////////////////////////////////////////////////////
185
187{
188 R__ASSERT(code==1 );
189 // std::cout << "evaluating analytic integral" << std::endl;
190 double xmin = x.min(rangeName);
191 double xmax = x.max(rangeName);
192
193 // if xmin~0 and xmax big, then can return 1. b/c evaluate is normalized.
194
195 // special case (form below doesn't work when lambda==0)
196 if(lambda==0){
198 }
199
200 // three forms
201 // FIRST FORM
202 // \sum_i=0^\infty exp(-lambda/2) (\lamda/2)^i chi2(x,k+2i) / i!
203 // could truncate sum
204
205
206 double sum = 0;
207 double ithTerm = 0;
208 double errorTol = fErrorTol; // for normalization allow slightly larger error
209 int MaxIters = fMaxIters; // for normalization use more terms
210
211 int iDominant = (int) std::floor(lambda/2);
212 // std::cout <<"iDominant: " << iDominant << std::endl;
213 // iDominant=0;
214 for(int i = iDominant; ; ++i){
215 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)
218 sum+=ithTerm;
219 // std::cout <<"progress: " << i << " " << ithTerm << " " << sum << std::endl;
220 if(ithTerm/sum < errorTol)
221 break;
222
223 if( i>iDominant+MaxIters){
226 coutW(Eval) << "RooNonCentralChiSquare Normalization did not converge: for k="<<k
227 << ", lambda="<<lambda << " fractional error = " << ithTerm/sum
228 << "\n either adjust tolerance with SetErrorTolerance(tol) or max_iter with SetMaxIter(max_it)"
229 << std::endl;
230 }
231 break;
232 }
233 }
234
235 for(int i = iDominant - 1; i >= 0; --i){
236 ithTerm =exp(-lambda/2.)*pow(lambda/2.,i)
239 sum+=ithTerm;
240 }
241 return sum;
242}
#define e(i)
Definition RSha256.hxx:103
#define coutI(a)
#define coutW(a)
#define ccoutD(a)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:130
char name[80]
Definition TGX11.cxx:142
float xmin
float xmax
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
bool matchArgs(const RooArgSet &allDeps, RooArgSet &analDeps, const RooArgProxy &a, const Proxies &... proxies) const
Definition RooAbsReal.h:425
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
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:49
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 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:2335