RooRealSumPdf.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooRealSumPdf.cxx 38078 2011-02-15 18:28:29Z cranmer $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 //
00019 // Class RooRealSumPdf implements a PDF constructed from a sum of
00020 // functions:
00021 //
00022 //                 Sum(i=1,n-1) coef_i * func_i(x) + [ 1 - (Sum(i=1,n-1) coef_i ] * func_n(x)
00023 //   pdf(x) =    ------------------------------------------------------------------------------
00024 //             Sum(i=1,n-1) coef_i * Int(func_i)dx + [ 1 - (Sum(i=1,n-1) coef_i ] * Int(func_n)dx
00025 //
00026 //
00027 // where coef_i and func_i are RooAbsReal objects, and x is the collection of dependents. 
00028 // In the present version coef_i may not depend on x, but this limitation may be removed in the future
00029 //
00030 
00031 #include "RooFit.h"
00032 #include "Riostream.h"
00033 
00034 #include "TIterator.h"
00035 #include "TList.h"
00036 #include "RooRealSumPdf.h"
00037 #include "RooRealProxy.h"
00038 #include "RooPlot.h"
00039 #include "RooRealVar.h"
00040 #include "RooAddGenContext.h"
00041 #include "RooRealConstant.h"
00042 #include "RooRealIntegral.h"
00043 #include "RooMsgService.h"
00044 
00045 
00046 
00047 ClassImp(RooRealSumPdf)
00048 ;
00049 
00050 
00051 //_____________________________________________________________________________
00052 RooRealSumPdf::RooRealSumPdf() 
00053 {
00054   // Default constructor
00055   // coverity[UNINIT_CTOR]
00056   _funcIter  = _funcList.createIterator() ;
00057   _coefIter  = _coefList.createIterator() ;
00058   _extended = kFALSE ;
00059 }
00060 
00061 
00062 
00063 //_____________________________________________________________________________
00064 RooRealSumPdf::RooRealSumPdf(const char *name, const char *title) :
00065   RooAbsPdf(name,title), 
00066   _normIntMgr(this,10),
00067   _haveLastCoef(kFALSE),
00068   _funcList("!funcList","List of functions",this),
00069   _coefList("!coefList","List of coefficients",this),
00070   _extended(kFALSE)
00071 {
00072   // Constructor with name and title
00073   _funcIter   = _funcList.createIterator() ;
00074   _coefIter  = _coefList.createIterator() ;
00075 }
00076 
00077 
00078 
00079 //_____________________________________________________________________________
00080 RooRealSumPdf::RooRealSumPdf(const char *name, const char *title,
00081                      RooAbsReal& func1, RooAbsReal& func2, RooAbsReal& coef1) : 
00082   RooAbsPdf(name,title),
00083   _normIntMgr(this,10),
00084   _haveLastCoef(kFALSE),
00085   _funcList("!funcList","List of functions",this),
00086   _coefList("!coefList","List of coefficients",this),
00087   _extended(kFALSE)
00088 {
00089   // Construct p.d.f consisting of coef1*func1 + (1-coef1)*func2
00090   // The input coefficients and functions are allowed to be negative
00091   // but the resulting sum is not, which is enforced at runtime
00092 
00093   // Special constructor with two functions and one coefficient
00094   _funcIter  = _funcList.createIterator() ;
00095   _coefIter = _coefList.createIterator() ;
00096 
00097   _funcList.add(func1) ;  
00098   _funcList.add(func2) ;
00099   _coefList.add(coef1) ;
00100 
00101 }
00102 
00103 
00104 //_____________________________________________________________________________
00105 RooRealSumPdf::RooRealSumPdf(const char *name, const char *title, const RooArgList& inFuncList, const RooArgList& inCoefList, Bool_t extended) :
00106   RooAbsPdf(name,title),
00107   _normIntMgr(this,10),
00108   _haveLastCoef(kFALSE),
00109   _funcList("!funcList","List of functions",this),
00110   _coefList("!coefList","List of coefficients",this),
00111   _extended(extended)
00112 { 
00113   // Constructor p.d.f implementing sum_i [ coef_i * func_i ], if N_coef==N_func
00114   // or sum_i [ coef_i * func_i ] + (1 - sum_i [ coef_i ] )* func_N if Ncoef==N_func-1
00115   // 
00116   // All coefficients and functions are allowed to be negative
00117   // but the sum is not, which is enforced at runtime.
00118 
00119   if (!(inFuncList.getSize()==inCoefList.getSize()+1 || inFuncList.getSize()==inCoefList.getSize())) {
00120     coutE(InputArguments) << "RooRealSumPdf::RooRealSumPdf(" << GetName() 
00121                           << ") number of pdfs and coefficients inconsistent, must have Nfunc=Ncoef or Nfunc=Ncoef+1" << endl ;
00122     assert(0) ;
00123   }
00124 
00125   _funcIter  = _funcList.createIterator() ;
00126   _coefIter = _coefList.createIterator() ;
00127  
00128   // Constructor with N functions and N or N-1 coefs
00129   TIterator* funcIter = inFuncList.createIterator() ;
00130   TIterator* coefIter = inCoefList.createIterator() ;
00131   RooAbsArg* func ;
00132   RooAbsArg* coef ;
00133 
00134   while((coef = (RooAbsArg*)coefIter->Next())) {
00135     func = (RooAbsArg*) funcIter->Next() ;
00136 
00137     if (!dynamic_cast<RooAbsReal*>(coef)) {
00138       coutW(InputArguments) << "RooRealSumPdf::RooRealSumPdf(" << GetName() << ") coefficient " << coef->GetName() << " is not of type RooAbsReal, ignored" << endl ;
00139       continue ;
00140     }
00141     if (!dynamic_cast<RooAbsReal*>(func)) {
00142       coutW(InputArguments) << "RooRealSumPdf::RooRealSumPdf(" << GetName() << ") func " << func->GetName() << " is not of type RooAbsReal, ignored" << endl ;
00143       continue ;
00144     }
00145     _funcList.add(*func) ;
00146     _coefList.add(*coef) ;    
00147   }
00148 
00149   func = (RooAbsReal*) funcIter->Next() ;
00150   if (func) {
00151     if (!dynamic_cast<RooAbsReal*>(func)) {
00152       coutE(InputArguments) << "RooRealSumPdf::RooRealSumPdf(" << GetName() << ") last func " << coef->GetName() << " is not of type RooAbsReal, fatal error" << endl ;
00153       assert(0) ;
00154     }
00155     _funcList.add(*func) ;  
00156   } else {
00157     _haveLastCoef = kTRUE ;
00158   }
00159   
00160   delete funcIter ;
00161   delete coefIter  ;
00162 }
00163 
00164 
00165 
00166 
00167 //_____________________________________________________________________________
00168 RooRealSumPdf::RooRealSumPdf(const RooRealSumPdf& other, const char* name) :
00169   RooAbsPdf(other,name),
00170   _normIntMgr(other._normIntMgr,this),
00171   _haveLastCoef(other._haveLastCoef),
00172   _funcList("!funcList",this,other._funcList),
00173   _coefList("!coefList",this,other._coefList),
00174   _extended(other._extended)
00175 {
00176   // Copy constructor
00177 
00178   _funcIter  = _funcList.createIterator() ;
00179   _coefIter = _coefList.createIterator() ;
00180 }
00181 
00182 
00183 
00184 //_____________________________________________________________________________
00185 RooRealSumPdf::~RooRealSumPdf()
00186 {
00187   // Destructor
00188   delete _funcIter ;
00189   delete _coefIter ;
00190 }
00191 
00192 
00193 
00194 
00195 
00196 //_____________________________________________________________________________
00197 RooAbsPdf::ExtendMode RooRealSumPdf::extendMode() const 
00198 {
00199   return (_extended && (_funcList.getSize()==_coefList.getSize())) ? CanBeExtended : CanNotBeExtended ;
00200 }
00201 
00202 
00203 
00204 
00205 //_____________________________________________________________________________
00206 Double_t RooRealSumPdf::evaluate() const 
00207 {
00208   // Calculate the current value
00209 
00210   Double_t value(0) ;
00211 
00212   // Do running sum of coef/func pairs, calculate lastCoef.
00213   _funcIter->Reset() ;
00214   _coefIter->Reset() ;
00215   RooAbsReal* coef ;
00216   RooAbsReal* func ;
00217       
00218   // N funcs, N-1 coefficients 
00219   Double_t lastCoef(1) ;
00220   while((coef=(RooAbsReal*)_coefIter->Next())) {
00221     func = (RooAbsReal*)_funcIter->Next() ;
00222     Double_t coefVal = coef->getVal() ;
00223     if (coefVal) {
00224       cxcoutD(Eval) << "RooRealSumPdf::eval(" << GetName() << ") coefVal = " << coefVal << " funcVal = " << func->getVal() << endl ;
00225       if (func->isSelectedComp()) {
00226         value += func->getVal()*coefVal ;
00227       }
00228       lastCoef -= coef->getVal() ;
00229     }
00230   }
00231   
00232   if (!_haveLastCoef) {
00233     // Add last func with correct coefficient
00234     func = (RooAbsReal*) _funcIter->Next() ;
00235     if (func->isSelectedComp()) {
00236       value += func->getVal()*lastCoef ;
00237     }
00238 
00239     cxcoutD(Eval) << "RooRealSumPdf::eval(" << GetName() << ") lastCoef = " << lastCoef << " funcVal = " << func->getVal() << endl ;
00240     
00241     // Warn about coefficient degeneration
00242     if (lastCoef<0 || lastCoef>1) {
00243       coutW(Eval) << "RooRealSumPdf::evaluate(" << GetName() 
00244                   << " WARNING: sum of FUNC coefficients not in range [0-1], value=" 
00245                   << 1-lastCoef << endl ;
00246     } 
00247   }
00248 
00249   return value ;
00250 }
00251 
00252 
00253 
00254 
00255 //_____________________________________________________________________________
00256 Bool_t RooRealSumPdf::checkObservables(const RooArgSet* nset) const 
00257 {
00258   // Check if FUNC is valid for given normalization set.
00259   // Coeffient and FUNC must be non-overlapping, but func-coefficient 
00260   // pairs may overlap each other
00261   //
00262   // In the present implementation, coefficients may not be observables or derive
00263   // from observables
00264 
00265   Bool_t ret(kFALSE) ;
00266 
00267   _funcIter->Reset() ;
00268   _coefIter->Reset() ;
00269   RooAbsReal* coef ;
00270   RooAbsReal* func ;
00271   while((coef=(RooAbsReal*)_coefIter->Next())) {
00272     func = (RooAbsReal*)_funcIter->Next() ;
00273     if (func->observableOverlaps(nset,*coef)) {
00274       coutE(InputArguments) << "RooRealSumPdf::checkObservables(" << GetName() << "): ERROR: coefficient " << coef->GetName() 
00275                             << " and FUNC " << func->GetName() << " have one or more observables in common" << endl ;
00276       ret = kTRUE ;
00277     }
00278     if (coef->dependsOn(*nset)) {
00279       coutE(InputArguments) << "RooRealPdf::checkObservables(" << GetName() << "): ERROR coefficient " << coef->GetName() 
00280                             << " depends on one or more of the following observables" ; nset->Print("1") ;
00281       ret = kTRUE ;
00282     }
00283   }
00284   
00285   return ret ;
00286 }
00287 
00288 
00289 
00290 
00291 //_____________________________________________________________________________
00292 Int_t RooRealSumPdf::getAnalyticalIntegralWN(RooArgSet& allVars, RooArgSet& analVars, 
00293                                              const RooArgSet* normSet2, const char* /*rangeName*/) const 
00294 {
00295   // Advertise that all integrals can be handled internally.
00296 
00297   // Handle trivial no-integration scenario
00298   if (allVars.getSize()==0) return 0 ;
00299   if (_forceNumInt) return 0 ;
00300 
00301   // Select subset of allVars that are actual dependents
00302   analVars.add(allVars) ;
00303   RooArgSet* normSet = normSet2 ? getObservables(normSet2) : 0 ;
00304 
00305 
00306   // Check if this configuration was created before
00307   Int_t sterileIdx(-1) ;
00308   CacheElem* cache = (CacheElem*) _normIntMgr.getObj(normSet,&analVars,&sterileIdx,0) ;
00309   if (cache) {
00310     return _normIntMgr.lastIndex()+1 ;
00311   }
00312   
00313   // Create new cache element
00314   cache = new CacheElem ;
00315 
00316   // Make list of function projection and normalization integrals 
00317   _funcIter->Reset() ;
00318   RooAbsReal *func ;
00319   while((func=(RooAbsReal*)_funcIter->Next())) {
00320     RooAbsReal* funcInt = func->createIntegral(analVars) ;
00321     cache->_funcIntList.addOwned(*funcInt) ;
00322     if (normSet && normSet->getSize()>0) {
00323       RooAbsReal* funcNorm = func->createIntegral(*normSet) ;
00324       cache->_funcNormList.addOwned(*funcNorm) ;
00325     }
00326   }
00327 
00328   // Store cache element
00329   Int_t code = _normIntMgr.setObj(normSet,&analVars,(RooAbsCacheElement*)cache,0) ;
00330 
00331   if (normSet) {
00332     delete normSet ;
00333   }
00334 
00335   return code+1 ; 
00336 }
00337 
00338 
00339 
00340 
00341 //_____________________________________________________________________________
00342 Double_t RooRealSumPdf::analyticalIntegralWN(Int_t code, const RooArgSet* normSet2, const char* /*rangeName*/) const 
00343 {
00344   // Implement analytical integrations by deferring integration of component
00345   // functions to integrators of components
00346 
00347   // Handle trivial passthrough scenario
00348   if (code==0) return getVal(normSet2) ;
00349 
00350 
00351   // WVE needs adaptation for rangeName feature
00352   CacheElem* cache = (CacheElem*) _normIntMgr.getObjByIndex(code-1) ;
00353 
00354   TIterator* funcIntIter = cache->_funcIntList.createIterator() ;
00355   _coefIter->Reset() ;
00356   _funcIter->Reset() ;
00357   RooAbsReal *coef(0), *funcInt(0), *func(0) ;
00358   Double_t value(0) ;
00359 
00360   // N funcs, N-1 coefficients 
00361   Double_t lastCoef(1) ;
00362   while((coef=(RooAbsReal*)_coefIter->Next())) {
00363     funcInt = (RooAbsReal*)funcIntIter->Next() ;
00364     func    = (RooAbsReal*)_funcIter->Next() ;
00365     Double_t coefVal = coef->getVal(normSet2) ;
00366     if (coefVal) {
00367       if (func->isSelectedComp()) {
00368         value += funcInt->getVal()*coefVal ;
00369       }
00370       lastCoef -= coef->getVal(normSet2) ;
00371     }
00372   }
00373   
00374   if (!_haveLastCoef) {
00375     // Add last func with correct coefficient
00376     funcInt = (RooAbsReal*) funcIntIter->Next() ;
00377     if (func->isSelectedComp()) {
00378       value += funcInt->getVal()*lastCoef ;
00379     }
00380     
00381     // Warn about coefficient degeneration
00382     if (lastCoef<0 || lastCoef>1) {
00383       coutW(Eval) << "RooRealSumPdf::evaluate(" << GetName() 
00384                   << " WARNING: sum of FUNC coefficients not in range [0-1], value=" 
00385                   << 1-lastCoef << endl ;
00386     } 
00387   }
00388 
00389   delete funcIntIter ;
00390   
00391   Double_t normVal(1) ;
00392   if (normSet2) {
00393     normVal = 0 ;
00394 
00395     // N funcs, N-1 coefficients 
00396     RooAbsReal* funcNorm ;
00397     TIterator* funcNormIter = cache->_funcNormList.createIterator() ;
00398     _coefIter->Reset() ;
00399     while((coef=(RooAbsReal*)_coefIter->Next())) {
00400       funcNorm = (RooAbsReal*)funcNormIter->Next() ;
00401       Double_t coefVal = coef->getVal(normSet2) ;
00402       if (coefVal) {
00403         normVal += funcNorm->getVal()*coefVal ;
00404       }
00405     }
00406     
00407     // Add last func with correct coefficient
00408     if (!_haveLastCoef) {
00409       funcNorm = (RooAbsReal*) funcNormIter->Next() ;
00410       normVal += funcNorm->getVal()*lastCoef ;
00411     }
00412       
00413     delete funcNormIter ;      
00414   }
00415 
00416   return value / normVal;
00417 }
00418 
00419 
00420 //_____________________________________________________________________________
00421 Double_t RooRealSumPdf::expectedEvents(const RooArgSet* nset) const
00422 {
00423  // try something simple
00424  RooArgSet* nset2 = nset? getObservables(*nset) : 0 ;
00425  RooAbsReal* integral = createIntegral(nset2?*nset2:RooArgSet());
00426  delete nset2 ;
00427 
00428  double ret = integral->getVal();
00429  delete integral;
00430 
00431  return ret;
00432 }
00433 
00434 
00435 //_____________________________________________________________________________
00436 void RooRealSumPdf::printMetaArgs(ostream& os) const 
00437 {
00438   // Customized printing of arguments of a RooRealSumPdf to more intuitively reflect the contents of the
00439   // product operator construction
00440 
00441   _funcIter->Reset() ;
00442   _coefIter->Reset() ;
00443 
00444   Bool_t first(kTRUE) ;
00445     
00446   RooAbsArg* coef, *func ;
00447   if (_coefList.getSize()!=0) { 
00448     while((coef=(RooAbsArg*)_coefIter->Next())) {
00449       if (!first) {
00450         os << " + " ;
00451       } else {
00452         first = kFALSE ;
00453       }
00454       func=(RooAbsArg*)_funcIter->Next() ;
00455       os << coef->GetName() << " * " << func->GetName() ;
00456     }
00457     func = (RooAbsArg*) _funcIter->Next() ;
00458     if (func) {
00459       os << " + [%] * " << func->GetName() ;
00460     }
00461   } else {
00462     
00463     while((func=(RooAbsArg*)_funcIter->Next())) {
00464       if (!first) {
00465         os << " + " ;
00466       } else {
00467         first = kFALSE ;
00468       }
00469       os << func->GetName() ; 
00470     }  
00471   }
00472 
00473   os << " " ;    
00474 }

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