/***************************************************************************** * Project: RooFit * * * * Copyright (c) 2000-2005, Regents of the University of California * * and Stanford University. All rights reserved. * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ ////////////////////////////////////////////////////////////////////////////// // // BEGIN_HTML // Class RooProjectedPdf is a RooAbsPdf implementation that represent a projection // of a given input p.d.f and the object returned by RooAbsPdf::createProjection. //

// The actual projection integral for it value and normalization are // calculated on the fly in getVal() once the normalization observables are known. // Class RooProjectedPdf can cache projected p.d.f.s for multiple normalization // observables simultaneously. //

// The createProjection() method of RooProjectedPdf is overloaded and will // return a new RooProjectedPdf that performs the projection of itself // and the requested additional projections in one integration step // The performance of

f->createProjection(x)->createProjection(y)
// is therefore identical to that of
f->createProjection(RooArgSet(x,y))
// END_HTML // #include "Riostream.h" #include "RooFit.h" #include "RooProjectedPdf.h" #include "RooMsgService.h" #include "RooAbsReal.h" #include "RooRealVar.h" #include "RooNameReg.h" using namespace std; ClassImp(RooProjectedPdf) ; //_____________________________________________________________________________ RooProjectedPdf::RooProjectedPdf() : _curNormSet(0) { // Default constructor } //_____________________________________________________________________________ RooProjectedPdf::RooProjectedPdf(const char *name, const char *title, RooAbsReal& _intpdf, const RooArgSet& intObs) : RooAbsPdf(name,title), intpdf("!IntegratedPdf","intpdf",this,_intpdf,kFALSE,kFALSE), intobs("!IntegrationObservables","intobs",this,kFALSE,kFALSE), deps("!Dependents","deps",this,kTRUE,kTRUE), _cacheMgr(this,10) { // Construct projection of input pdf '_intpdf' over observables 'intObs' intobs.add(intObs) ; // Add all other dependens of projected p.d.f. directly RooArgSet* tmpdeps = _intpdf.getParameters(intObs) ; deps.add(*tmpdeps) ; delete tmpdeps ; } //_____________________________________________________________________________ RooProjectedPdf::RooProjectedPdf(const RooProjectedPdf& other, const char* name) : RooAbsPdf(other,name), intpdf("!IntegratedPdf",this,other.intpdf), intobs("!IntegrationObservable",this,other.intobs), deps("!Dependents",this,other.deps), _cacheMgr(other._cacheMgr,this) { // Copy constructor } //_____________________________________________________________________________ Double_t RooProjectedPdf::getValV(const RooArgSet* set) const { // Special version of getVal() overrides RooAbsReal::getValF() to save value of current normalization set _curNormSet = (RooArgSet*)set ; return RooAbsPdf::getValV(set) ; } //_____________________________________________________________________________ Double_t RooProjectedPdf::evaluate() const { // Evaluate projected p.d.f // Calculate current unnormalized value of object int code ; const RooAbsReal* proj = getProjection(&intobs,_curNormSet,0,code) ; return proj->getVal() ; } //_____________________________________________________________________________ const RooAbsReal* RooProjectedPdf::getProjection(const RooArgSet* iset, const RooArgSet* nset, const char* rangeName, int& code) const { // Retrieve object representing projection integral of input p.d.f // over observables iset, while normalizing over observables // nset. The code argument returned by reference is the unique code // defining this particular projection configuration // Check if this configuration was created before Int_t sterileIdx(-1) ; CacheElem* cache = (CacheElem*) _cacheMgr.getObj(iset,nset,&sterileIdx,RooNameReg::ptr(rangeName)) ; if (cache) { code = _cacheMgr.lastIndex() ; return static_cast(cache->_projection); } RooArgSet* nset2 = intpdf.arg().getObservables(*nset) ; if (iset) { nset2->add(*iset) ; } RooAbsReal* proj = intpdf.arg().createIntegral(iset?*iset:RooArgSet(),nset2,0,rangeName) ; delete nset2 ; cache = new CacheElem ; cache->_projection = proj ; code = _cacheMgr.setObj(iset,nset,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName)) ; coutI(Integration) << "RooProjectedPdf::getProjection(" << GetName() << ") creating new projection " << proj->GetName() << " with code " << code << endl ; return proj ; } //_____________________________________________________________________________ RooAbsPdf* RooProjectedPdf::createProjection(const RooArgSet& iset) { // Special version of RooAbsReal::createProjection that deals with // projections of projections. Instead of integrating twice, a new // RooProjectedPdf is returned that is configured to perform the // complete integration in one step RooArgSet combiset(iset) ; combiset.add(intobs) ; return static_cast( const_cast(intpdf.arg()) ).createProjection(combiset) ; } //_____________________________________________________________________________ Bool_t RooProjectedPdf::forceAnalyticalInt(const RooAbsArg& /*dep*/) const { // Force RooRealIntegral to relegate integration of all observables to internal logic return kTRUE ; } //_____________________________________________________________________________ Int_t RooProjectedPdf::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, const RooArgSet* normSet, const char* rangeName) const { // Mark all requested variables as internally integrated analVars.add(allVars) ; // Create the appropriate integral int code ; RooArgSet allVars2(allVars) ; allVars2.add(intobs) ; getProjection(&allVars2,normSet,rangeName,code) ; return code+1 ; } //_____________________________________________________________________________ Double_t RooProjectedPdf::analyticalIntegralWN(Int_t code, const RooArgSet* /*normSet*/, const char* rangeName) const { // Return analytical integral represent by appropriate element of projection cache CacheElem *cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1) ; if (cache) { Double_t ret= cache->_projection->getVal() ; return ret ; } else { RooArgSet* vars = getParameters(RooArgSet()) ; vars->add(intobs) ; RooArgSet* iset = _cacheMgr.nameSet1ByIndex(code-1)->select(*vars) ; RooArgSet* nset = _cacheMgr.nameSet2ByIndex(code-1)->select(*vars) ; Int_t code2(-1) ; const RooAbsReal* proj = getProjection(iset,nset,rangeName,code2) ; delete vars ; delete nset ; delete iset ; Double_t ret = proj->getVal() ; return ret ; } } //_____________________________________________________________________________ Int_t RooProjectedPdf::getGenerator(const RooArgSet& /*directVars*/, RooArgSet& /*generateVars*/, Bool_t /*staticInitOK*/) const { // No internal generator is implemented return 0 ; } //_____________________________________________________________________________ void RooProjectedPdf::generateEvent(Int_t /*code*/) { // No internal generator is implemented return; } //_____________________________________________________________________________ Bool_t RooProjectedPdf::redirectServersHook(const RooAbsCollection& newServerList, Bool_t /*mustReplaceAll*/, Bool_t /*nameChange*/, Bool_t /*isRecursive*/) { // Intercept a server redirection all and update list of dependents if necessary // Specifically update the set proxy 'deps' which introduces the dependency // on server value dirty flags of ourselves // Redetermine explicit list of dependents if intPdf is being replaced RooAbsArg* newPdf = newServerList.find(intpdf.arg().GetName()) ; if (newPdf) { // Determine if set of dependens of new p.d.f is different from old p.d.f. RooArgSet olddeps(deps) ; RooArgSet* newdeps = newPdf->getParameters(intobs) ; RooArgSet* common = (RooArgSet*) newdeps->selectCommon(deps) ; newdeps->remove(*common,kTRUE,kTRUE) ; olddeps.remove(*common,kTRUE,kTRUE) ; // If so, adjust composition of deps Listproxy if (newdeps->getSize()>0) { deps.add(*newdeps) ; } if (olddeps.getSize()>0) { deps.remove(olddeps,kTRUE,kTRUE) ; } delete common ; delete newdeps ; } return kFALSE ; } //_____________________________________________________________________________ RooArgList RooProjectedPdf::CacheElem::containedArgs(Action) { // Return RooAbsArg elements contained in projection cache element. RooArgList ret(*_projection) ; return ret ; } //_____________________________________________________________________________ void RooProjectedPdf::printMetaArgs(ostream& os) const { // Customized printing of arguments of a RooRealIntegral to more intuitively reflect the contents of the // integration operation os << "Int " << intpdf.arg().GetName() ; os << " d" ; os << intobs ; os << " " ; } //_____________________________________________________________________________ void RooProjectedPdf::CacheElem::printCompactTreeHook(ostream& os, const char* indent, Int_t curElem, Int_t maxElem) { // Print contents of cache when printing self as part of object tree if (curElem==0) { os << indent << "RooProjectedPdf begin projection cache" << endl ; } TString indent2(indent) ; indent2 += Form("[%d] ",curElem) ; _projection->printCompactTree(os,indent2) ; if(curElem==maxElem) { os << indent << "RooProjectedPdf end projection cache" << endl ; } }