RooAbsReal.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooAbsReal.cxx 37224 2010-12-03 13:31:21Z 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 // BEGIN_HTML
00020 // RooAbsReal is the common abstract base class for objects that represent a
00021 // real value and implements functionality common to all real-valued objects
00022 // such as the ability to plot them, to construct integrals of them, the
00023 // ability to advertise (partial) analytical integrals etc..
00024 
00025 // Implementation of RooAbsReal may be derived, thus no interface
00026 // is provided to modify the contents.
00027 // 
00028 // 
00029 // END_HTML
00030 //
00031 
00032 #include <sys/types.h>
00033 
00034 
00035 #include "RooFit.h"
00036 #include "RooMsgService.h"
00037 
00038 #include "RooAbsReal.h"
00039 #include "RooAbsReal.h"
00040 #include "RooArgSet.h"
00041 #include "RooArgList.h"
00042 #include "RooPlot.h"
00043 #include "RooCurve.h"
00044 #include "RooRealVar.h"
00045 #include "RooArgProxy.h"
00046 #include "RooFormulaVar.h"
00047 #include "RooRealBinding.h"
00048 #include "RooRealIntegral.h"
00049 #include "RooAbsCategoryLValue.h"
00050 #include "RooCustomizer.h"
00051 #include "RooAbsData.h"
00052 #include "RooScaledFunc.h"
00053 #include "RooAddPdf.h"
00054 #include "RooCmdConfig.h"
00055 #include "RooCategory.h"
00056 #include "RooNumIntConfig.h"
00057 #include "RooAddition.h"
00058 #include "RooDataSet.h"
00059 #include "RooDataHist.h"
00060 #include "RooDataWeightedAverage.h"
00061 #include "RooNumRunningInt.h"
00062 #include "RooGlobalFunc.h"
00063 #include "RooParamBinning.h"
00064 #include "RooProfileLL.h"
00065 #include "RooFunctor.h"
00066 #include "RooDerivative.h"
00067 #include "RooGenFunction.h"
00068 #include "RooMultiGenFunction.h"
00069 #include "RooCmdConfig.h"
00070 #include "RooXYChi2Var.h"
00071 #include "RooMinuit.h"
00072 #include "RooChi2Var.h"
00073 #include "RooFitResult.h"
00074 #include "RooMoment.h"
00075 #include "RooBrentRootFinder.h"
00076 
00077 #include "Riostream.h"
00078 
00079 #include "Math/IFunction.h"
00080 #include "TMath.h"
00081 #include "TObjString.h"
00082 #include "TTree.h"
00083 #include "TH1.h"
00084 #include "TH2.h"
00085 #include "TH3.h"
00086 #include "TBranch.h"
00087 #include "TLeaf.h"
00088 #include "TAttLine.h"
00089 #include "TF1.h"
00090 #include "TF2.h"
00091 #include "TF3.h"
00092 #include "TMatrixD.h"
00093 #include "TVector.h"
00094 
00095 #include <sstream>
00096 
00097 using namespace std ;
00098  
00099 ClassImp(RooAbsReal)
00100 ;
00101 
00102 Bool_t RooAbsReal::_cacheCheck(kFALSE) ;
00103 Bool_t RooAbsReal::_globalSelectComp = kFALSE ;
00104 
00105 RooAbsReal::ErrorLoggingMode RooAbsReal::_evalErrorMode = RooAbsReal::PrintErrors ;
00106 Int_t RooAbsReal::_evalErrorCount = 0 ;
00107 map<const RooAbsArg*,pair<string,list<RooAbsReal::EvalError> > > RooAbsReal::_evalErrorList ;
00108 
00109 
00110 //_____________________________________________________________________________
00111 RooAbsReal::RooAbsReal() : _specIntegratorConfig(0), _treeVar(kFALSE), _selectComp(kTRUE), _lastNSet(0)
00112 {
00113   // Default constructor
00114 }
00115 
00116 
00117 
00118 //_____________________________________________________________________________
00119 RooAbsReal::RooAbsReal(const char *name, const char *title, const char *unit) : 
00120   RooAbsArg(name,title), _plotMin(0), _plotMax(0), _plotBins(100), 
00121   _value(0),  _unit(unit), _forceNumInt(kFALSE), _specIntegratorConfig(0), _treeVar(kFALSE), _selectComp(kTRUE), _lastNSet(0)
00122 {
00123   // Constructor with unit label
00124   setValueDirty() ;
00125   setShapeDirty() ;
00126 
00127 }
00128 
00129 
00130 
00131 //_____________________________________________________________________________
00132 RooAbsReal::RooAbsReal(const char *name, const char *title, Double_t inMinVal,
00133                        Double_t inMaxVal, const char *unit) :
00134   RooAbsArg(name,title), _plotMin(inMinVal), _plotMax(inMaxVal), _plotBins(100),
00135   _value(0), _unit(unit), _forceNumInt(kFALSE), _specIntegratorConfig(0), _treeVar(kFALSE), _selectComp(kTRUE), _lastNSet(0)
00136 {
00137   // Constructor with plot range and unit label
00138   setValueDirty() ;
00139   setShapeDirty() ;
00140 
00141 }
00142 
00143 
00144 
00145 //_____________________________________________________________________________
00146 RooAbsReal::RooAbsReal(const RooAbsReal& other, const char* name) : 
00147   RooAbsArg(other,name), _plotMin(other._plotMin), _plotMax(other._plotMax), 
00148   _plotBins(other._plotBins), _value(other._value), _unit(other._unit), _forceNumInt(other._forceNumInt), 
00149   _treeVar(other._treeVar), _selectComp(other._selectComp), _lastNSet(0)
00150 {
00151   // Copy constructor
00152 
00153   if (other._specIntegratorConfig) {
00154     _specIntegratorConfig = new RooNumIntConfig(*other._specIntegratorConfig) ;
00155   } else {
00156     _specIntegratorConfig = 0 ;
00157   }
00158 }
00159 
00160 
00161 
00162 //_____________________________________________________________________________
00163 RooAbsReal::~RooAbsReal()
00164 {
00165   // Destructor
00166 
00167   if (_specIntegratorConfig) delete _specIntegratorConfig ;
00168 }
00169 
00170 
00171 
00172 //_____________________________________________________________________________
00173 Bool_t RooAbsReal::operator==(Double_t value) const
00174 {
00175   // Equality operator comparing to a Double_t
00176   return (getVal()==value) ;
00177 }
00178 
00179 
00180 
00181 //_____________________________________________________________________________
00182 Bool_t RooAbsReal::operator==(const RooAbsArg& other) 
00183 {
00184   // Equality operator when comparing to another RooAbsArg.
00185   // Only functional when the other arg is a RooAbsReal
00186 
00187   const RooAbsReal* otherReal = dynamic_cast<const RooAbsReal*>(&other) ;
00188   return otherReal ? operator==(otherReal->getVal()) : kFALSE ;
00189 }
00190 
00191 
00192 
00193 //_____________________________________________________________________________
00194 TString RooAbsReal::getTitle(Bool_t appendUnit) const 
00195 {
00196   // Return this variable's title string. If appendUnit is true and
00197   // this variable has units, also append a string " (<unit>)".
00198   
00199   TString title(GetTitle());
00200   if(appendUnit && 0 != strlen(getUnit())) {
00201     title.Append(" (");
00202     title.Append(getUnit());
00203     title.Append(")");
00204   }
00205   return title;
00206 }
00207 
00208 
00209 
00210 //_____________________________________________________________________________
00211 Double_t RooAbsReal::getVal(const RooArgSet* nset) const
00212 {
00213   // Return value of object. If the cache is clean, return the
00214   // cached value, otherwise recalculate on the fly and refill
00215   // the cache
00216 
00217   if (nset && nset!=_lastNSet) {
00218     ((RooAbsReal*) this)->setProxyNormSet(nset) ;    
00219     _lastNSet = (RooArgSet*) nset ;
00220   }
00221 
00222   if (isValueDirty() || isShapeDirty()) {
00223 
00224     _value = traceEval(nset) ;
00225 
00226     clearValueDirty() ; 
00227     clearShapeDirty() ; 
00228 
00229   } else if (_cacheCheck) {
00230     
00231     // Check if cache contains value that evaluate() gives now
00232     Double_t checkValue = traceEval(nset);
00233 
00234     if (checkValue != _value) {
00235       // If not, print warning
00236       coutW(Eval) << "RooAbsReal::getVal(" << GetName() << ") WARNING: cache contains " << _value 
00237                   << " but evaluate() returns " << checkValue << endl ;
00238 
00239       // And update cache (so that we see the difference)
00240       _value = checkValue ;
00241     }                                                                                                
00242     
00243   }
00244 
00245   return _value ;
00246 }
00247 
00248 
00249 
00250 //_____________________________________________________________________________
00251 Double_t RooAbsReal::traceEval(const RooArgSet* /*nset*/) const
00252 {
00253   // Calculate current value of object, with error tracing wrapper
00254 
00255   Double_t value = evaluate() ;
00256 
00257   if (TMath::IsNaN(value)) {
00258     logEvalError("function value is NAN") ;
00259   }
00260 
00261   cxcoutD(Tracing) << "RooAbsReal::getVal(" << GetName() << ") operMode = " << _operMode << " recalculated, new value = " << value << endl ;
00262   
00263   //Standard tracing code goes here
00264   if (!isValidReal(value)) {
00265     coutW(Tracing) << "RooAbsReal::traceEval(" << GetName() 
00266                    << "): validation failed: " << value << endl ;
00267   }
00268 
00269   //Call optional subclass tracing code
00270   traceEvalHook(value) ;
00271 
00272   return value ;
00273 }
00274 
00275 
00276 
00277 //_____________________________________________________________________________
00278 Int_t RooAbsReal::getAnalyticalIntegralWN(RooArgSet& allDeps, RooArgSet& analDeps, 
00279                                           const RooArgSet* /*normSet*/, const char* rangeName) const
00280 {
00281   // Variant of getAnalyticalIntegral that is also passed the normalization set
00282   // that should be applied to the integrand of which the integral is request.
00283   // For certain operator p.d.f it is useful to overload this function rather
00284   // than analyticalIntegralWN() as the additional normalization information
00285   // may be useful in determining a more efficient decomposition of the
00286   // requested integral
00287 
00288   return _forceNumInt ? 0 : getAnalyticalIntegral(allDeps,analDeps,rangeName) ;
00289 }
00290 
00291 
00292 
00293 //_____________________________________________________________________________
00294 Int_t RooAbsReal::getAnalyticalIntegral(RooArgSet& /*integSet*/, RooArgSet& /*anaIntSet*/, const char* /*rangeName*/) const
00295 {
00296   // Interface function getAnalyticalIntergral advertises the
00297   // analytical integrals that are supported. 'integSet'
00298   // is the set of dependents for which integration is requested. The
00299   // function should copy the subset of dependents it can analytically
00300   // integrate to anaIntSet and return a unique identification code for
00301   // this integration configuration.  If no integration can be
00302   // performed, zero should be returned.
00303   
00304   return 0 ;
00305 }
00306 
00307 
00308 
00309 //_____________________________________________________________________________
00310 Double_t RooAbsReal::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
00311 {
00312   // Implements the actual analytical integral(s) advertised by
00313   // getAnalyticalIntegral.  This functions will only be called with
00314   // codes returned by getAnalyticalIntegral, except code zero.
00315 
00316 //   cout << "RooAbsReal::analyticalIntegralWN(" << GetName() << ") code = " << code << " normSet = " << (normSet?*normSet:RooArgSet()) << endl ;
00317   if (code==0) return getVal(normSet) ;
00318   return analyticalIntegral(code,rangeName) ;
00319 }
00320 
00321 
00322 
00323 //_____________________________________________________________________________
00324 Double_t RooAbsReal::analyticalIntegral(Int_t code, const char* /*rangeName*/) const
00325 {
00326   // Implements the actual analytical integral(s) advertised by
00327   // getAnalyticalIntegral.  This functions will only be called with
00328   // codes returned by getAnalyticalIntegral, except code zero.
00329 
00330   // By default no analytical integrals are implemented
00331   coutF(Eval)  << "RooAbsReal::analyticalIntegral(" << GetName() << ") code " << code << " not implemented" << endl ;
00332   return 0 ;
00333 }
00334 
00335 
00336 
00337 //_____________________________________________________________________________
00338 const char *RooAbsReal::getPlotLabel() const 
00339 {
00340   // Get the label associated with the variable
00341 
00342   return _label.IsNull() ? fName.Data() : _label.Data();
00343 }
00344 
00345 
00346 
00347 //_____________________________________________________________________________
00348 void RooAbsReal::setPlotLabel(const char *label) 
00349 {
00350   // Set the label associated with this variable
00351 
00352   _label= label;
00353 }
00354 
00355 
00356 
00357 //_____________________________________________________________________________
00358 Bool_t RooAbsReal::readFromStream(istream& /*is*/, Bool_t /*compact*/, Bool_t /*verbose*/) 
00359 {
00360   //Read object contents from stream (dummy for now)
00361 
00362   return kFALSE ;
00363 } 
00364 
00365 
00366 
00367 //_____________________________________________________________________________
00368 void RooAbsReal::writeToStream(ostream& /*os*/, Bool_t /*compact*/) const
00369 {
00370   //Write object contents to stream (dummy for now)
00371 }
00372 
00373 
00374 
00375 //_____________________________________________________________________________
00376 void RooAbsReal::printValue(ostream& os) const
00377 {
00378   // Print object value 
00379   os << getVal() ;
00380 }
00381 
00382 
00383 
00384 //_____________________________________________________________________________
00385 void RooAbsReal::printMultiline(ostream& os, Int_t contents, Bool_t verbose, TString indent) const
00386 {
00387   // Structure printing
00388 
00389   RooAbsArg::printMultiline(os,contents,verbose,indent) ;
00390   os << indent << "--- RooAbsReal ---" << endl;
00391   TString unit(_unit);
00392   if(!unit.IsNull()) unit.Prepend(' ');
00393   //os << indent << "  Value = " << getVal() << unit << endl;
00394   os << endl << indent << "  Plot label is \"" << getPlotLabel() << "\"" << endl;
00395 
00396 }
00397 
00398 
00399 //_____________________________________________________________________________
00400 Bool_t RooAbsReal::isValid() const 
00401 {
00402   // Check if current value is valid
00403 
00404   return isValidReal(_value) ;
00405 }
00406 
00407 
00408 
00409 //_____________________________________________________________________________
00410 Bool_t RooAbsReal::isValidReal(Double_t /*value*/, Bool_t /*printError*/) const 
00411 {
00412   // Interface function to check if given value is a valid value for this object.
00413   // This default implementation considers all values valid
00414 
00415   return kTRUE ;
00416 }
00417 
00418 
00419 
00420 
00421 //_____________________________________________________________________________
00422 RooAbsReal* RooAbsReal::createProfile(const RooArgSet& paramsOfInterest) 
00423 {
00424   // Create a RooProfileLL object that eliminates all nuisance parameters in the
00425   // present function. The nuisance parameters are defined as all parameters
00426   // of the function except the stated paramsOfInterest
00427 
00428   // Construct name of profile object
00429   TString name(Form("%s_Profile[",GetName())) ;
00430   TIterator* iter = paramsOfInterest.createIterator() ;
00431   RooAbsArg* arg ;
00432   Bool_t first(kTRUE) ;
00433   while((arg=(RooAbsArg*)iter->Next())) {
00434     if (first) {
00435       first=kFALSE ;
00436     } else {
00437       name.Append(",") ;
00438     }
00439     name.Append(arg->GetName()) ;
00440   }
00441   delete iter ;
00442   name.Append("]") ;
00443   
00444   // Create and return profile object
00445   return new RooProfileLL(name.Data(),Form("Profile of %s",GetTitle()),*this,paramsOfInterest) ;
00446 }
00447        
00448 
00449 
00450 
00451 
00452 
00453 //_____________________________________________________________________________
00454 RooAbsReal* RooAbsReal::createIntegral(const RooArgSet& iset, const RooCmdArg& arg1, const RooCmdArg& arg2,
00455                                        const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5, 
00456                                        const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) const 
00457 {
00458   // Create an object that represents the integral of the function over one or more observables listed in iset
00459   // The actual integration calculation is only performed when the return object is evaluated. The name
00460   // of the integral object is automatically constructed from the name of the input function, the variables
00461   // it integrates and the range integrates over
00462   //
00463   // The following named arguments are accepted
00464   //
00465   // NormSet(const RooArgSet&)            -- Specify normalization set, mostly useful when working with PDFS
00466   // NumIntConfig(const RooNumIntConfig&) -- Use given configuration for any numeric integration, if necessary
00467   // Range(const char* name)              -- Integrate only over given range. Multiple ranges may be specified
00468   //                                         by passing multiple Range() arguments  
00469 
00470 
00471 
00472   // Define configuration for this method
00473   RooCmdConfig pc(Form("RooAbsReal::createIntegral(%s)",GetName())) ;
00474   pc.defineString("rangeName","RangeWithName",0,"",kTRUE) ;
00475   pc.defineObject("normSet","NormSet",0,0) ;
00476   pc.defineObject("numIntConfig","NumIntConfig",0,0) ;
00477 
00478   // Process & check varargs 
00479   pc.process(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
00480   if (!pc.ok(kTRUE)) {
00481     return 0 ;
00482   }
00483 
00484   // Extract values from named arguments
00485   const char* rangeName = pc.getString("rangeName",0,kTRUE) ;
00486   const RooArgSet* nset = static_cast<const RooArgSet*>(pc.getObject("normSet",0)) ;
00487   const RooNumIntConfig* cfg = static_cast<const RooNumIntConfig*>(pc.getObject("numIntConfig",0)) ;
00488 
00489   return createIntegral(iset,nset,cfg,rangeName) ;
00490 }
00491 
00492 
00493 
00494 
00495 
00496 //_____________________________________________________________________________
00497 RooAbsReal* RooAbsReal::createIntegral(const RooArgSet& iset, const RooArgSet* nset, 
00498                                        const RooNumIntConfig* cfg, const char* rangeName) const 
00499 {
00500   // Create an object that represents the integral of the function over one or more observables listed in iset
00501   // The actual integration calculation is only performed when the return object is evaluated. The name
00502   // of the integral object is automatically constructed from the name of the input function, the variables
00503   // it integrates and the range integrates over. If nset is specified the integrand is request
00504   // to be normalized over nset (only meaningful when the integrand is a pdf). If rangename is specified
00505   // the integral is performed over the named range, otherwise it is performed over the domain of each
00506   // integrated observable. If cfg is specified it will be used to configure any numeric integration
00507   // aspect of the integral. It will not force the integral to be performed numerically, which is
00508   // decided automatically by RooRealIntegral
00509 
00510   if (!rangeName || strchr(rangeName,',')==0) {
00511     // Simple case: integral over full range or single limited range
00512     return createIntObj(iset,nset,cfg,rangeName) ;
00513   } 
00514 
00515   // Integral over multiple ranges
00516   RooArgSet components ;
00517   
00518   // char* buf = new char[strlen(rangeName)+1] ;
00519   //   strlcpy(buf,rangeName) ;
00520   //   char* range = strtok(buf,",") ;
00521   
00522   //   while (range) {
00523   //     RooAbsReal* compIntegral = createIntObj(iset,nset,cfg,range) ;
00524   //     components.add(*compIntegral) ;
00525   //     range = strtok(0,",") ;
00526   //   }
00527   //   delete[] buf ;
00528   
00529   // + ALEX
00530   TObjArray* oa = TString(rangeName).Tokenize(",");
00531   
00532   for( Int_t i=0; i < oa->GetEntries(); ++i) {
00533     TObjString* os = (TObjString*) (*oa)[i];
00534 //     cout<< "    ALEX:: RooAbsReal::createIntegral (" << GetName() << ")  os = " << os->GetString().Data() <<endl;
00535     if(!os) break;
00536     RooAbsReal* compIntegral = createIntObj(iset,nset,cfg,os->GetString().Data()) ;
00537 //     cout << "just created " << compIntegral->GetName() << " for rangename = " << os->GetString().Data() << endl ;
00538     components.add(*compIntegral) ;
00539   }
00540   delete oa;
00541   // - ALEX 
00542 //     cout<< "    ALEX:: RooAbsReal::createIntegral (" << GetName() << ")  components = " << components <<endl;
00543 
00544   TString title(GetTitle()) ;
00545   title.Prepend("Integral of ") ;
00546   TString fullName(GetName()) ;
00547   fullName.Append(integralNameSuffix(iset,nset,rangeName)) ;
00548 
00549   return new RooAddition(fullName.Data(),title.Data(),components,kTRUE) ;
00550 }
00551 
00552 
00553 
00554 //_____________________________________________________________________________
00555 RooAbsReal* RooAbsReal::createIntObj(const RooArgSet& iset2, const RooArgSet* nset2, 
00556                                      const RooNumIntConfig* cfg, const char* rangeName) const 
00557 {
00558   // Utility function for createIntegral that creates the actual integreal object
00559 
00560   // Make internal use copies of iset and nset
00561   RooArgSet iset(iset2) ;
00562   const RooArgSet* nset = nset2 ;
00563 
00564   // Initialize local variables perparing for recursive loop
00565   Bool_t error = kFALSE ;
00566   const RooAbsReal* integrand = this ;
00567   RooAbsReal* integral = 0 ;
00568 
00569   // Handle trivial case of no integration here explicitly
00570   if (iset.getSize()==0) {
00571 
00572     TString title(GetTitle()) ;
00573     title.Prepend("Integral of ") ;
00574     
00575     TString name(GetName()) ;
00576     name.Append(integralNameSuffix(iset,nset,rangeName)) ;
00577 
00578     return new RooRealIntegral(name,title,*this,iset,nset,cfg,rangeName) ;
00579   }
00580 
00581   // Process integration over remaining integration variables
00582   while(iset.getSize()>0) {
00583 
00584     // Find largest set of observables that can be integrated in one go
00585     RooArgSet innerSet ;
00586     findInnerMostIntegration(iset,innerSet,rangeName) ;
00587 
00588     // If largest set of observables that can be integrated is empty set, problem was ill defined
00589     // Postpone error messaging and handling to end of function, exit loop here
00590     if (innerSet.getSize()==0) {
00591       error = kTRUE ; 
00592       break ;
00593     }
00594 
00595     // Prepare name and title of integral to be created
00596     TString title(integrand->GetTitle()) ;
00597     title.Prepend("Integral of ") ;
00598 
00599     TString name(integrand->GetName()) ;
00600     name.Append(integrand->integralNameSuffix(innerSet,nset,rangeName)) ;
00601 
00602     // Construct innermost integral
00603     integral = new RooRealIntegral(name,title,*integrand,innerSet,nset,cfg,rangeName) ;
00604 
00605     // Integral of integral takes ownership of innermost integral
00606     if (integrand != this) {
00607       integral->addOwnedComponents(*integrand) ;
00608     }
00609 
00610     // Remove already integrated observables from to-do list
00611     iset.remove(innerSet) ;
00612 
00613     // Send info message on recursion if needed
00614     if (integrand == this && iset.getSize()>0) {
00615       coutI(Integration) << GetName() << " : multidimensional integration over observables with parameterized ranges in terms of other integrated observables detected, using recursive integration strategy to construct final integral" << endl ;
00616     }
00617 
00618     // Prepare for recursion, next integral should integrate last integrand
00619     integrand = integral ;
00620 
00621 
00622     // Only need normalization set in innermost integration
00623     nset = 0 ; 
00624   }
00625 
00626   if (error) {
00627     coutE(Integration) << GetName() << " : ERROR while defining recursive integral over observables with parameterized integration ranges, please check that integration rangs specify uniquely defined integral " << endl; 
00628     delete integral ;
00629     integral = 0 ;
00630   }
00631 
00632   return integral ;
00633 }
00634 
00635 
00636 
00637 //_____________________________________________________________________________
00638 void RooAbsReal::findInnerMostIntegration(const RooArgSet& allObs, RooArgSet& innerObs, const char* rangeName) const
00639 {
00640   // Utility function for createIntObj() that aids in the construct of recursive integrals
00641   // over functions with multiple observables with parameterized ranges. This function
00642   // finds in a given set allObs over which integration is requested the largeset subset
00643   // of observables that can be integrated simultaneously. This subset consists of
00644   // observables with fixed ranges and observables with parameterized ranges whose
00645   // parameterization does not depend on any observable that is also integrated.
00646 
00647   // Make lists of 
00648   // a) integrated observables with fixed ranges, 
00649   // b) integrated observables with parameterized ranges depending on other integrated observables
00650   // c) integrated observables used in definition of any parameterized ranges of integrated observables
00651   RooArgSet obsWithFixedRange(allObs) ;
00652   RooArgSet obsWithParamRange ;
00653   RooArgSet obsServingAsRangeParams ;
00654 
00655   // Loop over all integrated observables
00656   TIterator* oiter = allObs.createIterator() ;
00657   RooAbsArg* aarg ;
00658   while((aarg=(RooAbsArg*)oiter->Next())) {
00659     // Check if observable is real-valued lvalue
00660     RooAbsRealLValue* arglv = dynamic_cast<RooAbsRealLValue*>(aarg) ;
00661     if (arglv) {
00662 
00663       // Check if range is parameterized
00664       RooAbsBinning& binning = arglv->getBinning(rangeName,kTRUE,kTRUE) ;
00665       if (binning.isParameterized()) { 
00666         RooArgSet* loBoundObs = binning.lowBoundFunc()->getObservables(allObs) ;
00667         RooArgSet* hiBoundObs = binning.highBoundFunc()->getObservables(allObs) ;
00668 
00669         // Check if range parameterization depends on other integrated observables
00670         if (loBoundObs->overlaps(allObs) || hiBoundObs->overlaps(allObs)) {
00671           obsWithParamRange.add(*aarg) ;
00672           obsWithFixedRange.remove(*aarg) ;
00673           obsServingAsRangeParams.add(*loBoundObs,kFALSE) ;
00674           obsServingAsRangeParams.add(*hiBoundObs,kFALSE) ;
00675         }
00676         delete loBoundObs ;
00677         delete hiBoundObs ;
00678       }
00679     }
00680   }
00681   delete oiter ;
00682 
00683   // Make list of fixed-range observables that are _not_ involved in the parameterization of ranges of other observables
00684   RooArgSet obsWithFixedRangeNP(obsWithFixedRange) ;
00685   obsWithFixedRangeNP.remove(obsServingAsRangeParams) ; 
00686   
00687   // Make list of param-range observables that are _not_ involved in the parameterization of ranges of other observables
00688   RooArgSet obsWithParamRangeNP(obsWithParamRange) ;
00689   obsWithParamRangeNP.remove(obsServingAsRangeParams) ; 
00690   
00691   // Construct inner-most integration: over observables (with fixed or param range) not used in any other param range definitions
00692   innerObs.removeAll() ;
00693   innerObs.add(obsWithFixedRangeNP) ;
00694   innerObs.add(obsWithParamRangeNP) ;
00695 
00696 }
00697 
00698 
00699 //_____________________________________________________________________________
00700 TString RooAbsReal::integralNameSuffix(const RooArgSet& iset, const RooArgSet* nset, const char* rangeName, Bool_t omitEmpty) const 
00701 {
00702   // Construct string with unique suffix name to give to integral object that encodes
00703   // integrated observables, normalization observables and the integration range name
00704   
00705   TString name ;
00706   if (iset.getSize()>0) {
00707 
00708     RooArgSet isetTmp(iset) ;
00709     isetTmp.sort() ;  
00710 
00711     name.Append("_Int[") ;
00712     TIterator* iter = isetTmp.createIterator() ;
00713     RooAbsArg* arg ;
00714     Bool_t first(kTRUE) ;
00715     while((arg=(RooAbsArg*)iter->Next())) {
00716       if (first) {
00717         first=kFALSE ;
00718       } else {
00719         name.Append(",") ;
00720       }
00721       name.Append(arg->GetName()) ;
00722     }
00723     delete iter ;
00724     if (rangeName) {
00725       name.Append("|") ;
00726       name.Append(rangeName) ;
00727     }
00728     name.Append("]");
00729   } else if (!omitEmpty) {
00730     name.Append("_Int[]") ;
00731   }
00732 
00733   if (nset && nset->getSize()>0 ) {
00734 
00735     RooArgSet nsetTmp(*nset) ;
00736     nsetTmp.sort() ;
00737 
00738     name.Append("_Norm[") ;
00739     Bool_t first(kTRUE); 
00740     TIterator* iter  = nsetTmp.createIterator() ;
00741     RooAbsArg* arg ;
00742     while((arg=(RooAbsArg*)iter->Next())) {
00743       if (first) {
00744         first=kFALSE ;
00745       } else {
00746         name.Append(",") ;
00747       }
00748       name.Append(arg->GetName()) ;
00749     }
00750     delete iter ;
00751     const RooAbsPdf* thisPdf = dynamic_cast<const RooAbsPdf*>(this) ;    
00752     if (thisPdf && thisPdf->normRange()) {
00753       name.Append("|") ;
00754       name.Append(thisPdf->normRange()) ;
00755     }
00756     name.Append("]") ;
00757   }
00758 
00759   return name ;
00760 }
00761 
00762 
00763 
00764 //_____________________________________________________________________________
00765 const RooAbsReal* RooAbsReal::createPlotProjection(const RooArgSet& depVars, const RooArgSet& projVars, 
00766                                                RooArgSet*& cloneSet) const 
00767 {
00768   // Utility function for plotOn() that creates a projection of a function or p.d.f 
00769   // to be plotted on a RooPlot. 
00770   return createPlotProjection(depVars,&projVars,cloneSet) ; 
00771 }
00772 
00773 
00774 
00775 //_____________________________________________________________________________
00776 const RooAbsReal* RooAbsReal::createPlotProjection(const RooArgSet& depVars, const RooArgSet& projVars) const 
00777 {
00778   // Utility function for plotOn() that creates a projection of a function or p.d.f 
00779   // to be plotted on a RooPlot. 
00780   RooArgSet* cloneSet = new RooArgSet() ;
00781   return createPlotProjection(depVars,&projVars,cloneSet) ; 
00782 }
00783 
00784 
00785 
00786 //_____________________________________________________________________________
00787 const RooAbsReal *RooAbsReal::createPlotProjection(const RooArgSet &dependentVars, const RooArgSet *projectedVars,
00788                                                    RooArgSet *&cloneSet, const char* rangeName, const RooArgSet* condObs) const 
00789 {
00790   // Utility function for plotOn() that creates a projection of a function or p.d.f 
00791   // to be plotted on a RooPlot. 
00792   //
00793   // Create a new object G that represents the normalized projection:
00794   //
00795   //             Integral [ F[x,y,p] , { y } ]
00796   //  G[x,p] = ---------------------------------
00797   //            Integral [ F[x,y,p] , { x,y } ]
00798   //
00799   // where F[x,y,p] is the function we represent, "x" are the
00800   // specified dependentVars, "y" are the specified projectedVars, and
00801   // "p" are our remaining variables ("parameters"). Return a
00802   // pointer to the newly created object, or else zero in case of an
00803   // error.  The caller is responsible for deleting the contents of
00804   // cloneSet (which includes the returned projection object) 
00805 
00806   // Get the set of our leaf nodes
00807   RooArgSet leafNodes;
00808   RooArgSet treeNodes;
00809   leafNodeServerList(&leafNodes,this);
00810   treeNodeServerList(&treeNodes,this) ;
00811 
00812 
00813   // Check that the dependents are all fundamental. Filter out any that we
00814   // do not depend on, and make substitutions by name in our leaf list.
00815   // Check for overlaps with the projection variables.
00816 
00817   TIterator *dependentIterator= dependentVars.createIterator();
00818   assert(0 != dependentIterator);
00819   const RooAbsArg *arg = 0;
00820   while((arg= (const RooAbsArg*)dependentIterator->Next())) {
00821     if(!arg->isFundamental() && !dynamic_cast<const RooAbsLValue*>(arg)) {
00822       coutE(Plotting) << ClassName() << "::" << GetName() << ":createPlotProjection: variable \"" << arg->GetName()
00823            << "\" of wrong type: " << arg->ClassName() << endl;
00824       delete dependentIterator;
00825       return 0;
00826     }
00827 
00828     RooAbsArg *found= treeNodes.find(arg->GetName()); 
00829     if(!found) {
00830       coutE(Plotting) << ClassName() << "::" << GetName() << ":createPlotProjection: \"" << arg->GetName()
00831                       << "\" is not a dependent and will be ignored." << endl;
00832       continue;
00833     }
00834     if(found != arg) {
00835       if (leafNodes.find(found->GetName())) {
00836         leafNodes.replace(*found,*arg);
00837       } else {
00838         leafNodes.add(*arg) ;
00839 
00840         // Remove any dependents of found, replace by dependents of LV node
00841         RooArgSet* lvDep = arg->getObservables(&leafNodes) ;
00842         RooAbsArg* lvs ;
00843         TIterator* iter = lvDep->createIterator() ;
00844         while((lvs=(RooAbsArg*)iter->Next())) {
00845           RooAbsArg* tmp = leafNodes.find(lvs->GetName()) ;
00846           if (tmp) {
00847             leafNodes.remove(*tmp) ;
00848             leafNodes.add(*lvs) ;
00849           }
00850         }
00851         delete iter ;
00852         
00853       }
00854     }
00855 
00856     // check if this arg is also in the projection set
00857     if(0 != projectedVars && projectedVars->find(arg->GetName())) {
00858       coutE(Plotting) << ClassName() << "::" << GetName() << ":createPlotProjection: \"" << arg->GetName()
00859                       << "\" cannot be both a dependent and a projected variable." << endl;
00860       delete dependentIterator;
00861       return 0;
00862     }
00863   }
00864 
00865   // Remove the projected variables from the list of leaf nodes, if necessary.
00866   if(0 != projectedVars) leafNodes.remove(*projectedVars,kTRUE);
00867 
00868   // Make a deep-clone of ourself so later operations do not disturb our original state
00869   cloneSet= (RooArgSet*)RooArgSet(*this).snapshot(kTRUE);
00870   if (!cloneSet) {
00871     coutE(Plotting) << "RooAbsPdf::createPlotProjection(" << GetName() << ") Couldn't deep-clone PDF, abort," << endl ;
00872     return 0 ;
00873   }
00874   RooAbsReal *theClone= (RooAbsReal*)cloneSet->find(GetName());
00875 
00876   // The remaining entries in our list of leaf nodes are the the external
00877   // dependents (x) and parameters (p) of the projection. Patch them back
00878   // into the theClone. This orphans the nodes they replace, but the orphans
00879   // are still in the cloneList and so will be cleaned up eventually.
00880   //cout << "redirection leafNodes : " ; leafNodes.Print("1") ;
00881 
00882   RooArgSet* plotLeafNodes = (RooArgSet*) leafNodes.selectCommon(dependentVars) ;
00883   theClone->recursiveRedirectServers(*plotLeafNodes,kFALSE,kFALSE,kFALSE);
00884   delete plotLeafNodes ;
00885 
00886   // Create the set of normalization variables to use in the projection integrand
00887   RooArgSet normSet(dependentVars);
00888   if(0 != projectedVars) normSet.add(*projectedVars);
00889   if(0 != condObs) {
00890     normSet.remove(*condObs,kTRUE,kTRUE) ;
00891   }
00892   
00893   // Try to create a valid projection integral. If no variables are to be projected,
00894   // create a null projection anyway to bind our normalization over the dependents
00895   // consistently with the way they would be bound with a non-trivial projection.
00896   RooArgSet empty;
00897   if(0 == projectedVars) projectedVars= &empty;
00898 
00899   TString name = GetName() ;
00900   name += integralNameSuffix(*projectedVars,&normSet,rangeName,kTRUE) ;
00901 
00902   TString title(GetTitle());  
00903   title.Prepend("Projection of ");
00904 
00905   RooRealIntegral *projected= new RooRealIntegral(name.Data(),title.Data(),*theClone,*projectedVars,&normSet,0,rangeName);
00906   if(0 == projected || !projected->isValid()) {
00907     coutE(Plotting) << ClassName() << "::" << GetName() << ":createPlotProjection: cannot integrate out ";
00908     projectedVars->printStream(cout,kName|kArgs,kSingleLine);
00909     // cleanup and exit
00910     if(0 != projected) delete projected;
00911     delete dependentIterator;
00912     return 0;
00913   }
00914   // Add the projection integral to the cloneSet so that it eventually gets cleaned up by the caller.
00915   cloneSet->addOwned(*projected);
00916 
00917   // cleanup
00918   delete dependentIterator;
00919 
00920   // return a const pointer to remind the caller that they do not delete the returned object
00921   // directly (it is contained in the cloneSet instead).
00922   return projected;
00923 }
00924 
00925 
00926 
00927 
00928 //_____________________________________________________________________________
00929 TH1 *RooAbsReal::fillHistogram(TH1 *hist, const RooArgList &plotVars,
00930                                Double_t scaleFactor, const RooArgSet *projectedVars, Bool_t scaleForDensity,
00931                                const RooArgSet* condObs, Bool_t setError) const 
00932 {
00933   // Fill the ROOT histogram 'hist' with values sampled from this
00934   // function at the bin centers.  Our value is calculated by first
00935   // integrating out any variables in projectedVars and then scaling
00936   // the result by scaleFactor. Returns a pointer to the input
00937   // histogram, or zero in case of an error. The input histogram can
00938   // be any TH1 subclass, and therefore of arbitrary
00939   // dimension. Variables are matched with the (x,y,...) dimensions of
00940   // the input histogram according to the order in which they appear
00941   // in the input plotVars list. If scaleForDensity is true the
00942   // histogram is filled with a the functions density rather than
00943   // the functions value (i.e. the value at the bin center is multiplied
00944   // with bin volume)
00945 
00946   // Do we have a valid histogram to use?
00947   if(0 == hist) {
00948     coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillHistogram: no valid histogram to fill" << endl;
00949     return 0;
00950   }
00951 
00952   // Check that the number of plotVars matches the input histogram's dimension
00953   Int_t hdim= hist->GetDimension();
00954   if(hdim != plotVars.getSize()) {
00955     coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillHistogram: plotVars has the wrong dimension" << endl;
00956     return 0;
00957   }
00958 
00959 
00960   // Check that the plot variables are all actually RooRealVars and print a warning if we do not
00961   // explicitly depend on one of them. Fill a set (not list!) of cloned plot variables.
00962   RooArgSet plotClones;
00963   for(Int_t index= 0; index < plotVars.getSize(); index++) {
00964     const RooAbsArg *var= plotVars.at(index);
00965     const RooRealVar *realVar= dynamic_cast<const RooRealVar*>(var);
00966     if(0 == realVar) {
00967       coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillHistogram: cannot plot variable \"" << var->GetName()
00968            << "\" of type " << var->ClassName() << endl;
00969       return 0;
00970     }
00971     if(!this->dependsOn(*realVar)) {
00972       coutE(InputArguments) << ClassName() << "::" << GetName()
00973            << ":fillHistogram: WARNING: variable is not an explicit dependent: " << realVar->GetName() << endl;
00974     }
00975     plotClones.addClone(*realVar,kTRUE); // do not complain about duplicates
00976   }
00977 
00978   // Reconnect all plotClones to each other, imported when plotting N-dim integrals with entangled parameterized ranges
00979   TIterator* pciter= plotClones.createIterator() ;
00980   RooAbsArg* pc ;
00981   while((pc=(RooAbsArg*)pciter->Next())) {
00982     pc->recursiveRedirectServers(plotClones,kFALSE,kFALSE,kTRUE) ;
00983   }
00984 
00985   delete pciter ;
00986   
00987 
00988 
00989   // Call checkObservables
00990   RooArgSet allDeps(plotClones) ;
00991   if (projectedVars) {
00992     allDeps.add(*projectedVars) ;
00993   }
00994   if (checkObservables(&allDeps)) {
00995     coutE(InputArguments) << "RooAbsReal::fillHistogram(" << GetName() << ") error in checkObservables, abort" << endl ;
00996     return hist ;
00997   }
00998 
00999   // Create a standalone projection object to use for calculating bin contents
01000   RooArgSet *cloneSet = 0;
01001   const RooAbsReal *projected= createPlotProjection(plotClones,projectedVars,cloneSet,0,condObs);
01002   cxcoutD(Plotting) << "RooAbsReal::fillHistogram(" << GetName() << ") plot projection object is " << projected->GetName() << endl ;
01003 
01004   // Prepare to loop over the histogram bins
01005   Int_t xbins(0),ybins(1),zbins(1);
01006   RooRealVar *xvar = 0;
01007   RooRealVar *yvar = 0;
01008   RooRealVar *zvar = 0;
01009   TAxis *xaxis = 0;
01010   TAxis *yaxis = 0;
01011   TAxis *zaxis = 0;
01012   switch(hdim) {
01013   case 3:
01014     zbins= hist->GetNbinsZ();
01015     zvar= dynamic_cast<RooRealVar*>(plotClones.find(plotVars.at(2)->GetName()));
01016     zaxis= hist->GetZaxis();
01017     assert(0 != zvar && 0 != zaxis);
01018     if (scaleForDensity) {
01019       scaleFactor*= (zaxis->GetXmax() - zaxis->GetXmin())/zbins;
01020     }
01021     // fall through to next case...
01022   case 2:
01023     ybins= hist->GetNbinsY(); 
01024     yvar= dynamic_cast<RooRealVar*>(plotClones.find(plotVars.at(1)->GetName()));
01025     yaxis= hist->GetYaxis();
01026     assert(0 != yvar && 0 != yaxis);
01027     if (scaleForDensity) {
01028       scaleFactor*= (yaxis->GetXmax() - yaxis->GetXmin())/ybins;
01029     }
01030     // fall through to next case...
01031   case 1:
01032     xbins= hist->GetNbinsX();
01033     xvar= dynamic_cast<RooRealVar*>(plotClones.find(plotVars.at(0)->GetName()));
01034     xaxis= hist->GetXaxis();
01035     assert(0 != xvar && 0 != xaxis);
01036     if (scaleForDensity) {
01037       scaleFactor*= (xaxis->GetXmax() - xaxis->GetXmin())/xbins;
01038     }
01039     break;
01040   default:
01041     coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillHistogram: cannot fill histogram with "
01042                           << hdim << " dimensions" << endl;
01043     break;
01044   }
01045 
01046   // Loop over the input histogram's bins and fill each one with our projection's
01047   // value, calculated at the center.
01048   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
01049   Int_t xbin(0),ybin(0),zbin(0);
01050   Int_t bins= xbins*ybins*zbins;
01051   for(Int_t bin= 0; bin < bins; bin++) {
01052     switch(hdim) {
01053     case 3:
01054       if(bin % (xbins*ybins) == 0) {
01055         zbin++;
01056         zvar->setVal(zaxis->GetBinCenter(zbin));
01057       }
01058       // fall through to next case...
01059     case 2:
01060       if(bin % xbins == 0) {
01061         ybin= (ybin%ybins) + 1;
01062         yvar->setVal(yaxis->GetBinCenter(ybin));
01063       }
01064       // fall through to next case...
01065     case 1:
01066       xbin= (xbin%xbins) + 1;
01067       xvar->setVal(xaxis->GetBinCenter(xbin));
01068       break;
01069     default:
01070       coutE(InputArguments) << "RooAbsReal::fillHistogram: Internal Error!" << endl;
01071       break;
01072     }
01073 
01074     Double_t result= scaleFactor*projected->getVal();
01075     if (RooAbsReal::numEvalErrors()>0) {
01076       coutW(Plotting) << "WARNING: Function evaluation error(s) at coordinates [x]=" << xvar->getVal() ;
01077       if (hdim==2) ccoutW(Plotting) << " [y]=" << yvar->getVal() ;
01078       if (hdim==3) ccoutW(Plotting) << " [z]=" << zvar->getVal() ;
01079       ccoutW(Plotting) << endl ;
01080       // RooAbsReal::printEvalErrors(ccoutW(Plotting),10) ;
01081       result = 0 ;
01082     }
01083     RooAbsReal::clearEvalErrorLog() ;
01084     
01085     hist->SetBinContent(hist->GetBin(xbin,ybin,zbin),result);
01086     if (setError) {
01087       hist->SetBinError(hist->GetBin(xbin,ybin,zbin),result) ;
01088     }
01089     //cout << "bin " << bin << " -> (" << xbin << "," << ybin << "," << zbin << ") = " << result << endl;
01090   }
01091   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
01092 
01093   // cleanup
01094   delete cloneSet;
01095 
01096   return hist;
01097 }
01098 
01099 
01100 
01101 //_____________________________________________________________________________
01102 RooDataHist* RooAbsReal::fillDataHist(RooDataHist *hist, const RooArgSet* normSet, Double_t scaleFactor, 
01103                                       Bool_t correctForBinSize, Bool_t showProgress) const 
01104 {
01105   // Fill a RooDataHist with values sampled from this function at the
01106   // bin centers.  If extendedMode is true, the p.d.f. values is multiplied
01107   // by the number of expected events in each bin
01108   // 
01109   // An optional scaling by a given scaleFactor can be performed. 
01110   // Returns a pointer to the input RooDataHist, or zero
01111   // in case of an error. 
01112   //
01113   // If correctForBinSize is true the RooDataHist
01114   // is filled with the functions density (function value times the
01115   // bin volume) rather than function value.  
01116   //
01117   // If showProgress is true
01118   // a process indicator is printed on stdout in steps of one percent,
01119   // which is mostly useful for the sampling of expensive functions
01120   // such as likelihoods
01121 
01122   // Do we have a valid histogram to use?
01123   if(0 == hist) {
01124     coutE(InputArguments) << ClassName() << "::" << GetName() << ":fillDataHist: no valid RooDataHist to fill" << endl;
01125     return 0;
01126   }
01127 
01128   // Call checkObservables
01129   RooArgSet allDeps(*hist->get()) ;
01130   if (checkObservables(&allDeps)) {
01131     coutE(InputArguments) << "RooAbsReal::fillDataHist(" << GetName() << ") error in checkObservables, abort" << endl ;
01132     return hist ;
01133   }
01134   
01135   // Make deep clone of self and attach to dataset observables
01136   RooArgSet* origObs = getObservables(hist) ;  
01137   //RooArgSet* cloneSet = (RooArgSet*) RooArgSet(*this).snapshot(kTRUE) ;
01138   //RooAbsReal* theClone = (RooAbsReal*) cloneSet->find(GetName()) ;
01139   const_cast<RooAbsReal*>(this)->recursiveRedirectServers(*hist->get()) ;
01140   
01141   // Iterator over all bins of RooDataHist and fill weights
01142   Int_t onePct = hist->numEntries()/100 ;
01143   if (onePct==0) {
01144     onePct++ ;
01145   }
01146   for (Int_t i=0 ; i<hist->numEntries() ; i++) {    
01147     if (showProgress && (i%onePct==0)) {
01148       ccoutP(Eval) << "." << flush ;
01149     }
01150     const RooArgSet* obs = hist->get(i) ;
01151     Double_t binVal = /*theClone->*/getVal(normSet?normSet:obs)*scaleFactor ;
01152     if (correctForBinSize) binVal*= hist->binVolume() ;
01153     hist->set(binVal) ;
01154   }
01155 
01156   //delete cloneSet ;
01157   const_cast<RooAbsReal*>(this)->recursiveRedirectServers(*origObs) ;
01158   delete origObs ;
01159 
01160   return hist;
01161 }
01162 
01163 
01164 
01165 
01166 //_____________________________________________________________________________
01167 TH1* RooAbsReal::createHistogram(const char* varNameList, Int_t xbins, Int_t ybins, Int_t zbins) const 
01168 {
01169   // Create and fill a ROOT histogram TH1,TH2 or TH3 with the values of this function for the variables with given names
01170   // The number of bins can be controlled using the [xyz]bins parameters. For a greater degree of control
01171   // use the createHistogram() method below with named arguments
01172   //
01173   // The caller takes ownership of the returned histogram
01174 
01175   // Parse list of variable names
01176   char buf[1024] ;
01177   strlcpy(buf,varNameList,1024) ;
01178   char* varName = strtok(buf,",:") ;
01179 
01180   RooArgSet* vars = getVariables() ;
01181   
01182   RooRealVar* xvar = (RooRealVar*) vars->find(varName) ;
01183   varName = strtok(0,",") ;
01184   RooRealVar* yvar = varName ? (RooRealVar*) vars->find(varName) : 0 ;
01185   varName = strtok(0,",") ;
01186   RooRealVar* zvar = varName ? (RooRealVar*) vars->find(varName) : 0 ;
01187 
01188   delete vars ;
01189 
01190   // Construct list of named arguments to pass to the implementation version of createHistogram()
01191 
01192   RooLinkedList argList ; 
01193   if (xbins>0) {
01194     argList.Add(RooFit::Binning(xbins).Clone()) ;
01195   }
01196  
01197   if (yvar) {        
01198     if (ybins>0) {
01199       argList.Add(RooFit::YVar(*yvar,RooFit::Binning(ybins)).Clone()) ;
01200     } else {
01201       argList.Add(RooFit::YVar(*yvar).Clone()) ;
01202     }
01203   }
01204 
01205 
01206   if (zvar) {        
01207     if (zbins>0) {
01208       argList.Add(RooFit::ZVar(*zvar,RooFit::Binning(zbins)).Clone()) ;
01209     } else {
01210       argList.Add(RooFit::ZVar(*zvar).Clone()) ;
01211     }
01212   }
01213 
01214 
01215   // Call implementation function
01216   TH1* result = createHistogram(GetName(),*xvar,argList) ;
01217 
01218   // Delete temporary list of RooCmdArgs 
01219   argList.Delete() ;
01220 
01221   return result ;
01222 }
01223 
01224 
01225 
01226 //_____________________________________________________________________________
01227 TH1 *RooAbsReal::createHistogram(const char *name, const RooAbsRealLValue& xvar,
01228                                  const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3, const RooCmdArg& arg4, 
01229                                  const RooCmdArg& arg5, const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) const 
01230 {
01231   // Create and fill a ROOT histogram TH1,TH2 or TH3 with the values of this function. 
01232   //
01233   // This function accepts the following arguments
01234   //
01235   // name -- Name of the ROOT histogram
01236   // xvar -- Observable to be mapped on x axis of ROOT histogram
01237   //
01238   // Binning(const char* name)                    -- Apply binning with given name to x axis of histogram
01239   // Binning(RooAbsBinning& binning)              -- Apply specified binning to x axis of histogram
01240   // Binning(int nbins, [double lo, double hi])   -- Apply specified binning to x axis of histogram
01241   // ConditionalObservables(const RooArgSet& set) -- Do not normalized PDF over following observables when projecting PDF into histogram
01242   // Scaling(Bool_t)                              -- Apply density-correction scaling (multiply by bin volume), default is kTRUE
01243   //
01244   // YVar(const RooAbsRealLValue& var,...)    -- Observable to be mapped on y axis of ROOT histogram
01245   // ZVar(const RooAbsRealLValue& var,...)    -- Observable to be mapped on z axis of ROOT histogram
01246   //
01247   // The YVar() and ZVar() arguments can be supplied with optional Binning() arguments to control the binning of the Y and Z axes, e.g.
01248   // createHistogram("histo",x,Binning(-1,1,20), YVar(y,Binning(-1,1,30)), ZVar(z,Binning("zbinning")))
01249   //
01250   // The caller takes ownership of the returned histogram
01251 
01252 
01253   RooLinkedList l ;
01254   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
01255   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
01256   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
01257   l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
01258 
01259   return createHistogram(name,xvar,l) ;
01260 }
01261 
01262 
01263 //_____________________________________________________________________________
01264 TH1* RooAbsReal::createHistogram(const char *name, const RooAbsRealLValue& xvar, RooLinkedList& argList) const 
01265 {
01266   // Internal method implementing createHistogram
01267 
01268 
01269   // Define configuration for this method
01270   RooCmdConfig pc(Form("RooAbsReal::createHistogram(%s)",GetName())) ;
01271   pc.defineInt("scaling","Scaling",0,1) ;
01272   pc.defineSet("projObs","ProjectedObservables",0,0) ;
01273   pc.defineObject("yvar","YVar",0,0) ;
01274   pc.defineObject("zvar","ZVar",0,0) ;  
01275   pc.allowUndefined() ;
01276 
01277   // Process & check varargs 
01278   pc.process(argList) ;
01279   if (!pc.ok(kTRUE)) {
01280     return 0 ;
01281   }
01282 
01283   RooArgList vars(xvar) ;
01284   RooAbsArg* yvar = static_cast<RooAbsArg*>(pc.getObject("yvar")) ;
01285   if (yvar) {
01286     vars.add(*yvar) ;
01287   }
01288   RooAbsArg* zvar = static_cast<RooAbsArg*>(pc.getObject("zvar")) ;
01289   if (zvar) {
01290     vars.add(*zvar) ;
01291   }
01292 
01293   RooArgSet* projObs = pc.getSet("projObs") ;
01294   RooArgSet* intObs = 0 ;
01295 
01296   Bool_t doScaling = pc.getInt("scaling") ;
01297 
01298   RooLinkedList argListCreate(argList) ;
01299   pc.stripCmdList(argListCreate,"Scaling,ProjectedObservables") ;
01300 
01301   TH1* histo = xvar.createHistogram(name,argListCreate) ;
01302   fillHistogram(histo,vars,1.0,intObs,doScaling,projObs,kFALSE) ;
01303 
01304   return histo ;
01305 }
01306 
01307 
01308 
01309 //_____________________________________________________________________________
01310 RooPlot* RooAbsReal::plotOn(RooPlot* frame, const RooCmdArg& arg1, const RooCmdArg& arg2,
01311                             const RooCmdArg& arg3, const RooCmdArg& arg4,
01312                             const RooCmdArg& arg5, const RooCmdArg& arg6,
01313                             const RooCmdArg& arg7, const RooCmdArg& arg8,
01314                             const RooCmdArg& arg9, const RooCmdArg& arg10) const
01315 {
01316   // Plot (project) PDF on specified frame. If a PDF is plotted in an empty frame, it
01317   // will show a unit normalized curve in the frame variable, taken at the present value 
01318   // of other observables defined for this PDF
01319   //
01320   // If a PDF is plotted in a frame in which a dataset has already been plotted, it will
01321   // show a projected curve integrated over all variables that were present in the shown
01322   // dataset except for the one on the x-axis. The normalization of the curve will also
01323   // be adjusted to the event count of the plotted dataset. An informational message
01324   // will be printed for each projection step that is performed
01325   //
01326   // This function takes the following named arguments
01327   //
01328   // Projection control
01329   // ------------------
01330   // Slice(const RooArgSet& set)     -- Override default projection behaviour by omittting observables listed 
01331   //                                    in set from the projection, resulting a 'slice' plot. Slicing is usually
01332   //                                    only sensible in discrete observables. The slice is position at the 'current'
01333   //                                    value of the observable objects
01334   //
01335   // Slice(RooCategory& cat,         -- Override default projection behaviour by omittting specified category 
01336   //       const char* label)           observable from the projection, resulting in a 'slice' plot. The slice is positioned
01337   //                                    at the given label value. Multiple Slice() commands can be given to specify slices
01338   //                                    in multiple observables
01339   //
01340   // Project(const RooArgSet& set)   -- Override default projection behaviour by projecting over observables
01341   //                                    given in set and complete ignoring the default projection behavior. Advanced use only.
01342   //
01343   // ProjWData(const RooAbsData& d)  -- Override default projection _technique_ (integration). For observables present in given dataset
01344   //                                    projection of PDF is achieved by constructing an average over all observable values in given set.
01345   //                                    Consult RooFit plotting tutorial for further explanation of meaning & use of this technique
01346   //
01347   // ProjWData(const RooArgSet& s,   -- As above but only consider subset 's' of observables in dataset 'd' for projection through data averaging
01348   //           const RooAbsData& d)
01349   //
01350   // ProjectionRange(const char* rn) -- Override default range of projection integrals to a different range speficied by given range name.
01351   //                                    This technique allows you to project a finite width slice in a real-valued observable
01352   //
01353   // NumCPU(Int_t ncpu)              -- Number of CPUs to use simultaneously to calculate data-weighted projections (only in combination with ProjWData)
01354   //
01355   //
01356   // Misc content control
01357   // --------------------
01358   // PrintEvalErrors(Int_t numErr)   -- Control number of p.d.f evaluation errors printed per curve. A negative
01359   //                                    value suppress output completely, a zero value will only print the error count per p.d.f component,
01360   //                                    a positive value is will print details of each error up to numErr messages per p.d.f component.
01361   // 
01362   // EvalErrorValue(Double_t value)  -- Set curve points at which (pdf) evaluation error occur to specified value. By default the 
01363   //                                    function value is plotted.
01364   //
01365   // Normalization(Double_t scale,   -- Adjust normalization by given scale factor. Interpretation of number depends on code: Relative:
01366   //                ScaleType code)     relative adjustment factor, NumEvent: scale to match given number of events.
01367   //
01368   // Name(const chat* name)          -- Give curve specified name in frame. Useful if curve is to be referenced later
01369   //
01370   // Asymmetry(const RooCategory& c) -- Show the asymmetry of the PDF in given two-state category [F(+)-F(-)] / [F(+)+F(-)] rather than
01371   //                                    the PDF projection. Category must have two states with indices -1 and +1 or three states with
01372   //                                    indeces -1,0 and +1.
01373   //
01374   // ShiftToZero(Bool_t flag)        -- Shift entire curve such that lowest visible point is at exactly zero. Mostly useful when
01375   //                                    plotting -log(L) or chi^2 distributions
01376   //
01377   // AddTo(const char* name,         -- Add constructed projection to already existing curve with given name and relative weight factors
01378   //                                    double_t wgtSelf, double_t wgtOther)
01379   //
01380   // Plotting control 
01381   // ----------------
01382   // DrawOption(const char* opt)     -- Select ROOT draw option for resulting TGraph object
01383   //
01384   // LineStyle(Int_t style)          -- Select line style by ROOT line style code, default is solid
01385   //
01386   // LineColor(Int_t color)          -- Select line color by ROOT color code, default is blue
01387   //
01388   // LineWidth(Int_t width)          -- Select line with in pixels, default is 3
01389   //
01390   // FillStyle(Int_t style)          -- Select fill style, default is not filled. If a filled style is selected, also use VLines()
01391   //                                    to add vertical downward lines at end of curve to ensure proper closure
01392   // FillColor(Int_t color)          -- Select fill color by ROOT color code
01393   //
01394   // Range(const char* name)         -- Only draw curve in range defined by given name
01395   //
01396   // Range(double lo, double hi)     -- Only draw curve in specified range
01397   //
01398   // VLines()                        -- Add vertical lines to y=0 at end points of curve
01399   //
01400   // Precision(Double_t eps)         -- Control precision of drawn curve w.r.t to scale of plot, default is 1e-3. Higher precision
01401   //                                    will result in more and more densely spaced curve points
01402   //
01403   // Invisible(Bool_t flag)           -- Add curve to frame, but do not display. Useful in combination AddTo()
01404   //
01405   // VisualizeError(const RooFitResult& fitres, Double_t Z=1, Bool_t linearMethod=kTRUE) 
01406   //                                  -- Visualize the uncertainty on the parameters, as given in fitres, at 'Z' sigma'
01407   //
01408   // VisualizeError(const RooFitResult& fitres, const RooArgSet& param, Double_t Z=1, Bool_t linearMethod=kTRUE) ;
01409   //                                  -- Visualize the uncertainty on the subset of parameters 'param', as given in fitres, at 'Z' sigma'
01410   //
01411   //
01412   // Details on error band visualization
01413   // -----------------------------------
01414   //
01415   // By default (linMethod=kTRUE) a linearized error is shown which is calculated as follows
01416   //                                    T            
01417   // error(x) = Z* F_a(x) * Corr(a,a') F_a'(x)
01418   //
01419   // where     F_a(x) = [ f(x,a+da) - f(x,a-da) ] / 2, with f(x) the plotted curve and 'da' taken from the fit result
01420   //       Corr(a,a') = the correlation matrix from the fit result
01421   //                Z = requested significance 'Z sigma band'
01422   //
01423   // The linear method is fast (required 2*N evaluations of the curve, where N is the number of parameters), but may
01424   // not be accurate in the presence of strong correlations (~>0.9) and at Z>2 due to linear and Gaussian approximations made
01425   //
01426   // Alternatively (linMethod=kFALSE), a more robust error is calculated using a sampling method. In this method a number of curves
01427   // is calculated with variations of the parameter values, as drawn from a multi-variate Gaussian p.d.f. that is constructed
01428   // from the fit results covariance matrix. The error(x) is determined by calculating a central interval that capture N% of the variations 
01429   // for each valye of x, where N% is controlled by Z (i.e. Z=1 gives N=68%). The number of sampling curves is chosen to be such
01430   // that at least 30 curves are expected to be outside the N% interval, and is minimally 100 (e.g. Z=1->Ncurve=100, Z=2->Ncurve=659, Z=3->Ncurve=11111)
01431   // Intervals from the sampling method can be asymmetric, and may perform better in the presence of strong correlations, but may take (much)
01432   // longer to calculate
01433 
01434   RooLinkedList l ;
01435   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
01436   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
01437   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
01438   l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
01439   l.Add((TObject*)&arg9) ;  l.Add((TObject*)&arg10) ;
01440   return plotOn(frame,l) ;
01441 }
01442 
01443 
01444 
01445 //_____________________________________________________________________________
01446 RooPlot* RooAbsReal::plotOn(RooPlot* frame, RooLinkedList& argList) const
01447 {
01448   // Internal back-end function of plotOn() with named arguments
01449 
01450   // Special handling here if argList contains RangeWithName argument with multiple
01451   // range names -- Need to translate this call into multiple calls
01452 
01453   RooCmdArg* rcmd = (RooCmdArg*) argList.FindObject("RangeWithName") ;
01454   if (rcmd && TString(rcmd->getString(0)).Contains(",")) {
01455 
01456     // List joint ranges as choice of normalization for all later processing
01457     RooCmdArg rnorm = RooFit::NormRange(rcmd->getString(0)) ;
01458     argList.Add(&rnorm) ;
01459 
01460     list<string> rlist ;
01461 
01462     // Separate named ranges using strtok
01463     char buf[1024] ;
01464     strlcpy(buf,rcmd->getString(0),1024) ;
01465     char* oneRange = strtok(buf,",") ;
01466     while(oneRange) {
01467       rlist.push_back(oneRange) ;
01468       oneRange = strtok(0,",") ;      
01469     }
01470 
01471     for (list<string>::iterator riter=rlist.begin() ; riter!=rlist.end() ; ++riter) {
01472       // Process each range with a separate command with a single range to be plotted
01473       rcmd->setString(0,riter->c_str()) ;
01474       RooAbsReal::plotOn(frame,argList) ;
01475     }
01476     return frame ;
01477     
01478   }
01479 
01480   // Define configuration for this method
01481   RooCmdConfig pc(Form("RooAbsReal::plotOn(%s)",GetName())) ;
01482   pc.defineString("drawOption","DrawOption",0,"L") ;
01483   pc.defineString("projectionRangeName","ProjectionRange",0,"",kTRUE) ;
01484   pc.defineString("curveNameSuffix","CurveNameSuffix",0,"") ;
01485   pc.defineString("sliceCatState","SliceCat",0,"",kTRUE) ;
01486   pc.defineDouble("scaleFactor","Normalization",0,1.0) ;
01487   pc.defineObject("sliceSet","SliceVars",0) ;
01488   pc.defineObject("sliceCatList","SliceCat",0,0,kTRUE) ;
01489   pc.defineObject("projSet","Project",0) ;
01490   pc.defineObject("asymCat","Asymmetry",0) ;
01491   pc.defineDouble("precision","Precision",0,1e-3) ;
01492   pc.defineDouble("evalErrorVal","EvalErrorValue",0,0) ;
01493   pc.defineInt("doEvalError","EvalErrorValue",0,0) ;
01494   pc.defineInt("shiftToZero","ShiftToZero",0,0) ;  
01495   pc.defineObject("projDataSet","ProjData",0) ;
01496   pc.defineObject("projData","ProjData",1) ;
01497   pc.defineObject("errorFR","VisualizeError",0) ;
01498   pc.defineDouble("errorZ","VisualizeError",0,1.) ;
01499   pc.defineSet("errorPars","VisualizeError",0) ;
01500   pc.defineInt("linearMethod","VisualizeError",0,0) ;
01501   pc.defineInt("binProjData","ProjData",0,0) ;
01502   pc.defineDouble("rangeLo","Range",0,-999.) ;
01503   pc.defineDouble("rangeHi","Range",1,-999.) ;
01504   pc.defineInt("numee","PrintEvalErrors",0,10) ;
01505   pc.defineInt("rangeAdjustNorm","Range",0,0) ;
01506   pc.defineInt("rangeWNAdjustNorm","RangeWithName",0,0) ;
01507   pc.defineInt("VLines","VLines",0,2) ; // 2==ExtendedWings
01508   pc.defineString("rangeName","RangeWithName",0,"") ;
01509   pc.defineString("normRangeName","NormRange",0,"") ;
01510   pc.defineInt("lineColor","LineColor",0,-999) ;
01511   pc.defineInt("lineStyle","LineStyle",0,-999) ;
01512   pc.defineInt("lineWidth","LineWidth",0,-999) ;
01513   pc.defineInt("fillColor","FillColor",0,-999) ;
01514   pc.defineInt("fillStyle","FillStyle",0,-999) ;
01515   pc.defineString("curveName","Name",0,"") ;
01516   pc.defineInt("curveInvisible","Invisible",0,0) ;
01517   pc.defineInt("showProg","ShowProgress",0,0) ;
01518   pc.defineInt("numCPU","NumCPU",0,1) ;
01519   pc.defineInt("interleave","NumCPU",1,0) ; 
01520   pc.defineString("addToCurveName","AddTo",0,"") ;
01521   pc.defineDouble("addToWgtSelf","AddTo",0,1.) ;
01522   pc.defineDouble("addToWgtOther","AddTo",1,1.) ;
01523   pc.defineInt("moveToBack","MoveToBack",0,0) ;
01524   pc.defineMutex("SliceVars","Project") ;
01525   pc.defineMutex("AddTo","Asymmetry") ;
01526   pc.defineMutex("Range","RangeWithName") ;
01527   pc.defineMutex("VisualizeError","VisualizeErrorData") ;
01528 
01529   // Process & check varargs 
01530   pc.process(argList) ;
01531   if (!pc.ok(kTRUE)) {
01532     return frame ;
01533   }
01534 
01535   PlotOpt o ;
01536 
01537   RooFitResult* errFR = (RooFitResult*) pc.getObject("errorFR") ;
01538   Double_t errZ = pc.getDouble("errorZ") ;
01539   RooArgSet* errPars = pc.getSet("errorPars") ;
01540   Bool_t linMethod = pc.getInt("linearMethod") ;
01541   if (errFR) {
01542     return plotOnWithErrorBand(frame,*errFR,errZ,errPars,argList,linMethod) ;
01543   }
01544 
01545   // Extract values from named arguments
01546   o.numee       = pc.getInt("numee") ;
01547   o.drawOptions = pc.getString("drawOption") ;
01548   o.curveNameSuffix = pc.getString("curveNameSuffix") ;
01549   o.scaleFactor = pc.getDouble("scaleFactor") ;
01550   o.projData = (const RooAbsData*) pc.getObject("projData") ;
01551   o.binProjData = pc.getInt("binProjData") ;
01552   o.projDataSet = (const RooArgSet*) pc.getObject("projDataSet") ;
01553   o.numCPU = pc.getInt("numCPU") ;
01554   o.interleave = pc.getInt("interleave") ;
01555   o.eeval      = pc.getDouble("evalErrorVal") ;
01556   o.doeeval   = pc.getInt("doEvalError") ;
01557 
01558   const RooArgSet* sliceSetTmp = (const RooArgSet*) pc.getObject("sliceSet") ;
01559   RooArgSet* sliceSet = sliceSetTmp ? ((RooArgSet*) sliceSetTmp->Clone()) : 0 ;
01560   const RooArgSet* projSet = (const RooArgSet*) pc.getObject("projSet") ;
01561   const RooAbsCategoryLValue* asymCat = (const RooAbsCategoryLValue*) pc.getObject("asymCat") ;
01562 
01563 
01564   // Look for category slice arguments and add them to the master slice list if found
01565   const char* sliceCatState = pc.getString("sliceCatState",0,kTRUE) ;
01566   const RooLinkedList& sliceCatList = pc.getObjectList("sliceCatList") ;
01567   if (sliceCatState) {
01568 
01569     // Make the master slice set if it doesnt exist
01570     if (!sliceSet) {
01571       sliceSet = new RooArgSet ;
01572     }
01573 
01574     // Prepare comma separated label list for parsing
01575     char buf[1024] ;
01576     strlcpy(buf,sliceCatState,1024) ;
01577     const char* slabel = strtok(buf,",") ;
01578 
01579     // Loop over all categories provided by (multiple) Slice() arguments
01580     TIterator* iter = sliceCatList.MakeIterator() ;
01581     RooCategory* scat ;
01582     while((scat=(RooCategory*)iter->Next())) {
01583       if (slabel) {
01584         // Set the slice position to the value indicate by slabel
01585         scat->setLabel(slabel) ;
01586         // Add the slice category to the master slice set
01587         sliceSet->add(*scat,kFALSE) ;
01588       }
01589       slabel = strtok(0,",") ;
01590     }
01591     delete iter ;
01592   }
01593 
01594   o.precision = pc.getDouble("precision") ;
01595   o.shiftToZero = (pc.getInt("shiftToZero")!=0) ;
01596   Int_t vlines = pc.getInt("VLines");
01597   if (pc.hasProcessed("Range")) {
01598     o.rangeLo = pc.getDouble("rangeLo") ;
01599     o.rangeHi = pc.getDouble("rangeHi") ;
01600     o.postRangeFracScale = pc.getInt("rangeAdjustNorm") ;
01601     if (vlines==2) vlines=0 ; // Default is NoWings if range was specified
01602   } else if (pc.hasProcessed("RangeWithName")) {    
01603     o.normRangeName = pc.getString("rangeName",0,kTRUE) ;
01604     o.rangeLo = frame->getPlotVar()->getMin(pc.getString("rangeName",0,kTRUE)) ;
01605     o.rangeHi = frame->getPlotVar()->getMax(pc.getString("rangeName",0,kTRUE)) ;
01606     o.postRangeFracScale = pc.getInt("rangeWNAdjustNorm") ;
01607     if (vlines==2) vlines=0 ; // Default is NoWings if range was specified
01608   } 
01609 
01610 
01611   // If separate normalization range was specified this overrides previous settings
01612   if (pc.hasProcessed("NormRange")) {
01613     o.normRangeName = pc.getString("normRangeName") ;
01614     o.postRangeFracScale = kTRUE ;    
01615   }
01616 
01617   o.wmode = (vlines==2)?RooCurve::Extended:(vlines==1?RooCurve::Straight:RooCurve::NoWings) ;
01618   o.projectionRangeName = pc.getString("projectionRangeName",0,kTRUE) ;
01619   o.curveName = pc.getString("curveName",0,kTRUE) ;
01620   o.curveInvisible = pc.getInt("curveInvisible") ;
01621   o.progress = pc.getInt("showProg") ;
01622   o.addToCurveName = pc.getString("addToCurveName",0,kTRUE) ;
01623   o.addToWgtSelf = pc.getDouble("addToWgtSelf") ;
01624   o.addToWgtOther = pc.getDouble("addToWgtOther") ;  
01625 
01626   if (o.addToCurveName && !frame->findObject(o.addToCurveName,RooCurve::Class())) {
01627     coutE(InputArguments) << "RooAbsReal::plotOn(" << GetName() << ") cannot find existing curve " << o.addToCurveName << " to add to in RooPlot" << endl ;
01628     return frame ;
01629   }
01630   
01631   RooArgSet projectedVars ;
01632   if (sliceSet) {
01633     cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") Preprocessing: have slice " << *sliceSet << endl ;
01634 
01635     makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
01636     
01637     // Take out the sliced variables
01638     TIterator* iter = sliceSet->createIterator() ;
01639     RooAbsArg* sliceArg ;
01640     while((sliceArg=(RooAbsArg*)iter->Next())) {
01641       RooAbsArg* arg = projectedVars.find(sliceArg->GetName()) ;
01642       if (arg) {
01643         projectedVars.remove(*arg) ;
01644       } else {
01645         coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") slice variable " 
01646                         << sliceArg->GetName() << " was not projected anyway" << endl ;
01647       }
01648     }
01649     delete iter ;
01650   } else if (projSet) {
01651     cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") Preprocessing: have projSet " << *projSet << endl ;
01652     makeProjectionSet(frame->getPlotVar(),projSet,projectedVars,kFALSE) ;
01653   } else {
01654     cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") Preprocessing: have neither sliceSet nor projSet " << endl ;
01655     makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
01656   }
01657   o.projSet = &projectedVars ;
01658 
01659   cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") Preprocessing: projectedVars = " << projectedVars << endl ;
01660 
01661 
01662   RooPlot* ret ;
01663   if (!asymCat) {
01664     // Forward to actual calculation
01665     ret = RooAbsReal::plotOn(frame,o) ;
01666   } else {        
01667     // Forward to actual calculation
01668     ret = RooAbsReal::plotAsymOn(frame,*asymCat,o) ;
01669   }
01670 
01671   delete sliceSet ;
01672 
01673   // Optionally adjust line/fill attributes
01674   Int_t lineColor = pc.getInt("lineColor") ;
01675   Int_t lineStyle = pc.getInt("lineStyle") ;
01676   Int_t lineWidth = pc.getInt("lineWidth") ;
01677   Int_t fillColor = pc.getInt("fillColor") ;
01678   Int_t fillStyle = pc.getInt("fillStyle") ;
01679   if (lineColor!=-999) ret->getAttLine()->SetLineColor(lineColor) ;
01680   if (lineStyle!=-999) ret->getAttLine()->SetLineStyle(lineStyle) ;
01681   if (lineWidth!=-999) ret->getAttLine()->SetLineWidth(lineWidth) ;
01682   if (fillColor!=-999) ret->getAttFill()->SetFillColor(fillColor) ;
01683   if (fillStyle!=-999) ret->getAttFill()->SetFillStyle(fillStyle) ;
01684 
01685   // Move last inserted object to back to drawing stack if requested
01686   if (pc.getInt("moveToBack") && frame->numItems()>1) {   
01687     frame->drawBefore(frame->getObject(0)->GetName(), frame->getCurve()->GetName());    
01688   }
01689   
01690   return ret ;
01691 }
01692 
01693 
01694 
01695 
01696 //_____________________________________________________________________________
01697 // coverity[PASS_BY_VALUE]
01698 RooPlot* RooAbsReal::plotOn(RooPlot *frame, PlotOpt o) const
01699 {
01700   // Plotting engine function for internal use
01701   // 
01702   // Plot ourselves on given frame. If frame contains a histogram, all dimensions of the plotted
01703   // function that occur in the previously plotted dataset are projected via partial integration,
01704   // otherwise no projections are performed. Optionally, certain projections can be performed
01705   // by summing over the values present in a provided dataset ('projData'), to correctly
01706   // project out data dependents that are not properly described by the PDF (e.g. per-event errors).
01707   //
01708   // The functions value can be multiplied with an optional scale factor. The interpretation
01709   // of the scale factor is unique for generic real functions, for PDFs there are various interpretations
01710   // possible, which can be selection with 'stype' (see RooAbsPdf::plotOn() for details).
01711   //
01712   // The default projection behaviour can be overriden by supplying an optional set of dependents
01713   // to project. For most cases, plotSliceOn() and plotProjOn() provide a more intuitive interface
01714   // to modify the default projection behavour.
01715 
01716   // Sanity checks
01717   if (plotSanityChecks(frame)) return frame ;
01718 
01719   // ProjDataVars is either all projData observables, or the user indicated subset of it
01720   RooArgSet projDataVars ;
01721   if (o.projData) {
01722     cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") have ProjData with observables = " << *o.projData->get() << endl ;
01723     if (o.projDataSet) {
01724       RooArgSet* tmp = (RooArgSet*) o.projData->get()->selectCommon(*o.projDataSet) ;
01725       projDataVars.add(*tmp) ;
01726       cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") have ProjDataSet = " << *o.projDataSet << " will only use this subset of projData" << endl ;
01727       delete tmp ;
01728     } else {
01729       cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") using full ProjData" << endl ;
01730       projDataVars.add(*o.projData->get()) ;
01731     }
01732   }
01733 
01734   cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") ProjDataVars = " << projDataVars << endl ;
01735 
01736   // Make list of variables to be projected
01737   RooArgSet projectedVars ;
01738   RooArgSet sliceSet ;
01739   if (o.projSet) {
01740     cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") have input projSet = " << *o.projSet << endl ;
01741     makeProjectionSet(frame->getPlotVar(),o.projSet,projectedVars,kFALSE) ;
01742     cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") calculated projectedVars = " << *o.projSet << endl ;
01743 
01744     // Print list of non-projected variables
01745     if (frame->getNormVars()) {
01746       RooArgSet *sliceSetTmp = getObservables(*frame->getNormVars()) ;
01747 
01748       cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") frame->getNormVars() that are also observables = " << *sliceSetTmp << endl ;
01749 
01750       sliceSetTmp->remove(projectedVars,kTRUE,kTRUE) ;
01751       sliceSetTmp->remove(*frame->getPlotVar(),kTRUE,kTRUE) ;
01752 
01753       if (o.projData) {
01754         RooArgSet* tmp = (RooArgSet*) projDataVars.selectCommon(*o.projSet) ;
01755         sliceSetTmp->remove(*tmp,kTRUE,kTRUE) ;
01756         delete tmp ;
01757       }
01758 
01759       if (sliceSetTmp->getSize()) {
01760         coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot on " 
01761                         << frame->getPlotVar()->GetName() << " represents a slice in " << *sliceSetTmp << endl ;
01762       }
01763       sliceSet.add(*sliceSetTmp) ;
01764       delete sliceSetTmp ;
01765     }
01766   } else {
01767     makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
01768   }
01769 
01770   cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") projectedVars = " << projectedVars << " sliceSet = " << sliceSet << endl ;
01771 
01772 
01773   RooArgSet* projDataNeededVars = 0 ;
01774   // Take out data-projected dependents from projectedVars
01775   if (o.projData) {
01776     projDataNeededVars = (RooArgSet*) projectedVars.selectCommon(projDataVars) ;
01777     projectedVars.remove(projDataVars,kTRUE,kTRUE) ;
01778   }
01779 
01780   // Clone the plot variable
01781   RooAbsReal* realVar = (RooRealVar*) frame->getPlotVar() ;
01782   RooArgSet* plotCloneSet = (RooArgSet*) RooArgSet(*realVar).snapshot(kTRUE) ;
01783   if (!plotCloneSet) {
01784     coutE(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") Couldn't deep-clone self, abort," << endl ;
01785     return frame ;
01786   }
01787   RooRealVar* plotVar = (RooRealVar*) plotCloneSet->find(realVar->GetName());
01788 
01789   // Inform user about projections
01790   if (projectedVars.getSize()) {
01791     coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot on " << plotVar->GetName() 
01792                     << " integrates over variables " << projectedVars 
01793                     << (o.projectionRangeName?Form(" in range %s",o.projectionRangeName):"") << endl;
01794   }  
01795   if (projDataNeededVars && projDataNeededVars->getSize()>0) {
01796     coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot on " << plotVar->GetName() 
01797                     << " averages using data variables " << *projDataNeededVars << endl ;
01798   }
01799 
01800   // Create projection integral
01801   RooArgSet* projectionCompList ;
01802 
01803   RooArgSet* deps = getObservables(frame->getNormVars()) ;
01804   deps->remove(projectedVars,kTRUE,kTRUE) ;
01805   if (projDataNeededVars) {
01806     deps->remove(*projDataNeededVars,kTRUE,kTRUE) ;
01807   }
01808   deps->remove(*plotVar,kTRUE,kTRUE) ;
01809   deps->add(*plotVar) ;
01810 
01811   // Now that we have the final set of dependents, call checkObservables()
01812 
01813   // WVE take out conditional observables
01814   if (checkObservables(deps)) {
01815     coutE(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") error in checkObservables, abort" << endl ;
01816     delete deps ;
01817     delete plotCloneSet ;
01818     if (projDataNeededVars) delete projDataNeededVars ;
01819     return frame ;
01820   }
01821 
01822   RooArgSet normSet(*deps) ;
01823   //normSet.add(projDataVars) ;
01824 
01825   RooAbsReal *projection = (RooAbsReal*) createPlotProjection(normSet, &projectedVars, projectionCompList, o.projectionRangeName) ;
01826   cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot projection object is " << projection->GetName() << endl ;
01827   if (dologD(Plotting)) {
01828     projection->printStream(ccoutD(Plotting),0,kVerbose) ;
01829   }
01830 
01831   // Always fix RooAddPdf normalizations
01832   RooArgSet fullNormSet(*deps) ;
01833   fullNormSet.add(projectedVars) ;
01834   if (projDataNeededVars && projDataNeededVars->getSize()>0) {
01835     fullNormSet.add(*projDataNeededVars) ;
01836   }
01837   RooArgSet* compSet = projection->getComponents() ;
01838   TIterator* iter = compSet->createIterator() ;
01839   RooAbsArg* arg ;
01840   while((arg=(RooAbsArg*)iter->Next())) {
01841     RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(arg) ;
01842     if (pdf) {
01843       pdf->selectNormalization(&fullNormSet) ;
01844     } 
01845   }
01846   delete iter ;
01847   delete compSet ;
01848   
01849   
01850   // Apply data projection, if requested
01851   if (o.projData && projDataNeededVars && projDataNeededVars->getSize()>0) {
01852 
01853     // If data set contains more rows than needed, make reduced copy first
01854     RooAbsData* projDataSel = (RooAbsData*)o.projData;
01855 
01856     if (projDataNeededVars->getSize()<o.projData->get()->getSize()) {
01857       
01858       // Determine if there are any slice variables in the projection set
01859       RooArgSet* sliceDataSet = (RooArgSet*) sliceSet.selectCommon(*o.projData->get()) ;
01860       TString cutString ;
01861       if (sliceDataSet->getSize()>0) {
01862         TIterator* iter2 = sliceDataSet->createIterator() ;
01863         RooAbsArg* sliceVar ; 
01864         Bool_t first(kTRUE) ;
01865         while((sliceVar=(RooAbsArg*)iter2->Next())) {
01866           if (!first) {
01867             cutString.Append("&&") ;
01868           } else {
01869             first=kFALSE ;          
01870           }
01871 
01872           RooAbsRealLValue* real ;
01873           RooAbsCategoryLValue* cat ;     
01874           if ((real = dynamic_cast<RooAbsRealLValue*>(sliceVar))) {
01875             cutString.Append(Form("%s==%f",real->GetName(),real->getVal())) ;
01876           } else if ((cat = dynamic_cast<RooAbsCategoryLValue*>(sliceVar))) {
01877             cutString.Append(Form("%s==%d",cat->GetName(),cat->getIndex())) ;       
01878           }
01879         }
01880         delete iter2 ;
01881       }
01882       delete sliceDataSet ;
01883 
01884       if (!cutString.IsNull()) {
01885         projDataSel = ((RooAbsData*)o.projData)->reduce(*projDataNeededVars,cutString) ;
01886         coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") reducing given projection dataset to entries with " << cutString << endl ;
01887       } else {
01888         projDataSel = ((RooAbsData*)o.projData)->reduce(*projDataNeededVars) ;
01889       }
01890       coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() 
01891                       << ") only the following components of the projection data will be used: " << *projDataNeededVars << endl ;
01892     }
01893 
01894     // Request binning of unbinned projection dataset that consists exclusively of category observables
01895     if (!o.binProjData && dynamic_cast<RooDataSet*>(projDataSel)!=0) {
01896       
01897       // Determine if dataset contains only categories
01898       TIterator* iter2 = projDataSel->get()->createIterator() ;
01899       Bool_t allCat(kTRUE) ;
01900       RooAbsArg* arg2 ;
01901       while((arg2=(RooAbsArg*)iter2->Next())) {
01902         if (!dynamic_cast<RooCategory*>(arg2)) allCat = kFALSE ;
01903       }
01904       delete iter2 ;
01905       if (allCat) {
01906         o.binProjData = kTRUE ;
01907         coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") unbinned projection dataset consist only of discrete variables,"
01908                         << " performing projection with binned copy for optimization." << endl ;
01909         
01910       }
01911     }
01912 
01913     // Bin projection dataset if requested
01914     if (o.binProjData) {
01915       RooAbsData* tmp = new RooDataHist(Form("%s_binned",projDataSel->GetName()),"Binned projection data",*projDataSel->get(),*projDataSel) ;
01916       if (projDataSel!=o.projData) delete projDataSel ;
01917       projDataSel = tmp ;
01918     }
01919     
01920 
01921 
01922     // Attach dataset
01923     projection->getVal(projDataSel->get()) ;
01924     projection->attachDataSet(*projDataSel) ;
01925     
01926     // Construct optimized data weighted average
01927     RooDataWeightedAverage dwa(Form("%sDataWgtAvg",GetName()),"Data Weighted average",*projection,*projDataSel,RooArgSet()/**projDataSel->get()*/,o.numCPU,o.interleave,kTRUE) ;
01928     //RooDataWeightedAverage dwa(Form("%sDataWgtAvg",GetName()),"Data Weighted average",*projection,*projDataSel,*projDataSel->get(),o.numCPU,o.interleave,kTRUE) ;
01929     dwa.constOptimizeTestStatistic(Activate) ;
01930 
01931     RooRealBinding projBind(dwa,*plotVar) ;
01932     RooScaledFunc scaleBind(projBind,o.scaleFactor);
01933 
01934     // Set default range, if not specified
01935     if (o.rangeLo==0 && o.rangeHi==0) {
01936       o.rangeLo = frame->GetXaxis()->GetXmin() ;
01937       o.rangeHi = frame->GetXaxis()->GetXmax() ;
01938     }
01939     
01940     // Construct name of curve for data weighed average
01941     TString curveName(projection->GetName()) ;
01942     curveName.Append(Form("_DataAvg[%s]",projDataSel->get()->contentsString().c_str())) ;
01943     // Append slice set specification if any
01944     if (sliceSet.getSize()>0) {
01945       curveName.Append(Form("_Slice[%s]",sliceSet.contentsString().c_str())) ;      
01946     }
01947     // Append any suffixes imported from RooAbsPdf::plotOn
01948     if (o.curveNameSuffix) {
01949       curveName.Append(o.curveNameSuffix) ;
01950     }
01951 
01952     // Curve constructor for data weighted average    
01953     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
01954     RooCurve *curve = new RooCurve(projection->GetName(),projection->GetTitle(),scaleBind,
01955                                    o.rangeLo,o.rangeHi,frame->GetNbinsX(),o.precision,o.precision,o.shiftToZero,o.wmode,o.numee,o.doeeval,o.eeval) ;
01956     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
01957 
01958     curve->SetName(curveName.Data()) ;
01959 
01960     // Add self to other curve if requested
01961     if (o.addToCurveName) {
01962       RooCurve* otherCurve = static_cast<RooCurve*>(frame->findObject(o.addToCurveName,RooCurve::Class())) ;
01963 
01964       // Curve constructor for sum of curves
01965       RooCurve* sumCurve = new RooCurve(projection->GetName(),projection->GetTitle(),*curve,*otherCurve,o.addToWgtSelf,o.addToWgtOther) ;
01966       sumCurve->SetName(Form("%s_PLUS_%s",curve->GetName(),otherCurve->GetName())) ;
01967       delete curve ;
01968       curve = sumCurve ;
01969       
01970     }
01971 
01972     if (o.curveName) {
01973       curve->SetName(o.curveName) ;
01974     }
01975 
01976     // add this new curve to the specified plot frame
01977     frame->addPlotable(curve, o.drawOptions);
01978 
01979     if (projDataSel!=o.projData) delete projDataSel ;
01980        
01981   } else {
01982     
01983     // Set default range, if not specified
01984     if (o.rangeLo==0 && o.rangeHi==0) {
01985       o.rangeLo = frame->GetXaxis()->GetXmin() ;
01986       o.rangeHi = frame->GetXaxis()->GetXmax() ;
01987     }
01988 
01989     // Calculate a posteriori range fraction scaling if requested (2nd part of normalization correction for
01990     // result fit on subrange of data)
01991     if (o.postRangeFracScale) {
01992       if (!o.normRangeName) {
01993         o.normRangeName = "plotRange" ;
01994         plotVar->setRange("plotRange",o.rangeLo,o.rangeHi) ;
01995       }
01996 
01997       // Evaluate fractional correction integral always on full p.d.f, not component.
01998       Bool_t tmp = _globalSelectComp ;
01999       globalSelectComp(kTRUE) ;
02000       RooAbsReal* intFrac = projection->createIntegral(*plotVar,*plotVar,o.normRangeName) ;
02001       globalSelectComp(kTRUE) ;
02002       o.scaleFactor /= intFrac->getVal() ;
02003       globalSelectComp(tmp) ;
02004       delete intFrac ;
02005 
02006     }
02007 
02008     // create a new curve of our function using the clone to do the evaluations
02009     // Curve constructor for regular projections
02010 
02011     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
02012     RooCurve *curve = new RooCurve(*projection,*plotVar,o.rangeLo,o.rangeHi,frame->GetNbinsX(),
02013                                    o.scaleFactor,0,o.precision,o.precision,o.shiftToZero,o.wmode,o.numee,o.doeeval,o.eeval,o.progress);
02014     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
02015 
02016 
02017 
02018     // Set default name of curve
02019     TString curveName(projection->GetName()) ;
02020     if (sliceSet.getSize()>0) {
02021       curveName.Append(Form("_Slice[%s]",sliceSet.contentsString().c_str())) ;      
02022     }
02023     if (o.curveNameSuffix) {
02024       // Append any suffixes imported from RooAbsPdf::plotOn
02025       curveName.Append(o.curveNameSuffix) ;
02026     }
02027     curve->SetName(curveName.Data()) ;
02028 
02029 
02030     // Add self to other curve if requested
02031     if (o.addToCurveName) {
02032       RooCurve* otherCurve = static_cast<RooCurve*>(frame->findObject(o.addToCurveName,RooCurve::Class())) ;
02033       RooCurve* sumCurve = new RooCurve(projection->GetName(),projection->GetTitle(),*curve,*otherCurve,o.addToWgtSelf,o.addToWgtOther) ;
02034       sumCurve->SetName(Form("%s_PLUS_%s",curve->GetName(),otherCurve->GetName())) ;
02035       delete curve ;
02036       curve = sumCurve ;
02037     }
02038 
02039     // Override name of curve by user name, if specified
02040     if (o.curveName) {
02041       curve->SetName(o.curveName) ;
02042     }
02043 
02044     // add this new curve to the specified plot frame
02045     frame->addPlotable(curve, o.drawOptions, o.curveInvisible);
02046   }
02047 
02048   if (projDataNeededVars) delete projDataNeededVars ;
02049   delete deps ;
02050   delete projectionCompList ;
02051   delete plotCloneSet ;
02052   return frame;
02053 }
02054 
02055 
02056 
02057 
02058 //_____________________________________________________________________________
02059 RooPlot* RooAbsReal::plotSliceOn(RooPlot *frame, const RooArgSet& sliceSet, Option_t* drawOptions, 
02060                                  Double_t scaleFactor, ScaleType stype, const RooAbsData* projData) const
02061 {
02062   // OBSOLETE -- RETAINED FOR BACKWARD COMPATIBILITY. Use the plotOn(frame,Slice(...)) instead
02063 
02064   RooArgSet projectedVars ;
02065   makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
02066   
02067   // Take out the sliced variables
02068   TIterator* iter = sliceSet.createIterator() ;
02069   RooAbsArg* sliceArg ;
02070   while((sliceArg=(RooAbsArg*)iter->Next())) {
02071     RooAbsArg* arg = projectedVars.find(sliceArg->GetName()) ;
02072     if (arg) {
02073       projectedVars.remove(*arg) ;
02074     } else {
02075       coutI(Plotting) << "RooAbsReal::plotSliceOn(" << GetName() << ") slice variable " 
02076                       << sliceArg->GetName() << " was not projected anyway" << endl ;
02077     }
02078   }
02079   delete iter ;
02080 
02081   PlotOpt o ;
02082   o.drawOptions = drawOptions ;
02083   o.scaleFactor = scaleFactor ;
02084   o.stype = stype ;
02085   o.projData = projData ;
02086   o.projSet = &projectedVars ;
02087   return plotOn(frame,o) ;
02088 }
02089 
02090 
02091 
02092 
02093 //_____________________________________________________________________________
02094 // coverity[PASS_BY_VALUE]
02095 RooPlot* RooAbsReal::plotAsymOn(RooPlot *frame, const RooAbsCategoryLValue& asymCat, PlotOpt o) const
02096 
02097 {
02098   // Plotting engine for asymmetries. Implements the functionality if plotOn(frame,Asymmetry(...))) 
02099   //
02100   // Plot asymmetry of ourselves, defined as
02101   //
02102   //   asym = f(asymCat=-1) - f(asymCat=+1) / ( f(asymCat=-1) + f(asymCat=+1) )
02103   //
02104   // on frame. If frame contains a histogram, all dimensions of the plotted
02105   // asymmetry function that occur in the previously plotted dataset are projected via partial integration.
02106   // Otherwise no projections are performed,
02107   //
02108   // The asymmetry function can be multiplied with an optional scale factor. The default projection 
02109   // behaviour can be overriden by supplying an optional set of dependents to project. 
02110 
02111   // Sanity checks
02112   if (plotSanityChecks(frame)) return frame ;
02113 
02114   // ProjDataVars is either all projData observables, or the user indicated subset of it
02115   RooArgSet projDataVars ;
02116   if (o.projData) {
02117     if (o.projDataSet) {
02118       RooArgSet* tmp = (RooArgSet*) o.projData->get()->selectCommon(*o.projDataSet) ;
02119       projDataVars.add(*tmp) ;
02120       delete tmp ;
02121     } else {
02122       projDataVars.add(*o.projData->get()) ;
02123     }
02124   }
02125 
02126   // Must depend on asymCat
02127   if (!dependsOn(asymCat)) {
02128     coutE(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() 
02129                     << ") function doesn't depend on asymmetry category " << asymCat.GetName() << endl ;
02130     return frame ;
02131   }
02132 
02133   // asymCat must be a signCat
02134   if (!asymCat.isSignType()) {
02135     coutE(Plotting) << "RooAbsReal::plotAsymOn(" << GetName()
02136                     << ") asymmetry category must have 2 or 3 states with index values -1,0,1" << endl ;
02137     return frame ;
02138   }
02139   
02140   // Make list of variables to be projected
02141   RooArgSet projectedVars ;
02142   RooArgSet sliceSet ;
02143   if (o.projSet) {
02144     makeProjectionSet(frame->getPlotVar(),o.projSet,projectedVars,kFALSE) ;
02145 
02146     // Print list of non-projected variables
02147     if (frame->getNormVars()) {
02148       RooArgSet *sliceSetTmp = getObservables(*frame->getNormVars()) ;
02149       sliceSetTmp->remove(projectedVars,kTRUE,kTRUE) ;
02150       sliceSetTmp->remove(*frame->getPlotVar(),kTRUE,kTRUE) ;
02151 
02152       if (o.projData) {
02153         RooArgSet* tmp = (RooArgSet*) projDataVars.selectCommon(*o.projSet) ;
02154         sliceSetTmp->remove(*tmp,kTRUE,kTRUE) ;
02155         delete tmp ;
02156       }
02157 
02158       if (sliceSetTmp->getSize()) {
02159         coutI(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() << ") plot on " 
02160                         << frame->getPlotVar()->GetName() << " represents a slice in " << *sliceSetTmp << endl ;
02161       }
02162       sliceSet.add(*sliceSetTmp) ;
02163       delete sliceSetTmp ;
02164     }
02165   } else {
02166     makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
02167   }
02168 
02169 
02170   // Take out data-projected dependens from projectedVars
02171   RooArgSet* projDataNeededVars = 0 ;
02172   if (o.projData) {
02173     projDataNeededVars = (RooArgSet*) projectedVars.selectCommon(projDataVars) ;
02174     projectedVars.remove(projDataVars,kTRUE,kTRUE) ;
02175   }
02176 
02177   // Take out plotted asymmetry from projection
02178   if (projectedVars.find(asymCat.GetName())) {
02179     projectedVars.remove(*projectedVars.find(asymCat.GetName())) ;
02180   }
02181 
02182   // Clone the plot variable
02183   RooAbsReal* realVar = (RooRealVar*) frame->getPlotVar() ;
02184   RooRealVar* plotVar = (RooRealVar*) realVar->Clone() ;
02185 
02186   // Inform user about projections
02187   if (projectedVars.getSize()) {
02188     coutI(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() << ") plot on " << plotVar->GetName() 
02189                     << " projects variables " << projectedVars << endl ;
02190   }  
02191   if (projDataNeededVars && projDataNeededVars->getSize()>0) {
02192     coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") plot on " << plotVar->GetName() 
02193                     << " averages using data variables "<<  *projDataNeededVars << endl ;
02194   }
02195 
02196 
02197   // Customize two copies of projection with fixed negative and positive asymmetry
02198   RooAbsCategoryLValue* asymPos = (RooAbsCategoryLValue*) asymCat.Clone("asym_pos") ;
02199   RooAbsCategoryLValue* asymNeg = (RooAbsCategoryLValue*) asymCat.Clone("asym_neg") ;
02200   asymPos->setIndex(1) ;
02201   asymNeg->setIndex(-1) ;
02202   RooCustomizer* custPos = new RooCustomizer(*this,"pos") ;
02203   RooCustomizer* custNeg = new RooCustomizer(*this,"neg") ;
02204   //custPos->setOwning(kTRUE) ;
02205   //custNeg->setOwning(kTRUE) ;
02206   custPos->replaceArg(asymCat,*asymPos) ;
02207   custNeg->replaceArg(asymCat,*asymNeg) ;
02208   RooAbsReal* funcPos = (RooAbsReal*) custPos->build() ;
02209   RooAbsReal* funcNeg = (RooAbsReal*) custNeg->build() ;
02210 
02211   // Create projection integral 
02212   RooArgSet *posProjCompList, *negProjCompList ;
02213 
02214   // Add projDataVars to normalized dependents of projection
02215   // This is needed only for asymmetries (why?)
02216   RooArgSet depPos(*plotVar,*asymPos) ;
02217   RooArgSet depNeg(*plotVar,*asymNeg) ;
02218   depPos.add(projDataVars) ;
02219   depNeg.add(projDataVars) ;
02220 
02221   const RooAbsReal *posProj = funcPos->createPlotProjection(depPos, &projectedVars, posProjCompList) ;
02222   const RooAbsReal *negProj = funcNeg->createPlotProjection(depNeg, &projectedVars, negProjCompList) ;
02223   if (!posProj || !negProj) {
02224     coutE(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() << ") Unable to create projections, abort" << endl ;
02225     return frame ; 
02226   }
02227 
02228   // Create a RooFormulaVar representing the asymmetry
02229   TString asymName(GetName()) ;
02230   asymName.Append("_Asym[") ;
02231   asymName.Append(asymCat.GetName()) ;
02232   asymName.Append("]") ;
02233   TString asymTitle(asymCat.GetName()) ;
02234   asymTitle.Append(" Asymmetry of ") ;
02235   asymTitle.Append(GetTitle()) ;
02236   RooFormulaVar* funcAsym = new RooFormulaVar(asymName,asymTitle,"(@0-@1)/(@0+@1)",RooArgSet(*posProj,*negProj)) ;
02237 
02238   if (o.projData) {
02239     
02240     // If data set contains more rows than needed, make reduced copy first
02241     RooAbsData* projDataSel = (RooAbsData*)o.projData;
02242     if (projDataNeededVars->getSize()<o.projData->get()->getSize()) {
02243       
02244       // Determine if there are any slice variables in the projection set
02245       RooArgSet* sliceDataSet = (RooArgSet*) sliceSet.selectCommon(*o.projData->get()) ;
02246       TString cutString ;
02247       if (sliceDataSet->getSize()>0) {
02248         TIterator* iter = sliceDataSet->createIterator() ;
02249         RooAbsArg* sliceVar ; 
02250         Bool_t first(kTRUE) ;
02251         while((sliceVar=(RooAbsArg*)iter->Next())) {
02252           if (!first) {
02253             cutString.Append("&&") ;
02254           } else {
02255             first=kFALSE ;          
02256           }
02257 
02258           RooAbsRealLValue* real ;
02259           RooAbsCategoryLValue* cat ;     
02260           if ((real = dynamic_cast<RooAbsRealLValue*>(sliceVar))) {
02261             cutString.Append(Form("%s==%f",real->GetName(),real->getVal())) ;
02262           } else if ((cat = dynamic_cast<RooAbsCategoryLValue*>(sliceVar))) {
02263             cutString.Append(Form("%s==%d",cat->GetName(),cat->getIndex())) ;       
02264           }
02265         }
02266         delete iter ;
02267       }
02268       delete sliceDataSet ;
02269 
02270       if (!cutString.IsNull()) {
02271         projDataSel = ((RooAbsData*)o.projData)->reduce(*projDataNeededVars,cutString) ;
02272         coutI(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() 
02273                         << ") reducing given projection dataset to entries with " << cutString << endl ;
02274       } else {
02275         projDataSel = ((RooAbsData*)o.projData)->reduce(*projDataNeededVars) ;
02276       }
02277       coutI(Plotting) << "RooAbsReal::plotAsymOn(" << GetName() 
02278                       << ") only the following components of the projection data will be used: " << *projDataNeededVars << endl ;
02279     }    
02280     
02281 
02282     RooDataWeightedAverage dwa(Form("%sDataWgtAvg",GetName()),"Data Weighted average",*funcAsym,*projDataSel,RooArgSet()/**projDataSel->get()*/,o.numCPU,o.interleave,kTRUE) ;
02283     //RooDataWeightedAverage dwa(Form("%sDataWgtAvg",GetName()),"Data Weighted average",*funcAsym,*projDataSel,*projDataSel->get(),o.numCPU,o.interleave,kTRUE) ;
02284     dwa.constOptimizeTestStatistic(Activate) ;
02285 
02286     RooRealBinding projBind(dwa,*plotVar) ;
02287 
02288     ((RooAbsReal*)posProj)->attachDataSet(*projDataSel) ;
02289     ((RooAbsReal*)negProj)->attachDataSet(*projDataSel) ;
02290 
02291     RooScaledFunc scaleBind(projBind,o.scaleFactor);
02292 
02293     // Set default range, if not specified
02294     if (o.rangeLo==0 && o.rangeHi==0) {
02295       o.rangeLo = frame->GetXaxis()->GetXmin() ;
02296       o.rangeHi = frame->GetXaxis()->GetXmax() ;
02297     }
02298 
02299     // Construct name of curve for data weighed average
02300     TString curveName(funcAsym->GetName()) ;
02301     curveName.Append(Form("_DataAvg[%s]",projDataSel->get()->contentsString().c_str())) ;
02302     // Append slice set specification if any
02303     if (sliceSet.getSize()>0) {
02304       curveName.Append(Form("_Slice[%s]",sliceSet.contentsString().c_str())) ;      
02305     }
02306     // Append any suffixes imported from RooAbsPdf::plotOn
02307     if (o.curveNameSuffix) {
02308       curveName.Append(o.curveNameSuffix) ;
02309     }
02310 
02311 
02312     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
02313     RooCurve *curve = new RooCurve(funcAsym->GetName(),funcAsym->GetTitle(),scaleBind,
02314                                    o.rangeLo,o.rangeHi,frame->GetNbinsX(),o.precision,o.precision,kFALSE,o.wmode,o.numee,o.doeeval,o.eeval) ;
02315     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
02316 
02317     dynamic_cast<TAttLine*>(curve)->SetLineColor(2) ;
02318     // add this new curve to the specified plot frame
02319     frame->addPlotable(curve, o.drawOptions);
02320 
02321     ccoutW(Eval) << endl ;
02322 
02323     if (projDataSel!=o.projData) delete projDataSel ;
02324        
02325   } else {
02326 
02327     // Set default range, if not specified
02328     if (o.rangeLo==0 && o.rangeHi==0) {
02329       o.rangeLo = frame->GetXaxis()->GetXmin() ;
02330       o.rangeHi = frame->GetXaxis()->GetXmax() ;
02331     }
02332 
02333     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
02334     RooCurve* curve= new RooCurve(*funcAsym,*plotVar,o.rangeLo,o.rangeHi,frame->GetNbinsX(),
02335                                   o.scaleFactor,0,o.precision,o.precision,kFALSE,o.wmode,o.numee,o.doeeval,o.eeval);
02336     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
02337 
02338     dynamic_cast<TAttLine*>(curve)->SetLineColor(2) ;
02339 
02340 
02341     // Set default name of curve
02342     TString curveName(funcAsym->GetName()) ;
02343     if (sliceSet.getSize()>0) {
02344       curveName.Append(Form("_Slice[%s]",sliceSet.contentsString().c_str())) ;      
02345     }
02346     if (o.curveNameSuffix) {
02347       // Append any suffixes imported from RooAbsPdf::plotOn
02348       curveName.Append(o.curveNameSuffix) ;
02349     }
02350     curve->SetName(curveName.Data()) ;
02351     
02352     // add this new curve to the specified plot frame
02353     frame->addPlotable(curve, o.drawOptions);
02354 
02355   }
02356 
02357   // Cleanup
02358   delete custPos ;
02359   delete custNeg ;
02360   delete funcPos ;
02361   delete funcNeg ;
02362   delete posProjCompList ;
02363   delete negProjCompList ;
02364   delete asymPos ;
02365   delete asymNeg ;
02366   delete funcAsym ;
02367 
02368   delete plotVar ;
02369 
02370   return frame;
02371 }
02372 
02373 
02374 
02375 //_____________________________________________________________________________
02376 Double_t RooAbsReal::getPropagatedError(const RooFitResult& fr) 
02377 {
02378   // Calculate error on self by propagated errors on parameters with correlations as given by fit result
02379   // The linearly propagated error is calculated as follows
02380   //                                    T            
02381   // error(x) = F_a(x) * Corr(a,a') F_a'(x)
02382   //
02383   // where     F_a(x) = [ f(x,a+da) - f(x,a-da) ] / 2, with f(x) this function and 'da' taken from the fit result
02384   //       Corr(a,a') = the correlation matrix from the fit result
02385   //
02386 
02387 
02388   // Clone self for internal use
02389   RooAbsReal* cloneFunc = (RooAbsReal*) cloneTree() ;
02390   RooArgSet* errorParams = cloneFunc->getObservables(fr.floatParsFinal()) ;
02391   RooArgSet* nset = cloneFunc->getParameters(*errorParams) ;
02392     
02393   // Make list of parameter instances of cloneFunc in order of error matrix
02394   RooArgList paramList ;
02395   const RooArgList& fpf = fr.floatParsFinal() ;
02396   vector<int> fpf_idx ;
02397   for (Int_t i=0 ; i<fpf.getSize() ; i++) {
02398     RooAbsArg* par = errorParams->find(fpf[i].GetName()) ;
02399     if (par) {
02400       paramList.add(*par) ;
02401       fpf_idx.push_back(i) ;
02402     }
02403   }
02404 
02405   vector<Double_t> plusVar, minusVar ;    
02406   
02407   // Create vector of plus,minus variations for each parameter  
02408   TMatrixDSym V(paramList.getSize()==fr.floatParsFinal().getSize()?
02409                 fr.covarianceMatrix():
02410                 fr.reducedCovarianceMatrix(paramList)) ;
02411   
02412   for (Int_t ivar=0 ; ivar<paramList.getSize() ; ivar++) {
02413     
02414     RooRealVar& rrv = (RooRealVar&)fpf[fpf_idx[ivar]] ;
02415     
02416     Double_t cenVal = rrv.getVal() ;
02417     Double_t errVal = sqrt(V(ivar,ivar)) ;
02418     
02419     // Make Plus variation
02420     ((RooRealVar*)paramList.at(ivar))->setVal(cenVal+errVal) ;
02421     plusVar.push_back(cloneFunc->getVal(nset)) ;
02422     
02423     // Make Minus variation
02424     ((RooRealVar*)paramList.at(ivar))->setVal(cenVal-errVal) ;
02425     minusVar.push_back(cloneFunc->getVal(nset)) ;
02426     
02427     ((RooRealVar*)paramList.at(ivar))->setVal(cenVal) ;
02428   }
02429   
02430   TMatrixDSym C(paramList.getSize()) ;      
02431   vector<double> errVec(paramList.getSize()) ;
02432   for (int i=0 ; i<paramList.getSize() ; i++) {
02433     errVec[i] = sqrt(V(i,i)) ;
02434     for (int j=i ; j<paramList.getSize() ; j++) {
02435       C(i,j) = V(i,j)/sqrt(V(i,i)*V(j,j)) ;
02436       C(j,i) = C(i,j) ;
02437     }
02438   }
02439   
02440   // Make vector of variations
02441   TVectorD F(plusVar.size()) ;
02442   for (unsigned int j=0 ; j<plusVar.size() ; j++) {
02443     F[j] = (plusVar[j]-minusVar[j])/2 ;
02444   }
02445 
02446   // Calculate error in linear approximation from variations and correlation coefficient
02447   Double_t sum = F*(C*F) ;
02448 
02449   delete cloneFunc ;
02450   delete errorParams ;
02451   delete nset ;
02452 
02453   return sqrt(sum) ;
02454 }
02455 
02456 
02457 
02458 
02459 
02460 
02461 
02462 
02463 
02464 
02465 //_____________________________________________________________________________
02466 RooPlot* RooAbsReal::plotOnWithErrorBand(RooPlot* frame,const RooFitResult& fr, Double_t Z,const RooArgSet* params, const RooLinkedList& argList, Bool_t linMethod) const 
02467 {
02468   // Plot function or p.d.f. on frame with support for visualization of the uncertainty encoded in the given fit result fr.
02469   // If params is non-zero, only the subset of the parameters in fr that occur in params is considered for the error evaluation
02470   // Argument argList can contain any RooCmdArg named argument that can be applied to a regular plotOn() operation
02471   //
02472   // By default (linMethod=kTRUE) a linearized error is shown which is calculated as follows
02473   //                                    T            
02474   // error(x) = Z* F_a(x) * Corr(a,a') F_a'(x)
02475   //
02476   // where     F_a(x) = [ f(x,a+da) - f(x,a-da) ] / 2, with f(x) the plotted curve and 'da' taken from the fit result
02477   //       Corr(a,a') = the correlation matrix from the fit result
02478   //                Z = requested signifance 'Z sigma band'
02479   //
02480   // The linear method is fast (required 2*N evaluations of the curve, where N is the number of parameters), but may
02481   // not be accurate in the presence of strong correlations (~>0.9) and at Z>2 due to linear and Gaussian approximations made
02482   //
02483   // Alternatively, a more robust error is calculated using a sampling method. In this method a number of curves
02484   // is calculated with variations of the parameter values, as drawn from a multi-variate Gaussian p.d.f. that is constructed
02485   // from the fit results covariance matrix. The error(x) is determined by calculating a central interval that capture N% of the variations 
02486   // for each valye of x, where N% is controlled by Z (i.e. Z=1 gives N=68%). The number of sampling curves is chosen to be such
02487   // that at least 30 curves are expected to be outside the N% interval, and is minimally 100 (e.g. Z=1->Ncurve=100, Z=2->Ncurve=659, Z=3->Ncurve=11111)
02488   // Intervals from the sampling method can be asymmetric, and may perform better in the presence of strong correlations
02489 
02490   RooLinkedList plotArgList(argList) ;
02491   RooCmdConfig pc(Form("RooAbsPdf::plotOn(%s)",GetName())) ;
02492   pc.stripCmdList(plotArgList,"VisualizeError,MoveToBack") ;  
02493 
02494 
02495   // Generate central value curve
02496   RooLinkedList tmp(plotArgList) ;
02497   plotOn(frame,tmp) ;
02498   RooCurve* cenCurve = frame->getCurve() ;
02499   frame->remove(0,kFALSE) ;
02500 
02501   RooCurve* band(0) ;
02502   if (!linMethod) {
02503 
02504     // *** Interval method ***
02505     //
02506     // Make N variations of parameters samples from V and visualize N% central interval where N% is defined from Z
02507 
02508     // Clone self for internal use
02509     RooAbsReal* cloneFunc = (RooAbsReal*) cloneTree() ;
02510     RooArgSet* cloneParams = cloneFunc->getObservables(fr.floatParsFinal()) ;
02511     RooArgSet* errorParams = params?((RooArgSet*)cloneParams->selectCommon(*params)):cloneParams ;
02512     
02513     // Generate 100 random parameter points distributed according to fit result covariance matrix
02514     RooAbsPdf* paramPdf = fr.createHessePdf(*errorParams) ;
02515     Int_t n = Int_t(100./TMath::Erfc(Z/sqrt(2.))) ;
02516     if (n<100) n=100 ;
02517     
02518     coutI(Plotting) << "RooAbsReal::plotOn(" << GetName() << ") INFO: visualizing " << Z << "-sigma uncertainties in parameters " 
02519                   << *errorParams << " from fit result " << fr.GetName() << " using " << n << " samplings." << endl ;
02520     
02521     // Generate variation curves with above set of parameter values
02522     Double_t ymin = frame->GetMinimum() ;
02523     Double_t ymax = frame->GetMaximum() ;
02524     RooDataSet* d = paramPdf->generate(*errorParams,n) ;
02525     vector<RooCurve*> cvec ;
02526     for (int i=0 ; i<d->numEntries() ; i++) {
02527       *cloneParams = (*d->get(i)) ;
02528       RooLinkedList tmp2(plotArgList) ;
02529       cloneFunc->plotOn(frame,tmp2) ;
02530       cvec.push_back(frame->getCurve()) ;
02531       frame->remove(0,kFALSE) ;
02532     }
02533     frame->SetMinimum(ymin) ;
02534     frame->SetMaximum(ymax) ;
02535     
02536     
02537     // Generate upper and lower curve points from 68% interval around each point of central curve
02538     band = cenCurve->makeErrorBand(cvec,Z) ;
02539     
02540     // Cleanup 
02541     delete paramPdf ;
02542     delete cloneFunc ;
02543     for (vector<RooCurve*>::iterator i=cvec.begin() ; i!=cvec.end() ; i++) {
02544       delete (*i) ;
02545     }
02546 
02547   } else {
02548 
02549     // *** Linear Method ***
02550     //
02551     // Make a one-sigma up- and down fluctation for each parameter and visualize
02552     // a from a linearized calculation as follows
02553     //
02554     //   error(x) = F(a) C_aa' F(a')
02555     //
02556     //   Where F(a) = (f(x,a+da) - f(x,a-da))/2
02557     //   and C_aa' is the correlation matrix
02558 
02559     // Clone self for internal use
02560     RooAbsReal* cloneFunc = (RooAbsReal*) cloneTree() ;
02561     RooArgSet* cloneParams = cloneFunc->getObservables(fr.floatParsFinal()) ;
02562     RooArgSet* errorParams = params?((RooArgSet*)cloneParams->selectCommon(*params)):cloneParams ;    
02563     
02564 
02565     // Make list of parameter instances of cloneFunc in order of error matrix
02566     RooArgList paramList ;
02567     const RooArgList& fpf = fr.floatParsFinal() ;
02568     vector<int> fpf_idx ;
02569     for (Int_t i=0 ; i<fpf.getSize() ; i++) {
02570       RooAbsArg* par = errorParams->find(fpf[i].GetName()) ;
02571       if (par) {
02572         paramList.add(*par) ;
02573         fpf_idx.push_back(i) ;
02574       }
02575     }
02576 
02577     vector<RooCurve*> plusVar, minusVar ;    
02578 
02579     // Create vector of plus,minus variations for each parameter
02580     
02581     TMatrixDSym V(paramList.getSize()==fr.floatParsFinal().getSize()?
02582                   fr.covarianceMatrix():
02583                   fr.reducedCovarianceMatrix(paramList)) ;
02584     
02585     for (Int_t ivar=0 ; ivar<paramList.getSize() ; ivar++) {
02586       
02587       RooRealVar& rrv = (RooRealVar&)fpf[fpf_idx[ivar]] ;
02588       
02589       Double_t cenVal = rrv.getVal() ;
02590       Double_t errVal = sqrt(V(ivar,ivar)) ;
02591       
02592       // Make Plus variation
02593       ((RooRealVar*)paramList.at(ivar))->setVal(cenVal+Z*errVal) ;
02594       RooLinkedList tmp2(plotArgList) ;
02595       cloneFunc->plotOn(frame,tmp2) ;
02596       plusVar.push_back(frame->getCurve()) ;
02597       frame->remove(0,kFALSE) ;
02598       
02599       // Make Minus variation
02600       ((RooRealVar*)paramList.at(ivar))->setVal(cenVal-Z*errVal) ;
02601       RooLinkedList tmp3(plotArgList) ;
02602       cloneFunc->plotOn(frame,tmp3) ;
02603       minusVar.push_back(frame->getCurve()) ;
02604       frame->remove(0,kFALSE) ;
02605       
02606       ((RooRealVar*)paramList.at(ivar))->setVal(cenVal) ;
02607     }
02608     
02609     TMatrixDSym C(paramList.getSize()) ;      
02610     vector<double> errVec(paramList.getSize()) ;
02611     for (int i=0 ; i<paramList.getSize() ; i++) {
02612       errVec[i] = sqrt(V(i,i)) ;
02613       for (int j=i ; j<paramList.getSize() ; j++) {
02614         C(i,j) = V(i,j)/sqrt(V(i,i)*V(j,j)) ;
02615         C(j,i) = C(i,j) ;
02616       }
02617     }
02618     
02619     band = cenCurve->makeErrorBand(plusVar,minusVar,C,Z) ;    
02620     
02621     
02622     // Cleanup 
02623     delete cloneFunc ;
02624     for (vector<RooCurve*>::iterator i=plusVar.begin() ; i!=plusVar.end() ; i++) {
02625       delete (*i) ;
02626     }
02627     for (vector<RooCurve*>::iterator i=minusVar.begin() ; i!=minusVar.end() ; i++) {
02628       delete (*i) ;
02629     }
02630 
02631   }
02632 
02633   delete cenCurve ;
02634   if (!band) return frame ;
02635   
02636   // Define configuration for this method
02637   pc.defineString("drawOption","DrawOption",0,"F") ;
02638   pc.defineString("curveNameSuffix","CurveNameSuffix",0,"") ;
02639   pc.defineInt("lineColor","LineColor",0,-999) ;
02640   pc.defineInt("lineStyle","LineStyle",0,-999) ;
02641   pc.defineInt("lineWidth","LineWidth",0,-999) ;
02642   pc.defineInt("fillColor","FillColor",0,-999) ;
02643   pc.defineInt("fillStyle","FillStyle",0,-999) ;
02644   pc.defineString("curveName","Name",0,"") ;
02645   pc.defineInt("curveInvisible","Invisible",0,0) ;
02646   pc.defineInt("moveToBack","MoveToBack",0,0) ;
02647   pc.allowUndefined() ;
02648 
02649   // Process & check varargs 
02650   pc.process(argList) ;
02651   if (!pc.ok(kTRUE)) {
02652     return frame ;
02653   }
02654 
02655   // Insert error band in plot frame
02656   frame->addPlotable(band,pc.getString("drawOption"),pc.getInt("curveInvisible")) ;
02657 
02658 
02659   // Optionally adjust line/fill attributes
02660   Int_t lineColor = pc.getInt("lineColor") ;
02661   Int_t lineStyle = pc.getInt("lineStyle") ;
02662   Int_t lineWidth = pc.getInt("lineWidth") ;
02663   Int_t fillColor = pc.getInt("fillColor") ;
02664   Int_t fillStyle = pc.getInt("fillStyle") ;
02665   if (lineColor!=-999) frame->getAttLine()->SetLineColor(lineColor) ;
02666   if (lineStyle!=-999) frame->getAttLine()->SetLineStyle(lineStyle) ;
02667   if (lineWidth!=-999) frame->getAttLine()->SetLineWidth(lineWidth) ;
02668   if (fillColor!=-999) frame->getAttFill()->SetFillColor(fillColor) ;
02669   if (fillStyle!=-999) frame->getAttFill()->SetFillStyle(fillStyle) ;
02670 
02671   // Adjust name if requested
02672   if (pc.getString("curveName",0,kTRUE)) {
02673     band->SetName(pc.getString("curveName",0,kTRUE)) ;
02674   } else if (pc.getString("curveNameSuffix",0,kTRUE)) {
02675     TString name(band->GetName()) ;
02676     name.Append(pc.getString("curveNameSuffix",0,kTRUE)) ;
02677     band->SetName(name.Data()) ;
02678   }
02679 
02680   // Move last inserted object to back to drawing stack if requested
02681   if (pc.getInt("moveToBack") && frame->numItems()>1) {   
02682     frame->drawBefore(frame->getObject(0)->GetName(), frame->getCurve()->GetName());    
02683   }
02684   
02685   
02686   return frame ;
02687 }
02688 
02689 
02690 
02691 
02692 //_____________________________________________________________________________
02693 Bool_t RooAbsReal::plotSanityChecks(RooPlot* frame) const
02694 {
02695   // Utility function for plotOn(), perform general sanity check on frame to ensure safe plotting operations
02696 
02697   // check that we are passed a valid plot frame to use
02698   if(0 == frame) {
02699     coutE(Plotting) << ClassName() << "::" << GetName() << ":plotOn: frame is null" << endl;
02700     return kTRUE;
02701   }
02702 
02703   // check that this frame knows what variable to plot
02704   RooAbsReal* var = frame->getPlotVar() ;
02705   if(!var) {
02706     coutE(Plotting) << ClassName() << "::" << GetName()
02707          << ":plotOn: frame does not specify a plot variable" << endl;
02708     return kTRUE;
02709   }
02710 
02711   // check that the plot variable is not derived
02712   if(!dynamic_cast<RooAbsRealLValue*>(var)) {
02713     coutE(Plotting) << ClassName() << "::" << GetName() << ":plotOn: cannot plot variable \""
02714                     << var->GetName() << "\" of type " << var->ClassName() << endl;
02715     return kTRUE;
02716   }
02717 
02718   // check if we actually depend on the plot variable
02719   if(!this->dependsOn(*var)) {
02720     coutE(Plotting) << ClassName() << "::" << GetName() << ":plotOn: WARNING: variable is not an explicit dependent: "
02721                     << var->GetName() << endl;
02722   }
02723   
02724   return kFALSE ;
02725 }
02726 
02727 
02728 
02729 
02730 //_____________________________________________________________________________
02731 void RooAbsReal::makeProjectionSet(const RooAbsArg* plotVar, const RooArgSet* allVars, 
02732                                    RooArgSet& projectedVars, Bool_t silent) const
02733 {
02734   // Utility function for plotOn() that constructs the set of
02735   // observables to project when plotting ourselves as function of
02736   // 'plotVar'. 'allVars' is the list of variables that must be
02737   // projected, but may contain variables that we do not depend on. If
02738   // 'silent' is cleared, warnings about inconsistent input parameters
02739   // will be printed.
02740 
02741   cxcoutD(Plotting) << "RooAbsReal::makeProjectionSet(" << GetName() << ") plotVar = " << plotVar->GetName() 
02742                     << " allVars = " << (allVars?(*allVars):RooArgSet()) << endl ;
02743 
02744   projectedVars.removeAll() ;
02745   if (!allVars) return ;
02746 
02747   // Start out with suggested list of variables  
02748   projectedVars.add(*allVars) ;
02749 
02750   // Take out plot variable
02751   RooAbsArg *found= projectedVars.find(plotVar->GetName());
02752   if(found) {
02753     projectedVars.remove(*found);
02754 
02755     // Take out eventual servers of plotVar
02756     RooArgSet* plotServers = plotVar->getObservables(&projectedVars) ;
02757     TIterator* psIter = plotServers->createIterator() ;
02758     RooAbsArg* ps ;
02759     while((ps=(RooAbsArg*)psIter->Next())) {
02760       RooAbsArg* tmp = projectedVars.find(ps->GetName()) ;
02761       if (tmp) {
02762         cxcoutD(Plotting) << "RooAbsReal::makeProjectionSet(" << GetName() << ") removing " << tmp->GetName() 
02763                           << " from projection set because it a server of " << plotVar->GetName() << endl ;
02764         projectedVars.remove(*tmp) ;
02765       }
02766     }
02767     delete psIter ;
02768     delete plotServers ;
02769 
02770     if (!silent) {
02771       coutW(Plotting) << "RooAbsReal::plotOn(" << GetName() 
02772                       << ") WARNING: cannot project out frame variable (" 
02773                       << found->GetName() << "), ignoring" << endl ; 
02774     }
02775   }
02776 
02777   // Take out all non-dependents of function
02778   TIterator* iter = allVars->createIterator() ;
02779   RooAbsArg* arg ;
02780   while((arg=(RooAbsArg*)iter->Next())) {
02781     if (!dependsOnValue(*arg)) {
02782       projectedVars.remove(*arg,kTRUE) ;
02783 
02784       cxcoutD(Plotting) << "RooAbsReal::plotOn(" << GetName() 
02785                         << ") function doesn't depend on projection variable " 
02786                         << arg->GetName() << ", ignoring" << endl ;
02787     }
02788   }
02789   delete iter ;
02790 }
02791 
02792 
02793 
02794 
02795 //_____________________________________________________________________________
02796 Bool_t RooAbsReal::isSelectedComp() const 
02797 { 
02798   // If true, the current pdf is a selected component (for use in plotting)
02799   return _selectComp || _globalSelectComp ; 
02800 }
02801 
02802 
02803 
02804 //_____________________________________________________________________________
02805 void RooAbsReal::globalSelectComp(Bool_t flag) 
02806 { 
02807   // Global switch controlling the activation of the selectComp() functionality
02808   _globalSelectComp = flag ; 
02809 }
02810 
02811 
02812 
02813 
02814 //_____________________________________________________________________________
02815 RooAbsFunc *RooAbsReal::bindVars(const RooArgSet &vars, const RooArgSet* nset, Bool_t clipInvalid) const 
02816 {
02817   // Create an interface adaptor f(vars) that binds us to the specified variables
02818   // (in arbitrary order). For example, calling bindVars({x1,x3}) on an object
02819   // F(x1,x2,x3,x4) returns an object f(x1,x3) that is evaluated using the
02820   // current values of x2 and x4. The caller takes ownership of the returned adaptor.
02821 
02822   RooAbsFunc *binding= new RooRealBinding(*this,vars,nset,clipInvalid);
02823   if(binding && !binding->isValid()) {
02824     coutE(InputArguments) << ClassName() << "::" << GetName() << ":bindVars: cannot bind to " << vars << endl ;
02825     delete binding;
02826     binding= 0;
02827   }
02828   return binding;
02829 }
02830 
02831 
02832 
02833 //_____________________________________________________________________________
02834 void RooAbsReal::copyCache(const RooAbsArg* source, Bool_t /*valueOnly*/) 
02835 {
02836   // Copy the cached value of another RooAbsArg to our cache.
02837   // Warning: This function copies the cached values of source,
02838   // it is the callers responsibility to make sure the cache is clean
02839 
02840   RooAbsReal* other = static_cast<RooAbsReal*>(const_cast<RooAbsArg*>(source)) ;
02841 
02842   if (!other->_treeVar) {
02843     _value = other->_value ;
02844   } else {
02845     if (source->getAttribute("FLOAT_TREE_BRANCH")) {
02846       _value = other->_floatValue ;
02847     } else if (source->getAttribute("INTEGER_TREE_BRANCH")) {
02848       _value = other->_intValue ;
02849     } else if (source->getAttribute("BYTE_TREE_BRANCH")) {
02850       _value = other->_byteValue ;
02851     } else if (source->getAttribute("SIGNEDBYTE_TREE_BRANCH")) {
02852       _value = other->_sbyteValue ;
02853     } else if (source->getAttribute("UNSIGNED_INTEGER_TREE_BRANCH")) {
02854       _value = other->_uintValue ;
02855     } 
02856   }
02857   setValueDirty() ;
02858 }
02859 
02860 
02861 
02862 //_____________________________________________________________________________
02863 void RooAbsReal::attachToTree(TTree& t, Int_t bufSize)
02864 {
02865   // Attach object to a branch of given TTree. By default it will
02866   // register the internal value cache RooAbsReal::_value as branch
02867   // buffer for a Double_t tree branch with the same name as this
02868   // object. If no Double_t branch is found with the name of this
02869   // object, this method looks for a Float_t Int_t, UChar_t and UInt_t
02870   // branch in that order. If any of these are found the buffer for
02871   // that branch is set to a correctly typed conversion buffer in this
02872   // RooRealVar.  A flag is set that will cause copyCache to copy the
02873   // object value from the appropriate conversion buffer instead of
02874   // the _value buffer.
02875 
02876   // First determine if branch is taken
02877   TString cleanName(cleanBranchName()) ;
02878   TBranch* branch = t.GetBranch(cleanName) ;
02879   if (branch) { 
02880     
02881     // Determine if existing branch is Float_t or Double_t
02882     TLeaf* leaf = (TLeaf*)branch->GetListOfLeaves()->At(0) ;
02883 
02884     // Check that leaf is _not_ an array
02885     Int_t dummy ;
02886     TLeaf* counterLeaf = leaf->GetLeafCounter(dummy) ;
02887     if (counterLeaf) {
02888       coutE(Eval) << "RooAbsReal::attachToTree(" << GetName() << ") ERROR: TTree branch " << GetName() 
02889                   << " is an array and cannot be attached to a RooAbsReal" << endl ;      
02890       return ;
02891     }
02892     
02893     TString typeName(leaf->GetTypeName()) ;
02894 
02895     if (!typeName.CompareTo("Float_t")) {
02896       coutI(Eval) << "RooAbsReal::attachToTree(" << GetName() << ") TTree Float_t branch " << GetName() 
02897                   << " will be converted to double precision" << endl ;
02898       setAttribute("FLOAT_TREE_BRANCH",kTRUE) ;
02899       _treeVar = kTRUE ;
02900       t.SetBranchAddress(cleanName,&_floatValue) ;
02901     } else if (!typeName.CompareTo("Int_t")) {
02902       coutI(Eval) << "RooAbsReal::attachToTree(" << GetName() << ") TTree Int_t branch " << GetName() 
02903                   << " will be converted to double precision" << endl ;
02904       setAttribute("INTEGER_TREE_BRANCH",kTRUE) ;
02905       _treeVar = kTRUE ;
02906       t.SetBranchAddress(cleanName,&_intValue) ;
02907     } else if (!typeName.CompareTo("UChar_t")) {
02908       coutI(Eval) << "RooAbsReal::attachToTree(" << GetName() << ") TTree UChar_t branch " << GetName() 
02909                   << " will be converted to double precision" << endl ;
02910       setAttribute("BYTE_TREE_BRANCH",kTRUE) ;
02911       _treeVar = kTRUE ;
02912       t.SetBranchAddress(cleanName,&_byteValue) ;
02913     } else if (!typeName.CompareTo("Char_t")) {
02914       coutI(Eval) << "RooAbsReal::attachToTree(" << GetName() << ") TTree Char_t branch " << GetName() 
02915                   << " will be converted to double precision" << endl ;
02916       setAttribute("SIGNEDBYTE_TREE_BRANCH",kTRUE) ;
02917       _treeVar = kTRUE ;
02918       t.SetBranchAddress(cleanName,&_sbyteValue) ;
02919     }  else if (!typeName.CompareTo("UInt_t")) { 
02920       coutI(Eval) << "RooAbsReal::attachToTree(" << GetName() << ") TTree UInt_t branch " << GetName() 
02921                   << " will be converted to double precision" << endl ;
02922       setAttribute("UNSIGNED_INTEGER_TREE_BRANCH",kTRUE) ;
02923       _treeVar = kTRUE ;
02924       t.SetBranchAddress(cleanName,&_uintValue) ;
02925     } else if (!typeName.CompareTo("Double_t")) {
02926       t.SetBranchAddress(cleanName,&_value) ;
02927     } else {
02928       coutE(InputArguments) << "RooAbsReal::attachToTree(" << GetName() << ") data type " << typeName << " is not supported" << endl ;
02929     }   
02930     
02931     if (branch->GetCompressionLevel()<0) {
02932       // cout << "RooAbsReal::attachToTree(" << GetName() << ") Fixing compression level of branch " << cleanName << endl ;
02933       branch->SetCompressionLevel(1) ;
02934     }
02935 
02936 //      cout << "RooAbsReal::attachToTree(" << cleanName << "): branch already exists in tree " << (void*)&t << ", changing address" << endl ;
02937 
02938   } else {
02939 
02940     TString format(cleanName);
02941     format.Append("/D");
02942     branch = t.Branch(cleanName, &_value, (const Text_t*)format, bufSize);
02943     branch->SetCompressionLevel(1) ;
02944     //      cout << "RooAbsReal::attachToTree(" << cleanName << "): creating new branch in tree " << (void*)&t << endl ;
02945   }
02946 
02947 }
02948 
02949 
02950 
02951 //_____________________________________________________________________________
02952 void RooAbsReal::fillTreeBranch(TTree& t) 
02953 {
02954   // Fill the tree branch that associated with this object with its current value
02955 
02956   // First determine if branch is taken
02957   TBranch* branch = t.GetBranch(cleanBranchName()) ;
02958   if (!branch) { 
02959     coutE(Eval) << "RooAbsReal::fillTreeBranch(" << GetName() << ") ERROR: not attached to tree: " << cleanBranchName() << endl ;
02960     assert(0) ;
02961   }
02962   branch->Fill() ;
02963   
02964 }
02965 
02966 
02967 
02968 //_____________________________________________________________________________
02969 void RooAbsReal::setTreeBranchStatus(TTree& t, Bool_t active) 
02970 {
02971   // (De)Activate associated tree branch
02972 
02973   TBranch* branch = t.GetBranch(cleanBranchName()) ;
02974   if (branch) { 
02975     t.SetBranchStatus(cleanBranchName(),active?1:0) ;
02976   }
02977 }
02978 
02979 
02980 
02981 //_____________________________________________________________________________
02982 RooAbsArg *RooAbsReal::createFundamental(const char* newname) const 
02983 {
02984   // Create a RooRealVar fundamental object with our properties. The new
02985   // object will be created without any fit limits.
02986 
02987   RooRealVar *fund= new RooRealVar(newname?newname:GetName(),GetTitle(),_value,getUnit());
02988   fund->removeRange();
02989   fund->setPlotLabel(getPlotLabel());
02990   fund->setAttribute("fundamentalCopy");
02991   return fund;
02992 }
02993 
02994 
02995 
02996 //_____________________________________________________________________________
02997 Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
02998                               const RooArgProxy& a) const
02999 {
03000   // Utility function for use in getAnalyticalIntegral(). If the
03001   // content of proxy 'a' occurs in set 'allDeps' then the argument
03002   // held in 'a' is copied from allDeps to analDeps
03003 
03004   TList nameList ;
03005   nameList.Add(new TObjString(a.absArg()->GetName())) ;
03006   Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
03007   nameList.Delete() ;
03008   return result ;
03009 }
03010 
03011 
03012 
03013 //_____________________________________________________________________________
03014 Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
03015                               const RooArgProxy& a, const RooArgProxy& b) const
03016 {
03017   // Utility function for use in getAnalyticalIntegral(). If the
03018   // contents of proxies a,b occur in set 'allDeps' then the arguments
03019   // held in a,b are copied from allDeps to analDeps
03020 
03021   TList nameList ;
03022   nameList.Add(new TObjString(a.absArg()->GetName())) ;
03023   nameList.Add(new TObjString(b.absArg()->GetName())) ;  
03024   Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
03025   nameList.Delete() ;
03026   return result ;
03027 }
03028 
03029 
03030 
03031 //_____________________________________________________________________________
03032 Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
03033                               const RooArgProxy& a, const RooArgProxy& b,
03034                               const RooArgProxy& c) const
03035 {
03036   // Utility function for use in getAnalyticalIntegral(). If the
03037   // contents of proxies a,b,c occur in set 'allDeps' then the arguments
03038   // held in a,b,c are copied from allDeps to analDeps
03039 
03040   TList nameList ;
03041   nameList.Add(new TObjString(a.absArg()->GetName())) ;
03042   nameList.Add(new TObjString(b.absArg()->GetName())) ;
03043   nameList.Add(new TObjString(c.absArg()->GetName())) ;
03044   Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
03045   nameList.Delete() ;
03046   return result ;
03047 }
03048 
03049 
03050 
03051 //_____________________________________________________________________________
03052 Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
03053                               const RooArgProxy& a, const RooArgProxy& b,
03054                               const RooArgProxy& c, const RooArgProxy& d) const
03055 {
03056   // Utility function for use in getAnalyticalIntegral(). If the
03057   // contents of proxies a,b,c,d occur in set 'allDeps' then the arguments
03058   // held in a,b,c,d are copied from allDeps to analDeps
03059 
03060   TList nameList ;
03061   nameList.Add(new TObjString(a.absArg()->GetName())) ;
03062   nameList.Add(new TObjString(b.absArg()->GetName())) ;
03063   nameList.Add(new TObjString(c.absArg()->GetName())) ;
03064   nameList.Add(new TObjString(d.absArg()->GetName())) ;
03065   Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
03066   nameList.Delete() ;
03067   return result ;
03068 }
03069 
03070 
03071 //_____________________________________________________________________________
03072 Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
03073                              const RooArgSet& refset) const 
03074 {
03075   // Utility function for use in getAnalyticalIntegral(). If the
03076   // contents of 'refset' occur in set 'allDeps' then the arguments
03077   // held in 'refset' are copied from allDeps to analDeps.
03078 
03079   TList nameList ;
03080   TIterator* iter = refset.createIterator() ;
03081   RooAbsArg* arg ;
03082   while ((arg=(RooAbsArg*)iter->Next())) {
03083     nameList.Add(new TObjString(arg->GetName())) ;    
03084   }
03085   delete iter ;
03086 
03087   Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
03088   nameList.Delete() ;
03089   return result ;
03090 }
03091 
03092 
03093 
03094 //_____________________________________________________________________________
03095 Bool_t RooAbsReal::matchArgsByName(const RooArgSet &allArgs, RooArgSet &matchedArgs,
03096                                   const TList &nameList) const 
03097 {
03098   // Check if allArgs contains matching elements for each name in nameList. If it does,
03099   // add the corresponding args from allArgs to matchedArgs and return kTRUE. Otherwise
03100   // return kFALSE and do not change matchedArgs.
03101   
03102   RooArgSet matched("matched");
03103   TIterator *iterator= nameList.MakeIterator();
03104   TObjString *name = 0;
03105   Bool_t isMatched(kTRUE);
03106   while((isMatched && (name= (TObjString*)iterator->Next()))) {
03107     RooAbsArg *found= allArgs.find(name->String().Data());
03108     if(found) {
03109       matched.add(*found);
03110     }
03111     else {
03112       isMatched= kFALSE;
03113     }
03114   }
03115 
03116   // nameList may not contain multiple entries with the same name
03117   // that are both matched
03118   if (isMatched && (matched.getSize()!=nameList.GetSize())) {
03119     isMatched = kFALSE ;
03120   }
03121 
03122   delete iterator;
03123   if(isMatched) matchedArgs.add(matched);
03124   return isMatched;
03125 }
03126 
03127 
03128 
03129 //_____________________________________________________________________________
03130 RooNumIntConfig* RooAbsReal::defaultIntegratorConfig() 
03131 {
03132   // Returns the default numeric integration configuration for all RooAbsReals
03133   return &RooNumIntConfig::defaultConfig() ;
03134 }
03135 
03136 
03137 //_____________________________________________________________________________
03138 RooNumIntConfig* RooAbsReal::specialIntegratorConfig() const
03139 {
03140   // Returns the specialized integrator configuration for _this_ RooAbsReal.
03141   // If this object has no specialized configuration, a null pointer is returned.
03142 
03143   return _specIntegratorConfig ;
03144 }
03145  
03146 
03147 //_____________________________________________________________________________
03148 RooNumIntConfig* RooAbsReal::specialIntegratorConfig(Bool_t createOnTheFly) 
03149 {
03150   // Returns the specialized integrator configuration for _this_ RooAbsReal.
03151   // If this object has no specialized configuration, a null pointer is returned,
03152   // unless createOnTheFly is kTRUE in which case a clone of the default integrator
03153   // configuration is created, installed as specialized configuration, and returned
03154 
03155   if (!_specIntegratorConfig && createOnTheFly) {
03156     _specIntegratorConfig = new RooNumIntConfig(*defaultIntegratorConfig()) ;
03157   }
03158   return _specIntegratorConfig ;
03159 }
03160 
03161 
03162 
03163 //_____________________________________________________________________________
03164 const RooNumIntConfig* RooAbsReal::getIntegratorConfig() const 
03165 {
03166   // Return the numeric integration configuration used for this object. If
03167   // a specialized configuration was associated with this object, that configuration
03168   // is returned, otherwise the default configuration for all RooAbsReals is returned
03169 
03170   const RooNumIntConfig* config = specialIntegratorConfig() ;
03171   if (config) return config ;
03172   return defaultIntegratorConfig() ;
03173 }
03174 
03175 
03176 //_____________________________________________________________________________
03177 RooNumIntConfig* RooAbsReal::getIntegratorConfig() 
03178 {
03179   // Return the numeric integration configuration used for this object. If
03180   // a specialized configuration was associated with this object, that configuration
03181   // is returned, otherwise the default configuration for all RooAbsReals is returned
03182 
03183   RooNumIntConfig* config = specialIntegratorConfig() ;
03184   if (config) return config ;
03185   return defaultIntegratorConfig() ;
03186 }
03187 
03188 
03189 
03190 //_____________________________________________________________________________
03191 void RooAbsReal::setIntegratorConfig(const RooNumIntConfig& config) 
03192 {
03193   // Set the given integrator configuration as default numeric integration
03194   // configuration for this object
03195   if (_specIntegratorConfig) {
03196     delete _specIntegratorConfig ;
03197   }
03198   _specIntegratorConfig = new RooNumIntConfig(config) ;  
03199 }
03200 
03201 
03202 
03203 //_____________________________________________________________________________
03204 void RooAbsReal::setIntegratorConfig() 
03205 {
03206   // Remove the specialized numeric integration configuration associated
03207   // with this object
03208   if (_specIntegratorConfig) {
03209     delete _specIntegratorConfig ;
03210   }
03211   _specIntegratorConfig = 0 ;
03212 }
03213 
03214 
03215 
03216 
03217 //_____________________________________________________________________________
03218 void RooAbsReal::selectNormalization(const RooArgSet*, Bool_t) 
03219 {
03220   // Interface function to force use of a given set of observables
03221   // to interpret function value. Needed for functions or p.d.f.s
03222   // whose shape depends on the choice of normalization such as
03223   // RooAddPdf
03224 }
03225  
03226 
03227 
03228 
03229 //_____________________________________________________________________________
03230 void RooAbsReal::selectNormalizationRange(const char*, Bool_t) 
03231 {
03232   // Interface function to force use of a given normalization range
03233   // to interpret function value. Needed for functions or p.d.f.s
03234   // whose shape depends on the choice of normalization such as
03235   // RooAddPdf
03236 }
03237 
03238 
03239 
03240 //_____________________________________________________________________________
03241 void RooAbsReal::setCacheCheck(Bool_t flag) 
03242 { 
03243   // Activate cache validation mode
03244   _cacheCheck = flag ; 
03245 }
03246 
03247 
03248 
03249 //_____________________________________________________________________________
03250 Int_t RooAbsReal::getMaxVal(const RooArgSet& /*vars*/) const 
03251 {
03252   // Advertise capability to determine maximum value of function for given set of 
03253   // observables. If no direct generator method is provided, this information
03254   // will assist the accept/reject generator to operate more efficiently as
03255   // it can skip the initial trial sampling phase to empirically find the function
03256   // maximum
03257 
03258   return 0 ;
03259 }
03260 
03261 
03262 
03263 //_____________________________________________________________________________
03264 Double_t RooAbsReal::maxVal(Int_t /*code*/) const
03265 {
03266   // Return maximum value for set of observables identified by code assigned
03267   // in getMaxVal
03268 
03269   assert(1) ;
03270   return 0 ;
03271 }
03272 
03273 
03274 
03275 //_____________________________________________________________________________
03276 void RooAbsReal::EvalError::setMessage(const char* tmp) 
03277 { 
03278   if (strlen(tmp)<1023) {
03279     strlcpy(_msg,tmp,1023) ; 
03280   } else {
03281     strncpy(_msg,tmp,1020); 
03282     _msg[1020]='.' ; _msg[1021]='.' ; 
03283     _msg[1022]='.' ; _msg[1023]=0 ;    
03284   }
03285 }
03286 
03287 
03288 
03289 //_____________________________________________________________________________
03290 void RooAbsReal::EvalError::setServerValues(const char* tmp) 
03291 { 
03292   if (strlen(tmp)<1023) {
03293     strlcpy(_srvval,tmp,1023) ; 
03294   } else {
03295     strncpy(_srvval,tmp,1020); 
03296     _srvval[1020]='.' ; _srvval[1021]='.' ;
03297     _srvval[1022]='.' ; _srvval[1023]=0 ;    
03298   }
03299 }
03300 
03301 
03302 
03303 //_____________________________________________________________________________
03304 void RooAbsReal::logEvalError(const RooAbsReal* originator, const char* origName, const char* message, const char* serverValueString) 
03305 {
03306   // Interface to insert remote error logging messages received by RooRealMPFE into current error loggin stream
03307 
03308   if (_evalErrorMode==CountErrors) {
03309     _evalErrorCount++ ;
03310     return ;
03311   }
03312 
03313   static Bool_t inLogEvalError = kFALSE ;  
03314 
03315   if (inLogEvalError) {
03316     return ;
03317   }
03318   inLogEvalError = kTRUE ;
03319 
03320   EvalError ee ;
03321   ee.setMessage(message) ;
03322 
03323   if (serverValueString) {
03324     ee.setServerValues(serverValueString) ;
03325   } 
03326 
03327   if (_evalErrorMode==PrintErrors) {
03328    oocoutE((TObject*)0,Eval) << "RooAbsReal::logEvalError(" << "<STATIC>" << ") evaluation error, " << endl 
03329                    << " origin       : " << origName << endl 
03330                    << " message      : " << ee._msg << endl
03331                    << " server values: " << ee._srvval << endl ;
03332   } else if (_evalErrorMode==CollectErrors) {
03333     _evalErrorList[originator].first = origName ;
03334     _evalErrorList[originator].second.push_back(ee) ;
03335   }
03336 
03337 
03338   inLogEvalError = kFALSE ;
03339 }
03340 
03341 
03342 
03343 //_____________________________________________________________________________
03344 void RooAbsReal::logEvalError(const char* message, const char* serverValueString) const
03345 {
03346   // Log evaluation error message. Evaluation errors may be routed through a different
03347   // protocol than generic RooFit warning message (which go straight through RooMsgService)
03348   // because evaluation errors can occur in very large numbers in the use of likelihood
03349   // evaluations. In logEvalError mode, controlled by global method enableEvalErrorLogging()
03350   // messages reported through this function are not printed but all stored in a list,
03351   // along with server values at the time of reporting. Error messages logged in this
03352   // way can be printed in a structured way, eliminating duplicates and with the ability
03353   // to truncate the list by printEvalErrors. This is the standard mode of error logging
03354   // during MINUIT operations. If enableEvalErrorLogging() is false, all errors
03355   // reported through this method are passed for immediate printing through RooMsgService.
03356   // A string with server names and values is constructed automatically for error logging
03357   // purposes, unless a custom string with similar information is passed as argument.
03358 
03359   if (_evalErrorMode==CountErrors) {
03360     _evalErrorCount++ ;
03361     return ;
03362   }
03363 
03364   static Bool_t inLogEvalError = kFALSE ;  
03365 
03366   if (inLogEvalError) {
03367     return ;
03368   }
03369   inLogEvalError = kTRUE ;
03370 
03371   EvalError ee ;
03372   ee.setMessage(message) ;
03373 
03374   if (serverValueString) {
03375     ee.setServerValues(serverValueString) ;
03376   } else {
03377     string srvval ;
03378     ostringstream oss ;
03379     Bool_t first(kTRUE) ;
03380     for (Int_t i=0 ; i<numProxies() ; i++) {
03381       //RooAbsProxy* p = getProxy(i) ;
03382       //if (p->name()[0]=='!') continue ;
03383       if (first) {
03384         first=kFALSE ;
03385       } else {
03386         oss << ", " ;
03387       }
03388       getProxy(i)->print(oss,kTRUE) ;
03389     }
03390     ee.setServerValues(oss.str().c_str()) ;
03391   }
03392 
03393   ostringstream oss2 ;
03394   printStream(oss2,kName|kClassName|kArgs,kInline)  ;
03395 
03396   if (_evalErrorMode==PrintErrors) {
03397    coutE(Eval) << "RooAbsReal::logEvalError(" << GetName() << ") evaluation error, " << endl 
03398                << " origin       : " << oss2.str() << endl 
03399                << " message      : " << ee._msg << endl
03400                << " server values: " << ee._srvval << endl ;
03401   } else if (_evalErrorMode==CollectErrors) {
03402     _evalErrorList[this].first = oss2.str().c_str() ;
03403     _evalErrorList[this].second.push_back(ee) ;
03404   }
03405 
03406   inLogEvalError = kFALSE ;
03407   //coutE(Tracing) << "RooAbsReal::logEvalError(" << GetName() << ") message = " << message << endl ;
03408 }
03409 
03410 
03411 
03412 
03413 //_____________________________________________________________________________
03414 void RooAbsReal::clearEvalErrorLog() 
03415 {
03416   // Clear the stack of evaluation error messages
03417   if (_evalErrorMode==PrintErrors) {
03418     return ;
03419   } else if (_evalErrorMode==CollectErrors) {
03420     _evalErrorList.clear() ;
03421   } else {
03422     _evalErrorCount = 0 ;
03423   }
03424 }
03425 
03426 
03427 
03428 //_____________________________________________________________________________
03429 void RooAbsReal::printEvalErrors(ostream& os, Int_t maxPerNode) 
03430 {
03431   // Print all outstanding logged evaluation error on the given ostream. If maxPerNode
03432   // is zero, only the number of errors for each source (object with unique name) is listed.
03433   // If maxPerNode is greater than zero, up to maxPerNode detailed error messages are shown
03434   // per source of errors. A truncation message is shown if there were more errors logged
03435   // than shown.
03436 
03437   if (_evalErrorMode == CountErrors) {
03438     os << _evalErrorCount << " errors counted" << endl ;
03439   }
03440 
03441   if (maxPerNode<0) return ;
03442 
03443   map<const RooAbsArg*,pair<string,list<EvalError> > >::iterator iter = _evalErrorList.begin() ;
03444 
03445   for(;iter!=_evalErrorList.end() ; ++iter) {
03446     if (maxPerNode==0) {
03447 
03448       // Only print node name with total number of errors
03449       os << iter->second.first ;
03450       //iter->first->printStream(os,kName|kClassName|kArgs,kInline)  ;
03451       os << " has " << iter->second.second.size() << " errors" << endl ;      
03452 
03453     } else {
03454 
03455       // Print node name and details of 'maxPerNode' errors
03456       os << iter->second.first << endl ;
03457       //iter->first->printStream(os,kName|kClassName|kArgs,kSingleLine) ;
03458 
03459       Int_t i(0) ;
03460       std::list<EvalError>::iterator iter2 = iter->second.second.begin() ;
03461       for(;iter2!=iter->second.second.end() ; ++iter2, i++) {
03462         os << "     " << iter2->_msg << " @ " << iter2->_srvval << endl ;
03463         if (i>maxPerNode) {
03464           os << "    ... (remaining " << iter->second.second.size() - maxPerNode << " messages suppressed)" << endl ;
03465           break ;
03466         }
03467       } 
03468     }
03469   }
03470 }
03471 
03472 
03473 
03474 //_____________________________________________________________________________
03475 Int_t RooAbsReal::numEvalErrors()
03476 {
03477   // Return the number of logged evaluation errors since the last clearing.
03478   if (_evalErrorMode==CountErrors) {
03479     return _evalErrorCount ;
03480   }
03481 
03482   Int_t ntot(0) ;
03483   map<const RooAbsArg*,pair<string,list<EvalError> > >::iterator iter = _evalErrorList.begin() ;
03484   for(;iter!=_evalErrorList.end() ; ++iter) {
03485     ntot += iter->second.second.size() ;
03486   }
03487   return ntot ;
03488 }
03489 
03490 
03491 
03492 //_____________________________________________________________________________
03493 void RooAbsReal::fixAddCoefNormalization(const RooArgSet& addNormSet, Bool_t force) 
03494 {
03495   // Fix the interpretation of the coefficient of any RooAddPdf component in
03496   // the expression tree headed by this object to the given set of observables.
03497   //
03498   // If the force flag is false, the normalization choice is only fixed for those
03499   // RooAddPdf components that have the default 'automatic' interpretation of
03500   // coefficients (i.e. the interpretation is defined by the observables passed
03501   // to getVal()). If force is true, also RooAddPdf that already have a fixed
03502   // interpretation are changed to a new fixed interpretation.
03503 
03504   RooArgSet* compSet = getComponents() ;
03505   TIterator* iter = compSet->createIterator() ;
03506   RooAbsArg* arg ;
03507   while((arg=(RooAbsArg*)iter->Next())) {
03508     RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(arg) ;
03509     if (pdf) {
03510       if (addNormSet.getSize()>0) {
03511         pdf->selectNormalization(&addNormSet,force) ;
03512       } else {
03513         pdf->selectNormalization(0,force) ;
03514       }
03515     } 
03516   }
03517   delete iter ;
03518   delete compSet ;  
03519 }
03520 
03521 
03522 
03523 //_____________________________________________________________________________
03524 void RooAbsReal::fixAddCoefRange(const char* rangeName, Bool_t force) 
03525 {
03526   // Fix the interpretation of the coefficient of any RooAddPdf component in
03527   // the expression tree headed by this object to the given set of observables.
03528   //
03529   // If the force flag is false, the normalization range choice is only fixed for those
03530   // RooAddPdf components that currently use the default full domain to interpret their
03531   // coefficients. If force is true, also RooAddPdf that already have a fixed
03532   // interpretation range are changed to a new fixed interpretation range.
03533 
03534   RooArgSet* compSet = getComponents() ;
03535   TIterator* iter = compSet->createIterator() ;
03536   RooAbsArg* arg ;
03537   while((arg=(RooAbsArg*)iter->Next())) {
03538     RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(arg) ;
03539     if (pdf) {
03540       pdf->selectNormalizationRange(rangeName,force) ;
03541     }
03542   }
03543   delete iter ;
03544   delete compSet ;    
03545 }
03546 
03547 
03548 
03549 //_____________________________________________________________________________
03550 void RooAbsReal::preferredObservableScanOrder(const RooArgSet& obs, RooArgSet& orderedObs) const
03551 {
03552   // Interface method for function objects to indicate their prefferred order of observables
03553   // for scanning their values into a (multi-dimensional) histogram or RooDataSet. The observables
03554   // to be ordered are offered in argument 'obs' and should be copied in their preferred
03555   // order into argument 'orderdObs', This default implementation indicates no preference
03556   // and copies the original order of 'obs' into 'orderedObs'
03557 
03558   // Dummy implementation, do nothing 
03559   orderedObs.removeAll() ;
03560   orderedObs.add(obs) ;
03561 }
03562 
03563 
03564 
03565 //_____________________________________________________________________________
03566 RooAbsReal* RooAbsReal::createRunningIntegral(const RooArgSet& iset, const RooArgSet& nset) 
03567 {
03568   // Create a running integral over this function, i.e. given a f(x), create an object
03569   // representing 'int[x_lo,x] f(x_prime) dx_prime'
03570 
03571   return createRunningIntegral(iset,RooFit::SupNormSet(nset)) ;
03572 }
03573 
03574 
03575 
03576 //_____________________________________________________________________________
03577 RooAbsReal* RooAbsReal::createRunningIntegral(const RooArgSet& iset, const RooCmdArg& arg1, const RooCmdArg& arg2,
03578                                  const RooCmdArg& arg3, const RooCmdArg& arg4, const RooCmdArg& arg5, 
03579                                  const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) 
03580 {
03581   // Create an object that represents the running integral of the function over one or more observables listed in iset, i.e.
03582   // 
03583   //   int[x_lo,x] f(x_prime) dx_prime
03584   // 
03585   // The actual integration calculation is only performed when the return object is evaluated. The name
03586   // of the integral object is automatically constructed from the name of the input function, the variables
03587   // it integrates and the range integrates over. The default strategy to calculate the running integrals is
03588   //
03589   //   - If the integrand (this object) supports analytical integration, construct an integral object
03590   //     that calculate the running integrals value by calculating the analytical integral each
03591   //     time the running integral object is evaluated
03592   //
03593   //   - If the integrand (this object) requires numeric integration to construct the running integral
03594   //     create an object of class RooNumRunningInt which first samples the entire function and integrates
03595   //     the sampled function numerically. This method has superior performance as there is no need to
03596   //     perform a full (numeric) integration for each evaluation of the running integral object, but
03597   //     only when one of its parameters has changed.
03598   //
03599   // The choice of strategy can be changed with the ScanAll() argument, which forces the use of the
03600   // scanning technique implemented in RooNumRunningInt for all use cases, and with the ScanNone()
03601   // argument which forces the 'integrate each evaluation' technique for all use cases. The sampling
03602   // granularity for the scanning technique can be controlled with the ScanParameters technique
03603   // which allows to specify the number of samples to be taken, and to which order the resulting
03604   // running integral should be interpolated. The default values are 1000 samples and 2nd order
03605   // interpolation.
03606   //
03607   // The following named arguments are accepted
03608   //
03609   // SupNormSet(const RooArgSet&)         -- Observables over which should be normalized _in_addition_ to the
03610   //                                         integration observables
03611   // ScanParameters(Int_t nbins,          -- Parameters for scanning technique of making CDF: number
03612   //                Int_t intOrder)          of sampled bins and order of interpolation applied on numeric cdf
03613   // ScanNum()                            -- Apply scanning technique if cdf integral involves numeric integration
03614   // ScanAll()                            -- Always apply scanning technique 
03615   // ScanNone()                           -- Never apply scanning technique                  
03616 
03617   // Define configuration for this method
03618   RooCmdConfig pc(Form("RooAbsReal::createRunningIntegral(%s)",GetName())) ;
03619   pc.defineObject("supNormSet","SupNormSet",0,0) ;
03620   pc.defineInt("numScanBins","ScanParameters",0,1000) ;
03621   pc.defineInt("intOrder","ScanParameters",1,2) ;
03622   pc.defineInt("doScanNum","ScanNum",0,1) ;
03623   pc.defineInt("doScanAll","ScanAll",0,0) ;
03624   pc.defineInt("doScanNon","ScanNone",0,0) ;
03625   pc.defineMutex("ScanNum","ScanAll","ScanNone") ;
03626 
03627   // Process & check varargs 
03628   pc.process(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
03629   if (!pc.ok(kTRUE)) {
03630     return 0 ;
03631   }
03632 
03633   // Extract values from named arguments
03634   const RooArgSet* snset = static_cast<const RooArgSet*>(pc.getObject("supNormSet",0)) ;
03635   RooArgSet nset ;
03636   if (snset) {
03637     nset.add(*snset) ;
03638   }
03639   Int_t numScanBins = pc.getInt("numScanBins") ;
03640   Int_t intOrder = pc.getInt("intOrder") ;
03641   Int_t doScanNum = pc.getInt("doScanNum") ;
03642   Int_t doScanAll = pc.getInt("doScanAll") ;
03643   Int_t doScanNon = pc.getInt("doScanNon") ;
03644 
03645   // If scanning technique is not requested make integral-based cdf and return
03646   if (doScanNon) {
03647     return createIntRI(iset,nset) ;
03648   }
03649   if (doScanAll) {
03650     return createScanRI(iset,nset,numScanBins,intOrder) ;
03651   }
03652   if (doScanNum) {
03653     RooRealIntegral* tmp = (RooRealIntegral*) createIntegral(iset) ;
03654     Int_t isNum= (tmp->numIntRealVars().getSize()==1) ;
03655     delete tmp ;
03656 
03657     if (isNum) {
03658       coutI(NumIntegration) << "RooAbsPdf::createRunningIntegral(" << GetName() << ") integration over observable(s) " << iset << " involves numeric integration," << endl 
03659                             << "      constructing cdf though numeric integration of sampled pdf in " << numScanBins << " bins and applying order " 
03660                             << intOrder << " interpolation on integrated histogram." << endl 
03661                             << "      To override this choice of technique use argument ScanNone(), to change scan parameters use ScanParameters(nbins,order) argument" << endl ;
03662     }
03663     
03664     return isNum ? createScanRI(iset,nset,numScanBins,intOrder) : createIntRI(iset,nset) ;
03665   }
03666   return 0 ;
03667 }
03668 
03669 
03670 
03671 //_____________________________________________________________________________
03672 RooAbsReal* RooAbsReal::createScanRI(const RooArgSet& iset, const RooArgSet& nset, Int_t numScanBins, Int_t intOrder) 
03673 {
03674   // Utility function for createRunningIntegral that construct an object
03675   // implementing the numeric scanning technique for calculating the running integral
03676   
03677   string name = string(GetName()) + "_NUMRUNINT_" + integralNameSuffix(iset,&nset).Data() ;  
03678   RooRealVar* ivar = (RooRealVar*) iset.first() ;
03679   ivar->setBins(numScanBins,"numcdf") ;
03680   RooNumRunningInt* ret = new RooNumRunningInt(name.c_str(),name.c_str(),*this,*ivar,"numrunint") ;
03681   ret->setInterpolationOrder(intOrder) ;
03682   return ret ;
03683 }
03684 
03685 
03686 
03687 //_____________________________________________________________________________
03688 RooAbsReal* RooAbsReal::createIntRI(const RooArgSet& iset, const RooArgSet& nset) 
03689 {
03690   // Utility function for createRunningIntegral that construct an
03691   // object implementing the standard (analytical) integration
03692   // technique for calculating the running integral
03693 
03694   // Make list of input arguments keeping only RooRealVars
03695   RooArgList ilist ;
03696   TIterator* iter2 = iset.createIterator() ;
03697   RooAbsArg* arg ;
03698   while((arg=(RooAbsArg*)iter2->Next())) {
03699     if (dynamic_cast<RooRealVar*>(arg)) {
03700       ilist.add(*arg) ;
03701     } else {
03702       coutW(InputArguments) << "RooAbsPdf::createRunningIntegral(" << GetName() << ") WARNING ignoring non-RooRealVar input argument " << arg->GetName() << endl ;      
03703     }
03704   }
03705   delete iter2 ;
03706 
03707   RooArgList cloneList ;
03708   RooArgList loList ;
03709   RooArgSet clonedBranchNodes ;
03710 
03711   // Setup customizer that stores all cloned branches in our non-owning list
03712   RooCustomizer cust(*this,"cdf") ;
03713   cust.setCloneBranchSet(clonedBranchNodes) ;
03714   cust.setOwning(kFALSE) ;
03715 
03716   // Make integration observable x_prime for each observable x as well as an x_lowbound 
03717   TIterator* iter = ilist.createIterator() ;
03718   RooRealVar* rrv ;
03719   while((rrv=(RooRealVar*)iter->Next())) {
03720 
03721     // Make clone x_prime of each c.d.f observable x represening running integral
03722     RooRealVar* cloneArg = (RooRealVar*) rrv->clone(Form("%s_prime",rrv->GetName())) ;
03723     cloneList.add(*cloneArg) ;
03724     cust.replaceArg(*rrv,*cloneArg) ;
03725 
03726     // Make clone x_lowbound of each c.d.f observable representing low bound of x
03727     RooRealVar* cloneLo = (RooRealVar*) rrv->clone(Form("%s_lowbound",rrv->GetName())) ;
03728     cloneLo->setVal(rrv->getMin()) ;
03729     loList.add(*cloneLo) ;
03730 
03731     // Make parameterized binning from [x_lowbound,x] for each x_prime
03732     RooParamBinning pb(*cloneLo,*rrv,100) ;
03733     cloneArg->setBinning(pb,"CDF") ;
03734     
03735   }
03736   delete iter ;
03737 
03738   RooAbsReal* tmp = (RooAbsReal*) cust.build() ;
03739 
03740   // Construct final normalization set for c.d.f = integrated observables + any extra specified by user
03741   RooArgSet finalNset(nset) ;
03742   finalNset.add(cloneList,kTRUE) ;
03743   RooAbsReal* cdf = tmp->createIntegral(cloneList,finalNset,"CDF") ;
03744 
03745   // Transfer ownership of cloned items to top-level c.d.f object
03746   cdf->addOwnedComponents(*tmp) ;
03747   cdf->addOwnedComponents(cloneList) ;
03748   cdf->addOwnedComponents(loList) ;
03749 
03750   return cdf ;
03751 }
03752 
03753 
03754 //_____________________________________________________________________________
03755 RooFunctor* RooAbsReal::functor(const RooArgList& obs, const RooArgList& pars, const RooArgSet& nset) const 
03756 {
03757   // Return a RooFunctor object bound to this RooAbsReal with given definition of observables
03758   // and parameters
03759 
03760   RooArgSet* realObs = getObservables(obs) ;
03761   if (realObs->getSize() != obs.getSize()) {
03762     coutE(InputArguments) << "RooAbsReal::functor(" << GetName() << ") ERROR: one or more specified observables are not variables of this p.d.f" << endl ;
03763     delete realObs ;
03764     return 0 ;
03765   }
03766   RooArgSet* realPars = getObservables(pars) ;
03767   if (realPars->getSize() != pars.getSize()) {
03768     coutE(InputArguments) << "RooAbsReal::functor(" << GetName() << ") ERROR: one or more specified parameters are not variables of this p.d.f" << endl ;
03769     delete realPars ;
03770     return 0 ;
03771   }
03772   delete realObs ;
03773   delete realPars ;
03774 
03775   return new RooFunctor(*this,obs,pars,nset) ;
03776 }
03777 
03778 
03779 
03780 //_____________________________________________________________________________
03781 TF1* RooAbsReal::asTF(const RooArgList& obs, const RooArgList& pars, const RooArgSet& nset) const 
03782 {
03783   // Return a ROOT TF1,2,3 object bound to this RooAbsReal with given definition of observables
03784   // and parameters
03785 
03786   // Check that specified input are indeed variables of this function
03787   RooArgSet* realObs = getObservables(obs) ;
03788   if (realObs->getSize() != obs.getSize()) {
03789     coutE(InputArguments) << "RooAbsReal::functor(" << GetName() << ") ERROR: one or more specified observables are not variables of this p.d.f" << endl ;
03790     delete realObs ;
03791     return 0 ;
03792   }
03793   RooArgSet* realPars = getObservables(pars) ;
03794   if (realPars->getSize() != pars.getSize()) {
03795     coutE(InputArguments) << "RooAbsReal::functor(" << GetName() << ") ERROR: one or more specified parameters are not variables of this p.d.f" << endl ;
03796     delete realPars ;
03797     return 0 ;
03798   }
03799   delete realObs ;
03800   delete realPars ;
03801   
03802   // Check that all obs and par are of type RooRealVar
03803   for (int i=0 ; i<obs.getSize() ; i++) {
03804     if (dynamic_cast<RooRealVar*>(obs.at(i))==0) {
03805       coutE(ObjectHandling) << "RooAbsReal::asTF(" << GetName() << ") ERROR: proposed observable " << obs.at(0)->GetName() << " is not of type RooRealVar" << endl ;
03806       return 0 ;
03807     }
03808   }
03809   for (int i=0 ; i<pars.getSize() ; i++) {
03810     if (dynamic_cast<RooRealVar*>(pars.at(i))==0) {
03811       coutE(ObjectHandling) << "RooAbsReal::asTF(" << GetName() << ") ERROR: proposed parameter " << pars.at(0)->GetName() << " is not of type RooRealVar" << endl ;
03812       return 0 ;
03813     }
03814   }
03815   
03816   // Create functor and TFx of matching dimension
03817   TF1* tf=0 ;
03818   RooFunctor* f ;
03819   switch(obs.getSize()) {
03820   case 1: {
03821     RooRealVar* x = (RooRealVar*)obs.at(0) ;
03822     f = functor(obs,pars,nset) ;
03823     tf = new TF1(GetName(),f,x->getMin(),x->getMax(),pars.getSize(),"RooFunctor") ;
03824     break ;
03825   }
03826   case 2: {
03827     RooRealVar* x = (RooRealVar*)obs.at(0) ;
03828     RooRealVar* y = (RooRealVar*)obs.at(1) ;
03829     f = functor(obs,pars,nset) ;
03830     tf = new TF2(GetName(),f,x->getMin(),x->getMax(),y->getMin(),y->getMax(),pars.getSize(),"RooFunctor") ;
03831     break ;
03832   }
03833   case 3: {
03834     RooRealVar* x = (RooRealVar*)obs.at(0) ;
03835     RooRealVar* y = (RooRealVar*)obs.at(1) ;
03836     RooRealVar* z = (RooRealVar*)obs.at(2) ;
03837     f = functor(obs,pars,nset) ;
03838     tf = new TF3(GetName(),f,x->getMin(),x->getMax(),y->getMin(),y->getMax(),z->getMin(),z->getMax(),pars.getSize(),"RooFunctor") ;
03839     break ;
03840   }
03841   default:
03842     coutE(InputArguments) << "RooAbsReal::asTF(" << GetName() << ") ERROR: " << obs.getSize() 
03843                           << " observables specified, but a ROOT TFx can only have  1,2 or 3 observables" << endl ;
03844     return 0 ;
03845   }
03846 
03847   // Set initial parameter values of TFx to those of RooRealVars
03848   for (int i=0 ; i<pars.getSize() ; i++) {
03849     RooRealVar* p = (RooRealVar*) pars.at(i) ;
03850     tf->SetParameter(i,p->getVal()) ;
03851     tf->SetParName(i,p->GetName()) ;
03852     //tf->SetParLimits(i,p->getMin(),p->getMax()) ;
03853   }
03854 
03855   return tf ;
03856 }
03857 
03858 
03859 //_____________________________________________________________________________
03860 RooDerivative* RooAbsReal::derivative(RooRealVar& obs, Int_t order, Double_t eps) 
03861 {
03862   // Return function representing first, second or third order derivative of this function
03863   string name=Form("%s_DERIV_%s",GetName(),obs.GetName()) ;
03864   string title=Form("Derivative of %s w.r.t %s ",GetName(),obs.GetName()) ;
03865   return new RooDerivative(name.c_str(),title.c_str(),*this,obs,order,eps) ;
03866 }
03867 
03868 
03869 
03870 //_____________________________________________________________________________
03871 RooDerivative* RooAbsReal::derivative(RooRealVar& obs, const RooArgSet& normSet, Int_t order, Double_t eps) 
03872 {
03873   // Return function representing first, second or third order derivative of this function
03874   string name=Form("%s_DERIV_%s",GetName(),obs.GetName()) ;
03875   string title=Form("Derivative of %s w.r.t %s ",GetName(),obs.GetName()) ;
03876   return new RooDerivative(name.c_str(),title.c_str(),*this,obs,normSet,order,eps) ;
03877 }
03878 
03879 
03880 
03881 //_____________________________________________________________________________
03882 RooMoment* RooAbsReal::moment(RooRealVar& obs, Int_t order, Bool_t central, Bool_t takeRoot) 
03883 {
03884   // Return function representing moment of function of given order. If central is
03885   // true, the central moment is given <(x-<x>)^2>
03886   string name=Form("%s_MOMENT_%d%s_%s",GetName(),order,(central?"C":""),obs.GetName()) ;
03887   string title=Form("%sMoment of order %d of %s w.r.t %s ",(central?"Central ":""),order,GetName(),obs.GetName()) ;
03888   return new RooMoment(name.c_str(),title.c_str(),*this,obs,order,central,takeRoot) ;
03889 }
03890 
03891 
03892 //_____________________________________________________________________________
03893 RooMoment* RooAbsReal::moment(RooRealVar& obs, const RooArgSet& normObs, Int_t order, Bool_t central, Bool_t takeRoot, Bool_t intNormObs) 
03894 {
03895   // Return function representing moment of p.d.f (normalized w.r.t given observables) of given order. If central is
03896   // true, the central moment is given <(x-<x>)^2>. If intNormObs is true, the moment of the function integrated over
03897   // all normalization observables is returned.
03898   string name=Form("%s_MOMENT_%d%s_%s",GetName(),order,(central?"C":""),obs.GetName()) ;
03899   string title=Form("%sMoment of order %d of %s w.r.t %s ",(central?"Central ":""),order,GetName(),obs.GetName()) ;
03900   return new RooMoment(name.c_str(),title.c_str(),*this,obs,normObs,order,central,takeRoot,intNormObs) ;
03901 }
03902 
03903 
03904 
03905 //_____________________________________________________________________________
03906 Double_t RooAbsReal::findRoot(RooRealVar& x, Double_t xmin, Double_t xmax, Double_t yval) 
03907 {
03908   //
03909   // Return value of x (in range xmin,xmax) at which function equals yval.
03910   // (Calculation is performed with Brent root finding algorithm)
03911   
03912   Double_t result(0) ;
03913   RooBrentRootFinder(RooRealBinding(*this,x)).findRoot(result,xmin,xmax,yval) ;
03914   return result ;
03915 }
03916 
03917 
03918 
03919 
03920 //_____________________________________________________________________________
03921 RooGenFunction* RooAbsReal::iGenFunction(RooRealVar& x, const RooArgSet& nset) 
03922 {
03923   return new RooGenFunction(*this,x,RooArgList(),nset.getSize()>0?nset:RooArgSet(x)) ;
03924 }
03925 
03926 
03927 
03928 //_____________________________________________________________________________
03929 RooMultiGenFunction* RooAbsReal::iGenFunction(const RooArgSet& observables, const RooArgSet& nset) 
03930 {
03931   return new RooMultiGenFunction(*this,observables,RooArgList(),nset.getSize()>0?nset:observables) ;
03932 }
03933 
03934 
03935 
03936 
03937 //_____________________________________________________________________________
03938 RooFitResult* RooAbsReal::chi2FitTo(RooDataHist& data, const RooCmdArg& arg1,  const RooCmdArg& arg2,  
03939                                     const RooCmdArg& arg3,  const RooCmdArg& arg4, const RooCmdArg& arg5,  
03940                                     const RooCmdArg& arg6,  const RooCmdArg& arg7, const RooCmdArg& arg8) 
03941 {  
03942   // Perform a chi^2 fit to given histogram By default the fit is executed through the MINUIT
03943   // commands MIGRAD, HESSE in succession
03944   //
03945   // The following named arguments are supported
03946   //
03947   // Options to control construction of -log(L)
03948   // ------------------------------------------
03949   // Range(const char* name)         -- Fit only data inside range with given name
03950   // 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.
03951   //                                    Multiple comma separated range names can be specified.
03952   // NumCPU(int num)                 -- Parallelize NLL calculation on num CPUs
03953   // Optimize(Bool_t flag)           -- Activate constant term optimization (on by default)
03954   //
03955   // Options to control flow of fit procedure
03956   // ----------------------------------------
03957   // InitialHesse(Bool_t flag)      -- Flag controls if HESSE before MIGRAD as well, off by default
03958   // Hesse(Bool_t flag)             -- Flag controls if HESSE is run after MIGRAD, on by default
03959   // Minos(Bool_t flag)             -- Flag controls if MINOS is run after HESSE, on by default
03960   // Minos(const RooArgSet& set)    -- Only run MINOS on given subset of arguments
03961   // Save(Bool_t flag)              -- Flac controls if RooFitResult object is produced and returned, off by default
03962   // Strategy(Int_t flag)           -- Set Minuit strategy (0 through 2, default is 1)
03963   // FitOptions(const char* optStr) -- Steer fit with classic options string (for backward compatibility). Use of this option
03964   //                                   excludes use of any of the new style steering options.
03965   //
03966   // Options to control informational output
03967   // ---------------------------------------
03968   // Verbose(Bool_t flag)           -- Flag controls if verbose output is printed (NLL, parameter changes during fit
03969   // Timer(Bool_t flag)             -- Time CPU and wall clock consumption of fit steps, off by default
03970   // PrintLevel(Int_t level)        -- Set Minuit print level (-1 through 3, default is 1). At -1 all RooFit informational 
03971   //                                   messages are suppressed as well
03972   // Warnings(Bool_t flag)          -- Enable or disable MINUIT warnings (enabled by default)
03973   // PrintEvalErrors(Int_t numErr)  -- Control number of p.d.f evaluation errors printed per likelihood evaluation. A negative
03974   //                                   value suppress output completely, a zero value will only print the error count per p.d.f component,
03975   //                                   a positive value is will print details of each error up to numErr messages per p.d.f component.
03976   // 
03977   // 
03978   
03979   RooLinkedList l ;
03980   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
03981   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
03982   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
03983   l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
03984   return chi2FitTo(data,l) ;
03985   
03986 }
03987 
03988 
03989 
03990 //_____________________________________________________________________________
03991 RooFitResult* RooAbsReal::chi2FitTo(RooDataHist& data, const RooLinkedList& cmdList) 
03992 {
03993   // Internal back-end function to steer chi2 fits
03994 
03995   // Select the pdf-specific commands 
03996   RooCmdConfig pc(Form("RooAbsPdf::chi2FitTo(%s)",GetName())) ;
03997 
03998   // Pull arguments to be passed to chi2 construction from list
03999   RooLinkedList fitCmdList(cmdList) ;
04000   RooLinkedList chi2CmdList = pc.filterCmdList(fitCmdList,"Range,RangeWithName,NumCPU,Optimize") ;
04001 
04002   RooAbsReal* chi2 = createChi2(data,chi2CmdList) ;
04003   RooFitResult* ret = chi2FitDriver(*chi2,fitCmdList) ;
04004   
04005   // Cleanup
04006   delete chi2 ;
04007   return ret ;
04008 }
04009 
04010 
04011 
04012 
04013 //_____________________________________________________________________________
04014 RooAbsReal* RooAbsReal::createChi2(RooDataHist& data, const RooCmdArg& arg1,  const RooCmdArg& arg2,  
04015                                    const RooCmdArg& arg3,  const RooCmdArg& arg4, const RooCmdArg& arg5,  
04016                                    const RooCmdArg& arg6,  const RooCmdArg& arg7, const RooCmdArg& arg8) 
04017 {
04018   // Create a chi-2 from a histogram and this function.
04019   //
04020   // The following named arguments are supported
04021   //
04022   //  Options to control construction of the chi^2
04023   //  ------------------------------------------
04024   //  DataError(RooAbsData::ErrorType)  -- Choose between Poisson errors and Sum-of-weights errors
04025   //  NumCPU(Int_t)                     -- Activate parallel processing feature on N processes
04026   //  Range()                           -- Calculate Chi2 only in selected region
04027 
04028   string name = Form("chi2_%s_%s",GetName(),data.GetName()) ;
04029  
04030   return new RooChi2Var(name.c_str(),name.c_str(),*this,data,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
04031 }
04032 
04033 
04034 
04035 
04036 //_____________________________________________________________________________
04037 RooAbsReal* RooAbsReal::createChi2(RooDataHist& data, const RooLinkedList& cmdList) 
04038 {
04039   // Internal back-end function to create a chi2
04040 
04041   // Fill array of commands
04042   const RooCmdArg* cmds[8] ;
04043   TIterator* iter = cmdList.MakeIterator() ;
04044   Int_t i(0) ;
04045   RooCmdArg* arg ;
04046   while((arg=(RooCmdArg*)iter->Next())) {
04047     cmds[i++] = arg ;
04048   }
04049   for (;i<8 ; i++) {
04050     cmds[i] = &RooCmdArg::none() ;
04051   }
04052   delete iter ;
04053   
04054   // Construct chi2
04055   string name = Form("chi2_%s_%s",GetName(),data.GetName()) ;
04056   return new RooChi2Var(name.c_str(),name.c_str(),*this,data,*cmds[0],*cmds[1],*cmds[2],*cmds[3],*cmds[4],*cmds[5],*cmds[6],*cmds[7]) ;
04057   
04058 }
04059 
04060 
04061 
04062 
04063 
04064 //_____________________________________________________________________________
04065 RooFitResult* RooAbsReal::chi2FitTo(RooDataSet& xydata, const RooCmdArg& arg1,  const RooCmdArg& arg2,  
04066                                       const RooCmdArg& arg3,  const RooCmdArg& arg4, const RooCmdArg& arg5,  
04067                                       const RooCmdArg& arg6,  const RooCmdArg& arg7, const RooCmdArg& arg8) 
04068 {
04069   // Create a chi-2 from a series of x and y value stored in a dataset.
04070   // The y values can either be the event weights, or can be another column designated
04071   // by the YVar() argument. The y value must have errors defined for the chi-2 to
04072   // be well defined.
04073   //
04074   // The following named arguments are supported
04075   //
04076   // Options to control construction of the chi^2
04077   // ------------------------------------------
04078   // YVar(RooRealVar& yvar)          -- Designate given column in dataset as Y value 
04079   // Integrate(Bool_t flag)          -- Integrate function over range specified by X errors
04080   //                                    rather than take value at bin center.
04081   //
04082   // Options to control flow of fit procedure
04083   // ----------------------------------------
04084   // InitialHesse(Bool_t flag)      -- Flag controls if HESSE before MIGRAD as well, off by default
04085   // Hesse(Bool_t flag)             -- Flag controls if HESSE is run after MIGRAD, on by default
04086   // Minos(Bool_t flag)             -- Flag controls if MINOS is run after HESSE, on by default
04087   // Minos(const RooArgSet& set)    -- Only run MINOS on given subset of arguments
04088   // Save(Bool_t flag)              -- Flac controls if RooFitResult object is produced and returned, off by default
04089   // Strategy(Int_t flag)           -- Set Minuit strategy (0 through 2, default is 1)
04090   // FitOptions(const char* optStr) -- Steer fit with classic options string (for backward compatibility). Use of this option
04091   //                                   excludes use of any of the new style steering options.
04092   //
04093   // Options to control informational output
04094   // ---------------------------------------
04095   // Verbose(Bool_t flag)           -- Flag controls if verbose output is printed (NLL, parameter changes during fit
04096   // Timer(Bool_t flag)             -- Time CPU and wall clock consumption of fit steps, off by default
04097   // PrintLevel(Int_t level)        -- Set Minuit print level (-1 through 3, default is 1). At -1 all RooFit informational 
04098   //                                   messages are suppressed as well
04099   // Warnings(Bool_t flag)          -- Enable or disable MINUIT warnings (enabled by default)
04100   // PrintEvalErrors(Int_t numErr)  -- Control number of p.d.f evaluation errors printed per likelihood evaluation. A negative
04101   //                                   value suppress output completely, a zero value will only print the error count per p.d.f component,
04102   //                                   a positive value is will print details of each error up to numErr messages per p.d.f component.
04103 
04104   RooLinkedList l ;
04105   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
04106   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
04107   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
04108   l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
04109   return chi2FitTo(xydata,l) ;  
04110 }
04111 
04112 
04113 
04114 
04115 //_____________________________________________________________________________
04116 RooFitResult* RooAbsReal::chi2FitTo(RooDataSet& xydata, const RooLinkedList& cmdList) 
04117 {  
04118   // Internal back-end function to steer chi2 fits
04119   
04120   // Select the pdf-specific commands 
04121   RooCmdConfig pc(Form("RooAbsPdf::chi2FitTo(%s)",GetName())) ;
04122 
04123   // Pull arguments to be passed to chi2 construction from list
04124   RooLinkedList fitCmdList(cmdList) ;
04125   RooLinkedList chi2CmdList = pc.filterCmdList(fitCmdList,"YVar,Integrate") ;
04126 
04127   RooAbsReal* xychi2 = createChi2(xydata,chi2CmdList) ;
04128   RooFitResult* ret = chi2FitDriver(*xychi2,fitCmdList) ;
04129   
04130   // Cleanup
04131   delete xychi2 ;
04132   return ret ;
04133 }
04134 
04135 
04136 
04137 
04138 //_____________________________________________________________________________
04139 RooAbsReal* RooAbsReal::createChi2(RooDataSet& data, const RooCmdArg& arg1,  const RooCmdArg& arg2,  
04140                                      const RooCmdArg& arg3,  const RooCmdArg& arg4, const RooCmdArg& arg5,  
04141                                      const RooCmdArg& arg6,  const RooCmdArg& arg7, const RooCmdArg& arg8) 
04142 {
04143   // Create a chi-2 from a series of x and y value stored in a dataset.
04144   // The y values can either be the event weights (default), or can be another column designated
04145   // by the YVar() argument. The y value must have errors defined for the chi-2 to
04146   // be well defined. 
04147   //
04148   // The following named arguments are supported
04149   //
04150   // Options to control construction of the chi^2
04151   // ------------------------------------------
04152   // YVar(RooRealVar& yvar)          -- Designate given column in dataset as Y value 
04153   // Integrate(Bool_t flag)          -- Integrate function over range specified by X errors
04154   //                                    rather than take value at bin center.
04155   // 
04156   
04157   RooLinkedList l ;
04158   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
04159   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
04160   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
04161   l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
04162   return createChi2(data,l) ;
04163 }
04164 
04165 
04166 
04167 //_____________________________________________________________________________
04168 RooAbsReal* RooAbsReal::createChi2(RooDataSet& data, const RooLinkedList& cmdList) 
04169 {
04170   // Internal back-end function to create a chi^2 from a function and a dataset
04171 
04172   // Select the pdf-specific commands 
04173   RooCmdConfig pc(Form("RooAbsPdf::fitTo(%s)",GetName())) ;
04174 
04175   pc.defineInt("integrate","Integrate",0,0) ;
04176   pc.defineObject("yvar","YVar",0,0) ;
04177   
04178   // Process and check varargs 
04179   pc.process(cmdList) ;
04180   if (!pc.ok(kTRUE)) {
04181     return 0 ;
04182   }
04183 
04184   // Decode command line arguments 
04185   Bool_t integrate = pc.getInt("integrate") ;
04186   RooRealVar* yvar = (RooRealVar*) pc.getObject("yvar") ;
04187 
04188   string name = Form("chi2_%s_%s",GetName(),data.GetName()) ;
04189  
04190   if (yvar) {
04191     return new RooXYChi2Var(name.c_str(),name.c_str(),*this,data,*yvar,integrate) ;
04192   } else {
04193     return new RooXYChi2Var(name.c_str(),name.c_str(),*this,data,integrate) ;
04194   }  
04195 }
04196 
04197 
04198 
04199 
04200 
04201 
04202 //_____________________________________________________________________________
04203 RooFitResult* RooAbsReal::chi2FitDriver(RooAbsReal& fcn, RooLinkedList& cmdList) 
04204 {
04205   // Internal driver function for chi2 fits
04206 
04207   // Select the pdf-specific commands 
04208   RooCmdConfig pc(Form("RooAbsPdf::chi2FitDriver(%s)",GetName())) ;
04209 
04210   pc.defineString("fitOpt","FitOptions",0,"") ;
04211 
04212   pc.defineInt("optConst","Optimize",0,1) ;
04213   pc.defineInt("verbose","Verbose",0,0) ;
04214   pc.defineInt("doSave","Save",0,0) ;
04215   pc.defineInt("doTimer","Timer",0,0) ;
04216   pc.defineInt("plevel","PrintLevel",0,1) ;
04217   pc.defineInt("strat","Strategy",0,1) ;
04218   pc.defineInt("initHesse","InitialHesse",0,0) ;
04219   pc.defineInt("hesse","Hesse",0,1) ;
04220   pc.defineInt("minos","Minos",0,0) ;
04221   pc.defineInt("ext","Extended",0,2) ;
04222   pc.defineInt("numee","PrintEvalErrors",0,10) ;
04223   pc.defineInt("doWarn","Warnings",0,1) ;
04224   pc.defineObject("minosSet","Minos",0,0) ;
04225 
04226   pc.defineMutex("FitOptions","Verbose") ;
04227   pc.defineMutex("FitOptions","Save") ;
04228   pc.defineMutex("FitOptions","Timer") ;
04229   pc.defineMutex("FitOptions","Strategy") ;
04230   pc.defineMutex("FitOptions","InitialHesse") ;
04231   pc.defineMutex("FitOptions","Hesse") ;
04232   pc.defineMutex("FitOptions","Minos") ;
04233   
04234   // Process and check varargs 
04235   pc.process(cmdList) ;
04236   if (!pc.ok(kTRUE)) {
04237     return 0 ;
04238   }
04239 
04240   // Decode command line arguments
04241   const char* fitOpt = pc.getString("fitOpt",0,kTRUE) ;
04242   Int_t optConst = pc.getInt("optConst") ;
04243   Int_t verbose  = pc.getInt("verbose") ;
04244   Int_t doSave   = pc.getInt("doSave") ;
04245   Int_t doTimer  = pc.getInt("doTimer") ;
04246   Int_t plevel    = pc.getInt("plevel") ;
04247   Int_t strat    = pc.getInt("strat") ;
04248   Int_t initHesse= pc.getInt("initHesse") ;
04249   Int_t hesse    = pc.getInt("hesse") ;
04250   Int_t minos    = pc.getInt("minos") ;
04251   Int_t numee    = pc.getInt("numee") ;
04252   Int_t doWarn   = pc.getInt("doWarn") ;
04253   const RooArgSet* minosSet = static_cast<RooArgSet*>(pc.getObject("minosSet")) ;
04254 
04255   // Instantiate MINUIT
04256   RooMinuit m(fcn) ;
04257 
04258   if (doWarn==0) {
04259     m.setNoWarn() ;
04260   }
04261   
04262   m.setPrintEvalErrors(numee) ;
04263   if (plevel!=1) {
04264     m.setPrintLevel(plevel) ;
04265   }
04266 
04267   if (optConst) {
04268     // Activate constant term optimization
04269     m.optimizeConst(1) ;
04270   }
04271 
04272   RooFitResult *ret = 0 ;
04273 
04274   if (fitOpt) {
04275 
04276     // Play fit options as historically defined
04277     ret = m.fit(fitOpt) ;
04278     
04279   } else {
04280 
04281     if (verbose) {
04282       // Activate verbose options
04283       m.setVerbose(1) ;
04284     }
04285     if (doTimer) {
04286       // Activate timer options
04287       m.setProfile(1) ;
04288     }
04289     
04290     if (strat!=1) {
04291       // Modify fit strategy
04292       m.setStrategy(strat) ;
04293     }
04294 
04295     if (initHesse) {
04296       // Initialize errors with hesse
04297       m.hesse() ;
04298     }
04299 
04300     // Minimize using migrad
04301     m.migrad() ;
04302 
04303     if (hesse) {
04304       // Evaluate errors with Hesse
04305       m.hesse() ;
04306     }
04307 
04308     if (minos) {
04309       // Evaluate errs with Minos
04310       if (minosSet) {
04311         m.minos(*minosSet) ;
04312       } else {
04313         m.minos() ;
04314       }
04315     }
04316 
04317     // Optionally return fit result
04318     if (doSave) {
04319       string name = Form("fitresult_%s",fcn.GetName()) ;
04320       string title = Form("Result of fit of %s ",GetName()) ;
04321       ret = m.save(name.c_str(),title.c_str()) ;
04322     } 
04323 
04324   }
04325   
04326   // Cleanup
04327   return ret ;
04328 
04329 }
04330 
04331 
04332 //_____________________________________________________________________________
04333 RooAbsReal::ErrorLoggingMode RooAbsReal::evalErrorLoggingMode() 
04334 { 
04335   // Return current evaluation error logging mode. 
04336   return _evalErrorMode ; 
04337 }
04338 
04339 //_____________________________________________________________________________
04340 void RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::ErrorLoggingMode m) 
04341 { 
04342   // Set evaluation error logging mode. Options are
04343   //
04344   // PrintErrors - Print each error through RooMsgService() as it occurs
04345   // CollectErrors - Accumulate errors, but do not print them. A subsequent call
04346   //                 to printEvalErrors() will print a summary
04347   // CountErrors - Accumulate error count, but do not print them. 
04348   //
04349 
04350   _evalErrorMode =  m; 
04351 }
04352 
04353 
04354 
04355 

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