Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooAbsCachedPdf.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 RooAbsCachedPdf.cxx
14\class RooAbsCachedPdf
15\ingroup Roofitcore
16
17Abstract base class for p.d.f.s that need or
18want to cache their evaluate() output in a RooHistPdf defined in
19terms of the used observables. This base class manages the creation
20and storage of all RooHistPdf cache p.d.fs and the RooDataHists
21that define their shape. Implementations of RooAbsCachedPdf must
22define member function fillCacheObject() which serves to fill an
23already created RooDataHist with the p.d.fs function values. In
24addition the member functions actualObservables() and
25actualParameters() must be define which report what the actual
26observables to be cached are for a given set of observables passed
27by the user to getVal() and on which parameters need to be tracked
28for changes to trigger a refilling of the cache histogram.
29**/
30
31#include "RooAbsCachedPdf.h"
32#include "RooMsgService.h"
33#include "RooDataHist.h"
34#include "RooHistPdf.h"
37
39
40
41
42////////////////////////////////////////////////////////////////////////////////
43/// Constructor
44
45RooAbsCachedPdf::RooAbsCachedPdf(const char *name, const char *title, int ipOrder) :
46 RooAbsPdf(name,title),
47 _cacheMgr(this,10),
48 _ipOrder(ipOrder)
49 {
50 }
51
52
53
54////////////////////////////////////////////////////////////////////////////////
55/// Copy constructor
56
58 RooAbsPdf(other,name),
59 _cacheMgr(other._cacheMgr,this),
60 _ipOrder(other._ipOrder),
61 _disableCache(other._disableCache)
62 {
63 }
64
65
66////////////////////////////////////////////////////////////////////////////////
67/// Implementation of getVal() overriding default implementation
68/// of RooAbsPdf. Return normalized value stored in cache p.d.f
69/// rather than return value of evaluate() which is undefined
70/// for RooAbsCachedPdf
71
72double RooAbsCachedPdf::getValV(const RooArgSet* nset) const
73{
74 if (_disableCache) {
75 return RooAbsPdf::getValV(nset) ;
76 }
77
78 // Calculate current unnormalized value of object
79 auto * cachedPdf = getCache(nset)->pdf();
80 double value = cachedPdf->getVal(nset) ;
81 _norm = cachedPdf->_norm;
82 return _value = value ;
83}
84
85
86
87////////////////////////////////////////////////////////////////////////////////
88/// Return pointer to RooHistPdf cache pdf for given choice of observables
89
91{
92 PdfCacheElem* cache = getCache(nset) ;
93 return cache ? cache->pdf() : nullptr;
94}
95
96
97////////////////////////////////////////////////////////////////////////////////
98/// Return pointer to RooDataHist cache histogram for given choice of observables
99
101{
102 PdfCacheElem* cache = getCache(nset) ;
103 return cache ? cache->hist() : nullptr;
104}
105
106
107////////////////////////////////////////////////////////////////////////////////
108/// Retrieve cache object associated with given choice of observables. If cache object
109/// does not exist, create and fill and register it on the fly. If recalculate=false
110/// recalculation of cache contents of existing caches that are marked dirty due to
111/// dependent parameter changes is suppressed.
112
114{
115 // Check if this configuration was created becfore
116 int sterileIdx = -1 ;
117 auto cache = static_cast<PdfCacheElem*>(_cacheMgr.getObj(nset,nullptr,&sterileIdx));
118
119 // Check if we have a cache histogram in the global expensive object cache
120 if (cache) {
121 if (cache->paramTracker()->hasChanged(true) && (recalculate || !cache->pdf()->haveUnitNorm()) ) {
122 cxcoutD(Eval) << "RooAbsCachedPdf::getCache(" << GetName() << ") cache " << cache << " pdf "
123 << cache->pdf()->GetName() << " requires recalculation as parameters changed" << std::endl ;
124 fillCacheObject(*cache) ;
125 cache->pdf()->setValueDirty() ;
126 }
127 return cache ;
128 }
129
130 // Create and fill cache
131 cache = createCache(nset) ;
132
133 // Check if we have contents registered already in global expensive object cache
134 auto histTmp = static_cast<RooDataHist const*>(expensiveObjectCache().retrieveObject(cache->hist()->GetName(),RooDataHist::Class(),cache->paramTracker()->parameters()));
135
136 if (histTmp) {
137
138 cache->hist()->reset() ;
139 cache->hist()->add(*histTmp) ;
140
141 } else {
142
143 fillCacheObject(*cache) ;
144
145 auto eoclone = new RooDataHist(*cache->hist()) ;
146 eoclone->removeSelfFromDir() ;
147 expensiveObjectCache().registerObject(GetName(),cache->hist()->GetName(),*eoclone,cache->paramTracker()->parameters()) ;
148
149 }
150
151
152 // Store this cache configuration
153 int code = _cacheMgr.setObj(nset,nullptr,(static_cast<RooAbsCacheElement*>(cache)),nullptr) ;
154
155 coutI(Caching) << "RooAbsCachedPdf::getCache(" << GetName() << ") creating new cache " << cache << " with pdf "
156 << cache->pdf()->GetName() << " for nset " << (nset?*nset:RooArgSet()) << " with code " << code ;
157 if (histTmp) {
158 ccoutI(Caching) << " from preexisting content." ;
159 }
160 ccoutI(Caching) << std::endl ;
161
162 return cache ;
163}
164
165
166
167
168////////////////////////////////////////////////////////////////////////////////
169/// Constructor of cache object which owns RooDataHist cache histogram,
170/// RooHistPdf pdf that represents is shape and RooChangeTracker meta
171/// object that tracks changes in listed dependent parameter of cache.
172
174{
175 // Create cache object itself -- Default implementation is a RooHistPdf
176 std::unique_ptr<RooArgSet> nset2{self.actualObservables(nsetIn?*nsetIn:RooArgSet())};
177
178 RooArgSet orderedObs ;
179 if (nset2) {
180 self.preferredObservableScanOrder(*nset2,orderedObs) ;
181 }
182
183 // Create RooDataHist
184 auto hname = std::string(self.GetName()) + "_" + self.inputBaseName() + "_CACHEHIST"
185 + self.cacheNameSuffix(orderedObs) + self.histNameSuffix().Data();
186 _hist = std::make_unique<RooDataHist>(hname,hname,orderedObs,self.binningName()) ;
187 _hist->removeSelfFromDir() ;
188
189 //RooArgSet* observables= self.getObservables(orderedObs) ;
190 // cout << "orderedObs = " << orderedObs << " observables = " << *observables << std::endl ;
191
192 // Get set of p.d.f. observable corresponding to set of histogram observables
193 RooArgSet pdfObs ;
194 RooArgSet pdfFinalObs ;
195 for(auto const& harg : orderedObs) {
196 RooAbsArg& po = self.pdfObservable(*harg) ;
197 pdfObs.add(po) ;
198 if (po.isFundamental()) {
199 pdfFinalObs.add(po) ;
200 } else {
201 pdfFinalObs.add(*std::unique_ptr<RooArgSet>(po.getVariables()));
202 }
203 }
204
205 // Create RooHistPdf
206 auto pdfname = std::string(self.inputBaseName()) + "_CACHE" + self.cacheNameSuffix(pdfFinalObs);
207 // add a different name when cache is built in case nsetIn is not an empty list
208 if (nsetIn && !nsetIn->empty()) {
209 pdfname += "_NORM";
210 for (auto *arg : *nsetIn)
211 pdfname += std::string("_") + arg->GetName();
212 }
213 _pdf = std::make_unique<RooHistPdf>(pdfname.c_str(),pdfname.c_str(),pdfObs,orderedObs,*_hist,self.getInterpolationOrder()) ;
214 if (nsetIn) {
215 _nset.addClone(*nsetIn) ;
216 }
217
218 // Create pseudo-object that tracks changes in parameter values
219
220 std::unique_ptr<RooArgSet> params{self.actualParameters(pdfFinalObs)};
221 params->remove(pdfFinalObs,true,true) ;
222
223 auto name = std::string(_pdf->GetName()) + "_CACHEPARAMS";
224 _paramTracker = std::make_unique<RooChangeTracker>(name.c_str(),name.c_str(),*params,true) ;
225 _paramTracker->hasChanged(true) ; // clear dirty flag as cache is up-to-date upon creation
226
227 // Introduce formal dependency of RooHistPdf on parameters so that const optimization code
228 // makes the correct decisions
229 _pdf->addServerList(*params) ;
230
231 // Set initial state of cache to dirty
232 _pdf->setValueDirty() ;
233}
234
235
236
237////////////////////////////////////////////////////////////////////////////////
238/// Construct string with unique suffix for cache objects based on
239/// observable names that define cache configuration
240
241std::string RooAbsCachedPdf::cacheNameSuffix(const RooArgSet& nset) const
242{
243 std::string name = "_Obs[";
244 if (!nset.empty()) {
245 bool first(true) ;
246 for(auto const& arg : nset) {
247 if (first) {
248 first=false ;
249 } else {
250 name += ",";
251 }
252 name += arg->GetName();
253 }
254 }
255
256 name += "]";
257 if (const char* payloadUS = payloadUniqueSuffix()) {
258 name += payloadUS;
259 }
260 return name ;
261}
262
263
264
265////////////////////////////////////////////////////////////////////////////////
266/// Change the interpolation order that is used in RooHistPdf cache
267/// representation smoothing the RooDataHist shapes.
268
270{
271 _ipOrder = order ;
272
273 for (int i=0 ; i<_cacheMgr.cacheSize() ; i++) {
274 if (auto cache = static_cast<PdfCacheElem*>(_cacheMgr.getObjByIndex(i))) {
275 cache->pdf()->setInterpolationOrder(order) ;
276 }
277 }
278}
279
280
281
282////////////////////////////////////////////////////////////////////////////////
283/// Returns all RooAbsArg objects contained in the cache element
284
286{
287 RooArgList ret(*_pdf) ;
288 ret.add(*_paramTracker) ;
289 if (_norm) ret.add(*_norm) ;
290 return ret ;
291}
292
293
294////////////////////////////////////////////////////////////////////////////////
295/// Print contents of cache when printing self as part of object tree
296
297void RooAbsCachedPdf::PdfCacheElem::printCompactTreeHook(std::ostream& os, const char* indent, int curElem, int maxElem)
298{
299 if (curElem==0) {
300 os << indent << "--- RooAbsCachedPdf begin cache ---" << std::endl ;
301 }
302
303 os << "[" << curElem << "]" << " Configuration for observables " << _nset << std::endl;
304 auto indent2 = std::string(indent) + "[" + std::to_string(curElem) + "]";
305 _pdf->printCompactTree(os,indent2.c_str()) ;
306 if (_norm) {
307 os << "[" << curElem << "] Norm ";
309 }
310
311 if (curElem==maxElem) {
312 os << indent << "--- RooAbsCachedPdf end cache --- " << std::endl ;
313 }
314}
315
316
317
318////////////////////////////////////////////////////////////////////////////////
319/// Force RooRealIntegral to offer all our actual observable for internal
320/// integration
321
323{
324 return !std::unique_ptr<RooArgSet>{actualObservables(dep)}->empty();
325}
326
327
328
329////////////////////////////////////////////////////////////////////////////////
330/// Advertises internal (analytical) integration capabilities. Call
331/// is forwarded to RooHistPdf cache p.d.f of cache that is used for
332/// given choice of observables
333
334int RooAbsCachedPdf::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, const RooArgSet* normSet, const char* rangeName) const
335{
336 if (allVars.empty()) {
337 return 0 ;
338 }
339
340 PdfCacheElem* cache = getCache(normSet?normSet:&allVars) ;
341 int code = cache->pdf()->getAnalyticalIntegralWN(allVars,analVars,normSet,rangeName) ;
342
343 if (code==0) {
344 return 0 ;
345 }
346
347 RooArgSet* all = new RooArgSet ;
348 RooArgSet* ana = new RooArgSet ;
349 RooArgSet* nrm = new RooArgSet ;
350 all->addClone(allVars) ;
351 ana->addClone(analVars) ;
352 if (normSet) {
353 nrm->addClone(*normSet) ;
354 }
355 std::vector<int> codeList(2);
356 codeList[0] = code ;
357 codeList[1] = cache->pdf()->haveUnitNorm() ? 1 : 0 ;
358 int masterCode = _anaReg.store(codeList,all,ana,nrm)+1 ; // takes ownership of all sets
359
360
361 // Mark all observables as internally integrated
362 if (cache->pdf()->haveUnitNorm()) {
363 analVars.add(allVars,true) ;
364 }
365
366 return masterCode ;
367}
368
369
370
371////////////////////////////////////////////////////////////////////////////////
372/// Implements internal (analytical) integration capabilities. Call
373/// is forwarded to RooHistPdf cache p.d.f of cache that is used for
374/// given choice of observables
375
376double RooAbsCachedPdf::analyticalIntegralWN(int code, const RooArgSet* normSet, const char* rangeName) const
377{
378 if (code==0) {
379 return getVal(normSet) ;
380 }
381
382 RooArgSet *allVars(nullptr);
383 RooArgSet *anaVars(nullptr);
384 RooArgSet *normSet2(nullptr);
385 RooArgSet *dummy(nullptr);
386 const std::vector<int> codeList = _anaReg.retrieve(code-1,allVars,anaVars,normSet2,dummy) ;
387
388 PdfCacheElem* cache = getCache(normSet2?normSet2:anaVars,false) ;
389 double ret = cache->pdf()->analyticalIntegralWN(codeList[0],normSet,rangeName) ;
390
391 if (codeList[1]>0) {
392 RooArgSet factObs(*allVars) ;
393 factObs.remove(*anaVars,true,true) ;
394 for(auto * arg : dynamic_range_cast<RooAbsLValue*>(factObs)) {
395 ret *= arg->volume(rangeName) ;
396 }
397 }
398
399 return ret ;
400}
401
402
404{
406}
407
408
409std::unique_ptr<RooAbsArg>
411{
412 if (normSet.empty()) {
413 return RooAbsPdf::compileForNormSet(normSet, ctx);
414 }
415 std::unique_ptr<RooAbsPdf> pdfClone(static_cast<RooAbsPdf *>(this->Clone()));
416 ctx.compileServers(*pdfClone, {});
417
418 auto newArg = std::make_unique<RooFit::Detail::RooNormalizedPdf>(*pdfClone, normSet);
419
420 // The direct servers are this pdf and the normalization integral, which
421 // don't need to be compiled further.
422 for (RooAbsArg *server : newArg->servers()) {
423 ctx.markAsCompiled(*server);
424 }
425 ctx.markAsCompiled(*newArg);
426 newArg->addOwnedComponents(std::move(pdfClone));
427 return newArg;
428}
#define coutI(a)
#define cxcoutD(a)
#define ccoutI(a)
#define ClassImp(name)
Definition Rtypes.h:382
static void indent(ostringstream &buf, int indent_level)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:110
@ kName
const std::vector< Int_t > & retrieve(Int_t masterCode) const
Retrieve the array of integer codes associated with the given master code.
Int_t store(const std::vector< Int_t > &codeList, RooArgSet *set1=nullptr, RooArgSet *set2=nullptr, RooArgSet *set3=nullptr, RooArgSet *set4=nullptr)
Store given arrays of integer codes, and up to four RooArgSets in the registry (each setX pointer may...
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
RooExpensiveObjectCache & expensiveObjectCache() const
RooFit::OwningPtr< RooArgSet > getVariables(bool stripDisconnected=true) const
Return RooArgSet with all variables (tree leaf nodes of expression tree)
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
Definition RooAbsArg.h:89
virtual bool isFundamental() const
Is this object a fundamental type that can be added to a dataset? Fundamental-type subclasses overrid...
Definition RooAbsArg.h:192
Abstract base class for objects to be stored in RooAbsCache cache manager objects.
RooArgList containedArgs(Action) override
Returns all RooAbsArg objects contained in the cache element.
std::unique_ptr< RooChangeTracker > _paramTracker
PdfCacheElem(const RooAbsCachedPdf &self, const RooArgSet *nset)
Constructor of cache object which owns RooDataHist cache histogram, RooHistPdf pdf that represents is...
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< RooHistPdf > _pdf
std::unique_ptr< RooDataHist > _hist
Abstract base class for p.d.f.s that need or want to cache their evaluate() output in a RooHistPdf de...
Int_t getInterpolationOrder() const
virtual RooAbsArg & pdfObservable(RooAbsArg &histObservable) const
Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &analVars, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Advertises internal (analytical) integration capabilities.
double getValV(const RooArgSet *set=nullptr) const override
Implementation of getVal() overriding default implementation of RooAbsPdf.
virtual PdfCacheElem * createCache(const RooArgSet *nset) const
PdfCacheElem * getCache(const RooArgSet *nset, bool recalculate=true) const
Retrieve cache object associated with given choice of observables.
virtual RooFit::OwningPtr< RooArgSet > actualObservables(const RooArgSet &nset) const =0
RooAICRegistry _anaReg
! Registry for analytical integration codes
virtual TString histNameSuffix() const
virtual const char * binningName() const
bool forceAnalyticalInt(const RooAbsArg &dep) const override
Force RooRealIntegral to offer all our actual observable for internal integration.
virtual const char * inputBaseName() const =0
RooAbsPdf * getCachePdf(const RooArgSet &nset) const
RooDataHist * getCacheHist(const RooArgSet &nset) const
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
bool _disableCache
Flag to run object in passthrough (= non-caching mode)
virtual void fillCacheObject(PdfCacheElem &cache) const =0
RooObjCacheManager _cacheMgr
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Implements internal (analytical) integration capabilities.
Int_t _ipOrder
The cache manager.
virtual const char * payloadUniqueSuffix() const
std::string cacheNameSuffix(const RooArgSet &nset) const
Construct string with unique suffix for cache objects based on observable names that define cache con...
void doEval(RooFit::EvalContext &) const override
Base function for computing multiple values of a RooAbsReal.
void setInterpolationOrder(int order)
Change the interpolation order that is used in RooHistPdf cache representation smoothing the RooDataH...
virtual RooFit::OwningPtr< RooArgSet > actualParameters(const RooArgSet &nset) const =0
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
virtual RooAbsArg * addClone(const RooAbsArg &var, bool silent=false)
Add a clone of the specified argument to list.
Abstract interface for all probability density functions.
Definition RooAbsPdf.h:40
std::unique_ptr< RooAbsArg > compileForNormSet(RooArgSet const &normSet, RooFit::Detail::CompileContext &ctx) const override
double getValV(const RooArgSet *set=nullptr) const override
Return current value, normalized by integrating over the observables in nset.
RooArgSet const * _normSet
Normalization integral (owned by _normMgr)
Definition RooAbsPdf.h:320
RooAbsReal * _norm
Definition RooAbsPdf.h:319
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Analytical integral with normalization (see RooAbsReal::analyticalIntegralWN() for further informatio...
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
virtual Int_t getAnalyticalIntegralWN(RooArgSet &allVars, RooArgSet &analVars, const RooArgSet *normSet, const char *rangeName=nullptr) const
Variant of getAnalyticalIntegral that is also passed the normalization set that should be applied to ...
double _value
Cache for current value of object.
Definition RooAbsReal.h:533
virtual void preferredObservableScanOrder(const RooArgSet &obs, RooArgSet &orderedObs) const
Interface method for function objects to indicate their preferred order of observables for scanning t...
virtual void doEval(RooFit::EvalContext &) const
Base function for computing multiple values of a RooAbsReal.
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.
Int_t cacheSize() const
Return size of cache.
T * getObjByIndex(Int_t index) const
Retrieve payload object by slot index.
T * getObj(const RooArgSet *nset, Int_t *sterileIndex=nullptr, const TNamed *isetRangeName=nullptr)
Getter function without integration set.
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
static TClass * Class()
void reset() override
Reset all bin weights to zero.
bool registerObject(const char *ownerName, const char *objectName, TObject &cacheObject, const RooArgSet &params)
Register object associated with given name and given associated parameters with given values in cache...
const TObject * retrieveObject(const char *name, TClass *tclass, const RooArgSet &params)
Retrieve object from cache that was registered under given name with given parameters,...
void markAsCompiled(RooAbsArg &arg) const
void compileServers(RooAbsArg &arg, RooArgSet const &normSet)
bool haveUnitNorm() const
Definition RooHistPdf.h:82
virtual void printStream(std::ostream &os, Int_t contents, StyleOption style, TString indent="") const
Print description of object on ostream, printing contents set by contents integer,...
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * Data() const
Definition TString.h:376