RooAbsCachedPdf.cxx

Go to the documentation of this file.
00001  /***************************************************************************** 
00002   * Project: RooFit                                                           * 
00003   *                                                                           * 
00004   * Copyright (c) 2000-2005, Regents of the University of California          * 
00005   *                          and Stanford University. All rights reserved.    * 
00006   *                                                                           * 
00007   * Redistribution and use in source and binary forms,                        * 
00008   * with or without modification, are permitted according to the terms        * 
00009   * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             * 
00010   *****************************************************************************/ 
00011 
00012 //////////////////////////////////////////////////////////////////////////////
00013 // 
00014 // BEGIN_HTML
00015 // RooAbsCachedPdf is the abstract base class for p.d.f.s that need or
00016 // want to cache their evaluate() output in a RooHistPdf defined in
00017 // terms of the used observables. This base class manages the creation
00018 // and storage of all RooHistPdf cache p.d.fs and the RooDataHists
00019 // that define their shape. Implementations of RooAbsCachedPdf must
00020 // define member function fillCacheObject() which serves to fill an
00021 // already created RooDataHist with the p.d.fs function values. In
00022 // addition the member functions actualObservables() and
00023 // actualParameters() must be define which report what the actual
00024 // observables to be cached are for a given set of observables passed
00025 // by the user to getVal() and on which parameters need to be tracked
00026 // for changes to trigger a refilling of the cache histogram.
00027 // END_HTML
00028 //
00029 //
00030 //
00031 //
00032 
00033 #include "Riostream.h" 
00034 using namespace std ;
00035 
00036 #include "RooFit.h"
00037 #include "TString.h"
00038 #include "RooAbsCachedPdf.h" 
00039 #include "RooAbsReal.h" 
00040 #include "RooMsgService.h"
00041 #include "RooDataHist.h"
00042 #include "RooHistPdf.h"
00043 #include "RooGlobalFunc.h"
00044 #include "RooRealVar.h"
00045 #include "RooChangeTracker.h"
00046 #include "RooExpensiveObjectCache.h"
00047 
00048 ClassImp(RooAbsCachedPdf) 
00049 
00050 
00051 
00052 //_____________________________________________________________________________
00053 RooAbsCachedPdf::RooAbsCachedPdf(const char *name, const char *title, Int_t ipOrder) :
00054   RooAbsPdf(name,title), 
00055   _cacheMgr(this,10),
00056   _ipOrder(ipOrder),
00057   _disableCache(kFALSE)
00058  { 
00059    // Constructor
00060  } 
00061 
00062 
00063 
00064 //_____________________________________________________________________________
00065 RooAbsCachedPdf::RooAbsCachedPdf(const RooAbsCachedPdf& other, const char* name) :  
00066    RooAbsPdf(other,name), 
00067    _cacheMgr(other._cacheMgr,this),
00068    _ipOrder(other._ipOrder),
00069    _disableCache(other._disableCache)
00070  { 
00071    // Copy constructor
00072  } 
00073 
00074 
00075 
00076 //_____________________________________________________________________________
00077 RooAbsCachedPdf::~RooAbsCachedPdf() 
00078 {
00079   // Destructor
00080 }
00081 
00082 
00083 
00084 //_____________________________________________________________________________
00085 Double_t RooAbsCachedPdf::getVal(const RooArgSet* nset) const 
00086 {
00087   // Implementation of getVal() overriding default implementation
00088   // of RooAbsPdf. Return normalized value stored in cache p.d.f
00089   // rather than return value of evaluate() which is undefined
00090   // for RooAbsCachedPdf
00091 
00092   if (_disableCache) {
00093     return RooAbsPdf::getVal(nset) ;
00094   }
00095 
00096   // Calculate current unnormalized value of object
00097   PdfCacheElem* cache = getCache(nset) ;
00098 
00099   Double_t value = cache->pdf()->getVal(nset) ;  
00100 
00101   _value = value ;    
00102   return _value ;
00103 }
00104 
00105 
00106 
00107 //_____________________________________________________________________________
00108 RooAbsPdf* RooAbsCachedPdf::getCachePdf(const RooArgSet* nset) const 
00109 {
00110   // Return pointer to RooHistPdf cache pdf for given choice of observables
00111 
00112   PdfCacheElem* cache = getCache(nset) ;
00113 
00114   if (cache) {
00115     return cache->pdf() ;
00116   } else {
00117     return 0 ;
00118   }
00119 }
00120 
00121 
00122 //_____________________________________________________________________________
00123 RooDataHist* RooAbsCachedPdf::getCacheHist(const RooArgSet* nset) const 
00124 {
00125   // Return pointer to RooDataHist cache histogram for given choice of observables
00126 
00127   PdfCacheElem* cache = getCache(nset) ;
00128 
00129   if (cache) {
00130     return cache->hist() ;
00131   } else {
00132     return 0 ;
00133   }
00134 }
00135 
00136 
00137 //_____________________________________________________________________________
00138 void RooAbsCachedPdf::clearCacheObject(PdfCacheElem& cache) const 
00139 {
00140   // Mark all bins of given cache as unitialized (value -1)
00141 
00142   cache.hist()->setAllWeights(-1) ;  
00143 }
00144 
00145 
00146 
00147 //_____________________________________________________________________________
00148 RooAbsCachedPdf::PdfCacheElem* RooAbsCachedPdf::getCache(const RooArgSet* nset, Bool_t recalculate) const
00149 {
00150   // Retrieve cache object associated with given choice of observables. If cache object
00151   // does not exist, create and fill and register it on the fly. If recalculate=false
00152   // recalculation of cache contents of existing caches that are marked dirty due to
00153   // dependent parameter changes is suppressed. 
00154 
00155   // Check if this configuration was created becfore
00156   Int_t sterileIdx(-1) ;
00157   PdfCacheElem* cache = (PdfCacheElem*) _cacheMgr.getObj(nset,0,&sterileIdx,0) ;
00158 
00159   // Check if we have a cache histogram in the global expensive object cache
00160   if (cache) {
00161     if (cache->paramTracker()->hasChanged(kTRUE) && (recalculate || !cache->pdf()->haveUnitNorm()) ) {
00162       cxcoutD(Eval) << "RooAbsCachedPdf::getCache(" << GetName() << ") cache " << cache << " pdf " 
00163                     << cache->pdf()->GetName() << " requires recalculation as parameters changed" << endl ;     
00164       fillCacheObject(*cache) ;  
00165       cache->pdf()->setValueDirty() ;
00166     }
00167     return cache ;
00168   }
00169 
00170   // Create and fill cache
00171   cache = createCache(nset) ; 
00172 
00173   // Check if we have contents registered already in global expensive object cache 
00174   RooDataHist* htmp = (RooDataHist*) expensiveObjectCache().retrieveObject(cache->hist()->GetName(),RooDataHist::Class(),cache->paramTracker()->parameters()) ;
00175 
00176   if (htmp) {    
00177 
00178     cache->hist()->reset() ;
00179     cache->hist()->add(*htmp) ;
00180 
00181   } else {
00182 
00183     fillCacheObject(*cache) ;  
00184 
00185     RooDataHist* eoclone = new RooDataHist(*cache->hist()) ;
00186     eoclone->removeSelfFromDir() ;
00187     expensiveObjectCache().registerObject(GetName(),cache->hist()->GetName(),*eoclone,cache->paramTracker()->parameters()) ;
00188     
00189   } 
00190 
00191   
00192   // Store this cache configuration
00193   Int_t code = _cacheMgr.setObj(nset,0,((RooAbsCacheElement*)cache),0) ;
00194 
00195   coutI(Caching) << "RooAbsCachedPdf::getCache(" << GetName() << ") creating new cache " << cache << " with pdf "
00196                  << cache->pdf()->GetName() << " for nset " << (nset?*nset:RooArgSet()) << " with code " << code ;
00197   if (htmp) {
00198     ccoutI(Caching) << " from preexisting content." ;
00199   }
00200   ccoutI(Caching) << endl ;
00201   
00202   return cache ;
00203 }
00204 
00205 
00206 
00207 
00208 //_____________________________________________________________________________
00209 RooAbsCachedPdf::PdfCacheElem::PdfCacheElem(const RooAbsCachedPdf& self, const RooArgSet* nsetIn) : 
00210   _pdf(0), _paramTracker(0), _hist(0), _norm(0) 
00211 {
00212   // Constructor of cache object which owns RooDataHist cache histogram,
00213   // RooHistPdf pdf that represents is shape and RooChangeTracker meta
00214   // object that tracks changes in listed dependent parameter of cache.
00215 
00216   // Create cache object itself -- Default implementation is a RooHistPdf
00217   RooArgSet* nset2 = self.actualObservables(nsetIn?*nsetIn:RooArgSet()) ;
00218 
00219   RooArgSet orderedObs ;
00220   if (nset2) {
00221     self.preferredObservableScanOrder(*nset2,orderedObs) ;
00222   }
00223 
00224   // Create RooDataHist
00225   TString hname = self.GetName() ;
00226   hname.Append("_") ;
00227   hname.Append(self.inputBaseName()) ;
00228   hname.Append("_CACHEHIST") ;
00229   hname.Append(self.cacheNameSuffix(orderedObs)) ;
00230   hname.Append(self.histNameSuffix()) ;
00231   _hist = new RooDataHist(hname,hname,orderedObs,self.binningName()) ;
00232   _hist->removeSelfFromDir() ;
00233 
00234   //RooArgSet* observables= self.getObservables(orderedObs) ;
00235   // cout << "orderedObs = " << orderedObs << " observables = " << *observables << endl ;
00236 
00237   // Get set of p.d.f. observable corresponding to set of histogram observables
00238   RooArgSet pdfObs ;
00239   RooArgSet pdfFinalObs ;
00240   TIterator* iter = orderedObs.createIterator() ;
00241   RooAbsArg* harg ;
00242   while((harg=(RooAbsArg*)iter->Next())) {
00243     RooAbsArg& po = self.pdfObservable(*harg) ;
00244     pdfObs.add(po) ;
00245     if (po.isFundamental()) {
00246       pdfFinalObs.add(po) ;
00247     } else {      
00248       RooArgSet* tmp = po.getVariables() ;
00249       pdfFinalObs.add(*tmp) ;
00250       delete tmp ;
00251     }
00252   }
00253   delete iter ;
00254 
00255   // Create RooHistPdf
00256   TString pdfname = self.inputBaseName() ;
00257   pdfname.Append("_CACHE") ;
00258   pdfname.Append(self.cacheNameSuffix(pdfFinalObs)) ;
00259   _pdf = new RooHistPdf(pdfname,pdfname,pdfObs,orderedObs,*_hist,self.getInterpolationOrder()) ;
00260   if (nsetIn) {
00261     _nset.addClone(*nsetIn) ;
00262   }
00263 
00264   // Create pseudo-object that tracks changes in parameter values
00265 
00266   RooArgSet* params = self.actualParameters(pdfFinalObs) ;
00267   params->remove(pdfFinalObs,kTRUE,kTRUE) ;
00268   
00269   string name= Form("%s_CACHEPARAMS",_pdf->GetName()) ;
00270   _paramTracker = new RooChangeTracker(name.c_str(),name.c_str(),*params,kTRUE) ;
00271   _paramTracker->hasChanged(kTRUE) ; // clear dirty flag as cache is up-to-date upon creation
00272 
00273   // Introduce formal dependency of RooHistPdf on parameters so that const optimization code
00274   // makes the correct decisions
00275   _pdf->addServerList(*params) ;
00276 
00277   // Set initial state of cache to dirty
00278   _pdf->setValueDirty() ;
00279 
00280   //delete observables ;
00281   delete params ;
00282   delete nset2 ;
00283 
00284 }
00285 
00286 
00287 
00288 //_____________________________________________________________________________
00289 TString RooAbsCachedPdf::cacheNameSuffix(const RooArgSet& nset) const 
00290 {
00291   // Construct string with unique suffix for cache objects based on 
00292   // observable names that define cache configuration
00293 
00294   TString name ;
00295   name.Append("_Obs[") ;
00296   if (nset.getSize()>0) {
00297     TIterator* iter = nset.createIterator() ;
00298     RooAbsArg* arg ;
00299     Bool_t first(kTRUE) ;
00300     while((arg=(RooAbsArg*)iter->Next())) {
00301       if (first) {
00302         first=kFALSE ;
00303       } else {
00304         name.Append(",") ;
00305       }
00306       name.Append(arg->GetName()) ;
00307     }
00308     delete iter ;
00309   } 
00310 
00311   name.Append("]") ;
00312   const char* payloadUS = payloadUniqueSuffix() ;
00313   if (payloadUS) {
00314     name.Append(payloadUS) ;
00315   }
00316   return name ;
00317 }
00318 
00319 
00320 
00321 //_____________________________________________________________________________
00322 void RooAbsCachedPdf::setInterpolationOrder(Int_t order) 
00323 {
00324   // Change the interpolation order that is used in RooHistPdf cache
00325   // representation smoothing the RooDataHist shapes.
00326 
00327   _ipOrder = order ;
00328 
00329   Int_t i ;
00330   for (i=0 ; i<_cacheMgr.cacheSize() ; i++) {
00331     PdfCacheElem* cache = (PdfCacheElem*) _cacheMgr.getObjByIndex(i) ;
00332     if (cache) {
00333       cache->pdf()->setInterpolationOrder(order) ;
00334     }
00335   }
00336 }
00337 
00338 
00339 
00340 //_____________________________________________________________________________
00341 RooArgList RooAbsCachedPdf::PdfCacheElem::containedArgs(Action) 
00342 {
00343   // Returns all RooAbsArg objects contained in the cache element
00344   RooArgList ret(*_pdf) ;
00345   ret.add(*_paramTracker) ;
00346   if (_norm) ret.add(*_norm) ;
00347   return ret ;
00348 }
00349 
00350 
00351 
00352 //_____________________________________________________________________________
00353 RooAbsCachedPdf::PdfCacheElem::~PdfCacheElem() 
00354 {
00355   // Cache element destructor
00356 
00357   if (_norm) {
00358     delete _norm ;
00359   }
00360   if (_pdf) {
00361     delete _pdf ;
00362   }
00363   if (_paramTracker) {
00364     delete _paramTracker ;
00365   }
00366   if (_hist) {
00367     delete _hist ;
00368   }
00369 }
00370 
00371 
00372 
00373 //_____________________________________________________________________________
00374 void RooAbsCachedPdf::PdfCacheElem::printCompactTreeHook(ostream& os, const char* indent, Int_t curElem, Int_t maxElem) 
00375 {
00376   // Print contents of cache when printing self as part of object tree
00377 
00378   if (curElem==0) {
00379     os << indent << "--- RooAbsCachedPdf begin cache ---" << endl ;
00380   }
00381 
00382   TString indent2(indent) ;
00383   os << Form("[%d] Configuration for observables ",curElem) << _nset << endl ;
00384   indent2 += Form("[%d] ",curElem) ;
00385   _pdf->printCompactTree(os,indent2) ;
00386   if (_norm) {
00387     os << Form("[%d] Norm ",curElem) ;
00388     _norm->printStream(os,kName|kArgs,kSingleLine) ;
00389   }
00390   
00391   if (curElem==maxElem) {
00392     os << indent << "--- RooAbsCachedPdf end cache --- " << endl ;
00393   }
00394 }
00395 
00396 
00397 
00398 //_____________________________________________________________________________
00399 Bool_t RooAbsCachedPdf::forceAnalyticalInt(const RooAbsArg& dep) const 
00400 {
00401   // Force RooRealIntegral to offer all our actual observable for internal
00402   // integration
00403 
00404   RooArgSet* actObs = actualObservables(dep) ;
00405   Bool_t ret = (actObs->getSize()>0) ;
00406   delete actObs ;
00407   return ret ;
00408 }
00409 
00410 
00411 
00412 //_____________________________________________________________________________
00413 Int_t RooAbsCachedPdf::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, const RooArgSet* normSet, const char* rangeName) const 
00414 {
00415   // Advertises internal (analytical) integration capabilities. Call
00416   // is forwarded to RooHistPdf cache p.d.f of cache that is used for
00417   // given choice of observables
00418 
00419   if (allVars.getSize()==0) {
00420     return 0 ;
00421   }
00422 
00423   PdfCacheElem* cache = getCache(normSet?normSet:&allVars) ;
00424   Int_t code = cache->pdf()->getAnalyticalIntegralWN(allVars,analVars,normSet,rangeName) ;
00425 
00426   if (code==0) {
00427     return 0 ;
00428   }
00429 
00430   RooArgSet* all = new RooArgSet ;
00431   RooArgSet* ana = new RooArgSet ;
00432   RooArgSet* nrm = new RooArgSet ;
00433   all->addClone(allVars) ;
00434   ana->addClone(analVars) ;
00435   if (normSet) {
00436     nrm->addClone(*normSet) ;
00437   }
00438   Int_t codeList[2] ;
00439   codeList[0] = code ;
00440   codeList[1] = cache->pdf()->haveUnitNorm() ? 1 : 0 ;
00441   Int_t masterCode = _anaReg.store(codeList,2,all,ana,nrm)+1 ; // takes ownership of all sets
00442 
00443   
00444   // Mark all observables as internally integrated 
00445   if (cache->pdf()->haveUnitNorm()) {
00446     analVars.add(allVars,kTRUE) ;
00447   }
00448 
00449   return masterCode ;
00450 }
00451 
00452 
00453 
00454 //_____________________________________________________________________________
00455 Double_t RooAbsCachedPdf::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
00456 {  
00457   // Implements internal (analytical) integration capabilities. Call
00458   // is forwarded to RooHistPdf cache p.d.f of cache that is used for
00459   // given choice of observables
00460 
00461   if (code==0) {
00462     return getVal(normSet) ; 
00463   }  
00464 
00465   RooArgSet *allVars(0),*anaVars(0),*normSet2(0),*dummy(0) ;
00466   const Int_t* codeList = _anaReg.retrieve(code-1,allVars,anaVars,normSet2,dummy) ;
00467 
00468 
00469   
00470   PdfCacheElem* cache = getCache(normSet2?normSet2:anaVars,kFALSE) ;
00471   Double_t ret = cache->pdf()->analyticalIntegralWN(codeList[0],normSet,rangeName) ;
00472 
00473   if (codeList[1]>0) {
00474     RooArgSet factObs(*allVars) ;
00475     factObs.remove(*anaVars,kTRUE,kTRUE) ;
00476     TIterator* iter = factObs.createIterator() ;
00477     RooAbsLValue* arg ;
00478     while((arg=dynamic_cast<RooAbsLValue*>(iter->Next()))) {
00479       ret *= arg->volume(rangeName) ;
00480     }
00481     delete iter ;
00482   }
00483   
00484   return ret ;
00485 }
00486 
00487 
00488 
00489 
00490 

Generated on Tue Jul 5 15:05:19 2011 for ROOT_528-00b_version by  doxygen 1.5.1