Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooAbsCachedReal.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 RooAbsCachedReal.cxx
14 \class RooAbsCachedReal
15 \ingroup Roofitcore
16 
17 RooAbsCachedReal is the abstract base class for functions that need or
18 want to cache their evaluate() output in a RooHistFunc defined in
19 terms of the used observables. This base class manages the creation
20 and storage of all RooHistFunc cache p.d.fs and the RooDataHists
21 that define their shape. Implementations of RooAbsCachedReal must
22 define member function fillCacheObject() which serves to fill an
23 already created RooDataHist with the functions function values. In
24 addition the member functions actualObservables() and
25 actualParameters() must be define which report what the actual
26 observables to be cached are for a given set of observables passed
27 by the user to getVal() and on which parameters need to be tracked
28 for changes to trigger a refilling of the cache histogram.
29 **/
30 
31 #include "Riostream.h"
32 using namespace std ;
33 
34 #include "RooFit.h"
35 #include "TString.h"
36 #include "RooAbsCachedReal.h"
37 #include "RooAbsReal.h"
38 #include "RooMsgService.h"
39 #include "RooDataHist.h"
40 #include "RooHistFunc.h"
41 #include "RooChangeTracker.h"
43 
44 ClassImp(RooAbsCachedReal);
45 
46 
47 
48 ////////////////////////////////////////////////////////////////////////////////
49 /// Constructor
50 
51 RooAbsCachedReal::RooAbsCachedReal(const char *name, const char *title, Int_t ipOrder) :
52  RooAbsReal(name,title),
53  _cacheMgr(this,10),
54  _ipOrder(ipOrder),
55  _disableCache(kFALSE)
56  {
57  }
58 
59 
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Copy constructor
63 
64 RooAbsCachedReal::RooAbsCachedReal(const RooAbsCachedReal& other, const char* name) :
65  RooAbsReal(other,name),
66  _cacheMgr(other._cacheMgr,this),
67  _ipOrder(other._ipOrder),
68  _disableCache(other._disableCache)
69  {
70  }
71 
72 
73 
74 ////////////////////////////////////////////////////////////////////////////////
75 /// Destructor
76 
77 RooAbsCachedReal::~RooAbsCachedReal()
78 {
79 }
80 
81 
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 /// Implementation of getVal() overriding default implementation
85 /// of RooAbsReal. Return value stored in cache p.d.f
86 /// rather than return value of evaluate() which is undefined
87 /// for RooAbsCachedReal
88 
89 Double_t RooAbsCachedReal::getValV(const RooArgSet* nset) const
90 {
91  if (_disableCache) {
92  return RooAbsReal::getValV(nset) ;
93  }
94 
95  // Cannot call cached p.d.f w.o nset
96  // if (!nset) return evaluate() ;
97 
98  // Calculate current unnormalized value of object
99  // coverity[NULL_RETURNS]
100  FuncCacheElem* cache = getCache(nset) ;
101 
102  _value = cache->func()->getVal() ;
103 
104  return _value ;
105 }
106 
107 
108 
109 ////////////////////////////////////////////////////////////////////////////////
110 /// Mark all bins as unitialized (value -1)
111 
112 void RooAbsCachedReal::clearCacheObject(FuncCacheElem& cache) const
113 {
114  cache.hist()->setAllWeights(-1) ;
115 }
116 
117 
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// Interface function to create an internal cache object that represent
121 /// each cached function configuration. This interface allows to create and
122 /// return a class derived from RooAbsCachedReal::FuncCacheElem so that
123 /// a derived class fillCacheObject implementation can utilize extra functionality
124 /// defined in such a derived cache class
125 
126 RooAbsCachedReal::FuncCacheElem* RooAbsCachedReal::createCache(const RooArgSet* nset) const
127 {
128  return new FuncCacheElem(const_cast<RooAbsCachedReal&>(*this),nset) ;
129 }
130 
131 
132 
133 ////////////////////////////////////////////////////////////////////////////////
134 /// Retrieve cache corresponding to observables in nset
135 
136 RooAbsCachedReal::FuncCacheElem* RooAbsCachedReal::getCache(const RooArgSet* nset) const
137 {
138  // Check if this configuration was created becfore
139  Int_t sterileIdx(-1) ;
140  FuncCacheElem* cache = (FuncCacheElem*) _cacheMgr.getObj(nset,0,&sterileIdx) ;
141  if (cache) {
142  if (cache->paramTracker()->hasChanged(kTRUE)) {
143  ccoutD(Eval) << "RooAbsCachedReal::getCache(" << GetName() << ") cached function "
144  << cache->func()->GetName() << " requires recalculation as parameters changed" << endl ;
145  fillCacheObject(*cache) ;
146  cache->func()->setValueDirty() ;
147  }
148  return cache ;
149  }
150 
151  cache = createCache(nset) ;
152 
153  // Set cache function data to ADirty since function will need update every time in cache update process
154  RooFIter iarg( cache->hist()->get()->fwdIterator() );
155  RooAbsArg *arg(0);
156  while ( (arg=iarg.next()) ) {
157  arg->setOperMode(ADirty);
158  }
159 
160  // Check if we have contents registered already in global expensive object cache
161  RooDataHist* htmp = (RooDataHist*) expensiveObjectCache().retrieveObject(cache->hist()->GetName(),RooDataHist::Class(),cache->paramTracker()->parameters()) ;
162 
163  if (htmp) {
164 
165  cache->hist()->reset() ;
166  cache->hist()->add(*htmp) ;
167 
168  } else {
169 
170  fillCacheObject(*cache) ;
171 
172  RooDataHist* eoclone = new RooDataHist(*cache->hist()) ;
173  eoclone->removeSelfFromDir() ;
174  expensiveObjectCache().registerObject(GetName(),cache->hist()->GetName(),*eoclone,cache->paramTracker()->parameters()) ;
175  }
176 
177  // Store this cache configuration
178  Int_t code = _cacheMgr.setObj(nset,0,((RooAbsCacheElement*)cache),0) ;
179  ccoutD(Caching) << "RooAbsCachedReal("<<this<<")::getCache(" << GetName() << ") creating new cache " << cache->func()->GetName() << " for nset " << (nset?*nset:RooArgSet()) << " with code " << code << endl ;
180 
181  return cache ;
182 }
183 
184 
185 
186 ////////////////////////////////////////////////////////////////////////////////
187 /// Constructor of cache storage unit class
188 ///
189 /// Create RooDataHist that will cache function values and create
190 /// RooHistFunc that represent s RooDataHist shape as function, create
191 /// meta object that tracks changes in declared parameters of p.d.f
192 /// through actualParameters()
193 
194 RooAbsCachedReal::FuncCacheElem::FuncCacheElem(const RooAbsCachedReal& self, const RooArgSet* nset)
195 {
196  // Disable source caching by default
197  _cacheSource = kFALSE ;
198  _sourceClone = 0 ;
199 
200  RooArgSet* nset2 = self.actualObservables(nset?*nset:RooArgSet()) ;
201 
202  RooArgSet orderedObs ;
203  self.preferredObservableScanOrder(*nset2,orderedObs) ;
204 
205  // Create RooDataHist
206  TString hname = self.inputBaseName() ;
207  hname.Append("_CACHEHIST") ;
208  hname.Append(self.cacheNameSuffix(*nset2)) ;
209 
210  _hist = new RooDataHist(hname,hname,*nset2,self.binningName()) ;
211  _hist->removeSelfFromDir() ;
212 
213  RooArgSet* observables= self.actualObservables(*nset2) ;
214 
215  // Create RooHistFunc
216  TString funcname = self.inputBaseName() ;
217  funcname.Append("_CACHE") ;
218  funcname.Append(self.cacheNameSuffix(*nset2)) ;
219  _func = new RooHistFunc(funcname,funcname,*observables,*_hist,self.getInterpolationOrder()) ;
220  if (self.operMode()==ADirty) _func->setOperMode(ADirty) ;
221 
222  // Set initial state of cache to dirty
223  _func->setValueDirty() ;
224 
225  // Create pseudo-object that tracks changes in parameter values
226  RooArgSet* params = self.actualParameters(orderedObs) ;
227  string name= Form("%s_CACHEPARAMS",_func->GetName()) ;
228  _paramTracker = new RooChangeTracker(name.c_str(),name.c_str(),*params,kTRUE) ;
229  _paramTracker->hasChanged(kTRUE) ; // clear dirty flag as cache is up-to-date upon creation
230 
231  // Introduce formal dependency of RooHistFunc on parameters so that const optimization code
232  // makes the correct decisions
233  _func->addServerList(*params) ;
234 
235 
236  delete observables ;
237  delete params ;
238  delete nset2 ;
239 
240 }
241 
242 
243 ////////////////////////////////////////////////////////////////////////////////
244 
245 RooAbsCachedReal::FuncCacheElem::~FuncCacheElem()
246 {
247  if (_sourceClone) { delete _sourceClone ; }
248  delete _paramTracker ;
249  delete _func ;
250  delete _hist ;
251 }
252 
253 
254 
255 
256 ////////////////////////////////////////////////////////////////////////////////
257 /// Construct unique suffix name for cache p.d.f object
258 
259 TString RooAbsCachedReal::cacheNameSuffix(const RooArgSet& nset) const
260 {
261  TString name ;
262  name.Append("_Obs[") ;
263  if (nset.getSize()>0) {
264  TIterator* iter = nset.createIterator() ;
265  RooAbsArg* arg ;
266  Bool_t first(kTRUE) ;
267  while((arg=(RooAbsArg*)iter->Next())) {
268  if (first) {
269  first=kFALSE ;
270  } else {
271  name.Append(",") ;
272  }
273  name.Append(arg->GetName()) ;
274  }
275  delete iter ;
276  }
277 
278  name.Append("]") ;
279  const char* payloadUS = payloadUniqueSuffix() ;
280  if (payloadUS) {
281  name.Append(payloadUS) ;
282  }
283  return name ;
284 }
285 
286 
287 
288 ////////////////////////////////////////////////////////////////////////////////
289 /// Set interpolation order of RooHistFunct representing cache histogram
290 
291 void RooAbsCachedReal::setInterpolationOrder(Int_t order)
292 {
293  _ipOrder = order ;
294 
295  for (Int_t i=0 ; i<_cacheMgr.cacheSize() ; i++) {
296  FuncCacheElem* cache = (FuncCacheElem*) _cacheMgr.getObjByIndex(i) ;
297  if (cache) {
298  cache->func()->setInterpolationOrder(order) ;
299  }
300  }
301 }
302 
303 
304 
305 ////////////////////////////////////////////////////////////////////////////////
306 /// Return list of contained RooAbsArg objects
307 
308 RooArgList RooAbsCachedReal::FuncCacheElem::containedArgs(Action)
309 {
310  RooArgList ret(*func()) ;
311 
312  ret.add(*_paramTracker) ;
313  if (_sourceClone) {
314  ret.add(*_sourceClone) ;
315  }
316  return ret ;
317 }
318 
319 
320 ////////////////////////////////////////////////////////////////////////////////
321 /// Print contents of cache when printing self as part of object tree
322 
323 void RooAbsCachedReal::FuncCacheElem::printCompactTreeHook(ostream& os, const char* indent, Int_t curElem, Int_t maxElem)
324 {
325  if (curElem==0) {
326  os << indent << "--- RooAbsCachedReal begin cache ---" << endl ;
327  }
328 
329  TString indent2(indent) ;
330  indent2 += Form("[%d] ",curElem) ;
331  func()->printCompactTree(os,indent2) ;
332 
333  if (curElem==maxElem) {
334  os << indent << "--- RooAbsCachedReal end cache --- " << endl ;
335  }
336 }
337 
338 
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 /// Return analytical integration capabilities of the RooHistFunc that corresponds to the set of observables in allVars
342 
343 Int_t RooAbsCachedReal::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, const RooArgSet* normSet, const char* rangeName) const
344 {
345  FuncCacheElem* cache = getCache(normSet?normSet:&allVars) ;
346  Int_t code = cache->func()->getAnalyticalIntegralWN(allVars,analVars,normSet,rangeName) ;
347  _anaIntMap[code].first = &allVars ;
348  _anaIntMap[code].second = normSet ;
349  return code ;
350 }
351 
352 
353 
354 ////////////////////////////////////////////////////////////////////////////////
355 /// Forward call to implementation in relevant RooHistFunc instance
356 
357 Double_t RooAbsCachedReal::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
358 {
359  if (code==0) {
360  return getVal(normSet) ;
361  }
362 
363  const RooArgSet* anaVars = _anaIntMap[code].first ;
364  const RooArgSet* normSet2 = _anaIntMap[code].second ;
365 
366  FuncCacheElem* cache = getCache(normSet2?normSet2:anaVars) ;
367  return cache->func()->analyticalIntegralWN(code,normSet,rangeName) ;
368 
369 }
370 
371 
372 
373 
374