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
57 RooAbsPdf(other,name),
58 _cacheMgr(other._cacheMgr,this),
59 _ipOrder(other._ipOrder),
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
160 RooArgSet orderedObs ;
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
175 RooArgSet pdfObs ;
176 RooArgSet pdfFinalObs ;
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) {
197 _nset.addClone(*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
274
275
276////////////////////////////////////////////////////////////////////////////////
277/// Print contents of cache when printing self as part of object tree
278
279void RooAbsCachedPdf::PdfCacheElem::printCompactTreeHook(std::ostream& os, const char* indent, int curElem, int maxElem)
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 ";
290 _norm->printStream(os,kName|kArgs,kSingleLine) ;
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
316int RooAbsCachedPdf::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, const RooArgSet* normSet, const char* rangeName) const
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
377 // Mirror getAnalyticalIntegralWN's lookup key. If the caller passed a null
378 // normSet to getAnalyticalIntegralWN, the stored normSet2 is non-null but
379 // empty; use anaVars (content-equivalent to the original allVars) instead,
380 // so that analyticalIntegralWN and getAnalyticalIntegralWN both key the
381 // _cacheMgr lookup on the same content and hit the same slot.
382 const RooArgSet *cacheNset = (normSet2 && !normSet2->empty()) ? normSet2 : anaVars;
383 PdfCacheElem *cache = getCache(cacheNset, false);
384 double ret = cache->pdf()->analyticalIntegralWN(codeList[0],normSet,rangeName) ;
385
386 if (codeList[1]>0) {
387 RooArgSet factObs(*allVars) ;
388 factObs.remove(*anaVars,true,true) ;
389 for(auto * arg : dynamic_range_cast<RooAbsLValue*>(factObs)) {
390 ret *= arg->volume(rangeName) ;
391 }
392 }
393
394 return ret ;
395}
396
397
403
404
405std::unique_ptr<RooAbsArg>
407{
408 if (normSet.empty()) {
409 return RooAbsPdf::compileForNormSet(normSet, ctx);
410 }
411 std::unique_ptr<RooAbsPdf> pdfClone(static_cast<RooAbsPdf *>(this->Clone()));
412 ctx.compileServers(*pdfClone, {});
413
414 // Pin a stable normalization set on the clone so that doEval() and the
415 // analytical integration path triggered inside RooNormalizedPdf below hit
416 // the same _cacheMgr slot. Otherwise the analytical-integral path keys the
417 // slot on its own (local) integration variable set while doEval keys it on
418 // the unset (null) _normSet of the clone, and the heavy cache content is
419 // rebuilt on the first Evaluator step of every fit.
420 auto *cachedClone = static_cast<RooAbsCachedPdf *>(pdfClone.get());
421 cachedClone->_compiledNormSet.removeAll();
422 cachedClone->_compiledNormSet.add(normSet);
423 cachedClone->_hasCompiledNormSet = true;
424
425 auto newArg = std::make_unique<RooFit::Detail::RooNormalizedPdf>(*pdfClone, normSet);
426
427 // The direct servers are the cloned pdf (already compiled above) and the
428 // freshly-built normalization integral. Neither needs further compilation.
429 ctx.markSubtreeAsCompiled(*newArg);
430 newArg->addOwnedComponents(std::move(pdfClone));
431 return newArg;
432}
ROOT::RRangeCast< T, true, Range_t > dynamic_range_cast(Range_t &&coll)
#define coutI(a)
#define cxcoutD(a)
#define coutE(a)
#define ccoutI(a)
char * ret
Definition Rotated.cxx:221
static void indent(ostringstream &buf, int indent_level)
char name[80]
Definition TGX11.cxx:148
@ kName
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:88
virtual bool isFundamental() const
Is this object a fundamental type that can be added to a dataset?
Definition RooAbsArg.h:175
RooAbsArg()
Default constructor.
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...
std::unique_ptr< RooAbsReal > _norm
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
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 _hasCompiledNormSet
! whether _compiledNormSet has been populated
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
! 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...
RooArgSet _compiledNormSet
Pinned at compileForNormSet() time on the cloned cache pdf, so that doEval() looks up the same _cache...
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.
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...
RooAbsPdf()
Default constructor.
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 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
Container class to hold N-dimensional binned data.
Definition RooDataHist.h:40
void compileServers(RooAbsArg &arg, RooArgSet const &normSet)
void markSubtreeAsCompiled(RooAbsArg &arg) const
Mark arg and every branch node reachable through its server tree as already compiled.
bool haveUnitNorm() const
Definition RooHistPdf.h:82
const char * GetName() const override
Returns name of object.
Definition TNamed.h:49
const char * Data() const
Definition TString.h:384