#include "RooFit.h"
#include "Riostream.h"
#include "Riostream.h"
#include <iomanip>
#include <fstream>
#include <vector>
#include <string>
#include <stdlib.h>
#include <math.h>
#include "TRegexp.h"
#include "TTreeFormula.h"
#include "TIterator.h"
#include "TObjArray.h"
#include "TTreeFormula.h"
#include "TIterator.h"
#include "TPaveText.h"
#include "TLeaf.h"
#include "TMath.h"
#include "TH1.h"
#include "TH2.h"
#include "TH3.h"
#include "TFile.h"
#include "TChain.h"
#include "TROOT.h"
#include "RooTreeData.h"
#include "RooAbsArg.h"
#include "RooArgSet.h"
#include "RooArgList.h"
#include "RooRealVar.h"
#include "RooAbsReal.h"
#include "RooAbsCategory.h"
#include "Roo1DTable.h"
#include "RooFormula.h"
#include "RooCategory.h"
#include "RooPlot.h"
#include "RooStringVar.h"
#include "RooHist.h"
#include "RooFormulaVar.h"
#include "RooTrace.h"
#include "RooAbsBinning.h" 
#include "RooCmdConfig.h" 
#include "RooGlobalFunc.h"
ClassImp(RooTreeData)
;
Int_t RooTreeData::_defTreeBufSize = 4096 ;
Int_t RooTreeData::Scan(const char* varexp, const char* selection, Option_t* option, 
		    Int_t nentries, Int_t firstentry) 
{
   
   return _tree->Scan(varexp,selection,option,nentries,firstentry) ;
}
Int_t RooTreeData::ScanCache(const char* varexp, const char* selection, Option_t* option, 
		    Int_t nentries, Int_t firstentry) 
{
   
   return _cacheTree->Scan(varexp,selection,option,nentries,firstentry) ;
}
 
Stat_t RooTreeData::GetEntries() const
{
   
   return _tree->GetEntries() ;
}
 
void RooTreeData::Reset(Option_t* option)
{
   
   _tree->Reset(option) ;
}
 
void RooTreeData::treePrint()
{
   
   _tree->Print();
}
 
Int_t RooTreeData::Fill()
{
   
   return _tree->Fill() ;
}
 
