Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooProjectedPdf.cxx
Go to the documentation of this file.
1 /*****************************************************************************
2 * Project: RooFit *
3 * *
4 * Copyright (c) 2000-2005, Regents of the University of California *
5 * and Stanford University. All rights reserved. *
6 * *
7 * Redistribution and use in source and binary forms, *
8 * with or without modification, are permitted according to the terms *
9 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
10 *****************************************************************************/
11
12/**
13\file RooProjectedPdf.cxx
14\class RooProjectedPdf
15\ingroup Roofitcore
16
17A RooAbsPdf implementation that represent a projection
18of a given input p.d.f and the object returned by RooAbsPdf::createProjection.
19The actual projection integral for it value and normalization are
20calculated on the fly in getVal() once the normalization observables are known.
21Class RooProjectedPdf can cache projected p.d.f.s for multiple normalization
22observables simultaneously.
23The createProjection() method of RooProjectedPdf is overloaded and will
24return a new RooProjectedPdf that performs the projection of itself
25and the requested additional projections in one integration step
26The performance of <pre>f->createProjection(x)->createProjection(y)</pre>
27is therefore identical to that of <pre>f->createProjection(RooArgSet(x,y))</pre>
28**/
29
30#include "Riostream.h"
31
32#include "RooProjectedPdf.h"
33#include "RooMsgService.h"
34#include "RooAbsReal.h"
35#include "RooRealVar.h"
36#include "RooNameReg.h"
37#include "RooRatio.h"
38#include "RooWrapperPdf.h"
39#include "RooFitImplHelpers.h"
40
41 ////////////////////////////////////////////////////////////////////////////////
42 /// Default constructor
43
45
46 ////////////////////////////////////////////////////////////////////////////////
47 /// Construct projection of input pdf '_intpdf' over observables 'intObs'
48
49 RooProjectedPdf::RooProjectedPdf(const char *name, const char *title, RooAbsReal& _intpdf, const RooArgSet& intObs) :
50 RooAbsPdf(name,title),
51 intpdf("!IntegratedPdf","intpdf",this,_intpdf,false,false),
52 intobs("!IntegrationObservables","intobs",this,false,true),
53 deps("!Dependents","deps",this,true,false),
54 _cacheMgr(this,10)
55 {
56 // Since a projected PDF is an integral, we can use the same logic from
57 // RooRealIntegral via the projection integral to figure out what the
58 // servers are. Integration observables will be shape servers, the other
59 // servers are value servers.
60 int code;
61 auto proj = getProjection(&intObs, nullptr, nullptr, code);
62 for(RooAbsArg* server : proj->servers()) {
63 if(server->isShapeServer(*proj)) {
65 } else if(server->isValueServer(*proj)) {
66 deps.add(*server);
67 }
68 }
69 }
70
71
72
73////////////////////////////////////////////////////////////////////////////////
74/// Copy constructor
75
78 intpdf("!IntegratedPdf",this,other.intpdf),
79 intobs("!IntegrationObservables",this,other.intobs),
80 deps("!Dependents",this,other.deps),
81 _cacheMgr(other._cacheMgr,this)
82{
83 }
84
85
86
87////////////////////////////////////////////////////////////////////////////////
88/// Evaluate projected p.d.f
89
91{
92 // Calculate current unnormalized value of object
93 int code ;
94 return getProjection(&intobs, _normSet, normRange(), code)->getVal() ;
95}
96
97
98
99////////////////////////////////////////////////////////////////////////////////
100/// Retrieve object representing projection integral of input p.d.f
101/// over observables iset, while normalizing over observables
102/// nset. The code argument returned by reference is the unique code
103/// defining this particular projection configuration
104
105const RooAbsReal* RooProjectedPdf::getProjection(const RooArgSet* iset, const RooArgSet* nset, const char* rangeName, int& code) const
106{
107
108 // Check if this configuration was created before
109 Int_t sterileIdx(-1) ;
110 if (auto cache = static_cast<CacheElem*>(_cacheMgr.getObj(iset,nset,&sterileIdx,RooNameReg::ptr(rangeName)))) {
111 code = _cacheMgr.lastIndex() ;
112 return static_cast<const RooAbsReal*>(cache->_projection.get());
113 }
114
116 intpdf.arg().getObservables(nset, nset2);
117
118 if (iset) {
119 nset2.add(*iset) ;
120 }
121
122 auto cache = new CacheElem ;
123 cache->_projection = std::unique_ptr<RooAbsReal>{intpdf.arg().createIntegral(iset?*iset:RooArgSet(),&nset2,nullptr,rangeName)};
124
125 code = _cacheMgr.setObj(iset, nset, cache, RooNameReg::ptr(rangeName)) ;
126
127 coutI(Integration) << "RooProjectedPdf::getProjection(" << GetName() << ") creating new projection "
128 << cache->_projection->GetName() << " with code " << code << std::endl;
129
130 return cache->_projection.get();
131}
132
133
134
135////////////////////////////////////////////////////////////////////////////////
136/// Special version of RooAbsReal::createProjection that deals with
137/// projections of projections. Instead of integrating twice, a new
138/// RooProjectedPdf is returned that is configured to perform the
139/// complete integration in one step
140
142{
144 combiset.add(intobs) ;
145 return static_cast<RooAbsPdf&>( const_cast<RooAbsReal&>(intpdf.arg()) ).createProjection(combiset) ;
146}
147
148
149
150////////////////////////////////////////////////////////////////////////////////
151/// Force RooRealIntegral to relegate integration of all observables to internal logic
152
154{
155 return true ;
156}
157
158
159
160////////////////////////////////////////////////////////////////////////////////
161/// Mark all requested variables as internally integrated
162
164{
165 analVars.add(allVars) ;
166
167 // Create the appropriate integral
168 int code ;
169 RooArgSet allVars2(allVars) ;
170 allVars2.add(intobs) ;
172
173 return code+1 ;
174}
175
176
177
178////////////////////////////////////////////////////////////////////////////////
179/// Return analytical integral represent by appropriate element of projection cache
180
181double RooProjectedPdf::analyticalIntegralWN(Int_t code, const RooArgSet* /*normSet*/, const char* rangeName) const
182{
183 if (auto cache = static_cast<CacheElem*>(_cacheMgr.getObjByIndex(code-1))) {
184 return cache->_projection->getVal() ;
185 } else {
186
187 RooArgSet vars;
188 getParameters(nullptr, vars);
189 vars.add(intobs) ;
190 RooArgSet iset = _cacheMgr.selectFromSet1(vars, code-1) ;
191 RooArgSet nset = _cacheMgr.selectFromSet2(vars, code-1) ;
192
193 int code2 = -1 ;
194
195 return getProjection(&iset,&nset,rangeName,code2)->getVal() ;
196 }
197
198}
199
200
201
202////////////////////////////////////////////////////////////////////////////////
203/// Intercept a server redirection all and update list of dependents if necessary
204/// Specifically update the set proxy 'deps' which introduces the dependency
205/// on server value dirty flags of ourselves
206
208 bool nameChange, bool isRecursive)
209{
210 // Redetermine explicit list of dependents if intPdf is being replaced
211 if (RooAbsArg* newPdf = newServerList.find(intpdf.arg().GetName())) {
212
213 // Determine if set of dependents of new p.d.f is different from old p.d.f.
216 newPdf->getParameters(&intobs, newdeps);
218 newdeps.selectCommon(deps, common);
219 newdeps.remove(common,true,true) ;
220 olddeps.remove(common,true,true) ;
221
222 // If so, adjust composition of deps Listproxy
223 if (!newdeps.empty()) {
224 deps.add(newdeps) ;
225 }
226 if (!olddeps.empty()) {
227 deps.remove(olddeps,true,true) ;
228 }
229 }
230
232}
233
234
235
236////////////////////////////////////////////////////////////////////////////////
237/// Return RooAbsArg elements contained in projection cache element.
238
243
244
245
246////////////////////////////////////////////////////////////////////////////////
247/// Customized printing of arguments of a RooRealIntegral to more intuitively reflect the contents of the
248/// integration operation
249
250void RooProjectedPdf::printMetaArgs(std::ostream& os) const
251{
252 os << "Int " << intpdf.arg().GetName() << " d" << intobs << " ";
253}
254
255
256
257
258////////////////////////////////////////////////////////////////////////////////
259/// Print contents of cache when printing self as part of object tree
260
262{
263 if (curElem==0) {
264 os << indent << "RooProjectedPdf begin projection cache" << std::endl ;
265 }
266
268 indent2 += Form("[%d] ",curElem) ;
269
270 _projection->printCompactTree(os,indent2) ;
271
272 if(curElem==maxElem) {
273 os << indent << "RooProjectedPdf end projection cache" << std::endl ;
274 }
275}
276
277
278std::unique_ptr<RooAbsArg>
280{
283 nset2.add(intobs);
284
285 bool forcedAnalyticalInt = false;
286 for (RooAbsArg *obs : intobs) {
288 }
289
290 // If the pdf forces analytical integration, it is usually because it is
291 // expoliting the analytical integration hooks for special integral
292 // semantics (e.g. conditional RooProdPdfs). In these cases, we can't take
293 // the optimized code path below that splits up the projection into
294 // numerator and denominator, as the integral might not factorize like this.
296 auto newArg = std::unique_ptr<RooAbsReal>{intpdf->createIntegral(intobs, &nset2)};
297
298 std::string namePdf = std::string{newArg->GetName()} + "_wrapped_pdf";
299
300 auto newArgPdf = std::make_unique<RooWrapperPdf>(namePdf.c_str(), namePdf.c_str(), *newArg);
301
303 newArgPdf->addOwnedComponents(std::move(newArg));
304
305 return newArgPdf;
306 }
307
308 // Build the projection as an explicit ratio of two integrals instead of a
309 // single RooRealIntegral with a function-normalization set. The latter
310 // would force the integrand to evaluate the *normalized* pdf, hiding the
311 // normalization integral inside RooAbsPdf::_normMgr. That hidden integral
312 // is invisible to the RooFit::Evaluator and is therefore re-run for every
313 // step of the outer integrator during minimization (because the evaluator
314 // sets all its tracked nodes to ADirty). Exposing the normalization as a
315 // sibling node lets the evaluator cache it once per likelihood evaluation.
316 std::unique_ptr<RooAbsReal> numerator{intpdf->createIntegral(intobs)};
317 std::unique_ptr<RooAbsReal> denominator{intpdf->createIntegral(nset2)};
318
319 std::string nameRatio =
320 std::string{numerator->GetName()} + "_Norm[" + RooHelpers::getColonSeparatedNameString(nset2, ',') + "]";
321 auto ratio = std::make_unique<RooRatio>(nameRatio.c_str(), nameRatio.c_str(), *numerator, *denominator);
322
323 std::string namePdf = nameRatio + "_wrapped_pdf";
324 auto newArgPdf = std::make_unique<RooWrapperPdf>(namePdf.c_str(), namePdf.c_str(), *ratio);
325
326 ctx.markAsCompiled(*numerator);
327 ctx.markAsCompiled(*denominator);
328 ctx.markAsCompiled(*ratio);
330
331 newArgPdf->addOwnedComponents(std::move(numerator));
332 newArgPdf->addOwnedComponents(std::move(denominator));
333 newArgPdf->addOwnedComponents(std::move(ratio));
334
335 return newArgPdf;
336}
#define coutI(a)
static void indent(ostringstream &buf, int indent_level)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
char name[80]
Definition TGX11.cxx:145
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2495
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:76
RooFit::OwningPtr< RooArgSet > getParameters(const RooAbsData *data, bool stripDisconnected=true) const
Create a list of leaf nodes in the arg tree starting with ourself as top node that don't match any of...
RooFit::OwningPtr< RooArgSet > getObservables(const RooArgSet &set, bool valueOnly=true) const
Given a set of possible observables, return the observables that this PDF depends on.
Abstract container object that can hold multiple RooAbsArg objects.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:32
RooArgSet const * _normSet
! Normalization set with for above integral
Definition RooAbsPdf.h:314
const char * normRange() const
Definition RooAbsPdf.h:246
bool redirectServersHook(const RooAbsCollection &newServerList, bool mustReplaceAll, bool nameChange, bool isRecursiveStep) override
Hook function intercepting redirectServer calls.
virtual RooAbsPdf * createProjection(const RooArgSet &iset)
Return a p.d.f that represent a projection of this p.d.f integrated over given observables.
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:63
virtual bool forceAnalyticalInt(const RooAbsArg &) const
Definition RooAbsReal.h:170
RooFit::OwningPtr< RooAbsReal > createIntegral(const RooArgSet &iset, const RooCmdArg &arg1, const RooCmdArg &arg2={}, const RooCmdArg &arg3={}, const RooCmdArg &arg4={}, const RooCmdArg &arg5={}, const RooCmdArg &arg6={}, const RooCmdArg &arg7={}, const RooCmdArg &arg8={}) const
Create an object that represents the integral of the function over one or more observables listed in ...
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:24
Int_t setObj(const RooArgSet *nset, T *obj, const TNamed *isetRangeName=nullptr)
Setter function without integration set.
RooArgSet selectFromSet1(RooArgSet const &argSet, int index) const
Create RooArgSet containing the objects that are both in the cached set 1 with a given index and an i...
T * getObjByIndex(Int_t index) const
Retrieve payload object by slot index.
RooArgSet selectFromSet2(RooArgSet const &argSet, int index) const
Create RooArgSet containing the objects that are both in the cached set 2 with a given index and an i...
Int_t lastIndex() const
Return index of slot used in last get or set operation.
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=nullptr, const TNamed *isetRangeName=nullptr)
Getter function without integration set.
bool add(const RooAbsArg &var, bool valueServer, bool shapeServer, bool silent)
Overloaded RooCollection_t::add() method insert object into set and registers object as server to own...
bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false) override
Remove object 'var' from set and deregister 'var' as server to owner.
void markAsCompiled(RooAbsArg &arg) const
static const TNamed * ptr(const char *stringPtr)
Return a unique TNamed pointer for given C++ string.
RooArgList containedArgs(Action) override
Return RooAbsArg elements contained in projection cache element.
void printCompactTreeHook(std::ostream &, const char *, Int_t, Int_t) override
Print contents of cache when printing self as part of object tree.
std::unique_ptr< RooAbsReal > _projection
A RooAbsPdf implementation that represent a projection of a given input p.d.f and the object returned...
RooRealProxy intpdf
p.d.f that is integrated
RooObjCacheManager _cacheMgr
! The cache manager
double evaluate() const override
Evaluate projected p.d.f.
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Return analytical integral represent by appropriate element of projection cache.
bool forceAnalyticalInt(const RooAbsArg &dep) const override
Force RooRealIntegral to relegate integration of all observables to internal logic.
bool redirectServersHook(const RooAbsCollection &newServerList, bool, bool, bool) override
Intercept a server redirection all and update list of dependents if necessary Specifically update the...
RooAbsPdf * createProjection(const RooArgSet &iset) override
Special version of RooAbsReal::createProjection that deals with projections of projections.
void printMetaArgs(std::ostream &os) const override
Customized printing of arguments of a RooRealIntegral to more intuitively reflect the contents of the...
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
RooProjectedPdf()
Default constructor.
const RooAbsReal * 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,...
RooSetProxy intobs
observables that p.d.f is integrated over
RooSetProxy deps
dependents of this p.d.f
Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &analVars, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Mark all requested variables as internally integrated.
const T & arg() const
Return reference to object held in proxy.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
Basic string class.
Definition TString.h:138
std::string getColonSeparatedNameString(RooArgSet const &argSet, char delim=':')