// Class RooNumRunningInt is an implementation of RooAbsCachedReal that represents a running integral
// <pre>
// RI(f(x)) = Int[x_lo,x] f(x') dx'
// </pre>
// that is calculated internally with a numeric technique: The input function
// is first sampled into a histogram, which is then numerically integrated.
// The output function is an interpolated version of the integrated histogram.
// The sampling density is controlled by the binning named "cache" in the observable x.
// The shape of the p.d.f is always calculated for the entire domain in x and
// cached in a histogram. The cache histogram is automatically recalculated
// when any of the parameters of the input p.d.f. has changed.
// END_HTML
#include "Riostream.h"
#include "RooAbsPdf.h"
#include "RooNumRunningInt.h"
#include "RooAbsReal.h"
#include "RooMsgService.h"
#include "RooDataHist.h"
#include "RooHistPdf.h"
#include "RooRealVar.h"
using namespace std;
ClassImp(RooNumRunningInt)
;
RooNumRunningInt::RooNumRunningInt(const char *name, const char *title, RooAbsReal& _func, RooRealVar& _x, const char* bname) :
RooAbsCachedReal(name,title),
func("func","func",this,_func),
x("x","x",this,_x),
_binningName(bname?bname:"cache")
{
setInterpolationOrder(2) ;
}
RooNumRunningInt::RooNumRunningInt(const RooNumRunningInt& other, const char* name) :
RooAbsCachedReal(other,name),
func("func",this,other.func),
x("x",this,other.x),
_binningName(other._binningName)
{
}
RooNumRunningInt::~RooNumRunningInt()
{
}
const char* RooNumRunningInt::inputBaseName() const
{
static string ret ;
ret = func.arg().GetName() ;
ret += "_NUMRUNINT" ;
return ret.c_str() ;
} ;
RooNumRunningInt::RICacheElem::RICacheElem(const RooNumRunningInt& self, const RooArgSet* nset) :
FuncCacheElem(self,nset), _self(&const_cast<RooNumRunningInt&>(self))
{
_ax = new Double_t[hist()->numEntries()] ;
_ay = new Double_t[hist()->numEntries()] ;
_xx = (RooRealVar*) hist()->get()->find(self.x.arg().GetName()) ;
for (int i=0 ; i<hist()->numEntries() ; i++) {
hist()->get(i) ;
_ax[i] = _xx->getVal() ;
_ay[i] = -1 ;
}
}
RooNumRunningInt::RICacheElem::~RICacheElem()
{
delete[] _ax ;
delete[] _ay ;
}
RooArgList RooNumRunningInt::RICacheElem::containedArgs(Action action)
{
RooArgList ret ;
ret.add(FuncCacheElem::containedArgs(action)) ;
ret.add(*_self) ;
ret.add(*_xx) ;
return ret ;
}
void RooNumRunningInt::RICacheElem::calculate(Bool_t cdfmode)
{
Int_t nbins = hist()->numEntries() ;
Double_t xsave = _self->x ;
Int_t lastHi=0 ;
Int_t nInitRange=32 ;
for (int i=1 ; i<=nInitRange ; i++) {
Int_t hi = (i*nbins)/nInitRange -1 ;
Int_t lo = lastHi ;
addRange(lo,hi,nbins) ;
lastHi=hi ;
}
for (int i=1 ; i<nbins ; i++) {
_ay[i] += _ay[i-1] ;
}
Double_t binv = (_self->x.max()-_self->x.min())/nbins ;
for (int i=0 ; i<nbins ; i++) {
hist()->get(i) ;
if (cdfmode) {
hist()->set(_ay[i]/_ay[nbins-1]) ;
} else {
hist()->set(_ay[i]*binv) ;
}
}
if (cdfmode) {
func()->setCdfBoundaries(kTRUE) ;
}
_self->x = xsave ;
}
void RooNumRunningInt::RICacheElem::addRange(Int_t ixlo, Int_t ixhi, Int_t nbins)
{
if (_ay[ixlo]<0) {
addPoint(ixlo) ;
}
if (_ay[ixhi]<0) {
addPoint(ixhi) ;
}
if (ixhi-ixlo==1) {
return ;
}
if (ixhi-ixlo==2) {
addPoint(ixlo+1) ;
return ;
}
Int_t ixmid = (ixlo+ixhi)/2 ;
addPoint(ixmid) ;
Double_t yInt = _ay[ixlo] + (_ay[ixhi]-_ay[ixlo])*(ixmid-ixlo)/(ixhi-ixlo) ;
if (fabs(yInt-_ay[ixmid])*(_ax[nbins-1]-_ax[0])>1e-6) {
addRange(ixlo,ixmid,nbins) ;
addRange(ixmid,ixhi,nbins) ;
} else {
for (Int_t j=ixlo+1 ; j<ixmid ; j++) {
_ay[j] = _ay[ixlo] + (_ay[ixmid]-_ay[ixlo])*(j-ixlo)/(ixmid-ixlo) ;
}
for (Int_t j=ixmid+1 ; j<ixhi ; j++) {
_ay[j] = _ay[ixmid] + (_ay[ixhi]-_ay[ixmid])*(j-ixmid)/(ixhi-ixmid) ;
}
}
}
void RooNumRunningInt::RICacheElem::addPoint(Int_t ix)
{
hist()->get(ix) ;
_self->x = _xx->getVal() ;
_ay[ix] = _self->func.arg().getVal(*_xx) ;
}
void RooNumRunningInt::fillCacheObject(RooAbsCachedReal::FuncCacheElem& cache) const
{
RICacheElem& riCache = static_cast<RICacheElem&>(cache) ;
riCache.calculate(kFALSE) ;
}
RooArgSet* RooNumRunningInt::actualObservables(const RooArgSet& ) const
{
RooArgSet* ret = new RooArgSet ;
ret->add(x.arg()) ;
return ret ;
}
RooArgSet* RooNumRunningInt::actualParameters(const RooArgSet& ) const
{
RooArgSet* ret = func.arg().getParameters(RooArgSet()) ;
ret->remove(x.arg(),kTRUE,kTRUE) ;
return ret ;
}
RooAbsCachedReal::FuncCacheElem* RooNumRunningInt::createCache(const RooArgSet* nset) const
{
return new RICacheElem(*const_cast<RooNumRunningInt*>(this),nset) ;
}
Double_t RooNumRunningInt::evaluate() const
{
cout << "RooNumRunningInt::evaluate(" << GetName() << ")" << endl ;
return 0 ;
}