//
// RooGenProdProj is an auxiliary class for RooProdPdf that calculates
// a general normalized projection of a product of non-factorizing PDFs, e.g.
//
// Int ( P1 * P2 * ....) dx
// P_x_xy = -------------------------------
// Int (P1 * P2 * ... ) dx dy
//
// Partial integrals that factorize that can be calculated are calculated
// analytically. Remaining non-factorizing observables are integrated numerically.
// END_HTML
#include "RooFit.h"
#include "Riostream.h"
#include "Riostream.h"
#include <math.h>
#include "RooGenProdProj.h"
#include "RooAbsReal.h"
#include "RooAbsPdf.h"
#include "RooErrorHandler.h"
#include "RooProduct.h"
using namespace std;
ClassImp(RooGenProdProj)
;
RooGenProdProj::RooGenProdProj() :
_compSetOwnedN(0),
_compSetOwnedD(0),
_haveD(kFALSE)
{
}
RooGenProdProj::RooGenProdProj(const char *name, const char *title, const RooArgSet& _prodSet, const RooArgSet& _intSet,
const RooArgSet& _normSet, const char* isetRangeName, const char* normRangeName, Bool_t doFactorize) :
RooAbsReal(name, title),
_compSetOwnedN(0),
_compSetOwnedD(0),
_compSetN("compSetN","Set of integral components owned by numerator",this,kFALSE),
_compSetD("compSetD","Set of integral components owned by denominator",this,kFALSE),
_intList("intList","List of integrals",this,kTRUE),
_haveD(kFALSE)
{
setExpensiveObjectCache(_prodSet.first()->expensiveObjectCache()) ;
_compSetOwnedN = new RooArgSet ;
_compSetOwnedD = new RooArgSet ;
RooAbsReal* numerator = makeIntegral("numerator",_prodSet,_intSet,*_compSetOwnedN,isetRangeName,doFactorize) ;
RooAbsReal* denominator = makeIntegral("denominator",_prodSet,_normSet,*_compSetOwnedD,normRangeName,doFactorize) ;
_compSetN.add(*_compSetOwnedN) ;
_compSetD.add(*_compSetOwnedD) ;
_intList.add(*numerator) ;
if (denominator) {
_intList.add(*denominator) ;
_haveD = kTRUE ;
}
}
RooGenProdProj::RooGenProdProj(const RooGenProdProj& other, const char* name) :
RooAbsReal(other, name),
_compSetOwnedN(0),
_compSetOwnedD(0),
_compSetN("compSetN","Set of integral components owned by numerator",this),
_compSetD("compSetD","Set of integral components owned by denominator",this),
_intList("intList","List of integrals",this)
{
TIterator* iter = serverIterator() ;
RooAbsArg* server ;
while((server=(RooAbsArg*)iter->Next())) {
removeServer(*server,kTRUE) ;
}
delete iter ;
_compSetOwnedN = (RooArgSet*) other._compSetN.snapshot() ;
_compSetN.add(*_compSetOwnedN) ;
_compSetOwnedD = (RooArgSet*) other._compSetD.snapshot() ;
_compSetD.add(*_compSetOwnedD) ;
RooAbsArg* arg ;
TIterator* nIter = _compSetOwnedN->createIterator() ;
while((arg=(RooAbsArg*)nIter->Next())) {
arg->setOperMode(_operMode) ;
}
delete nIter ;
TIterator* dIter = _compSetOwnedD->createIterator() ;
while((arg=(RooAbsArg*)dIter->Next())) {
arg->setOperMode(_operMode) ;
}
delete dIter ;
_haveD = other._haveD ;
_intList.add(*_compSetN.find(other._intList.at(0)->GetName())) ;
if (other._haveD) {
_intList.add(*_compSetD.find(other._intList.at(1)->GetName())) ;
}
}
RooGenProdProj::~RooGenProdProj()
{
if (_compSetOwnedN) delete _compSetOwnedN ;
if (_compSetOwnedD) delete _compSetOwnedD ;
}
RooAbsReal* RooGenProdProj::makeIntegral(const char* name, const RooArgSet& compSet, const RooArgSet& intSet,
RooArgSet& saveSet, const char* isetRangeName, Bool_t doFactorize)
{
RooArgSet anaIntSet, numIntSet ;
TIterator* compIter = compSet.createIterator() ;
TIterator* intIter = intSet.createIterator() ;
RooAbsPdf* pdf ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)intIter->Next())) {
Int_t count(0) ;
compIter->Reset() ;
while((pdf=(RooAbsPdf*)compIter->Next())) {
if (pdf->dependsOn(*arg)) count++ ;
}
if (count==0) {
} else if (count==1) {
anaIntSet.add(*arg) ;
} else {
}
}
RooArgSet prodSet ;
numIntSet.add(intSet) ;
compIter->Reset() ;
while((pdf=(RooAbsPdf*)compIter->Next())) {
if (doFactorize && pdf->dependsOn(anaIntSet)) {
RooArgSet anaSet ;
Int_t code = pdf->getAnalyticalIntegralWN(anaIntSet,anaSet,0,isetRangeName) ;
if (code!=0) {
RooAbsReal* pai = pdf->createIntegral(anaSet,isetRangeName) ;
pai->setOperMode(_operMode) ;
prodSet.add(*pai) ;
numIntSet.remove(anaSet) ;
saveSet.addOwned(*pai) ;
} else {
prodSet.add(*pdf) ;
}
} else {
prodSet.add(*pdf) ;
}
}
TString prodName ;
if (isetRangeName) {
prodName = Form("%s_%s_Range[%s]",GetName(),name,isetRangeName) ;
} else {
prodName = Form("%s_%s",GetName(),name) ;
}
RooProduct* prod = new RooProduct(prodName,"product",prodSet) ;
prod->setExpensiveObjectCache(expensiveObjectCache()) ;
prod->setOperMode(_operMode) ;
saveSet.addOwned(*prod) ;
RooAbsReal* ret = prod->createIntegral(numIntSet,isetRangeName) ;
ret->setOperMode(_operMode) ;
saveSet.addOwned(*ret) ;
delete compIter ;
delete intIter ;
return ret ;
}
Double_t RooGenProdProj::evaluate() const
{
Double_t nom = ((RooAbsReal*)_intList.at(0))->getVal() ;
if (!_haveD) return nom ;
Double_t den = ((RooAbsReal*)_intList.at(1))->getVal() ;
return nom / den ;
}
void RooGenProdProj::operModeHook()
{
RooAbsArg* arg ;
TIterator* nIter = _compSetOwnedN->createIterator() ;
while((arg=(RooAbsArg*)nIter->Next())) {
arg->setOperMode(_operMode) ;
}
delete nIter ;
TIterator* dIter = _compSetOwnedD->createIterator() ;
while((arg=(RooAbsArg*)dIter->Next())) {
arg->setOperMode(_operMode) ;
}
delete dIter ;
_intList.at(0)->setOperMode(_operMode) ;
if (_haveD) _intList.at(1)->setOperMode(Auto) ;
}