Revision 716fb731a3c8c9b583235feddac21006994d9626 authored by Kyle Cranmer on 03 August 2011, 22:09:36 UTC, committed by Kyle Cranmer on 03 August 2011, 22:09:36 UTC
git-svn-id: http://root.cern.ch/svn/root/branches/v5-30-00-patches@40446 27541ba8-7e3a-0410-8455-c3a389f83636
1 parent 0db9ccb
RooEffProd.cxx
/*****************************************************************************
* Project: RooFit *
* Package: RooFitCore *
* @(#)root/roofitcore:$Id$
* Authors: *
* WV, Wouter Verkerke, NIKHEF
* GR, Gerhard Raven, NIKHEF/VU *
* *
* 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
// The class RooEffProd implements the product of a PDF with an efficiency function.
// The normalization integral of the product is calculated numerically, but the
// event generation is handled by a specialized generator context that implements
// the event generation in a more efficient for cases where the PDF has an internal
// generator that is smarter than accept reject.
// END_HTML
//
#include "RooFit.h"
#include "RooEffProd.h"
#include "RooEffGenContext.h"
#include "RooNameReg.h"
#include "RooRealVar.h"
ClassImp(RooEffProd)
;
//_____________________________________________________________________________
RooEffProd::RooEffProd(const char *name, const char *title,
RooAbsPdf& inPdf, RooAbsReal& inEff) :
RooAbsPdf(name,title),
_cacheMgr(this,10),
_pdf("pdf","pre-efficiency pdf", this,inPdf),
_eff("eff","efficiency function",this,inEff),
_nset(0),
_fixedNset(0)
{
// Constructor of a a production of p.d.f inPdf with efficiency
// function inEff.
}
//_____________________________________________________________________________
RooEffProd::RooEffProd(const RooEffProd& other, const char* name) :
RooAbsPdf(other, name),
_cacheMgr(other._cacheMgr,this),
_pdf("pdf",this,other._pdf),
_eff("acc",this,other._eff),
_nset(0),
_fixedNset(0)
{
// Copy constructor
}
//_____________________________________________________________________________
RooEffProd::~RooEffProd()
{
// Destructor
}
//_____________________________________________________________________________
Double_t RooEffProd::getVal(const RooArgSet* set) const
{
// Return p.d.f. value normalized over given set of observables
_nset = _fixedNset ? _fixedNset : set ;
return RooAbsPdf::getVal(set) ;
}
//_____________________________________________________________________________
Double_t RooEffProd::evaluate() const
{
// Calculate and return 'raw' unnormalized value of p.d.f
return eff()->getVal() * pdf()->getVal(_nset);
}
//_____________________________________________________________________________
RooAbsGenContext* RooEffProd::genContext(const RooArgSet &vars, const RooDataSet *prototype,
const RooArgSet* auxProto, Bool_t verbose) const
{
// Return specialized generator context for RooEffProds that implements generation
// in a more efficient way than can be done for generic correlated products
assert(pdf()!=0);
assert(eff()!=0);
return new RooEffGenContext(*this,*pdf(),*eff(),vars,prototype,auxProto,verbose) ;
}
//_____________________________________________________________________________
Int_t RooEffProd::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars,
const RooArgSet* normSet, const char* rangeName) const
{
// Return internal integration capabilities of the p.d.f. Given a set 'allVars' for which
// integration is requested, returned the largest subset for which internal (analytical)
// integration is implemented (in argument analVars). The return value is a unique integer
// code that identifies the integration configuration (integrated observables and range name).
//
// This implementation in RooEffProd catches all integrals without normalization and reroutes them
// through a custom integration routine that properly accounts for the use of normalized p.d.f.
// in the evaluate() expression, which breaks the default RooAbsPdf normalization handling
// No special handling required if a normalization set is given
if (normSet && normSet->getSize()>0) {
return 0 ;
}
// No special handling required if running with a fixed normalization set
if (_fixedNset) {
return 0 ;
}
// Special handling of integrals w/o normalization set. We need to pass _a_ normalization set
// to pdf().getVal(nset) in evaluate() because for certain p.d.fs the shape depends on the
// chosen normalization set. This functions correctly automatically for plain getVal() calls,
// however when the (numeric) normalization is calculated, getVal() is called without any normalization
// set causing the normalization to be calculated for a possibly different shape. To fix that
// integrals over a RooEffProd without normalization setup are explicitly handled here. These integrals
// are calculated using a clone of the RooEffProd that has a fixed normalization set passed to the
// underlying p.d.f regardless of the normalization set passed to getVal(). Here the set of observables
// over which is integrated is passed.
// Declare that we can analytically integrate all requested observables
analVars.add(allVars) ;
// Check if cache was previously created
Int_t sterileIndex(-1) ;
CacheElem* cache = (CacheElem*) _cacheMgr.getObj(&allVars,&allVars,&sterileIndex,RooNameReg::ptr(rangeName)) ;
if (cache) {
return _cacheMgr.lastIndex()+1;
}
// Construct cache with clone of p.d.f that has fixed normalization set that is passed to input pdf
cache = new CacheElem ;
cache->_intObs.addClone(allVars) ;
cache->_clone = (RooEffProd*) clone(Form("%s_clone",GetName())) ;
cache->_clone->_fixedNset = &cache->_intObs ;
cache->_int = cache->_clone->createIntegral(cache->_intObs) ;
// Store cache and return index as code
Int_t code = _cacheMgr.setObj(&allVars,&allVars,(RooAbsCacheElement*)cache,RooNameReg::ptr(rangeName)) ;
return code+1 ;
}
//_____________________________________________________________________________
Double_t RooEffProd::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* /*rangeName*/) const
{
// Return value of integral identified by code, which should be a return value of getAnalyticalIntegralWN,
// Code zero is always handled and signifies no integration (return value is normalized p.d.f. value)
// Return analytical integral defined by given scenario code
// No integration scenario
if (code==0) {
return getVal(normSet) ;
}
// Partial integration scenarios
CacheElem* cache = (CacheElem*) _cacheMgr.getObjByIndex(code-1) ;
return cache->_int->getVal() ;
}
//_____________________________________________________________________________
RooArgList RooEffProd::CacheElem::containedArgs(Action)
{
// Report all RooAbsArg derived objects contained in Cache Element (used in function optimization and
// and server redirect management of the cache)
RooArgList ret(_intObs) ;
ret.add(*_int) ;
ret.add(*_clone) ;
return ret ;
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...