RooAbsPdf.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooAbsPdf.cxx 36230 2010-10-09 20:21:02Z wouter $
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 // RooAbsPdf is the abstract interface for all probability density
00020 // functions The class provides hybrid analytical/numerical
00021 // normalization for its implementations, error tracing and a MC
00022 // generator interface.
00023 //
00024 // A minimal implementation of a PDF class derived from RooAbsPdf
00025 // should overload the evaluate() function. This functions should
00026 // return PDFs value.
00027 //
00028 //
00029 // [Normalization/Integration]
00030 //
00031 // Although the normalization of a PDF is an integral part of a
00032 // probability density function, normalization is treated separately
00033 // in RooAbsPdf. The reason is that a RooAbsPdf object is more than a
00034 // PDF: it can be a building block for a more complex, composite PDF
00035 // if any of its variables are functions instead of variables. In
00036 // such cases the normalization of the composite may not be simply the
00037 // integral over the dependents of the top level PDF as these are
00038 // functions with potentially non-trivial Jacobian terms themselves.
00039 // Therefore 
00040 //
00041 // --> No explicit attempt should be made to normalize 
00042 //     the functions output in evaluate(). 
00043 //
00044 // In addition, RooAbsPdf objects do not have a static concept of what
00045 // variables are parameters and what variables are dependents (which
00046 // need to be integrated over for a correct PDF normalization). 
00047 // Instead the choice of normalization is always specified each time a
00048 // normalized values is requested from the PDF via the getVal()
00049 // method.
00050 //
00051 // RooAbsPdf manages the entire normalization logic of each PDF with
00052 // help of a RooRealIntegral object, which coordinates the integration
00053 // of a given choice of normalization. By default, RooRealIntegral will
00054 // perform a fully numeric integration of all dependents. However,
00055 // PDFs can advertise one or more (partial) analytical integrals of
00056 // their function, and these will be used by RooRealIntegral, if it
00057 // determines that this is safe (i.e. no hidden Jacobian terms,
00058 // multiplication with other PDFs that have one or more dependents in
00059 // commen etc)
00060 //
00061 // To implement analytical integrals, two functions must be implemented. First,
00062 //
00063 // Int_t getAnalyticalIntegral(const RooArgSet& integSet, RooArgSet& anaIntSet)
00064 // 
00065 // advertises the analytical integrals that are supported. 'integSet'
00066 // is the set of dependents for which integration is requested. The
00067 // function should copy the subset of dependents it can analytically
00068 // integrate to anaIntSet and return a unique identification code for
00069 // this integration configuration.  If no integration can be
00070 // performed, zero should be returned.  Second,
00071 //
00072 // Double_t analyticalIntegral(Int_t code)
00073 //
00074 // Implements the actual analytical integral(s) advertised by
00075 // getAnalyticalIntegral.  This functions will only be called with
00076 // codes returned by getAnalyticalIntegral, except code zero.
00077 //
00078 // The integration range for real each dependent to be integrated can
00079 // be obtained from the dependents' proxy functions min() and
00080 // max(). Never call these proxy functions for any proxy not known to
00081 // be a dependent via the integration code.  Doing so may be
00082 // ill-defined, e.g. in case the proxy holds a function, and will
00083 // trigger an assert. Integrated category dependents should always be
00084 // summed over all of their states.
00085 //
00086 //
00087 //
00088 // [Direct generation of observables]
00089 //
00090 // Any PDF dependent can be generated with the accept/reject method,
00091 // but for certain PDFs more efficient methods may be implemented. To
00092 // implement direct generation of one or more observables, two
00093 // functions need to be implemented, similar to those for analytical
00094 // integrals:
00095 //
00096 // Int_t getGenerator(const RooArgSet& generateVars, RooArgSet& directVars) and
00097 // void generateEvent(Int_t code)
00098 //
00099 // The first function advertises observables that can be generated,
00100 // similar to the way analytical integrals are advertised. The second
00101 // function implements the generator for the advertised observables
00102 //
00103 // The generated dependent values should be store in the proxy
00104 // objects. For this the assignment operator can be used (i.e. xProxy
00105 // = 3.0 ). Never call assign to any proxy not known to be a dependent
00106 // via the generation code.  Doing so may be ill-defined, e.g. in case
00107 // the proxy holds a function, and will trigger an assert
00108 
00109 
00110 #include "RooFit.h"
00111 #include "RooMsgService.h" 
00112 
00113 #include "TClass.h"
00114 #include "Riostream.h"
00115 #include "TMath.h"
00116 #include "TObjString.h"
00117 #include "TPaveText.h"
00118 #include "TList.h"
00119 #include "TH1.h"
00120 #include "TH2.h"
00121 #include "TMatrixD.h"
00122 #include "TMatrixDSym.h"
00123 #include "RooAbsPdf.h"
00124 #include "RooDataSet.h"
00125 #include "RooArgSet.h"
00126 #include "RooArgProxy.h"
00127 #include "RooRealProxy.h"
00128 #include "RooRealVar.h"
00129 #include "RooGenContext.h"
00130 #include "RooPlot.h"
00131 #include "RooCurve.h"
00132 #include "RooNLLVar.h"
00133 #include "RooMinuit.h"
00134 #include "RooCategory.h"
00135 #include "RooNameReg.h"
00136 #include "RooCmdConfig.h"
00137 #include "RooGlobalFunc.h"
00138 #include "RooAddition.h"
00139 #include "RooRandom.h"
00140 #include "RooNumIntConfig.h"
00141 #include "RooProjectedPdf.h"
00142 #include "RooInt.h"
00143 #include "RooCustomizer.h"
00144 #include "RooConstraintSum.h"
00145 #include "RooParamBinning.h"
00146 #include "RooNumCdf.h"
00147 #include "RooFitResult.h"
00148 #include "RooNumGenConfig.h"
00149 #include "RooCachedReal.h"
00150 #include "RooXYChi2Var.h"
00151 #include "RooChi2Var.h"
00152 #include "RooMinimizer.h"
00153 #include "RooRealIntegral.h"
00154 #include <string>
00155 
00156 ClassImp(RooAbsPdf) 
00157 ;
00158 
00159 
00160 Int_t RooAbsPdf::_verboseEval = 0;
00161 Bool_t RooAbsPdf::_evalError = kFALSE ;
00162 TString RooAbsPdf::_normRangeOverride ;
00163 
00164 //_____________________________________________________________________________
00165 RooAbsPdf::RooAbsPdf() : _norm(0), _normSet(0), _minDimNormValueCache(999), _valueCacheIntOrder(2), _specGeneratorConfig(0)
00166 {
00167   // Default constructor
00168 }
00169 
00170 
00171 
00172 //_____________________________________________________________________________
00173 RooAbsPdf::RooAbsPdf(const char *name, const char *title) : 
00174   RooAbsReal(name,title), _norm(0), _normSet(0), _minDimNormValueCache(999), _valueCacheIntOrder(2), _normMgr(this,10), _selectComp(kTRUE), _specGeneratorConfig(0)
00175 {
00176   // Constructor with name and title only
00177   resetErrorCounters() ;
00178   setTraceCounter(0) ;
00179 }
00180 
00181 
00182 
00183 //_____________________________________________________________________________
00184 RooAbsPdf::RooAbsPdf(const char *name, const char *title, 
00185                      Double_t plotMin, Double_t plotMax) :
00186   RooAbsReal(name,title,plotMin,plotMax), _norm(0), _normSet(0), _minDimNormValueCache(999), _valueCacheIntOrder(2), _normMgr(this,10), _selectComp(kTRUE), _specGeneratorConfig(0)
00187 {
00188   // Constructor with name, title, and plot range
00189   resetErrorCounters() ;
00190   setTraceCounter(0) ;
00191 }
00192 
00193 
00194 
00195 //_____________________________________________________________________________
00196 RooAbsPdf::RooAbsPdf(const RooAbsPdf& other, const char* name) : 
00197   RooAbsReal(other,name), _norm(0), _normSet(0), _minDimNormValueCache(other._minDimNormValueCache), _valueCacheIntOrder(other._valueCacheIntOrder),
00198   _normMgr(other._normMgr,this), _selectComp(other._selectComp), _normRange(other._normRange)
00199 {
00200   // Copy constructor
00201   resetErrorCounters() ;
00202   setTraceCounter(other._traceCount) ;
00203 
00204   if (other._specGeneratorConfig) {
00205     _specGeneratorConfig = new RooNumGenConfig(*other._specGeneratorConfig) ;
00206   } else {
00207     _specGeneratorConfig = 0 ;
00208   }
00209 }
00210 
00211 
00212 
00213 //_____________________________________________________________________________
00214 RooAbsPdf::~RooAbsPdf()
00215 {
00216   // Destructor
00217 
00218   if (_specGeneratorConfig) delete _specGeneratorConfig ;
00219 }
00220 
00221 
00222 
00223 //_____________________________________________________________________________
00224 Double_t RooAbsPdf::getVal(const RooArgSet* nset) const
00225 {
00226   // Return current value, normalizated by integrating over
00227   // the observables in 'nset'. If 'nset' is 0, the unnormalized value. 
00228   // is returned. All elements of 'nset' must be lvalues
00229   //
00230   // Unnormalized values are not cached
00231   // Doing so would be complicated as _norm->getVal() could
00232   // spoil the cache and interfere with returning the cached
00233   // return value. Since unnormalized calls are typically
00234   // done in integration calls, there is no performance hit.
00235 
00236   if (!nset) {
00237     Double_t val = evaluate() ;
00238     Bool_t error = traceEvalPdf(val) ;
00239     cxcoutD(Tracing) << IsA()->GetName() << "::getVal(" << GetName() 
00240                      << "): value = " << val << " (unnormalized)" << endl ;
00241     if (error) {
00242       raiseEvalError() ;
00243       return 0 ;
00244     }
00245     return val ;
00246   }
00247 
00248   // Process change in last data set used
00249   Bool_t nsetChanged(kFALSE) ;
00250   if (nset!=_normSet || _norm==0) {
00251     nsetChanged = syncNormalization(nset) ;
00252   }
00253 
00254   // Return value of object. Calculated if dirty, otherwise cached value is returned.
00255   if ((isValueDirty() || nsetChanged || _norm->isValueDirty()) && operMode()!=AClean) {
00256 
00257     // Evaluate numerator
00258     Double_t rawVal = evaluate() ;
00259     Bool_t error = traceEvalPdf(rawVal) ; // Error checking and printing
00260 
00261     // Evaluate denominator
00262     Double_t normVal(_norm->getVal()) ;
00263     
00264     Double_t normError(kFALSE) ;
00265     if (normVal==0.) {
00266       normError=kTRUE ;
00267       logEvalError("p.d.f normalization integral is zero") ;  
00268     }
00269 
00270     // Raise global error flag if problems occur
00271     if (normError||error) raiseEvalError() ;
00272 
00273     _value = normError ? 0 : (rawVal / normVal) ;
00274 
00275     cxcoutD(Tracing) << "RooAbsPdf::getVal(" << GetName() << ") new value with norm " << _norm->GetName() << " = " << rawVal << "/" << normVal << " = " << _value << endl ;
00276 
00277     clearValueDirty() ; //setValueDirty(kFALSE) ;
00278     clearShapeDirty() ; //setShapeDirty(kFALSE) ;    
00279   } 
00280 
00281   if (_traceCount>0) {
00282     cxcoutD(Tracing) << "[" << _traceCount << "] " ;
00283     Int_t tmp = _traceCount ;
00284     _traceCount = 0 ;
00285     printStream(ccoutD(Tracing),kName|kValue|kArgs,kSingleLine) ;
00286     _traceCount = tmp-1  ;
00287   }
00288 
00289   return _value ;
00290 }
00291 
00292 
00293 
00294 //_____________________________________________________________________________
00295 Double_t RooAbsPdf::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
00296 {
00297   // Analytical integral with normalization (see RooAbsReal::analyticalIntegralWN() for further information)
00298   //
00299   // This function applies the normalization specified by 'normSet' to the integral returned
00300   // by RooAbsReal::analyticalIntegral(). The passthrough scenario (code=0) is also changed
00301   // to return a normalized answer
00302 
00303   cxcoutD(Eval) << "RooAbsPdf::analyticalIntegralWN(" << GetName() << ") code = " << code << " normset = " << (normSet?*normSet:RooArgSet()) << endl ;
00304 
00305 
00306   if (code==0) return getVal(normSet) ;
00307   if (normSet) {
00308     return analyticalIntegral(code,rangeName) / getNorm(normSet) ;
00309   } else {
00310     return analyticalIntegral(code,rangeName) ;
00311   }
00312 }
00313 
00314 
00315 
00316 //_____________________________________________________________________________
00317 Bool_t RooAbsPdf::traceEvalPdf(Double_t value) const
00318 {
00319   // Check that passed value is positive and not 'not-a-number'.  If
00320   // not, print an error, until the error counter reaches its set
00321   // maximum.
00322 
00323   // check for a math error or negative value
00324   Bool_t error= isnan(value) || (value < 0);
00325   if (isnan(value)) {
00326     logEvalError(Form("p.d.f value is Not-a-Number (%f), forcing value to zero",value)) ;
00327   }
00328   if (value<0) {
00329     logEvalError(Form("p.d.f value is less than zero (%f), forcing value to zero",value)) ;
00330   }
00331 
00332   // do nothing if we are no longer tracing evaluations and there was no error
00333   if(!error) return error ;
00334 
00335   // otherwise, print out this evaluations input values and result
00336   if(++_errorCount <= 10) {
00337     cxcoutD(Tracing) << "*** Evaluation Error " << _errorCount << " ";
00338     if(_errorCount == 10) cxcoutD(Tracing) << "(no more will be printed) ";
00339   }
00340   else {
00341     return error  ;
00342   }
00343 
00344   Print() ;
00345   return error ;
00346 }
00347 
00348 
00349 
00350 
00351 //_____________________________________________________________________________
00352 Double_t RooAbsPdf::getNorm(const RooArgSet* nset) const
00353 {
00354   // Return the integral of this PDF over all observables listed in 'nset'. 
00355 
00356   if (!nset) return 1 ;
00357 
00358   syncNormalization(nset,kTRUE) ;
00359   if (_verboseEval>1) cxcoutD(Tracing) << IsA()->GetName() << "::getNorm(" << GetName() << "): norm(" << _norm << ") = " << _norm->getVal() << endl ;
00360 
00361   Double_t ret = _norm->getVal() ;
00362 //   cout << "RooAbsPdf::getNorm(" << GetName() << ") norm obj = " << _norm->GetName() << endl ;
00363   if (ret==0.) {
00364     if(++_errorCount <= 10) {
00365       coutW(Eval) << "RooAbsPdf::getNorm(" << GetName() << ":: WARNING normalization is zero, nset = " ;  nset->Print("1") ;
00366       if(_errorCount == 10) coutW(Eval) << "RooAbsPdf::getNorm(" << GetName() << ") INFO: no more messages will be printed " << endl ;
00367     }
00368   }
00369 
00370   return ret ;
00371 }
00372 
00373 
00374 
00375 //_____________________________________________________________________________
00376 const RooAbsReal* RooAbsPdf::getNormObj(const RooArgSet* nset, const RooArgSet* iset, const TNamed* rangeName) const 
00377 {
00378   // Return pointer to RooAbsReal object that implements calculation of integral over observables iset in range
00379   // rangeName, optionally taking the integrand normalized over observables nset
00380 
00381 
00382   // Check normalization is already stored
00383   CacheElem* cache = (CacheElem*) _normMgr.getObj(nset,iset,0,rangeName) ;
00384   if (cache) {
00385     return cache->_norm ;
00386   }
00387 
00388   // If not create it now
00389   RooArgSet* depList = getObservables(iset) ;
00390   RooAbsReal* norm = createIntegral(*depList,*nset, *getIntegratorConfig(), RooNameReg::str(rangeName)) ;
00391   delete depList ;
00392 
00393   // Store it in the cache
00394   cache = new CacheElem(*norm) ;
00395   _normMgr.setObj(nset,iset,cache,rangeName) ;
00396 
00397   // And return the newly created integral
00398   return norm ;
00399 }
00400 
00401 
00402 
00403 //_____________________________________________________________________________
00404 Bool_t RooAbsPdf::syncNormalization(const RooArgSet* nset, Bool_t adjustProxies) const
00405 {
00406   // Verify that the normalization integral cached with this PDF
00407   // is valid for given set of normalization observables
00408   //
00409   // If not, the cached normalization integral (if any) is deleted
00410   // and a new integral is constructed for use with 'nset'
00411   // Elements in 'nset' can be discrete and real, but must be lvalues
00412   //
00413   // For functions that declare to be self-normalized by overloading the
00414   // selfNormalized() function, a unit normalization is always constructed
00415 
00416 
00417   //cout << IsA()->GetName() << "::syncNormalization(" << GetName() << ") nset = " << nset << " = " << (nset?*nset:RooArgSet()) << endl ;
00418 
00419   _normSet = (RooArgSet*) nset ;
00420 
00421   // Check if data sets are identical
00422   CacheElem* cache = (CacheElem*) _normMgr.getObj(nset) ;
00423   if (cache) {
00424 
00425     Bool_t nsetChanged = (_norm!=cache->_norm) ;
00426     _norm = cache->_norm ;
00427 
00428 
00429 //     cout << "returning existing object " << _norm->GetName() << endl ;
00430 
00431     if (nsetChanged && adjustProxies) {
00432       // Update dataset pointers of proxies
00433       ((RooAbsPdf*) this)->setProxyNormSet(nset) ;
00434     }
00435   
00436     return nsetChanged ;
00437   }
00438     
00439   // Update dataset pointers of proxies
00440   if (adjustProxies) {
00441     ((RooAbsPdf*) this)->setProxyNormSet(nset) ;
00442   }
00443   
00444   RooArgSet* depList = getObservables(nset) ;
00445 
00446   if (_verboseEval>0) {
00447     if (!selfNormalized()) {
00448       cxcoutD(Tracing) << IsA()->GetName() << "::syncNormalization(" << GetName() 
00449            << ") recreating normalization integral " << endl ;
00450       if (depList) depList->printStream(ccoutD(Tracing),kName|kValue|kArgs,kSingleLine) ; else ccoutD(Tracing) << "<none>" << endl ;
00451     } else {
00452       cxcoutD(Tracing) << IsA()->GetName() << "::syncNormalization(" << GetName() << ") selfNormalized, creating unit norm" << endl;
00453     }
00454   }
00455 
00456   // Destroy old normalization & create new
00457   if (selfNormalized() || !dependsOn(*depList)) {    
00458     TString ntitle(GetTitle()) ; ntitle.Append(" Unit Normalization") ;
00459     TString nname(GetName()) ; nname.Append("_UnitNorm") ;
00460     _norm = new RooRealVar(nname.Data(),ntitle.Data(),1) ;
00461   } else {    
00462     const char* nr = (_normRangeOverride.Length()>0 ? _normRangeOverride.Data() : (_normRange.Length()>0 ? _normRange.Data() : 0)) ;
00463 
00464 //     cout << "RooAbsPdf::syncNormalization(" << GetName() << ") rangeName for normalization is " << (nr?nr:"<null>") << endl ;
00465     RooRealIntegral* normInt = (RooRealIntegral*) createIntegral(*depList,*getIntegratorConfig(),nr) ;
00466     normInt->getVal() ;
00467 //     cout << "resulting normInt = " << normInt->GetName() << endl ;
00468 
00469     RooArgSet* normParams = normInt->getVariables() ;
00470     if (normParams->getSize()>0 && normParams->getSize()<3 && normInt->numIntRealVars().getSize()>=_minDimNormValueCache) {
00471       coutI(Caching) << "RooAbsPdf::syncNormalization(" << GetName() << ") INFO: constructing " << normParams->getSize() 
00472                      << "-dim value cache for normalization integral over " << *depList << endl ;
00473       string name = Form("%s_CACHE_[%s]",normInt->GetName(),normParams->contentsString().c_str()) ;
00474       RooCachedReal* cachedNorm = new RooCachedReal(name.c_str(),name.c_str(),*normInt,*normParams) ;     
00475       cachedNorm->setInterpolationOrder(_valueCacheIntOrder) ;
00476       cachedNorm->addOwnedComponents(*normInt) ;
00477       _norm = cachedNorm ;
00478     } else {
00479       _norm = normInt ;
00480     } 
00481     delete normParams ;
00482   }
00483 
00484 
00485 
00486   // Register new normalization with manager (takes ownership)
00487   cache = new CacheElem(*_norm) ;
00488   _normMgr.setObj(nset,cache) ;
00489 
00490 //     cout << "making new object " << _norm->GetName() << endl ;
00491 
00492   delete depList ;
00493   return kTRUE ;
00494 }
00495 
00496 
00497 
00498 //_____________________________________________________________________________
00499 void RooAbsPdf::setNormValueCaching(Int_t minNumIntDim, Int_t ipOrder) 
00500 { 
00501   // Activate caching of normalization integral values in a interpolated histogram 
00502   // for integrals that exceed the specified minimum number of numerically integrated
00503   // dimensions, _and_ of which the integral has at most 2 parameters. 
00504   //
00505   // The cache is scanned with a granularity defined by a binning named "cache" in the 
00506   // scanned integral parameters and is interpolated to given order.
00507   // The cache values are kept for the livetime of the ROOT session/application
00508   // and are persisted along with the object in case the p.d.f. is persisted
00509   // in a RooWorkspace
00510   // 
00511   // This feature can substantially speed up fits and improve convergence with slow 
00512   // multi-dimensional integrals whose value varies slowly with the parameters so that the
00513   // an interpolated histogram is a good approximation of the true integral value.
00514   // The improved convergence behavior is a result of making the value of the normalization
00515   // integral deterministic for each value of the parameters. If (multi-dimensional) numeric
00516   // integrals are calculated at insufficient precision (>=1e-7) MINUIT convergence may
00517   // be impaired by the effects numerical noise that can cause that subsequent evaluations
00518   // of an integral at the same point in parameter space can give slightly different answers.
00519 
00520   _minDimNormValueCache = minNumIntDim ; 
00521   _valueCacheIntOrder = ipOrder ; 
00522 }
00523 
00524 
00525 
00526 
00527 //_____________________________________________________________________________
00528 Bool_t RooAbsPdf::traceEvalHook(Double_t value) const 
00529 {
00530   // WVE 08/21/01 Probably obsolete now.
00531 
00532   // Floating point error checking and tracing for given float value
00533 
00534   // check for a math error or negative value
00535   Bool_t error= isnan(value) || (value < 0);
00536 
00537   // do nothing if we are no longer tracing evaluations and there was no error
00538   if(!error && _traceCount <= 0) return error ;
00539 
00540   // otherwise, print out this evaluations input values and result
00541   if(error && ++_errorCount <= 10) {
00542     cxcoutD(Tracing) << "*** Evaluation Error " << _errorCount << " ";
00543     if(_errorCount == 10) ccoutD(Tracing) << "(no more will be printed) ";
00544   }
00545   else if(_traceCount > 0) {
00546     ccoutD(Tracing) << '[' << _traceCount-- << "] ";
00547   }
00548   else {
00549     return error ;
00550   }
00551 
00552   Print() ;
00553 
00554   return error ;
00555 }
00556 
00557 
00558 
00559 
00560 //_____________________________________________________________________________
00561 void RooAbsPdf::resetErrorCounters(Int_t resetValue)
00562 {
00563   // Reset error counter to given value, limiting the number
00564   // of future error messages for this pdf to 'resetValue'
00565 
00566   _errorCount = resetValue ;
00567   _negCount   = resetValue ;
00568 }
00569 
00570 
00571 
00572 //_____________________________________________________________________________
00573 void RooAbsPdf::setTraceCounter(Int_t value, Bool_t allNodes)
00574 {
00575   // Reset trace counter to given value, limiting the
00576   // number of future trace messages for this pdf to 'value'
00577 
00578   if (!allNodes) {
00579     _traceCount = value ;
00580     return ; 
00581   } else {
00582     RooArgList branchList ;
00583     branchNodeServerList(&branchList) ;
00584     TIterator* iter = branchList.createIterator() ;
00585     RooAbsArg* arg ;
00586     while((arg=(RooAbsArg*)iter->Next())) {
00587       RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(arg) ;
00588       if (pdf) pdf->setTraceCounter(value,kFALSE) ;
00589     }
00590     delete iter ;
00591   }
00592 
00593 }
00594 
00595 
00596 
00597 
00598 //_____________________________________________________________________________
00599 Double_t RooAbsPdf::getLogVal(const RooArgSet* nset) const 
00600 {
00601   // Return the log of the current value with given normalization
00602   // An error message is printed if the argument of the log is negative.
00603 
00604   Double_t prob = getVal(nset) ;
00605   if(prob < 0) {
00606 
00607     logEvalError("getLogVal() top-level p.d.f evaluates to a negative number") ;
00608 
00609     return 0;
00610   }
00611   if(prob == 0) {
00612 
00613     logEvalError("getLogVal() top-level p.d.f evaluates to zero") ;
00614 
00615     return log((double)0);
00616   }
00617   return log(prob);
00618 }
00619 
00620 
00621 
00622 //_____________________________________________________________________________
00623 Double_t RooAbsPdf::extendedTerm(UInt_t observed, const RooArgSet* nset) const 
00624 {
00625   // Returned the extended likelihood term (Nexpect - Nobserved*log(NExpected)
00626   // of this PDF for the given number of observed events
00627   //
00628   // For successfull operation the PDF implementation must indicate
00629   // it is extendable by overloading canBeExtended() and must
00630   // implemented the expectedEvents() function.
00631 
00632   // check if this PDF supports extended maximum likelihood fits
00633   if(!canBeExtended()) {
00634     coutE(InputArguments) << fName << ": this PDF does not support extended maximum likelihood"
00635          << endl;
00636     return 0;
00637   }
00638 
00639   Double_t expected= expectedEvents(nset);
00640   if(expected < 0) {
00641     coutE(InputArguments) << fName << ": calculated negative expected events: " << expected
00642          << endl;
00643     return 0;
00644   }
00645 
00646   // calculate and return the negative log-likelihood of the Poisson
00647   // factor for this dataset, dropping the constant log(observed!)
00648   Double_t extra= expected - observed*log(expected);
00649 
00650 //   cout << "RooAbsPdf::extendedTerm(" << GetName() << ") observed = " << observed << " expected = " << expected << endl ;
00651 
00652   Bool_t trace(kFALSE) ;
00653   if(trace) {
00654     cxcoutD(Tracing) << fName << "::extendedTerm: expected " << expected << " events, got "
00655                      << observed << " events. extendedTerm = " << extra << endl;
00656   }
00657   return extra;
00658 }
00659 
00660 
00661 
00662 //_____________________________________________________________________________
00663 RooAbsReal* RooAbsPdf::createNLL(RooAbsData& data, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3, const RooCmdArg& arg4, 
00664                                              const RooCmdArg& arg5, const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) 
00665 {
00666   // Construct representation of -log(L) of PDFwith given dataset. If dataset is unbinned, an unbinned likelihood is constructed. If the dataset
00667   // is binned, a binned likelihood is constructed. 
00668   //
00669   // The following named arguments are supported
00670   //
00671   // ConditionalObservables(const RooArgSet& set) -- Do not normalize PDF over listed observables
00672   // Extended(Bool_t flag)           -- Add extended likelihood term, off by default
00673   // Range(const char* name)         -- Fit only data inside range with given name
00674   // Range(Double_t lo, Double_t hi) -- Fit only data inside given range. A range named "fit" is created on the fly on all observables.
00675   //                                    Multiple comma separated range names can be specified.
00676   // SumCoefRange(const char* name)  -- Set the range in which to interpret the coefficients of RooAddPdf components 
00677   // NumCPU(int num)                 -- Parallelize NLL calculation on num CPUs
00678   // Optimize(Bool_t flag)           -- Activate constant term optimization (on by default)
00679   // SplitRange(Bool_t flag)         -- Use separate fit ranges in a simultaneous fit. Actual range name for each
00680   //                                    subsample is assumed to by rangeName_{indexState} where indexState
00681   //                                    is the state of the master index category of the simultaneous fit
00682   // Constrain(const RooArgSet&pars) -- For p.d.f.s that contain internal parameter constraint terms, only apply constraints to given subset of parameters
00683   // ExternalConstraints(const RooArgSet& ) -- Include given external constraints to likelihood
00684   // Verbose(Bool_t flag)           -- Constrols RooFit informational messages in likelihood construction
00685   // CloneData(Bool flag)           -- Use clone of dataset in NLL (default is true)
00686   // 
00687   // 
00688   
00689   RooLinkedList l ;
00690   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
00691   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
00692   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
00693   l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
00694   return createNLL(data,l) ;
00695 }
00696 
00697 
00698 
00699 
00700 //_____________________________________________________________________________
00701 RooAbsReal* RooAbsPdf::createNLL(RooAbsData& data, const RooLinkedList& cmdList) 
00702 {
00703   // Construct representation of -log(L) of PDFwith given dataset. If dataset is unbinned, an unbinned likelihood is constructed. If the dataset
00704   // is binned, a binned likelihood is constructed. 
00705   //
00706   // See RooAbsPdf::createNLL(RooAbsData& data, RooCmdArg arg1, RooCmdArg arg2, RooCmdArg arg3, RooCmdArg arg4, 
00707   //                                    RooCmdArg arg5, RooCmdArg arg6, RooCmdArg arg7, RooCmdArg arg8) 
00708   //
00709   // for documentation of options
00710 
00711 
00712   // Select the pdf-specific commands 
00713   RooCmdConfig pc(Form("RooAbsPdf::createNLL(%s)",GetName())) ;
00714 
00715   pc.defineString("rangeName","RangeWithName",0,"",kTRUE) ;
00716   pc.defineString("addCoefRange","SumCoefRange",0,"") ;
00717   pc.defineDouble("rangeLo","Range",0,-999.) ;
00718   pc.defineDouble("rangeHi","Range",1,-999.) ;
00719   pc.defineInt("splitRange","SplitRange",0,0) ;
00720   pc.defineInt("ext","Extended",0,2) ;
00721   pc.defineInt("numcpu","NumCPU",0,1) ;
00722   pc.defineInt("verbose","Verbose",0,0) ;
00723   pc.defineInt("optConst","Optimize",0,0) ;
00724   pc.defineInt("cloneData","CloneData",2,0) ;
00725   pc.defineSet("projDepSet","ProjectedObservables",0,0) ;
00726   pc.defineSet("cPars","Constrain",0,0) ;
00727   pc.defineInt("constrAll","Constrained",0,0) ;
00728   pc.defineSet("extCons","ExternalConstraints",0,0) ;
00729   pc.defineMutex("Range","RangeWithName") ;
00730   pc.defineMutex("Constrain","Constrained") ;
00731   
00732   // Process and check varargs 
00733   pc.process(cmdList) ;
00734   if (!pc.ok(kTRUE)) {
00735     return 0 ;
00736   }
00737 
00738   // Decode command line arguments
00739   const char* rangeName = pc.getString("rangeName",0,kTRUE) ;
00740   const char* addCoefRangeName = pc.getString("addCoefRange",0,kTRUE) ;
00741   Int_t ext      = pc.getInt("ext") ;
00742   Int_t numcpu   = pc.getInt("numcpu") ;
00743   Int_t splitr   = pc.getInt("splitRange") ;
00744   Bool_t verbose = pc.getInt("verbose") ;
00745   Int_t optConst = pc.getInt("optConst") ;
00746   Int_t cloneData = pc.getInt("cloneData") ;
00747   
00748   // If no explicit cloneData command is specified, cloneData is set to true if optimization is activated
00749   if (cloneData==2) {
00750     cloneData = optConst ;
00751   }
00752   RooArgSet* cPars = pc.getSet("cPars") ;
00753   Bool_t doStripDisconnected=kFALSE ;
00754 
00755   // If no explicit list of parameters to be constrained is specified apply default algorithm
00756   // All terms of RooProdPdfs that do not contain observables and share a parameters with one or more
00757   // terms that do contain observables are added as constraints.
00758   if (!cPars) {    
00759     cPars = getParameters(data,kFALSE) ;
00760     doStripDisconnected=kTRUE ;
00761   }
00762   const RooArgSet* extCons = pc.getSet("extCons") ;
00763 
00764   // Process automatic extended option
00765   if (ext==2) {
00766     ext = ((extendMode()==CanBeExtended || extendMode()==MustBeExtended)) ? 1 : 0 ;
00767     if (ext) {
00768       coutI(Minimization) << "p.d.f. provides expected number of events, including extended term in likelihood." << endl ;
00769     }
00770   }
00771 
00772   if (pc.hasProcessed("Range")) {
00773     Double_t rangeLo = pc.getDouble("rangeLo") ;
00774     Double_t rangeHi = pc.getDouble("rangeHi") ;
00775    
00776     // Create range with name 'fit' with above limits on all observables
00777     RooArgSet* obs = getObservables(&data) ;
00778     TIterator* iter = obs->createIterator() ;
00779     RooAbsArg* arg ;
00780     while((arg=(RooAbsArg*)iter->Next())) {
00781       RooRealVar* rrv =  dynamic_cast<RooRealVar*>(arg) ;
00782       if (rrv) rrv->setRange("fit",rangeLo,rangeHi) ;
00783     }
00784     // Set range name to be fitted to "fit"
00785     rangeName = "fit" ;
00786   }
00787 
00788   RooArgSet projDeps ;
00789   RooArgSet* tmp = pc.getSet("projDepSet") ;  
00790   if (tmp) {
00791     projDeps.add(*tmp) ;
00792   }
00793 
00794   // Construct NLL
00795   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00796   RooAbsReal* nll ;
00797   string baseName = Form("nll_%s_%s",GetName(),data.GetName()) ;
00798   if (!rangeName || strchr(rangeName,',')==0) {
00799     // Simple case: default range, or single restricted range
00800     //cout<<"FK: Data test 1: "<<data.sumEntries()<<endl;
00801 
00802     nll = new RooNLLVar(baseName.c_str(),"-log(likelihood)",*this,data,projDeps,ext,rangeName,addCoefRangeName,numcpu,kFALSE,verbose,splitr,cloneData) ;
00803 
00804   } else {
00805     // Composite case: multiple ranges
00806     RooArgList nllList ;
00807     char* buf = new char[strlen(rangeName)+1] ;
00808     strlcpy(buf,rangeName,strlen(rangeName)+1) ;
00809     char* token = strtok(buf,",") ;
00810     while(token) {
00811       RooAbsReal* nllComp = new RooNLLVar(Form("%s_%s",baseName.c_str(),token),"-log(likelihood)",*this,data,projDeps,ext,token,addCoefRangeName,numcpu,kFALSE,verbose,splitr,cloneData) ;
00812       nllList.add(*nllComp) ;
00813       token = strtok(0,",") ;
00814     }
00815     delete[] buf ;
00816     nll = new RooAddition(baseName.c_str(),"-log(likelihood)",nllList,kTRUE) ;
00817   }
00818   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00819   
00820   // Collect internal and external constraint specifications
00821   RooArgSet allConstraints ;
00822   if (cPars && cPars->getSize()>0) {
00823     RooArgSet* constraints = getAllConstraints(*data.get(),*cPars,doStripDisconnected) ;
00824     allConstraints.add(*constraints) ;
00825     delete constraints ;
00826     
00827   }
00828   if (extCons) {
00829     allConstraints.add(*extCons) ;
00830   }
00831 
00832   // Include constraints, if any, in likelihood
00833   RooAbsReal* nllCons(0) ;
00834   if (allConstraints.getSize()>0 && cPars) {   
00835 
00836     coutI(Minimization) << " Including the following contraint terms in minimization: " << allConstraints << endl ;
00837 
00838     nllCons = new RooConstraintSum(Form("%s_constr",baseName.c_str()),"nllCons",allConstraints,*cPars) ;
00839     RooAbsReal* orignll = nll ;
00840 
00841     nll = new RooAddition(Form("%s_with_constr",baseName.c_str()),"nllWithCons",RooArgSet(*nll,*nllCons)) ;
00842     nll->addOwnedComponents(RooArgSet(*orignll,*nllCons)) ;
00843   }
00844 
00845   if (optConst) {
00846 
00847     nll->constOptimizeTestStatistic(RooAbsArg::Activate) ;
00848   }
00849 
00850   if (doStripDisconnected) {
00851     delete cPars ;
00852   }
00853   return nll ;
00854 }
00855 
00856 
00857 
00858 
00859 
00860 
00861 //_____________________________________________________________________________
00862 RooFitResult* RooAbsPdf::fitTo(RooAbsData& data, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3, const RooCmdArg& arg4, 
00863                                                  const RooCmdArg& arg5, const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) 
00864 {
00865   // Fit PDF to given dataset. If dataset is unbinned, an unbinned maximum likelihood is performed. If the dataset
00866   // is binned, a binned maximum likelihood is performed. By default the fit is executed through the MINUIT
00867   // commands MIGRAD, HESSE and MINOS in succession.
00868   //
00869   // The following named arguments are supported
00870   //
00871   // Options to control construction of -log(L)
00872   // ------------------------------------------
00873   // ConditionalObservables(const RooArgSet& set) -- Do not normalize PDF over listed observables
00874   // Extended(Bool_t flag)           -- Add extended likelihood term, off by default
00875   // Range(const char* name)         -- Fit only data inside range with given name
00876   // Range(Double_t lo, Double_t hi) -- Fit only data inside given range. A range named "fit" is created on the fly on all observables.
00877   //                                    Multiple comma separated range names can be specified.
00878   // SumCoefRange(const char* name)  -- Set the range in which to interpret the coefficients of RooAddPdf components 
00879   // NumCPU(int num)                 -- Parallelize NLL calculation on num CPUs
00880   // SplitRange(Bool_t flag)         -- Use separate fit ranges in a simultaneous fit. Actual range name for each
00881   //                                    subsample is assumed to by rangeName_{indexState} where indexState
00882   //                                    is the state of the master index category of the simultaneous fit
00883   // Constrained()                   -- Apply all constrained contained in the p.d.f. in the likelihood 
00884   // Contrain(const RooArgSet&pars)  -- Apply constraints to listed parameters in likelihood using internal constrains in p.d.f
00885   // ExternalConstraints(const RooArgSet& ) -- Include given external constraints to likelihood
00886   //
00887   // Options to control flow of fit procedure
00888   // ----------------------------------------
00889   //
00890   // Minimizer(type,algo)           -- Choose minimization package and algorithm to use. Default is MINUIT/MIGRAD through the RooMinuit
00891   //                                   interface, but others can be specified (through RooMinimizer interface)
00892   //
00893   //                                          Type         Algorithm
00894   //                                          ------       ---------
00895   //                                          Minuit       migrad, simplex, minimize (=migrad+simplex), migradimproved (=migrad+improve)
00896   //                                          Minuit2      migrad, simplex, minimize, scan
00897   //                                          GSLMultiMin  conjugatefr, conjugatepr, bfgs, bfgs2, steepestdescent
00898   //                                          GSLSimAn     -
00899   //
00900   // 
00901   // InitialHesse(Bool_t flag)      -- Flag controls if HESSE before MIGRAD as well, off by default
00902   // Optimize(Bool_t flag)          -- Activate constant term optimization of test statistic during minimization (on by default)
00903   // Hesse(Bool_t flag)             -- Flag controls if HESSE is run after MIGRAD, on by default
00904   // Minos(Bool_t flag)             -- Flag controls if MINOS is run after HESSE, on by default
00905   // Minos(const RooArgSet& set)    -- Only run MINOS on given subset of arguments
00906   // Save(Bool_t flag)              -- Flac controls if RooFitResult object is produced and returned, off by default
00907   // Strategy(Int_t flag)           -- Set Minuit strategy (0 through 2, default is 1)
00908   // FitOptions(const char* optStr) -- Steer fit with classic options string (for backward compatibility). Use of this option
00909   //                                   excludes use of any of the new style steering options.
00910   //
00911   // SumW2Error(Bool_t flag)        -- Apply correaction to errors and covariance matrix using sum-of-weights covariance matrix
00912   //                                   to obtain correct error for weighted likelihood fits. If this option is activated the
00913   //                                   corrected covariance matrix is calculated as Vcorr = V C-1 V, where V is the original 
00914   //                                   covariance matrix and C is the inverse of the covariance matrix calculated using the
00915   //                                   weights squared
00916   //
00917   // Options to control informational output
00918   // ---------------------------------------
00919   // Verbose(Bool_t flag)           -- Flag controls if verbose output is printed (NLL, parameter changes during fit
00920   // Timer(Bool_t flag)             -- Time CPU and wall clock consumption of fit steps, off by default
00921   // PrintLevel(Int_t level)        -- Set Minuit print level (-1 through 3, default is 1). At -1 all RooFit informational 
00922   //                                   messages are suppressed as well
00923   // Warnings(Bool_t flag)          -- Enable or disable MINUIT warnings (enabled by default)
00924   // PrintEvalErrors(Int_t numErr)  -- Control number of p.d.f evaluation errors printed per likelihood evaluation. A negative
00925   //                                   value suppress output completely, a zero value will only print the error count per p.d.f component,
00926   //                                   a positive value is will print details of each error up to numErr messages per p.d.f component.
00927   // 
00928   // 
00929   
00930   RooLinkedList l ;
00931   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
00932   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
00933   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
00934   l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
00935   return fitTo(data,l) ;
00936 }
00937 
00938 
00939 
00940 //_____________________________________________________________________________
00941 RooFitResult* RooAbsPdf::fitTo(RooAbsData& data, const RooLinkedList& cmdList) 
00942 {
00943   // Fit PDF to given dataset. If dataset is unbinned, an unbinned maximum likelihood is performed. If the dataset
00944   // is binned, a binned maximum likelihood is performed. By default the fit is executed through the MINUIT
00945   // commands MIGRAD, HESSE and MINOS in succession.
00946   //
00947   // See RooAbsPdf::fitTo(RooAbsData& data, RooCmdArg arg1, RooCmdArg arg2, RooCmdArg arg3, RooCmdArg arg4, 
00948   //                                         RooCmdArg arg5, RooCmdArg arg6, RooCmdArg arg7, RooCmdArg arg8) 
00949   //
00950   // for documentation of options
00951 
00952 
00953   // Select the pdf-specific commands 
00954   RooCmdConfig pc(Form("RooAbsPdf::fitTo(%s)",GetName())) ;
00955 
00956   RooLinkedList fitCmdList(cmdList) ;
00957   RooLinkedList nllCmdList = pc.filterCmdList(fitCmdList,"ProjectedObservables,Extended,Range,RangeWithName,SumCoefRange,NumCPU,SplitRange,Constrained,Constrain,ExternalConstraints,CloneData") ;
00958 
00959   pc.defineString("fitOpt","FitOptions",0,"") ;
00960   pc.defineInt("optConst","Optimize",0,1) ;
00961   pc.defineInt("verbose","Verbose",0,0) ;
00962   pc.defineInt("doSave","Save",0,0) ;
00963   pc.defineInt("doTimer","Timer",0,0) ;
00964   pc.defineInt("plevel","PrintLevel",0,1) ;
00965   pc.defineInt("strat","Strategy",0,1) ;
00966   pc.defineInt("initHesse","InitialHesse",0,0) ;
00967   pc.defineInt("hesse","Hesse",0,1) ;
00968   pc.defineInt("minos","Minos",0,0) ;
00969   pc.defineInt("ext","Extended",0,2) ;
00970   pc.defineInt("numcpu","NumCPU",0,1) ;
00971   pc.defineInt("numee","PrintEvalErrors",0,10) ;
00972   pc.defineInt("doEEWall","EvalErrorWall",0,1) ;
00973   pc.defineInt("doWarn","Warnings",0,1) ;
00974   pc.defineInt("doSumW2","SumW2Error",0,-1) ;
00975   pc.defineString("mintype","Minimizer",0,"") ;
00976   pc.defineString("minalg","Minimizer",1,"") ;
00977   pc.defineObject("minosSet","Minos",0,0) ;
00978   pc.defineSet("cPars","Constrain",0,0) ;
00979   pc.defineSet("extCons","ExternalConstraints",0,0) ;
00980   pc.defineMutex("FitOptions","Verbose") ;
00981   pc.defineMutex("FitOptions","Save") ;
00982   pc.defineMutex("FitOptions","Timer") ;
00983   pc.defineMutex("FitOptions","Strategy") ;
00984   pc.defineMutex("FitOptions","InitialHesse") ;
00985   pc.defineMutex("FitOptions","Hesse") ;
00986   pc.defineMutex("FitOptions","Minos") ;
00987   pc.defineMutex("Range","RangeWithName") ;
00988   pc.defineMutex("InitialHesse","Minimizer") ;
00989   
00990   // Process and check varargs 
00991   pc.process(fitCmdList) ;
00992   if (!pc.ok(kTRUE)) {
00993     return 0 ;
00994   }
00995 
00996   // Decode command line arguments
00997   const char* fitOpt = pc.getString("fitOpt",0,kTRUE) ;
00998   Int_t optConst = pc.getInt("optConst") ;
00999   Int_t verbose  = pc.getInt("verbose") ;
01000   Int_t doSave   = pc.getInt("doSave") ;
01001   Int_t doTimer  = pc.getInt("doTimer") ;
01002   Int_t plevel    = pc.getInt("plevel") ;
01003   Int_t strat    = pc.getInt("strat") ;
01004   Int_t initHesse= pc.getInt("initHesse") ;
01005   Int_t hesse    = pc.getInt("hesse") ;
01006   Int_t minos    = pc.getInt("minos") ;
01007   Int_t numee    = pc.getInt("numee") ;
01008   Int_t doEEWall = pc.getInt("doEEWall") ;
01009   Int_t doWarn   = pc.getInt("doWarn") ;
01010   Int_t doSumW2  = pc.getInt("doSumW2") ;
01011   const RooArgSet* minosSet = static_cast<RooArgSet*>(pc.getObject("minosSet")) ;
01012 #ifdef __ROOFIT_NOROOMINIMIZER
01013   const char* minType =0 ;
01014 #else
01015   const char* minType = pc.getString("mintype","",kTRUE) ;
01016   const char* minAlg = pc.getString("minalg","",kTRUE) ;
01017 #endif
01018 
01019   // Determine if the dataset has weights  
01020   Bool_t weightedData = data.isNonPoissonWeighted() ;
01021 
01022   // Warn user that a SumW2Error() argument should be provided if weighted data is offered
01023   if (weightedData && doSumW2==-1) {
01024     coutW(InputArguments) << "RooAbsPdf::fitTo(" << GetName() << ") WARNING: a likelihood fit is request of what appears to be weighted data. " << endl
01025                           << "       While the estimated values of the parameters will always be calculated taking the weights into account, " << endl 
01026                           << "       there are multiple ways to estimate the errors on these parameter values. You are advised to make an " << endl 
01027                           << "       explicit choice on the error calculation: " << endl
01028                           << "           - Either provide SumW2Error(kTRUE), to calculate a sum-of-weights corrected HESSE error matrix " << endl
01029                           << "             (error will be proportional to the number of events)" << endl 
01030                           << "           - Or provide SumW2Error(kFALSE), to return errors from original HESSE error matrix" << endl 
01031                           << "             (which will be proportional to the sum of the weights)" << endl 
01032                           << "       If you want the errors to reflect the information contained in the provided dataset, choose kTRUE. " << endl
01033                           << "       If you want the errors to reflect the precision you would be able to obtain with an unweighted dataset " << endl 
01034                           << "       with 'sum-of-weights' events, choose kFALSE." << endl ;
01035   }
01036 
01037 
01038   // Warn user that sum-of-weights correction does not apply to MINOS errrors
01039   if (doSumW2==1 && minos) {
01040     coutW(InputArguments) << "RooAbsPdf::fitTo(" << GetName() << ") WARNING: sum-of-weights correction does not apply to MINOS errors" << endl ;
01041   }
01042     
01043   RooAbsReal* nll = createNLL(data,nllCmdList) ;  
01044 
01045   RooFitResult *ret = 0 ;    
01046 
01047   // Instantiate MINUIT
01048 
01049   if (minType) {
01050 
01051 #ifndef __ROOFIT_NOROOMINIMIZER
01052     RooMinimizer m(*nll) ;
01053 
01054     m.setMinimizerType(minType) ;
01055     
01056     m.setEvalErrorWall(doEEWall) ;
01057     if (doWarn==0) {
01058       // m.setNoWarn() ; WVE FIX THIS
01059     }
01060     
01061     m.setPrintEvalErrors(numee) ;
01062     if (plevel!=1) {
01063       m.setPrintLevel(plevel) ;
01064     }
01065     
01066     if (optConst) {
01067       // Activate constant term optimization
01068       m.optimizeConst(1) ;
01069     }
01070     
01071     if (fitOpt) {
01072       
01073       // Play fit options as historically defined
01074       ret = m.fit(fitOpt) ;
01075       
01076     } else {
01077       
01078       if (verbose) {
01079         // Activate verbose options
01080         m.setVerbose(1) ;
01081       }
01082       if (doTimer) {
01083         // Activate timer options
01084         m.setProfile(1) ;
01085       }
01086       
01087       if (strat!=1) {
01088         // Modify fit strategy
01089         m.setStrategy(strat) ;
01090       }
01091       
01092       if (initHesse) {
01093         // Initialize errors with hesse
01094         m.hesse() ;
01095       }
01096       
01097       // Minimize using chosen algorithm
01098       m.minimize(minType,minAlg) ;
01099       
01100       if (hesse) {
01101         // Evaluate errors with Hesse
01102         m.hesse() ;
01103       }
01104       
01105       if (doSumW2==1) {
01106         
01107         // Make list of RooNLLVar components of FCN
01108         list<RooNLLVar*> nllComponents ;
01109         RooArgSet* comps = nll->getComponents() ;
01110         RooAbsArg* arg ;
01111         TIterator* citer = comps->createIterator() ;
01112         while((arg=(RooAbsArg*)citer->Next())) {
01113           RooNLLVar* nllComp = dynamic_cast<RooNLLVar*>(arg) ;
01114           if (nllComp) {
01115             nllComponents.push_back(nllComp) ;
01116           }
01117         }
01118         delete citer ;
01119         delete comps ;  
01120         
01121         // Calculated corrected errors for weighted likelihood fits
01122         RooFitResult* rw = m.save() ;
01123         for (list<RooNLLVar*>::iterator iter1=nllComponents.begin() ; iter1!=nllComponents.end() ; iter1++) {
01124           (*iter1)->applyWeightSquared(kTRUE) ;
01125         }
01126         coutI(Fitting) << "RooAbsPdf::fitTo(" << GetName() << ") Calculating sum-of-weights-squared correction matrix for covariance matrix" << endl ;
01127         m.hesse() ;
01128         RooFitResult* rw2 = m.save() ;
01129         for (list<RooNLLVar*>::iterator iter2=nllComponents.begin() ; iter2!=nllComponents.end() ; iter2++) {
01130           (*iter2)->applyWeightSquared(kFALSE) ;
01131         }
01132         
01133         // Apply correction matrix
01134         const TMatrixDSym& V = rw->covarianceMatrix() ;
01135         TMatrixDSym  C = rw2->covarianceMatrix() ;
01136         
01137         // Invert C
01138         Double_t det(0) ;
01139         C.Invert(&det) ;
01140         if (det==0) {
01141           coutE(Fitting) << "RooAbsPdf::fitTo(" << GetName() 
01142                          << ") ERROR: Cannot apply sum-of-weights correction to covariance matrix: correction matrix calculated with weight-squared is singular" <<endl ;
01143         } else {
01144           
01145           // Calculate corrected covariance matrix = V C-1 V
01146           TMatrixD VCV(V,TMatrixD::kMult,TMatrixD(C,TMatrixD::kMult,V)) ; 
01147           
01148           // Make matrix explicitly symmetric
01149           Int_t n = VCV.GetNrows() ;
01150           TMatrixDSym VCVsym(n) ;
01151           for (Int_t i=0 ; i<n ; i++) {
01152             for (Int_t j=i ; j<n ; j++) {
01153               if (i==j) {
01154                 VCVsym(i,j) = VCV(i,j) ;
01155               }
01156               if (i!=j) {
01157                 Double_t deltaRel = (VCV(i,j)-VCV(j,i))/sqrt(VCV(i,i)*VCV(j,j)) ;
01158                 if (fabs(deltaRel)>1e-3) {
01159                   coutW(Fitting) << "RooAbsPdf::fitTo(" << GetName() << ") WARNING: Corrected covariance matrix is not (completely) symmetric: V[" << i << "," << j << "] = " 
01160                                  << VCV(i,j) << " V[" << j << "," << i << "] = " << VCV(j,i) << " explicitly restoring symmetry by inserting average value" << endl ;
01161                 }
01162                 VCVsym(i,j) = (VCV(i,j)+VCV(j,i))/2 ;
01163               }
01164             }
01165           }
01166           
01167           // Propagate corrected errors to parameters objects
01168           m.applyCovarianceMatrix(VCVsym) ;
01169         }
01170         
01171         delete rw ;
01172         delete rw2 ;
01173       }
01174       
01175       if (minos) {
01176         // Evaluate errs with Minos
01177         if (minosSet) {
01178           m.minos(*minosSet) ;
01179         } else {
01180           m.minos() ;
01181         }
01182       }
01183       
01184       // Optionally return fit result
01185       if (doSave) {
01186         string name = Form("fitresult_%s_%s",GetName(),data.GetName()) ;
01187         string title = Form("Result of fit of p.d.f. %s to dataset %s",GetName(),data.GetName()) ;
01188         ret = m.save(name.c_str(),title.c_str()) ;
01189       } 
01190       
01191     }
01192     if (optConst) {
01193       m.optimizeConst(0) ;
01194     }
01195 
01196 #endif
01197 
01198   } else {
01199 
01200     RooMinuit m(*nll) ;
01201     
01202     m.setEvalErrorWall(doEEWall) ;
01203     if (doWarn==0) {
01204       m.setNoWarn() ;
01205     }
01206     
01207     m.setPrintEvalErrors(numee) ;
01208     if (plevel!=1) {
01209       m.setPrintLevel(plevel) ;
01210     }
01211     
01212     if (optConst) {
01213       // Activate constant term optimization
01214       m.optimizeConst(1) ;
01215     }
01216     
01217     if (fitOpt) {
01218       
01219       // Play fit options as historically defined
01220       ret = m.fit(fitOpt) ;
01221       
01222     } else {
01223       
01224       if (verbose) {
01225         // Activate verbose options
01226         m.setVerbose(1) ;
01227       }
01228       if (doTimer) {
01229         // Activate timer options
01230         m.setProfile(1) ;
01231       }
01232       
01233       if (strat!=1) {
01234         // Modify fit strategy
01235         m.setStrategy(strat) ;
01236       }
01237       
01238       if (initHesse) {
01239         // Initialize errors with hesse
01240         m.hesse() ;
01241       }
01242       
01243       // Minimize using migrad
01244       m.migrad() ;
01245       
01246       if (hesse) {
01247         // Evaluate errors with Hesse
01248         m.hesse() ;
01249       }
01250       
01251       if (doSumW2==1) {
01252         
01253         // Make list of RooNLLVar components of FCN
01254         list<RooNLLVar*> nllComponents ;
01255         RooArgSet* comps = nll->getComponents() ;
01256         RooAbsArg* arg ;
01257         TIterator* citer = comps->createIterator() ;
01258         while((arg=(RooAbsArg*)citer->Next())) {
01259           RooNLLVar* nllComp = dynamic_cast<RooNLLVar*>(arg) ;
01260           if (nllComp) {
01261             nllComponents.push_back(nllComp) ;
01262           }
01263         }
01264         delete citer ;
01265         delete comps ;  
01266         
01267         // Calculated corrected errors for weighted likelihood fits
01268         RooFitResult* rw = m.save() ;
01269         for (list<RooNLLVar*>::iterator iter1=nllComponents.begin() ; iter1!=nllComponents.end() ; iter1++) {
01270           (*iter1)->applyWeightSquared(kTRUE) ;
01271         }
01272         coutI(Fitting) << "RooAbsPdf::fitTo(" << GetName() << ") Calculating sum-of-weights-squared correction matrix for covariance matrix" << endl ;
01273         m.hesse() ;
01274         RooFitResult* rw2 = m.save() ;
01275         for (list<RooNLLVar*>::iterator iter2=nllComponents.begin() ; iter2!=nllComponents.end() ; iter2++) {
01276           (*iter2)->applyWeightSquared(kFALSE) ;
01277         }
01278         
01279         // Apply correction matrix
01280         const TMatrixDSym& V = rw->covarianceMatrix() ;
01281         TMatrixDSym  C = rw2->covarianceMatrix() ;
01282         
01283         // Invert C
01284         Double_t det(0) ;
01285         C.Invert(&det) ;
01286         if (det==0) {
01287           coutE(Fitting) << "RooAbsPdf::fitTo(" << GetName() 
01288                          << ") ERROR: Cannot apply sum-of-weights correction to covariance matrix: correction matrix calculated with weight-squared is singular" <<endl ;
01289         } else {
01290           
01291           // Calculate corrected covariance matrix = V C-1 V
01292           TMatrixD VCV(V,TMatrixD::kMult,TMatrixD(C,TMatrixD::kMult,V)) ; 
01293           
01294           // Make matrix explicitly symmetric
01295           Int_t n = VCV.GetNrows() ;
01296           TMatrixDSym VCVsym(n) ;
01297           for (Int_t i=0 ; i<n ; i++) {
01298             for (Int_t j=i ; j<n ; j++) {
01299               if (i==j) {
01300                 VCVsym(i,j) = VCV(i,j) ;
01301               }
01302               if (i!=j) {
01303                 Double_t deltaRel = (VCV(i,j)-VCV(j,i))/sqrt(VCV(i,i)*VCV(j,j)) ;
01304                 if (fabs(deltaRel)>1e-3) {
01305                   coutW(Fitting) << "RooAbsPdf::fitTo(" << GetName() << ") WARNING: Corrected covariance matrix is not (completely) symmetric: V[" << i << "," << j << "] = " 
01306                                  << VCV(i,j) << " V[" << j << "," << i << "] = " << VCV(j,i) << " explicitly restoring symmetry by inserting average value" << endl ;
01307                 }
01308                 VCVsym(i,j) = (VCV(i,j)+VCV(j,i))/2 ;
01309               }
01310             }
01311           }
01312           
01313           // Propagate corrected errors to parameters objects
01314           m.applyCovarianceMatrix(VCVsym) ;
01315         }
01316         
01317         delete rw ;
01318         delete rw2 ;
01319       }
01320       
01321       if (minos) {
01322         // Evaluate errs with Minos
01323         if (minosSet) {
01324           m.minos(*minosSet) ;
01325         } else {
01326           m.minos() ;
01327         }
01328       }
01329       
01330       // Optionally return fit result
01331       if (doSave) {
01332         string name = Form("fitresult_%s_%s",GetName(),data.GetName()) ;
01333         string title = Form("Result of fit of p.d.f. %s to dataset %s",GetName(),data.GetName()) ;
01334         ret = m.save(name.c_str(),title.c_str()) ;
01335       } 
01336       
01337     }
01338 
01339     if (optConst) {
01340       m.optimizeConst(0) ;
01341     }
01342     
01343   }
01344 
01345 
01346   
01347   // Cleanup
01348   delete nll ;
01349   return ret ;
01350 }
01351 
01352 
01353 
01354 //_____________________________________________________________________________
01355 RooFitResult* RooAbsPdf::chi2FitTo(RooDataHist& data, const RooLinkedList& cmdList) 
01356 {
01357   // Internal back-end function to steer chi2 fits
01358 
01359   // Select the pdf-specific commands 
01360   RooCmdConfig pc(Form("RooAbsPdf::chi2FitTo(%s)",GetName())) ;
01361 
01362   // Pull arguments to be passed to chi2 construction from list
01363   RooLinkedList fitCmdList(cmdList) ;
01364   RooLinkedList chi2CmdList = pc.filterCmdList(fitCmdList,"Range,RangeWithName,NumCPU,Optimize,ProjectedObservables,AddCoefRange,SplitRange") ;
01365 
01366   RooAbsReal* chi2 = createChi2(data,chi2CmdList) ;
01367   RooFitResult* ret = chi2FitDriver(*chi2,fitCmdList) ;
01368   
01369   // Cleanup
01370   delete chi2 ;
01371   return ret ;
01372 }
01373 
01374 
01375 
01376 
01377 //_____________________________________________________________________________
01378 RooAbsReal* RooAbsPdf::createChi2(RooDataHist& data, const RooCmdArg& arg1,  const RooCmdArg& arg2,  
01379                                    const RooCmdArg& arg3,  const RooCmdArg& arg4, const RooCmdArg& arg5,  
01380                                    const RooCmdArg& arg6,  const RooCmdArg& arg7, const RooCmdArg& arg8) 
01381 {
01382   // Create a chi-2 from a histogram and this function.
01383   //
01384   // The following named arguments are supported
01385   //
01386   //  Options to control construction of the chi^2
01387   //  ------------------------------------------
01388   //  Extended()   -- Use expected number of events of an extended p.d.f as normalization 
01389   //  DataError()  -- Choose between Poisson errors and Sum-of-weights errors
01390   //  NumCPU()     -- Activate parallel processing feature
01391   //  Range()      -- Fit only selected region
01392   //  SumCoefRange() -- Set the range in which to interpret the coefficients of RooAddPdf components 
01393   //  SplitRange() -- Fit range is split by index catory of simultaneous PDF
01394   //  ConditionalObservables() -- Define projected observables 
01395 
01396   string name = Form("chi2_%s_%s",GetName(),data.GetName()) ;
01397  
01398   return new RooChi2Var(name.c_str(),name.c_str(),*this,data,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
01399 }
01400 
01401 
01402 
01403 
01404 //_____________________________________________________________________________
01405 RooAbsReal* RooAbsPdf::createChi2(RooDataSet& data, const RooLinkedList& cmdList) 
01406 {
01407   // Internal back-end function to create a chi^2 from a p.d.f. and a dataset
01408 
01409   // Select the pdf-specific commands 
01410   RooCmdConfig pc(Form("RooAbsPdf::fitTo(%s)",GetName())) ;
01411 
01412   pc.defineInt("integrate","Integrate",0,0) ;
01413   pc.defineObject("yvar","YVar",0,0) ;
01414   
01415   // Process and check varargs 
01416   pc.process(cmdList) ;
01417   if (!pc.ok(kTRUE)) {
01418     return 0 ;
01419   }
01420 
01421   // Decode command line arguments 
01422   Bool_t integrate = pc.getInt("integrate") ;
01423   RooRealVar* yvar = (RooRealVar*) pc.getObject("yvar") ;
01424 
01425   string name = Form("chi2_%s_%s",GetName(),data.GetName()) ;
01426  
01427   if (yvar) {
01428     return new RooXYChi2Var(name.c_str(),name.c_str(),*this,data,*yvar,integrate) ;
01429   } else {
01430     return new RooXYChi2Var(name.c_str(),name.c_str(),*this,data,integrate) ;
01431   }  
01432 }
01433 
01434 
01435 
01436 
01437 //_____________________________________________________________________________
01438 void RooAbsPdf::printValue(ostream& os) const
01439 {
01440   // Print value of p.d.f, also print normalization integral that was last used, if any
01441 
01442   getVal() ;
01443 
01444   if (_norm) {
01445     os << evaluate() << "/" << _norm->getVal() ;
01446   } else {
01447     os << evaluate() ;
01448   }
01449 }
01450 
01451 
01452 
01453 //_____________________________________________________________________________
01454 void RooAbsPdf::printMultiline(ostream& os, Int_t contents, Bool_t verbose, TString indent) const
01455 {
01456   // Print multi line detailed information of this RooAbsPdf
01457 
01458   RooAbsReal::printMultiline(os,contents,verbose,indent);
01459   os << indent << "--- RooAbsPdf ---" << endl;
01460   os << indent << "Cached value = " << _value << endl ;
01461   if (_norm) {
01462     os << indent << " Normalization integral: " << endl ;
01463     TString moreIndent(indent) ; moreIndent.Append("   ") ;
01464     _norm->printStream(os,kName|kAddress|kTitle|kValue|kArgs,kSingleLine,moreIndent.Data()) ;
01465   }
01466 }
01467 
01468 
01469 
01470 //_____________________________________________________________________________
01471 RooAbsGenContext* RooAbsPdf::genContext(const RooArgSet &vars, const RooDataSet *prototype, 
01472                                         const RooArgSet* auxProto, Bool_t verbose) const 
01473 {
01474   // Interface function to create a generator context from a p.d.f. This default
01475   // implementation returns a 'standard' context that works for any p.d.f
01476   return new RooGenContext(*this,vars,prototype,auxProto,verbose) ;
01477 }
01478 
01479 
01480 
01481 //_____________________________________________________________________________
01482 RooDataSet *RooAbsPdf::generate(const RooArgSet& whatVars, Int_t nEvents, const RooCmdArg& arg1,
01483                                 const RooCmdArg& arg2, const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5) 
01484 {
01485   // Generate a new dataset containing the specified variables with events sampled from our distribution. 
01486   // Generate the specified number of events or expectedEvents() if not specified.
01487   //
01488   // Any variables of this PDF that are not in whatVars will use their
01489   // current values and be treated as fixed parameters. Returns zero
01490   // in case of an error. The caller takes ownership of the returned
01491   // dataset.
01492   //
01493   // The following named arguments are supported
01494   //
01495   // Name(const char* name)             -- Name of the output dataset
01496   // Verbose(Bool_t flag)               -- Print informational messages during event generation
01497   // Extended()                         -- The actual number of events generated will be sampled from a Poisson distribution
01498   //                                       with mu=nevt. For use with extended maximum likelihood fits
01499   // ProtoData(const RooDataSet& data,  -- Use specified dataset as prototype dataset. If randOrder is set to true
01500   //                 Bool_t randOrder)     the order of the events in the dataset will be read in a random order
01501   //                                       if the requested number of events to be generated does not match the
01502   //                                       number of events in the prototype dataset
01503   //                                        
01504   // If ProtoData() is used, the specified existing dataset as a prototype: the new dataset will contain 
01505   // the same number of events as the prototype (unless otherwise specified), and any prototype variables not in
01506   // whatVars will be copied into the new dataset for each generated event and also used to set our PDF parameters. 
01507   // The user can specify a  number of events to generate that will override the default. The result is a
01508   // copy of the prototype dataset with only variables in whatVars randomized. Variables in whatVars that 
01509   // are not in the prototype will be added as new columns to the generated dataset.  
01510   return generate(whatVars,RooFit::NumEvents(nEvents),arg1,arg2,arg3,arg4,arg5) ;
01511 }
01512 
01513 
01514 
01515 //_____________________________________________________________________________
01516 RooDataSet *RooAbsPdf::generate(const RooArgSet& whatVars, const RooCmdArg& arg1,const RooCmdArg& arg2,
01517                                 const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6) 
01518 {
01519   // Generate a new dataset containing the specified variables with events sampled from our distribution. 
01520   // Generate the specified number of events or expectedEvents() if not specified.
01521   //
01522   // Any variables of this PDF that are not in whatVars will use their
01523   // current values and be treated as fixed parameters. Returns zero
01524   // in case of an error. The caller takes ownership of the returned
01525   // dataset.
01526   //
01527   // The following named arguments are supported
01528   //
01529   // Name(const char* name)             -- Name of the output dataset
01530   // Verbose(Bool_t flag)               -- Print informational messages during event generation
01531   // NumEvent(int nevt)                 -- Generate specified number of events
01532   // Extended()                         -- The actual number of events generated will be sampled from a Poisson distribution
01533   //                                       with mu=nevt. For use with extended maximum likelihood fits
01534   // ProtoData(const RooDataSet& data,  -- Use specified dataset as prototype dataset. If randOrder is set to true
01535   //                 Bool_t randOrder,     the order of the events in the dataset will be read in a random order
01536   //                 Bool_t resample)      if the requested number of events to be generated does not match the
01537   //                                       number of events in the prototype dataset. If resample is also set to 
01538   //                                       true, the prototype dataset will be resampled rather than be strictly
01539   //                                       reshuffled. In this mode events of the protodata may be used more than
01540   //                                       once.
01541   //
01542   // If ProtoData() is used, the specified existing dataset as a prototype: the new dataset will contain 
01543   // the same number of events as the prototype (unless otherwise specified), and any prototype variables not in
01544   // whatVars will be copied into the new dataset for each generated event and also used to set our PDF parameters. 
01545   // The user can specify a  number of events to generate that will override the default. The result is a
01546   // copy of the prototype dataset with only variables in whatVars randomized. Variables in whatVars that 
01547   // are not in the prototype will be added as new columns to the generated dataset.  
01548 
01549   // Select the pdf-specific commands 
01550   RooCmdConfig pc(Form("RooAbsPdf::generate(%s)",GetName())) ;
01551   pc.defineObject("proto","PrototypeData",0,0) ;
01552   pc.defineString("dsetName","Name",0,"") ;
01553   pc.defineInt("randProto","PrototypeData",0,0) ;
01554   pc.defineInt("resampleProto","PrototypeData",1,0) ;
01555   pc.defineInt("verbose","Verbose",0,0) ;
01556   pc.defineInt("extended","Extended",0,0) ;
01557   pc.defineInt("nEvents","NumEvents",0,0) ;
01558   
01559   
01560   // Process and check varargs 
01561   pc.process(arg1,arg2,arg3,arg4,arg5,arg6) ;
01562   if (!pc.ok(kTRUE)) {
01563     return 0 ;
01564   }
01565 
01566   // Decode command line arguments
01567   RooDataSet* protoData = static_cast<RooDataSet*>(pc.getObject("proto",0)) ;
01568   const char* dsetName = pc.getString("dsetName") ;
01569   Int_t nEvents = pc.getInt("nEvents") ;
01570   Bool_t verbose = pc.getInt("verbose") ;
01571   Bool_t randProto = pc.getInt("randProto") ;
01572   Bool_t resampleProto = pc.getInt("resampleProto") ;
01573   Bool_t extended = pc.getInt("extended") ;
01574 
01575   if (extended) {
01576     nEvents = RooRandom::randomGenerator()->Poisson(nEvents==0?expectedEvents(&whatVars):nEvents) ;
01577     cxcoutI(Generation) << " Extended mode active, number of events generated (" << nEvents << ") is Poisson fluctuation on " 
01578                           << GetName() << "::expectedEvents() = " << nEvents << endl ;
01579     // If Poisson fluctuation results in zero events, stop here
01580     if (nEvents==0) {
01581       return new RooDataSet("emptyData","emptyData",whatVars) ;
01582     }
01583   } else if (nEvents==0) {
01584     cxcoutI(Generation) << "No number of events specified , number of events generated is " 
01585                           << GetName() << "::expectedEvents() = " << expectedEvents(&whatVars)<< endl ;
01586   }
01587 
01588   if (extended && protoData && !randProto) {
01589     cxcoutI(Generation) << "WARNING Using generator option Extended() (Poisson distribution of #events) together "
01590                           << "with a prototype dataset implies incomplete sampling or oversampling of proto data. " 
01591                           << "Set randomize flag in ProtoData() option to randomize prototype dataset order and thus "
01592                           << "to randomize the set of over/undersampled prototype events for each generation cycle." << endl ;
01593   }
01594 
01595 
01596   // Forward to appropiate implementation
01597   RooDataSet* data ;
01598   if (protoData) {
01599     data = generate(whatVars,*protoData,nEvents,verbose,randProto,resampleProto) ;
01600   } else {
01601     data = generate(whatVars,nEvents,verbose) ;
01602   }
01603 
01604   // Rename dataset to given name if supplied
01605   if (dsetName && strlen(dsetName)>0) {
01606     data->SetName(dsetName) ;
01607   }
01608 
01609   return data ;
01610 }
01611 
01612 
01613 
01614 
01615 
01616 //_____________________________________________________________________________
01617 RooAbsPdf::GenSpec* RooAbsPdf::prepareMultiGen(const RooArgSet &whatVars,  
01618                                                const RooCmdArg& arg1,const RooCmdArg& arg2,
01619                                                const RooCmdArg& arg3,const RooCmdArg& arg4,
01620                                                const RooCmdArg& arg5,const RooCmdArg& arg6) 
01621 {
01622   // Prepare GenSpec configuration object for efficient generation of multiple datasets from idetical specification
01623   // This method does not perform any generation. To generate according to generations specification call RooAbsPdf::generate(RooAbsPdf::GenSpec&)
01624   //
01625   // Generate the specified number of events or expectedEvents() if not specified.
01626   //
01627   // Any variables of this PDF that are not in whatVars will use their
01628   // current values and be treated as fixed parameters. Returns zero
01629   // in case of an error. The caller takes ownership of the returned
01630   // dataset.
01631   //
01632   // The following named arguments are supported
01633   //
01634   // Name(const char* name)             -- Name of the output dataset
01635   // Verbose(Bool_t flag)               -- Print informational messages during event generation
01636   // NumEvent(int nevt)                 -- Generate specified number of events
01637   // Extended()                         -- The actual number of events generated will be sampled from a Poisson distribution
01638   //                                       with mu=nevt. For use with extended maximum likelihood fits
01639   // ProtoData(const RooDataSet& data,  -- Use specified dataset as prototype dataset. If randOrder is set to true
01640   //                 Bool_t randOrder,     the order of the events in the dataset will be read in a random order
01641   //                 Bool_t resample)      if the requested number of events to be generated does not match the
01642   //                                       number of events in the prototype dataset. If resample is also set to 
01643   //                                       true, the prototype dataset will be resampled rather than be strictly
01644   //                                       reshuffled. In this mode events of the protodata may be used more than
01645   //                                       once.
01646   //
01647   // If ProtoData() is used, the specified existing dataset as a prototype: the new dataset will contain 
01648   // the same number of events as the prototype (unless otherwise specified), and any prototype variables not in
01649   // whatVars will be copied into the new dataset for each generated event and also used to set our PDF parameters. 
01650   // The user can specify a  number of events to generate that will override the default. The result is a
01651   // copy of the prototype dataset with only variables in whatVars randomized. Variables in whatVars that 
01652   // are not in the prototype will be added as new columns to the generated dataset.  
01653 
01654   // Select the pdf-specific commands 
01655   RooCmdConfig pc(Form("RooAbsPdf::generate(%s)",GetName())) ;
01656   pc.defineObject("proto","PrototypeData",0,0) ;
01657   pc.defineString("dsetName","Name",0,"") ;
01658   pc.defineInt("randProto","PrototypeData",0,0) ;
01659   pc.defineInt("resampleProto","PrototypeData",1,0) ;
01660   pc.defineInt("verbose","Verbose",0,0) ;
01661   pc.defineInt("extended","Extended",0,0) ;
01662   pc.defineInt("nEvents","NumEvents",0,0) ;
01663   
01664   
01665   // Process and check varargs 
01666   pc.process(arg1,arg2,arg3,arg4,arg5,arg6) ;
01667   if (!pc.ok(kTRUE)) {
01668     return 0 ;
01669   }
01670 
01671   // Decode command line arguments
01672   RooDataSet* protoData = static_cast<RooDataSet*>(pc.getObject("proto",0)) ;
01673   const char* dsetName = pc.getString("dsetName") ;
01674   Int_t nEvents = pc.getInt("nEvents") ;
01675   Bool_t verbose = pc.getInt("verbose") ;
01676   Bool_t randProto = pc.getInt("randProto") ;
01677   Bool_t resampleProto = pc.getInt("resampleProto") ;
01678   Bool_t extended = pc.getInt("extended") ;
01679 
01680   return new GenSpec(genContext(whatVars,protoData,0,verbose),whatVars,protoData,nEvents,extended,randProto,resampleProto,dsetName) ;  
01681 }
01682 
01683 
01684 //_____________________________________________________________________________
01685 RooDataSet *RooAbsPdf::generate(RooAbsPdf::GenSpec& spec) const
01686 {
01687   // Generate data according to a pre-configured specification created by
01688   // RooAbsPdf::prepareMultiGen(). If many identical generation requests
01689   // are needed, e.g. in toy MC studies, it is more efficient to use the prepareMultiGen()/generate()
01690   // combination than calling the standard generate() multiple times as 
01691   // initialization overhead is only incurred once.
01692 
01693   Int_t nEvt = spec._extended ? RooRandom::randomGenerator()->Poisson(spec._nGen) : spec._nGen ;
01694 
01695   return generate(*spec._genContext,spec._whatVars,spec._protoData,
01696                   nEvt,kFALSE,spec._randProto,spec._resampleProto) ;
01697 }
01698 
01699 
01700 
01701 
01702 
01703 //_____________________________________________________________________________
01704 RooDataSet *RooAbsPdf::generate(const RooArgSet &whatVars, Int_t nEvents, Bool_t verbose) const 
01705 {
01706   // Generate a new dataset containing the specified variables with
01707   // events sampled from our distribution. Generate the specified
01708   // number of events or else try to use expectedEvents() if nEvents <= 0.
01709   // Any variables of this PDF that are not in whatVars will use their
01710   // current values and be treated as fixed parameters. Returns zero
01711   // in case of an error. The caller takes ownership of the returned
01712   // dataset.
01713 
01714   if (nEvents==0 && extendMode()==CanNotBeExtended) {
01715     return new RooDataSet("emptyData","emptyData",whatVars) ;
01716   }
01717 
01718   RooDataSet *generated = 0;
01719   RooAbsGenContext *context= genContext(whatVars,0,0,verbose);
01720   if(0 != context && context->isValid()) {
01721     generated= context->generate(nEvents);
01722   }
01723   else {
01724     coutE(Generation)  << "RooAbsPdf::generate(" << GetName() << ") cannot create a valid context" << endl;
01725   }
01726   if(0 != context) delete context;
01727   return generated;
01728 }
01729 
01730 
01731 
01732 
01733 //_____________________________________________________________________________
01734 RooDataSet *RooAbsPdf::generate(RooAbsGenContext& context, const RooArgSet &whatVars, const RooDataSet *prototype,
01735                                 Int_t nEvents, Bool_t /*verbose*/, Bool_t randProtoOrder, Bool_t resampleProto) const 
01736 {
01737   // Internal method  
01738   if (nEvents==0 && (prototype==0 || prototype->numEntries()==0)) {
01739     return new RooDataSet("emptyData","emptyData",whatVars) ;
01740   }
01741 
01742 
01743   RooDataSet *generated = 0;
01744 
01745   // Resampling implies reshuffling in the implementation
01746   if (resampleProto) {
01747     randProtoOrder=kTRUE ;
01748   }
01749 
01750   if (randProtoOrder && prototype && prototype->numEntries()!=nEvents) {
01751     coutI(Generation) << "RooAbsPdf::generate (Re)randomizing event order in prototype dataset (Nevt=" << nEvents << ")" << endl ;
01752     Int_t* newOrder = randomizeProtoOrder(prototype->numEntries(),nEvents,resampleProto) ;
01753     context.setProtoDataOrder(newOrder) ;
01754     delete[] newOrder ;
01755   }
01756 
01757   if(context.isValid()) {
01758     generated= context.generate(nEvents);
01759   }
01760   else {
01761     coutE(Generation) << "RooAbsPdf::generate(" << GetName() << ") do not have a valid generator context" << endl;
01762   }
01763   return generated;
01764 }
01765 
01766 
01767 
01768 
01769 //_____________________________________________________________________________
01770 RooDataSet *RooAbsPdf::generate(const RooArgSet &whatVars, const RooDataSet& prototype,
01771                                 Int_t nEvents, Bool_t verbose, Bool_t randProtoOrder, Bool_t resampleProto) const 
01772 {
01773   // Generate a new dataset with values of the whatVars variables
01774   // sampled from our distribution. Use the specified existing dataset
01775   // as a prototype: the new dataset will contain the same number of
01776   // events as the prototype (by default), and any prototype variables not in
01777   // whatVars will be copied into the new dataset for each generated
01778   // event and also used to set our PDF parameters. The user can specify a
01779   // number of events to generate that will override the default. The result is a
01780   // copy of the prototype dataset with only variables in whatVars
01781   // randomized. Variables in whatVars that are not in the prototype
01782   // will be added as new columns to the generated dataset.  Returns
01783   // zero in case of an error. The caller takes ownership of the
01784   // returned dataset.
01785 
01786   RooAbsGenContext *context= genContext(whatVars,&prototype,0,verbose);
01787   if (context) {
01788     RooDataSet* data =  generate(*context,whatVars,&prototype,nEvents,verbose,randProtoOrder,resampleProto) ;
01789     delete context ;
01790     return data ;
01791   } else {
01792     coutE(Generation) << "RooAbsPdf::generate(" << GetName() << ") ERROR creating generator context" << endl ;
01793     return 0 ;
01794   }
01795 }
01796 
01797 
01798 
01799 //_____________________________________________________________________________
01800 Int_t* RooAbsPdf::randomizeProtoOrder(Int_t nProto, Int_t, Bool_t resampleProto) const
01801 {
01802   // Return lookup table with randomized access order for prototype events,
01803   // given nProto prototype data events and nGen events that will actually
01804   // be accessed
01805 
01806   // Make unsorted linked list of indeces
01807   RooLinkedList l ;
01808   Int_t i ;
01809   for (i=0 ; i<nProto ; i++) {
01810     l.Add(new RooInt(i)) ;
01811   }
01812 
01813   // Make output list
01814   Int_t* lut = new Int_t[nProto] ;
01815 
01816   // Randomly samply input list into output list
01817   if (!resampleProto) {
01818     // In this mode, randomization is a strict reshuffle of the order
01819     for (i=0 ; i<nProto ; i++) {
01820       Int_t iran = RooRandom::integer(nProto-i) ;
01821       RooInt* sample = (RooInt*) l.At(iran) ;
01822       lut[i] = *sample ;
01823       l.Remove(sample) ;
01824       delete sample ;
01825     }
01826   } else {
01827     // In this mode, we resample, i.e. events can be used more than once
01828     for (i=0 ; i<nProto ; i++) {
01829       lut[i] = RooRandom::integer(nProto);
01830     }
01831   }
01832 
01833 
01834   return lut ;
01835 }
01836 
01837 
01838 
01839 //_____________________________________________________________________________
01840 Int_t RooAbsPdf::getGenerator(const RooArgSet &/*directVars*/, RooArgSet &/*generatedVars*/, Bool_t /*staticInitOK*/) const 
01841 {
01842   // Load generatedVars with the subset of directVars that we can generate events for,
01843   // and return a code that specifies the generator algorithm we will use. A code of
01844   // zero indicates that we cannot generate any of the directVars (in this case, nothing
01845   // should be added to generatedVars). Any non-zero codes will be passed to our generateEvent()
01846   // implementation, but otherwise its value is arbitrary. The default implemetation of
01847   // this method returns zero. Subclasses will usually implement this method using the
01848   // matchArgs() methods to advertise the algorithms they provide.
01849 
01850 
01851   return 0 ;
01852 }
01853 
01854 
01855 
01856 //_____________________________________________________________________________
01857 void RooAbsPdf::initGenerator(Int_t /*code*/) 
01858 {  
01859   // Interface for one-time initialization to setup the generator for the specified code.
01860 }
01861 
01862 
01863 
01864 //_____________________________________________________________________________
01865 void RooAbsPdf::generateEvent(Int_t /*code*/) 
01866 {
01867   // Interface for generation of anan event using the algorithm
01868   // corresponding to the specified code. The meaning of each code is
01869   // defined by the getGenerator() implementation. The default
01870   // implementation does nothing.
01871 }
01872 
01873 
01874 
01875 //_____________________________________________________________________________
01876 Bool_t RooAbsPdf::isDirectGenSafe(const RooAbsArg& arg) const 
01877 {
01878   // Check if given observable can be safely generated using the
01879   // pdfs internal generator mechanism (if that existsP). Observables
01880   // on which a PDF depends via more than route are not safe
01881   // for use with internal generators because they introduce
01882   // correlations not known to the internal generator
01883 
01884   // Arg must be direct server of self
01885   if (!findServer(arg.GetName())) return kFALSE ;
01886 
01887   // There must be no other dependency routes
01888   TIterator* sIter = serverIterator() ;
01889   const RooAbsArg *server = 0;
01890   while((server=(const RooAbsArg*)sIter->Next())) {
01891     if(server == &arg) continue;
01892     if(server->dependsOn(arg)) {
01893       delete sIter ;
01894       return kFALSE ;
01895     }
01896   }
01897   delete sIter ;
01898   return kTRUE ;
01899 }
01900 
01901 
01902 
01903 
01904 //_____________________________________________________________________________
01905 RooDataHist *RooAbsPdf::generateBinned(const RooArgSet& whatVars, Double_t nEvents, const RooCmdArg& arg1,
01906                                        const RooCmdArg& arg2, const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5) 
01907 {
01908   // Generate a new dataset containing the specified variables with events sampled from our distribution. 
01909   // Generate the specified number of events or expectedEvents() if not specified.
01910   //
01911   // Any variables of this PDF that are not in whatVars will use their
01912   // current values and be treated as fixed parameters. Returns zero
01913   // in case of an error. The caller takes ownership of the returned
01914   // dataset.
01915   //
01916   // The following named arguments are supported
01917   //
01918   // Name(const char* name)             -- Name of the output dataset
01919   // Verbose(Bool_t flag)               -- Print informational messages during event generation
01920   // Extended()                         -- The actual number of events generated will be sampled from a Poisson distribution
01921   //                                       with mu=nevt. For use with extended maximum likelihood fits
01922   // ExpectedData()                     -- Return a binned dataset _without_ statistical fluctuations (also aliased as Asimov())
01923   return generateBinned(whatVars,RooFit::NumEvents(nEvents),arg1,arg2,arg3,arg4,arg5) ;
01924 }
01925 
01926 
01927 
01928 //_____________________________________________________________________________
01929 RooDataHist *RooAbsPdf::generateBinned(const RooArgSet& whatVars, const RooCmdArg& arg1,const RooCmdArg& arg2,
01930                                        const RooCmdArg& arg3,const RooCmdArg& arg4, const RooCmdArg& arg5,const RooCmdArg& arg6) 
01931 {
01932   // Generate a new dataset containing the specified variables with events sampled from our distribution. 
01933   // Generate the specified number of events or expectedEvents() if not specified.
01934   //
01935   // Any variables of this PDF that are not in whatVars will use their
01936   // current values and be treated as fixed parameters. Returns zero
01937   // in case of an error. The caller takes ownership of the returned
01938   // dataset.
01939   //
01940   // The following named arguments are supported
01941   //
01942   // Name(const char* name)             -- Name of the output dataset
01943   // Verbose(Bool_t flag)               -- Print informational messages during event generation
01944   // NumEvent(int nevt)                 -- Generate specified number of events
01945   // Extended()                         -- The actual number of events generated will be sampled from a Poisson distribution
01946   //                                       with mu=nevt. For use with extended maximum likelihood fits
01947   // ExpectedData()                     -- Return a binned dataset _without_ statistical fluctuations (also aliased as Asimov())
01948   
01949 
01950   // Select the pdf-specific commands 
01951   RooCmdConfig pc(Form("RooAbsPdf::generate(%s)",GetName())) ;
01952   pc.defineString("dsetName","Name",0,"") ;
01953   pc.defineInt("verbose","Verbose",0,0) ;
01954   pc.defineInt("extended","Extended",0,0) ;
01955   pc.defineInt("nEvents","NumEvents",0,0) ;
01956   pc.defineDouble("nEventsD","NumEventsD",0,-1.) ;
01957   pc.defineInt("expectedData","ExpectedData",0,0) ;
01958   
01959   // Process and check varargs 
01960   pc.process(arg1,arg2,arg3,arg4,arg5,arg6) ;
01961   if (!pc.ok(kTRUE)) {
01962     return 0 ;
01963   }
01964 
01965   // Decode command line arguments
01966   Double_t nEvents = pc.getDouble("nEventsD") ;
01967   if (nEvents<0) {
01968     nEvents = pc.getInt("nEvents") ;
01969   }
01970   //Bool_t verbose = pc.getInt("verbose") ;
01971   Bool_t extended = pc.getInt("extended") ;
01972   Bool_t expectedData = pc.getInt("expectedData") ;
01973   const char* dsetName = pc.getString("dsetName") ;
01974 
01975   if (extended) {
01976     nEvents = (nEvents==0?Int_t(expectedEvents(&whatVars)+0.5):nEvents) ;
01977     cxcoutI(Generation) << " Extended mode active, number of events generated (" << nEvents << ") is Poisson fluctuation on " 
01978                         << GetName() << "::expectedEvents() = " << nEvents << endl ;
01979     // If Poisson fluctuation results in zero events, stop here
01980     if (nEvents==0) {
01981       return 0 ;
01982     }
01983   } else if (nEvents==0) {
01984     cxcoutI(Generation) << "No number of events specified , number of events generated is " 
01985                         << GetName() << "::expectedEvents() = " << expectedEvents(&whatVars)<< endl ;
01986   }
01987 
01988   // Forward to appropiate implementation
01989   RooDataHist* data = generateBinned(whatVars,nEvents,expectedData,extended) ;
01990 
01991   // Rename dataset to given name if supplied
01992   if (dsetName && strlen(dsetName)>0) {
01993     data->SetName(dsetName) ;
01994   }
01995 
01996   return data ;
01997 }
01998 
01999 
02000 
02001 
02002 //_____________________________________________________________________________
02003 RooDataHist *RooAbsPdf::generateBinned(const RooArgSet &whatVars, Double_t nEvents, Bool_t expectedData, Bool_t extended) const 
02004 {
02005   // Generate a new dataset containing the specified variables with
02006   // events sampled from our distribution. Generate the specified
02007   // number of events or else try to use expectedEvents() if nEvents <= 0.
02008   //
02009   // If expectedData is kTRUE (it is kFALSE by default), the returned histogram returns the 'expected'
02010   // data sample, i.e. no statistical fluctuations are present.
02011   //
02012   // Any variables of this PDF that are not in whatVars will use their
02013   // current values and be treated as fixed parameters. Returns zero
02014   // in case of an error. The caller takes ownership of the returned
02015   // dataset.
02016 
02017   // Create empty RooDataHist
02018   RooDataHist* hist = new RooDataHist("genData","genData",whatVars) ;
02019 
02020   // Scale to number of events and introduce Poisson fluctuations
02021   if (nEvents<=0) {
02022     if (!canBeExtended()) {
02023       coutE(InputArguments) << "RooAbsPdf::generateBinned(" << GetName() << ") ERROR: No event count provided and p.d.f does not provide expected number of events" << endl ;
02024       delete hist ;
02025       return 0 ;
02026     } else {
02027       // Don't round in expectedData mode
02028       if (expectedData) {
02029         nEvents = expectedEvents(&whatVars) ;
02030       } else {
02031         nEvents = Int_t(expectedEvents(&whatVars)+0.5) ;
02032       }
02033     }
02034   } 
02035   
02036   // Sample p.d.f. distribution
02037   fillDataHist(hist,&whatVars,1,kTRUE) ;  
02038 
02039   vector<int> histOut(hist->numEntries()) ;
02040   Double_t histMax(-1) ;
02041   Int_t histOutSum(0) ;
02042   for (int i=0 ; i<hist->numEntries() ; i++) {
02043     hist->get(i) ;
02044     if (expectedData) {
02045 
02046       // Expected data, multiply p.d.f by nEvents
02047       Double_t w=hist->weight()*nEvents ;
02048       hist->set(w,sqrt(w)) ;
02049 
02050     } else if (extended) {
02051 
02052       // Extended mode, set contents to Poisson(pdf*nEvents)
02053       Double_t w = RooRandom::randomGenerator()->Poisson(hist->weight()*nEvents) ;
02054       hist->set(w,sqrt(w)) ;
02055 
02056     } else {
02057 
02058       // Regular mode, fill array of weights with Poisson(pdf*nEvents), but to not fill
02059       // histogram yet.
02060       if (hist->weight()>histMax) {
02061         histMax = hist->weight() ;
02062       }
02063       histOut[i] = RooRandom::randomGenerator()->Poisson(hist->weight()*nEvents) ;
02064       histOutSum += histOut[i] ;
02065     }
02066   }
02067 
02068 
02069   if (!expectedData && !extended) {
02070 
02071     // Second pass for regular mode - Trim/Extend dataset to exact number of entries
02072 
02073     // Calculate difference between what is generated so far and what is requested
02074     Int_t nEvtExtra = abs(Int_t(nEvents)-histOutSum) ;
02075     Int_t wgt = (histOutSum>nEvents) ? -1 : 1 ;
02076 
02077     // Perform simple binned accept/reject procedure to get to exact event count
02078     while(nEvtExtra>0) {
02079 
02080       Int_t ibinRand = RooRandom::randomGenerator()->Integer(hist->numEntries()) ;
02081       hist->get(ibinRand) ;
02082       Double_t ranY = RooRandom::randomGenerator()->Uniform(histMax) ;
02083 
02084       if (ranY<hist->weight()) {
02085         if (wgt==1) {
02086           histOut[ibinRand]++ ;
02087         } else {
02088           // If weight is negative, prior bin content must be at least 1
02089           if (histOut[ibinRand]>0) {
02090             histOut[ibinRand]-- ;
02091           } else {
02092             continue ;
02093           }
02094         }
02095         nEvtExtra-- ;
02096       }
02097     }
02098 
02099     // Transfer working array to histogram
02100     for (int i=0 ; i<hist->numEntries() ; i++) {
02101       hist->get(i) ;
02102       hist->set(histOut[i],sqrt(1.0*histOut[i])) ;
02103     }    
02104 
02105   } else if (expectedData) {
02106 
02107     // Second pass for expectedData mode -- Normalize to exact number of requested events
02108     // Minor difference may be present in first round due to difference between 
02109     // bin average and bin integral in sampling bins
02110     Double_t corr = nEvents/hist->sumEntries() ;
02111     for (int i=0 ; i<hist->numEntries() ; i++) {
02112       hist->get(i) ;
02113       hist->set(hist->weight()*corr,sqrt(hist->weight()*corr)) ;
02114     }
02115 
02116   }
02117 
02118   return hist;
02119 }
02120 
02121 
02122 
02123 //_____________________________________________________________________________
02124 RooPlot* RooAbsPdf::plotOn(RooPlot* frame, RooLinkedList& cmdList) const
02125 {
02126   // Plot (project) PDF on specified frame. If a PDF is plotted in an empty frame, it
02127   // will show a unit normalized curve in the frame variable, taken at the present value 
02128   // of other observables defined for this PDF
02129   //
02130   // If a PDF is plotted in a frame in which a dataset has already been plotted, it will
02131   // show a projected curve integrated over all variables that were present in the shown
02132   // dataset except for the one on the x-axis. The normalization of the curve will also
02133   // be adjusted to the event count of the plotted dataset. An informational message
02134   // will be printed for each projection step that is performed
02135   //
02136   // This function takes the following named arguments
02137   //
02138   // Projection control
02139   // ------------------
02140   // Slice(const RooArgSet& set)     -- Override default projection behaviour by omittting observables listed 
02141   //                                    in set from the projection, resulting a 'slice' plot. Slicing is usually
02142   //                                    only sensible in discrete observables
02143   // Project(const RooArgSet& set)   -- Override default projection behaviour by projecting over observables
02144   //                                    given in set and complete ignoring the default projection behavior. Advanced use only.
02145   // ProjWData(const RooAbsData& d)  -- Override default projection _technique_ (integration). For observables present in given dataset
02146   //                                    projection of PDF is achieved by constructing an average over all observable values in given set.
02147   //                                    Consult RooFit plotting tutorial for further explanation of meaning & use of this technique
02148   // ProjWData(const RooArgSet& s,   -- As above but only consider subset 's' of observables in dataset 'd' for projection through data averaging
02149   //           const RooAbsData& d)
02150   // ProjectionRange(const char* rn) -- Override default range of projection integrals to a different range speficied by given range name.
02151   //                                    This technique allows you to project a finite width slice in a real-valued observable
02152   // NormRange(const char* name)     -- Calculate curve normalization w.r.t. only in specified ranges. NB: A Range() by default implies a NormRange()
02153   //                                    on the same range, but this option allows to override the default, or specify a normalization ranges
02154   //                                    when the full curve is to be drawn
02155   // 
02156   // Misc content control
02157   // --------------------
02158   // Normalization(Double_t scale,   -- Adjust normalization by given scale factor. Interpretation of number depends on code: Relative:
02159   //                ScaleType code)     relative adjustment factor, NumEvent: scale to match given number of events.
02160   // Name(const chat* name)          -- Give curve specified name in frame. Useful if curve is to be referenced later
02161   // Asymmetry(const RooCategory& c) -- Show the asymmetry of the PDF in given two-state category [F(+)-F(-)] / [F(+)+F(-)] rather than
02162   //                                    the PDF projection. Category must have two states with indices -1 and +1 or three states with
02163   //                                    indeces -1,0 and +1.
02164   // ShiftToZero(Bool_t flag)        -- Shift entire curve such that lowest visible point is at exactly zero. Mostly useful when
02165   //                                    plotting -log(L) or chi^2 distributions
02166   // AddTo(const char* name,         -- Add constructed projection to already existing curve with given name and relative weight factors
02167   //       double_t wgtSelf, double_t wgtOther)
02168   //
02169   // Plotting control 
02170   // ----------------
02171   // LineStyle(Int_t style)          -- Select line style by ROOT line style code, default is solid
02172   // LineColor(Int_t color)          -- Select line color by ROOT color code, default is blue
02173   // LineWidth(Int_t width)          -- Select line with in pixels, default is 3
02174   // FillStyle(Int_t style)          -- Select fill style, default is not filled. If a filled style is selected, also use VLines()
02175   //                                    to add vertical downward lines at end of curve to ensure proper closure
02176   // FillColor(Int_t color)          -- Select fill color by ROOT color code
02177   // Range(const char* name)         -- Only draw curve in range defined by given name
02178   // Range(double lo, double hi)     -- Only draw curve in specified range
02179   // VLines()                        -- Add vertical lines to y=0 at end points of curve
02180   // Precision(Double_t eps)         -- Control precision of drawn curve w.r.t to scale of plot, default is 1e-3. Higher precision
02181   //                                    will result in more and more densely spaced curve points
02182   // Invisble(Bool_t flag)           -- Add curve to frame, but do not display. Useful in combination AddTo()
02183 
02184 
02185   // Pre-processing if p.d.f. contains a fit range and there is no command specifying one,
02186   // add a fit range as default range
02187   RooCmdArg* plotRange(0) ;
02188   RooCmdArg* normRange2(0) ;  
02189   if (getStringAttribute("fitrange") && !cmdList.FindObject("Range") && 
02190       !cmdList.FindObject("RangeWithName")) {
02191     plotRange = (RooCmdArg*) RooFit::Range(getStringAttribute("fitrange")).Clone() ;    
02192     cmdList.Add(plotRange) ;
02193   }
02194 
02195   if (getStringAttribute("fitrange") && !cmdList.FindObject("NormRange")) {
02196     normRange2 = (RooCmdArg*) RooFit::NormRange(getStringAttribute("fitrange")).Clone() ;    
02197     cmdList.Add(normRange2) ;
02198   }
02199 
02200   if (plotRange || normRange2) {
02201     coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") p.d.f was fitted in range and no explicit " 
02202                     << (plotRange?"plot":"") << ((plotRange&&normRange2)?",":"")
02203                     << (normRange2?"norm":"") << " range was specified, using fit range as default" << endl ;
02204   }
02205 
02206   // Sanity checks
02207   if (plotSanityChecks(frame)) return frame ;
02208 
02209   // Select the pdf-specific commands 
02210   RooCmdConfig pc(Form("RooAbsPdf::plotOn(%s)",GetName())) ;
02211   pc.defineDouble("scaleFactor","Normalization",0,1.0) ;
02212   pc.defineInt("scaleType","Normalization",0,Relative) ;  
02213   pc.defineObject("compSet","SelectCompSet",0) ;
02214   pc.defineString("compSpec","SelectCompSpec",0) ;
02215   pc.defineObject("asymCat","Asymmetry",0) ;
02216   pc.defineDouble("rangeLo","Range",0,-999.) ;
02217   pc.defineDouble("rangeHi","Range",1,-999.) ;
02218   pc.defineString("rangeName","RangeWithName",0,"") ;
02219   pc.defineString("normRangeName","NormRange",0,"") ;
02220   pc.defineInt("rangeAdjustNorm","Range",0,0) ;
02221   pc.defineInt("rangeWNAdjustNorm","RangeWithName",0,0) ;
02222   pc.defineMutex("SelectCompSet","SelectCompSpec") ;
02223   pc.defineMutex("Range","RangeWithName") ;
02224   pc.allowUndefined() ; // unknowns may be handled by RooAbsReal
02225 
02226   // Process and check varargs 
02227   pc.process(cmdList) ;
02228   if (!pc.ok(kTRUE)) {
02229     return frame ;
02230   }
02231 
02232   // Decode command line arguments
02233   ScaleType stype = (ScaleType) pc.getInt("scaleType") ;
02234   Double_t scaleFactor = pc.getDouble("scaleFactor") ;
02235   const RooAbsCategoryLValue* asymCat = (const RooAbsCategoryLValue*) pc.getObject("asymCat") ;
02236   const char* compSpec = pc.getString("compSpec") ;
02237   const RooArgSet* compSet = (const RooArgSet*) pc.getObject("compSet") ;
02238   Bool_t haveCompSel = ( (compSpec && strlen(compSpec)>0) || compSet) ;
02239 
02240   // Suffix for curve name
02241   TString nameSuffix ;
02242   if (compSpec && strlen(compSpec)>0) {
02243     nameSuffix.Append("_Comp[") ;
02244     nameSuffix.Append(compSpec) ;
02245     nameSuffix.Append("]") ;    
02246   } else if (compSet) {
02247     nameSuffix.Append("_Comp[") ;
02248     nameSuffix.Append(compSet->contentsString().c_str()) ;
02249     nameSuffix.Append("]") ;    
02250   }
02251 
02252   // Remove PDF-only commands from command list
02253   pc.stripCmdList(cmdList,"SelectCompSet,SelectCompSpec") ;
02254   
02255   // Adjust normalization, if so requested
02256   if (asymCat) {
02257     RooCmdArg cnsuffix("CurveNameSuffix",0,0,0,0,nameSuffix.Data(),0,0,0) ;
02258     cmdList.Add(&cnsuffix);
02259     return  RooAbsReal::plotOn(frame,cmdList) ;
02260   }
02261 
02262   // More sanity checks
02263   Double_t nExpected(1) ;
02264   if (stype==RelativeExpected) {
02265     if (!canBeExtended()) {
02266       coutE(Plotting) << "RooAbsPdf::plotOn(" << GetName() 
02267                       << "): ERROR the 'Expected' scale option can only be used on extendable PDFs" << endl ;
02268       return frame ;
02269     }
02270     nExpected = expectedEvents(frame->getNormVars()) ;
02271   }
02272 
02273   if (stype != Raw) {    
02274 
02275     if (frame->getFitRangeNEvt() && stype==Relative) {
02276 
02277       Bool_t hasCustomRange(kFALSE), adjustNorm(kFALSE) ;
02278 
02279       list<pair<Double_t,Double_t> > rangeLim ;
02280 
02281       // Retrieve plot range to be able to adjust normalization to data
02282       if (pc.hasProcessed("Range")) {
02283 
02284         Double_t rangeLo = pc.getDouble("rangeLo") ;
02285         Double_t rangeHi = pc.getDouble("rangeHi") ;
02286         rangeLim.push_back(make_pair(rangeLo,rangeHi)) ;
02287         adjustNorm = pc.getInt("rangeAdjustNorm") ;
02288         hasCustomRange = kTRUE ;
02289 
02290         coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") only plotting range [" 
02291                         << rangeLo << "," << rangeHi << "]" ;
02292         if (!pc.hasProcessed("NormRange")) {      
02293           ccoutI(Plotting) << ", curve is normalized to data in " << (adjustNorm?"given":"full") << " given range" << endl ;
02294         } else {
02295           ccoutI(Plotting) << endl ;
02296         }
02297 
02298         nameSuffix.Append(Form("_Range[%f_%f]",rangeLo,rangeHi)) ;
02299 
02300       } else if (pc.hasProcessed("RangeWithName")) {    
02301 
02302         char tmp[1024] ;
02303         strlcpy(tmp,pc.getString("rangeName",0,kTRUE),1024) ;
02304         char* rangeNameToken = strtok(tmp,",") ;
02305         while(rangeNameToken) {
02306           Double_t rangeLo = frame->getPlotVar()->getMin(rangeNameToken) ;
02307           Double_t rangeHi = frame->getPlotVar()->getMax(rangeNameToken) ;
02308           rangeLim.push_back(make_pair(rangeLo,rangeHi)) ;
02309           rangeNameToken = strtok(0,",") ;
02310         }
02311         adjustNorm = pc.getInt("rangeWNAdjustNorm") ;
02312         hasCustomRange = kTRUE ;
02313 
02314         coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") only plotting range '" << pc.getString("rangeName",0,kTRUE) << "'" ;
02315         if (!pc.hasProcessed("NormRange")) {      
02316           ccoutI(Plotting) << ", curve is normalized to data in " << (adjustNorm?"given":"full") << " given range" << endl ;
02317         } else {
02318           ccoutI(Plotting) << endl ;
02319         }
02320 
02321         nameSuffix.Append(Form("_Range[%s]",pc.getString("rangeName"))) ;
02322       } 
02323       // Specification of a normalization range override those in a regular ranage
02324       if (pc.hasProcessed("NormRange")) {    
02325         char tmp[1024] ;
02326         strlcpy(tmp,pc.getString("normRangeName",0,kTRUE),1024) ;
02327         char* rangeNameToken = strtok(tmp,",") ;
02328         rangeLim.clear() ;
02329         while(rangeNameToken) {
02330           Double_t rangeLo = frame->getPlotVar()->getMin(rangeNameToken) ;
02331           Double_t rangeHi = frame->getPlotVar()->getMax(rangeNameToken) ;
02332           rangeLim.push_back(make_pair(rangeLo,rangeHi)) ;
02333           rangeNameToken = strtok(0,",") ;
02334         }
02335         adjustNorm = kTRUE ;
02336         hasCustomRange = kTRUE ;        
02337         coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") p.d.f. curve is normalized using explicit choice of ranges '" << pc.getString("normRangeName",0,kTRUE) << "'" << endl ;
02338 
02339         nameSuffix.Append(Form("_NormRange[%s]",pc.getString("rangeName"))) ;
02340 
02341       }
02342 
02343       if (hasCustomRange && adjustNorm) {       
02344 
02345         Double_t rangeNevt(0) ;
02346         list<pair<Double_t,Double_t> >::iterator riter = rangeLim.begin() ;
02347         for (;riter!=rangeLim.end() ; ++riter) {
02348           Double_t nevt= frame->getFitRangeNEvt(riter->first,riter->second) ;
02349           rangeNevt += nevt ;
02350         }
02351         scaleFactor *= rangeNevt/nExpected ;
02352 
02353       } else {
02354         scaleFactor *= frame->getFitRangeNEvt()/nExpected ;
02355       }
02356     } else if (stype==RelativeExpected) {
02357       scaleFactor *= nExpected ; 
02358     } else if (stype==NumEvent) {
02359       scaleFactor /= nExpected ;
02360     }
02361     scaleFactor *= frame->getFitRangeBinW() ;
02362   } 
02363   frame->updateNormVars(*frame->getPlotVar()) ;
02364 
02365   // Append overriding scale factor command at end of original command list
02366   RooCmdArg tmp = RooFit::Normalization(scaleFactor,Raw) ;
02367   cmdList.Add(&tmp) ;
02368 
02369   // Was a component selected requested
02370   if (haveCompSel) {
02371     
02372     // Get complete set of tree branch nodes
02373     RooArgSet branchNodeSet ;
02374     branchNodeServerList(&branchNodeSet) ;
02375     
02376     // Discard any non-RooAbsReal nodes
02377     TIterator* iter = branchNodeSet.createIterator() ;
02378     RooAbsArg* arg ;
02379     while((arg=(RooAbsArg*)iter->Next())) {
02380       if (!dynamic_cast<RooAbsReal*>(arg)) {
02381         branchNodeSet.remove(*arg) ;
02382       }
02383     }
02384     delete iter ;
02385     
02386     // Obtain direct selection
02387     RooArgSet* dirSelNodes ;
02388     if (compSet) {
02389       dirSelNodes = (RooArgSet*) branchNodeSet.selectCommon(*compSet) ;
02390     } else {
02391       dirSelNodes = (RooArgSet*) branchNodeSet.selectByName(compSpec) ;
02392     }
02393     if (dirSelNodes->getSize()>0) {
02394       coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") directly selected PDF components: " << *dirSelNodes << endl ;
02395       
02396       // Do indirect selection and activate both
02397       plotOnCompSelect(dirSelNodes) ;
02398     } else {
02399       if (compSet) {
02400         coutE(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") ERROR: component selection set " << *compSet << " does not match any components of p.d.f." << endl ;
02401       } else {
02402         coutE(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") ERROR: component selection expression '" << compSpec << "' does not select any components of p.d.f." << endl ;
02403       }
02404       return 0 ;
02405     }
02406 
02407     delete dirSelNodes ;
02408   }
02409 
02410 
02411   RooCmdArg cnsuffix("CurveNameSuffix",0,0,0,0,nameSuffix.Data(),0,0,0) ;
02412   cmdList.Add(&cnsuffix);
02413 
02414   RooPlot* ret =  RooAbsReal::plotOn(frame,cmdList) ;
02415   
02416   // Restore selection status ;
02417   if (haveCompSel) plotOnCompSelect(0) ;
02418 
02419   if (plotRange) {
02420     delete plotRange ;
02421   }
02422   if (normRange2) {
02423     delete normRange2 ;
02424   }  
02425 
02426   return ret ;
02427 }
02428 
02429 
02430 
02431 //_____________________________________________________________________________
02432 void RooAbsPdf::plotOnCompSelect(RooArgSet* selNodes) const
02433 {
02434   // Helper function for plotting of composite p.d.fs. Given
02435   // a set of selected components that should be plotted,
02436   // find all nodes that (in)directly depend on these selected
02437   // nodes. Mark all directly and indirecty selected nodes
02438   // as 'selected' using the selectComp() method
02439 
02440   // Get complete set of tree branch nodes
02441   RooArgSet branchNodeSet ;
02442   branchNodeServerList(&branchNodeSet) ;
02443 
02444   // Discard any non-PDF nodes
02445   TIterator* iter = branchNodeSet.createIterator() ;
02446   RooAbsArg* arg ;
02447   while((arg=(RooAbsArg*)iter->Next())) {
02448     if (!dynamic_cast<RooAbsReal*>(arg)) {
02449       branchNodeSet.remove(*arg) ;
02450     }
02451   }
02452 
02453   // If no set is specified, restored all selection bits to kTRUE
02454   if (!selNodes) {
02455     // Reset PDF selection bits to kTRUE
02456     iter->Reset() ;
02457     while((arg=(RooAbsArg*)iter->Next())) {
02458       ((RooAbsReal*)arg)->selectComp(kTRUE) ;
02459     }
02460     delete iter ;
02461     return ;
02462   }
02463 
02464 
02465   // Add all nodes below selected nodes
02466   iter->Reset() ;
02467   TIterator* sIter = selNodes->createIterator() ;
02468   RooArgSet tmp ;
02469   while((arg=(RooAbsArg*)iter->Next())) {
02470     sIter->Reset() ;
02471     RooAbsArg* selNode ;
02472     while((selNode=(RooAbsArg*)sIter->Next())) {
02473       if (selNode->dependsOn(*arg)) {
02474         tmp.add(*arg,kTRUE) ;
02475       }      
02476     }      
02477   }
02478   delete sIter ;
02479 
02480   // Add all nodes that depend on selected nodes
02481   iter->Reset() ;
02482   while((arg=(RooAbsArg*)iter->Next())) {
02483     if (arg->dependsOn(*selNodes)) {
02484       tmp.add(*arg,kTRUE) ;
02485     }
02486   }
02487 
02488   tmp.remove(*selNodes,kTRUE) ;
02489   tmp.remove(*this) ;
02490   selNodes->add(tmp) ;
02491   coutI(Plotting) << "RooAbsPdf::plotOn(" << GetName() << ") indirectly selected PDF components: " << tmp << endl ;
02492 
02493   // Set PDF selection bits according to selNodes
02494   iter->Reset() ;
02495   while((arg=(RooAbsArg*)iter->Next())) {
02496     Bool_t select = selNodes->find(arg->GetName()) ? kTRUE : kFALSE ;
02497     ((RooAbsReal*)arg)->selectComp(select) ;
02498   }
02499   
02500   delete iter ;
02501 } 
02502 
02503 
02504 
02505 
02506 //_____________________________________________________________________________
02507 // coverity[PASS_BY_VALUE]
02508 RooPlot* RooAbsPdf::plotOn(RooPlot *frame, PlotOpt o) const
02509 {
02510   // Plot oneself on 'frame'. In addition to features detailed in  RooAbsReal::plotOn(),
02511   // the scale factor for a PDF can be interpreted in three different ways. The interpretation
02512   // is controlled by ScaleType
02513   //
02514   //  Relative  -  Scale factor is applied on top of PDF normalization scale factor 
02515   //  NumEvent  -  Scale factor is interpreted as a number of events. The surface area
02516   //               under the PDF curve will match that of a histogram containing the specified
02517   //               number of event
02518   //  Raw       -  Scale factor is applied to the raw (projected) probability density.
02519   //               Not too useful, option provided for completeness.
02520 
02521   // Sanity checks
02522   if (plotSanityChecks(frame)) return frame ;
02523 
02524   // More sanity checks
02525   Double_t nExpected(1) ;
02526   if (o.stype==RelativeExpected) {
02527     if (!canBeExtended()) {
02528       coutE(Plotting) << "RooAbsPdf::plotOn(" << GetName() 
02529                       << "): ERROR the 'Expected' scale option can only be used on extendable PDFs" << endl ;
02530       return frame ;
02531     }
02532     nExpected = expectedEvents(frame->getNormVars()) ;
02533   }
02534 
02535   // Adjust normalization, if so requested
02536   if (o.stype != Raw) {    
02537 
02538     if (frame->getFitRangeNEvt() && o.stype==Relative) {
02539       // If non-default plotting range is specified, adjust number of events in fit range
02540       o.scaleFactor *= frame->getFitRangeNEvt()/nExpected ;
02541     } else if (o.stype==RelativeExpected) {
02542       o.scaleFactor *= nExpected ;
02543     } else if (o.stype==NumEvent) {
02544       o.scaleFactor /= nExpected ;
02545     }
02546     o.scaleFactor *= frame->getFitRangeBinW() ;
02547   }
02548   frame->updateNormVars(*frame->getPlotVar()) ;
02549 
02550   return RooAbsReal::plotOn(frame,o) ;
02551 }
02552 
02553 
02554 
02555 
02556 //_____________________________________________________________________________
02557 RooPlot* RooAbsPdf::paramOn(RooPlot* frame, const RooCmdArg& arg1, const RooCmdArg& arg2, 
02558                             const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5, 
02559                             const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8)
02560 {
02561   // Add a box with parameter values (and errors) to the specified frame
02562   //
02563   // The following named arguments are supported
02564   //
02565   //   Parameters(const RooArgSet& param) -- Only the specified subset of parameters will be shown. 
02566   //                                         By default all non-contant parameters are shown
02567   //   ShowConstants(Bool_t flag)         -- Also display constant parameters
02568   //   Format(const char* optStr)         -- Classing [arameter formatting options, provided for backward compatibility
02569   //   Format(const char* what,...)       -- Parameter formatting options, details given below
02570   //   Label(const chat* label)           -- Add header label to parameter box
02571   //   Layout(Double_t xmin,              -- Specify relative position of left,right side of box and top of box. Position of 
02572   //       Double_t xmax, Double_t ymax)     bottom of box is calculated automatically from number lines in box
02573   //                                 
02574   //
02575   // The Format(const char* what,...) has the following structure
02576   //
02577   //   const char* what      -- Controls what is shown. "N" adds name, "E" adds error, 
02578   //                            "A" shows asymmetric error, "U" shows unit, "H" hides the value
02579   //   FixedPrecision(int n) -- Controls precision, set fixed number of digits
02580   //   AutoPrecision(int n)  -- Controls precision. Number of shown digits is calculated from error 
02581   //                            + n specified additional digits (1 is sensible default)
02582   //
02583   // Example use: pdf.paramOn(frame, Label("fit result"), Format("NEU",AutoPrecision(1)) ) ;
02584   //
02585 
02586   // Stuff all arguments in a list
02587   RooLinkedList cmdList;
02588   cmdList.Add(const_cast<RooCmdArg*>(&arg1)) ;  cmdList.Add(const_cast<RooCmdArg*>(&arg2)) ;
02589   cmdList.Add(const_cast<RooCmdArg*>(&arg3)) ;  cmdList.Add(const_cast<RooCmdArg*>(&arg4)) ;
02590   cmdList.Add(const_cast<RooCmdArg*>(&arg5)) ;  cmdList.Add(const_cast<RooCmdArg*>(&arg6)) ;
02591   cmdList.Add(const_cast<RooCmdArg*>(&arg7)) ;  cmdList.Add(const_cast<RooCmdArg*>(&arg8)) ;
02592 
02593   // Select the pdf-specific commands 
02594   RooCmdConfig pc(Form("RooAbsPdf::paramOn(%s)",GetName())) ;
02595   pc.defineString("label","Label",0,"") ;
02596   pc.defineDouble("xmin","Layout",0,0.50) ;
02597   pc.defineDouble("xmax","Layout",1,0.99) ;
02598   pc.defineInt("ymaxi","Layout",0,Int_t(0.95*10000)) ;
02599   pc.defineInt("showc","ShowConstants",0,0) ;
02600   pc.defineObject("params","Parameters",0,0) ;
02601   pc.defineString("formatStr","Format",0,"NELU") ;
02602   pc.defineInt("sigDigit","Format",0,2) ;
02603   pc.defineInt("dummy","FormatArgs",0,0) ;
02604   pc.defineMutex("Format","FormatArgs") ;
02605 
02606   // Process and check varargs 
02607   pc.process(cmdList) ;
02608   if (!pc.ok(kTRUE)) {
02609     return frame ;
02610   }
02611 
02612   const char* label = pc.getString("label") ;
02613   Double_t xmin = pc.getDouble("xmin") ;
02614   Double_t xmax = pc.getDouble("xmax") ;
02615   Double_t ymax = pc.getInt("ymaxi") / 10000. ;
02616   Int_t showc = pc.getInt("showc") ;
02617 
02618 
02619   const char* formatStr = pc.getString("formatStr") ;
02620   Int_t sigDigit = pc.getInt("sigDigit") ;  
02621 
02622   // Decode command line arguments
02623   RooArgSet* params = static_cast<RooArgSet*>(pc.getObject("params")) ;
02624   if (!params) {
02625     params = getParameters(frame->getNormVars()) ;
02626     if (pc.hasProcessed("FormatArgs")) {
02627       const RooCmdArg* formatCmd = static_cast<RooCmdArg*>(cmdList.FindObject("FormatArgs")) ;
02628       paramOn(frame,*params,showc,label,0,0,xmin,xmax,ymax,formatCmd) ;
02629     } else {
02630       paramOn(frame,*params,showc,label,sigDigit,formatStr,xmin,xmax,ymax) ;
02631     }
02632     delete params ;
02633   } else {
02634     RooArgSet* pdfParams = getParameters(frame->getNormVars()) ;    
02635     RooArgSet* selParams = static_cast<RooArgSet*>(pdfParams->selectCommon(*params)) ;
02636     if (pc.hasProcessed("FormatArgs")) {
02637       const RooCmdArg* formatCmd = static_cast<RooCmdArg*>(cmdList.FindObject("FormatArgs")) ;
02638       paramOn(frame,*selParams,showc,label,0,0,xmin,xmax,ymax,formatCmd) ;
02639     } else {
02640       paramOn(frame,*selParams,showc,label,sigDigit,formatStr,xmin,xmax,ymax) ;
02641     }
02642     delete selParams ;
02643     delete pdfParams ;
02644   }
02645   
02646   return frame ;
02647 }
02648 
02649 
02650 
02651 
02652 //_____________________________________________________________________________
02653 RooPlot* RooAbsPdf::paramOn(RooPlot* frame, const RooAbsData* data, const char *label,
02654                             Int_t sigDigits, Option_t *options, Double_t xmin,
02655                             Double_t xmax ,Double_t ymax) 
02656 {
02657   // OBSOLETE FUNCTION PROVIDED FOR BACKWARD COMPATIBILITY
02658 
02659   RooArgSet* params = getParameters(data) ;
02660   TString opts(options) ;  
02661   paramOn(frame,*params,opts.Contains("c"),label,sigDigits,options,xmin,xmax,ymax) ;
02662   delete params ;
02663   return frame ;
02664 }
02665 
02666 
02667 
02668 //_____________________________________________________________________________
02669 RooPlot* RooAbsPdf::paramOn(RooPlot* frame, const RooArgSet& params, Bool_t showConstants, const char *label,
02670                             Int_t sigDigits, Option_t *options, Double_t xmin,
02671                             Double_t xmax ,Double_t ymax, const RooCmdArg* formatCmd) 
02672 {
02673   // Add a text box with the current parameter values and their errors to the frame.
02674   // Observables of this PDF appearing in the 'data' dataset will be omitted.
02675   //
02676   // Optional label will be inserted as first line of the text box. Use 'sigDigits'
02677   // to modify the default number of significant digits printed. The 'xmin,xmax,ymax'
02678   // values specify the inital relative position of the text box in the plot frame  
02679 
02680 
02681   // parse the options
02682   TString opts = options;
02683   opts.ToLower();
02684   Bool_t showLabel= (label != 0 && strlen(label) > 0);
02685   
02686   // calculate the box's size, adjusting for constant parameters
02687   TIterator* pIter = params.createIterator() ;
02688 
02689   Int_t nPar= params.getSize();
02690   Double_t ymin(ymax), dy(0.06);
02691   Int_t index(nPar);
02692   RooRealVar *var = 0;
02693   while((var=(RooRealVar*)pIter->Next())) {
02694     if(showConstants || !var->isConstant()) ymin-= dy;
02695   }
02696 
02697   if(showLabel) ymin-= dy;
02698 
02699   // create the box and set its options
02700   TPaveText *box= new TPaveText(xmin,ymax,xmax,ymin,"BRNDC");
02701   if(!box) return 0;
02702   box->SetName(Form("%s_paramBox",GetName())) ;
02703   box->SetFillColor(0);
02704   box->SetBorderSize(1);
02705   box->SetTextAlign(12);
02706   box->SetTextSize(0.04F);
02707   box->SetFillStyle(1001);
02708   box->SetFillColor(0);
02709   //char buffer[512];
02710   index= nPar;
02711   pIter->Reset() ;
02712   while((var=(RooRealVar*)pIter->Next())) {
02713     if(var->isConstant() && !showConstants) continue;
02714     
02715     TString *formatted= options ? var->format(sigDigits, options) : var->format(*formatCmd) ;
02716     box->AddText(formatted->Data());
02717     delete formatted;
02718   }
02719   // add the optional label if specified
02720   if(showLabel) box->AddText(label);
02721 
02722   // Add box to frame 
02723   frame->addObject(box) ;
02724 
02725   delete pIter ;
02726   return frame ;
02727 }
02728 
02729 
02730 
02731 
02732 //_____________________________________________________________________________
02733 Double_t RooAbsPdf::expectedEvents(const RooArgSet*) const 
02734 { 
02735   // Return expected number of events from this p.d.f for use in extended
02736   // likelihood calculations. This default implementation returns zero
02737   return 0 ; 
02738 } 
02739 
02740 
02741 
02742 //_____________________________________________________________________________
02743 void RooAbsPdf::verboseEval(Int_t stat) 
02744 { 
02745   // Change global level of verbosity for p.d.f. evaluations
02746 
02747   _verboseEval = stat ; 
02748 }
02749 
02750 
02751 
02752 //_____________________________________________________________________________
02753 Int_t RooAbsPdf::verboseEval() 
02754 { 
02755   // Return global level of verbosity for p.d.f. evaluations
02756 
02757   return _verboseEval ;
02758 }
02759 
02760 
02761 
02762 //_____________________________________________________________________________
02763 void RooAbsPdf::CacheElem::operModeHook(RooAbsArg::OperMode) 
02764 {
02765   // Dummy implementation
02766 }
02767 
02768 
02769 
02770 //_____________________________________________________________________________
02771 RooAbsPdf::CacheElem::~CacheElem() 
02772 { 
02773   // Destructor of normalization cache element. If this element 
02774   // provides the 'current' normalization stored in RooAbsPdf::_norm
02775   // zero _norm pointer here before object pointed to is deleted here
02776 
02777   // Zero _norm pointer in RooAbsPdf if it is points to our cache payload
02778   if (_owner) {
02779     RooAbsPdf* pdfOwner = static_cast<RooAbsPdf*>(_owner) ;
02780     if (pdfOwner->_norm == _norm) {
02781       pdfOwner->_norm = 0 ;
02782     }
02783   }
02784 
02785   delete _norm ; 
02786 } 
02787 
02788 
02789 
02790 //_____________________________________________________________________________
02791 RooAbsPdf* RooAbsPdf::createProjection(const RooArgSet& iset) 
02792 {
02793   // Return a p.d.f that represent a projection of this p.d.f integrated over given observables
02794 
02795   // Construct name for new object
02796   TString name(GetName()) ;
02797   name.Append("_Proj[") ;
02798   if (iset.getSize()>0) {
02799     TIterator* iter = iset.createIterator() ;
02800     RooAbsArg* arg ;
02801     Bool_t first(kTRUE) ;
02802     while((arg=(RooAbsArg*)iter->Next())) {
02803       if (first) {
02804         first=kFALSE ;
02805       } else {
02806         name.Append(",") ;
02807       }
02808       name.Append(arg->GetName()) ;
02809     }
02810     delete iter ;
02811   }
02812   name.Append("]") ;
02813   
02814   // Return projected p.d.f.
02815   return new RooProjectedPdf(name.Data(),name.Data(),*this,iset) ;
02816 }
02817 
02818 
02819 
02820 //_____________________________________________________________________________
02821 RooAbsReal* RooAbsPdf::createCdf(const RooArgSet& iset, const RooArgSet& nset) 
02822 {
02823   // Create a cumulative distribution function of this p.d.f in terms
02824   // of the observables listed in iset. If no nset argument is given
02825   // the c.d.f normalization is constructed over the integrated
02826   // observables, so that its maximum value is precisely 1. It is also
02827   // possible to choose a different normalization for
02828   // multi-dimensional p.d.f.s: eg. for a pdf f(x,y,z) one can
02829   // construct a partial cdf c(x,y) that only when integrated itself
02830   // over z results in a maximum value of 1. To construct such a cdf pass
02831   // z as argument to the optional nset argument
02832 
02833   return createCdf(iset,RooFit::SupNormSet(nset)) ;
02834 }
02835 
02836 
02837 
02838 //_____________________________________________________________________________
02839 RooAbsReal* RooAbsPdf::createCdf(const RooArgSet& iset, const RooCmdArg& arg1, const RooCmdArg& arg2,
02840                                  const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5, 
02841                                  const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) 
02842 {
02843   // Create an object that represents the integral of the function over one or more observables listed in iset
02844   // The actual integration calculation is only performed when the return object is evaluated. The name
02845   // of the integral object is automatically constructed from the name of the input function, the variables
02846   // it integrates and the range integrates over
02847   //
02848   // The following named arguments are accepted
02849   //
02850   // SupNormSet(const RooArgSet&)         -- Observables over which should be normalized _in_addition_ to the
02851   //                                         integration observables
02852   // ScanNumCdf()                         -- Apply scanning technique if cdf integral involves numeric integration [ default ] 
02853   // ScanAllCdf()                         -- Always apply scanning technique 
02854   // ScanNoCdf()                          -- Never apply scanning technique                  
02855   // ScanParameters(Int_t nbins,          -- Parameters for scanning technique of making CDF: number
02856   //                Int_t intOrder)          of sampled bins and order of interpolation applied on numeric cdf
02857 
02858   // Define configuration for this method
02859   RooCmdConfig pc(Form("RooAbsReal::createCdf(%s)",GetName())) ;
02860   pc.defineObject("supNormSet","SupNormSet",0,0) ;
02861   pc.defineInt("numScanBins","ScanParameters",0,1000) ;
02862   pc.defineInt("intOrder","ScanParameters",1,2) ;
02863   pc.defineInt("doScanNum","ScanNumCdf",0,1) ;
02864   pc.defineInt("doScanAll","ScanAllCdf",0,0) ;
02865   pc.defineInt("doScanNon","ScanNoCdf",0,0) ;
02866   pc.defineMutex("ScanNumCdf","ScanAllCdf","ScanNoCdf") ;
02867 
02868   // Process & check varargs 
02869   pc.process(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
02870   if (!pc.ok(kTRUE)) {
02871     return 0 ;
02872   }
02873 
02874   // Extract values from named arguments
02875   const RooArgSet* snset = static_cast<const RooArgSet*>(pc.getObject("supNormSet",0)) ;
02876   RooArgSet nset ;
02877   if (snset) {
02878     nset.add(*snset) ;
02879   }
02880   Int_t numScanBins = pc.getInt("numScanBins") ;
02881   Int_t intOrder = pc.getInt("intOrder") ;
02882   Int_t doScanNum = pc.getInt("doScanNum") ;
02883   Int_t doScanAll = pc.getInt("doScanAll") ;
02884   Int_t doScanNon = pc.getInt("doScanNon") ;
02885 
02886   // If scanning technique is not requested make integral-based cdf and return
02887   if (doScanNon) {
02888     return createIntRI(iset,nset) ;
02889   }
02890   if (doScanAll) {
02891     return createScanCdf(iset,nset,numScanBins,intOrder) ;
02892   }
02893   if (doScanNum) {
02894     RooRealIntegral* tmp = (RooRealIntegral*) createIntegral(iset) ;
02895     Int_t isNum= (tmp->numIntRealVars().getSize()>0) ;
02896     delete tmp ;
02897 
02898     if (isNum) {
02899       coutI(NumIntegration) << "RooAbsPdf::createCdf(" << GetName() << ") integration over observable(s) " << iset << " involves numeric integration," << endl 
02900                             << "      constructing cdf though numeric integration of sampled pdf in " << numScanBins << " bins and applying order " 
02901                             << intOrder << " interpolation on integrated histogram." << endl 
02902                             << "      To override this choice of technique use argument ScanNone(), to change scan parameters use ScanParameters(nbins,order) argument" << endl ;
02903     }
02904     
02905     return isNum ? createScanCdf(iset,nset,numScanBins,intOrder) : createIntRI(iset,nset) ;
02906   }
02907   return 0 ;
02908 }
02909 
02910 RooAbsReal* RooAbsPdf::createScanCdf(const RooArgSet& iset, const RooArgSet& nset, Int_t numScanBins, Int_t intOrder) 
02911 {
02912   string name = string(GetName()) + "_NUMCDF_" + integralNameSuffix(iset,&nset).Data() ;  
02913   RooRealVar* ivar = (RooRealVar*) iset.first() ;
02914   ivar->setBins(numScanBins,"numcdf") ;
02915   RooNumCdf* ret = new RooNumCdf(name.c_str(),name.c_str(),*this,*ivar,"numcdf") ;
02916   ret->setInterpolationOrder(intOrder) ;
02917   return ret ;
02918 }
02919 
02920 
02921 
02922 
02923 //_____________________________________________________________________________
02924 RooArgSet* RooAbsPdf::getAllConstraints(const RooArgSet& observables, RooArgSet& constrainedParams, Bool_t stripDisconnected) const 
02925 {
02926   // This helper function finds and collects all constraints terms of all coponent p.d.f.s
02927   // and returns a RooArgSet with all those terms
02928 
02929   RooArgSet* ret = new RooArgSet("AllConstraints") ;
02930 
02931   RooArgSet* comps = getComponents() ;
02932   TIterator* iter = comps->createIterator() ;
02933   RooAbsArg *arg ;
02934   while((arg=(RooAbsArg*)iter->Next())) {
02935     RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(arg) ;
02936     if (pdf && !ret->find(pdf->GetName())) {
02937       RooArgSet* compRet = pdf->getConstraints(observables,constrainedParams,stripDisconnected) ;
02938       if (compRet) {
02939         ret->add(*compRet,kFALSE) ;
02940         delete compRet ;
02941       }
02942     }
02943   }
02944   delete iter ;
02945   delete comps ;
02946 
02947   return ret ;
02948 }
02949 
02950 
02951 //_____________________________________________________________________________
02952 void RooAbsPdf::clearEvalError() 
02953 { 
02954   // Clear the evaluation error flag
02955   _evalError = kFALSE ; 
02956 }
02957 
02958 
02959 
02960 //_____________________________________________________________________________
02961 Bool_t RooAbsPdf::evalError() 
02962 { 
02963   // Return the evaluation error flag
02964   return _evalError ; 
02965 }
02966 
02967 
02968 
02969 //_____________________________________________________________________________
02970 void RooAbsPdf::raiseEvalError() 
02971 { 
02972   // Raise the evaluation error flag
02973   _evalError = kTRUE ; 
02974 }
02975 
02976 
02977 
02978 //_____________________________________________________________________________
02979 RooNumGenConfig* RooAbsPdf::defaultGeneratorConfig() 
02980 {
02981   // Returns the default numeric MC generator configuration for all RooAbsReals
02982   return &RooNumGenConfig::defaultConfig() ;
02983 }
02984 
02985 
02986 //_____________________________________________________________________________
02987 RooNumGenConfig* RooAbsPdf::specialGeneratorConfig() const 
02988 {
02989   // Returns the specialized integrator configuration for _this_ RooAbsReal.
02990   // If this object has no specialized configuration, a null pointer is returned
02991   return _specGeneratorConfig ;
02992 }
02993 
02994 
02995 
02996 //_____________________________________________________________________________
02997 RooNumGenConfig* RooAbsPdf::specialGeneratorConfig(Bool_t createOnTheFly) 
02998 {
02999   // Returns the specialized integrator configuration for _this_ RooAbsReal.
03000   // If this object has no specialized configuration, a null pointer is returned,
03001   // unless createOnTheFly is kTRUE in which case a clone of the default integrator
03002   // configuration is created, installed as specialized configuration, and returned
03003 
03004   if (!_specGeneratorConfig && createOnTheFly) {
03005     _specGeneratorConfig = new RooNumGenConfig(*defaultGeneratorConfig()) ;
03006   }
03007   return _specGeneratorConfig ;
03008 }
03009 
03010 
03011 
03012 //_____________________________________________________________________________
03013 const RooNumGenConfig* RooAbsPdf::getGeneratorConfig() const 
03014 {
03015   // Return the numeric MC generator configuration used for this object. If
03016   // a specialized configuration was associated with this object, that configuration
03017   // is returned, otherwise the default configuration for all RooAbsReals is returned
03018 
03019   const RooNumGenConfig* config = specialGeneratorConfig() ;
03020   if (config) return config ;
03021   return defaultGeneratorConfig() ;
03022 }
03023 
03024 
03025 
03026 //_____________________________________________________________________________
03027 void RooAbsPdf::setGeneratorConfig(const RooNumGenConfig& config) 
03028 {
03029   // Set the given configuration as default numeric MC generator
03030   // configuration for this object
03031   if (_specGeneratorConfig) {
03032     delete _specGeneratorConfig ;
03033   }
03034   _specGeneratorConfig = new RooNumGenConfig(config) ;  
03035 }
03036 
03037 
03038 
03039 //_____________________________________________________________________________
03040 void RooAbsPdf::setGeneratorConfig() 
03041 {
03042   // Remove the specialized numeric MC generator configuration associated
03043   // with this object
03044   if (_specGeneratorConfig) {
03045     delete _specGeneratorConfig ;
03046   }
03047   _specGeneratorConfig = 0 ;
03048 }
03049 
03050 
03051 
03052 //_____________________________________________________________________________
03053 RooAbsPdf::GenSpec::~GenSpec() 
03054 {
03055   delete _genContext ;
03056 }
03057 
03058 
03059 //_____________________________________________________________________________
03060 RooAbsPdf::GenSpec::GenSpec(RooAbsGenContext* context, const RooArgSet& whatVars, RooDataSet* protoData, Int_t nGen, 
03061                             Bool_t extended, Bool_t randProto, Bool_t resampleProto, TString dsetName) :
03062   _genContext(context), _whatVars(whatVars), _protoData(protoData), _nGen(nGen), _extended(extended), 
03063   _randProto(randProto), _resampleProto(resampleProto), _dsetName(dsetName) 
03064 {
03065 }
03066 
03067 
03068 
03069 //_____________________________________________________________________________
03070 void RooAbsPdf::setNormRange(const char* rangeName) 
03071 { 
03072   if (rangeName) {
03073     _normRange = rangeName ; 
03074   } else {
03075     _normRange.Clear() ; 
03076   }
03077 
03078   if (_norm) { 
03079     _normMgr.sterilize() ;
03080     _norm = 0 ; 
03081   }
03082 }
03083 
03084 
03085 //_____________________________________________________________________________
03086 void RooAbsPdf::setNormRangeOverride(const char* rangeName) 
03087 {
03088   if (rangeName) {
03089     _normRangeOverride = rangeName ; 
03090   } else {
03091     _normRangeOverride.Clear() ; 
03092   }
03093 
03094   if (_norm) { 
03095     _normMgr.sterilize() ;
03096     _norm = 0 ; 
03097   }
03098 }

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