Logo ROOT  
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 "BatchHelpers.h"
26#include "RooVDTHeaders.h"
27
28#include <limits>
29#include <cmath>
30
31using namespace std;
32
34
35////////////////////////////////////////////////////////////////////////////////
36/// Constructor
37
38RooPoisson::RooPoisson(const char *name, const char *title,
39 RooAbsReal& _x,
40 RooAbsReal& _mean,
41 Bool_t noRounding) :
42 RooAbsPdf(name,title),
43 x("x","x",this,_x),
44 mean("mean","mean",this,_mean),
45 _noRounding(noRounding),
46 _protectNegative(false)
47{
48}
49
50////////////////////////////////////////////////////////////////////////////////
51/// Copy constructor
52
53 RooPoisson::RooPoisson(const RooPoisson& other, const char* name) :
54 RooAbsPdf(other,name),
55 x("x",this,other.x),
56 mean("mean",this,other.mean),
57 _noRounding(other._noRounding),
58 _protectNegative(other._protectNegative)
59{
60}
61
62////////////////////////////////////////////////////////////////////////////////
63/// Implementation in terms of the TMath::Poisson() function.
64
66{
67 Double_t k = _noRounding ? x : floor(x);
68 if(_protectNegative && mean<0)
69 return 1e-3;
70 return TMath::Poisson(k,mean) ;
71}
72
73
74
75namespace {
76
77template<class Tx, class TMean>
78void compute(const size_t n, double* __restrict output, Tx x, TMean mean,
79 const bool protectNegative, const bool noRounding) {
80
81 for (size_t i = 0; i < n; ++i) { //CHECK_VECTORISE
82 const double x_i = noRounding ? x[i] : floor(x[i]);
83 // The std::lgamma yields different values than in the scalar implementation.
84 // Need to check which one is more accurate.
85// output[i] = std::lgamma(x_i + 1.);
86 output[i] = TMath::LnGamma(x_i + 1.);
87 }
88
89
90 for (size_t i = 0; i < n; ++i) { //CHECK_VECTORISE
91 const double x_i = noRounding ? x[i] : floor(x[i]);
92 const double logMean = _rf_fast_log(mean[i]);
93 const double logPoisson = x_i * logMean - mean[i] - output[i];
94 output[i] = _rf_fast_exp(logPoisson);
95
96 // Cosmetics
97 if (x_i < 0.)
98 output[i] = 0.;
99 else if (x_i == 0.) {
100 output[i] = 1./_rf_fast_exp(mean[i]);
101 }
102 if (protectNegative && mean[i] < 0.)
103 output[i] = 1.E-3;
104 }
105}
106
107}
108
109
110////////////////////////////////////////////////////////////////////////////////
111/// Compute Poisson values in batches.
112RooSpan<double> RooPoisson::evaluateBatch(std::size_t begin, std::size_t batchSize) const {
113 using namespace BatchHelpers;
114 auto xData = x.getValBatch(begin, batchSize);
115 auto meanData = mean.getValBatch(begin, batchSize);
116 const bool batchX = !xData.empty();
117 const bool batchMean = !meanData.empty();
118
119 if (!batchX && !batchMean) {
120 return {};
121 }
122 batchSize = findSize({ xData, meanData });
123 auto output = _batchData.makeWritableBatchUnInit(begin, batchSize);
124
125 if (batchX && !batchMean ) {
126 compute(batchSize, output.data(), xData, BracketAdapter<double>(mean), _protectNegative, _noRounding);
127 }
128 else if (!batchX && batchMean ) {
129 compute(batchSize, output.data(), BracketAdapter<double>(x), meanData, _protectNegative, _noRounding);
130 }
131 else if (batchX && batchMean ) {
132 compute(batchSize, output.data(), xData, meanData, _protectNegative, _noRounding);
133 }
134 return output;
135}
136
137
138////////////////////////////////////////////////////////////////////////////////
139
140Int_t RooPoisson::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* /*rangeName*/) const
141{
142 if (matchArgs(allVars,analVars,x)) return 1 ;
143 if (matchArgs(allVars, analVars, mean)) return 2;
144 return 0 ;
145}
146
147////////////////////////////////////////////////////////////////////////////////
148
149Double_t RooPoisson::analyticalIntegral(Int_t code, const char* rangeName) const
150{
151 R__ASSERT(code == 1 || code == 2) ;
152
153 if(_protectNegative && mean<0)
154 return exp(-2*mean); // make it fall quickly
155
156 if (code == 1) {
157 // Implement integral over x as summation. Add special handling in case
158 // range boundaries are not on integer values of x
159 const double xmin = std::max(0., x.min(rangeName));
160 const double xmax = x.max(rangeName);
161
162 if (xmax < 0. || xmax < xmin) {
163 return 0.;
164 }
165 if (!x.hasMax() || RooNumber::isInfinite(xmax)) {
166 //Integrating the full Poisson distribution here
167 return 1.;
168 }
169
170 // The range as integers. ixmin is included, ixmax outside.
171 const unsigned int ixmin = xmin;
172 const unsigned int ixmax = std::min(xmax + 1.,
173 (double)std::numeric_limits<unsigned int>::max());
174
175 // Sum from 0 to just before the bin outside of the range.
176 if (ixmin == 0) {
177 return ROOT::Math::poisson_cdf(ixmax - 1, mean);
178 }
179 else {
180 // If necessary, subtract from 0 to the beginning of the range
181 if (ixmin <= mean) {
182 return ROOT::Math::poisson_cdf(ixmax - 1, mean) - ROOT::Math::poisson_cdf(ixmin - 1, mean);
183 }
184 else {
185 //Avoid catastrophic cancellation in the high tails:
186 return ROOT::Math::poisson_cdf_c(ixmin - 1, mean) - ROOT::Math::poisson_cdf_c(ixmax - 1, mean);
187 }
188
189 }
190
191 } else if(code == 2) {
192
193 // the integral with respect to the mean is the integral of a gamma distribution
194 Double_t mean_min = mean.min(rangeName);
195 Double_t mean_max = mean.max(rangeName);
196
197 Double_t ix;
198 if(_noRounding) ix = x + 1;
199 else ix = Int_t(TMath::Floor(x)) + 1.0; // negative ix does not need protection (gamma returns 0.0)
200
201 return ROOT::Math::gamma_cdf(mean_max, ix, 1.0) - ROOT::Math::gamma_cdf(mean_min, ix, 1.0);
202 }
203
204 return 0;
205
206}
207
208////////////////////////////////////////////////////////////////////////////////
209/// Advertise internal generator in x
210
211Int_t RooPoisson::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t /*staticInitOK*/) const
212{
213 if (matchArgs(directVars,generateVars,x)) return 1 ;
214 return 0 ;
215}
216
217////////////////////////////////////////////////////////////////////////////////
218/// Implement internal generator using TRandom::Poisson
219
221{
222 R__ASSERT(code==1) ;
223 Double_t xgen ;
224 while(1) {
226 if (xgen<=x.max() && xgen>=x.min()) {
227 x = xgen ;
228 break;
229 }
230 }
231 return;
232}
#define e(i)
Definition: RSha256.hxx:103
double _rf_fast_exp(double x)
VDT headers for RooFit.
Definition: RooVDTHeaders.h:47
double _rf_fast_log(double x)
Definition: RooVDTHeaders.h:51
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)
RooSpan< double > makeWritableBatchUnInit(std::size_t begin, std::size_t batchSize)
Make a batch and return a span pointing to the pdf-local memory.
Definition: BatchData.cxx:58
Little adapter that gives a bracket operator to types that don't have one.
Definition: BatchHelpers.h:58
RooAbsReal is the common abstract base class for objects that represent a real value and implements f...
Definition: RooAbsReal.h:59
Bool_t matchArgs(const RooArgSet &allDeps, RooArgSet &numDeps, const RooArgProxy &a) const
Utility function for use in getAnalyticalIntegral().
BatchHelpers::BatchData _batchData
Definition: RooAbsReal.h:447
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:38
Int_t getAnalyticalIntegral(RooArgSet &allVars, RooArgSet &analVars, const char *rangeName=0) const override
Interface function getAnalyticalIntergral advertises the analytical integrals that are supported.
Definition: RooPoisson.cxx:140
Bool_t _protectNegative
Definition: RooPoisson.h:41
void generateEvent(Int_t code) override
Implement internal generator using TRandom::Poisson.
Definition: RooPoisson.cxx:220
Int_t getGenerator(const RooArgSet &directVars, RooArgSet &generateVars, Bool_t staticInitOK=kTRUE) const override
Advertise internal generator in x.
Definition: RooPoisson.cxx:211
Double_t analyticalIntegral(Int_t code, const char *rangeName=0) const override
Implements the actual analytical integral(s) advertised by getAnalyticalIntegral.
Definition: RooPoisson.cxx:149
Double_t evaluate() const override
Implementation in terms of the TMath::Poisson() function.
Definition: RooPoisson.cxx:65
RooSpan< double > evaluateBatch(std::size_t begin, std::size_t batchSize) const override
Compute Poisson values in batches.
Definition: RooPoisson.cxx:112
Bool_t _noRounding
Definition: RooPoisson.h:40
RooRealProxy mean
Definition: RooPoisson.h:39
static TRandom * randomGenerator()
Return a pointer to a singleton random-number generator implementation.
Definition: RooRandom.cxx:54
A simple container to hold a batch of data values.
Definition: RooSpan.h:32
Double_t min(const char *rname=0) const
Query lower limit of range. This requires the payload to be RooAbsRealLValue or derived.
RooSpan< const double > getValBatch(std::size_t begin, std::size_t batchSize) const
Bool_t hasMax(const char *rname=0) const
Check if the range has a upper bound. This requires the payload to be RooAbsRealLValue or derived.
Double_t max(const char *rname=0) const
Query upper limit of range. This requires the payload to be RooAbsRealLValue or derived.
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
const Int_t n
Definition: legend1.C:16
size_t findSize(std::vector< RooSpan< const double > > parameters)
This function returns the minimum size of the non-zero-sized batches.
Double_t Floor(Double_t x)
Definition: TMath.h:693
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
static void output(int code)
Definition: gifencode.c:226