// RooProdPdf is an efficient implementation of a product of PDFs of the form
//
// PDF_1 * PDF_2 * ... * PDF_N
//
// PDFs may share observables. If that is the case any irreducable subset
// of PDFS that share observables will be normalized with explicit numeric
// integration as any built-in normalization will no longer be valid.
//
// Alternatively, products using conditional PDFs can be defined, e.g.
//
// F(x|y) * G(y)
//
// meaning a pdf F(x) _given_ y and a PDF G(y). In this contruction F is only
// normalized w.r.t x and G is normalized w.r.t y. The product in this construction
// is properly normalized.
//
// If exactly one of the component PDFs supports extended likelihood fits, the
// product will also be usable in extended mode, returning the number of expected
// events from the extendable component PDF. The extendable component does not
// have to appear in any specific place in the list.
//
// END_HTML
#include "RooProdPdf.h"
#include "RooRealProxy.h"
#include "RooProdGenContext.h"
#include "RooGenProdProj.h"
#include "RooProduct.h"
#include "RooNameReg.h"
#include "RooMsgService.h"
#include "RooFormulaVar.h"
#include "RooRealVar.h"
#include "RooAddition.h"
#include "RooGlobalFunc.h"
#include "RooConstVar.h"
#include "RooWorkspace.h"
#include "RooRangeBoolean.h"
#include "RooCustomizer.h"
#include "RooRealIntegral.h"
#include "RooTrace.h"
#include <cstring>
#include <sstream>
#include <algorithm>
#ifndef _WIN32
#include <strings.h>
#else
static char *strtok_r(char *s1, const char *s2, char **lasts)
{
char *ret;
if (s1 == NULL)
s1 = *lasts;
while(*s1 && strchr(s2, *s1))
++s1;
if(*s1 == '\0')
return NULL;
ret = s1;
while(*s1 && !strchr(s2, *s1))
++s1;
if(*s1)
*s1++ = '\0';
*lasts = s1;
return ret;
}
#endif
#include "TSystem.h"
using namespace std;
ClassImp(RooProdPdf)
;
RooProdPdf::RooProdPdf() :
_curNormSet(0),
_cutOff(0),
_extendedIndex(-1),
_useDefaultGen(kFALSE),
_refRangeName(0),
_selfNorm(kTRUE)
{
TRACE_CREATE
}
RooProdPdf::RooProdPdf(const char *name, const char *title, Double_t cutOff) :
RooAbsPdf(name,title),
_cacheMgr(this,10),
_genCode(10),
_cutOff(cutOff),
_pdfList("!pdfs","List of PDFs",this),
_extendedIndex(-1),
_useDefaultGen(kFALSE),
_refRangeName(0),
_selfNorm(kTRUE)
{
TRACE_CREATE
}
RooProdPdf::RooProdPdf(const char *name, const char *title,
RooAbsPdf& pdf1, RooAbsPdf& pdf2, Double_t cutOff) :
RooAbsPdf(name,title),
_cacheMgr(this,10),
_genCode(10),
_cutOff(cutOff),
_pdfList("!pdfs","List of PDFs",this),
_extendedIndex(-1),
_useDefaultGen(kFALSE),
_refRangeName(0),
_selfNorm(kTRUE)
{
_pdfList.add(pdf1) ;
RooArgSet* nset1 = new RooArgSet("nset") ;
_pdfNSetList.Add(nset1) ;
if (pdf1.canBeExtended()) {
_extendedIndex = _pdfList.index(&pdf1) ;
}
_pdfList.add(pdf2) ;
RooArgSet* nset2 = new RooArgSet("nset") ;
_pdfNSetList.Add(nset2) ;
if (pdf2.canBeExtended()) {
if (_extendedIndex>=0) {
coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName()
<< ") multiple components with extended terms detected,"
<< " product will not be extendible." << endl ;
_extendedIndex=-1 ;
} else {
_extendedIndex=_pdfList.index(&pdf2) ;
}
}
TRACE_CREATE
}
RooProdPdf::RooProdPdf(const char* name, const char* title, const RooArgList& inPdfList, Double_t cutOff) :
RooAbsPdf(name,title),
_cacheMgr(this,10),
_genCode(10),
_cutOff(cutOff),
_pdfList("!pdfs","List of PDFs",this),
_extendedIndex(-1),
_useDefaultGen(kFALSE),
_refRangeName(0),
_selfNorm(kTRUE)
{
RooFIter iter = inPdfList.fwdIterator();
RooAbsArg* arg ;
Int_t numExtended(0) ;
while((arg=(RooAbsArg*)iter.next())) {
RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(arg) ;
if (!pdf) {
coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName() << ") list arg "
<< arg->GetName() << " is not a PDF, ignored" << endl ;
continue ;
}
_pdfList.add(*pdf) ;
RooArgSet* nset = new RooArgSet("nset") ;
_pdfNSetList.Add(nset) ;
if (pdf->canBeExtended()) {
_extendedIndex = _pdfList.index(pdf) ;
numExtended++ ;
}
}
if (numExtended>1) {
coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName()
<< ") WARNING: multiple components with extended terms detected,"
<< " product will not be extendible." << endl ;
_extendedIndex = -1 ;
}
TRACE_CREATE
}
RooProdPdf::RooProdPdf(const char* name, const char* title, const RooArgSet& fullPdfSet,
const RooCmdArg& arg1, const RooCmdArg& arg2,
const RooCmdArg& arg3, const RooCmdArg& arg4,
const RooCmdArg& arg5, const RooCmdArg& arg6,
const RooCmdArg& arg7, const RooCmdArg& arg8) :
RooAbsPdf(name,title),
_cacheMgr(this,10),
_genCode(10),
_cutOff(0),
_pdfList("!pdfs","List of PDFs",this),
_extendedIndex(-1),
_useDefaultGen(kFALSE),
_refRangeName(0),
_selfNorm(kTRUE)
{
RooLinkedList l ;
l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
initializeFromCmdArgList(fullPdfSet,l) ;
TRACE_CREATE
}
RooProdPdf::RooProdPdf(const char* name, const char* title,
const RooCmdArg& arg1, const RooCmdArg& arg2,
const RooCmdArg& arg3, const RooCmdArg& arg4,
const RooCmdArg& arg5, const RooCmdArg& arg6,
const RooCmdArg& arg7, const RooCmdArg& arg8) :
RooAbsPdf(name,title),
_cacheMgr(this,10),
_genCode(10),
_cutOff(0),
_pdfList("!pdfList","List of PDFs",this),
_extendedIndex(-1),
_useDefaultGen(kFALSE),
_refRangeName(0),
_selfNorm(kTRUE)
{
RooLinkedList l ;
l.Add((TObject*)&arg1) ; l.Add((TObject*)&arg2) ;
l.Add((TObject*)&arg3) ; l.Add((TObject*)&arg4) ;
l.Add((TObject*)&arg5) ; l.Add((TObject*)&arg6) ;
l.Add((TObject*)&arg7) ; l.Add((TObject*)&arg8) ;
initializeFromCmdArgList(RooArgSet(),l) ;
TRACE_CREATE
}
RooProdPdf::RooProdPdf(const char* name, const char* title, const RooArgSet& fullPdfSet, const RooLinkedList& cmdArgList) :
RooAbsPdf(name,title),
_cacheMgr(this,10),
_genCode(10),
_cutOff(0),
_pdfList("!pdfs","List of PDFs",this),
_extendedIndex(-1),
_useDefaultGen(kFALSE),
_refRangeName(0),
_selfNorm(kTRUE)
{
initializeFromCmdArgList(fullPdfSet, cmdArgList) ;
TRACE_CREATE
}
RooProdPdf::RooProdPdf(const RooProdPdf& other, const char* name) :
RooAbsPdf(other,name),
_cacheMgr(other._cacheMgr,this),
_genCode(other._genCode),
_cutOff(other._cutOff),
_pdfList("!pdfs",this,other._pdfList),
_extendedIndex(other._extendedIndex),
_useDefaultGen(other._useDefaultGen),
_refRangeName(other._refRangeName),
_selfNorm(other._selfNorm),
_defNormSet(other._defNormSet)
{
RooFIter iter = other._pdfNSetList.fwdIterator();
RooArgSet* nset ;
while((nset=(RooArgSet*)iter.next())) {
RooArgSet* tmp = (RooArgSet*) nset->snapshot() ;
tmp->setName(nset->GetName()) ;
_pdfNSetList.Add(tmp) ;
}
TRACE_CREATE
}
void RooProdPdf::initializeFromCmdArgList(const RooArgSet& fullPdfSet, const RooLinkedList& l)
{
Int_t numExtended(0) ;
RooFIter siter = fullPdfSet.fwdIterator() ;
RooAbsPdf* pdf ;
while((pdf=(RooAbsPdf*)siter.next())) {
_pdfList.add(*pdf) ;
RooArgSet* nset1 = new RooArgSet("nset") ;
_pdfNSetList.Add(nset1) ;
if (pdf->canBeExtended()) {
_extendedIndex = _pdfList.index(pdf) ;
numExtended++ ;
}
}
RooFIter iter = l.fwdIterator();
RooCmdArg* carg ;
while((carg=(RooCmdArg*)iter.next())) {
if (0 == strcmp(carg->GetName(), "Conditional")) {
Int_t argType = carg->getInt(0) ;
RooArgSet* pdfSet = (RooArgSet*) carg->getSet(0) ;
RooArgSet* normSet = (RooArgSet*) carg->getSet(1) ;
RooFIter siter2 = pdfSet->fwdIterator() ;
RooAbsPdf* thePdf ;
while ((thePdf=(RooAbsPdf*)siter2.next())) {
_pdfList.add(*thePdf) ;
RooArgSet* tmp = (RooArgSet*) normSet->snapshot() ;
tmp->setName(0 == argType ? "nset" : "cset") ;
_pdfNSetList.Add(tmp) ;
if (thePdf->canBeExtended()) {
_extendedIndex = _pdfList.index(thePdf) ;
numExtended++ ;
}
}
} else if (0 != strlen(carg->GetName())) {
coutW(InputArguments) << "Unknown arg: " << carg->GetName() << endl ;
}
}
if (numExtended>1) {
coutW(InputArguments) << "RooProdPdf::RooProdPdf(" << GetName()
<< ") WARNING: multiple components with extended terms detected,"
<< " product will not be extendible." << endl ;
_extendedIndex = -1 ;
}
}
RooProdPdf::~RooProdPdf()
{
_pdfNSetList.Delete() ;
TRACE_DESTROY
}
Double_t RooProdPdf::getValV(const RooArgSet* set) const
{
_curNormSet = (RooArgSet*)set ;
return RooAbsPdf::getValV(set) ;
}
Double_t RooProdPdf::evaluate() const
{
Int_t code ;
CacheElem* cache = (CacheElem*) _cacheMgr.getObj(_curNormSet,0,&code) ;
if (!cache) {
RooArgList *plist(0) ;
RooLinkedList *nlist(0) ;
getPartIntList(_curNormSet,0,plist,nlist,code) ;
cache = (CacheElem*) _cacheMgr.getObj(_curNormSet,0,&code) ;
}
return calculate(*cache) ;
}
Double_t RooProdPdf::calculate(const RooArgList* partIntList, const RooLinkedList* normSetList) const
{
RooAbsReal* partInt;
RooArgSet* normSet;
Double_t value = 1.0;
RooFIter plIter = partIntList->fwdIterator(), nlIter = normSetList->fwdIterator();
for (partInt = (RooAbsReal*) plIter.next(),
normSet = (RooArgSet*) nlIter.next(); partInt && normSet;
partInt = (RooAbsReal*) plIter.next(),
normSet = (RooArgSet*) nlIter.next()) {
const Double_t piVal = partInt->getVal(normSet->getSize() > 0 ? normSet : 0);
value *= piVal;
if (value <= _cutOff) { break; }
}
return value ;
}
Double_t RooProdPdf::calculate(const RooProdPdf::CacheElem& cache, Bool_t ) const
{
if (cache._isRearranged) {
if (dologD(Eval)) {
cxcoutD(Eval) << "RooProdPdf::calculate(" << GetName() << ") rearranged product calculation"
<< " calculate: num = " << cache._rearrangedNum->GetName() << " = " << cache._rearrangedNum->getVal() << endl ;
cxcoutD(Eval) << "calculate: den = " << cache._rearrangedDen->GetName() << " = " << cache._rearrangedDen->getVal() << endl ;
}
return cache._rearrangedNum->getVal() / cache._rearrangedDen->getVal();
} else {
RooAbsReal* partInt;
RooArgSet* normSet;
RooFIter plIter = cache._partList.fwdIterator();
RooFIter nlIter = cache._normList.fwdIterator();
Double_t value = 1.0;
for (partInt = (RooAbsReal*) plIter.next(),
normSet = (RooArgSet*) nlIter.next(); partInt && normSet;
partInt = (RooAbsReal*) plIter.next(),
normSet = (RooArgSet*) nlIter.next()) {
const Double_t piVal = partInt->getVal(normSet->getSize() > 0 ? normSet : 0);
value *= piVal ;
if (value <= _cutOff) break;
}
return value ;
}
}
void RooProdPdf::factorizeProduct(const RooArgSet& normSet, const RooArgSet& intSet,
RooLinkedList& termList, RooLinkedList& normList,
RooLinkedList& impDepList, RooLinkedList& crossDepList,
RooLinkedList& intList) const
{
RooLinkedList depAllList;
RooLinkedList depIntNoNormList;
RooArgSet* term(0);
RooArgSet* termNormDeps(0);
RooArgSet* termAllDeps(0);
RooArgSet* termIntDeps(0);
RooArgSet* termIntNoNormDeps(0);
RooAbsPdf* pdf;
RooArgSet* pdfNSetOrig;
for (RooFIter pdfIter = _pdfList.fwdIterator(),
nIter = _pdfNSetList.fwdIterator();
(pdfNSetOrig = (RooArgSet*) nIter.next(),
pdf = (RooAbsPdf*) pdfIter.next()); ) {
RooArgSet* pdfNSet, *pdfCSet;
if (0 == strcmp("nset", pdfNSetOrig->GetName())) {
pdfNSet = pdf->getObservables(*pdfNSetOrig);
pdfCSet = new RooArgSet;
} else if (0 == strcmp("cset", pdfNSetOrig->GetName())) {
RooArgSet* tmp = pdf->getObservables(normSet);
tmp->remove(*pdfNSetOrig, kTRUE, kTRUE);
pdfCSet = pdfNSetOrig;
pdfNSet = tmp;
} else {
pdfNSet = pdf->getObservables(*pdfNSetOrig);
pdfCSet = new RooArgSet;
}
RooArgSet pdfNormDeps;
RooArgSet pdfAllDeps;
RooArgSet* tmp = pdf->getObservables(normSet);
pdfAllDeps.add(*tmp);
delete tmp;
if (pdfNSet->getSize() > 0) {
RooArgSet* tmp2 = (RooArgSet*) pdfAllDeps.selectCommon(*pdfNSet);
pdfNormDeps.add(*tmp2);
delete tmp2;
} else {
pdfNormDeps.add(pdfAllDeps);
}
RooArgSet* pdfIntSet = pdf->getObservables(intSet) ;
if (0 == pdfNormDeps.getSize() && pdfCSet->getSize() > 0) {
pdfIntSet->remove(*pdfCSet, kTRUE, kTRUE);
}
RooArgSet pdfIntNoNormDeps(*pdfIntSet);
pdfIntNoNormDeps.remove(pdfNormDeps, kTRUE, kTRUE);
Bool_t done(kFALSE);
for (RooFIter lIter = termList.fwdIterator(),
ldIter = normList.fwdIterator(),
laIter = depAllList.fwdIterator();
(termNormDeps = (RooArgSet*) ldIter.next(),
termAllDeps = (RooArgSet*) laIter.next(),
term = (RooArgSet*) lIter.next()); ) {
Bool_t normOverlap = pdfNormDeps.overlaps(*termNormDeps);
if (normOverlap) {
term->add(*pdf);
termNormDeps->add(pdfNormDeps, kFALSE);
termAllDeps->add(pdfAllDeps, kFALSE);
if (!termIntDeps) {
termIntDeps = new RooArgSet("termIntDeps");
}
termIntDeps->add(*pdfIntSet, kFALSE);
if (!termIntNoNormDeps) {
termIntNoNormDeps = new RooArgSet("termIntNoNormDeps");
}
termIntNoNormDeps->add(pdfIntNoNormDeps, kFALSE);
done = kTRUE;
}
}
if (!done) {
if (!(0 == pdfNormDeps.getSize() && 0 == pdfAllDeps.getSize() &&
0 == pdfIntSet->getSize()) || 0 == normSet.getSize()) {
term = new RooArgSet("term");
termNormDeps = new RooArgSet("termNormDeps");
termAllDeps = new RooArgSet("termAllDeps");
termIntDeps = new RooArgSet("termIntDeps");
termIntNoNormDeps = new RooArgSet("termIntNoNormDeps");
term->add(*pdf);
termNormDeps->add(pdfNormDeps, kFALSE);
termAllDeps->add(pdfAllDeps, kFALSE);
termIntDeps->add(*pdfIntSet, kFALSE);
termIntNoNormDeps->add(pdfIntNoNormDeps, kFALSE);
termList.Add(term);
normList.Add(termNormDeps);
depAllList.Add(termAllDeps);
intList.Add(termIntDeps);
depIntNoNormList.Add(termIntNoNormDeps);
}
}
delete pdfNSet;
delete pdfIntSet;
if (pdfCSet != pdfNSetOrig) {
delete pdfCSet;
}
}
RooArgSet *normDeps, *allDeps, *intNoNormDeps;
for (RooFIter lIter = termList.fwdIterator(),
ldIter = normList.fwdIterator(),
laIter = depAllList.fwdIterator(),
innIter = depIntNoNormList.fwdIterator();
(normDeps = (RooArgSet*) ldIter.next(),
allDeps = (RooArgSet*) laIter.next(),
intNoNormDeps = (RooArgSet*) innIter.next(),
term=(RooArgSet*)lIter.next()); ) {
RooArgSet impDeps(*allDeps);
impDeps.remove(*normDeps, kTRUE, kTRUE);
impDepList.Add(impDeps.snapshot());
RooArgSet* crossDeps = (RooArgSet*) intNoNormDeps->selectCommon(*normDeps);
crossDepList.Add(crossDeps->snapshot());
delete crossDeps;
}
depAllList.Delete();
depIntNoNormList.Delete();
return;
}
void RooProdPdf::getPartIntList(const RooArgSet* nset, const RooArgSet* iset,
pRooArgList& partList, pRooLinkedList& nsetList,
Int_t& code, const char* isetRangeName) const
{
Int_t sterileIdx(-1);
CacheElem* cache = (CacheElem*) _cacheMgr.getObj(nset,iset,&sterileIdx,isetRangeName);
if (cache) {
code = _cacheMgr.lastIndex();
partList = &cache->_partList;
nsetList = &cache->_normList;
return;
}
cache = new CacheElem;
RooLinkedList terms, norms, imp, ints, cross;
RooArgSet factNset(nset ? (*nset) : _defNormSet);
factorizeProduct(factNset, iset ? (*iset) : RooArgSet(), terms, norms, imp, cross, ints);
RooArgSet *norm, *integ, *xdeps, *imps;
RooLinkedList groupedList;
RooArgSet outerIntDeps;
groupProductTerms(groupedList, outerIntDeps, terms, norms, imp, ints, cross);
RooFIter gIter = groupedList.fwdIterator();
RooLinkedList* group;
map<string, RooArgSet> ratioTerms;
while ((group = (RooLinkedList*) gIter.next())) {
if (1 == group->GetSize()) {
RooArgSet* term = (RooArgSet*) group->At(0);
Int_t termIdx = terms.IndexOf(term);
norm=(RooArgSet*) norms.At(termIdx);
imps=(RooArgSet*)imp.At(termIdx);
RooArgSet termNSet(*norm), termImpSet(*imps);
if (termImpSet.getSize() > 0 && 0 != _refRangeName) {
Bool_t rangeIdentical(kTRUE);
RooFIter niter = termNSet.fwdIterator();
RooRealVar* normObs;
while ((normObs = (RooRealVar*) niter.next())) {
if (_normRange.Length() > 0) {
if (normObs->getMin(_normRange.Data()) != normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
if (normObs->getMax(_normRange.Data()) != normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
}
else{
if (normObs->getMin() != normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
if (normObs->getMax() != normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
}
}
if (!rangeIdentical || 1) {
RooAbsReal* ratio = makeCondPdfRatioCorr(*(RooAbsReal*)term->first(), termNSet, termImpSet, normRange(), RooNameReg::str(_refRangeName));
ostringstream str; termImpSet.printValue(str);
ratioTerms[str.str()].add(*ratio);
}
}
} else {
RooArgSet compTermSet, compTermNorm;
RooFIter tIter = group->fwdIterator();
RooArgSet* term;
while ((term = (RooArgSet*) tIter.next())) {
Int_t termIdx = terms.IndexOf(term);
norm=(RooArgSet*) norms.At(termIdx);
imps=(RooArgSet*)imp.At(termIdx);
RooArgSet termNSet(*norm), termImpSet(*imps);
if (termImpSet.getSize() > 0 && 0 != _refRangeName) {
Bool_t rangeIdentical(kTRUE);
RooFIter niter = termNSet.fwdIterator();
RooRealVar* normObs;
if(_normRange.Length() > 0) {
while ((normObs = (RooRealVar*) niter.next())) {
if (normObs->getMin(_normRange.Data()) != normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
if (normObs->getMax(_normRange.Data()) != normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
}
} else {
while ((normObs = (RooRealVar*) niter.next())) {
if (normObs->getMin() != normObs->getMin(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
if (normObs->getMax() != normObs->getMax(RooNameReg::str(_refRangeName))) rangeIdentical = kFALSE;
}
}
if (!rangeIdentical || 1) {
RooAbsReal* ratio = makeCondPdfRatioCorr(*(RooAbsReal*)term->first(), termNSet, termImpSet, normRange(), RooNameReg::str(_refRangeName));
ostringstream str; termImpSet.printValue(str);
ratioTerms[str.str()].add(*ratio);
}
}
}
}
}
gIter = groupedList.fwdIterator();
while ((group = (RooLinkedList*) gIter.next())) {
if (1 == group->GetSize()) {
RooArgSet* term = (RooArgSet*) group->At(0);
Int_t termIdx = terms.IndexOf(term);
norm = (RooArgSet*) norms.At(termIdx);
imps = (RooArgSet*) imp.At(termIdx);
RooArgSet termNSet(*norm), termImpSet(*imps);
ostringstream str; termNSet.printValue(str);
if (ratioTerms[str.str()].getSize() > 0) {
term->add(ratioTerms[str.str()]);
}
} else {
RooArgSet compTermSet, compTermNorm;
RooFIter tIter = group->fwdIterator();
RooArgSet* term;
while ((term = (RooArgSet*) tIter.next())) {
Int_t termIdx = terms.IndexOf(term);
norm = (RooArgSet*) norms.At(termIdx);
imps = (RooArgSet*) imp.At(termIdx);
RooArgSet termNSet(*norm), termImpSet(*imps);
ostringstream str; termNSet.printValue(str);
if (ratioTerms[str.str()].getSize() > 0) {
term->add(ratioTerms[str.str()]);
}
}
}
}
gIter = groupedList.fwdIterator();
while ((group = (RooLinkedList*) gIter.next())) {
if (1 == group->GetSize()) {
RooArgSet* term = (RooArgSet*) group->At(0);
Int_t termIdx = terms.IndexOf(term);
norm = (RooArgSet*) norms.At(termIdx);
integ = (RooArgSet*) ints.At(termIdx);
xdeps = (RooArgSet*) cross.At(termIdx);
imps = (RooArgSet*) imp.At(termIdx);
RooArgSet termNSet, termISet, termXSet, termImpSet;
termISet.add(*integ);
termNSet.add(*norm);
termXSet.add(*xdeps);
termImpSet.add(*imps);
Bool_t isOwned(kFALSE);
vector<RooAbsReal*> func = processProductTerm(nset, iset, isetRangeName, term, termNSet, termISet, isOwned);
if (func[0]) {
cache->_partList.add(*func[0]);
if (isOwned) cache->_ownedList.addOwned(*func[0]);
cache->_normList.Add(norm->snapshot(kFALSE));
cache->_numList.addOwned(*func[1]);
cache->_denList.addOwned(*func[2]);
}
} else {
RooArgSet compTermSet, compTermNorm, compTermNum, compTermDen;
RooFIter tIter = group->fwdIterator();
RooArgSet* term;
while ((term = (RooArgSet*) tIter.next())) {
Int_t termIdx = terms.IndexOf(term);
norm = (RooArgSet*) norms.At(termIdx);
integ = (RooArgSet*) ints.At(termIdx);
xdeps = (RooArgSet*) cross.At(termIdx);
imps = (RooArgSet*) imp.At(termIdx);
RooArgSet termNSet, termISet, termXSet, termImpSet;
termISet.add(*integ);
termNSet.add(*norm);
termXSet.add(*xdeps);
termImpSet.add(*imps);
termISet.remove(outerIntDeps, kTRUE, kTRUE);
Bool_t isOwned;
vector<RooAbsReal*> func = processProductTerm(nset, iset, isetRangeName, term, termNSet, termISet, isOwned, kTRUE);
if (func[0]) {
compTermSet.add(*func[0]);
if (isOwned) cache->_ownedList.addOwned(*func[0]);
compTermNorm.add(*norm, kFALSE);
compTermNum.add(*func[1]);
compTermDen.add(*func[2]);
}
}
const std::string prodname = makeRGPPName("SPECPROD", compTermSet, outerIntDeps, RooArgSet(), isetRangeName);
RooProduct* prodtmp = new RooProduct(prodname.c_str(), prodname.c_str(), compTermSet);
cache->_ownedList.addOwned(*prodtmp);
const std::string intname = makeRGPPName("SPECINT", compTermSet, outerIntDeps, RooArgSet(), isetRangeName);
RooRealIntegral* inttmp = new RooRealIntegral(intname.c_str(), intname.c_str(), *prodtmp, outerIntDeps, 0, 0, isetRangeName);
inttmp->setStringAttribute("PROD_TERM_TYPE", "SPECINT");
cache->_ownedList.addOwned(*inttmp);
cache->_partList.add(*inttmp);
const string prodname_num = makeRGPPName("SPECPROD_NUM", compTermNum, RooArgSet(), RooArgSet(), 0);
RooProduct* prodtmp_num = new RooProduct(prodname_num.c_str(), prodname_num.c_str(), compTermNum);
prodtmp_num->addOwnedComponents(compTermNum);
cache->_ownedList.addOwned(*prodtmp_num);
const string prodname_den = makeRGPPName("SPECPROD_DEN", compTermDen, RooArgSet(), RooArgSet(), 0);
RooProduct* prodtmp_den = new RooProduct(prodname_den.c_str(), prodname_den.c_str(), compTermDen);
prodtmp_den->addOwnedComponents(compTermDen);
cache->_ownedList.addOwned(*prodtmp_den);
string name = Form("SPEC_RATIO(%s,%s)", prodname_num.c_str(), prodname_den.c_str());
RooFormulaVar* ndr = new RooFormulaVar(name.c_str(), "@0/@1", RooArgList(*prodtmp_num, *prodtmp_den));
RooAbsReal* numtmp = ndr->createIntegral(outerIntDeps,isetRangeName);
numtmp->addOwnedComponents(*ndr);
cache->_numList.addOwned(*numtmp);
cache->_denList.addOwned(*(RooAbsArg*)RooFit::RooConst(1).clone("1"));
cache->_normList.Add(compTermNorm.snapshot(kFALSE));
}
}
code = _cacheMgr.setObj(nset, iset, (RooAbsCacheElement*)cache, RooNameReg::ptr(isetRangeName));
partList = &cache->_partList;
nsetList = &cache->_normList;
if (_normRange.Contains(",")) {
rearrangeProduct(*cache);
}
groupedList.Delete();
terms.Delete();
ints.Delete();
imp.Delete();
norms.Delete();
cross.Delete();
}
RooAbsReal* RooProdPdf::makeCondPdfRatioCorr(RooAbsReal& pdf, const RooArgSet& termNset, const RooArgSet& , const char* normRangeTmp, const char* refRange) const
{
RooAbsReal* ratio_num = pdf.createIntegral(termNset,normRangeTmp) ;
RooAbsReal* ratio_den = pdf.createIntegral(termNset,refRange) ;
RooFormulaVar* ratio = new RooFormulaVar(Form("ratio(%s,%s)",ratio_num->GetName(),ratio_den->GetName()),"@0/@1",
RooArgList(*ratio_num,*ratio_den)) ;
ratio->addOwnedComponents(RooArgSet(*ratio_num,*ratio_den)) ;
ratio->setAttribute("RATIO_TERM") ;
return ratio ;
}
void RooProdPdf::rearrangeProduct(RooProdPdf::CacheElem& cache) const
{
RooAbsReal* part, *num, *den ;
RooArgSet nomList ;
list<string> rangeComps ;
{
char* buf = new char[strlen(_normRange.Data()) + 1] ;
strcpy(buf,_normRange.Data()) ;
char* save(0) ;
char* token = strtok_r(buf,",",&save) ;
while(token) {
rangeComps.push_back(token) ;
token = strtok_r(0,",",&save) ;
}
delete[] buf;
}
map<string,RooArgSet> denListList ;
RooArgSet specIntDeps ;
string specIntRange ;
RooFIter iterp = cache._partList.fwdIterator() ;
RooFIter iter1 = cache._numList.fwdIterator() ;
RooFIter iter2 = cache._denList.fwdIterator() ;
RooFIter itern = cache._normList.fwdIterator() ;
while((part=(RooAbsReal*)iterp.next())) {
itern.next() ;
num = (RooAbsReal*) iter1.next() ;
den = (RooAbsReal*) iter2.next() ;
RooFormulaVar* ratio(0) ;
RooArgSet origNumTerm ;
if (string("SPECINT")==part->getStringAttribute("PROD_TERM_TYPE")) {
RooRealIntegral* orig = (RooRealIntegral*) num;
RooFormulaVar* specratio = (RooFormulaVar*) &orig->integrand() ;
RooProduct* func = (RooProduct*) specratio->getParameter(0) ;
RooArgSet* comps = orig->getComponents() ;
RooFIter iter = comps->fwdIterator() ;
RooAbsArg* carg ;
while((carg=(RooAbsArg*)iter.next())) {
if (carg->getAttribute("RATIO_TERM")) {
ratio = (RooFormulaVar*)carg ;
break ;
}
}
delete comps ;
if (ratio) {
RooCustomizer cust(*func,"blah") ;
cust.replaceArg(*ratio,RooFit::RooConst(1)) ;
RooAbsArg* funcCust = cust.build() ;
nomList.add(*funcCust) ;
} else {
nomList.add(*func) ;
}
} else {
RooAbsReal* func = num;
if (func->InheritsFrom(RooRealIntegral::Class())) {
func = (RooAbsReal*) &((RooRealIntegral*)(func))->integrand();
}
if (func->InheritsFrom(RooProduct::Class())) {
RooArgSet comps(((RooProduct*)(func))->components()) ;
RooFIter iter = comps.fwdIterator() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)iter.next())) {
if (arg->getAttribute("RATIO_TERM")) {
ratio = (RooFormulaVar*)(arg) ;
} else {
origNumTerm.add(*arg) ;
}
}
}
if (ratio) {
nomList.add(origNumTerm) ;
} else {
nomList.add(*num) ;
}
}
for (list<string>::iterator iter = rangeComps.begin() ; iter != rangeComps.end() ; ++iter) {
if (string("SPECINT")==part->getStringAttribute("PROD_TERM_TYPE")) {
RooRealIntegral* orig = (RooRealIntegral*) num;
RooFormulaVar* specRatio = (RooFormulaVar*) &orig->integrand() ;
specIntDeps.add(orig->intVars()) ;
if (orig->intRange()) {
specIntRange = orig->intRange() ;
}
RooProduct* dentmp = (RooProduct*) specRatio->getParameter(1) ;
RooArgSet comps(dentmp->components()) ;
RooFIter piter = comps.fwdIterator() ;
RooAbsReal* parg ;
while((parg=(RooAbsReal*)piter.next())) {
if (ratio && parg->dependsOn(*ratio)) {
RooAbsReal* specializedRatio = specializeRatio(*(RooFormulaVar*)ratio,iter->c_str()) ;
RooAbsArg *partCust(0) ;
if (parg->InheritsFrom(RooAddition::Class())) {
RooAddition* tmpadd = (RooAddition*)(parg) ;
RooCustomizer cust(*tmpadd->list1().first(),Form("blah_%s",iter->c_str())) ;
cust.replaceArg(*ratio,*specializedRatio) ;
partCust = cust.build() ;
} else {
RooCustomizer cust(*parg,Form("blah_%s",iter->c_str())) ;
cust.replaceArg(*ratio,*specializedRatio) ;
partCust = cust.build() ;
}
RooAbsReal* specializedPartCust = specializeIntegral(*(RooAbsReal*)partCust,iter->c_str()) ;
string name = Form("%s_divided_by_ratio",specializedPartCust->GetName()) ;
RooFormulaVar* specIntFinal = new RooFormulaVar(name.c_str(),"@0/@1",RooArgList(*specializedPartCust,*specializedRatio)) ;
denListList[*iter].add(*specIntFinal) ;
} else {
denListList[*iter].add(*specializeIntegral(*parg,iter->c_str())) ;
}
}
} else {
if (ratio) {
RooAbsReal* specRatio = specializeRatio(*(RooFormulaVar*)ratio,iter->c_str()) ;
RooArgSet tmp(origNumTerm) ;
tmp.add(*specRatio) ;
const string pname = makeRGPPName("PROD",tmp,RooArgSet(),RooArgSet(),0) ;
RooProduct* specDenProd = new RooProduct(pname.c_str(),pname.c_str(),tmp) ;
RooAbsReal* specInt(0) ;
if (den->InheritsFrom(RooRealIntegral::Class())) {
specInt = specDenProd->createIntegral(((RooRealIntegral*)den)->intVars(),iter->c_str()) ;
} else if (den->InheritsFrom(RooAddition::Class())) {
RooAddition* orig = (RooAddition*)den ;
RooRealIntegral* origInt = (RooRealIntegral*) orig->list1().first() ;
specInt = specDenProd->createIntegral(origInt->intVars(),iter->c_str()) ;
} else {
throw string("this should not happen") ;
}
string name = Form("%s_divided_by_ratio",specInt->GetName()) ;
RooFormulaVar* specIntFinal = new RooFormulaVar(name.c_str(),"@0/@1",RooArgList(*specInt,*specRatio)) ;
denListList[*iter].add(*specIntFinal) ;
} else {
denListList[*iter].add(*specializeIntegral(*den,iter->c_str())) ;
}
}
}
}
if (nomList.getSize()==0) {
return ;
}
string name = Form("%s_numerator",GetName()) ;
RooAbsReal* numerator = new RooProduct(name.c_str(),name.c_str(),nomList) ;
RooArgSet products ;
for (map<string,RooArgSet>::iterator iter = denListList.begin() ; iter != denListList.end() ; ++iter) {
name = Form("%s_denominator_comp_%s",GetName(),iter->first.c_str()) ;
RooProduct* prod_comp = new RooProduct(name.c_str(),name.c_str(),iter->second) ;
products.add(*prod_comp) ;
}
name = Form("%s_denominator_sum",GetName()) ;
RooAbsReal* norm = new RooAddition(name.c_str(),name.c_str(),products) ;
norm->addOwnedComponents(products) ;
if (specIntDeps.getSize()>0) {
string namesr = Form("SPEC_RATIO(%s,%s)",numerator->GetName(),norm->GetName()) ;
RooFormulaVar* ndr = new RooFormulaVar(namesr.c_str(),"@0/@1",RooArgList(*numerator,*norm)) ;
RooAbsReal* numtmp = ndr->createIntegral(specIntDeps,specIntRange.c_str()) ;
numerator = numtmp ;
norm = (RooAbsReal*) RooFit::RooConst(1).Clone() ;
}
cache._rearrangedNum = numerator ;
cache._rearrangedDen = norm ;
cache._isRearranged = kTRUE ;
}
RooAbsReal* RooProdPdf::specializeRatio(RooFormulaVar& input, const char* targetRangeName) const
{
RooRealIntegral* numint = (RooRealIntegral*) input.getParameter(0) ;
RooRealIntegral* denint = (RooRealIntegral*) input.getParameter(1) ;
RooAbsReal* numint_spec = specializeIntegral(*numint,targetRangeName) ;
RooAbsReal* ret = new RooFormulaVar(Form("ratio(%s,%s)",numint_spec->GetName(),denint->GetName()),"@0/@1",RooArgList(*numint_spec,*denint)) ;
ret->addOwnedComponents(*numint_spec) ;
return ret ;
}
RooAbsReal* RooProdPdf::specializeIntegral(RooAbsReal& input, const char* targetRangeName) const
{
if (input.InheritsFrom(RooRealIntegral::Class())) {
RooRealIntegral* orig = (RooRealIntegral*)&input ;
return orig->integrand().createIntegral(orig->intVars(),targetRangeName) ;
} else if (input.InheritsFrom(RooAddition::Class())) {
RooAddition* orig = (RooAddition*)&input ;
RooRealIntegral* origInt = (RooRealIntegral*) orig->list1().first() ;
return origInt->integrand().createIntegral(origInt->intVars(),targetRangeName) ;
} else {
}
return &input ;
}
void RooProdPdf::groupProductTerms(RooLinkedList& groupedTerms, RooArgSet& outerIntDeps,
const RooLinkedList& terms, const RooLinkedList& norms,
const RooLinkedList& imps, const RooLinkedList& ints, const RooLinkedList& ) const
{
RooFIter tIter = terms.fwdIterator() ;
RooArgSet* term ;
while((term=(RooArgSet*)tIter.next())) {
RooLinkedList* group = new RooLinkedList ;
group->Add(term) ;
groupedTerms.Add(group) ;
}
RooArgSet allImpDeps ;
RooFIter iIter = imps.fwdIterator() ;
RooArgSet *impDeps ;
while((impDeps=(RooArgSet*)iIter.next())) {
allImpDeps.add(*impDeps,kFALSE) ;
}
RooArgSet allIntDeps ;
iIter = ints.fwdIterator() ;
RooArgSet *intDeps ;
while((intDeps=(RooArgSet*)iIter.next())) {
allIntDeps.add(*intDeps,kFALSE) ;
}
RooArgSet* tmp = (RooArgSet*) allIntDeps.selectCommon(allImpDeps) ;
outerIntDeps.removeAll() ;
outerIntDeps.add(*tmp) ;
delete tmp ;
RooFIter oidIter = outerIntDeps.fwdIterator() ;
RooAbsArg* outerIntDep ;
while ((outerIntDep =(RooAbsArg*)oidIter.next())) {
RooLinkedList* newGroup = 0 ;
RooLinkedList* group ;
RooFIter glIter = groupedTerms.fwdIterator() ;
Bool_t needMerge = kFALSE ;
while((group=(RooLinkedList*)glIter.next())) {
RooArgSet* term2 ;
RooFIter tIter2 = group->fwdIterator() ;
while((term2=(RooArgSet*)tIter2.next())) {
Int_t termIdx = terms.IndexOf(term2) ;
RooArgSet* termNormDeps = (RooArgSet*) norms.At(termIdx) ;
RooArgSet* termIntDeps = (RooArgSet*) ints.At(termIdx) ;
RooArgSet* termImpDeps = (RooArgSet*) imps.At(termIdx) ;
if (termNormDeps->contains(*outerIntDep) ||
termIntDeps->contains(*outerIntDep) ||
termImpDeps->contains(*outerIntDep)) {
needMerge = kTRUE ;
}
}
if (needMerge) {
if (newGroup==0) {
newGroup = new RooLinkedList ;
}
tIter2 = group->fwdIterator() ;
while((term2=(RooArgSet*)tIter2.next())) {
newGroup->Add(term2) ;
}
groupedTerms.Remove(group) ;
delete group ;
}
}
if (newGroup) {
groupedTerms.Add(newGroup) ;
}
}
}
std::vector<RooAbsReal*> RooProdPdf::processProductTerm(const RooArgSet* nset, const RooArgSet* iset, const char* isetRangeName,
const RooArgSet* term,const RooArgSet& termNSet, const RooArgSet& termISet,
Bool_t& isOwned, Bool_t forceWrap) const
{
vector<RooAbsReal*> ret(3) ; ret[0] = 0 ; ret[1] = 0 ; ret[2] = 0 ;
if (termNSet.getSize()>0 && termNSet.getSize()==termISet.getSize() && isetRangeName==0) {
return ret ;
}
if (nset && termNSet.getSize()==0) {
return ret ;
}
if (iset && termISet.getSize()>0) {
if (term->getSize()==1) {
RooAbsPdf* pdf = (RooAbsPdf*) term->first() ;
RooAbsReal* partInt = pdf->createIntegral(termISet,termNSet,isetRangeName) ;
partInt->setStringAttribute("PROD_TERM_TYPE","IIIa") ;
isOwned=kTRUE ;
ret[0] = partInt ;
ret[1] = pdf->createIntegral(termISet,isetRangeName) ;
ret[2] = pdf->createIntegral(termNSet,normRange()) ;
return ret ;
} else {
const std::string name = makeRGPPName("GENPROJ_",*term,termISet,termNSet,isetRangeName) ;
RooAbsReal* partInt = new RooGenProdProj(name.c_str(),name.c_str(),*term,termISet,termNSet,isetRangeName) ;
partInt->setStringAttribute("PROD_TERM_TYPE","IIIb") ;
isOwned=kTRUE ;
ret[0] = partInt ;
const std::string name1 = makeRGPPName("PROD",*term,RooArgSet(),RooArgSet(),0) ;
RooProduct* tmp_prod = new RooProduct(name1.c_str(),name1.c_str(),*term) ;
ret[1] = tmp_prod->createIntegral(termISet,isetRangeName) ;
ret[2] = tmp_prod->createIntegral(termNSet,normRange()) ;
return ret ;
}
}
if (nset && nset->getSize()>0 && term->getSize()>1) {
const std::string name = makeRGPPName("GENPROJ_",*term,termISet,termNSet,isetRangeName) ;
RooAbsReal* partInt = new RooGenProdProj(name.c_str(),name.c_str(),*term,termISet,termNSet,isetRangeName,normRange()) ;
partInt->setExpensiveObjectCache(expensiveObjectCache()) ;
partInt->setStringAttribute("PROD_TERM_TYPE","IVa") ;
isOwned=kTRUE ;
ret[0] = partInt ;
const std::string name1 = makeRGPPName("PROD",*term,RooArgSet(),RooArgSet(),0) ;
RooProduct* tmp_prod = new RooProduct(name1.c_str(),name1.c_str(),*term) ;
ret[1] = tmp_prod->createIntegral(termISet,isetRangeName) ;
ret[2] = tmp_prod->createIntegral(termNSet,normRange()) ;
return ret ;
}
RooFIter pIter = term->fwdIterator() ;
RooAbsPdf* pdf ;
while((pdf=(RooAbsPdf*)pIter.next())) {
if (forceWrap) {
TString name(pdf->GetName()) ;
name.Append("_NORM[") ;
RooFIter nIter = termNSet.fwdIterator() ;
RooAbsArg* arg ;
Bool_t first(kTRUE) ;
while((arg=(RooAbsArg*)nIter.next())) {
if (!first) {
name.Append(",") ;
} else {
first=kFALSE ;
}
name.Append(arg->GetName()) ;
}
if (normRange()) {
name.Append("|") ;
name.Append(normRange()) ;
}
name.Append("]") ;
RooAbsReal* partInt = new RooRealIntegral(name.Data(),name.Data(),*pdf,RooArgSet(),&termNSet) ;
partInt->setStringAttribute("PROD_TERM_TYPE","IVb") ;
isOwned=kTRUE ;
ret[0] = partInt ;
ret[1] = pdf->createIntegral(RooArgSet()) ;
ret[2] = pdf->createIntegral(termNSet,normRange()) ;
return ret ;
} else {
isOwned=kFALSE ;
pdf->setStringAttribute("PROD_TERM_TYPE","IVb") ;
ret[0] = pdf ;
ret[1] = pdf->createIntegral(RooArgSet()) ;
ret[2] = termNSet.getSize()>0 ? pdf->createIntegral(termNSet,normRange()) : ((RooAbsReal*)RooFit::RooConst(1).clone("1")) ;
return ret ;
}
}
coutE(Eval) << "RooProdPdf::processProductTerm(" << GetName() << ") unidentified term!!!" << endl ;
return ret ;
}
std::string RooProdPdf::makeRGPPName(const char* pfx, const RooArgSet& term, const RooArgSet& iset,
const RooArgSet& nset, const char* isetRangeName) const
{
std::ostringstream os(pfx);
os << "[";
RooFIter pIter = term.fwdIterator() ;
Bool_t first(kTRUE) ;
RooAbsPdf* pdf ;
while ((pdf=(RooAbsPdf*)pIter.next())) {
if (!first) os << "_X_";
first = kFALSE;
os << pdf->GetName();
}
os << "]" << integralNameSuffix(iset,&nset,isetRangeName,kTRUE);
return os.str();
}
Bool_t RooProdPdf::forceAnalyticalInt(const RooAbsArg& ) const
{
return kTRUE ;
}
Int_t RooProdPdf::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars,
const RooArgSet* normSet, const char* rangeName) const
{
if (_forceNumInt) return 0 ;
analVars.add(allVars) ;
Int_t code ;
RooArgList *plist(0) ;
RooLinkedList *nlist(0) ;
getPartIntList(normSet,&allVars,plist,nlist,code,rangeName) ;
return code+1 ;
}
Double_t RooProdPdf::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
{
if (code==0) {
return getVal(normSet) ;
}
CacheElem* cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1) ;
RooArgList* partIntList(0) ;
RooLinkedList* normList(0) ;
if (cache==0) {
RooArgSet* vars = getParameters(RooArgSet()) ;
RooArgSet* nset = _cacheMgr.nameSet1ByIndex(code-1)->select(*vars) ;
RooArgSet* iset = _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) ;
Int_t code2(-1) ;
getPartIntList(nset,iset,partIntList,normList,code2,rangeName) ;
delete vars ;
cache = (CacheElem*) _cacheMgr.getObj(nset,iset,&code2,rangeName) ;
delete nset ;
delete iset ;
} else {
partIntList = &cache->_partList ;
normList = &cache->_normList ;
}
Double_t val = calculate(*cache,kTRUE) ;
return val ;
}
Bool_t RooProdPdf::checkObservables(const RooArgSet* ) const
{
return kFALSE ;
}
RooAbsPdf::ExtendMode RooProdPdf::extendMode() const
{
return (_extendedIndex>=0) ? ((RooAbsPdf*)_pdfList.at(_extendedIndex))->extendMode() : CanNotBeExtended ;
}
Double_t RooProdPdf::expectedEvents(const RooArgSet* nset) const
{
if (_extendedIndex<0) {
coutE(Generation) << "ERROR: Requesting expected number of events from a RooProdPdf that does not contain an extended p.d.f" << endl ;
}
assert(_extendedIndex>=0) ;
return ((RooAbsPdf*)_pdfList.at(_extendedIndex))->expectedEvents(nset) ;
}
RooAbsGenContext* RooProdPdf::genContext(const RooArgSet &vars, const RooDataSet *prototype,
const RooArgSet* auxProto, Bool_t verbose) const
{
if (_useDefaultGen) return RooAbsPdf::genContext(vars,prototype,auxProto,verbose) ;
return new RooProdGenContext(*this,vars,prototype,auxProto,verbose) ;
}
Int_t RooProdPdf::getGenerator(const RooArgSet& directVars, RooArgSet &generateVars, Bool_t staticInitOK) const
{
if (!_useDefaultGen) return 0 ;
RooArgSet directSafe ;
RooFIter dIter = directVars.fwdIterator() ;
RooAbsArg* arg ;
while((arg=(RooAbsArg*)dIter.next())) {
if (isDirectGenSafe(*arg)) directSafe.add(*arg) ;
}
RooAbsPdf* pdf ;
std::vector<Int_t> code;
code.reserve(64);
RooFIter pdfIter = _pdfList.fwdIterator();
while((pdf=(RooAbsPdf*)pdfIter.next())) {
RooArgSet pdfDirect ;
Int_t pdfCode = pdf->getGenerator(directSafe,pdfDirect,staticInitOK);
code.push_back(pdfCode);
if (pdfCode != 0) {
generateVars.add(pdfDirect) ;
}
}
if (generateVars.getSize()>0) {
Int_t masterCode = _genCode.store(code) ;
return masterCode+1 ;
} else {
return 0 ;
}
}
void RooProdPdf::initGenerator(Int_t code)
{
if (!_useDefaultGen) return ;
const std::vector<Int_t>& codeList = _genCode.retrieve(code-1) ;
RooAbsPdf* pdf ;
Int_t i(0) ;
RooFIter pdfIter = _pdfList.fwdIterator();
while((pdf=(RooAbsPdf*)pdfIter.next())) {
if (codeList[i]!=0) {
pdf->initGenerator(codeList[i]) ;
}
i++ ;
}
}
void RooProdPdf::generateEvent(Int_t code)
{
if (!_useDefaultGen) return ;
const std::vector<Int_t>& codeList = _genCode.retrieve(code-1) ;
RooAbsPdf* pdf ;
Int_t i(0) ;
RooFIter pdfIter = _pdfList.fwdIterator();
while((pdf=(RooAbsPdf*)pdfIter.next())) {
if (codeList[i]!=0) {
pdf->generateEvent(codeList[i]) ;
}
i++ ;
}
}
RooProdPdf::CacheElem::~CacheElem()
{
_normList.Delete() ;
if (_rearrangedNum) delete _rearrangedNum ;
if (_rearrangedDen) delete _rearrangedDen ;
}
RooArgList RooProdPdf::CacheElem::containedArgs(Action)
{
RooArgList ret ;
ret.add(_partList) ;
ret.add(_numList) ;
ret.add(_denList) ;
if (_rearrangedNum) ret.add(*_rearrangedNum) ;
if (_rearrangedDen) ret.add(*_rearrangedDen) ;
return ret ;
}
void RooProdPdf::CacheElem::printCompactTreeHook(ostream& os, const char* indent, Int_t curElem, Int_t maxElem)
{
if (curElem==0) {
os << indent << "RooProdPdf begin partial integral cache" << endl ;
}
RooFIter iter = _partList.fwdIterator() ;
RooAbsArg* arg ;
TString indent2(indent) ;
indent2 += Form("[%d] ",curElem) ;
while((arg=(RooAbsArg*)iter.next())) {
arg->printCompactTree(os,indent2) ;
}
if (curElem==maxElem) {
os << indent << "RooProdPdf end partial integral cache" << endl ;
}
}
Bool_t RooProdPdf::isDirectGenSafe(const RooAbsArg& arg) const
{
if (!_useDefaultGen) return RooAbsPdf::isDirectGenSafe(arg) ;
RooAbsPdf* pdf, *thePdf(0) ;
RooFIter pdfIter = _pdfList.fwdIterator();
while((pdf=(RooAbsPdf*)pdfIter.next())) {
if (pdf->dependsOn(arg)) {
if (thePdf) return kFALSE ;
thePdf = pdf ;
}
}
return thePdf?(thePdf->isDirectGenSafe(arg)):kFALSE ;
}
RooArgSet* RooProdPdf::findPdfNSet(RooAbsPdf& pdf) const
{
Int_t idx = _pdfList.index(&pdf) ;
if (idx<0) return 0 ;
return (RooArgSet*) _pdfNSetList.At(idx) ;
}
RooArgSet* RooProdPdf::getConstraints(const RooArgSet& observables, RooArgSet& constrainedParams, Bool_t stripDisconnected) const
{
RooArgSet constraints ;
RooArgSet pdfParams, conParams ;
RooFIter piter = _pdfList.fwdIterator() ;
RooAbsPdf* pdf ;
while((pdf=(RooAbsPdf*)piter.next())) {
if (!pdf->dependsOnValue(observables) && pdf->dependsOnValue(constrainedParams)) {
constraints.add(*pdf) ;
RooArgSet* tmp = pdf->getParameters(observables) ;
conParams.add(*tmp,kTRUE) ;
delete tmp ;
} else {
RooArgSet* tmp = pdf->getParameters(observables) ;
pdfParams.add(*tmp,kTRUE) ;
delete tmp ;
}
}
RooArgSet* finalConstraints = new RooArgSet("constraints") ;
RooFIter citer = constraints.fwdIterator() ;
while((pdf=(RooAbsPdf*)citer.next())) {
if (pdf->dependsOnValue(pdfParams) || !stripDisconnected) {
finalConstraints->add(*pdf) ;
} else {
coutI(Minimization) << "RooProdPdf::getConstraints(" << GetName() << ") omitting term " << pdf->GetName()
<< " as constraint term as it does not share any parameters with the other pdfs in product. "
<< "To force inclusion in likelihood, add an explicit Constrain() argument for the target parameter" << endl ;
}
}
RooArgSet* cexl = (RooArgSet*) conParams.selectCommon(constrainedParams) ;
cexl->remove(pdfParams,kTRUE,kTRUE) ;
constrainedParams.remove(*cexl,kTRUE,kTRUE) ;
delete cexl ;
return finalConstraints ;
}
RooArgSet* RooProdPdf::getConnectedParameters(const RooArgSet& observables) const
{
RooFIter iter = _pdfList.fwdIterator() ;
RooAbsArg* arg ;
RooArgSet* connectedPars = new RooArgSet("connectedPars") ;
while((arg=iter.next())) {
if (arg->dependsOn(observables)) {
RooArgSet* tmp = arg->getParameters(observables) ;
connectedPars->add(*tmp) ;
delete tmp ;
} else {
}
}
return connectedPars ;
}
void RooProdPdf::getParametersHook(const RooArgSet* nset, RooArgSet* params, Bool_t stripDisconnected) const
{
if (!stripDisconnected) return ;
if (!nset || nset->getSize()==0) return ;
RooArgList *plist(0) ;
RooLinkedList *nlist(0) ;
Int_t code ;
getPartIntList(nset,0,plist,nlist,code) ;
RooFIter piter = params->fwdIterator() ;
RooAbsReal* term, *param ;
RooArgSet tostrip ;
while((param=(RooAbsReal*)piter.next())) {
Bool_t anyDep(kFALSE) ;
RooFIter titer = plist->fwdIterator() ;
while((term=(RooAbsReal*)titer.next())) {
if (term->dependsOnValue(*param)) {
anyDep=kTRUE ;
}
}
if (!anyDep) {
tostrip.add(*param) ;
}
}
if (tostrip.getSize()>0) {
params->remove(tostrip,kTRUE,kTRUE);
}
}
void RooProdPdf::selectNormalizationRange(const char* rangeName, Bool_t force)
{
if (!force && _refRangeName) {
return ;
}
fixRefRange(rangeName) ;
}
void RooProdPdf::fixRefRange(const char* rangeName)
{
_refRangeName = (TNamed*)RooNameReg::ptr(rangeName) ;
}
std::list<Double_t>* RooProdPdf::plotSamplingHint(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
{
RooAbsPdf* pdf ;
RooFIter pdfIter = _pdfList.fwdIterator();
while((pdf=(RooAbsPdf*)pdfIter.next())) {
list<Double_t>* hint = pdf->plotSamplingHint(obs,xlo,xhi) ;
if (hint) {
return hint ;
}
}
return 0 ;
}
Bool_t RooProdPdf::isBinnedDistribution(const RooArgSet& obs) const
{
RooAbsPdf* pdf ;
RooFIter pdfIter = _pdfList.fwdIterator();
while((pdf=(RooAbsPdf*)pdfIter.next())) {
if (pdf->dependsOn(obs) && !pdf->isBinnedDistribution(obs)) {
return kFALSE ;
}
}
return kTRUE ;
}
std::list<Double_t>* RooProdPdf::binBoundaries(RooAbsRealLValue& obs, Double_t xlo, Double_t xhi) const
{
RooAbsPdf* pdf ;
RooFIter pdfIter = _pdfList.fwdIterator();
while((pdf=(RooAbsPdf*)pdfIter.next())) {
list<Double_t>* hint = pdf->binBoundaries(obs,xlo,xhi) ;
if (hint) {
return hint ;
}
}
return 0 ;
}
void RooProdPdf::setCacheAndTrackHints(RooArgSet& trackNodes)
{
RooFIter piter = pdfList().fwdIterator() ;
RooAbsArg* parg ;
while ((parg=piter.next())) {
if (parg->canNodeBeCached()==Always) {
trackNodes.add(*parg) ;
RooArgSet* pdf_nset = findPdfNSet((RooAbsPdf&)(*parg)) ;
if (pdf_nset) {
if (string("nset")==pdf_nset->GetName() && pdf_nset->getSize()>0) {
RooNameSet n(*pdf_nset) ;
parg->setStringAttribute("CATNormSet",n.content()) ;
}
if (string("cset")==pdf_nset->GetName()) {
RooNameSet c(*pdf_nset) ;
parg->setStringAttribute("CATCondSet",c.content()) ;
}
} else {
coutW(Optimization) << "RooProdPdf::setCacheAndTrackHints(" << GetName() << ") WARNING product pdf does not specify a normalization set for component " << parg->GetName() << endl ;
}
}
}
}
void RooProdPdf::printMetaArgs(ostream& os) const
{
RooFIter niter = _pdfNSetList.fwdIterator() ;
for (int i=0 ; i<_pdfList.getSize() ; i++) {
if (i>0) os << " * " ;
RooArgSet* ncset = (RooArgSet*) niter.next() ;
os << _pdfList.at(i)->GetName() ;
if (ncset->getSize()>0) {
if (string("nset")==ncset->GetName()) {
os << *ncset ;
} else {
os << "|" ;
RooFIter nciter = ncset->fwdIterator() ;
RooAbsArg* arg ;
Bool_t first(kTRUE) ;
while((arg=(RooAbsArg*)nciter.next())) {
if (!first) {
os << "," ;
} else {
first = kFALSE ;
}
os << arg->GetName() ;
}
}
}
}
os << " " ;
}
Bool_t RooProdPdf::redirectServersHook(const RooAbsCollection& , Bool_t , Bool_t nameChange, Bool_t )
{
if (nameChange && _pdfList.find("REMOVAL_DUMMY")) {
cxcoutD(LinkStateMgmt) << "RooProdPdf::redirectServersHook(" << GetName() << "): removing REMOVAL_DUMMY" << endl ;
RooAbsArg* pdfDel = _pdfList.find("REMOVAL_DUMMY") ;
TObject* setDel = _pdfNSetList.At(_pdfList.index("REMOVAL_DUMMY")) ;
_pdfList.remove(*pdfDel) ;
_pdfNSetList.Remove(setDel) ;
_cacheMgr.reset() ;
}
return kFALSE ;
}