Int_t RooTreeData::GetEntry(Int_t entry, Int_t getall)
{
   
   Int_t ret1 = _tree->GetEntry(entry,getall) ; 
   if (!ret1) return 0 ;
   _cacheTree->GetEntry(entry,getall) ; 
   return ret1 ;
}
RooTreeData::RooTreeData() 
{
  
  RooTrace::create(this) ; 
  _defCtor = kTRUE ;  
  _cacheTree = 0 ;
  _tree = 0 ;
}
RooTreeData::RooTreeData(const char *name, const char *title, const RooArgSet& vars) :
  RooAbsData(name,title,vars), _defCtor(kFALSE), _truth("Truth")
{
  
  RooTrace::create(this) ;
  
  _tree = 0 ;
  _cacheTree = 0 ;
  createTree(name,title) ;
  
  initialize();
}
RooTreeData::RooTreeData(const char *name, const char *title, RooTreeData *t, 
                       const RooArgSet& vars, const char *cuts) :
 RooAbsData(name,title,vars), _defCtor(kFALSE), _truth("Truth"), 
  _blindString(t->_blindString)
{
  
  
  RooTrace::create(this) ;
  _tree = 0 ;
  _cacheTree = 0 ;
  createTree(name,title) ;
  
  initialize();
  if (cuts && *cuts) {
    
    RooFormulaVar cutVar(cuts,cuts,t->_vars) ;
    loadValues(t,&cutVar);
  } else {
    loadValues(t,0);
  }
}
RooTreeData::RooTreeData(const char *name, const char *title, RooTreeData *t, 
                       const RooArgSet& vars, const RooFormulaVar& cutVar) :
  RooAbsData(name,title,vars), _defCtor(kFALSE), _truth("Truth"), 
  _blindString(t->_blindString)
{
  
  
  RooTrace::create(this) ;
  _tree = 0 ;
  _cacheTree = 0 ;
  createTree(name,title) ;
  
  initialize();
  
  RooArgSet* tmp = (RooArgSet*) RooArgSet(cutVar).snapshot() ;
  if (!tmp) {
    cout << "RooTreeData::RooTreeData(" << GetName() << ") Couldn't deep-clone cut variable, abort." << endl ;
    RooErrorHandler::softAbort() ;
  }
  RooFormulaVar* cloneVar = (RooFormulaVar*) tmp->find(cutVar.GetName()) ;
  cloneVar->attachDataSet(*this) ;
  loadValues(t,cloneVar);
  delete tmp ;
}
RooTreeData::RooTreeData(const char *name, const char *title, TTree *t, 
                       const RooArgSet& vars, const RooFormulaVar& cutVar) :
  RooAbsData(name,title,vars), _defCtor(kFALSE), _truth("Truth")
{
  
  
  RooTrace::create(this) ;
  _tree = 0 ;
  _cacheTree = 0 ;
  createTree(name,title) ;
  
  initialize();
  
  RooArgSet* tmp = (RooArgSet*) RooArgSet(cutVar).snapshot() ;
  if (!tmp) {
    cout << "RooTreeData::RooTreeData(" << GetName() << ") Couldn't deep-clone cut variable, abort." << endl ;
    RooErrorHandler::softAbort() ;
  }
  RooFormulaVar* cloneVar = (RooFormulaVar*) tmp->find(cutVar.GetName()) ;
  cloneVar->attachDataSet(*this) ;
  loadValues(t,cloneVar);
  delete tmp ;
}
RooTreeData::RooTreeData(const char *name, const char *title, RooTreeData *t, 
			 const RooArgSet& vars, const RooFormulaVar* cutVar, const char* cutRange,
			 Int_t nStart, Int_t nStop, Bool_t ) :
  RooAbsData(name,title,vars), _defCtor(kFALSE), _truth("Truth"), 
  _blindString(t->_blindString)
{
  
  RooTrace::create(this) ;
  _tree = 0 ;
  _cacheTree = 0 ;
  createTree(name,title) ;
  
  RooArgSet* cloneVarSet = 0;
  RooFormulaVar* cloneVar = 0;
  if (cutVar) {
    cloneVarSet = (RooArgSet*) RooArgSet(*cutVar).snapshot() ;
    if (!cloneVarSet) {
      cout << "RooTreeData::RooTreeData(" << GetName() << ") Couldn't deep-clone cut variable, abort." << endl ;
      RooErrorHandler::softAbort() ;
    }
   cloneVar = (RooFormulaVar*) cloneVarSet->find(cutVar->GetName()) ;
    cloneVar->attachDataSet(*t) ;
  }
  
  initialize();
  initCache(t->_cachedVars) ;
  
  loadValues(t,cloneVar,cutRange,nStart,nStop);
  
  if (cloneVarSet) delete cloneVarSet ;
}
RooTreeData::RooTreeData(const char *name, const char *title, TTree *t, 
                       const RooArgSet& vars, const char *cuts) :
  RooAbsData(name,title,vars), _defCtor(kFALSE), _truth("Truth")
{
  
  
  RooTrace::create(this) ;
  _tree = 0 ;
  _cacheTree = 0 ;
  createTree(name,title) ;
  
  initialize();
  if (cuts && *cuts) {
    
    RooFormulaVar cutVar(cuts,cuts,_vars) ;
    loadValues(t,&cutVar);
  } else {
    loadValues(t,0);    
  }
}
RooTreeData::RooTreeData(const char *name, const char *filename,
		       const char *treename,
                       const RooArgSet& vars, const char *cuts) :
  RooAbsData(name,name,vars), _defCtor(kFALSE), _truth("Truth")
{
  
  
  RooTrace::create(this) ;
  _tree = 0 ;
  _cacheTree = 0 ;
  createTree(name,name) ;
  
  initialize();
  
  if (cuts && *cuts) {
    RooFormulaVar cutVar(cuts,cuts,_vars) ;    
    loadValues(filename,treename,&cutVar);
  } else {
    loadValues(filename,treename,0);
  }
}
RooTreeData::RooTreeData(RooTreeData const & other, const char* newName) : 
  RooAbsData(other,newName), _defCtor(other._defCtor), _truth("Truth")
{
  
  RooTrace::create(this) ;
  _tree = 0 ;
  _cacheTree = 0 ;
  createTree(newName,other.GetTitle()) ;
  initialize() ;
  loadValues(&other,0) ;
}
void RooTreeData::createTree(const char* name, const char* title)
{
  
  
  TString pwd(gDirectory->GetPath()) ;
  TString memDir(gROOT->GetName()) ;
  memDir.Append(":/") ;
  gDirectory->cd(memDir) ;
  if (!_tree) {
    _tree = new TTree(name,title) ;
  }
  if (!_cacheTree) {
    _cacheTree = new TTree(name,title) ;
  }
  gDirectory->RecursiveRemove(_tree) ;
  gDirectory->RecursiveRemove(_cacheTree) ;
  gDirectory->cd(pwd) ;
  
}
RooTreeData::~RooTreeData()
{
  
  RooTrace::destroy(this) ;
  delete _tree ;
  delete _cacheTree ;
}
void RooTreeData::initialize() {
  
  
  
  createTree(GetName(),GetTitle()) ;
  
  _iterator->Reset() ;  
  RooAbsArg *var;
  while((0 != (var= (RooAbsArg*)_iterator->Next()))) {
    var->attachToTree(*_tree,_defTreeBufSize) ;
  }
}
void RooTreeData::initCache(const RooArgSet& cachedVars) 
{
  
  
  
  _cachedVars.removeAll() ;
  TIterator* iter = cachedVars.createIterator() ;
  RooAbsArg *var;
  while((0 != (var= (RooAbsArg*)iter->Next()))) {    
    var->attachToTree(*_cacheTree,_defTreeBufSize) ;
    _cachedVars.add(*var) ;
  }
  delete iter ;
}
void RooTreeData::loadValues(const char *filename, const char *treename,
			    RooFormulaVar* cutVar) {
  
  
  TFile *file= (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
  if(!file) file= new TFile(filename);
  if(!file) {
    cout << "RooTreeData::loadValues: unable to open " << filename << endl;
  }
  else {
    TTree* tree= (TTree*)gDirectory->Get(treename);
    loadValues(tree,cutVar);
  }
}
void RooTreeData::loadValues(const RooTreeData *t, RooFormulaVar* select, 
			     const char* rangeName, Int_t nStart, Int_t nStop)  
{
  
  
  
  
  if (select) {
    select->recursiveRedirectServers(*t->get()) ;
    RooArgSet branchList ;
    select->branchNodeServerList(&branchList) ;
    TIterator* iter = branchList.createIterator() ;
    RooAbsArg* arg ;
    while((arg=(RooAbsArg*)iter->Next())) {
      arg->setOperMode(RooAbsArg::ADirty) ;
    }
    delete iter ;
  }
  
  t->get(0) ;
  
  RooAbsArg* arg = 0;
  Int_t nevent = nStop < t->numEntries() ? nStop : t->numEntries() ;
  Bool_t allValid ;
  for(Int_t i=nStart; i < nevent ; ++i) {
    t->_tree->GetEntry(i,1) ;
    t->_cacheTree->GetEntry(i,1) ;
    
    if (select && select->getVal()==0) {
      continue ; 
    }
    
    _vars = t->_vars ;
    _iterator->Reset() ;
    
    allValid=kTRUE ;
    while((arg=(RooAbsArg*)_iterator->Next())) {
      if (!arg->isValid() || (rangeName && !arg->inRange(rangeName))) {
	allValid=kFALSE ;
	break ;
      }
    }
    if (!allValid) continue ;
    _cachedVars = t->_cachedVars ;
    Fill() ;
   }
  
  SetTitle(t->GetTitle());
}
void RooTreeData::loadValues(const TTree *t, RooFormulaVar* select, const char* , Int_t , Int_t ) 
{
  
  
  
  
  
  
  
  TTree* tClone ;
  if (dynamic_cast<const TChain*>(t)) {
    tClone = (TTree*) t->Clone() ; 
  } else {
    tClone = ((TTree*)t)->CloneTree() ;
  }
    
  
  RooArgSet *sourceArgSet = (RooArgSet*) _vars.snapshot(kFALSE) ;
  
  
  TIterator* sourceIter =  sourceArgSet->createIterator() ;
  RooAbsArg* sourceArg = 0;
  while ((sourceArg=(RooAbsArg*)sourceIter->Next())) {
    sourceArg->attachToTree(*tClone,_defTreeBufSize) ;
  }
  
  if (select) {
    select->recursiveRedirectServers(*sourceArgSet) ;
    RooArgSet branchList ;
    select->branchNodeServerList(&branchList) ;
    TIterator* iter = branchList.createIterator() ;
    RooAbsArg* arg ;
    while((arg=(RooAbsArg*)iter->Next())) {
      arg->setOperMode(RooAbsArg::ADirty) ;
    }
    delete iter ;
  }
  
  RooAbsArg* destArg = 0;
  Int_t numInvalid(0) ;
  Int_t nevent= (Int_t)tClone->GetEntries();
  for(Int_t i=0; i < nevent; ++i) {
    Int_t entryNumber=tClone->GetEntryNumber(i);
    if (entryNumber<0) break;
    tClone->GetEntry(entryNumber,1);
 
    
     _iterator->Reset() ;
     sourceIter->Reset() ;
     Bool_t allOK(kTRUE) ;
     while ((destArg = (RooAbsArg*)_iterator->Next())) {              
       sourceArg = (RooAbsArg*) sourceIter->Next() ;
       destArg->copyCache(sourceArg) ;
       if (!destArg->isValid()) {
	 numInvalid++ ;
	 allOK=kFALSE ;
	 break ;
       }       
     }   
     
     if (!allOK || (select && select->getVal()==0)) {
       continue ; 
     }
     Fill() ;
   }
  if (numInvalid>0) {
    cout << "RooTreeData::loadValues(" << GetName() << ") Ignored " << numInvalid << " out of range events" << endl ;
  }
  
  SetTitle(t->GetTitle());
  delete sourceIter ;
  delete sourceArgSet ;
  delete tClone ;
}
void RooTreeData::dump() {
  
  RooAbsArg* arg ;
  
  _iterator->Reset() ;
  while ((arg = (RooAbsArg*)_iterator->Next())) {       
    cout << arg->GetName() << "  " ;
  }  
  cout << endl ;
     
  
  Int_t nevent= (Int_t)_tree->GetEntries();
  for(Int_t i=0; i < nevent; ++i) {
    Int_t entryNumber=_tree->GetEntryNumber(i);
    if (entryNumber<0) break;
    get(entryNumber);
     
    _iterator->Reset() ;
    
    while ((arg = (RooAbsArg*)_iterator->Next())) {
     arg->writeToStream(cout,kTRUE) ; 
     cout << " " ;
     }  
    cout << endl ;
  }
}
void RooTreeData::resetCache() 
{
  
  
  _cachedVars.removeAll() ;
  
  delete _cacheTree ;
  _cacheTree = 0 ;
  createTree(GetName(),GetTitle()) ;
  return ;
}
void RooTreeData::setArgStatus(const RooArgSet& set, Bool_t active) 
{
  TIterator* iter = set.createIterator() ;
  RooAbsArg* arg ;
  while ((arg=(RooAbsArg*)iter->Next())) {
    RooAbsArg* depArg = _vars.find(arg->GetName()) ;
    if (!depArg) {
      cout << "RooTreeData::setArgStatus(" << GetName() 
	   << ") dataset doesn't contain variable " << arg->GetName() << endl ;
      continue ;
    }
    depArg->setTreeBranchStatus(*_tree,active) ;
  }
  delete iter ;
}
void RooTreeData::cacheArgs(RooArgSet& newVarSet, const RooArgSet* nset) 
{
  
  
  
  
  
  
  TIterator *iter = newVarSet.createIterator() ;
  RooAbsArg *arg ;
  Bool_t doTreeFill = (_cachedVars.getSize()==0) ;
    
  while ((arg=(RooAbsArg*)iter->Next())) {
    
    arg->attachToTree(*_cacheTree,_defTreeBufSize) ;
    arg->redirectServers(_vars) ;
    _cachedVars.add(*arg) ;
  }
  
  
  for (int i=0 ; i<GetEntries() ; i++) {
    get(i) ;
    
    
    iter->Reset() ;
    while ((arg=(RooAbsArg*)iter->Next())) {
      arg->setValueDirty() ;
      arg->syncCache(nset) ;
      if (!doTreeFill) {
	arg->fillTreeBranch(*_cacheTree) ;
      }
    }
    if (doTreeFill) {
      _cacheTree->Fill() ;
    }
  }
  delete iter ;
}
const RooArgSet* RooTreeData::get(Int_t index) const 
{
  
  
  
  checkInit() ;
  Int_t ret = ((RooTreeData*)this)->GetEntry(index, 1) ;
  if(!ret) return 0;
  if (_doDirtyProp) {
    
    _iterator->Reset() ;
    RooAbsArg* var = 0;
    while ((var=(RooAbsArg*)_iterator->Next())) {
      var->setValueDirty() ; 
    } 
    
    _cacheIter->Reset() ;
    while ((var=(RooAbsArg*)_cacheIter->Next())) {
      var->setValueDirty()  ; 
      var->clearValueDirty() ; 
    } 
  }
  return &_vars;
}
RooAbsArg* RooTreeData::addColumn(RooAbsArg& newVar)
{
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  checkInit() ;
  
  RooAbsArg* valHolder= newVar.createFundamental();
  
  if(!valHolder->isFundamental()) {
    cout << GetName() << "::addColumn: holder argument is not fundamental: \""
	 << valHolder->GetName() << "\"" << endl;
    return 0;
  }
  
  RooArgSet* newVarCloneList = (RooArgSet*) RooArgSet(newVar).snapshot() ;  
  if (!newVarCloneList) {
    cout << "RooTreeData::addColumn(" << GetName() << ") Couldn't deep-clone variable to add, abort." << endl ;
    return 0 ;
  }
  RooAbsArg* newVarClone = newVarCloneList->find(newVar.GetName()) ;
  newVarClone->recursiveRedirectServers(_vars,kFALSE) ;
  
  ((RooAbsArg*)valHolder)->attachToTree(*_tree,_defTreeBufSize) ;
  _vars.addOwned(*valHolder) ;
  
  for (int i=0 ; i<GetEntries() ; i++) {
    get(i) ;
    newVarClone->syncCache(&_vars) ;
    valHolder->copyCache(newVarClone) ;
    valHolder->fillTreeBranch(*_tree) ;
  }
  
  delete newVarCloneList;  
  return valHolder ;
}
RooArgSet* RooTreeData::addColumns(const RooArgList& varList)
{
  TIterator* vIter = varList.createIterator() ;
  RooAbsArg* var ;
  checkInit() ;
  TList cloneSetList ;
  RooArgSet cloneSet ;
  RooArgSet* holderSet = new RooArgSet ;
  while((var=(RooAbsArg*)vIter->Next())) {
    
    RooAbsArg* valHolder= var->createFundamental();
    holderSet->add(*valHolder) ;
    
    if(!valHolder->isFundamental()) {
      cout << GetName() << "::addColumn: holder argument is not fundamental: \""
	   << valHolder->GetName() << "\"" << endl;
      return 0;
    }
    
    
    RooArgSet* newVarCloneList = (RooArgSet*) RooArgSet(*var).snapshot() ;  
    if (!newVarCloneList) {
      cout << "RooTreeData::RooTreeData(" << GetName() << ") Couldn't deep-clone variable " << var->GetName() << ", abort." << endl ;
      return 0 ;
    }
    RooAbsArg* newVarClone = newVarCloneList->find(var->GetName()) ;   
    newVarClone->recursiveRedirectServers(_vars,kFALSE) ;
    newVarClone->recursiveRedirectServers(*holderSet,kFALSE) ;
    cloneSetList.Add(newVarCloneList) ;
    cloneSet.add(*newVarClone) ;
    
    ((RooAbsArg*)valHolder)->attachToTree(*_tree,_defTreeBufSize) ;
    _vars.addOwned(*valHolder) ;
  }
  delete vIter ;
  TIterator* cIter = cloneSet.createIterator() ;
  TIterator* hIter = holderSet->createIterator() ;
  RooAbsArg *clone, *holder ;
  
  for (int i=0 ; i<GetEntries() ; i++) {
    get(i) ;
    cIter->Reset() ;
    hIter->Reset() ;
    while((clone=(RooAbsArg*)cIter->Next())) {
      holder = (RooAbsArg*)hIter->Next() ;
      clone->syncCache(&_vars) ;
      holder->copyCache(clone) ;
      holder->fillTreeBranch(*_tree) ;
    }
  }
  
  delete cIter ;
  delete hIter ;
  cloneSetList.Delete() ;
  return holderSet ;
}
TList* RooTreeData::split(const RooAbsCategory& splitCat) const
{
  
  if (!splitCat.dependsOn(*get())) {
    cout << "RooTreeData::split(" << GetName() << ") ERROR category " << splitCat.GetName() 
	 << " doesn't depend on any variable in this dataset" << endl ;
    return 0 ;
  }
  
  RooAbsCategory* cloneCat =0;
  RooArgSet* cloneSet = 0;
  if (splitCat.isDerived()) {
    cloneSet = (RooArgSet*) RooArgSet(splitCat).snapshot(kTRUE) ;
    if (!cloneSet) {
      cout << "RooTreeData::split(" << GetName() << ") Couldn't deep-clone splitting category, abort." << endl ;
      return 0 ;
    }
    cloneCat = (RooAbsCategory*) cloneSet->find(splitCat.GetName()) ;
    cloneCat->attachDataSet(*this) ;
  } else {
    cloneCat = dynamic_cast<RooAbsCategory*>(get()->find(splitCat.GetName())) ;
    if (!cloneCat) {
      cout << "RooTreeData::split(" << GetName() << ") ERROR category " << splitCat.GetName() 
	   << " is fundamental and does not appear in this dataset" << endl ;
      return 0 ;      
    }
  }
  
  
  TList* dsetList = new TList ;
  
  RooArgSet subsetVars(*get()) ;
  if (splitCat.isDerived()) {
    RooArgSet* vars = splitCat.getVariables() ;
    subsetVars.remove(*vars,kTRUE,kTRUE) ;
    delete vars ;
  } else {
    subsetVars.remove(splitCat,kTRUE,kTRUE) ;
  }
  
  
  Int_t i ;
  for (i=0 ; i<numEntries() ; i++) {
    const RooArgSet* row =  get(i) ;
    RooAbsData* subset = (RooAbsData*) dsetList->FindObject(cloneCat->getLabel()) ;
    if (!subset) {
      subset = emptyClone(cloneCat->getLabel(),cloneCat->getLabel(),&subsetVars) ;
      dsetList->Add((RooAbsArg*)subset) ;
    }
    subset->add(*row,weight()) ;
  }
  delete cloneSet ;
  return dsetList ;
}
RooPlot* RooTreeData::plotOn(RooPlot* frame, const RooLinkedList& argList) const
{
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  RooCmdConfig pc(Form("RooTreeData::plotOn(%s)",GetName())) ;
  pc.defineString("drawOption","DrawOption",0,"P") ;
  pc.defineString("cutRange","CutRange",0,"",kTRUE) ;
  pc.defineString("cutString","CutSpec",0,"") ;
  pc.defineString("histName","Name",0,"") ;
  pc.defineObject("cutVar","CutVar",0) ;
  pc.defineObject("binning","Binning",0) ;
  pc.defineString("binningName","BinningName",0,"") ;
  pc.defineInt("nbins","BinningSpec",0,100) ;
  pc.defineDouble("xlo","BinningSpec",0,0) ;
  pc.defineDouble("xhi","BinningSpec",1,1) ;
  pc.defineObject("asymCat","Asymmetry",0) ;
  pc.defineInt("lineColor","LineColor",0,-999) ;
  pc.defineInt("lineStyle","LineStyle",0,-999) ;
  pc.defineInt("lineWidth","LineWidth",0,-999) ;
  pc.defineInt("markerColor","MarkerColor",0,-999) ;
  pc.defineInt("markerStyle","MarkerStyle",0,-999) ;
  pc.defineDouble("markerSize","MarkerSize",0,-999) ;
  pc.defineInt("errorType","DataError",0,(Int_t)RooAbsData::Poisson) ;
  pc.defineInt("histInvisible","Invisible",0,0) ;
  pc.defineInt("refreshFrameNorm","RefreshNorm",0,0) ;
  pc.defineString("addToHistName","AddTo",0,"") ;
  pc.defineDouble("addToWgtSelf","AddTo",0,1.) ;
  pc.defineDouble("addToWgtOther","AddTo",1,1.) ;
  pc.defineDouble("xErrorSize","XErrorSize",0,1.) ;
  pc.defineMutex("DataError","Asymmetry") ;
  pc.defineMutex("Binning","BinningName","BinningSpec") ;
  
  pc.process(argList) ;
  if (!pc.ok(kTRUE)) {
    return frame ;
  }
  PlotOpt o ;
  
  o.drawOptions = pc.getString("drawOption") ;
  o.cuts = pc.getString("cutString") ;
  if (pc.hasProcessed("Binning")) {
    o.bins = (RooAbsBinning*) pc.getObject("binning") ;
  } else if (pc.hasProcessed("BinningName")) {
    o.bins = &frame->getPlotVar()->getBinning(pc.getString("binningName")) ;
  } else if (pc.hasProcessed("BinningSpec")) {
    Double_t xlo = pc.getDouble("xlo") ;
    Double_t xhi = pc.getDouble("xhi") ;
    o.bins = new RooUniformBinning((xlo==xhi)?frame->getPlotVar()->getMin():xlo,
				   (xlo==xhi)?frame->getPlotVar()->getMax():xhi,pc.getInt("nbins")) ;
  }
  const RooAbsCategoryLValue* asymCat = (const RooAbsCategoryLValue*) pc.getObject("asymCat") ;
  o.etype = (RooAbsData::ErrorType) pc.getInt("errorType") ;
  o.histInvisible = pc.getInt("histInvisible") ;
  o.xErrorSize = pc.getDouble("xErrorSize") ;
  o.cutRange = pc.getString("cutRange",0,kTRUE) ;
  o.histName = pc.getString("histName",0,kTRUE) ;
  o.addToHistName = pc.getString("addToHistName",0,kTRUE) ;
  o.addToWgtSelf = pc.getDouble("addToWgtSelf") ;
  o.addToWgtOther = pc.getDouble("addToWgtOther") ;
  o.refreshFrameNorm = pc.getInt("refreshFrameNorm") ;
  
  if (o.addToHistName && !frame->findObject(o.addToHistName,RooHist::Class())) {
    cout << "RooTreeData::plotOn(" << GetName() << ") cannot find existing histogram " << o.addToHistName << " to add to in RooPlot" << endl ;
    return frame ;
  }
  RooPlot* ret ;
  if (!asymCat) {
    ret = plotOn(frame,o) ;
  } else {
    ret = plotAsymOn(frame,*asymCat,o) ;    
  }
  Int_t lineColor   = pc.getInt("lineColor") ;
  Int_t lineStyle   = pc.getInt("lineStyle") ;
  Int_t lineWidth   = pc.getInt("lineWidth") ;
  Int_t markerColor = pc.getInt("markerColor") ;
  Int_t markerStyle = pc.getInt("markerStyle") ;
  Size_t markerSize  = pc.getDouble("markerSize") ;
  if (lineColor!=-999) ret->getAttLine()->SetLineColor(lineColor) ;
  if (lineStyle!=-999) ret->getAttLine()->SetLineStyle(lineStyle) ;
  if (lineWidth!=-999) ret->getAttLine()->SetLineWidth(lineWidth) ;
  if (markerColor!=-999) ret->getAttMarker()->SetMarkerColor(markerColor) ;
  if (markerStyle!=-999) ret->getAttMarker()->SetMarkerStyle(markerStyle) ;
  if (markerSize!=-999) ret->getAttMarker()->SetMarkerSize(markerSize) ;
  if (pc.hasProcessed("BinningSpec")) {
    delete o.bins ;
  }
  return ret ;
}
RooPlot *RooTreeData::plotOn(RooPlot *frame, PlotOpt o) const 
{
  
  
  
  
  
  
  
  
  
  
  if(0 == frame) {
    cout << ClassName() << "::" << GetName() << ":plotOn: frame is null" << endl;
    return 0;
  }
  RooAbsRealLValue *var= (RooAbsRealLValue*) frame->getPlotVar();
  if(0 == var) {
    cout << ClassName() << "::" << GetName()
	 << ":plotOn: frame does not specify a plot variable" << endl;
    return 0;
  }
  
  TString histName(GetName());
  histName.Append("_plot");
  TH1F *hist ;
  if (o.bins) {
    hist= static_cast<TH1F*>(var->createHistogram(histName.Data(), RooFit::AxisLabel("Events"), RooFit::Binning(*o.bins))) ;
  } else {
    hist= var->createHistogram(histName.Data(), "Events", 
			       frame->GetXaxis()->GetXmin(), frame->GetXaxis()->GetXmax(), frame->GetNbinsX());
  }
  
  hist->Sumw2() ;
  if(0 == fillHistogram(hist,RooArgList(*var),o.cuts,o.cutRange)) {
    cout << ClassName() << "::" << GetName()
	 << ":plotOn: fillHistogram() failed" << endl;
    return 0;
  }
  
  
  Double_t nomBinWidth ;
  if (frame->getFitRangeNEvt()==0 && o.bins) {
    nomBinWidth = o.bins->averageBinWidth() ;
  } else {
    nomBinWidth = o.bins ? frame->getFitRangeBinW() : 0 ;
  }
  
  RooHist *graph= new RooHist(*hist,nomBinWidth,1,o.etype,o.xErrorSize);
  if(0 == graph) {
    cout << ClassName() << "::" << GetName()
	 << ":plotOn: unable to create a RooHist object" << endl;
    delete hist;
    return 0;
  }  
  
  
  RooAbsRealLValue* dataVar = (RooAbsRealLValue*) _vars.find(var->GetName()) ;
  Double_t nEnt(sumEntries()) ;
  if (dataVar->getMin()<var->getMin() || dataVar->getMax()>var->getMax()) {
    RooAbsData* tmp = ((RooTreeData*)this)->reduce(*var) ;
    nEnt = tmp->sumEntries() ;
    delete tmp ;
  }
  
  if ((o.cuts && strlen(o.cuts)) || o.cutRange) {
    cout << "RooTreeData::plotOn: plotting " << hist->GetSum() << " events out of " << nEnt << " total events" << endl ;
    graph->setRawEntries(nEnt) ;
  }
  
  if (o.addToHistName) {
    RooHist* otherGraph = static_cast<RooHist*>(frame->findObject(o.addToHistName,RooHist::Class())) ;
    if (!graph->hasIdenticalBinning(*otherGraph)) {
      cout << "RooTreeData::plotOn: ERROR Histogram to be added to, '" << o.addToHistName << "',has different binning" << endl ;
      delete graph ;
      return frame ;
    }
    RooHist* sumGraph = new RooHist(*graph,*otherGraph,o.addToWgtSelf,o.addToWgtOther,o.etype) ;
    delete graph ;
    graph = sumGraph ;
  }  
  
  if (o.histName) {
    graph->SetName(o.histName) ;
  }
  
  frame->updateNormVars(_vars);
  
  frame->addPlotable(graph,o.drawOptions,o.histInvisible,o.refreshFrameNorm);
  
  delete hist;
  return frame;  
}
RooPlot* RooTreeData::plotAsymOn(RooPlot* frame, const RooAbsCategoryLValue& asymCat, PlotOpt o) const 
{
  
  
  
  
  
  
  
  
  
  
  
  
  if(0 == frame) {
    cout << ClassName() << "::" << GetName() << ":plotAsymOn: frame is null" << endl;
    return 0;
  }
  RooAbsRealLValue *var= (RooAbsRealLValue*) frame->getPlotVar();
  if(0 == var) {
    cout << ClassName() << "::" << GetName()
	 << ":plotAsymOn: frame does not specify a plot variable" << endl;
    return 0;
  }
  
  TString hist1Name(GetName()),hist2Name(GetName());
  hist1Name.Append("_plot1");
  TH1F *hist1, *hist2 ;
  hist2Name.Append("_plot2");
  if (o.bins) {
    hist1= var->createHistogram(hist1Name.Data(), "Events", *o.bins) ;
    hist2= var->createHistogram(hist2Name.Data(), "Events", *o.bins) ;
  } else {
    hist1= var->createHistogram(hist1Name.Data(), "Events", 
				frame->GetXaxis()->GetXmin(), frame->GetXaxis()->GetXmax(),
				frame->GetNbinsX());
    hist2= var->createHistogram(hist2Name.Data(), "Events", 
				frame->GetXaxis()->GetXmin(), frame->GetXaxis()->GetXmax(),
				frame->GetNbinsX());
  }
  assert(0 != hist1 && 0 != hist2);
  TString cuts1,cuts2 ;
  if (o.cuts && strlen(o.cuts)) {
    cuts1 = Form("(%s)&&(%s>0)",o.cuts,asymCat.GetName());
    cuts2 = Form("(%s)&&(%s<0)",o.cuts,asymCat.GetName());
  } else {
    cuts1 = Form("(%s>0)",asymCat.GetName());
    cuts2 = Form("(%s<0)",asymCat.GetName());
  }
  if(0 == fillHistogram(hist1,RooArgList(*var),cuts1.Data()) ||
     0 == fillHistogram(hist2,RooArgList(*var),cuts2.Data())) {
    cout << ClassName() << "::" << GetName()
	 << ":plotAsymOn: createHistogram() failed" << endl;
    return 0;
  }
  
  RooHist *graph= new RooHist(*hist1,*hist2,0,1,o.xErrorSize);
  if(0 == graph) {
    cout << ClassName() << "::" << GetName()
	 << ":plotOn: unable to create a RooHist object" << endl;
    delete hist1;
    delete hist2;
    return 0;
  }
  
  frame->updateNormVars(_vars);
  
  if (o.histName) {
    graph->SetName(o.histName) ;
  }
  
  frame->addPlotable(graph,o.drawOptions);
  
  delete hist1;
  delete hist2;
  return frame;  
}
TH1 *RooTreeData::fillHistogram(TH1 *hist, const RooArgList &plotVars, const char *cuts, const char* cutRange) 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,localVars;
  for(Int_t index= 0; index < plotVars.getSize(); index++) {
    const RooAbsArg *var= plotVars.at(index);
    const RooAbsReal *realVar= dynamic_cast<const RooAbsReal*>(var);
    if(0 == realVar) {
      cout << ClassName() << "::" << GetName() << ":fillHistogram: cannot plot variable \"" << var->GetName()
	   << "\" of type " << var->ClassName() << endl;
      return 0;
    }
    RooAbsArg *found= _vars.find(realVar->GetName());
    if(!found) {
      RooAbsArg *clone= plotClones.addClone(*realVar,kTRUE); 
      assert(0 != clone);
      if(!clone->dependsOn(_vars)) {
	cout << ClassName() << "::" << GetName()
	     << ":fillHistogram: WARNING: data does not contain variable: " << realVar->GetName() << endl;
      }
      else {
	clone->recursiveRedirectServers(_vars);
      }
      localVars.add(*clone);
    }
    else {
      localVars.add(*found);
    }
  }
  
  RooFormula* select = 0;
  if(0 != cuts && strlen(cuts)) {
    select=new RooFormula(cuts,cuts,_vars);
    if (!select || !select->ok()) {
      cout << ClassName() << "::" << GetName() << ":fillHistogram: invalid cuts \"" << cuts << "\"" << endl;
      delete select;
      return 0 ;
    }
  }
  
  
  const RooAbsReal *xvar = 0;
  const RooAbsReal *yvar = 0;
  const RooAbsReal *zvar = 0;
  switch(hdim) {
  case 3:
    zvar= dynamic_cast<RooAbsReal*>(localVars.find(plotVars.at(2)->GetName()));
    assert(0 != zvar);
    
  case 2:
    yvar= dynamic_cast<RooAbsReal*>(localVars.find(plotVars.at(1)->GetName()));
    assert(0 != yvar);
    
  case 1:
    xvar= dynamic_cast<RooAbsReal*>(localVars.find(plotVars.at(0)->GetName()));
    assert(0 != xvar);
    break;
  default:
    cout << ClassName() << "::" << GetName() << ":fillHistogram: cannot fill histogram with "
	 << hdim << " dimensions" << endl;
    break;
  }
  
  vector<string> cutVec ;
  if (cutRange && strlen(cutRange)>0) {
    if (strchr(cutRange,',')==0) {
      cutVec.push_back(cutRange) ;
    } else {
      char* buf = new char[strlen(cutRange)+1] ;
      strcpy(buf,cutRange) ;
      const char* oneRange = strtok(buf,",") ;
      while(oneRange) {
	cutVec.push_back(oneRange) ;
	oneRange = strtok(0,",") ;
      }
      delete[] buf ;
    }
  }
  
  Int_t nevent= (Int_t)_tree->GetEntries();
  for(Int_t i=0; i < nevent; ++i) {
    Int_t entryNumber= _tree->GetEntryNumber(i);
    if (entryNumber<0) break;
    get(entryNumber);
    
    if (select && select->eval()==0) {
      continue ;
    }
    
    Bool_t selectByRange = kTRUE ;
    if (cutRange) {
      _iterator->Reset() ;
      RooAbsArg* arg ;
      while((arg=(RooAbsArg*)_iterator->Next())) {
	Bool_t selectThisArg = kFALSE ;
	UInt_t icut ;
	for (icut=0 ; icut<cutVec.size() ; icut++) {
	  if (arg->inRange(cutVec[icut].c_str())) {
	    selectThisArg = kTRUE ;
	    break ;
	  }
	}
	if (!selectThisArg) {
	  selectByRange = kFALSE ;
	  break ;
	}
      }
    }
    if (!selectByRange) {
      
      continue ;
    }
    Int_t bin(0);
    switch(hdim) {
    case 1:
      bin= hist->FindBin(xvar->getVal());
      hist->Fill(xvar->getVal(),weight()) ;
      break;
    case 2:
      bin= hist->FindBin(xvar->getVal(),yvar->getVal());
      static_cast<TH2*>(hist)->Fill(xvar->getVal(),yvar->getVal(),weight()) ;
      break;
    case 3:
      bin= hist->FindBin(xvar->getVal(),yvar->getVal(),zvar->getVal());
      static_cast<TH3*>(hist)->Fill(xvar->getVal(),yvar->getVal(),zvar->getVal(),weight()) ;
      break;
    default:
      assert(hdim < 3);
      break;
    }
    
    Double_t error2 = TMath::Power(hist->GetBinError(bin),2)-TMath::Power(weight(),2)  ;
    Double_t we = weightError(RooAbsData::SumW2) ;
    if (we==0) we = weight() ;
    error2 += TMath::Power(we,2) ;
    
    hist->SetBinError(bin,sqrt(error2)) ;
  }
  if(0 != select) delete select;
  return hist;
}
Roo1DTable* RooTreeData::table(const RooAbsCategory& cat, const char* cuts, const char* ) const
{
  
  
  
  
  
  
  
  
  RooAbsCategory* tableVar = (RooAbsCategory*) _vars.find(cat.GetName()) ;
  RooArgSet *tableSet = 0;
  Bool_t ownPlotVar(kFALSE) ;
  if (!tableVar) {
    if (!cat.dependsOn(_vars)) {
      cout << "RooTreeData::Table(" << GetName() << "): Argument " << cat.GetName() 
	   << " is not in dataset and is also not dependent on data set" << endl ;
      return 0 ; 
    }
    
    tableSet = (RooArgSet*) RooArgSet(cat).snapshot(kTRUE) ;
    if (!tableSet) {
      cout << "RooTreeData::table(" << GetName() << ") Couldn't deep-clone table category, abort." << endl ;
      return 0 ;
    }
    tableVar = (RooAbsCategory*) tableSet->find(cat.GetName()) ;
    ownPlotVar = kTRUE ;    
    
    tableVar->recursiveRedirectServers(_vars) ;
  }
  TString tableName(GetName()) ;
  if (cuts && strlen(cuts)) {
    tableName.Append("(") ;
    tableName.Append(cuts) ;
    tableName.Append(")") ;    
  }
  Roo1DTable* table = tableVar->createTable(tableName) ;
  
  RooFormulaVar* cutVar = 0;
  if (cuts && strlen(cuts)) {
    cutVar = new RooFormulaVar("cutVar",cuts,_vars) ;
  }
  
  
  Int_t nevent= (Int_t)_tree->GetEntries();
  for(Int_t i=0; i < nevent; ++i) {
    Int_t entryNumber=_tree->GetEntryNumber(i);
    if (entryNumber<0) break;
    get(entryNumber);
    if (cutVar && cutVar->getVal()==0) continue ;
    
    table->fill(*tableVar,weight()) ;
  }
  if (ownPlotVar) delete tableSet ;
  if (cutVar) delete cutVar ;
  return table ;
}
Double_t RooTreeData::moment(RooRealVar &var, Double_t order, Double_t offset, const char* cutSpec, const char* cutRange) const
{
  
  RooRealVar *varPtr= (RooRealVar*) _vars.find(var.GetName());
  if(0 == varPtr) {
    cout << "RooDataSet::moment(" << GetName() << ") ERROR: unknown variable: " << var.GetName() << endl ;
    return 0;
  }
  
  if (!dynamic_cast<RooRealVar*>(varPtr)) {
    cout << "RooDataSet::moment(" << GetName() << ") ERROR: variable " << var.GetName() << " is not of type RooRealVar" << endl ;
    return 0;
  }
  
  if(sumEntries() == 0.) {
    cout << "RooDataSet::moment(" << GetName() << ") WARNING: empty dataset" << endl ;
    return 0;
  }
  
  RooFormula* select = 0 ;
  if (cutSpec) {
    select = new RooFormula("select",cutSpec,*get()) ;
  }
  
  Double_t sum(0);
  const RooArgSet* vars ;
  for(Int_t index= 0; index < numEntries(); index++) {
    vars = get(index) ;
    if (select && select->eval()==0) continue ;
    if (cutRange && vars->allInRange(cutRange)) continue ;
    
    sum+= weight() * TMath::Power(varPtr->getVal() - offset,order);
  }
  return sum/sumEntries();
}
RooRealVar* RooTreeData::meanVar(RooRealVar &var, const char* cutSpec, const char* cutRange) const
{
  
  
  
  TString name(var.GetName()),title("Mean of ") ;
  name.Append("Mean");
  title.Append(var.GetTitle());
  RooRealVar *mean= new RooRealVar(name,title,0) ;
  mean->setConstant(kFALSE) ;
  
  TString label("<") ;
  label.Append(var.getPlotLabel());
  label.Append(">");
  mean->setPlotLabel(label.Data());
  
  Double_t meanVal=moment(var,1,0,cutSpec,cutRange) ;
  Double_t N(sumEntries(cutSpec,cutRange)) ;
  Double_t rmsVal= sqrt(moment(var,2,meanVal,cutSpec,cutRange)*N/(N-1));
  mean->setVal(meanVal) ;
  mean->setError(N > 0 ? rmsVal/sqrt(N) : 0);
  return mean;
}
RooRealVar* RooTreeData::rmsVar(RooRealVar &var, const char* cutSpec, const char* cutRange) const
{
  
  
  
  TString name(var.GetName()),title("RMS of ") ;
  name.Append("RMS");
  title.Append(var.GetTitle());
  RooRealVar *rms= new RooRealVar(name,title,0) ;
  rms->setConstant(kFALSE) ;
  
  TString label(var.getPlotLabel());
  label.Append("_{RMS}");
  rms->setPlotLabel(label);
  
  Double_t meanVal(moment(var,1)) ;
  Double_t N(sumEntries());
  Double_t rmsVal= sqrt(moment(var,2,meanVal,cutSpec,cutRange)*N/(N-1));
  rms->setVal(rmsVal) ;
  rms->setError(rmsVal/sqrt(2*N));
  return rms;
}
Bool_t RooTreeData::getRange(RooRealVar& var, Double_t& lowest, Double_t& highest) const 
{
  
  RooRealVar *varPtr= (RooRealVar*) _vars.find(var.GetName());
  if(0 == varPtr) {
    cout << "RooDataSet::getRange(" << GetName() << ") ERROR: unknown variable: " << var.GetName() << endl ;
    return kTRUE;
  }
  
  if (!dynamic_cast<RooRealVar*>(varPtr)) {
    cout << "RooDataSet::getRange(" << GetName() << ") ERROR: variable " << var.GetName() << " is not of type RooRealVar" << endl ;
    return kTRUE;
  }
  
  if(sumEntries() == 0.) {
    cout << "RooDataSet::getRange(" << GetName() << ") WARNING: empty dataset" << endl ;
    return kTRUE;
  }
  
  lowest = RooNumber::infinity ;
  highest = -RooNumber::infinity ;
  for (Int_t i=0 ; i<numEntries() ; i++) {
    get(i) ;
    if (varPtr->getVal()<lowest) {
      lowest = varPtr->getVal() ;
    }
    if (varPtr->getVal()>highest) {
      highest = varPtr->getVal() ;
    }
  }  
  return kFALSE ;
}
RooPlot* RooTreeData::statOn(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)
{
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  RooLinkedList cmdList;
  cmdList.Add(const_cast<RooCmdArg*>(&arg1)) ;  cmdList.Add(const_cast<RooCmdArg*>(&arg2)) ;
  cmdList.Add(const_cast<RooCmdArg*>(&arg3)) ;  cmdList.Add(const_cast<RooCmdArg*>(&arg4)) ;
  cmdList.Add(const_cast<RooCmdArg*>(&arg5)) ;  cmdList.Add(const_cast<RooCmdArg*>(&arg6)) ;
  cmdList.Add(const_cast<RooCmdArg*>(&arg7)) ;  cmdList.Add(const_cast<RooCmdArg*>(&arg8)) ;
  
  RooCmdConfig pc(Form("RooTreeData::statOn(%s)",GetName())) ;
  pc.defineString("what","What",0,"MNR") ;
  pc.defineString("label","Label",0,"") ;
  pc.defineDouble("xmin","Layout",0,0.65) ;
  pc.defineDouble("xmax","Layout",1,0.99) ;
  pc.defineInt("ymaxi","Layout",0,Int_t(0.95*10000)) ;
  pc.defineString("formatStr","Format",0,"NELU") ;
  pc.defineInt("sigDigit","Format",0,2) ;
  pc.defineInt("dummy","FormatArgs",0,0) ;
  pc.defineString("cutRange","CutRange",0,"",kTRUE) ;
  pc.defineString("cutString","CutSpec",0,"") ;
  pc.defineMutex("Format","FormatArgs") ;
  
  pc.process(cmdList) ;
  if (!pc.ok(kTRUE)) {
    return frame ;
  }
  const char* label = pc.getString("label") ;
  Double_t xmin = pc.getDouble("xmin") ;
  Double_t xmax = pc.getDouble("xmax") ;
  Double_t ymax = pc.getInt("ymaxi") / 10000. ;
  const char* formatStr = pc.getString("formatStr") ;
  Int_t sigDigit = pc.getInt("sigDigit") ;  
  const char* what = pc.getString("what") ;
  const char* cutSpec = pc.getString("cutString",0,kTRUE) ;
  const char* cutRange = pc.getString("cutRange",0,kTRUE) ;
  if (pc.hasProcessed("FormatArgs")) {
    RooCmdArg* formatCmd = static_cast<RooCmdArg*>(cmdList.FindObject("FormatArgs")) ;
    return statOn(frame,what,label,0,0,xmin,xmax,ymax,cutSpec,cutRange,formatCmd) ;
  } else {
    return statOn(frame,what,label,sigDigit,formatStr,xmin,xmax,ymax,cutSpec,cutRange) ;
  }
}
RooPlot* RooTreeData::statOn(RooPlot* frame, const char* what, const char *label, Int_t sigDigits,
			     Option_t *options, Double_t xmin, Double_t xmax, Double_t ymax, 
			     const char* cutSpec, const char* cutRange, const RooCmdArg* formatCmd) 
{
  Bool_t showLabel= (label != 0 && strlen(label) > 0);
  TString whatStr(what) ;
  whatStr.ToUpper() ;
  Bool_t showN = whatStr.Contains("N") ;
  Bool_t showR = whatStr.Contains("R") ;
  Bool_t showM = whatStr.Contains("M") ;
  Int_t nPar= 0;
  if (showN) nPar++ ;
  if (showR) nPar++ ;
  if (showM) nPar++ ;
  
  Double_t dy(0.06), ymin(ymax-nPar*dy);
  if(showLabel) ymin-= dy;
  
  TPaveText *box= new TPaveText(xmin,ymax,xmax,ymin,"BRNDC");
  if(!box) return 0;
  box->SetFillColor(0);
  box->SetBorderSize(1);
  box->SetTextAlign(12);
  box->SetTextSize(0.04F);
  box->SetFillStyle(1001);
  
  TText *text = 0;
  RooRealVar N("N","Number of Events",sumEntries(cutSpec,cutRange));
  N.setPlotLabel("Entries") ;
  RooRealVar *mean= meanVar(*(RooRealVar*)frame->getPlotVar(),cutSpec,cutRange);
  mean->setPlotLabel("Mean") ;
  RooRealVar *rms= rmsVar(*(RooRealVar*)frame->getPlotVar(),cutSpec,cutRange);
  rms->setPlotLabel("RMS") ;
  TString *rmsText, *meanText, *NText ;
  if (options) {
    rmsText= rms->format(sigDigits,options);
    meanText= mean->format(sigDigits,options);
    NText= N.format(sigDigits,options);
  } else {
    rmsText= rms->format(*formatCmd);
    meanText= mean->format(*formatCmd);
    NText= N.format(*formatCmd);
  }
  if (showR) text= box->AddText(rmsText->Data());
  if (showM) text= box->AddText(meanText->Data());
  if (showN) text= box->AddText(NText->Data());
  
  delete NText;
  delete meanText;
  delete rmsText;
  delete mean;
  delete rms;
  
  if(showLabel) text= box->AddText(label);
  frame->addObject(box) ;
  return frame ;
}
Int_t RooTreeData::numEntries(Bool_t) const 
{ 
  return (Int_t)GetEntries() ; 
}
void RooTreeData::printToStream(ostream& os, PrintOption opt, TString indent) const {
  
  
  
  
  oneLinePrint(os,*this);
  if(opt >= Standard) {
    if (isWeighted()) {
      os << indent << "  Contains " << numEntries() << " entries with a total weight of " << sumEntries() << endl;
    } else {
      os << indent << "  Contains " << numEntries() << " entries" << endl;
    }
    if(opt >= Shape) {
      os << indent << "  Defines ";
      TString deeper(indent);
      deeper.Append("  ");
      _vars.printToStream(os,Standard,deeper);
      os << indent << "  Caches ";
      _cachedVars.printToStream(os,Standard,deeper);
      
      if(_truth.getSize() > 0) {
	os << indent << "  Generated with ";
	_truth.printToStream(os,Shape,deeper);
      }
    }
  }
}
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.