#include "RooFit.h"
#include "RooAbsReal.h"
#include "RooAbsReal.h"
#include "RooArgSet.h"
#include "RooArgList.h"
#include "RooPlot.h"
#include "RooCurve.h"
#include "RooRealVar.h"
#include "RooArgProxy.h"
#include "RooFormulaVar.h"
#include "RooRealBinding.h"
#include "RooRealIntegral.h"
#include "RooAbsCategoryLValue.h"
#include "RooCustomizer.h"
#include "RooAbsData.h"
#include "RooScaledFunc.h"
#include "RooDataProjBinding.h"
#include "RooAddPdf.h"
#include "RooCmdConfig.h"
#include "RooCategory.h"
#include "RooNumIntConfig.h"
#include "RooAddition.h"
#include "Riostream.h"
#include "TObjString.h"
#include "TTree.h"
#include "TH1.h"
#include "TH2.h"
#include "TH3.h"
#include "TBranch.h"
#include "TLeaf.h"
#include "TAttLine.h"
 
ClassImp(RooAbsReal)
;
Bool_t RooAbsReal::_cacheCheck(kFALSE) ;
RooAbsReal::RooAbsReal() : _specIntegratorConfig(0)
{
}
RooAbsReal::RooAbsReal(const char *name, const char *title, const char *unit) : 
  RooAbsArg(name,title), _plotMin(0), _plotMax(0), _plotBins(100), 
  _value(0),  _unit(unit), _forceNumInt(kFALSE), _specIntegratorConfig(0)
{
  
  setValueDirty() ;
  setShapeDirty() ;
}
RooAbsReal::RooAbsReal(const char *name, const char *title, Double_t minVal,
		       Double_t maxVal, const char *unit) :
  RooAbsArg(name,title), _plotMin(minVal), _plotMax(maxVal), _plotBins(100),
  _value(0), _unit(unit), _forceNumInt(kFALSE), _specIntegratorConfig(0)
{
  
  setValueDirty() ;
  setShapeDirty() ;
}
RooAbsReal::RooAbsReal(const RooAbsReal& other, const char* name) : 
  RooAbsArg(other,name), _plotMin(other._plotMin), _plotMax(other._plotMax), 
  _plotBins(other._plotBins), _value(other._value), _unit(other._unit), _forceNumInt(other._forceNumInt)
{
  
  if (other._specIntegratorConfig) {
    _specIntegratorConfig = new RooNumIntConfig(*other._specIntegratorConfig) ;
  } else {
    _specIntegratorConfig = 0 ;
  }
}
RooAbsReal::~RooAbsReal()
{
  if (_specIntegratorConfig) delete _specIntegratorConfig ;
  
}
Bool_t RooAbsReal::operator==(Double_t value) const
{
  
  return (getVal()==value) ;
}
Bool_t RooAbsReal::operator==(const RooAbsArg& other) 
{
  const RooAbsReal* otherReal = dynamic_cast<const RooAbsReal*>(&other) ;
  return otherReal ? operator==(otherReal->getVal()) : kFALSE ;
}
TString RooAbsReal::getTitle(Bool_t appendUnit) const {
  
  
  TString title(GetTitle());
  if(appendUnit && 0 != strlen(getUnit())) {
    title.Append(" (");
    title.Append(getUnit());
    title.Append(")");
  }
  return title;
}
Double_t RooAbsReal::getVal(const RooArgSet* set) const
{
  
  if (isValueDirty() || isShapeDirty()) {
    _value = traceEval(set) ;
    clearValueDirty() ; 
    clearShapeDirty() ; 
  } else if (_cacheCheck) {
    
    
    Double_t checkValue = traceEval(set);
    if (checkValue != _value) {
      
      cout << "RooAbsReal::getVal(" << GetName() << ") WARNING: cache contains " << _value 
	   << " but evaluate() returns " << checkValue << endl ;
      
      _value = checkValue ;
    }                                                                                                
    
  }
  
  return _value ;
}
Double_t RooAbsReal::traceEval(const RooArgSet* ) const
{
  
  Double_t value = evaluate() ;
  
  
  if (!isValidReal(value)) {
    cout << "RooAbsReal::traceEval(" << GetName() 
	 << "): validation failed: " << value << endl ;
  }
  
  traceEvalHook(value) ;
  return value ;
}
Int_t RooAbsReal::getAnalyticalIntegralWN(RooArgSet& allDeps, RooArgSet& analDeps, 
					  const RooArgSet* , const char* rangeName) const
{
  
  
  return _forceNumInt ? 0 : getAnalyticalIntegral(allDeps,analDeps,rangeName) ;
}
Int_t RooAbsReal::getAnalyticalIntegral(RooArgSet& , RooArgSet& , const char* ) const
{
  
  return 0 ;
}
Double_t RooAbsReal::analyticalIntegralWN(Int_t code, const RooArgSet* normSet, const char* rangeName) const
{
  
  
  
  if (code==0) return getVal(normSet) ;
  return analyticalIntegral(code,rangeName) ;
}
Double_t RooAbsReal::analyticalIntegral(Int_t code, const char* ) const
{
  
  cout << "RooAbsReal::analyticalIntegral(" << GetName() << ") code " << code << " not implemented" << endl ;
  assert(0) ;
  return 0 ;
}
const char *RooAbsReal::getPlotLabel() const {
  
  return _label.IsNull() ? fName.Data() : _label.Data();
}
void RooAbsReal::setPlotLabel(const char *label) {
  
  _label= label;
}
Bool_t RooAbsReal::readFromStream(istream& , Bool_t , Bool_t ) 
{
  
  return kFALSE ;
} 
void RooAbsReal::writeToStream(ostream& , Bool_t ) const
{
  
}
void RooAbsReal::printToStream(ostream& os, PrintOption opt, TString indent) const
{
  
  
  
  
  
  RooAbsArg::printToStream(os,opt,indent);
  if(opt >= Shape) {
    os << indent << "--- RooAbsReal ---" << endl;
    TString unit(_unit);
    if(!unit.IsNull()) unit.Prepend(' ');
    os << indent << "  Value = " << getVal() << unit << endl;
    if(opt >= Verbose) {
      os << endl << indent << "  Plot label is \"" << getPlotLabel() << "\"" << endl;
    }
  }
}
void RooAbsReal::setPlotMin(Double_t value) {
  
  
  if (_plotMin>_plotMax) {
    cout << "RooAbsReal::setPlotMin(" << GetName() 
	 << "): Proposed new integration min. larger than max., setting min. to max." << endl ;
    _plotMin = _plotMax ;
  } else {
    _plotMin = value ;
  }
}
void RooAbsReal::setPlotMax(Double_t value) {
  
  
  if (_plotMax<_plotMin) {
    cout << "RooAbsReal::setPlotMax(" << GetName() 
	 << "): Proposed new integration max. smaller than min., setting max. to min." << endl ;
    _plotMax = _plotMin ;
  } else {
    _plotMax = value ;
  }
}
void RooAbsReal::setPlotRange(Double_t, Double_t) {
  
  cout << "RooAbsReal::setPlotBins(" << GetName() 
       << ") WARNING: setPlotRange deprecated. Specify plot range in RooAbsRealLValue::frame() when different from fitRange" << endl ;
}
void RooAbsReal::setPlotBins(Int_t ) {
  
  cout << "RooAbsReal::setPlotBins(" << GetName() 
       << ") WARNING: setPlotBins deprecated. Specify plot bins in RooAbsRealLValue::frame() when different from fitBins" << endl ;
}
Bool_t RooAbsReal::inPlotRange(Double_t value) const {
  
  return (value >= _plotMin && value <= _plotMax) ? kTRUE : kFALSE;
}
Bool_t RooAbsReal::isValid() const {
  
  return isValidReal(_value) ;
}
Bool_t RooAbsReal::isValidReal(Double_t , Bool_t ) const 
{
  
  return kTRUE ;
}
RooAbsReal* RooAbsReal::createIntegral(const RooArgSet& iset, const RooCmdArg arg1, const RooCmdArg arg2,
				       const RooCmdArg arg3, const RooCmdArg arg4, const RooCmdArg arg5, 
				       const RooCmdArg arg6, const RooCmdArg arg7, const RooCmdArg arg8) const 
{
  
  
  
  
  
  
  
  
  
  
  
  
  RooCmdConfig pc(Form("RooAbsReal::createIntegral(%s)",GetName())) ;
  pc.defineString("rangeName","RangeWithName",0,"",kTRUE) ;
  pc.defineObject("normSet","NormSet",0,0) ;
  pc.defineObject("numIntConfig","NumIntConfig",0,0) ;
  
  pc.process(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) ;
  if (!pc.ok(kTRUE)) {
    return 0 ;
  }
  
  const char* rangeName = pc.getString("rangeName",0,kTRUE) ;
  const RooArgSet* nset = static_cast<const RooArgSet*>(pc.getObject("normSet",0)) ;
  const RooNumIntConfig* cfg = static_cast<const RooNumIntConfig*>(pc.getObject("numIntConfig",0)) ;
  return createIntegral(iset,nset,cfg,rangeName) ;
}
RooAbsReal* RooAbsReal::createIntegral(const RooArgSet& iset, const RooArgSet* nset, const RooNumIntConfig* cfg, const char* rangeName) const 
{
  TString title(GetTitle()) ;
  title.Prepend("Integral of ") ;
  if (!rangeName || strchr(rangeName,',')==0) {
    
    TString name(GetName()) ;
    name.Append(integralNameSuffix(iset,nset,rangeName)) ;
    return new RooRealIntegral(name,title,*this,iset,nset,cfg,rangeName) ;
  } 
  
  char* buf = new char[strlen(rangeName)+1] ;
  strcpy(buf,rangeName) ;
  char* range = strtok(buf,",") ;
  RooArgSet components ;
  while (range) {
    TString compName(GetName()) ;
    compName.Append(integralNameSuffix(iset,nset,range)) ;
    RooAbsReal* compIntegral = new RooRealIntegral(compName,title,*this,iset,nset,cfg,range) ;
    components.add(*compIntegral) ;
    range = strtok(0,",") ;
  }
  delete[] buf ;
  TString fullName(GetName()) ;
  fullName.Append(integralNameSuffix(iset,nset,rangeName)) ;
  return new RooAddition(fullName,title,components,kTRUE) ;
}
TString RooAbsReal::integralNameSuffix(const RooArgSet& iset, const RooArgSet* nset, const char* rangeName) const 
{
  TString name ;
  name.Append("_Int[") ;
  if (iset.getSize()>0) {
    TIterator* iter = iset.createIterator() ;
    RooAbsArg* arg ;
    Bool_t first(kTRUE) ;
    while((arg=(RooAbsArg*)iter->Next())) {
      if (first) {
	first=kFALSE ;
      } else {
	name.Append(",") ;
      }
      name.Append(arg->GetName()) ;
    }
    delete iter ;
  }
  if (rangeName) {
    name.Append("|") ;
    name.Append(rangeName) ;
  }
  
  name.Append("]_Norm[") ;
  if (nset && nset->getSize()>0) {
    Bool_t first(kTRUE); 
    TIterator* iter  = nset->createIterator() ;
    RooAbsArg* arg ;
    while((arg=(RooAbsArg*)iter->Next())) {
      if (first) {
	first=kFALSE ;
      } else {
	name.Append(",") ;
      }
      name.Append(arg->GetName()) ;
    }
    delete iter ;
  }
  name.Append("]") ;
  return name ;
}
const RooAbsReal* RooAbsReal::createProjection(const RooArgSet& depVars, const RooArgSet& projVars, 
                                               RooArgSet*& cloneSet) const 
{
  return createProjection(depVars,&projVars,cloneSet) ; 
}
const RooAbsReal* RooAbsReal::createProjection(const RooArgSet& depVars, const RooArgSet& projVars) const 
{
  RooArgSet* cloneSet = new RooArgSet() ;
  return createProjection(depVars,&projVars,cloneSet) ; 
}
const RooAbsReal *RooAbsReal::createProjection(const RooArgSet &dependentVars, const RooArgSet *projectedVars,
					       RooArgSet *&cloneSet, const char* rangeName) const {
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  RooArgSet leafNodes;
  RooArgSet treeNodes;
  leafNodeServerList(&leafNodes,this);
  treeNodeServerList(&treeNodes,this) ;
  
  
  
  TIterator *dependentIterator= dependentVars.createIterator();
  assert(0 != dependentIterator);
  const RooAbsArg *arg = 0;
  while((arg= (const RooAbsArg*)dependentIterator->Next())) {
    if(!arg->isFundamental() && !dynamic_cast<const RooAbsLValue*>(arg)) {
      cout << ClassName() << "::" << GetName() << ":createProjection: variable \"" << arg->GetName()
	   << "\" of wrong type: " << arg->ClassName() << endl;
      delete dependentIterator;
      return 0;
    }
    
    RooAbsArg *found= treeNodes.find(arg->GetName()); 
    if(!found) {
      cout << ClassName() << "::" << GetName() << ":createProjection: \"" << arg->GetName()
	   << "\" is not a dependent and will be ignored." << endl;
      continue;
    }
    if(found != arg) {
      if (leafNodes.find(found->GetName())) {
	
	leafNodes.replace(*found,*arg);
      } else {
	
	leafNodes.add(*arg) ;
	
	RooArgSet* lvDep = arg->getObservables(&leafNodes) ;
	RooAbsArg* lvs ;
	TIterator* iter = lvDep->createIterator() ;
	while((lvs=(RooAbsArg*)iter->Next())) {
	  RooAbsArg* tmp = leafNodes.find(lvs->GetName()) ;
	  if (tmp) {
	    
	    leafNodes.remove(*tmp) ;
	    leafNodes.add(*lvs) ;
	  }
	}
	delete iter ;
	
      }
    }
    
    if(0 != projectedVars && projectedVars->find(arg->GetName())) {
      cout << ClassName() << "::" << GetName() << ":createProjection: \"" << arg->GetName()
	   << "\" cannot be both a dependent and a projected variable." << endl;
      delete dependentIterator;
      return 0;
    }
  }
  
  if(0 != projectedVars) leafNodes.remove(*projectedVars,kTRUE);
  
  
  cloneSet= (RooArgSet*)RooArgSet(*this).snapshot(kTRUE);
  
  if (!cloneSet) {
    cout << "RooAbsPdf::createProjection(" << GetName() << ") Couldn't deep-clone PDF, abort," << endl ;
    return 0 ;
  }
  RooAbsReal *clone= (RooAbsReal*)cloneSet->find(GetName());
  
  
  
  
  
  
  clone->recursiveRedirectServers(leafNodes);
  
  
    
  RooArgSet normSet(dependentVars);
  if(0 != projectedVars) normSet.add(*projectedVars);
  
  
  
  RooArgSet empty;
  if(0 == projectedVars) projectedVars= ∅
  TString name(GetName()),title(GetTitle());
  name.Append("Projected");
  title.Prepend("Projection of ");
  RooRealIntegral *projected= new RooRealIntegral(name.Data(),title.Data(),*clone,*projectedVars,&normSet,0,rangeName);
  if(0 == projected || !projected->isValid()) {
    cout << ClassName() << "::" << GetName() << ":createProjection: cannot integrate out ";
    projectedVars->printToStream(cout,OneLine);
    
    if(0 != projected) delete projected;
    delete dependentIterator;
    return 0;
  }
  
  cloneSet->addOwned(*projected);
  
  delete dependentIterator;
  
  
  return projected;
}
TH1 *RooAbsReal::fillHistogram(TH1 *hist, const RooArgList &plotVars,
			       Double_t scaleFactor, const RooArgSet *projectedVars) const {
  
  
  
  
  
  
  
  if(0 == hist) {
    cout << ClassName() << "::" << GetName() << ":fillHistogram: no valid histogram to fill" << endl;
    return 0;
  }
  
  Int_t hdim= hist->GetDimension();
  if(hdim != plotVars.getSize()) {
    cout << ClassName() << "::" << GetName() << ":fillHistogram: plotVars has the wrong dimension" << endl;
    return 0;
  }
  
  
  RooArgSet plotClones;
  for(Int_t index= 0; index < plotVars.getSize(); index++) {
    const RooAbsArg *var= plotVars.at(index);
    const RooRealVar *realVar= dynamic_cast<const RooRealVar*>(var);
    if(0 == realVar) {
      cout << ClassName() << "::" << GetName() << ":fillHistogram: cannot plot variable \"" << var->GetName()
	   << "\" of type " << var->ClassName() << endl;
      return 0;
    }
    if(!this->dependsOn(*realVar)) {
      cout << ClassName() << "::" << GetName()
	   << ":fillHistogram: WARNING: variable is not an explicit dependent: " << realVar->GetName() << endl;
    }
    plotClones.addClone(*realVar,kTRUE); 
  }
  
  RooArgSet allDeps(plotClones) ;
  if (projectedVars) allDeps.add(*projectedVars) ;
  if (checkObservables(&allDeps)) {
    cout << "RooAbsReal::fillHistogram(" << GetName() << ") error in checkObservables, abort" << endl ;
    return hist ;
  }
  
  RooArgSet *cloneSet = 0;
  const RooAbsReal *projected= createProjection(plotClones,projectedVars,cloneSet);
  
  Int_t xbins(0),ybins(1),zbins(1);
  RooRealVar *xvar = 0;
  RooRealVar *yvar = 0;
  RooRealVar *zvar = 0;
  TAxis *xaxis = 0;
  TAxis *yaxis = 0;
  TAxis *zaxis = 0;
  switch(hdim) {
  case 3:
    zbins= hist->GetNbinsZ();
    zvar= dynamic_cast<RooRealVar*>(plotClones.find(plotVars.at(2)->GetName()));
    zaxis= hist->GetZaxis();
    assert(0 != zvar && 0 != zaxis);
    scaleFactor*= (zaxis->GetXmax() - zaxis->GetXmin())/zbins;
    
  case 2:
    ybins= hist->GetNbinsY(); 
    yvar= dynamic_cast<RooRealVar*>(plotClones.find(plotVars.at(1)->GetName()));
    yaxis= hist->GetYaxis();
    assert(0 != yvar && 0 != yaxis);
    scaleFactor*= (yaxis->GetXmax() - yaxis->GetXmin())/ybins;
    
  case 1:
    xbins= hist->GetNbinsX();
    xvar= dynamic_cast<RooRealVar*>(plotClones.find(plotVars.at(0)->GetName()));
    xaxis= hist->GetXaxis();
    assert(0 != xvar && 0 != xaxis);
    scaleFactor*= (xaxis->GetXmax() - xaxis->GetXmin())/xbins;
    break;
  default:
    cout << ClassName() << "::" << GetName() << ":fillHistogram: cannot fill histogram with "
	 << hdim << " dimensions" << endl;
    break;
  }
  
  
  Int_t xbin(0),ybin(0),zbin(0);
  Int_t bins= xbins*ybins*zbins;
  for(Int_t bin= 0; bin < bins; bin++) {
    switch(hdim) {
    case 3:
      if(bin % (xbins*ybins) == 0) {
	zbin++;
	zvar->setVal(zaxis->GetBinCenter(zbin));
      }
      
    case 2:
      if(bin % xbins == 0) {
	ybin= (ybin%ybins) + 1;
	yvar->setVal(yaxis->GetBinCenter(ybin));
      }
      
    case 1:
      xbin= (xbin%xbins) + 1;
      xvar->setVal(xaxis->GetBinCenter(xbin));
      break;
    default:
      cout << "RooAbsReal::fillHistogram: Internal Error!" << endl;
      break;
    }
    Double_t result= scaleFactor*projected->getVal();
    hist->SetBinContent(hist->GetBin(xbin,ybin,zbin),result);
    
  }
  
  delete cloneSet;
  return hist;
}
TH1 *RooAbsReal::createHistogram(const char *name, const RooAbsRealLValue& xvar,
				 const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3, const RooCmdArg& arg4, 
				 const RooCmdArg& arg5, const RooCmdArg& arg6, const RooCmdArg& arg7, const RooCmdArg& arg8) const 
{
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  RooLinkedList l ;
  l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
  l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
  l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
  l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
  
  RooCmdConfig pc(Form("RooAbsReal::createHistogram(%s)",GetName())) ;
  pc.defineObject("projObs","ProjectedObservables",0,0) ;
  pc.defineObject("yvar","YVar",0,0) ;
  pc.defineObject("zvar","ZVar",0,0) ;
  pc.allowUndefined() ;
  
  
  pc.process(l) ;
  if (!pc.ok(kTRUE)) {
    return 0 ;
  }
  RooArgList vars(xvar) ;
  RooAbsArg* yvar = static_cast<RooAbsArg*>(pc.getObject("yvar")) ;
  if (yvar) {
    vars.add(*yvar) ;
  }
  RooAbsArg* zvar = static_cast<RooAbsArg*>(pc.getObject("zvar")) ;
  if (zvar) {
    vars.add(*zvar) ;
  }
  RooArgSet* projObs = static_cast<RooArgSet*>(pc.getObject("projObs")) ;
  TH1* histo = xvar.createHistogram(name,l) ;
  fillHistogram(histo,vars,1.0,projObs) ;
  return histo ;
}
RooPlot* RooAbsReal::plotOn(RooPlot* frame, const RooCmdArg& arg1, const RooCmdArg& arg2,
			    const RooCmdArg& arg3, const RooCmdArg& arg4,
			    const RooCmdArg& arg5, const RooCmdArg& arg6,
			    const RooCmdArg& arg7, const RooCmdArg& arg8,
			    const RooCmdArg& arg9, const RooCmdArg& arg10) const
{
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  RooLinkedList l ;
  l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
  l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
  l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
  l.Add((TObject*)&arg7) ;  l.Add((TObject*)&arg8) ;
  l.Add((TObject*)&arg9) ;  l.Add((TObject*)&arg10) ;
  return plotOn(frame,l) ;
}
RooPlot* RooAbsReal::plotOn(RooPlot* frame, RooLinkedList& argList) const
{
  
  
  RooCmdConfig pc(Form("RooAbsReal::plotOn(%s)",GetName())) ;
  pc.defineString("drawOption","DrawOption",0,"L") ;
  pc.defineString("projectionRangeName","ProjectionRange",0,"",kTRUE) ;
  pc.defineDouble("scaleFactor","Normalization",0,1.0) ;
  pc.defineObject("sliceSet","SliceVars",0) ;
  pc.defineObject("projSet","Project",0) ;
  pc.defineObject("asymCat","Asymmetry",0) ;
  pc.defineDouble("precision","Precision",0,1e-3) ;
  pc.defineInt("shiftToZero","ShiftToZero",0,0) ;  
  pc.defineObject("projDataSet","ProjData",0) ;
  pc.defineObject("projData","ProjData",1) ;
  pc.defineDouble("rangeLo","Range",0,-999.) ;
  pc.defineDouble("rangeHi","Range",1,-999.) ;
  pc.defineInt("rangeAdjustNorm","Range",0,0) ;
  pc.defineInt("rangeWNAdjustNorm","RangeWithName",0,0) ;
  pc.defineInt("VLines","VLines",0,2) ; 
  pc.defineString("rangeName","RangeWithName",0,"") ;
  pc.defineInt("lineColor","LineColor",0,-999) ;
  pc.defineInt("lineStyle","LineStyle",0,-999) ;
  pc.defineInt("lineWidth","LineWidth",0,-999) ;
  pc.defineInt("fillColor","FillColor",0,-999) ;
  pc.defineInt("fillStyle","FillStyle",0,-999) ;
  pc.defineString("curveName","Name",0,"") ;
  pc.defineInt("curveInvisible","Invisible",0,0) ;
  pc.defineString("addToCurveName","AddTo",0,"") ;
  pc.defineDouble("addToWgtSelf","AddTo",0,1.) ;
  pc.defineDouble("addToWgtOther","AddTo",1,1.) ;
  pc.defineMutex("SliceVars","Project") ;
  pc.defineMutex("AddTo","Asymmetry") ;
  pc.defineMutex("Range","RangeWithName") ;
  
  pc.process(argList) ;
  if (!pc.ok(kTRUE)) {
    return frame ;
  }
  PlotOpt o ;
  
  o.drawOptions = pc.getString("drawOption") ;
  o.scaleFactor = pc.getDouble("scaleFactor") ;
  o.projData = (const RooAbsData*) pc.getObject("projData") ;
  o.projDataSet = (const RooArgSet*) pc.getObject("projDataSet") ;
  const RooArgSet* sliceSet = (const RooArgSet*) pc.getObject("sliceSet") ;
  const RooArgSet* projSet = (const RooArgSet*) pc.getObject("projSet") ;
  const RooAbsCategoryLValue* asymCat = (const RooAbsCategoryLValue*) pc.getObject("asymCat") ;
  o.precision = pc.getDouble("precision") ;
  o.shiftToZero = (pc.getInt("shiftToZero")!=0) ;
  Int_t vlines = pc.getInt("VLines");
  if (pc.hasProcessed("Range")) {
    o.rangeLo = pc.getDouble("rangeLo") ;
    o.rangeHi = pc.getDouble("rangeHi") ;
    o.postRangeFracScale = pc.getInt("rangeAdjustNorm") ;
    if (vlines==2) vlines=0 ; 
  } else if (pc.hasProcessed("RangeWithName")) {    
    o.rangeLo = frame->getPlotVar()->getMin(pc.getString("rangeName",0,kTRUE)) ;
    o.rangeHi = frame->getPlotVar()->getMax(pc.getString("rangeName",0,kTRUE)) ;
    o.postRangeFracScale = pc.getInt("rangeAdjustNorm") ;
    if (vlines==2) vlines=0 ; 
  } else {
    
    RooArgSet* plotDep = getObservables(*frame->getPlotVar()) ;
    RooRealVar* plotDepVar = (RooRealVar*) plotDep->find(frame->getPlotVar()->GetName()) ;
    if (plotDepVar->hasBinning("fit")) {
      o.rangeLo = plotDepVar->getMin("fit") ;
      o.rangeHi = plotDepVar->getMax("fit") ;
      o.postRangeFracScale = kTRUE ;
      if (vlines==2) vlines=0 ; 
    }
    delete plotDep ;
  }
  o.wmode = (vlines==2)?RooCurve::Extended:(vlines==1?RooCurve::Straight:RooCurve::NoWings) ;
  o.projectionRangeName = pc.getString("projectionRangeName",0,kTRUE) ;
  o.curveName = pc.getString("curveName",0,kTRUE) ;
  o.curveInvisible = pc.getInt("curveInvisible") ;
  o.addToCurveName = pc.getString("addToCurveName",0,kTRUE) ;
  o.addToWgtSelf = pc.getDouble("addToWgtSelf") ;
  o.addToWgtOther = pc.getDouble("addToWgtOther") ;  
  if (o.addToCurveName && !frame->findObject(o.addToCurveName,RooCurve::Class())) {
    cout << "RooAbsReal::plotOn(" << GetName() << ") cannot find existing curve " << o.addToCurveName << " to add to in RooPlot" << endl ;
    return frame ;
  }
  
  RooArgSet projectedVars ;
  if (sliceSet) {
    makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
    
    
    TIterator* iter = sliceSet->createIterator() ;
    RooAbsArg* sliceArg ;
    while((sliceArg=(RooAbsArg*)iter->Next())) {
      RooAbsArg* arg = projectedVars.find(sliceArg->GetName()) ;
      if (arg) {
	projectedVars.remove(*arg) ;
      } else {
	cout << "RooAbsReal::plotOn(" << GetName() << ") slice variable " 
	     << sliceArg->GetName() << " was not projected anyway" << endl ;
      }
    }
    delete iter ;
  } else if (projSet) {
    makeProjectionSet(frame->getPlotVar(),projSet,projectedVars,kFALSE) ;
  } else {
    makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
  }
  o.projSet = &projectedVars ;
  RooPlot* ret ;
  if (!asymCat) {
    
    ret = RooAbsReal::plotOn(frame,o) ;
  } else {        
    
    ret = RooAbsReal::plotAsymOn(frame,*asymCat,o) ;
  }
  
  Int_t lineColor = pc.getInt("lineColor") ;
  Int_t lineStyle = pc.getInt("lineStyle") ;
  Int_t lineWidth = pc.getInt("lineWidth") ;
  Int_t fillColor = pc.getInt("fillColor") ;
  Int_t fillStyle = pc.getInt("fillStyle") ;
  if (lineColor!=-999) ret->getAttLine()->SetLineColor(lineColor) ;
  if (lineStyle!=-999) ret->getAttLine()->SetLineStyle(lineStyle) ;
  if (lineWidth!=-999) ret->getAttLine()->SetLineWidth(lineWidth) ;
  if (fillColor!=-999) ret->getAttFill()->SetFillColor(fillColor) ;
  if (fillStyle!=-999) ret->getAttFill()->SetFillStyle(fillStyle) ;
  
  return ret ;
}
RooPlot* RooAbsReal::plotOn(RooPlot *frame, PlotOpt o) const
{
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  if (plotSanityChecks(frame)) return frame ;
  
  RooArgSet projDataVars ;
  if (o.projData) {
    if (o.projDataSet) {
      RooArgSet* tmp = (RooArgSet*) o.projData->get()->selectCommon(*o.projDataSet) ;
      projDataVars.add(*tmp) ;
      delete tmp ;
    } else {
      projDataVars.add(*o.projData->get()) ;
    }
  }
  
  RooArgSet projectedVars ;
  RooArgSet sliceSet ;
  if (o.projSet) {
    makeProjectionSet(frame->getPlotVar(),o.projSet,projectedVars,kFALSE) ;
    
    if (frame->getNormVars()) {
      RooArgSet *sliceSetTmp = getObservables(*frame->getNormVars()) ;
      sliceSetTmp->remove(projectedVars,kTRUE,kTRUE) ;
      sliceSetTmp->remove(*frame->getPlotVar(),kTRUE,kTRUE) ;
      if (o.projData) {
	RooArgSet* tmp = (RooArgSet*) projDataVars.selectCommon(*o.projSet) ;
	sliceSetTmp->remove(*tmp,kTRUE,kTRUE) ;
	delete tmp ;
      }
      if (sliceSetTmp->getSize()) {
	cout << "RooAbsReal::plotOn(" << GetName() << ") plot on " 
	     << frame->getPlotVar()->GetName() << " represents a slice in " ;
	sliceSetTmp->Print("1") ;
      }
      sliceSet.add(*sliceSetTmp) ;
      delete sliceSetTmp ;
    }
  } else {
    makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
  }
  RooArgSet* projDataNeededVars = 0 ;
  
  if (o.projData) {
    projDataNeededVars = (RooArgSet*) projectedVars.selectCommon(projDataVars) ;
    projectedVars.remove(projDataVars,kTRUE,kTRUE) ;
  }
  
  RooAbsReal* realVar = (RooRealVar*) frame->getPlotVar() ;
  RooArgSet* plotCloneSet = (RooArgSet*) RooArgSet(*realVar).snapshot(kTRUE) ;
  if (!plotCloneSet) {
    cout << "RooAbsReal::plotOn(" << GetName() << ") Couldn't deep-clone self, abort," << endl ;
    return frame ;
  }
  RooRealVar* plotVar = (RooRealVar*) plotCloneSet->find(realVar->GetName());
  
  if (projectedVars.getSize()) {
    cout << "RooAbsReal::plotOn(" << GetName() << ") plot on " << plotVar->GetName() 
	 << " integrates over variables " << projectedVars 
	 << (o.projectionRangeName?Form(" in range %s",o.projectionRangeName):"") << endl;
  }  
  if (projDataNeededVars && projDataNeededVars->getSize()>0) {
    cout << "RooAbsReal::plotOn(" << GetName() << ") plot on " << plotVar->GetName() 
	 << " averages using data variables " ; projDataNeededVars->Print("1") ;
  }
  
  RooArgSet* projectionCompList ;
  RooArgSet* deps = getObservables(frame->getNormVars()) ;
  deps->remove(projectedVars,kTRUE,kTRUE) ;
  if (projDataNeededVars) {
    deps->remove(*projDataNeededVars,kTRUE,kTRUE) ;
  }
  deps->remove(*plotVar,kTRUE,kTRUE) ;
  deps->add(*plotVar) ;
  
  if (checkObservables(deps)) {
    cout << "RooAbsReal::plotOn(" << GetName() << ") error in checkObservables, abort" << endl ;
    delete deps ;
    delete plotCloneSet ;
    if (projDataNeededVars) delete projDataNeededVars ;
    return frame ;
  }
  
  RooAbsReal *projection = (RooAbsReal*) createProjection(*deps, &projectedVars, projectionCompList, o.projectionRangeName) ;
  
  
  RooArgSet fullNormSet(*deps) ;
  fullNormSet.add(projectedVars) ;
  if (projDataNeededVars && projDataNeededVars->getSize()>0) {
    fullNormSet.add(*projDataNeededVars) ;
  }
  RooArgSet* compSet = projection->getComponents() ;
  TIterator* iter = compSet->createIterator() ;
  RooAbsArg* arg ;
  while((arg=(RooAbsArg*)iter->Next())) {
    RooAbsPdf* pdf = dynamic_cast<RooAbsPdf*>(arg) ;
    if (pdf) {
      pdf->selectNormalization(&fullNormSet) ;
    } 
  }
  delete iter ;
  delete compSet ;
  
  
  
  if (o.projData && projDataNeededVars && projDataNeededVars->getSize()>0) {
    
    RooArgSet branchList("branchList") ;
    ((RooAbsReal*)projection)->setOperMode(RooAbsArg::ADirty) ;
    projection->branchNodeServerList(&branchList) ;
    TIterator* bIter = branchList.createIterator() ;
    RooAbsArg* branch ;
    while((branch=(RooAbsArg*)bIter->Next())) {
      branch->setOperMode(RooAbsArg::ADirty) ;
    }
    delete bIter ;
    
    RooAbsData* projDataSel = (RooAbsData*)o.projData;
    if (projDataNeededVars->getSize()<o.projData->get()->getSize()) {
      
      
      RooArgSet* sliceDataSet = (RooArgSet*) sliceSet.selectCommon(*o.projData->get()) ;
      TString cutString ;
      if (sliceDataSet->getSize()>0) {
	TIterator* iter = sliceDataSet->createIterator() ;
	RooAbsArg* sliceVar ; 
	Bool_t first(kTRUE) ;
	while((sliceVar=(RooAbsArg*)iter->Next())) {
	  if (!first) {
	    cutString.Append("&&") ;
	  } else {
	    first=kFALSE ;	    
	  }
	  RooAbsRealLValue* real ;
	  RooAbsCategoryLValue* cat ;	  
	  if ((real = dynamic_cast<RooAbsRealLValue*>(sliceVar))) {
	    cutString.Append(Form("%s==%f",real->GetName(),real->getVal())) ;
	  } else if ((cat = dynamic_cast<RooAbsCategoryLValue*>(sliceVar))) {
	    cutString.Append(Form("%s==%d",cat->GetName(),cat->getIndex())) ;	    
	  }
	}
	delete iter ;
      }
      delete sliceDataSet ;
      if (!cutString.IsNull()) {
	projDataSel = ((RooAbsData*)o.projData)->reduce(*projDataNeededVars,cutString) ;
	cout << "RooAbsReal::plotOn(" << GetName() << ") reducing given projection dataset to entries with " << cutString << endl ;
      } else {
	projDataSel = ((RooAbsData*)o.projData)->reduce(*projDataNeededVars) ;
      }
      cout << "RooAbsReal::plotOn(" << GetName() 
	   << ") only the following components of the projection data will be used: " ; 
      projDataNeededVars->Print("1") ;
    }
    
    projection->getVal(projDataSel->get()) ;
    
    
    projection->attachDataSet(*projDataSel) ;
    
    RooDataProjBinding projBind(*projection,*projDataSel,*plotVar) ;
    RooScaledFunc scaleBind(projBind,o.scaleFactor);
    
    if (o.rangeLo==0 && o.rangeHi==0) {
      o.rangeLo = frame->GetXaxis()->GetXmin() ;
      o.rangeHi = frame->GetXaxis()->GetXmax() ;
    }
    RooCurve *curve = new RooCurve(projection->GetName(),projection->GetTitle(),scaleBind,
				   o.rangeLo,o.rangeHi,frame->GetNbinsX(),o.precision,o.precision,o.shiftToZero,o.wmode) ;
    cout << endl ;
    
    if (o.addToCurveName) {
      RooCurve* otherCurve = static_cast<RooCurve*>(frame->findObject(o.addToCurveName,RooCurve::Class())) ;
      RooCurve* sumCurve = new RooCurve(projection->GetName(),projection->GetTitle(),*curve,*otherCurve,o.addToWgtSelf,o.addToWgtOther) ;
      delete curve ;
      curve = sumCurve ;
    }
    if (o.curveName) {
      curve->SetName(o.curveName) ;
    }
    
    frame->addPlotable(curve, o.drawOptions);
    if (projDataSel!=o.projData) delete projDataSel ;
    delete projDataNeededVars ;
       
  } else {
    
    
    if (o.rangeLo==0 && o.rangeHi==0) {
      o.rangeLo = frame->GetXaxis()->GetXmin() ;
      o.rangeHi = frame->GetXaxis()->GetXmax() ;
    }
    
    
    if (o.postRangeFracScale) {
      plotVar->setRange("plotRange",o.rangeLo,o.rangeHi) ;
      RooAbsReal* intFrac = projection->createIntegral(*plotVar,*plotVar,"plotRange") ;
      o.scaleFactor /= intFrac->getVal() ;
      delete intFrac ;
    }
    
    RooCurve *curve = new RooCurve(*projection,*plotVar,o.rangeLo,o.rangeHi,frame->GetNbinsX(),
				   o.scaleFactor,0,o.precision,o.precision,o.shiftToZero,o.wmode);
    
    if (o.addToCurveName) {
      RooCurve* otherCurve = static_cast<RooCurve*>(frame->findObject(o.addToCurveName,RooCurve::Class())) ;
      RooCurve* sumCurve = new RooCurve(projection->GetName(),projection->GetTitle(),*curve,*otherCurve,o.addToWgtSelf,o.addToWgtOther) ;
      delete curve ;
      curve = sumCurve ;
    }
    if (o.curveName) {
      curve->SetName(o.curveName) ;
    }
    
    frame->addPlotable(curve, o.drawOptions, o.curveInvisible);
  }
  delete deps ;
  delete projectionCompList ;
  delete plotCloneSet ;
  return frame;
}
RooPlot* RooAbsReal::plotSliceOn(RooPlot *frame, const RooArgSet& sliceSet, Option_t* drawOptions, 
				 Double_t scaleFactor, ScaleType stype, const RooAbsData* projData) const
{
  
  
  
  
  RooArgSet projectedVars ;
  makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
  
  
  TIterator* iter = sliceSet.createIterator() ;
  RooAbsArg* sliceArg ;
  while((sliceArg=(RooAbsArg*)iter->Next())) {
    RooAbsArg* arg = projectedVars.find(sliceArg->GetName()) ;
    if (arg) {
      projectedVars.remove(*arg) ;
    } else {
      cout << "RooAbsReal::plotSliceOn(" << GetName() << ") slice variable " 
	   << sliceArg->GetName() << " was not projected anyway" << endl ;
    }
  }
  delete iter ;
  PlotOpt o ;
  o.drawOptions = drawOptions ;
  o.scaleFactor = scaleFactor ;
  o.stype = stype ;
  o.projData = projData ;
  o.projSet = &projectedVars ;
  return plotOn(frame,o) ;
}
RooPlot* RooAbsReal::plotAsymOn(RooPlot *frame, const RooAbsCategoryLValue& asymCat, PlotOpt o) const
{
  
  
  
  
  
  
  
  
  
  
  
  if (plotSanityChecks(frame)) return frame ;
  
  RooArgSet projDataVars ;
  if (o.projData) {
    if (o.projDataSet) {
      RooArgSet* tmp = (RooArgSet*) o.projData->get()->selectCommon(*o.projDataSet) ;
      projDataVars.add(*tmp) ;
      delete tmp ;
    } else {
      projDataVars.add(*o.projData->get()) ;
    }
  }
  
  if (!dependsOn(asymCat)) {
    cout << "RooAbsReal::plotAsymOn(" << GetName() 
	 << ") function doesn't depend on asymmetry category " << asymCat.GetName() << endl ;
    return frame ;
  }
  
  if (!asymCat.isSignType()) {
    cout << "RooAbsReal::plotAsymOn(" << GetName()
	 << ") asymmetry category must have 2 or 3 states with index values -1,0,1" << endl ;
    return frame ;
  }
  
  
  RooArgSet projectedVars ;
  RooArgSet sliceSet ;
  if (o.projSet) {
    makeProjectionSet(frame->getPlotVar(),o.projSet,projectedVars,kFALSE) ;
    
    if (frame->getNormVars()) {
      RooArgSet *sliceSetTmp = getObservables(*frame->getNormVars()) ;
      sliceSetTmp->remove(projectedVars,kTRUE,kTRUE) ;
      sliceSetTmp->remove(*frame->getPlotVar(),kTRUE,kTRUE) ;
      if (o.projData) {
	RooArgSet* tmp = (RooArgSet*) projDataVars.selectCommon(*o.projSet) ;
	sliceSetTmp->remove(*tmp,kTRUE,kTRUE) ;
	delete tmp ;
      }
      if (sliceSetTmp->getSize()) {
	cout << "RooAbsReal::plotAsymOn(" << GetName() << ") plot on " 
	     << frame->getPlotVar()->GetName() << " represents a slice in " ;
	sliceSetTmp->Print("1") ;
      }
      sliceSet.add(*sliceSetTmp) ;
      delete sliceSetTmp ;
    }
  } else {
    makeProjectionSet(frame->getPlotVar(),frame->getNormVars(),projectedVars,kTRUE) ;
  }
  
  RooArgSet* projDataNeededVars = 0 ;
  if (o.projData) {
    projDataNeededVars = (RooArgSet*) projectedVars.selectCommon(projDataVars) ;
    projectedVars.remove(projDataVars,kTRUE,kTRUE) ;
  }
  
  if (projectedVars.find(asymCat.GetName())) {
    projectedVars.remove(*projectedVars.find(asymCat.GetName())) ;
  }
  
  RooAbsReal* realVar = (RooRealVar*) frame->getPlotVar() ;
  RooRealVar* plotVar = (RooRealVar*) realVar->Clone() ;
  
  if (projectedVars.getSize()) {
    cout << "RooAbsReal::plotAsymOn(" << GetName() << ") plot on " << plotVar->GetName() 
	 << " projects variables " ; projectedVars.Print("1") ;
  }  
  if (projDataNeededVars && projDataNeededVars->getSize()>0) {
    cout << "RooAbsReal::plotOn(" << GetName() << ") plot on " << plotVar->GetName() 
	 << " averages using data variables " ; projDataNeededVars->Print("1") ;
  }
  
  RooAbsCategoryLValue* asymPos = (RooAbsCategoryLValue*) asymCat.Clone("asym_pos") ;
  RooAbsCategoryLValue* asymNeg = (RooAbsCategoryLValue*) asymCat.Clone("asym_neg") ;
  asymPos->setIndex(1) ;
  asymNeg->setIndex(-1) ;
  RooCustomizer custPos(*this,"pos") ;
  RooCustomizer custNeg(*this,"neg") ;
  custPos.replaceArg(asymCat,*asymPos) ;
  custNeg.replaceArg(asymCat,*asymNeg) ;
  RooAbsReal* funcPos = (RooAbsReal*) custPos.build() ;
  RooAbsReal* funcNeg = (RooAbsReal*) custNeg.build() ;
  
  RooArgSet *posProjCompList, *negProjCompList ;
  
  
  RooArgSet depPos(*plotVar,*asymPos) ;
  RooArgSet depNeg(*plotVar,*asymNeg) ;
  depPos.add(projDataVars) ;
  depNeg.add(projDataVars) ;
  const RooAbsReal *posProj = funcPos->createProjection(depPos, &projectedVars, posProjCompList) ;
  const RooAbsReal *negProj = funcNeg->createProjection(depNeg, &projectedVars, negProjCompList) ;
  if (!posProj || !negProj) {
    cout << "RooAbsReal::plotAsymOn(" << GetName() << ") Unable to create projections, abort" << endl ;
    return frame ; 
  }
  
  TString asymName(GetName()) ;
  asymName.Append("Asymmetry[") ;
  asymName.Append(asymCat.GetName()) ;
  asymName.Append("]") ;
  TString asymTitle(asymCat.GetName()) ;
  asymTitle.Append(" Asymmetry of ") ;
  asymTitle.Append(GetTitle()) ;
  RooFormulaVar* funcAsym = new RooFormulaVar(asymName,asymTitle,"(@0-@1)/(@0+@1)",RooArgSet(*posProj,*negProj)) ;
  if (o.projData) {
    
    
    RooAbsData* projDataSel = (RooAbsData*)o.projData;
    if (projDataNeededVars->getSize()<o.projData->get()->getSize()) {
      
      
      RooArgSet* sliceDataSet = (RooArgSet*) sliceSet.selectCommon(*o.projData->get()) ;
      TString cutString ;
      if (sliceDataSet->getSize()>0) {
	TIterator* iter = sliceDataSet->createIterator() ;
	RooAbsArg* sliceVar ; 
	Bool_t first(kTRUE) ;
 	while((sliceVar=(RooAbsArg*)iter->Next())) {
	  if (!first) {
	    cutString.Append("&&") ;
 	  } else {
	    first=kFALSE ;	    
 	  }
 	  RooAbsRealLValue* real ;
	  RooAbsCategoryLValue* cat ;	  
 	  if ((real = dynamic_cast<RooAbsRealLValue*>(sliceVar))) {
	    cutString.Append(Form("%s==%f",real->GetName(),real->getVal())) ;
	  } else if ((cat = dynamic_cast<RooAbsCategoryLValue*>(sliceVar))) {
	    cutString.Append(Form("%s==%d",cat->GetName(),cat->getIndex())) ;	    
	  }
 	}
	delete iter ;
      }
      delete sliceDataSet ;
      if (!cutString.IsNull()) {
	projDataSel = ((RooAbsData*)o.projData)->reduce(*projDataNeededVars,cutString) ;
 	cout << "RooAbsReal::plotAsymOn(" << GetName() 
	     << ") reducing given projection dataset to entries with " << cutString << endl ;
      } else {
	projDataSel = ((RooAbsData*)o.projData)->reduce(*projDataNeededVars) ;
      }
      cout << "RooAbsReal::plotAsymOn(" << GetName() 
	   << ") only the following components of the projection data will be used: " ; 
      projDataNeededVars->Print("1") ;
    }    
    RooDataProjBinding projBind(*funcAsym,*projDataSel,*plotVar) ;
    ((RooAbsReal*)posProj)->attachDataSet(*projDataSel) ;
    ((RooAbsReal*)negProj)->attachDataSet(*projDataSel) ;
    RooScaledFunc scaleBind(projBind,o.scaleFactor);
    
    if (o.rangeLo==0 && o.rangeHi==0) {
      o.rangeLo = frame->GetXaxis()->GetXmin() ;
      o.rangeHi = frame->GetXaxis()->GetXmax() ;
    }
    RooCurve *curve = new RooCurve(funcAsym->GetName(),funcAsym->GetTitle(),scaleBind,
				   o.rangeLo,o.rangeHi,frame->GetNbinsX(),o.precision,o.precision,kFALSE,o.wmode) ;
    dynamic_cast<TAttLine*>(curve)->SetLineColor(2) ;
    
    frame->addPlotable(curve, o.drawOptions);
    cout << endl ;
    if (projDataSel!=o.projData) delete projDataSel ;
       
  } else {
    
    if (o.rangeLo==0 && o.rangeHi==0) {
      o.rangeLo = frame->GetXaxis()->GetXmin() ;
      o.rangeHi = frame->GetXaxis()->GetXmax() ;
    }
    RooCurve* curve= new RooCurve(*funcAsym,*plotVar,o.rangeLo,o.rangeHi,frame->GetNbinsX(),
				  o.scaleFactor,0,o.precision,o.precision,kFALSE,o.wmode);
    dynamic_cast<TAttLine*>(curve)->SetLineColor(2) ;
    
    
    frame->addPlotable(curve, o.drawOptions);
  }
  
  delete posProjCompList ;
  delete negProjCompList ;
  delete asymPos ;
  delete asymNeg ;
  delete funcAsym ;
  return frame;
}
Bool_t RooAbsReal::plotSanityChecks(RooPlot* frame) const
{
  
  
  if(0 == frame) {
    cout << ClassName() << "::" << GetName() << ":plotOn: frame is null" << endl;
    return kTRUE;
  }
  
  RooAbsReal* var = frame->getPlotVar() ;
  if(!var) {
    cout << ClassName() << "::" << GetName()
	 << ":plotOn: frame does not specify a plot variable" << endl;
    return kTRUE;
  }
  
  if(!dynamic_cast<RooAbsRealLValue*>(var)) {
     cout << ClassName() << "::" << GetName() << ":plotOn: cannot plot variable \""
	  << var->GetName() << "\" of type " << var->ClassName() << endl;
    return kTRUE;
  }
  
  if(!this->dependsOn(*var)) {
    cout << ClassName() << "::" << GetName() << ":plotOn: WARNING: variable is not an explicit dependent: "
	 << var->GetName() << endl;
  }
  
  return kFALSE ;
}
void RooAbsReal::makeProjectionSet(const RooAbsArg* plotVar, const RooArgSet* allVars, 
				   RooArgSet& projectedVars, Bool_t silent) const
{
  
  
  
  
  projectedVars.removeAll() ;
  if (!allVars) return ;
  
  projectedVars.add(*allVars) ;
  
  RooAbsArg *found= projectedVars.find(plotVar->GetName());
  if(found) {
    projectedVars.remove(*found);
    
    RooArgSet* plotServers = plotVar->getObservables(&projectedVars) ;
    TIterator* psIter = plotServers->createIterator() ;
    RooAbsArg* ps ;
    while((ps=(RooAbsArg*)psIter->Next())) {
      RooAbsArg* tmp = projectedVars.find(ps->GetName()) ;
      if (tmp) projectedVars.remove(*tmp) ;
    }
    delete psIter ;
    delete plotServers ;
    if (!silent) {
      cout << "RooAbsReal::plotOn(" << GetName() 
	   << ") WARNING: cannot project out frame variable (" 
	   << found->GetName() << "), ignoring" << endl ; 
    }
  }
  
  TIterator* iter = allVars->createIterator() ;
  RooAbsArg* arg ;
  while((arg=(RooAbsArg*)iter->Next())) {
    if (!dependsOn(*arg)) {
      projectedVars.remove(*arg,kTRUE) ;
      if (!silent) {
	cout << "RooAbsReal::plotOn(" << GetName() 
	     << ") WARNING: function doesn't depend on projection variable " 
	     << arg->GetName() << ", ignoring" << endl ;
      }
    }
  }
  delete iter ;
}
RooAbsFunc *RooAbsReal::bindVars(const RooArgSet &vars, const RooArgSet* nset, Bool_t clipInvalid) const {
  
  
  
  
  RooAbsFunc *binding= new RooRealBinding(*this,vars,nset,clipInvalid);
  if(binding && !binding->isValid()) {
    cout << ClassName() << "::" << GetName() << ":bindVars: cannot bind to ";
    vars.Print();
    delete binding;
    binding= 0;
  }
  return binding;
}
void RooAbsReal::copyCache(const RooAbsArg* source) 
{
  
  
  
  RooAbsReal* other = dynamic_cast<RooAbsReal*>(const_cast<RooAbsArg*>(source)) ;
  assert(other!=0) ;
  if (source->getAttribute("FLOAT_TREE_BRANCH")) {
    _value = *reinterpret_cast<Float_t*>(&other->_value) ;
  } else if (source->getAttribute("INTEGER_TREE_BRANCH")) {
    _value = *reinterpret_cast<Int_t*>(&other->_value) ;
  } else if (source->getAttribute("BYTE_TREE_BRANCH")) {
    _value = *reinterpret_cast<UChar_t*>(&other->_value) ;
  } else if (source->getAttribute("UNSIGNED_INTEGER_TREE_BRANCH")) {
    _value = *reinterpret_cast<UInt_t*>(&other->_value) ;
  } else {
    _value = other->_value ;
  }
  setValueDirty() ;
}
void RooAbsReal::attachToTree(TTree& t, Int_t bufSize)
{
  
  
  TString cleanName(cleanBranchName()) ;
  TBranch* branch = t.GetBranch(cleanName) ;
  if (branch) { 
    
    
    TString typeName(((TLeaf*)branch->GetListOfLeaves()->At(0))->GetTypeName()) ;
    if (!typeName.CompareTo("Float_t")) {
      cout << "RooAbsReal::attachToTree(" << GetName() << ") TTree Float_t branch " << GetName() 
	   << " will be converted to double precision" << endl ;
      setAttribute("FLOAT_TREE_BRANCH",kTRUE) ;
    } else if (!typeName.CompareTo("Int_t")) {
      cout << "RooAbsReal::attachToTree(" << GetName() << ") TTree Int_t branch " << GetName() 
	   << " will be converted to double precision" << endl ;
      setAttribute("INTEGER_TREE_BRANCH",kTRUE) ;
    } else if (!typeName.CompareTo("UChar_t")) {
      cout << "RooAbsReal::attachToTree(" << GetName() << ") TTree UChar_t branch " << GetName() 
	   << " will be converted to double precision" << endl ;
      setAttribute("BYTE_TREE_BRANCH",kTRUE) ;
    }  else if (!typeName.CompareTo("UInt_t")) { 
      cout << "RooAbsReal::attachToTree(" << GetName() << ") TTree UInt_t branch " << GetName() 
	   << " will be converted to double precision" << endl ;
      setAttribute("UNSIGNED_INTEGER_TREE_BRANCH",kTRUE) ;
    }    
    
    t.SetBranchAddress(cleanName,&_value) ;
    if (branch->GetCompressionLevel()<0) {
      cout << "RooAbsReal::attachToTree(" << GetName() << ") Fixing compression level of branch " << cleanName << endl ;
      branch->SetCompressionLevel(1) ;
    }
  } else {
    TString format(cleanName);
    format.Append("/D");
    branch = t.Branch(cleanName, &_value, (const Text_t*)format, bufSize);
    branch->SetCompressionLevel(1) ;
  }
}
void RooAbsReal::fillTreeBranch(TTree& t) 
{
  
  
  TBranch* branch = t.GetBranch(cleanBranchName()) ;
  if (!branch) { 
    cout << "RooAbsReal::fillTreeBranch(" << GetName() << ") ERROR: not attached to tree: " << cleanBranchName() << endl ;
    assert(0) ;
  }
  branch->Fill() ;
  
}
void RooAbsReal::setTreeBranchStatus(TTree& t, Bool_t active) 
{
  
  TBranch* branch = t.GetBranch(cleanBranchName()) ;
  if (branch) { 
    t.SetBranchStatus(cleanBranchName(),active?1:0) ;
  }
}
RooAbsArg *RooAbsReal::createFundamental(const char* newname) const {
  
  
  RooRealVar *fund= new RooRealVar(newname?newname:GetName(),GetTitle(),_value,getUnit());
  fund->removeRange();
  fund->setPlotLabel(getPlotLabel());
  fund->setAttribute("fundamentalCopy");
  return fund;
}
Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
			      const RooArgProxy& a) const
{
  
  TList nameList ;
  nameList.Add(new TObjString(a.absArg()->GetName())) ;
  Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
  nameList.Delete() ;
  return result ;
}
Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
			      const RooArgProxy& a, const RooArgProxy& b) const
{
  
  TList nameList ;
  nameList.Add(new TObjString(a.absArg()->GetName())) ;
  nameList.Add(new TObjString(b.absArg()->GetName())) ;  
  Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
  nameList.Delete() ;
  return result ;
}
Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
			      const RooArgProxy& a, const RooArgProxy& b,
			      const RooArgProxy& c) const
{
  
  TList nameList ;
  nameList.Add(new TObjString(a.absArg()->GetName())) ;
  nameList.Add(new TObjString(b.absArg()->GetName())) ;
  nameList.Add(new TObjString(c.absArg()->GetName())) ;
  Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
  nameList.Delete() ;
  return result ;
}
Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
			      const RooArgProxy& a, const RooArgProxy& b,
			      const RooArgProxy& c, const RooArgProxy& d) const
{
  
  TList nameList ;
  nameList.Add(new TObjString(a.absArg()->GetName())) ;
  nameList.Add(new TObjString(b.absArg()->GetName())) ;
  nameList.Add(new TObjString(c.absArg()->GetName())) ;
  nameList.Add(new TObjString(d.absArg()->GetName())) ;
  Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
  nameList.Delete() ;
  return result ;
}
Bool_t RooAbsReal::matchArgs(const RooArgSet& allDeps, RooArgSet& analDeps, 
			    const RooArgSet& set) const 
{
  
  TList nameList ;
  TIterator* iter = set.createIterator() ;
  RooAbsArg* arg ;
  while ((arg=(RooAbsArg*)iter->Next())) {
    nameList.Add(new TObjString(arg->GetName())) ;    
  }
  delete iter ;
  Bool_t result = matchArgsByName(allDeps,analDeps,nameList) ;
  nameList.Delete() ;
  return result ;
}
Bool_t RooAbsReal::matchArgsByName(const RooArgSet &allArgs, RooArgSet &matchedArgs,
				  const TList &nameList) const {
  
  
  
  RooArgSet matched("matched");
  TIterator *iterator= nameList.MakeIterator();
  TObjString *name = 0;
  Bool_t isMatched(kTRUE);
  while((isMatched && (name= (TObjString*)iterator->Next()))) {
    RooAbsArg *found= allArgs.find(name->String().Data());
    if(found) {
      matched.add(*found);
    }
    else {
      isMatched= kFALSE;
    }
  }
  
  
  if (isMatched && (matched.getSize()!=nameList.GetSize())) {
    isMatched = kFALSE ;
  }
  delete iterator;
  if(isMatched) matchedArgs.add(matched);
  return isMatched;
}
RooNumIntConfig* RooAbsReal::defaultIntegratorConfig() 
{
  return &RooNumIntConfig::defaultConfig() ;
}
RooNumIntConfig* RooAbsReal::specialIntegratorConfig() const 
{
  return _specIntegratorConfig ;
}
const RooNumIntConfig* RooAbsReal::getIntegratorConfig() const 
{
  const RooNumIntConfig* config = specialIntegratorConfig() ;
  if (config) return config ;
  return defaultIntegratorConfig() ;
}
void RooAbsReal::setIntegratorConfig(const RooNumIntConfig& config) 
{
  if (_specIntegratorConfig) {
    delete _specIntegratorConfig ;
  }
  _specIntegratorConfig = new RooNumIntConfig(config) ;  
}
void RooAbsReal::setIntegratorConfig() 
{
  if (_specIntegratorConfig) {
    delete _specIntegratorConfig ;
  }
  _specIntegratorConfig = 0 ;
}
void RooAbsReal::optimizeDirty(RooAbsData& dataset, const RooArgSet* normSet, Bool_t ) 
{
  getVal(normSet) ;
  RooArgSet branchList("branchList") ;
  setOperMode(RooAbsArg::ADirty) ;
  branchNodeServerList(&branchList) ;
  TIterator* bIter = branchList.createIterator() ;
  RooAbsArg* branch ;
  while((branch=(RooAbsArg*)bIter->Next())) {
    if (branch->dependsOn(*dataset.get())) {
      RooArgSet* bdep = branch->getObservables(dataset.get()) ;
      if (bdep->getSize()>0) {
	branch->setOperMode(RooAbsArg::ADirty) ;
      } else {
	
      }
      delete bdep ;
    }
  }
  delete bIter ;
  
  dataset.setDirtyProp(kFALSE) ;
}
void RooAbsReal::doConstOpt(RooAbsData& dataset, const RooArgSet* normSet, Bool_t verbose) 
{
  
  
  RooArgSet cacheList ;
  findCacheableBranches(this,&dataset,cacheList,normSet,verbose) ;
  dataset.cacheArgs(cacheList,normSet) ;  
  
  RooArgSet pruneList("pruneList") ;
  findUnusedDataVariables(&dataset,pruneList,verbose) ;
  findRedundantCacheServers(&dataset,cacheList,pruneList,verbose) ;
  if (pruneList.getSize()!=0) {
    
    if (verbose) {
      cout << "RooAbsReal::optimizeConst: The following unused tree branches are deactivated: " ; 
      pruneList.Print("1") ;
    }
    dataset.setArgStatus(pruneList,kFALSE) ;
  }
  TIterator* cIter = cacheList.createIterator() ;
  RooAbsArg *cacheArg ;
  while((cacheArg=(RooAbsArg*)cIter->Next())){
    cacheArg->setOperMode(RooAbsArg::AClean) ;
  }
  delete cIter ;
}
void RooAbsReal::undoConstOpt(RooAbsData& dataset, const RooArgSet* normSet, Bool_t verbose) 
{
  
  dataset.resetCache() ;
  
  dataset.setArgStatus(*dataset.get(),kTRUE) ;
  
  
  optimizeDirty(dataset,normSet,verbose) ;
}
Bool_t RooAbsReal::findCacheableBranches(RooAbsArg* arg, RooAbsData* dset, 
					    RooArgSet& cacheList, const RooArgSet* normSet, Bool_t verbose) 
{
  
  
  
  
  RooAbsReal* realArg = dynamic_cast<RooAbsReal*>(arg) ;
  if (realArg) {
    realArg->getVal(normSet) ;
  }
  TIterator* sIter = arg->serverIterator() ;
  RooAbsArg* server ;
  while((server=(RooAbsArg*)sIter->Next())) {
    if (server->isDerived()) {
      
      Bool_t canOpt(kTRUE) ;
      RooArgSet* branchParamList = server->getParameters(dset) ;
      TIterator* pIter = branchParamList->createIterator() ;
      RooAbsArg* param ;
      while((param = (RooAbsArg*)pIter->Next())) {
	if (!param->isConstant()) canOpt=kFALSE ;
      }
      delete pIter ;
      delete branchParamList ;
      if (canOpt) {
	if (!cacheList.find(server->GetName())) {
	  if (verbose) {
	    cout << "RooAbsReal::optimize: component " 
		 << server->GetName() << " will be cached" << endl ;
	  }
	  
	  cacheList.add(*server) ;
	} 
      } else {
	
	findCacheableBranches(server,dset,cacheList,normSet,verbose) ;
      }
    }
  }
  delete sIter ;
  return kFALSE ;
}
void RooAbsReal::findUnusedDataVariables(RooAbsData* dset,RooArgSet& pruneList, Bool_t ) 
{
  RooArgSet* observables = getObservables(dset) ;
  TIterator* vIter = observables->createIterator() ;
  RooAbsArg* arg ;
  while ((arg=(RooAbsArg*) vIter->Next())) {    
    if (!dependsOn(*arg)) {
      pruneList.add(*arg) ;
    }
  }
  delete vIter ;
  delete observables ;
}
void RooAbsReal::findRedundantCacheServers(RooAbsData* dset,RooArgSet& cacheList, RooArgSet& pruneList, Bool_t ) 
{
  TIterator* vIter = dset->get()->createIterator() ;
  RooAbsArg *var ;
  while ((var=(RooAbsArg*) vIter->Next())) {
    if (allClientsCached(var,cacheList)) {
      pruneList.add(*var) ;
    }
  }
  delete vIter ;
}
Bool_t RooAbsReal::allClientsCached(RooAbsArg* var, RooArgSet& cacheList)
{
  Bool_t ret(kTRUE), anyClient(kFALSE) ;
  TIterator* cIter = var->valueClientIterator() ;    
  RooAbsArg* client ;
  while ((client=(RooAbsArg*) cIter->Next())) {
    anyClient = kTRUE ;
    if (!cacheList.find(client->GetName())) {
      
      ret &= allClientsCached(client,cacheList) ;
    }
  }
  delete cIter ;
  return anyClient?ret:kFALSE ;
}
void RooAbsReal::selectNormalization(const RooArgSet*, Bool_t) 
{
} 
void RooAbsReal::selectNormalizationRange(const char*, Bool_t) 
{
}
Int_t RooAbsReal::getMaxVal(const RooArgSet& ) const 
  
  
  
  
  
{
  return 0 ;
}
Double_t RooAbsReal::maxVal(Int_t ) 
{
  
  
  assert(1) ;
  return 0 ;
}
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.