Logo ROOT   6.18/05
Reference Guide
RooPoisson.cxx
Go to the documentation of this file.
1 /*****************************************************************************
2 * Project: RooFit *
3 * *
4 * Simple Poisson PDF
5 * author: Kyle Cranmer <cranmer@cern.ch>
6 * *
7 *****************************************************************************/
8
9/** \class RooPoisson
10 \ingroup Roofit
11
12Poisson pdf
13**/
14
15#include "RooPoisson.h"
16
17#include "RooAbsReal.h"
18#include "RooAbsCategory.h"
19
20#include "RooRandom.h"
21#include "RooMath.h"
22#include "TMath.h"
24
25#include "TError.h"
26
27#include <limits>
28
29using namespace std;
30
32
33////////////////////////////////////////////////////////////////////////////////
34/// Constructor
35
36RooPoisson::RooPoisson(const char *name, const char *title,
37 RooAbsReal& _x,
38 RooAbsReal& _mean,
39 Bool_t noRounding) :
40 RooAbsPdf(name,title),
41 x("x","x",this,_x),
42 mean("mean","mean",this,_mean),
43 _noRounding(noRounding),
44 _protectNegative(false)
45{
46}
47
48////////////////////////////////////////////////////////////////////////////////
49/// Copy constructor
50
51 RooPoisson::RooPoisson(const RooPoisson& other, const char* name) :
52 RooAbsPdf(other,name),
53 x("x",this,other.x),
54 mean("mean",this,other.mean),
55 _noRounding(other._noRounding),
56 _protectNegative(other._protectNegative)
57{
58}
59
60////////////////////////////////////////////////////////////////////////////////
61/// Implementation in terms of the TMath::Poisson() function.
62
64{
65 Double_t k = _noRounding ? x : floor(x);
66 if(_protectNegative && mean<0)
67 return 1e-3;
68 return TMath::Poisson(k,mean) ;
69}
70
71////////////////////////////////////////////////////////////////////////////////
72/// calculate and return the negative log-likelihood of the Poisson
73
75{
76 return RooAbsPdf::getLogVal(s) ;
77// Double_t prob = getVal(s) ;
78// return prob ;
79
80 // Make inputs to naming conventions of RooAbsPdf::extendedTerm
81 Double_t expected=mean ;
82 Double_t observed=x ;
83
84 // Explicitly handle case Nobs=Nexp=0
85 if (fabs(expected)<1e-10 && fabs(observed)<1e-10) {
86 return 0 ;
87 }
88
89 // Explicitly handle case Nexp=0
90 if (fabs(observed)<1e-10) {
91 return -1*expected;
92 }
93
94 // Michaels code for log(poisson) in RooAbsPdf::extendedTer with an approximated log(observed!) term
95 Double_t extra=0;
96 if(observed<1000000) {
97 extra = -observed*log(expected)+expected+TMath::LnGamma(observed+1.);
98 } else {
99 //if many observed events, use Gauss approximation
100 Double_t sigma_square=expected;
101 Double_t diff=observed-expected;
102 extra=-log(sigma_square)/2 + (diff*diff)/(2*sigma_square);
103 }
104
105// if (fabs(extra)>100 || log(prob)>100) {
106// cout << "RooPoisson::getLogVal(" << GetName() << ") mu=" << expected << " x = " << x << " -log(P) = " << extra << " log(evaluate()) = " << log(prob) << endl ;
107// }
108
109// if (fabs(extra+log(prob))>1) {
110// cout << "RooPoisson::getLogVal(" << GetName() << ") WARNING mu=" << expected << " x = " << x << " -log(P) = " << extra << " log(evaluate()) = " << log(prob) << endl ;
111// }
112
113 //return log(prob);
114 return -extra-analyticalIntegral(1,0) ; //log(prob);
115
116}
117
118////////////////////////////////////////////////////////////////////////////////
119
120Int_t RooPoisson::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const
121{
122 if (matchArgs(allVars,analVars,x)) return 1 ;
123 if (matchArgs(allVars, analVars, mean)) return 2;
124 return 0 ;
125}
126
127////////////////////////////////////////////////////////////////////////////////
128
129Double_t RooPoisson::analyticalIntegral(Int_t code, const char* rangeName) const
130{
131 R__ASSERT(code == 1 || code == 2) ;
132
133 if(_protectNegative && mean<0)
134 return exp(-2*mean); // make it fall quickly
135
136 if (code == 1) {
137 // Implement integral over x as summation. Add special handling in case
138 // range boundaries are not on integer values of x
139 const double xmin = std::max(0., x.min(rangeName));
140 const double xmax = x.max(rangeName);
141
142 if (xmax < 0. || xmax < xmin) {
143 return 0.;
144 }
145 if (!x.hasMax() || RooNumber::isInfinite(xmax)) {
146 //Integrating the full Poisson distribution here
147 return 1.;
148 }
149
150 // The range as integers. ixmin is included, ixmax outside.
151 const unsigned int ixmin = xmin;
152 const unsigned int ixmax = std::min(xmax + 1.,
153 (double)std::numeric_limits<unsigned int>::max());
154
155 // Sum from 0 to just before the bin outside of the range.
156 if (ixmin == 0) {
157 return ROOT::Math::poisson_cdf(ixmax - 1, mean);
158 }
159 else {
160 // If necessary, subtract from 0 to the beginning of the range
161 if (ixmin <= mean) {
162 return ROOT::Math::poisson_cdf(ixmax - 1, mean) - ROOT::Math::poisson_cdf(ixmin - 1, mean);
163 }
164 else {
165 //Avoid catastrophic cancellation in the high tails:
166 return ROOT::Math::poisson_cdf_c(ixmin - 1, mean) - ROOT::Math::poisson_cdf_c(ixmax - 1, mean);
167 }
168
169 }
170
171 } else if(code == 2) {
172
173 // the integral with respect to the mean is the integral of a gamma distribution
174 Double_t mean_min = mean.min(rangeName);
175 Double_t mean_max = mean.max(rangeName);
176
177 Double_t ix;
178 if(_noRounding) ix = x + 1;
179 else ix = Int_t(TMath::Floor(x)) + 1.0; // negative ix does not need protection (gamma returns 0.0)
180
181 return ROOT::Math::gamma_cdf(mean_max, ix, 1.0) - ROOT::Math::gamma_cdf(mean_min, ix, 1.0);
182 }
183
184 return 0;
185
186}
187
188////////////////////////////////////////////////////////////////////////////////
189/// Advertise internal generator in x
190
191Int_t RooPoisson::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t /*staticInitOK*/) const
192{
193 if (matchArgs(directVars,generateVars,x)) return 1 ;
194 return 0 ;
195}
196
197////////////////////////////////////////////////////////////////////////////////
198/// Implement internal generator using TRandom::Poisson
199
201{
202 R__ASSERT(code==1) ;
203 Double_t xgen ;
204 while(1) {
206 if (xgen<=x.max() && xgen>=x.min()) {
207 x = xgen ;
208 break;
209 }
210 }
211 return;
212}
#define e(i)
Definition: RSha256.hxx:103
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
#define ClassImp(name)
Definition: Rtypes.h:365
#define R__ASSERT(e)
Definition: TError.h:96
char name[80]
Definition: TGX11.cxx:109
float xmin
Definition: THbookFile.cxx:93
float xmax
Definition: THbookFile.cxx:93
double floor(double)
double exp(double)
double log(double)
virtual Double_t getLogVal(const RooArgSet *set=0) const
Return the log of the current value with given normalization An error message is printed if the argum...
Definition: RooAbsPdf.cxx:621
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:53
Bool_t 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:28
static Int_t isInfinite(Double_t x)
Return true if x is infinite by RooNumBer internal specification.
Definition: RooNumber.cxx:58
Poisson pdf.
Definition: RooPoisson.h:19
RooRealProxy x
Definition: RooPoisson.h:40
void generateEvent(Int_t code)
Implement internal generator using TRandom::Poisson.
Definition: RooPoisson.cxx:200
Bool_t _protectNegative
Definition: RooPoisson.h:43
Double_t getLogVal(const RooArgSet *set=0) const
calculate and return the negative log-likelihood of the Poisson
Definition: RooPoisson.cxx:74
Double_t analyticalIntegral(Int_t code, const char *rangeName=0) const
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
Definition: RooPoisson.cxx:129
Int_t getGenerator(const RooArgSet &directVars, RooArgSet &generateVars, Bool_t staticInitOK=kTRUE) const
Advertise internal generator in x.
Definition: RooPoisson.cxx:191
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &analVars, const char *rangeName=0) const
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
Definition: RooPoisson.cxx:120
Double_t evaluate() const
Implementation in terms of the TMath::Poisson() function.
Definition: RooPoisson.cxx:63
Bool_t _noRounding
Definition: RooPoisson.h:42
RooRealProxy mean
Definition: RooPoisson.h:41
static TRandom * randomGenerator()
Return a pointer to a singleton random-number generator implementation.
Definition: RooRandom.cxx:54
Bool_t hasMax(const char *rname=0) const
Definition: RooRealProxy.h:59
Double_t min(const char *rname=0) const
Definition: RooRealProxy.h:56
Double_t max(const char *rname=0) const
Definition: RooRealProxy.h:57
virtual Int_t Poisson(Double_t mean)
Generates a random integer N according to a Poisson law.
Definition: TRandom.cxx:391
double poisson_cdf(unsigned int n, double mu)
Cumulative distribution function of the Poisson distribution Lower tail of the integral of the poisso...
double poisson_cdf_c(unsigned int n, double mu)
Complement of the cumulative distribution function of the Poisson distribution.
double gamma_cdf(double x, double alpha, double theta, double x0=0)
Cumulative distribution function of the gamma distribution (lower tail).
Double_t x[n]
Definition: legend1.C:17
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
static constexpr double s
Double_t Floor(Double_t x)
Definition: TMath.h:691
Double_t Poisson(Double_t x, Double_t par)
Compute the Poisson distribution function for (x,par) The Poisson PDF is implemented by means of Eule...
Definition: TMath.cxx:568
Double_t LnGamma(Double_t z)
Computation of ln[gamma(z)] for all z.
Definition: TMath.cxx:486