/*
<img src="gif/ttree_classtree.gif">
*/
//End_Html
/*
<img src="gif/tree_layout.gif">
*/
//End_Html
#include <string.h>
#include <stdio.h>
#include "snprintf.h"
#include "Riostream.h"
#include "TTreePlayer.h"
#include "TROOT.h"
#include "TSystem.h"
#include "TFile.h"
#include "TEventList.h"
#include "TEntryList.h"
#include "TBranchObject.h"
#include "TBranchElement.h"
#include "TStreamerInfo.h"
#include "TStreamerElement.h"
#include "TLeafObject.h"
#include "TLeafF.h"
#include "TLeafD.h"
#include "TLeafC.h"
#include "TLeafB.h"
#include "TLeafI.h"
#include "TLeafS.h"
#include "TMath.h"
#include "TH2.h"
#include "TH3.h"
#include "TPolyMarker.h"
#include "TPolyMarker3D.h"
#include "TDirectory.h"
#include "TClonesArray.h"
#include "TClass.h"
#include "TVirtualPad.h"
#include "TProfile.h"
#include "TProfile2D.h"
#include "TTreeFormula.h"
#include "TTreeFormulaManager.h"
#include "TStyle.h"
#include "Foption.h"
#include "TTreeResult.h"
#include "TTreeRow.h"
#include "TPrincipal.h"
#include "Api.h"
#include "TChain.h"
#include "TChainElement.h"
#include "TF1.h"
#include "TH1.h"
#include "TVirtualFitter.h"
#include "TEnv.h"
#include "THLimitsFinder.h"
#include "TSelectorDraw.h"
#include "TSelectorEntries.h"
#include "TPluginManager.h"
#include "TObjString.h"
#include "TTreeProxyGenerator.h"
#include "TTreeIndex.h"
#include "TChainIndex.h"
#include "TRefProxy.h"
#include "TRefArrayProxy.h"
#include "TVirtualMonitoring.h"
#include "TTreeCache.h"
R__EXTERN Foption_t Foption;
R__EXTERN  TTree *gTree;
TVirtualFitter *tFitter=0;
extern void TreeUnbinnedFitLikelihood(Int_t &npar, Double_t *gin, Double_t &f, Double_t *u, Int_t flag);
ClassImp(TTreePlayer)
TTreePlayer::TTreePlayer()
{
   fTree           = 0;
   fScanFileName   = 0;
   fScanRedirect   = kFALSE;
   fSelectedRows   = 0;
   fDimension      = 0;
   fHistogram      = 0;
   fFormulaList    = new TList();
   fFormulaList->SetOwner(kTRUE);
   fSelector         = new TSelectorDraw();
   fSelectorFromFile = 0;
   fSelectorClass    = 0;
   fSelectorUpdate   = 0;
   fInput            = new TList();
   fInput->Add(new TNamed("varexp",""));
   fInput->Add(new TNamed("selection",""));
   fSelector->SetInputList(fInput);
   gROOT->GetListOfCleanups()->Add(this);
   TClass::GetClass("TRef")->AdoptReferenceProxy(new TRefProxy());
   TClass::GetClass("TRefArray")->AdoptReferenceProxy(new TRefArrayProxy());
}
TTreePlayer::~TTreePlayer()
{
   delete fFormulaList;
   delete fSelector;
   DeleteSelectorFromFile();
   fInput->Delete();
   delete fInput;
   gROOT->GetListOfCleanups()->Remove(this);
}
TVirtualIndex *TTreePlayer::BuildIndex(const TTree *T, const char *majorname, const char *minorname)
{
   
   TVirtualIndex *index;
   if (dynamic_cast<const TChain*>(T)) {
      index = new TChainIndex(T, majorname, minorname);
      if (index->IsZombie()) {
         delete index;
         Error("BuildIndex", "Creating a TChainIndex unsuccessfull - switching to TTreeIndex");
      }
      else
         return index;
   }
   return new TTreeIndex(T,majorname,minorname);
}
TTree *TTreePlayer::CopyTree(const char *selection, Option_t *, Long64_t nentries,
                             Long64_t firstentry)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   TTree *tree = fTree->CloneTree(0);
   if (tree == 0) return 0;
   
   TObjArray* branches = tree->GetListOfBranches();
   Int_t nb = branches->GetEntriesFast();
   for (Int_t i = 0; i < nb; ++i) {
      TBranch* br = (TBranch*) branches->UncheckedAt(i);
      if (br->InheritsFrom("TBranchElement")) {
         ((TBranchElement*) br)->ResetDeleteObject();
      }
   }
   Long64_t entry,entryNumber;
   nentries = GetEntriesToProcess(firstentry, nentries);
   
   TTreeFormula *select = 0; 
                             
                             
   if (strlen(selection)) {
      select = new TTreeFormula("Selection",selection,fTree);
      if (!select || !select->GetNdim()) { delete select; }
      fFormulaList->Add(select);
   }
   
   Int_t tnumber = -1;
   for (entry=firstentry;entry<firstentry+nentries;entry++) {
      entryNumber = fTree->GetEntryNumber(entry);
      if (entryNumber < 0) break;
      Long64_t localEntry = fTree->LoadTree(entryNumber);
      if (localEntry < 0) break;
      if (tnumber != fTree->GetTreeNumber()) {
         tnumber = fTree->GetTreeNumber();
         if (select) select->UpdateFormulaLeaves();
      }
      if (select) {
         Int_t ndata = select->GetNdata();
         Bool_t keep = kFALSE;
         for(Int_t current = 0; current<ndata && !keep; current++) {
            keep |= (select->EvalInstance(current) != 0);
         }
         if (!keep) continue;
      }
      fTree->GetEntry(entryNumber);
      tree->Fill();
   }
   fFormulaList->Clear();
   return tree;
}
void TTreePlayer::DeleteSelectorFromFile()
{
   if (fSelectorFromFile && fSelectorClass) {
      if (fSelectorClass->IsLoaded()) {
         delete fSelectorFromFile;
      }
   }
   fSelectorFromFile = 0;
   fSelectorClass = 0;
}
Long64_t TTreePlayer::DrawScript(const char* wrapperPrefix,
                                 const char *macrofilename, const char *cutfilename,
                                 Option_t *option, Long64_t nentries, Long64_t firstentry)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   if (!macrofilename || strlen(macrofilename)==0) return 0;
   TString aclicMode;
   TString arguments;
   TString io;
   TString realcutname;
   if (cutfilename && strlen(cutfilename))
      realcutname =  gSystem->SplitAclicMode(cutfilename, aclicMode, arguments, io);
   
   TString realname = gSystem->SplitAclicMode(macrofilename, aclicMode, arguments, io);
   TString selname = wrapperPrefix;
   TTreeProxyGenerator gp(fTree,realname,realcutname,selname,option,3);
   selname = gp.GetFileName();
   if (aclicMode.Length()==0) {
      Warning("DrawScript","TTreeProxy does not work in interpreted mode yet. The script will be compiled.");
      aclicMode = "+";
   }
   selname.Append(aclicMode);
   Info("DrawScript",Form("Will process tree/chain using %s",selname.Data()));
   Long64_t result = fTree->Process(selname,option,nentries,firstentry);
   
   
   
   return result;
}
Long64_t TTreePlayer::DrawSelect(const char *varexp0, const char *selection, Option_t *option,Long64_t nentries, Long64_t firstentry)
{
   if (fTree->GetEntriesFriend() == 0) return 0;
   
   
   TString possibleFilename = varexp0;
   Ssiz_t dot_pos = possibleFilename.Last('.');
   if ( dot_pos != kNPOS
       && possibleFilename.Index("Alt$")<0 && possibleFilename.Index("Entries$")<0
       && possibleFilename.Index("Length$")<0  && possibleFilename.Index("Entry$")<0
       && possibleFilename.Index("LocalEntry$")<0
       && possibleFilename.Index("Iteration$")<0 && possibleFilename.Index("Sum$")<0
       && gSystem->IsFileInIncludePath(possibleFilename.Data())) {
      if (selection && strlen(selection) && !gSystem->IsFileInIncludePath(selection)) {
         Error("DrawSelect",
               "Drawing using a C++ file currently requires that both the expression and the selection are files\n\t\"%s\" is not a file",
               selection);
         return 0;
      }
      return DrawScript("generatedSel",varexp0,selection,option,nentries,firstentry);
   } else {
      possibleFilename = selection;
      if (possibleFilename.Index("Alt$")<0 && possibleFilename.Index("Entries$")<0
          && possibleFilename.Index("Length$")<0  && possibleFilename.Index("Entry$")<0
          && possibleFilename.Index("LocalEntry$")<0
          && possibleFilename.Index("Iteration$")<0 && possibleFilename.Index("Sum$")<0
          && gSystem->IsFileInIncludePath(possibleFilename.Data())) {
         Error("DrawSelect",
               "Drawing using a C++ file currently requires that both the expression and the selection are files\n\t\"%s\" is not a file",
               varexp0);
         return 0;
      }
   }
   Long64_t oldEstimate  = fTree->GetEstimate();
   TEventList *evlist  = fTree->GetEventList();
   TEntryList *elist = fTree->GetEntryList();
   if (evlist && elist){
      elist->SetBit(kCanDelete, kTRUE);
   }
   TNamed *cvarexp    = (TNamed*)fInput->FindObject("varexp");
   TNamed *cselection = (TNamed*)fInput->FindObject("selection");
   if (cvarexp) cvarexp->SetTitle(varexp0);
   if (cselection) cselection->SetTitle(selection);
   
   if (nentries > fTree->GetMaxEntryLoop()) nentries = fTree->GetMaxEntryLoop();
   
   Long64_t nrows = Process(fSelector,option,nentries,firstentry);
   fSelectedRows = nrows;
   fDimension = fSelector->GetDimension();
   
   if (fDimension <= 0) {
      fTree->SetEstimate(oldEstimate);
      if (fSelector->GetCleanElist()) {
         
         fTree->SetEntryList(elist);
         delete fSelector->GetObject();
      }
      return nrows;
   }
   
   Long64_t drawflag = fSelector->GetDrawFlag();
   Int_t action   = fSelector->GetAction();
   TString opt = option;
   opt.ToLower();
   Bool_t draw = kFALSE;
   if (!drawflag && !opt.Contains("goff")) draw = kTRUE;
   fHistogram = (TH1*)fSelector->GetObject();
   if (!nrows && drawflag && !opt.Contains("same")) {
      if (gPad) gPad->Clear();
      return 0;
   }
   
   if (fDimension == 1) {
      if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("X");
      if (draw) fHistogram->Draw(option);
   
   } else if (fDimension == 2) {
      if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("Y");
      if (fSelector->GetVar2()->IsInteger()) fHistogram->LabelsDeflate("X");
      if (action == 4) {
         if (draw) fHistogram->Draw(option);
      } else {
         Bool_t graph = kFALSE;
         Int_t l = opt.Length();
         if (l == 0 || opt == "same") graph = kTRUE;
         if (opt.Contains("p")     || opt.Contains("*")    || opt.Contains("l"))    graph = kTRUE;
         if (opt.Contains("surf")  || opt.Contains("lego") || opt.Contains("cont")) graph = kFALSE;
         if (opt.Contains("col")   || opt.Contains("hist") || opt.Contains("scat")) graph = kFALSE;
         if (!graph) {
            if (draw) fHistogram->Draw(option);
         } else {
            if (fSelector->GetOldHistogram() && draw) fHistogram->Draw(option);
         }
      }
   
   } else if (fDimension == 3) {
      if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("Z");
      if (fSelector->GetVar2()->IsInteger()) fHistogram->LabelsDeflate("Y");
      if (fSelector->GetVar3()->IsInteger()) fHistogram->LabelsDeflate("X");
      if (action == 23) {
         if (draw) fHistogram->Draw(option);
      } else {
         Int_t noscat = opt.Length();
         if (opt.Contains("same")) noscat -= 4;
         if (noscat) {
            if (draw) fHistogram->Draw(option);
         } else {
            if (fSelector->GetOldHistogram() && draw) fHistogram->Draw(option);
         }
      }
   
   } else if (fDimension == 4) {
      if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("Z");
      if (fSelector->GetVar2()->IsInteger()) fHistogram->LabelsDeflate("Y");
      if (fSelector->GetVar3()->IsInteger()) fHistogram->LabelsDeflate("X");
      if (draw) fHistogram->Draw(option);
      Int_t ncolors  = gStyle->GetNumberOfColors();
      TObjArray *pms = (TObjArray*)fHistogram->GetListOfFunctions()->FindObject("polymarkers");
      for (Int_t col=0;col<ncolors;col++) {
         if (!pms) continue;
         TPolyMarker3D *pm3d = (TPolyMarker3D*)pms->UncheckedAt(col);
         if (draw) pm3d->Draw();
      }
   }
   return fSelectedRows;
}
Int_t TTreePlayer::Fit(const char *formula ,const char *varexp, const char *selection,Option_t *option ,Option_t *goption,Long64_t nentries, Long64_t firstentry)
{
   Int_t nch = strlen(option) + 10;
   char *opt = new char[nch];
   if (option) sprintf(opt,"%s",option);
   else        strcpy(opt,"goff");
   Long64_t nsel = DrawSelect(varexp,selection,opt,nentries,firstentry);
   delete [] opt;
   Int_t fitResult = -1;
   
   if (fHistogram && nsel > 0) {
      fitResult = fHistogram->Fit(formula,option,goption);
   }
   return fitResult;
}
Long64_t TTreePlayer::GetEntries(const char *selection)
{
   
   
   
   
   
   
   
   
   
   
   TSelectorEntries s(selection);
   fTree->Process(&s);
   return s.GetSelectedRows();
}
Long64_t TTreePlayer::GetEntriesToProcess(Long64_t firstentry, Long64_t nentries) const
{
   
   
   
   Long64_t lastentry = firstentry + nentries - 1;
   if (lastentry > fTree->GetEntriesFriend()-1) {
      lastentry  = fTree->GetEntriesFriend() - 1;
      nentries   = lastentry - firstentry + 1;
   }
   
   
   TEntryList *elist = fTree->GetEntryList();
   if (elist && elist->GetN() < nentries) nentries = elist->GetN();
   return nentries;
}
const char *TTreePlayer::GetNameByIndex(TString &varexp, Int_t *index,Int_t colindex)
{
   Int_t i1,n;
   static TString column;
   if (colindex<0 ) return "";
   i1 = index[colindex] + 1;
   n  = index[colindex+1] - i1;
   column = varexp(i1,n);
   
   return column.Data();
}
static TString R__GetBranchPointerName(TLeaf *leaf)
{
   
   TLeaf *leafcount = leaf->GetLeafCount();
   TBranch *branch = leaf->GetBranch();
   TString branchname( branch->GetName() );
   if ( branch->GetNleaves() <= 1 ) {
       if (branch->IsA() != TBranchObject::Class()) {
         if (!leafcount) {
            TBranch *mother = branch->GetMother();
            const char* ltitle = leaf->GetTitle();
            if (mother && mother!=branch) {
               branchname = mother->GetName();
               if (branchname[branchname.Length()-1]!='.') {
                  branchname += ".";
               }
               if (strncmp(branchname.Data(),ltitle,branchname.Length())==0) {
                  branchname = "";
               }
            } else {
               branchname = "";
            }
            branchname += ltitle;
         }
      }
   }
   char *bname = (char*)branchname.Data();
   char *twodim = (char*)strstr(bname,"[");
   if (twodim) *twodim = 0;
   while (*bname) {
      if (*bname == '.') *bname='_';
      if (*bname == ':') *bname='_';
      if (*bname == '<') *bname='_';
      if (*bname == '>') *bname='_';
      bname++;
   }
   return branchname;
}
Int_t TTreePlayer::MakeClass(const char *classname, const char *option)
{
   TString opt = option;
   opt.ToLower();
   
   char *thead = new char[256];
   if (!classname) classname = fTree->GetName();
   sprintf(thead,"%s.h",classname);
   FILE *fp = fopen(thead,"w");
   if (!fp) {
      printf("Cannot open output file:%s\n",thead);
      delete [] thead;
      return 3;
   }
   char *tcimp = new char[256];
   sprintf(tcimp,"%s.C",classname);
   FILE *fpc = fopen(tcimp,"w");
   if (!fpc) {
      printf("Cannot open output file:%s\n",tcimp);
      delete [] thead;
      delete [] tcimp;
      return 3;
   }
   char *treefile = new char[1000];
   if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
      strcpy(treefile,fTree->GetDirectory()->GetFile()->GetName());
   } else {
      strcpy(treefile,"Memory Directory");
   }
   
   
   
   Bool_t ischain = fTree->InheritsFrom("TChain");
   Bool_t isHbook = fTree->InheritsFrom("THbookTree");
   if (isHbook) strcpy(treefile,fTree->GetTitle());
   
   TObjArray *leaves = fTree->GetListOfLeaves();
   Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
   TDatime td;
   fprintf(fp,"//////////////////////////////////////////////////////////\n");
   fprintf(fp,"// This class has been automatically generated on\n");
   fprintf(fp,"// %s by ROOT version %s\n",td.AsString(),gROOT->GetVersion());
   if (!ischain) {
      fprintf(fp,"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
      fprintf(fp,"// found on file: %s\n",treefile);
   } else {
      fprintf(fp,"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
   }
   fprintf(fp,"//////////////////////////////////////////////////////////\n");
   fprintf(fp,"\n");
   fprintf(fp,"#ifndef %s_h\n",classname);
   fprintf(fp,"#define %s_h\n",classname);
   fprintf(fp,"\n");
   fprintf(fp,"#include <TROOT.h>\n");
   fprintf(fp,"#include <TChain.h>\n");
   fprintf(fp,"#include <TFile.h>\n");
   if (isHbook) fprintf(fp,"#include <THbookFile.h>\n");
   if (opt.Contains("selector")) fprintf(fp,"#include <TSelector.h>\n");
   Int_t len, lenb,l;
   char blen[128];
   char *bname;
   Int_t *leaflen = new Int_t[nleaves];
   TObjArray *leafs = new TObjArray(nleaves);
   for (l=0;l<nleaves;l++) {
      TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
      leafs->AddAt(new TObjString(leaf->GetName()),l);
      leaflen[l] = leaf->GetMaximum();
   }
   if (ischain) {
      
      
      
      TChain *chain = (TChain*)fTree;
      Int_t ntrees = chain->GetNtrees();
      for (Int_t file=0;file<ntrees;file++) {
         Long64_t first = chain->GetTreeOffset()[file];
         chain->LoadTree(first);
         for (l=0;l<nleaves;l++) {
            TObjString *obj = (TObjString*)leafs->At(l);
            TLeaf *leaf = chain->GetLeaf(obj->GetName());
            if (leaf) {
               leaflen[l] = TMath::Max(leaflen[l],leaf->GetMaximum());
            }
         }
      }
      chain->LoadTree(0);
   }
   leaves = fTree->GetListOfLeaves();
   for (l=0;l<nleaves;l++) {
      TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
      strcpy(blen,leaf->GetName());
      bname = &blen[0];
      while (*bname) {
         if (*bname == '.') *bname='_';
         if (*bname == ':') *bname='_';
         if (*bname == '<') *bname='_';
         if (*bname == '>') *bname='_';
         bname++;
      }
      lenb = strlen(blen);
      if (blen[lenb-1] == '_') {
         blen[lenb-1] = 0;
         len = leaflen[l];
         if (len <= 0) len = 1;
         fprintf(fp,"   const Int_t kMax%s = %d;\n",blen,len);
      }
   }
   delete [] leaflen;
   leafs->Delete();
   delete leafs;
   fprintf(fp,"\n");
   if (opt.Contains("selector")) {
      fprintf(fp,"class %s : public TSelector {\n",classname);
      fprintf(fp,"public :\n");
      fprintf(fp,"   TTree          *fChain;   //!pointer to the analyzed TTree or TChain\n");
   } else {
      fprintf(fp,"class %s {\n",classname);
      fprintf(fp,"public :\n");
      fprintf(fp,"   TTree          *fChain;   //!pointer to the analyzed TTree or TChain\n");
      fprintf(fp,"   Int_t           fCurrent; //!current Tree number in a TChain\n");
   }
   fprintf(fp,"\n   // Declaration of leave types\n");
   TLeaf *leafcount;
   TLeafObject *leafobj;
   TBranchElement *bre=0;
   const char *headOK  = "   ";
   const char *headcom = " //";
   const char *head;
   char branchname[128];
   char aprefix[128];
   TObjArray branches(100);
   TObjArray mustInit(100);
   TObjArray mustInitArr(100);
   mustInitArr.SetOwner(kFALSE);
   Int_t *leafStatus = new Int_t[nleaves];
   for (l=0;l<nleaves;l++) {
      Int_t kmax = 0;
      head = headOK;
      leafStatus[l] = 0;
      TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
      len = leaf->GetLen(); if (len<=0) len = 1;
      leafcount =leaf->GetLeafCount();
      TBranch *branch = leaf->GetBranch();
      branchname[0] = 0;
      strcpy(branchname,branch->GetName());
      strcpy(aprefix,branch->GetName());
      if (!branches.FindObject(branch)) branches.Add(branch);
      else leafStatus[l] = 1;
      if ( branch->GetNleaves() > 1) {
         
         strcat(branchname,".");
         strcat(branchname,leaf->GetTitle());
         if (leafcount) {
            
            char *dim =  (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
         }
      } else {
         strcpy(branchname,branch->GetName());
      }
      char *twodim = (char*)strstr(leaf->GetTitle(),"][");
      bname = branchname;
      while (*bname) {
         if (*bname == '.') *bname='_';
         if (*bname == ':') *bname='_';
         if (*bname == '<') *bname='_';
         if (*bname == '>') *bname='_';
         bname++;
      }
      if (branch->IsA() == TBranchObject::Class()) {
         if (branch->GetListOfBranches()->GetEntriesFast()) {leafStatus[l] = 1; continue;}
         leafobj = (TLeafObject*)leaf;
         if (!leafobj->GetClass()) {leafStatus[l] = 1; head = headcom;}
         fprintf(fp,"%s%-15s *%s;\n",head,leafobj->GetTypeName(), leafobj->GetName());
         if (leafStatus[l] == 0) mustInit.Add(leafobj);
         continue;
      }
      if (leafcount) {
         len = leafcount->GetMaximum();
         if (len<=0) len = 1;
         strcpy(blen,leafcount->GetName());
         bname = &blen[0];
         while (*bname) {
            if (*bname == '.') *bname='_';
            if (*bname == ':') *bname='_';
            if (*bname == '<') *bname='_';
            if (*bname == '>') *bname='_';
            bname++;
         }
         lenb = strlen(blen);
         if (blen[lenb-1] == '_') {blen[lenb-1] = 0; kmax = 1;}
         else                     sprintf(blen,"%d",len);
      }
      if (branch->IsA() == TBranchElement::Class()) {
         bre = (TBranchElement*)branch;
         if (bre->GetType() != 3 && bre->GetType() != 4
             && bre->GetStreamerType() <= 0 && bre->GetListOfBranches()->GetEntriesFast()) {
            leafStatus[l] = 0;
         }
         if (bre->GetType() == 3 || bre->GetType() == 4) {
            fprintf(fp,"   %-15s %s_;\n","Int_t", branchname);
            continue;
         }
         if (bre->IsBranchFolder()) {
            fprintf(fp,"   %-15s *%s;\n",bre->GetClassName(), branchname);
            mustInit.Add(bre);
            continue;
         } else {
            if (branch->GetListOfBranches()->GetEntriesFast()) {leafStatus[l] = 1;}
         }
         if (bre->GetStreamerType() < 0) {
            if (branch->GetListOfBranches()->GetEntriesFast()) {
               fprintf(fp,"%s%-15s *%s;\n",headcom,bre->GetClassName(), bre->GetName());
            } else {
               fprintf(fp,"%s%-15s *%s;\n",head,bre->GetClassName(), bre->GetName());
               mustInit.Add(bre);
            }
            continue;
         }
         if (bre->GetStreamerType() == 0) {
            if (!TClass::GetClass(bre->GetClassName())->GetClassInfo()) {leafStatus[l] = 1; head = headcom;}
            fprintf(fp,"%s%-15s *%s;\n",head,bre->GetClassName(), bre->GetName());
            if (leafStatus[l] == 0) mustInit.Add(bre);
            continue;
         }
         if (bre->GetStreamerType() > 60) {
            TClass *cle = TClass::GetClass(bre->GetClassName());
            if (!cle) {leafStatus[l] = 1; continue;}
            if (bre->GetStreamerType() == 66) leafStatus[l] = 0;
            char brename[256];
            strcpy(brename,bre->GetName());
            char *bren = brename;
            char *adot = strrchr(bren,'.');
            if (adot) bren = adot+1;
            char *brack = strchr(bren,'[');
            if (brack) *brack = 0;
            TStreamerElement *elem = (TStreamerElement*)cle->GetStreamerInfo()->GetElements()->FindObject(bren);
            if (elem) {
               if (elem->IsA() == TStreamerBase::Class()) {leafStatus[l] = 1; continue;}
               if (!TClass::GetClass(elem->GetTypeName())) {leafStatus[l] = 1; continue;}
               if (!TClass::GetClass(elem->GetTypeName())->GetClassInfo()) {leafStatus[l] = 1; head = headcom;}
               if (leafcount) fprintf(fp,"%s%-15s %s[kMax%s];\n",head,elem->GetTypeName(), branchname,blen);
               else           fprintf(fp,"%s%-15s %s;\n",head,elem->GetTypeName(), branchname);
            } else {
               if (!TClass::GetClass(bre->GetClassName())->GetClassInfo()) {leafStatus[l] = 1; head = headcom;}
               fprintf(fp,"%s%-15s %s;\n",head,bre->GetClassName(), branchname);
            }
            continue;
         }
      }
      if (strlen(leaf->GetTypeName()) == 0) {leafStatus[l] = 1; continue;}
      if (leafcount) {
         
         
         
         
         
         
         
         
         const char *stars = " ";
         if (bre && bre->GetBranchCount2()) {
            stars = "*";
         }
         
         
         char *dimensions = 0;
         char *dimInName = (char*) strstr(branchname,"[");
         if ( twodim || dimInName ) {
            int dimlen = 0;
            if (dimInName) dimlen += strlen(dimInName) + 1;
            if (twodim)    dimlen += strlen(twodim) + 1;
            dimensions = new char[dimlen];
            if (dimInName) {
               strcpy(dimensions,dimInName);
               dimInName[0] = 0; 
            } else dimensions[0] = 0;
            if (twodim) strcat(dimensions,(char*)(twodim+1));
         }
         const char* leafcountName = leafcount->GetName();
         char b2len[128];
         if (bre && bre->GetBranchCount2()) {
            TLeaf * l2 = (TLeaf*)bre->GetBranchCount2()->GetListOfLeaves()->At(0);
            strcpy(b2len,l2->GetName());
            bname = &b2len[0];
            while (*bname) {
               if (*bname == '.') *bname='_';
               if (*bname == ':') *bname='_';
               if (*bname == '<') *bname='_';
               if (*bname == '>') *bname='_';
               bname++;
            }
            leafcountName = b2len;
         }
         if (dimensions) {
            if (kmax) fprintf(fp,"   %-14s %s%s[kMax%s]%s;   //[%s]\n",leaf->GetTypeName(), stars,
                              branchname,blen,dimensions,leafcountName);
            else      fprintf(fp,"   %-14s %s%s[%d]%s;   //[%s]\n",leaf->GetTypeName(), stars,
                              branchname,len,dimensions,leafcountName);
            delete dimensions;
         } else {
            if (kmax) fprintf(fp,"   %-14s %s%s[kMax%s];   //[%s]\n",leaf->GetTypeName(), stars, branchname,blen,leafcountName);
            else      fprintf(fp,"   %-14s %s%s[%d];   //[%s]\n",leaf->GetTypeName(), stars, branchname,len,leafcountName);
         }
         if (stars[0]=='*') {
            TNamed *n;
            if (kmax) n = new TNamed(branchname, Form("kMax%s",blen));
            else n = new TNamed(branchname, Form("%d",len));
            mustInitArr.Add(n);
         }
      } else {
         if (strstr(branchname,"[")) len = 1;
         if (len < 2) fprintf(fp,"   %-15s %s;\n",leaf->GetTypeName(), branchname);
         else {
            if (twodim) fprintf(fp,"   %-15s %s%s;\n",leaf->GetTypeName(), branchname,(char*)strstr(leaf->GetTitle(),"["));
            else        fprintf(fp,"   %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
         }
      }
   }
   fprintf(fp,"\n");
   fprintf(fp,"   // List of branches\n");
   for (l=0;l<nleaves;l++) {
      if (leafStatus[l]) continue;
      TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
      fprintf(fp,"   TBranch        *b_%s;   //!\n",R__GetBranchPointerName(leaf).Data());
   }
   if (opt.Contains("selector")) {
      fprintf(fp,"\n");
      fprintf(fp,"   %s(TTree * /*tree*/ =0) { }\n",classname) ;
      fprintf(fp,"   virtual ~%s() { }\n",classname);
      fprintf(fp,"   virtual Int_t   Version() const { return 2; }\n");
      fprintf(fp,"   virtual void    Begin(TTree *tree);\n");
      fprintf(fp,"   virtual void    SlaveBegin(TTree *tree);\n");
      fprintf(fp,"   virtual void    Init(TTree *tree);\n");
      fprintf(fp,"   virtual Bool_t  Notify();\n");
      fprintf(fp,"   virtual Bool_t  Process(Long64_t entry);\n");
      fprintf(fp,"   virtual Int_t   GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }\n");
      fprintf(fp,"   virtual void    SetOption(const char *option) { fOption = option; }\n");
      fprintf(fp,"   virtual void    SetObject(TObject *obj) { fObject = obj; }\n");
      fprintf(fp,"   virtual void    SetInputList(TList *input) { fInput = input; }\n");
      fprintf(fp,"   virtual TList  *GetOutputList() const { return fOutput; }\n");
      fprintf(fp,"   virtual void    SlaveTerminate();\n");
      fprintf(fp,"   virtual void    Terminate();\n\n");
      fprintf(fp,"   ClassDef(%s,0);\n",classname);
      fprintf(fp,"};\n");
      fprintf(fp,"\n");
      fprintf(fp,"#endif\n");
      fprintf(fp,"\n");
   } else {
      fprintf(fp,"\n");
      fprintf(fp,"   %s(TTree *tree=0);\n",classname);
      fprintf(fp,"   virtual ~%s();\n",classname);
      fprintf(fp,"   virtual Int_t    Cut(Long64_t entry);\n");
      fprintf(fp,"   virtual Int_t    GetEntry(Long64_t entry);\n");
      fprintf(fp,"   virtual Long64_t LoadTree(Long64_t entry);\n");
      fprintf(fp,"   virtual void     Init(TTree *tree);\n");
      fprintf(fp,"   virtual void     Loop();\n");
      fprintf(fp,"   virtual Bool_t   Notify();\n");
      fprintf(fp,"   virtual void     Show(Long64_t entry = -1);\n");
      fprintf(fp,"};\n");
      fprintf(fp,"\n");
      fprintf(fp,"#endif\n");
      fprintf(fp,"\n");
   }
   fprintf(fp,"#ifdef %s_cxx\n",classname);
   if (!opt.Contains("selector")) {
      fprintf(fp,"%s::%s(TTree *tree)\n",classname,classname);
      fprintf(fp,"{\n");
      fprintf(fp,"// if parameter tree is not specified (or zero), connect the file\n");
      fprintf(fp,"// used to generate this class and read the Tree.\n");
      fprintf(fp,"   if (tree == 0) {\n");
      if (ischain) {
         fprintf(fp,"\n#ifdef SINGLE_TREE\n");
         fprintf(fp,"      // The following code should be used if you want this class to access\n");
         fprintf(fp,"      // a single tree instead of a chain\n");
      }
      if (isHbook) {
         fprintf(fp,"      THbookFile *f = (THbookFile*)gROOT->GetListOfBrowsables()->FindObject(\"%s\");\n",treefile);
         fprintf(fp,"      if (!f) {\n");
         fprintf(fp,"         f = new THbookFile(\"%s\");\n",treefile);
         fprintf(fp,"      }\n");
         Int_t hid;
         sscanf(fTree->GetName(),"h%d",&hid);
         fprintf(fp,"      tree = (TTree*)f->Get(%d);\n\n",hid);
      } else {
         fprintf(fp,"      TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n",treefile);
         fprintf(fp,"      if (!f) {\n");
         fprintf(fp,"         f = new TFile(\"%s\");\n",treefile);
         if (gDirectory != gFile) {
            fprintf(fp,"         f->cd(\"%s\");\n",gDirectory->GetPath());
         }
         fprintf(fp,"      }\n");
         fprintf(fp,"      tree = (TTree*)gDirectory->Get(\"%s\");\n\n",fTree->GetName());
      }
      if (ischain) {
         fprintf(fp,"#else // SINGLE_TREE\n\n");
         fprintf(fp,"      // The following code should be used if you want this class to access a chain\n");
         fprintf(fp,"      // of trees.\n");
         fprintf(fp,"      TChain * chain = new TChain(\"%s\",\"%s\");\n",
                 fTree->GetName(),fTree->GetTitle());
         TIter next(((TChain*)fTree)->GetListOfFiles());
         TChainElement *element;
         while ((element = (TChainElement*)next())) {
            fprintf(fp,"      chain->Add(\"%s/%s\");\n",element->GetTitle(),element->GetName());
         }
         fprintf(fp,"      tree = chain;\n");
         fprintf(fp,"#endif // SINGLE_TREE\n\n");
      }
      fprintf(fp,"   }\n");
      fprintf(fp,"   Init(tree);\n");
      fprintf(fp,"}\n");
      fprintf(fp,"\n");
   }
   if (!opt.Contains("selector")) {
      fprintf(fp,"%s::~%s()\n",classname,classname);
      fprintf(fp,"{\n");
      fprintf(fp,"   if (!fChain) return;\n");
      if (isHbook) {
         
      } else {
         fprintf(fp,"   delete fChain->GetCurrentFile();\n");
      }
      fprintf(fp,"}\n");
      fprintf(fp,"\n");
   }
   if (!opt.Contains("selector")) {
      fprintf(fp,"Int_t %s::GetEntry(Long64_t entry)\n",classname);
      fprintf(fp,"{\n");
      fprintf(fp,"// Read contents of entry.\n");
      fprintf(fp,"   if (!fChain) return 0;\n");
      fprintf(fp,"   return fChain->GetEntry(entry);\n");
      fprintf(fp,"}\n");
   }
   if (!opt.Contains("selector")) {
      fprintf(fp,"Long64_t %s::LoadTree(Long64_t entry)\n",classname);
      fprintf(fp,"{\n");
      fprintf(fp,"// Set the environment to read one entry\n");
      fprintf(fp,"   if (!fChain) return -5;\n");
      fprintf(fp,"   Long64_t centry = fChain->LoadTree(entry);\n");
      fprintf(fp,"   if (centry < 0) return centry;\n");
      fprintf(fp,"   if (!fChain->InheritsFrom(TChain::Class()))  return centry;\n");
      fprintf(fp,"   TChain *chain = (TChain*)fChain;\n");
      fprintf(fp,"   if (chain->GetTreeNumber() != fCurrent) {\n");
      fprintf(fp,"      fCurrent = chain->GetTreeNumber();\n");
      fprintf(fp,"      Notify();\n");
      fprintf(fp,"   }\n");
      fprintf(fp,"   return centry;\n");
      fprintf(fp,"}\n");
      fprintf(fp,"\n");
   }
   fprintf(fp,"void %s::Init(TTree *tree)\n",classname);
   fprintf(fp,"{\n");
   fprintf(fp,"   // The Init() function is called when the selector needs to initialize\n"
              "   // a new tree or chain. Typically here the branch addresses and branch\n"
              "   // pointers of the tree will be set.\n"
              "   // It is normaly not necessary to make changes to the generated\n"
              "   // code, but the routine can be extended by the user if needed.\n"
              "   // Init() will be called many times when running on PROOF\n"
              "   // (once per file to be processed).\n\n");
   if (mustInit.Last()) {
      TIter next(&mustInit);
      TObject *obj;
      fprintf(fp,"   // Set object pointer\n");
      while( (obj = next()) ) {
         if (obj->InheritsFrom(TBranch::Class())) {
            strcpy(branchname,((TBranch*)obj)->GetName() );
         } else if (obj->InheritsFrom(TLeaf::Class())) {
            strcpy(branchname,((TLeaf*)obj)->GetName() );
         }
         bname = branchname;
         while (*bname) {
            if (*bname == '.') *bname='_';
            if (*bname == ':') *bname='_';
            if (*bname == '<') *bname='_';
            if (*bname == '>') *bname='_';
            bname++;
         }
         fprintf(fp,"   %s = 0;\n",branchname );
      }
   }
   if (mustInitArr.Last()) {
      TIter next(&mustInitArr);
      TNamed *info;
      fprintf(fp,"   // Set array pointer\n");
      while( (info = (TNamed*)next()) ) {
         fprintf(fp,"   for(int i=0; i<%s; ++i) %s[i] = 0;\n",info->GetTitle(),info->GetName());
      }
      fprintf(fp,"\n");
   }
   fprintf(fp,"   // Set branch addresses and branch pointers\n");
   fprintf(fp,"   if (!tree) return;\n");
   fprintf(fp,"   fChain = tree;\n");
   if (!opt.Contains("selector")) fprintf(fp,"   fCurrent = -1;\n");
   fprintf(fp,"   fChain->SetMakeClass(1);\n");
   fprintf(fp,"\n");
   for (l=0;l<nleaves;l++) {
      if (leafStatus[l]) continue;
      TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
      len = leaf->GetLen();
      leafcount =leaf->GetLeafCount();
      TBranch *branch = leaf->GetBranch();
      strcpy(aprefix,branch->GetName());
      if ( branch->GetNleaves() > 1) {
         
         strcpy(branchname,branch->GetName());
         strcat(branchname,".");
         strcat(branchname,leaf->GetTitle());
         if (leafcount) {
            
            char *dim =  (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
         }
      } else {
         strcpy(branchname,branch->GetName());
         if (branch->IsA() == TBranchElement::Class()) {
            bre = (TBranchElement*)branch;
            if (bre->GetType() == 3 || bre->GetType()==4) strcat(branchname,"_");
         }
      }
      bname = branchname;
      char *brak = strstr(branchname,"[");     if (brak) *brak = 0;
      char *twodim = (char*)strstr(bname,"["); if (twodim) *twodim = 0;
      while (*bname) {
         if (*bname == '.') *bname='_';
         if (*bname == ':') *bname='_';
         if (*bname == '<') *bname='_';
         if (*bname == '>') *bname='_';
         bname++;
      }
      if (branch->IsA() == TBranchObject::Class()) {
         if (branch->GetListOfBranches()->GetEntriesFast()) {
            fprintf(fp,"   fChain->SetBranchAddress(\"%s\",(void*)-1,&b_%s);\n",branch->GetName(),R__GetBranchPointerName(leaf).Data());
            continue;
         }
         strcpy(branchname,branch->GetName());
      }
      if (branch->IsA() == TBranchElement::Class()) {
         if (((TBranchElement*)branch)->GetType() == 3) len =1;
         if (((TBranchElement*)branch)->GetType() == 4) len =1;
      }
      if (leafcount) len = leafcount->GetMaximum()+1;
      if (len > 1) fprintf(fp,"   fChain->SetBranchAddress(\"%s\", %s, &b_%s);\n",
                           branch->GetName(), branchname, R__GetBranchPointerName(leaf).Data());
      else         fprintf(fp,"   fChain->SetBranchAddress(\"%s\", &%s, &b_%s);\n",
                           branch->GetName(), branchname, R__GetBranchPointerName(leaf).Data());
   }
   
   if (!opt.Contains("selector")) {
      fprintf(fp,"   Notify();\n");
   }
   fprintf(fp,"}\n");
   fprintf(fp,"\n");
   fprintf(fp,"Bool_t %s::Notify()\n",classname);
   fprintf(fp,"{\n");
   fprintf(fp,"   // The Notify() function is called when a new file is opened. This\n"
              "   // can be either for a new TTree in a TChain or when when a new TTree\n"
              "   // is started when using PROOF. It is normaly not necessary to make changes\n"
              "   // to the generated code, but the routine can be extended by the\n"
              "   // user if needed. The return value is currently not used.\n\n");
   fprintf(fp,"   return kTRUE;\n");
   fprintf(fp,"}\n");
   fprintf(fp,"\n");
   if (!opt.Contains("selector")) {
      fprintf(fp,"void %s::Show(Long64_t entry)\n",classname);
      fprintf(fp,"{\n");
      fprintf(fp,"// Print contents of entry.\n");
      fprintf(fp,"// If entry is not specified, print current entry\n");
      fprintf(fp,"   if (!fChain) return;\n");
      fprintf(fp,"   fChain->Show(entry);\n");
      fprintf(fp,"}\n");
   }
   if (!opt.Contains("selector")) {
      fprintf(fp,"Int_t %s::Cut(Long64_t entry)\n",classname);
      fprintf(fp,"{\n");
      fprintf(fp,"// This function may be called from Loop.\n");
      fprintf(fp,"// returns  1 if entry is accepted.\n");
      fprintf(fp,"// returns -1 otherwise.\n");
      fprintf(fp,"   return 1;\n");
      fprintf(fp,"}\n");
   }
   fprintf(fp,"#endif // #ifdef %s_cxx\n",classname);
   if (!opt.Contains("selector")) {
      
      fprintf(fpc,"#define %s_cxx\n",classname);
      fprintf(fpc,"#include \"%s\"\n",thead);
      fprintf(fpc,"#include <TH2.h>\n");
      fprintf(fpc,"#include <TStyle.h>\n");
      fprintf(fpc,"#include <TCanvas.h>\n");
      fprintf(fpc,"\n");
      fprintf(fpc,"void %s::Loop()\n",classname);
      fprintf(fpc,"{\n");
      fprintf(fpc,"//   In a ROOT session, you can do:\n");
      fprintf(fpc,"//      Root > .L %s.C\n",classname);
      fprintf(fpc,"//      Root > %s t\n",classname);
      fprintf(fpc,"//      Root > t.GetEntry(12); // Fill t data members with entry number 12\n");
      fprintf(fpc,"//      Root > t.Show();       // Show values of entry 12\n");
      fprintf(fpc,"//      Root > t.Show(16);     // Read and show values of entry 16\n");
      fprintf(fpc,"//      Root > t.Loop();       // Loop on all entries\n");
      fprintf(fpc,"//\n");
      fprintf(fpc,"\n//     This is the loop skeleton where:\n");
      fprintf(fpc,"//    jentry is the global entry number in the chain\n");
      fprintf(fpc,"//    ientry is the entry number in the current Tree\n");
      fprintf(fpc,"//  Note that the argument to GetEntry must be:\n");
      fprintf(fpc,"//    jentry for TChain::GetEntry\n");
      fprintf(fpc,"//    ientry for TTree::GetEntry and TBranch::GetEntry\n");
      fprintf(fpc,"//\n");
      fprintf(fpc,"//       To read only selected branches, Insert statements like:\n");
      fprintf(fpc,"// METHOD1:\n");
      fprintf(fpc,"//    fChain->SetBranchStatus(\"*\",0);  // disable all branches\n");
      fprintf(fpc,"//    fChain->SetBranchStatus(\"branchname\",1);  // activate branchname\n");
      fprintf(fpc,"// METHOD2: replace line\n");
      fprintf(fpc,"//    fChain->GetEntry(jentry);       //read all branches\n");
      fprintf(fpc,"//by  b_branchname->GetEntry(ientry); //read only this branch\n");
      fprintf(fpc,"   if (fChain == 0) return;\n");
      fprintf(fpc,"\n   Long64_t nentries = fChain->GetEntriesFast();\n");
      fprintf(fpc,"\n   Long64_t nbytes = 0, nb = 0;\n");
      fprintf(fpc,"   for (Long64_t jentry=0; jentry<nentries;jentry++) {\n");
      fprintf(fpc,"      Long64_t ientry = LoadTree(jentry);\n");
      fprintf(fpc,"      if (ientry < 0) break;\n");
      fprintf(fpc,"      nb = fChain->GetEntry(jentry);   nbytes += nb;\n");
      fprintf(fpc,"      // if (Cut(ientry) < 0) continue;\n");
      fprintf(fpc,"   }\n");
      fprintf(fpc,"}\n");
   }
   if (opt.Contains("selector")) {
      
      fprintf(fpc,"#define %s_cxx\n",classname);
      fprintf(fpc,"// The class definition in %s.h has been generated automatically\n",classname);
      fprintf(fpc,"// by the ROOT utility TTree::MakeSelector(). This class is derived\n");
      fprintf(fpc,"// from the ROOT class TSelector. For more information on the TSelector\n"
                  "// framework see $ROOTSYS/README/README.SELECTOR or the ROOT User Manual.\n\n");
      fprintf(fpc,"// The following methods are defined in this file:\n");
      fprintf(fpc,"//    Begin():        called everytime a loop on the tree starts,\n");
      fprintf(fpc,"//                    a convenient place to create your histograms.\n");
      fprintf(fpc,"//    SlaveBegin():   called after Begin(), when on PROOF called only on the\n"
                  "//                    slave servers.\n");
      fprintf(fpc,"//    Process():      called for each event, in this function you decide what\n");
      fprintf(fpc,"//                    to read and fill your histograms.\n");
      fprintf(fpc,"//    SlaveTerminate: called at the end of the loop on the tree, when on PROOF\n"
                  "//                    called only on the slave servers.\n");
      fprintf(fpc,"//    Terminate():    called at the end of the loop on the tree,\n");
      fprintf(fpc,"//                    a convenient place to draw/fit your histograms.\n");
      fprintf(fpc,"//\n");
      fprintf(fpc,"// To use this file, try the following session on your Tree T:\n");
      fprintf(fpc,"//\n");
      fprintf(fpc,"// Root > T->Process(\"%s.C\")\n",classname);
      fprintf(fpc,"// Root > T->Process(\"%s.C\",\"some options\")\n",classname);
      fprintf(fpc,"// Root > T->Process(\"%s.C+\")\n",classname);
      fprintf(fpc,"//\n\n");
      fprintf(fpc,"#include \"%s\"\n",thead);
      fprintf(fpc,"#include <TH2.h>\n");
      fprintf(fpc,"#include <TStyle.h>\n");
      fprintf(fpc,"\n");
      
      fprintf(fpc,"\n");
      fprintf(fpc,"void %s::Begin(TTree * /*tree*/)\n",classname);
      fprintf(fpc,"{\n");
      fprintf(fpc,"   // The Begin() function is called at the start of the query.\n");
      fprintf(fpc,"   // When running with PROOF Begin() is only called on the client.\n");
      fprintf(fpc,"   // The tree argument is deprecated (on PROOF 0 is passed).\n");
      fprintf(fpc,"\n");
      fprintf(fpc,"   TString option = GetOption();\n");
      fprintf(fpc,"\n");
      fprintf(fpc,"}\n");
      
      fprintf(fpc,"\n");
      fprintf(fpc,"void %s::SlaveBegin(TTree * /*tree*/)\n",classname);
      fprintf(fpc,"{\n");
      fprintf(fpc,"   // The SlaveBegin() function is called after the Begin() function.\n");
      fprintf(fpc,"   // When running with PROOF SlaveBegin() is called on each slave server.\n");
      fprintf(fpc,"   // The tree argument is deprecated (on PROOF 0 is passed).\n");
      fprintf(fpc,"\n");
      fprintf(fpc,"   TString option = GetOption();\n");
      fprintf(fpc,"\n");
      fprintf(fpc,"}\n");
      
      fprintf(fpc,"\n");
      fprintf(fpc,"Bool_t %s::Process(Long64_t entry)\n",classname);
      fprintf(fpc,"{\n");
      fprintf(fpc,"   // The Process() function is called for each entry in the tree (or possibly\n"
                  "   // keyed object in the case of PROOF) to be processed. The entry argument\n"
                  "   // specifies which entry in the currently loaded tree is to be processed.\n"
                  "   // It can be passed to either %s::GetEntry() or TBranch::GetEntry()\n"
                  "   // to read either all or the required parts of the data. When processing\n"
                  "   // keyed objects with PROOF, the object is already loaded and is available\n"
                  "   // via the fObject pointer.\n"
                  "   //\n"
                  "   // This function should contain the \"body\" of the analysis. It can contain\n"
                  "   // simple or elaborate selection criteria, run algorithms on the data\n"
                  "   // of the event and typically fill histograms.\n"
                  "   //\n"
                  "   // The processing can be stopped by calling Abort().\n"
                  "   //\n"
                  "   // Use fStatus to set the return value of TTree::Process().\n"
                  "   //\n"
                  "   // The return value is currently not used.\n\n", classname);
      fprintf(fpc,"\n");
      fprintf(fpc,"   return kTRUE;\n");
      fprintf(fpc,"}\n");
      
      fprintf(fpc,"\n");
      fprintf(fpc,"void %s::SlaveTerminate()\n",classname);
      fprintf(fpc,"{\n");
      fprintf(fpc,"   // The SlaveTerminate() function is called after all entries or objects\n"
                  "   // have been processed. When running with PROOF SlaveTerminate() is called\n"
                  "   // on each slave server.");
      fprintf(fpc,"\n");
      fprintf(fpc,"\n");
      fprintf(fpc,"}\n");
      
      fprintf(fpc,"\n");
      fprintf(fpc,"void %s::Terminate()\n",classname);
      fprintf(fpc,"{\n");
      fprintf(fpc,"   // The Terminate() function is the last function to be called during\n"
                  "   // a query. It always runs on the client, it can be used to present\n"
                  "   // the results graphically or save the results to file.");
      fprintf(fpc,"\n");
      fprintf(fpc,"\n");
      fprintf(fpc,"}\n");
   }
   Info("MakeClass","Files: %s and %s generated from TTree: %s",thead,tcimp,fTree->GetName());
   delete [] leafStatus;
   delete [] thead;
   delete [] tcimp;
   delete [] treefile;
   fclose(fp);
   fclose(fpc);
   return 0;
}
Int_t TTreePlayer::MakeCode(const char *filename)
{
   char *tfile = new char[1000];
   if (filename) strcpy(tfile,filename);
   else          sprintf(tfile,"%s.C",fTree->GetName());
   FILE *fp = fopen(tfile,"w");
   if (!fp) {
      printf("Cannot open output file:%s\n",tfile);
      return 3;
   }
   char *treefile = new char[1000];
   if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
      strcpy(treefile,fTree->GetDirectory()->GetFile()->GetName());
   } else {
      strcpy(treefile,"Memory Directory");
   }
   
   
   
   Bool_t ischain = fTree->InheritsFrom("TChain");
   TObjArray *leaves = fTree->GetListOfLeaves();
   Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
   TDatime td;
   fprintf(fp,"{\n");
   fprintf(fp,"//////////////////////////////////////////////////////////\n");
   fprintf(fp,"//   This file has been automatically generated \n");
   fprintf(fp,"//     (%s by ROOT version%s)\n",td.AsString(),gROOT->GetVersion());
   if (!ischain) {
      fprintf(fp,"//   from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
      fprintf(fp,"//   found on file: %s\n",treefile);
   } else {
      fprintf(fp,"//   from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
   }
   fprintf(fp,"//////////////////////////////////////////////////////////\n");
   fprintf(fp,"\n");
   fprintf(fp,"\n");
   fprintf(fp,"//Reset ROOT and connect tree file\n");
   fprintf(fp,"   gROOT->Reset();\n");
   if (ischain) {
      fprintf(fp,"\n#ifdef SINGLE_TREE\n");
      fprintf(fp,"   // The following code should be used if you want this code to access\n");
      fprintf(fp,"   // a single tree instead of a chain\n");
   }
   fprintf(fp,"   TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n",treefile);
   fprintf(fp,"   if (!f) {\n");
   fprintf(fp,"      f = new TFile(\"%s\");\n",treefile);
   if (gDirectory != gFile) {
      fprintf(fp,"      f->cd(\"%s\");\n",gDirectory->GetPath());
   }
   fprintf(fp,"   }\n");
   fprintf(fp,"   TTree *%s = (TTree*)gDirectory->Get(\"%s\");\n\n",fTree->GetName(),fTree->GetName());
   if (ischain) {
      fprintf(fp,"#else // SINGLE_TREE\n\n");
      fprintf(fp,"   // The following code should be used if you want this code to access a chain\n");
      fprintf(fp,"   // of trees.\n");
      fprintf(fp,"   TChain *%s = new TChain(\"%s\",\"%s\");\n",
                 fTree->GetName(),fTree->GetName(),fTree->GetTitle());
      TIter next(((TChain*)fTree)->GetListOfFiles());
      TChainElement *element;
      while ((element = (TChainElement*)next())) {
         fprintf(fp,"   %s->Add(\"%s/%s\");\n",fTree->GetName(),element->GetTitle(),element->GetName());
      }
      fprintf(fp,"#endif // SINGLE_TREE\n\n");
   }
   fprintf(fp,"//Declaration of leaves types\n");
   Int_t len, l;
   TLeaf *leafcount;
   TLeafObject *leafobj;
   char *bname;
   const char *headOK  = "   ";
   const char *headcom = " //";
   const char *head;
   char branchname[128];
   for (l=0;l<nleaves;l++) {
      TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
      len = leaf->GetLen();
      leafcount =leaf->GetLeafCount();
      TBranch *branch = leaf->GetBranch();
      if (branch->GetListOfBranches()->GetEntriesFast() > 0) continue;
      if ( branch->GetNleaves() > 1) {
         
         strcpy(branchname,branch->GetName());
         strcat(branchname,".");
         strcat(branchname,leaf->GetTitle());
         if (leafcount) {
            
            char *dim =  (char*)strstr(branchname,"[");
            dim[0] = 0;
         }
      } else {
         if (leafcount) strcpy(branchname,branch->GetName());
         else           strcpy(branchname,leaf->GetTitle());
      }
      char *twodim = (char*)strstr(leaf->GetTitle(),"][");
      bname = branchname;
      while (*bname) {
         if (*bname == '.') *bname='_';
         if (*bname == ':') *bname='_';
         if (*bname == '<') *bname='_';
         if (*bname == '>') *bname='_';
         bname++;
      }
      if (branch->IsA() == TBranchObject::Class()) {
         leafobj = (TLeafObject*)leaf;
         if (leafobj->GetClass()) head = headOK;
         else                     head = headcom;
         fprintf(fp,"%s%-15s *%s = 0;\n",head,leafobj->GetTypeName(), leafobj->GetName());
         continue;
      }
      if (leafcount) {
         len = leafcount->GetMaximum();
         
         
         char *dimInName = (char*) strstr(branchname,"[");
         char *dimensions = 0;
         if ( twodim || dimInName ) {
            int dimlen = 0;
            if (dimInName) dimlen += strlen(dimInName) + 1;
            if (twodim)    dimlen += strlen(twodim) + 1;
            dimensions = new char[dimlen];
            if (dimInName) {
               strcpy(dimensions,dimInName);
               dimInName[0] = 0; 
            } else dimensions[0] = 0;
            if (twodim) strcat(dimensions,(char*)(twodim+1));
         }
         if (dimensions) {
            fprintf(fp,"   %-15s %s[%d]%s;\n",leaf->GetTypeName(), branchname,len,dimensions);
            delete dimensions;
         } else {
            fprintf(fp,"   %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
         }
      } else {
         if (strstr(branchname,"[")) len = 1;
         if (len < 2) fprintf(fp,"   %-15s %s;\n",leaf->GetTypeName(), branchname);
         else         fprintf(fp,"   %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
      }
   }
   fprintf(fp,"\n   // Set branch addresses.\n");
   for (l=0;l<nleaves;l++) {
      TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
      len = leaf->GetLen();
      leafcount =leaf->GetLeafCount();
      TBranch *branch = leaf->GetBranch();
      if ( branch->GetNleaves() > 1) {
         
         strcpy(branchname,branch->GetName());
         strcat(branchname,".");
         strcat(branchname,leaf->GetTitle());
         if (leafcount) {
            
            char *dim =  (char*)strstr(branchname,"[");
            dim[0] = 0;
         }
      } else {
         if (leafcount) strcpy(branchname,branch->GetName());
         else           strcpy(branchname,leaf->GetTitle());
      }
      bname = branchname;
      while (*bname) {
         if (*bname == '.') *bname='_';
         if (*bname == ':') *bname='_';
         if (*bname == '<') *bname='_';
         if (*bname == '>') *bname='_';
         bname++;
      }
      char *brak = strstr(branchname,"[");
      if (brak) *brak = 0;
      head = headOK;
      if (branch->IsA() == TBranchObject::Class()) {
         strcpy(branchname,branch->GetName());
         leafobj = (TLeafObject*)leaf;
         if (!leafobj->GetClass()) head = headcom;
      }
      if (leafcount) len = leafcount->GetMaximum()+1;
      if (len > 1 || brak) fprintf(fp,"%s%s->SetBranchAddress(\"%s\",%s);\n",head,fTree->GetName(),branch->GetName(),branchname);
      else                 fprintf(fp,"%s%s->SetBranchAddress(\"%s\",&%s);\n",head,fTree->GetName(),branch->GetName(),branchname);
   }
   fprintf(fp,"\n//     This is the loop skeleton\n");
   fprintf(fp,"//       To read only selected branches, Insert statements like:\n");
   fprintf(fp,"// %s->SetBranchStatus(\"*\",0);  // disable all branches\n",fTree->GetName());
   fprintf(fp,"// %s->SetBranchStatus(\"branchname\",1);  // activate branchname\n",GetName());
   fprintf(fp,"\n   Long64_t nentries = %s->GetEntries();\n",fTree->GetName());
   fprintf(fp,"\n   Long64_t nbytes = 0;\n");
   fprintf(fp,"//   for (Long64_t i=0; i<nentries;i++) {\n");
   fprintf(fp,"//      nbytes += %s->GetEntry(i);\n",fTree->GetName());
   fprintf(fp,"//   }\n");
   fprintf(fp,"}\n");
   printf("Macro: %s generated from Tree: %s\n",tfile,fTree->GetName());
   delete [] tfile;
   delete [] treefile;
   fclose(fp);
   return 0;
}
Int_t TTreePlayer::MakeProxy(const char *proxyClassname,
                             const char *macrofilename, const char *cutfilename,
                             const char *option, Int_t maxUnrolling)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   if (macrofilename==0 || strlen(macrofilename)==0 ) {
      
      Error("MakeProxy","A file name for the user script is required");
      return 0;
   }
   TTreeProxyGenerator gp(fTree,macrofilename,cutfilename,proxyClassname,option,maxUnrolling);
   return 0;
}
TPrincipal *TTreePlayer::Principal(const char *varexp, const char *selection, Option_t *option, Long64_t nentries, Long64_t firstentry)
{
   TTreeFormula **var;
   TString *cnames;
   TString onerow;
   TString opt = option;
   opt.ToLower();
   TPrincipal *principal = 0;
   Long64_t entry,entryNumber;
   Int_t i,nch;
   Int_t *index = 0;
   Int_t ncols = 8;   
   TObjArray *leaves = fTree->GetListOfLeaves();
   Int_t nleaves = leaves->GetEntriesFast();
   if (nleaves < ncols) ncols = nleaves;
   nch = varexp ? strlen(varexp) : 0;
   nentries = GetEntriesToProcess(firstentry, nentries);
   TTreeFormula *select = 0;
   if (strlen(selection)) {
      select = new TTreeFormula("Selection",selection,fTree);
      if (!select) return principal;
      if (!select->GetNdim()) { delete select; return principal; }
      fFormulaList->Add(select);
   }
   int allvar = 0;
   if (!strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
   if (nch == 0 || allvar) {
      cnames = new TString[ncols];
      for (i=0;i<ncols;i++) {
         cnames[i] = ((TLeaf*)leaves->At(i))->GetName();
      }
   } else {
      ncols = 1;
      onerow = varexp;
      for (i=0;i<onerow.Length();i++)  if (onerow[i] == ':') ncols++;
      cnames = new TString[ncols];
      index  = new Int_t[ncols+1];
      fSelector->MakeIndex(onerow,index);
      for (i=0;i<ncols;i++) {
         cnames[i] = fSelector->GetNameByIndex(onerow,index,i);
      }
   }
   var = new TTreeFormula* [ncols];
   Double_t *xvars = new Double_t[ncols];
   for (i=0;i<ncols;i++) {
      var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
      fFormulaList->Add(var[i]);
   }
   TTreeFormulaManager *manager=0;
   if (fFormulaList->LastIndex()>=0) {
      manager = new TTreeFormulaManager;
      for(i=0;i<=fFormulaList->LastIndex();i++) {
         manager->Add((TTreeFormula*)fFormulaList->At(i));
      }
      manager->Sync();
   }
   if (opt.Contains("n")) principal = new TPrincipal(ncols, "n");
   else                   principal = new TPrincipal(ncols);
   fSelectedRows = 0;
   Int_t tnumber = -1;
   for (entry=firstentry;entry<firstentry+nentries;entry++) {
      entryNumber = fTree->GetEntryNumber(entry);
      if (entryNumber < 0) break;
      Long64_t localEntry = fTree->LoadTree(entryNumber);
      if (localEntry < 0) break;
      if (tnumber != fTree->GetTreeNumber()) {
         tnumber = fTree->GetTreeNumber();
         if (manager) manager->UpdateFormulaLeaves();
      }
      int ndata = 1;
      if (manager && manager->GetMultiplicity()) {
         ndata = manager->GetNdata();
      }
      for(int inst=0;inst<ndata;inst++) {
         Bool_t loaded = kFALSE;
         if (select) {
            if (select->EvalInstance(inst) == 0) {
               continue;
            }
         }
         if (inst==0) loaded = kTRUE;
         else if (!loaded) {
            
            
            for (i=0;i<ncols;i++) {
               var[i]->EvalInstance(0);
            }
            loaded = kTRUE;
         }
         for (i=0;i<ncols;i++) {
            xvars[i] = var[i]->EvalInstance(inst);
         }
         principal->AddRow(xvars);
      }
   }
   
   if (opt.Contains("p")) {
      principal->MakePrincipals(); 
      if (opt.Contains("d")) principal->Print();
      if (opt.Contains("h")) principal->MakeHistograms();
      if (opt.Contains("c")) principal->MakeCode();
   }
   fFormulaList->Clear();
   delete [] var;
   delete [] cnames;
   delete [] index;
   delete [] xvars;
   return principal;
}
Long64_t TTreePlayer::Process(const char *filename,Option_t *option, Long64_t nentries, Long64_t firstentry)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   DeleteSelectorFromFile(); 
   
   
   TString opt(option);
   TString file(filename);
   TSelector *selector = TSelector::GetSelector(file);
   if (!selector) return -1;
   fSelectorFromFile = selector;
   fSelectorClass    = selector->IsA();
   Long64_t nsel = Process(selector,opt,nentries,firstentry);
   return nsel;
}
Long64_t TTreePlayer::Process(TSelector *selector,Option_t *option, Long64_t nentries, Long64_t firstentry)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   nentries = GetEntriesToProcess(firstentry, nentries);
   TDirectory::TContext ctxt(0);
   fTree->SetNotify(selector);
   selector->SetOption(option);
   selector->Begin(fTree);       
   selector->SlaveBegin(fTree);  
   if (selector->Version() >= 2)
      selector->Init(fTree);
   selector->Notify();
   if (gMonitoringWriter)
      gMonitoringWriter->SendProcessingStatus("STARTED",kTRUE);
   if (selector->GetAbort() != TSelector::kAbortProcess
       && (selector->Version() != 0 || selector->GetStatus() != -1)) {
      Long64_t readbytesatstart = 0;
      readbytesatstart = TFile::GetFileBytesRead();
      
      TTreeCache *tpf = 0;
      TFile *curfile = fTree->GetCurrentFile();
      if (curfile && fTree->GetCacheSize() > 0) {
         tpf = (TTreeCache*)curfile->GetCacheRead();
         if (tpf)
            tpf->SetEntryRange(firstentry,firstentry+nentries);
         else {
            fTree->SetCacheSize(fTree->GetCacheSize());
            tpf = (TTreeCache*)curfile->GetCacheRead();
            if (tpf) tpf->SetEntryRange(firstentry,firstentry+nentries);
         }
      }
      
      TProcessEventTimer *timer = 0;
      Int_t interval = fTree->GetTimerInterval();
      if (!gROOT->IsBatch() && interval)
         timer = new TProcessEventTimer(interval);
      
      Long_t entry, entryNumber, localEntry;
      Bool_t useCutFill = selector->Version() == 0;
      
      if (gMonitoringWriter)
         gMonitoringWriter->SendProcessingProgress(0,0,kTRUE);
      
      
      
      fSelectorUpdate = selector;
      UpdateFormulaLeaves();
      for (entry=firstentry;entry<firstentry+nentries;entry++) {
         entryNumber = fTree->GetEntryNumber(entry);
         if (entryNumber < 0) break;
         if (timer && timer->ProcessEvents()) break;
         if (gROOT->IsInterrupted()) break;
         localEntry = fTree->LoadTree(entryNumber);
         if (localEntry < 0) break;
         if(useCutFill) {
            if (selector->ProcessCut(localEntry))
               selector->ProcessFill(localEntry); 
         } else {
            selector->Process(localEntry);        
         }
         if (gMonitoringWriter)
            gMonitoringWriter->SendProcessingProgress((entry-firstentry),TFile::GetFileBytesRead()-readbytesatstart,kTRUE);
         if (selector->GetAbort() == TSelector::kAbortProcess) break;
      }
      delete timer;
      
      {
         TFile *curfile = fTree->GetCurrentFile();
         if (curfile && fTree->GetCacheSize() > 0) {
            tpf = (TTreeCache*)curfile->GetCacheRead();
            if (tpf) tpf->SetEntryRange(0,0);
         }
      }
   }
   if (selector->Version() != 0 || selector->GetStatus() != -1) {
      selector->SlaveTerminate();   
      selector->Terminate();        
   }
   fSelectorUpdate = 0;
   if (gMonitoringWriter)
      gMonitoringWriter->SendProcessingStatus("DONE");
   return selector->GetStatus();
}
void TTreePlayer::RecursiveRemove(TObject *obj)
{
   if (fHistogram == obj) fHistogram = 0;
}
Long64_t TTreePlayer::Scan(const char *varexp, const char *selection,
                           Option_t * option,
                           Long64_t nentries, Long64_t firstentry)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   TString opt = option;
   opt.ToLower();
   UInt_t ui;
   UInt_t lenmax = 0;
   UInt_t colDefaultSize = 9;
   UInt_t colPrecision = 9;
   vector<TString> colFormats;
   vector<Int_t> colSizes;
   if (opt.Contains("lenmax=")) {
      int start = opt.Index("lenmax=");
      int numpos = start + strlen("lenmax=");
      int numlen = 0;
      int len = opt.Length();
      while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
      TString num = opt(numpos,numlen);
      opt.Remove(start,strlen("lenmax")+numlen);
      lenmax = atoi(num.Data());
   }
   if (opt.Contains("colsize=")) {
      int start = opt.Index("colsize=");
      int numpos = start + strlen("colsize=");
      int numlen = 0;
      int len = opt.Length();
      while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
      TString num = opt(numpos,numlen);
      opt.Remove(start,strlen("size")+numlen);
      colDefaultSize = atoi(num.Data());
      colPrecision = colDefaultSize;
      if (colPrecision>18) colPrecision = 18;
   }
   if (opt.Contains("precision=")) {
      int start = opt.Index("precision=");
      int numpos = start + strlen("precision=");
      int numlen = 0;
      int len = opt.Length();
      while( (numpos+numlen<len) && isdigit(opt[numpos+numlen]) ) numlen++;
      TString num = opt(numpos,numlen);
      opt.Remove(start,strlen("precision")+numlen);
      colPrecision = atoi(num.Data());
   }
   TString defFormat = Form("%d.%d",colDefaultSize,colPrecision);
   if (opt.Contains("col=")) {
      int start = opt.Index("col=");
      int numpos = start + strlen("col=");
      int numlen = 0;
      int len = opt.Length();
      while( (numpos+numlen<len) &&
             (isdigit(opt[numpos+numlen])
              || opt[numpos+numlen] == 'c'
              || opt[numpos+numlen] == 'd'
              || opt[numpos+numlen] == 'i'
              || opt[numpos+numlen] == 'o'
              || opt[numpos+numlen] == 'x'
              || opt[numpos+numlen] == 'X'
              || opt[numpos+numlen] == 'u'
              || opt[numpos+numlen] == 'f'
              || opt[numpos+numlen] == 'e'
              || opt[numpos+numlen] == 'E'
              || opt[numpos+numlen] == 'g'
              || opt[numpos+numlen] == 'G'
              || opt[numpos+numlen] == 'l'
              || opt[numpos+numlen] == 'L'
              || opt[numpos+numlen] == 'h'
              || opt[numpos+numlen] == '#'
              || opt[numpos+numlen]=='.'
              || opt[numpos+numlen]==':')) numlen++;
      TString flist = opt(numpos,numlen);
      opt.Remove(start,strlen("col")+numlen);
      int i = 0;
      while(i<flist.Length() && flist[i]==':') {
         colFormats.push_back(defFormat);
         colSizes.push_back(colDefaultSize);
         ++i;
      }
      for(; i<flist.Length(); ++i) {
         int next = flist.Index(":",i);
         if (next==i) {
            colFormats.push_back(defFormat);
         } else if (next==kNPOS) {
            colFormats.push_back(flist(i,flist.Length()-i));
            i = flist.Length();
         } else {
            colFormats.push_back(flist(i,next-i));
            i = next;
         }
         UInt_t siz = atoi(colFormats[colFormats.size()-1].Data());
         colSizes.push_back( siz ? siz : colDefaultSize );
      }
   }
   TTreeFormula **var;
   TString *cnames;
   TString onerow;
   Long64_t entry,entryNumber;
   Int_t i,nch;
   Int_t *index = 0;
   UInt_t ncols = 8;   
   ofstream out;
   Int_t lenfile = 0;
   char * fname = 0;
   if (fScanRedirect) {
      fTree->SetScanField(0);  
      fname = (char *) fScanFileName;
      if (!fname) fname = (char*)"";
      lenfile = strlen(fname);
      if (!lenfile) {
         Int_t nch = strlen(fTree->GetName());
         fname = new char[nch+10];
         strcpy(fname, fTree->GetName());
         strcat(fname, "-scan.dat");
      }
      out.open(fname, ios::out);
      if (!out.good ()) {
         if (!lenfile) delete [] fname;
         Error("Scan","Can not open file for redirection");
         return 0;
      }
   }
   TObjArray *leaves = fTree->GetListOfLeaves();
   if (leaves==0) return 0;
   UInt_t nleaves = leaves->GetEntriesFast();
   if (nleaves < ncols) ncols = nleaves;
   nch = varexp ? strlen(varexp) : 0;
   nentries = GetEntriesToProcess(firstentry, nentries);
   TTreeFormula        *select  = 0;
   if (selection && strlen(selection)) {
      select = new TTreeFormula("Selection",selection,fTree);
      if (!select) return -1;
      if (!select->GetNdim()) { delete select; return -1; }
      fFormulaList->Add(select);
   }
   int allvar = 0;
   if (!strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
   if (nch == 0 || allvar) {
      cnames = new TString[ncols];
      UInt_t ncs = ncols;
      ncols = 0;
      for (ui=0;ui<ncs;++ui) {
         TLeaf *lf = (TLeaf*)leaves->At(ui);
         if (lf->GetBranch()->GetListOfBranches()->GetEntries() > 0) continue;
         cnames[ncols] = lf->GetName();
         ncols++;
      }
   } else {
      ncols = 1;
      onerow = varexp;
      for (i=0;i<onerow.Length();i++) {
         if (onerow[i] == ':') {
            if (onerow[i+1] == ':') ++i;
            else ncols++;
         }
      }
      cnames = new TString[ncols];
      index  = new Int_t[ncols+1];
      fSelector->MakeIndex(onerow,index);
      for (ui=0;ui<ncols;ui++) {
         cnames[ui] = fSelector->GetNameByIndex(onerow,index,ui);
      }
   }
   var = new TTreeFormula* [ncols];
   for(ui=colFormats.size();ui<ncols;++ui) {
      colFormats.push_back(defFormat);
      colSizes.push_back(colDefaultSize);
   }
   for (ui=0;ui<ncols;ui++) {
      var[ui] = new TTreeFormula("Var1",cnames[ui].Data(),fTree);
      fFormulaList->Add(var[ui]);
   }
   TTreeFormulaManager *manager=0;
   Bool_t hasArray = kFALSE;
   Bool_t forceDim = kFALSE;
   if (fFormulaList->LastIndex()>=0) {
      if (select) {
         if (select->GetManager()->GetMultiplicity() > 0 ) {
            manager = new TTreeFormulaManager;
            for(i=0;i<=fFormulaList->LastIndex();i++) {
               manager->Add((TTreeFormula*)fFormulaList->At(i));
            }
            manager->Sync();
         }
      }
      for(i=0;i<=fFormulaList->LastIndex();i++) {
         TTreeFormula *form = ((TTreeFormula*)fFormulaList->At(i));
         switch( form->GetManager()->GetMultiplicity() ) {
            case  1:
            case  2:
               hasArray = kTRUE;
            case -1:
               forceDim = kTRUE;
               break;
            case  0:
               break;
         }
      }
   }
   onerow = "***********";
   if (hasArray) onerow += "***********";
   for (ui=0;ui<ncols;ui++) {
      TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
      onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
   }
   if (fScanRedirect)
      out<<onerow.Data()<<"*"<<endl;
   else
      printf("%s*\n",onerow.Data());
   onerow = "*    Row   ";
   if (hasArray) onerow += "* Instance ";
   for (ui=0;ui<ncols;ui++) {
      TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
      onerow += Form(numbFormat.Data(),var[ui]->PrintValue(-1));
   }
   if (fScanRedirect)
      out<<onerow.Data()<<"*"<<endl;
   else
      printf("%s*\n",onerow.Data());
   onerow = "***********";
   if (hasArray) onerow += "***********";
   for (ui=0;ui<ncols;ui++) {
      TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
      onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
   }
   if (fScanRedirect)
      out<<onerow.Data()<<"*"<<endl;
   else
      printf("%s*\n",onerow.Data());
   fSelectedRows = 0;
   Int_t tnumber = -1;
   Bool_t exitloop = kFALSE;
   for (entry=firstentry;
        entry<(firstentry+nentries) && !exitloop;
        entry++) {
      entryNumber = fTree->GetEntryNumber(entry);
      if (entryNumber < 0) break;
      Long64_t localEntry = fTree->LoadTree(entryNumber);
      if (localEntry < 0) break;
      if (tnumber != fTree->GetTreeNumber()) {
         tnumber = fTree->GetTreeNumber();
         if (manager) manager->UpdateFormulaLeaves();
         else {
            for(i=0;i<=fFormulaList->LastIndex();i++) {
               ((TTreeFormula*)fFormulaList->At(i))->UpdateFormulaLeaves();
            }
         }
      }
      int ndata = 1;
      if (forceDim) {
         if (manager) {
            ndata = manager->GetNdata(kTRUE);
         } else {
            
            for (ui=0;ui<ncols;ui++) {
               if (ndata < var[ui]->GetNdata() ) {
                  ndata = var[ui]->GetNdata();
               }
            }
            if (select && select->GetNdata()==0) ndata = 0;
         }
      }
      if (lenmax && ndata>(int)lenmax) ndata = lenmax;
      Bool_t loaded = kFALSE;
      for(int inst=0;inst<ndata;inst++) {
         if (select) {
            if (select->EvalInstance(inst) == 0) {
               continue;
            }
         }
         if (inst==0) loaded = kTRUE;
         else if (!loaded) {
            
            
            for (ui=0;ui<ncols;ui++) {
               var[ui]->EvalInstance(0);
            }
            loaded = kTRUE;
         }
         onerow = Form("* %8lld ",entryNumber);
         if (hasArray) {
            onerow += Form("* %8d ",inst);
         }
         for (ui=0;ui<ncols;++ui) {
            TString numbFormat = Form("* %%%d.%ds ",colSizes[ui],colSizes[ui]);
            if (var[ui]->GetNdim()) onerow += Form(numbFormat.Data(),var[ui]->PrintValue(0,inst,colFormats[ui].Data()));
            else {
               TString emptyForm = Form("* %%%dc ",colSizes[ui]);
               onerow += Form(emptyForm.Data(),' ');
            }
         }
         fSelectedRows++;
         if (fScanRedirect)
            out<<onerow.Data()<<"*"<<endl;
         else
            printf("%s*\n",onerow.Data());
         if (fTree->GetScanField() > 0 && fSelectedRows > 0) {
            if (fSelectedRows%fTree->GetScanField() == 0) {
               fprintf(stderr,"Type <CR> to continue or q to quit ==> ");
               int answer, readch;
               readch = getchar();
               answer = readch;
               while (readch != '\n' && readch != EOF) readch = getchar();
               if (answer == 'q' || answer == 'Q') {
                  exitloop = kTRUE;
                  break;
               }
            }
         }
      }
   }
   onerow = "***********";
   if (hasArray) onerow += "***********";
   for (ui=0;ui<ncols;ui++) {
      TString starFormat = Form("*%%%d.%ds",colSizes[ui]+2,colSizes[ui]+2);
      onerow += Form(starFormat.Data(),var[ui]->PrintValue(-2));
   }
   if (fScanRedirect)
      out<<onerow.Data()<<"*"<<endl;
   else
      printf("%s*\n",onerow.Data());
   if (select) Printf("==> %lld selected %s", fSelectedRows,
                      fSelectedRows == 1 ? "entry" : "entries");
   if (fScanRedirect) printf("File <%s> created\n", fname);
   fFormulaList->Clear();
   
   delete [] var;
   delete [] cnames;
   delete [] index;
   return fSelectedRows;
}
TSQLResult *TTreePlayer::Query(const char *varexp, const char *selection,
                               Option_t *, Long64_t nentries, Long64_t firstentry)
{
   
   
   
   
   
   TTreeFormula **var;
   TString *cnames;
   TString onerow;
   Long64_t entry,entryNumber;
   Int_t i,nch;
   Int_t *index = 0;
   Int_t ncols = 8;   
   TObjArray *leaves = fTree->GetListOfLeaves();
   Int_t nleaves = leaves->GetEntriesFast();
   if (nleaves < ncols) ncols = nleaves;
   nch = varexp ? strlen(varexp) : 0;
   nentries = GetEntriesToProcess(firstentry, nentries);
   
   TTreeFormula *select = 0;
   if (strlen(selection)) {
      select = new TTreeFormula("Selection",selection,fTree);
      if (!select) return 0;
      if (!select->GetNdim()) { delete select; return 0; }
      fFormulaList->Add(select);
   }
   
   int allvar = 0;
   if (!strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
   if (nch == 0 || allvar) {
      cnames = new TString[ncols];
      for (i=0;i<ncols;i++) {
         cnames[i] = ((TLeaf*)leaves->At(i))->GetName();
      }
   } else {
      
      ncols = 1;
      onerow = varexp;
      for (i=0;i<onerow.Length();i++)  if (onerow[i] == ':') ncols++;
      cnames = new TString[ncols];
      index  = new Int_t[ncols+1];
      fSelector->MakeIndex(onerow,index);
      for (i=0;i<ncols;i++) {
         cnames[i] = fSelector->GetNameByIndex(onerow,index,i);
      }
   }
   var = new TTreeFormula* [ncols];
   
   for (i=0;i<ncols;i++) {
      var[i] = new TTreeFormula("Var1",cnames[i].Data(),fTree);
      fFormulaList->Add(var[i]);
   }
   
   TTreeResult *res = new TTreeResult(ncols);
   for (i = 0; i < ncols; i++) {
      res->AddField(i, var[i]->PrintValue(-1));
   }
   
   const char *aresult;
   Int_t len;
   char *arow = new char[ncols*50];
   fSelectedRows = 0;
   Int_t tnumber = -1;
   Int_t *fields = new Int_t[ncols];
   for (entry=firstentry;entry<firstentry+nentries;entry++) {
      entryNumber = fTree->GetEntryNumber(entry);
      if (entryNumber < 0) break;
      Long64_t localEntry = fTree->LoadTree(entryNumber);
      if (localEntry < 0) break;
      if (tnumber != fTree->GetTreeNumber()) {
         tnumber = fTree->GetTreeNumber();
         for (i=0;i<ncols;i++) var[i]->UpdateFormulaLeaves();
      }
      if (select) {
         select->GetNdata();
         if (select->EvalInstance(0) == 0) continue;
      }
      for (i=0;i<ncols;i++) {
         aresult = var[i]->PrintValue(0);
         len = strlen(aresult)+1;
         if (i == 0) {
            memcpy(arow,aresult,len);
            fields[i] = len;
         } else {
            memcpy(arow+fields[i-1],aresult,len);
            fields[i] = fields[i-1] + len;
         }
      }
      res->AddRow(new TTreeRow(ncols,fields,arow));
      fSelectedRows++;
   }
   
   fFormulaList->Clear();
   delete [] fields;
   delete [] arow;
   delete [] var;
   delete [] cnames;
   delete [] index;
   return res;
}
void TTreePlayer::SetEstimate(Long64_t n)
{
   fSelector->SetEstimate(n);
}
void TTreePlayer::StartViewer(Int_t ww, Int_t wh)
{
   if (gROOT->IsBatch()) {
      Warning("StartViewer", "viewer cannot run in batch mode");
      return;
   }
   if (ww || wh) { }   
   TPluginHandler *h;
   if ((h = gROOT->GetPluginManager()->FindHandler("TVirtualTreeViewer"))) {
      if (h->LoadPlugin() == -1)
         return;
      h->ExecPlugin(1,fTree);
   }
}
void TreeUnbinnedFitLikelihood(Int_t & , Double_t * ,
                               Double_t &r, Double_t *par, Int_t )
{
   
   Double_t x[3];
   TF1 *fitfunc = (TF1*)tFitter->GetObjectFit();
   fitfunc->InitArgs(x,par);
   Long64_t n = gTree->GetSelectedRows();
   Double_t  *data1 = gTree->GetV1();
   Double_t  *data2 = gTree->GetV2();
   Double_t  *data3 = gTree->GetV3();
   Double_t *weight = gTree->GetW();
   Double_t logEpsilon = -230;   
   Double_t logL = 0.0, prob;
   
   for(Long64_t i = 0; i < n; i++) {
      if (weight[i] <= 0) continue;
      x[0] = data1[i];
      if (data2) x[1] = data2[i];
      if (data3) x[2] = data3[i];
      prob = fitfunc->EvalPar(x,par);
      
      if(prob > 0) logL += TMath::Log(prob) * weight[i];
      else         logL += logEpsilon * weight[i];
   }
   r = -2*logL;
}
Int_t TTreePlayer::UnbinnedFit(const char *funcname ,const char *varexp, const char *selection,Option_t *option ,Long64_t nentries, Long64_t firstentry)
{
 
   Int_t npar,nvpar,nparx;
   Int_t i;
   Int_t fitResult = 0;
   Double_t par, we, al, bl;
   Double_t eplus,eminus,eparab,globcc,amin,edm,errdef,werr;
   Double_t arglist[10];
   
   TF1* fitfunc = (TF1*)gROOT->GetFunction(funcname);
   if (!fitfunc) { Error("UnbinnedFit", "Unknown function: %s",funcname); return 0; }
   npar = fitfunc->GetNpar();
   if (npar <=0) { Error("UnbinnedFit", "Illegal number of parameters = %d",npar); return 0; }
   
   
   
   Long64_t oldEstimate = fTree->GetEstimate();
   Long64_t nent = fTree->GetEntriesFriend();
   fTree->SetEstimate(TMath::Min(nent,nentries));
   Long64_t nsel = DrawSelect(varexp, selection, "goff", nentries, firstentry);
   
   
   Long64_t nrows = GetSelectedRows();
   if (nrows <= 0) {
      Error("UnbinnedFit", "Cannot fit: no entries selected");
      return -1;
   }
   
   Int_t ndim = GetDimension();
   if (ndim != fitfunc->GetNdim()) {
      Error("UnbinnedFit", "Function dimension=%d not equal to expression dimension=%d",fitfunc->GetNdim(),ndim);
      return -2;
   }
   
   gTree = fTree;
   
   tFitter = TVirtualFitter::Fitter(fTree);
   tFitter->Clear();
   tFitter->SetFCN(TreeUnbinnedFitLikelihood);
   tFitter->SetObjectFit(fitfunc);
   TString opt = option;
   opt.ToLower();
   
   if (!opt.Contains("v")) {
      arglist[0] = -1;
      tFitter->ExecuteCommand("SET PRINT", arglist,1);
      arglist[0] = 0;
      tFitter->ExecuteCommand("SET NOW",   arglist,0);
   }
   
   Double_t min, max;
   for(i = 0; i < npar; i++) {
      fitfunc->GetParLimits(i, min, max);
      Double_t we = 0.1*TMath::Abs(max-min);
      if (we == 0) we = 0.3*TMath::Abs(fitfunc->GetParameter(i));
      if (we == 0) we = 1;
      if(min < max) {
         tFitter->SetParameter(i, fitfunc->GetParName(i),
                               fitfunc->GetParameter(i),
                               we, min, max);
      } else {
         tFitter->SetParameter(i, fitfunc->GetParName(i),
                               fitfunc->GetParameter(i),
                               we, 0, 0);
      }
      
      if(max <= min && min > 0.0) {
         tFitter->FixParameter(i);
      }
   }  
   
   if (opt.Contains("v")) {
      arglist[0] = 0;
      tFitter->ExecuteCommand("SET PRINT", arglist,1);
   }
   
   
   arglist[0] = 1;
   tFitter->ExecuteCommand("SET ERR",arglist,1);
   
   arglist[0] = TVirtualFitter::GetMaxIterations();
   arglist[1] = 1;
   fitResult += tFitter->ExecuteCommand("MIGRAD", arglist, 2);
   if (opt.Contains("m")) {
      fitResult += 1000*tFitter->ExecuteCommand("IMPROVE",arglist,0);
   }
   if (opt.Contains("e")) {
      fitResult +=  100*tFitter->ExecuteCommand("HESSE",arglist,0);
      fitResult +=   10*tFitter->ExecuteCommand("MINOS",arglist,0);
   }
   fitfunc->SetNDF(fitfunc->GetNumberFitPoints()-npar);
   
   char parName[50];
   for (i=0;i<npar;i++) {
      tFitter->GetParameter(i,parName, par,we,al,bl);
      if (opt.Contains("e")) werr = we;
      else {
         tFitter->GetErrors(i,eplus,eminus,eparab,globcc);
         if (eplus > 0 && eminus < 0) werr = 0.5*(eplus-eminus);
         else                         werr = we;
      }
      fitfunc->SetParameter(i,par);
      fitfunc->SetParError(i,werr);
   }
   tFitter->GetStats(amin,edm,errdef,nvpar,nparx);
   
   if (!opt.Contains("q")) {
      amin = 0;
      tFitter->PrintResults(1, amin);
   }
   
   fTree->SetEstimate(oldEstimate);
   
   
   
   if (opt.Contains("d")) {
      if (fHistogram->GetDimension() < 2) {
         TH1 *hf = (TH1*)fHistogram->Clone("unbinnedFit");
         hf->SetLineWidth(3);
         hf->Reset();
         Int_t nbins = fHistogram->GetXaxis()->GetNbins();
         Double_t norm = ((Double_t)nsel)*fHistogram->GetXaxis()->GetBinWidth(1);
         for (Int_t bin=1;bin<=nbins;bin++) {
            Double_t func = norm*fitfunc->Eval(hf->GetBinCenter(bin));
            hf->SetBinContent(bin,func);
         }
         fHistogram->GetListOfFunctions()->Add(hf,"lsame");
      }
      fHistogram->Draw();
   }
   return fitResult;
}
void TTreePlayer::UpdateFormulaLeaves()
{
   
   
   
   if (fSelector)  fSelector->Notify();
   if (fSelectorUpdate){
      
      
      if (fSelector==fSelectorUpdate) {
         
         TObject *obj = fSelector->GetObject();
         if (obj){
            if (fSelector->GetObject()->InheritsFrom(TEntryList::Class())){
               ((TEntryList*)fSelector->GetObject())->SetTree(fTree->GetTree());
            }
         }
      }   
      if (fSelectorFromFile==fSelectorUpdate) {
         TIter next(fSelectorFromFile->GetOutputList());
         TEntryList *elist=0;
         while ((elist=(TEntryList*)next())){
            if (elist->InheritsFrom(TEntryList::Class())){
               elist->SetTree(fTree->GetTree());
            }
         }
      }
   }
   if (fFormulaList->GetSize()) {
      TObjLink *lnk = fFormulaList->FirstLink();
      while (lnk) {
         lnk->GetObject()->Notify();
         lnk = lnk->Next();
      }
   }
}
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.