// Poisson pdf
// END_HTML
#include <iostream>
#include "RooPoisson.h"
#include "RooAbsReal.h"
#include "RooAbsCategory.h"
#include "RooRandom.h"
#include "RooMath.h"
#include "TMath.h"
#include "Math/ProbFuncMathCore.h"
using namespace std;
ClassImp(RooPoisson)
RooPoisson::RooPoisson(const char *name, const char *title,
RooAbsReal& _x,
RooAbsReal& _mean,
Bool_t noRounding) :
RooAbsPdf(name,title),
x("x","x",this,_x),
mean("mean","mean",this,_mean),
_noRounding(noRounding),
_protectNegative(false)
{
}
RooPoisson::RooPoisson(const RooPoisson& other, const char* name) :
RooAbsPdf(other,name),
x("x",this,other.x),
mean("mean",this,other.mean),
_noRounding(other._noRounding),
_protectNegative(other._protectNegative)
{
}
Double_t RooPoisson::evaluate() const
{
Double_t k = _noRounding ? x : floor(x);
if(_protectNegative && mean<0)
return 1e-3;
return TMath::Poisson(k,mean) ;
}
Double_t RooPoisson::getLogVal(const RooArgSet* s) const
{
return RooAbsPdf::getLogVal(s) ;
Double_t expected=mean ;
Double_t observed=x ;
if (fabs(expected)<1e-10 && fabs(observed)<1e-10) {
return 0 ;
}
if (fabs(observed)<1e-10) {
return -1*expected;
}
Double_t extra=0;
if(observed<1000000) {
extra = -observed*log(expected)+expected+TMath::LnGamma(observed+1.);
} else {
Double_t sigma_square=expected;
Double_t diff=observed-expected;
extra=-log(sigma_square)/2 + (diff*diff)/(2*sigma_square);
}
return -extra-analyticalIntegral(1,0) ;
}
Int_t RooPoisson::getAnalyticalIntegral(RooArgSet& allVars, RooArgSet& analVars, const char* ) const
{
if (matchArgs(allVars,analVars,x)) return 1 ;
if (matchArgs(allVars, analVars, mean)) return 2;
return 0 ;
}
Double_t RooPoisson::analyticalIntegral(Int_t code, const char* rangeName) const
{
assert(code == 1 || code == 2) ;
if(_protectNegative && mean<0)
return exp(-2*mean);
if (code == 1) {
Double_t xmin = x.min(rangeName) ;
Double_t xmax = x.max(rangeName) ;
if (xmin<0) xmin=0 ;
Int_t ixmin = Int_t (xmin) ;
Int_t ixmax = Int_t (xmax)+1 ;
Double_t fracLoBin = 1-(xmin-ixmin) ;
Double_t fracHiBin = 1-(ixmax-xmax) ;
if (!x.hasMax()) {
if (xmin<1e-6) {
return 1 ;
} else {
if(ixmin == 0){
return TMath::Poisson(0, mean)*(xmin-0);
}
Double_t sum(0) ;
sum += TMath::Poisson(0,mean)*fracLoBin ;
sum+= ROOT::Math::poisson_cdf(ixmin-2, mean) - ROOT::Math::poisson_cdf(0,mean) ;
sum += TMath::Poisson(ixmin-1,mean)*fracHiBin ;
return 1-sum ;
}
}
if(ixmin == ixmax-1){
return TMath::Poisson(ixmin, mean)*(xmax-xmin);
}
Double_t sum(0) ;
sum += TMath::Poisson(ixmin,mean)*fracLoBin ;
if (RooNumber::isInfinite(xmax)){
sum+= 1.-ROOT::Math::poisson_cdf(ixmin,mean) ;
} else {
sum+= ROOT::Math::poisson_cdf(ixmax-2, mean) - ROOT::Math::poisson_cdf(ixmin,mean) ;
sum += TMath::Poisson(ixmax-1,mean)*fracHiBin ;
}
return sum ;
} else if(code == 2) {
Double_t mean_min = mean.min(rangeName);
Double_t mean_max = mean.max(rangeName);
Double_t ix;
if(_noRounding) ix = x + 1;
else ix = Int_t(TMath::Floor(x)) + 1.0;
return ROOT::Math::gamma_cdf(mean_max, ix, 1.0) - ROOT::Math::gamma_cdf(mean_min, ix, 1.0);
}
return 0;
}
Int_t RooPoisson::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t ) const
{
if (matchArgs(directVars,generateVars,x)) return 1 ;
return 0 ;
}
void RooPoisson::generateEvent(Int_t code)
{
(void)code;
assert(code==1) ;
Double_t xgen ;
while(1) {
xgen = RooRandom::randomGenerator()->Poisson(mean);
if (xgen<=x.max() && xgen>=x.min()) {
x = xgen ;
break;
}
}
return;
}