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
38
39
40
41////////////////////////////////////////////////////////////////////////////////
42/// Constructor
43
44RooAbsCachedPdf::RooAbsCachedPdf(const char *name, const char *title, int ipOrder) :
45 RooAbsPdf(name,title),
46 _cacheMgr(this,10),
47 _ipOrder(ipOrder)
48 {
49 }
50
51
52
53////////////////////////////////////////////////////////////////////////////////
54/// Copy constructor
55
58 _cacheMgr(other._cacheMgr,this),
59 _ipOrder(other._ipOrder),
60 _disableCache(other._disableCache)
61 {
62 }
63
64
65////////////////////////////////////////////////////////////////////////////////
66/// Implementation of getVal() overriding default implementation
67/// of RooAbsPdf. Return normalized value stored in cache p.d.f
68/// rather than return value of evaluate() which is undefined
69/// for RooAbsCachedPdf
70
71double RooAbsCachedPdf::getValV(const RooArgSet* nset) const
72{
73 if (_disableCache) {
74 return RooAbsPdf::getValV(nset) ;
75 }
76
77 // Calculate current unnormalized value of object
78 auto * cachedPdf = getCache(nset)->pdf();
79 double value = cachedPdf->getVal(nset) ;
80 _norm = cachedPdf->_norm;
81 return _value = value ;
82}
83
84
85
86////////////////////////////////////////////////////////////////////////////////
87/// Return pointer to RooHistPdf cache pdf for given choice of observables
88
90{
91 PdfCacheElem* cache = getCache(nset) ;
92 return cache ? cache->pdf() : nullptr;
93}
94
95
96////////////////////////////////////////////////////////////////////////////////
97/// Return pointer to RooDataHist cache histogram for given choice of observables
98
100{
101 PdfCacheElem* cache = getCache(nset) ;
102 return cache ? cache->hist() : nullptr;
103}
104
105
106////////////////////////////////////////////////////////////////////////////////
107/// Retrieve cache object associated with given choice of observables. If cache object
108/// does not exist, create and fill and register it on the fly. If recalculate=false
109/// recalculation of cache contents of existing caches that are marked dirty due to
110/// dependent parameter changes is suppressed.
111
113{
114 // Check if this configuration was created becfore
115 int sterileIdx = -1 ;
116 auto cache = static_cast<PdfCacheElem*>(_cacheMgr.getObj(nset,nullptr,&sterileIdx));
117
118 // Check if we have a cache histogram in the global expensive object cache
119 if (cache) {
120 if (cache->paramTracker()->hasChanged(true) && (recalculate || !cache->pdf()->haveUnitNorm()) ) {
121 cxcoutD(Eval) << "RooAbsCachedPdf::getCache(" << GetName() << ") cache " << cache << " pdf "
122 << cache->pdf()->GetName() << " requires recalculation as parameters changed" << std::endl ;
123 fillCacheObject(*cache) ;
124 cache->pdf()->setValueDirty() ;
125 }
126 return cache ;
127 }
128
129 // Create and fill cache
130 cache = createCache(nset) ;
131
132 fillCacheObject(*cache) ;
133
134 auto eoclone = new RooDataHist(*cache->hist()) ;
135 eoclone->removeSelfFromDir() ;
136
137 // Store this cache configuration
138 int code = _cacheMgr.setObj(nset,nullptr,(static_cast<RooAbsCacheElement*>(cache)),nullptr) ;
139
140 coutI(Caching) << "RooAbsCachedPdf::getCache(" << GetName() << ") creating new cache " << cache << " with pdf "
141 << cache->pdf()->GetName() << " for nset " << (nset?*nset:RooArgSet()) << " with code " << code ;
142 ccoutI(Caching) << std::endl ;
143
144 return cache ;
145}
146
147
148
149
150////////////////////////////////////////////////////////////////////////////////
151/// Constructor of cache object which owns RooDataHist cache histogram,
152/// RooHistPdf pdf that represents is shape and RooChangeTracker meta
153/// object that tracks changes in listed dependent parameter of cache.
154
156{
157 // Create cache object itself -- Default implementation is a RooHistPdf
158 std::unique_ptr<RooArgSet> nset2{self.actualObservables(nsetIn?*nsetIn:RooArgSet())};
159
161 if (nset2) {
162 self.preferredObservableScanOrder(*nset2,orderedObs) ;
163 }
164
165 // Create RooDataHist
166 auto hname = std::string(self.GetName()) + "_" + self.inputBaseName() + "_CACHEHIST"
167 + self.cacheNameSuffix(orderedObs) + self.histNameSuffix().Data();
168 _hist = std::make_unique<RooDataHist>(hname,hname,orderedObs,self.binningName()) ;
169 _hist->removeSelfFromDir() ;
170
171 //RooArgSet* observables= self.getObservables(orderedObs) ;
172 // std::cout << "orderedObs = " << orderedObs << " observables = " << *observables << std::endl ;
173
174 // Get set of p.d.f. observable corresponding to set of histogram observables
177 for(auto const& harg : orderedObs) {
178 RooAbsArg& po = self.pdfObservable(*harg) ;
179 pdfObs.add(po) ;
180 if (po.isFundamental()) {
181 pdfFinalObs.add(po) ;
182 } else {
183 pdfFinalObs.add(*std::unique_ptr<RooArgSet>(po.getVariables()));
184 }
185 }
186
187 // Create RooHistPdf
188 auto pdfname = std::string(self.inputBaseName()) + "_CACHE" + self.cacheNameSuffix(pdfFinalObs);
189 // add a different name when cache is built in case nsetIn is not an empty list
190 if (nsetIn && !nsetIn->empty()) {
191 pdfname += "_NORM";
192 for (auto *arg : *nsetIn)
193 pdfname += std::string("_") + arg->GetName();
194 }
195 _pdf = std::make_unique<RooHistPdf>(pdfname.c_str(),pdfname.c_str(),pdfObs,orderedObs,*_hist,self.getInterpolationOrder()) ;
196 if (nsetIn) {
198 }
199
200 // Create pseudo-object that tracks changes in parameter values
201
202 std::unique_ptr<RooArgSet> params{self.actualParameters(pdfFinalObs)};
203 params->remove(pdfFinalObs,true,true) ;
204
205 auto name = std::string(_pdf->GetName()) + "_CACHEPARAMS";
206 _paramTracker = std::make_unique<RooChangeTracker>(name.c_str(),name.c_str(),*params,true) ;
207 _paramTracker->hasChanged(true) ; // clear dirty flag as cache is up-to-date upon creation
208
209 // Introduce formal dependency of RooHistPdf on parameters so that const optimization code
210 // makes the correct decisions
211 _pdf->addServerList(*params) ;
212
213 // Set initial state of cache to dirty
214 _pdf->setValueDirty() ;
215}
216
217
218
219////////////////////////////////////////////////////////////////////////////////
220/// Construct string with unique suffix for cache objects based on
221/// observable names that define cache configuration
222
223std::string RooAbsCachedPdf::cacheNameSuffix(const RooArgSet& nset) const
224{
225 std::string name = "_Obs[";
226 if (!nset.empty()) {
227 bool first(true) ;
228 for(auto const& arg : nset) {
229 if (first) {
230 first=false ;
231 } else {
232 name += ",";
233 }
234 name += arg->GetName();
235 }
236 }
237
238 name += "]";
239 if (const char* payloadUS = payloadUniqueSuffix()) {
240 name += payloadUS;
241 }
242 return name ;
243}
244
245
246
247////////////////////////////////////////////////////////////////////////////////
248/// Change the interpolation order that is used in RooHistPdf cache
249/// representation smoothing the RooDataHist shapes.
250
252{
253 _ipOrder = order ;
254
255 for (int i=0 ; i<_cacheMgr.cacheSize() ; i++) {
256 if (auto cache = static_cast<PdfCacheElem*>(_cacheMgr.getObjByIndex(i))) {
257 cache->pdf()->setInterpolationOrder(order) ;
258 }
259 }
260}
261
262
263
264////////////////////////////////////////////////////////////////////////////////
265/// Returns all RooAbsArg objects contained in the cache element
266
268{
269 RooArgList ret(*_pdf) ;
270 ret.add(*_paramTracker) ;
271 if (_norm) ret.add(*_norm) ;
272 return ret ;
273}
274
275
276////////////////////////////////////////////////////////////////////////////////
277/// Print contents of cache when printing self as part of object tree
278
280{
281 if (curElem==0) {
282 os << indent << "--- RooAbsCachedPdf begin cache ---" << std::endl ;
283 }
284
285 os << "[" << curElem << "]" << " Configuration for observables " << _nset << std::endl;
286 auto indent2 = std::string(indent) + "[" + std::to_string(curElem) + "]";
287 _pdf->printCompactTree(os,indent2.c_str()) ;
288 if (_norm) {
289 os << "[" << curElem << "] Norm ";
291 }
292
293 if (curElem==maxElem) {
294 os << indent << "--- RooAbsCachedPdf end cache --- " << std::endl ;
295 }
296}
297
298
299
300////////////////////////////////////////////////////////////////////////////////
301/// Force RooRealIntegral to offer all our actual observable for internal
302/// integration
303
305{
306 return !std::unique_ptr<RooArgSet>{actualObservables(dep)}->empty();
307}
308
309
310
311////////////////////////////////////////////////////////////////////////////////
312/// Advertises internal (analytical) integration capabilities. Call
313/// is forwarded to RooHistPdf cache p.d.f of cache that is used for
314/// given choice of observables
315
317{
318 if (allVars.empty()) {
319 return 0 ;
320 }
321
322 PdfCacheElem* cache = getCache(normSet?normSet:&allVars) ;
323 int code = cache->pdf()->getAnalyticalIntegralWN(allVars,analVars,normSet,rangeName) ;
324
325 if (code==0) {
326 return 0 ;
327 }
328
329 RooArgSet* all = new RooArgSet ;
330 RooArgSet* ana = new RooArgSet ;
331 RooArgSet* nrm = new RooArgSet ;
332 all->addClone(allVars) ;
333 ana->addClone(analVars) ;
334 if (normSet) {
335 nrm->addClone(*normSet) ;
336 }
337 std::vector<int> codeList(2);
338 codeList[0] = code ;
339 codeList[1] = cache->pdf()->haveUnitNorm() ? 1 : 0 ;
340 int masterCode = _anaReg.store(codeList,all,ana,nrm)+1 ; // takes ownership of all sets
341
342
343 // Mark all observables as internally integrated
344 if (cache->pdf()->haveUnitNorm()) {
345 analVars.add(allVars,true) ;
346 }
347
348 return masterCode ;
349}
350
351
352
353////////////////////////////////////////////////////////////////////////////////
354/// Implements internal (analytical) integration capabilities. Call
355/// is forwarded to RooHistPdf cache p.d.f of cache that is used for
356/// given choice of observables
357
358double RooAbsCachedPdf::analyticalIntegralWN(int code, const RooArgSet* normSet, const char* rangeName) const
359{
360 if (code==0) {
361 return getVal(normSet) ;
362 }
363 if (code < 0 || (code-1) >= static_cast<int>(_anaReg.size())) {
364 coutE(Integration) << "RooAbsCachedPdf::analyticalIntegralWN(" << GetName()
365 << "): analytical integration registry is empty for code: " << code << "."
366 << " RooWorkspace is not prepared to store integrals to functions when these inherit from RooAbsCachedPdf."
367 << std::endl;
368 return 0.;
369 }
370
371 RooArgSet *allVars(nullptr);
372 RooArgSet *anaVars(nullptr);
373 RooArgSet *normSet2(nullptr);
374 RooArgSet *dummy(nullptr);
375 const std::vector<int> codeList = _anaReg.retrieve(code-1,allVars,anaVars,normSet2,dummy) ;
376
378 double ret = cache->pdf()->analyticalIntegralWN(codeList[0],normSet,rangeName) ;
379
380 if (codeList[1]>0) {
381 RooArgSet factObs(*allVars) ;
382 factObs.remove(*anaVars,true,true) ;
383 for(auto * arg : dynamic_range_cast<RooAbsLValue*>(factObs)) {
384 ret *= arg->volume(rangeName) ;
385 }
386 }
387
388 return ret ;
389}
390
391
396
397
398std::unique_ptr<RooAbsArg>
400{
401 if (normSet.empty()) {
403 }
404 std::unique_ptr<RooAbsPdf> pdfClone(static_cast<RooAbsPdf *>(this->Clone()));
405 ctx.compileServers(*pdfClone, {});
406
407 auto newArg = std::make_unique<RooFit::Detail::RooNormalizedPdf>(*pdfClone, normSet);
408
409 // The direct servers are this pdf and the normalization integral, which
410 // don't need to be compiled further.
411 for (RooAbsArg *server : newArg->servers()) {
413 }
415 newArg->addOwnedComponents(std::move(pdfClone));
416 return newArg;
417}
#define coutI(a)
#define cxcoutD(a)
#define coutE(a)
#define ccoutI(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.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:148
@ kName
const std::vector< Int_t > & retrieve(Int_t masterCode) const
Retrieve the array of integer codes associated with the given master code.
size_t size() const
Get size of _clArr vector.
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:76
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
Definition RooAbsArg.h:88
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 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
bool forceAnalyticalInt(const RooAbsArg &dep) const override
Force RooRealIntegral to offer all our actual observable for internal integration.
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
! The cache manager
double analyticalIntegralWN(Int_t code, const RooArgSet *normSet, const char *rangeName=nullptr) const override
Implements internal (analytical) integration capabilities.
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 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:32
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 set with for above integral
Definition RooAbsPdf.h:314
RooAbsReal * _norm
! Normalization integral (owned by _normMgr)
Definition RooAbsPdf.h:313
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:107
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:539
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
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:49