#include <string.h>
#include <stdio.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 "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"
#include "TStyle.h"
#include "HFitInterface.h"
#include "Foption.h"
#include "Fit/UnBinData.h"
#include "Math/MinimizerOptions.h"
R__EXTERN Foption_t Foption;
TVirtualFitter *tFitter=0;
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::Class())) {
((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;
delete tree;
return 0;
}
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","%s",Form("Will process tree/chain using %s",selname.Data()));
Long64_t result = fTree->Process(selname,option,nentries,firstentry);
fTree->SetNotify(0);
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("Min$")<0 && possibleFilename.Index("Max$")<0
&& possibleFilename.Index("MinIf$")<0 && possibleFilename.Index("MaxIf$")<0
&& possibleFilename.Index("Iteration$")<0 && possibleFilename.Index("Sum$")<0
&& possibleFilename.Index(">")<0 && possibleFilename.Index("<")<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("Min$")<0 && possibleFilename.Index("Max$")<0
&& possibleFilename.Index("MinIf$")<0 && possibleFilename.Index("MaxIf$")<0
&& possibleFilename.Index("Iteration$")<0 && possibleFilename.Index("Sum$")<0
&& possibleFilename.Index(">")<0 && possibleFilename.Index("<")<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);
TString opt = option;
opt.ToLower();
Bool_t optpara = kFALSE;
Bool_t optcandle = kFALSE;
Bool_t optgl5d = kFALSE;
Bool_t optnorm = kFALSE;
if (opt.Contains("norm")) {optnorm = kTRUE; opt.ReplaceAll("norm",""); opt.ReplaceAll(" ","");}
if (opt.Contains("para")) optpara = kTRUE;
if (opt.Contains("candle")) optcandle = kTRUE;
if (opt.Contains("gl5d")) optgl5d = kTRUE;
Bool_t pgl = gStyle->GetCanvasPreferGL();
if (optgl5d) {
fTree->SetEstimate(fTree->GetEntries());
if (!gPad) {
if (pgl == kFALSE) gStyle->SetCanvasPreferGL(kTRUE);
gROOT->ProcessLineFast("new TCanvas();");
}
}
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();
Bool_t draw = kFALSE;
if (!drawflag && !opt.Contains("goff")) draw = kTRUE;
if (!optcandle && !optpara) fHistogram = (TH1*)fSelector->GetObject();
if (optnorm) {
Double_t sumh= fHistogram->GetSumOfWeights();
if (sumh != 0) fHistogram->Scale(1./sumh);
}
if (fDimension == 1) {
if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("X");
if (draw) fHistogram->Draw(opt.Data());
} else if (fDimension == 2 && !(optpara||optcandle)) {
if (fSelector->GetVar1()->IsInteger()) fHistogram->LabelsDeflate("Y");
if (fSelector->GetVar2()->IsInteger()) fHistogram->LabelsDeflate("X");
if (action == 4) {
if (draw) fHistogram->Draw(opt.Data());
} 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(opt.Data());
} else {
if (fSelector->GetOldHistogram() && draw) fHistogram->Draw(opt.Data());
}
}
} else if (fDimension == 3 && !(optpara||optcandle)) {
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(opt.Data());
} else if (action == 33) {
if (draw) {
if (opt.Contains("z")) fHistogram->Draw("func z");
else fHistogram->Draw("func");
}
} else {
Int_t noscat = opt.Length();
if (opt.Contains("same")) noscat -= 4;
if (noscat) {
if (draw) fHistogram->Draw(opt.Data());
} else {
if (fSelector->GetOldHistogram() && draw) fHistogram->Draw(opt.Data());
}
}
} else if (fDimension == 4 && !(optpara||optcandle)) {
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(opt.Data());
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();
}
} else if (optpara || optcandle) {
if (draw) {
TObject* para = fSelector->GetObject();
TObject *enlist = gDirectory->FindObject("enlist");
fTree->Draw(">>enlist",selection,"entrylist",nentries,firstentry);
gROOT->ProcessLineFast(Form("TParallelCoord::SetEntryList((TParallelCoord*)0x%lx,(TEntryList*)0x%lx)",
(ULong_t)para, (ULong_t)enlist));
}
} else if (optgl5d) {
gROOT->ProcessLineFast(Form("(new TGL5DDataSet((TTree *)0x%lx))->Draw(\"%s\");", (ULong_t)fTree, opt.Data()));
gStyle->SetCanvasPreferGL(pgl);
}
if (fHistogram) fHistogram->ResetBit(TH1::kCanRebin);
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 = option ? strlen(option) + 10 : 10;
char *opt = new char[nch];
if (option) strlcpy(opt,option,nch-1);
else strlcpy(opt,"goff",5);
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);
fTree->SetNotify(0);
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, Bool_t replace = kTRUE)
{
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;
}
}
}
if (replace) {
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='_';
if (*bname == '>') *bname='_';
bname++;
}
}
return branchname;
}
Int_t TTreePlayer::MakeClass(const char *classname, const char *option)
{
TString opt = option;
opt.ToLower();
if (!classname) classname = fTree->GetName();
TString thead;
thead.Form("%s.h", classname);
FILE *fp = fopen(thead, "w");
if (!fp) {
Error("MakeClass","cannot open output file %s", thead.Data());
return 3;
}
TString tcimp;
tcimp.Form("%s.C", classname);
FILE *fpc = fopen(tcimp, "w");
if (!fpc) {
Error("MakeClass","cannot open output file %s", tcimp.Data());
fclose(fp);
return 3;
}
TString treefile;
if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
treefile = fTree->GetDirectory()->GetFile()->GetName();
} else {
treefile = "Memory Directory";
}
Bool_t ischain = fTree->InheritsFrom(TChain::Class());
Bool_t isHbook = fTree->InheritsFrom("THbookTree");
if (isHbook)
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.Data());
} 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 l;
fprintf(fp,"\n// Header file for the classes stored in the TTree if any.\n");
TList listOfHeaders;
listOfHeaders.SetOwner();
for (l=0;l<nleaves;l++) {
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
TBranch *branch = leaf->GetBranch();
TClass *cl = TClass::GetClass(branch->GetClassName());
if (cl && cl->IsLoaded() && !listOfHeaders.FindObject(cl->GetName())) {
const char *declfile = cl->GetDeclFileName();
if (declfile && declfile[0]) {
static const char *precstl = "prec_stl/";
static const unsigned int precstl_len = strlen(precstl);
static const char *rootinclude = "include/";
static const unsigned int rootinclude_len = strlen(rootinclude);
if (strncmp(declfile,precstl,precstl_len) == 0) {
fprintf(fp,"#include <%s>\n",declfile+precstl_len);
listOfHeaders.Add(new TNamed(cl->GetName(),declfile+precstl_len));
} else if (strncmp(declfile,rootinclude,rootinclude_len) == 0) {
fprintf(fp,"#include <%s>\n",declfile+rootinclude_len);
listOfHeaders.Add(new TNamed(cl->GetName(),declfile+rootinclude_len));
} else {
fprintf(fp,"#include \"%s\"\n",declfile);
listOfHeaders.Add(new TNamed(cl->GetName(),declfile));
}
}
}
}
Int_t len, lenb;
char blen[1024];
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);
}
fprintf(fp,"\n// Fixed size dimensions of array or collections stored in the TTree if any.\n");
leaves = fTree->GetListOfLeaves();
for (l=0;l<nleaves;l++) {
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
strlcpy(blen,leaf->GetName(),sizeof(blen));
bname = &blen[0];
while (*bname) {
if (*bname == '.') *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 leaf types\n");
TLeaf *leafcount;
TLeafObject *leafobj;
TBranchElement *bre=0;
const char *headOK = " ";
const char *headcom = " //";
const char *head;
char branchname[1024];
char aprefix[1024];
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;
strlcpy(branchname,branch->GetName(),sizeof(branchname));
strlcpy(aprefix,branch->GetName(),sizeof(aprefix));
if (!branches.FindObject(branch)) branches.Add(branch);
else leafStatus[l] = 1;
if ( branch->GetNleaves() > 1) {
strlcat(branchname,".",sizeof(branchname));
strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
if (leafcount) {
char *dim = (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
}
} else {
strlcpy(branchname,branch->GetName(),sizeof(branchname));
}
char *twodim = (char*)strstr(leaf->GetTitle(),"][");
bname = branchname;
while (*bname) {
if (*bname == '.') *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;
strlcpy(blen,leafcount->GetName(),sizeof(blen));
bname = &blen[0];
while (*bname) {
if (*bname == '.') *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 snprintf(blen,sizeof(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(), branchname);
} else {
fprintf(fp,"%s%-15s *%s;\n",head,bre->GetClassName(), branchname);
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(), branchname);
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];
strlcpy(brename,bre->GetName(),255);
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 = "*";
}
TString dimensions;
char *dimInName = (char*) strstr(branchname,"[");
if ( twodim || dimInName ) {
if (dimInName) {
dimensions = dimInName;
dimInName[0] = 0;
}
if (twodim) dimensions += (char*)(twodim+1);
}
const char* leafcountName = leafcount->GetName();
char b2len[1024];
if (bre && bre->GetBranchCount2()) {
TLeaf * l2 = (TLeaf*)bre->GetBranchCount2()->GetListOfLeaves()->At(0);
strlcpy(b2len,l2->GetName(),sizeof(b2len));
bname = &b2len[0];
while (*bname) {
if (*bname == '.') *bname='_';
if (*bname == ',') *bname='_';
if (*bname == ':') *bname='_';
if (*bname == '<') *bname='_';
if (*bname == '>') *bname='_';
bname++;
}
leafcountName = b2len;
}
if (dimensions.Length()) {
if (kmax) fprintf(fp," %-14s %s%s[kMax%s]%s; //[%s]\n",leaf->GetTypeName(), stars,
branchname,blen,dimensions.Data(),leafcountName);
else fprintf(fp," %-14s %s%s[%d]%s; //[%s]\n",leaf->GetTypeName(), stars,
branchname,len,dimensions.Data(),leafcountName);
} 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) : fChain(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) : fChain(0) \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.Data());
fprintf(fp," if (!f) {\n");
fprintf(fp," f = new THbookFile(\"%s\");\n",treefile.Data());
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.Data());
fprintf(fp," if (!f || !f->IsOpen()) {\n");
fprintf(fp," f = new TFile(\"%s\");\n",treefile.Data());
fprintf(fp," }\n");
if (fTree->GetDirectory() != fTree->GetCurrentFile()) {
fprintf(fp," TDirectory * dir = (TDirectory*)f->Get(\"%s\");\n",fTree->GetDirectory()->GetPath());
fprintf(fp," dir->GetObject(\"%s\",tree);\n\n",fTree->GetName());
} else {
fprintf(fp," f->GetObject(\"%s\",tree);\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->GetTreeNumber() != fCurrent) {\n");
fprintf(fp," fCurrent = fChain->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 normally 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())) {
strlcpy(branchname,((TBranch*)obj)->GetName(),sizeof(branchname));
} else if (obj->InheritsFrom(TLeaf::Class())) {
strlcpy(branchname,((TLeaf*)obj)->GetName(),sizeof(branchname));
}
branchname[1023]=0;
bname = branchname;
while (*bname) {
if (*bname == '.') *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();
strlcpy(aprefix,branch->GetName(),sizeof(aprefix));
if ( branch->GetNleaves() > 1) {
strlcpy(branchname,branch->GetName(),sizeof(branchname));
strlcat(branchname,".",sizeof(branchname));
strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
if (leafcount) {
char *dim = (char*)strstr(branchname,"["); if (dim) dim[0] = 0;
}
} else {
strlcpy(branchname,branch->GetName(),sizeof(branchname));
if (branch->IsA() == TBranchElement::Class()) {
bre = (TBranchElement*)branch;
if (bre->GetType() == 3 || bre->GetType()==4) strlcat(branchname,"_",sizeof(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='_';
if (*bname == '>') *bname='_';
bname++;
}
const char *maybedisable = "";
if (branch != fTree->GetBranch(branch->GetName())) {
Error("MakeClass","The branch named %s (full path name: %s) is hidden by another branch of the same name and its data will not be loaded.",branch->GetName(),R__GetBranchPointerName(leaf,kFALSE).Data());
maybedisable = "// ";
}
if (branch->IsA() == TBranchObject::Class()) {
if (branch->GetListOfBranches()->GetEntriesFast()) {
fprintf(fp,"%s fChain->SetBranchAddress(\"%s\",(void*)-1,&b_%s);\n",maybedisable,branch->GetName(),R__GetBranchPointerName(leaf).Data());
continue;
}
strlcpy(branchname,branch->GetName(),sizeof(branchname));
}
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,"%s fChain->SetBranchAddress(\"%s\", %s, &b_%s);\n",
maybedisable,branch->GetName(), branchname, R__GetBranchPointerName(leaf).Data());
else fprintf(fp,"%s fChain->SetBranchAddress(\"%s\", &%s, &b_%s);\n",
maybedisable,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 normally 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.Data());
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 every time 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.Data());
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.Data(),tcimp.Data(),fTree->GetName());
delete [] leafStatus;
fclose(fp);
fclose(fpc);
return 0;
}
Int_t TTreePlayer::MakeCode(const char *filename)
{
TString tfile;
if (filename)
tfile = filename;
else
tfile.Form("%s.C", fTree->GetName());
FILE *fp = fopen(tfile, "w");
if (!fp) {
Error("MakeCode","cannot open output file %s", tfile.Data());
return 3;
}
TString treefile;
if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile()) {
treefile = fTree->GetDirectory()->GetFile()->GetName();
} else {
treefile = "Memory Directory";
}
Bool_t ischain = fTree->InheritsFrom(TChain::Class());
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.Data());
} 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.Data());
fprintf(fp," if (!f) {\n");
fprintf(fp," f = new TFile(\"%s\");\n",treefile.Data());
fprintf(fp," }\n");
if (fTree->GetDirectory() != fTree->GetCurrentFile()) {
fprintf(fp," TDirectory * dir = (TDirectory*)f->Get(\"%s\");\n",fTree->GetDirectory()->GetPath());
fprintf(fp," dir->GetObject(\"%s\",tree);\n\n",fTree->GetName());
} else {
fprintf(fp," f->GetObject(\"%s\",tree);\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 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[1024];
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) {
strlcpy(branchname,branch->GetName(),sizeof(branchname));
strlcat(branchname,".",sizeof(branchname));
strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
if (leafcount) {
char *dim = (char*)strstr(branchname,"[");
if (dim) dim[0] = 0;
}
} else {
if (leafcount) strlcpy(branchname,branch->GetName(),sizeof(branchname));
else strlcpy(branchname,leaf->GetTitle(),sizeof(branchname));
}
char *twodim = (char*)strstr(leaf->GetTitle(),"][");
bname = branchname;
while (*bname) {
if (*bname == '.') *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,"[");
TString dimensions;
if ( twodim || dimInName ) {
if (dimInName) {
dimensions = dimInName;
dimInName[0] = 0;
}
if (twodim) dimensions += (char*)(twodim+1);
}
if (dimensions.Length()) {
fprintf(fp," %-15s %s[%d]%s;\n",leaf->GetTypeName(), branchname,len,dimensions.Data());
} 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) {
strlcpy(branchname,branch->GetName(),sizeof(branchname));
strlcat(branchname,".",sizeof(branchname));
strlcat(branchname,leaf->GetTitle(),sizeof(branchname));
if (leafcount) {
char *dim = (char*)strstr(branchname,"[");
if (dim) dim[0] = 0;
}
} else {
if (leafcount) strlcpy(branchname,branch->GetName(),sizeof(branchname));
else strlcpy(branchname,leaf->GetTitle(),sizeof(branchname));
}
bname = branchname;
while (*bname) {
if (*bname == '.') *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()) {
strlcpy(branchname,branch->GetName(),sizeof(branchname));
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.Data(), fTree->GetName());
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;
std::vector<TString> cnames;
TString opt = option;
opt.ToLower();
TPrincipal *principal = 0;
Long64_t entry,entryNumber;
Int_t i,nch;
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 (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
if (nch == 0 || allvar) {
for (i=0;i<ncols;i++) {
cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
}
} else {
ncols = fSelector->SplitNames(varexp,cnames);
}
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 [] 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);
Bool_t process = (selector->GetAbort() != TSelector::kAbortProcess &&
(selector->Version() != 0 || selector->GetStatus() != -1)) ? kTRUE : kFALSE;
if (process) {
Long64_t readbytesatstart = 0;
readbytesatstart = TFile::GetFileBytesRead();
TTreeCache *tpf = 0;
TFile *curfile = fTree->GetCurrentFile();
if (curfile && fTree->GetCacheSize() > 0) {
tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
if (tpf)
tpf->SetEntryRange(firstentry,firstentry+nentries);
else {
fTree->SetCacheSize(fTree->GetCacheSize());
tpf = (TTreeCache*)curfile->GetCacheRead(fTree);
if (tpf) tpf->SetEntryRange(firstentry,firstentry+nentries);
}
}
TProcessEventTimer *timer = 0;
Int_t interval = fTree->GetTimerInterval();
if (!gROOT->IsBatch() && interval)
timer = new TProcessEventTimer(interval);
Long64_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;
if (selector->GetAbort() == TSelector::kAbortFile) {
entry += fTree->GetTree()->GetEntries() - localEntry;
selector->ResetAbort();
}
}
delete timer;
{
TFile *curfile2 = fTree->GetCurrentFile();
if (curfile2 && fTree->GetCacheSize() > 0) {
tpf = (TTreeCache*)curfile2->GetCacheRead(fTree);
if (tpf) tpf->SetEntryRange(0,0);
}
}
}
process = (selector->GetAbort() != TSelector::kAbortProcess &&
(selector->Version() != 0 || selector->GetStatus() != -1)) ? kTRUE : kFALSE;
Long64_t res = (process) ? 0 : -1;
if (process) {
selector->SlaveTerminate();
selector->Terminate();
res = selector->GetStatus();
}
fTree->SetNotify(0);
fSelectorUpdate = 0;
if (gMonitoringWriter)
gMonitoringWriter->SendProcessingStatus("DONE");
return res;
}
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] == 's'
|| 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;
std::vector<TString> cnames;
TString onerow;
Long64_t entry,entryNumber;
Int_t i,nch;
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 nch2 = strlen(fTree->GetName());
fname = new char[nch2+10];
strlcpy(fname, fTree->GetName(),nch2+10);
strlcat(fname, "-scan.dat",nch2+10);
}
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 (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
if (nch == 0 || allvar) {
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.push_back( lf->GetBranch()->GetMother()->GetName() );
if (cnames[ncols] == lf->GetName() ) {
} else if (cnames[ncols][cnames[ncols].Length()-1]=='.') {
cnames[ncols] = lf->GetBranch()->GetName();
} else {
if (lf->GetBranch()->GetMother()->IsA()->InheritsFrom(TBranchElement::Class())) {
TBranchElement *mother = (TBranchElement*)lf->GetBranch()->GetMother();
if (mother->GetType() == 3 || mother->GetType() == 4) {
cnames[ncols] = lf->GetBranch()->GetName();
++ncols;
continue;
}
}
if (!strchr(lf->GetBranch()->GetName() ,'[') ) {
cnames[ncols].Append('.');
cnames[ncols].Append( lf->GetBranch()->GetName() );
}
}
if (strcmp( lf->GetBranch()->GetName(), lf->GetName() ) != 0 ) {
cnames[ncols].Append('.');
cnames[ncols].Append( lf->GetName() );
}
++ncols;
}
} else {
ncols = fSelector->SplitNames(varexp, cnames);
}
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;
forceDim = kTRUE;
break;
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;
return fSelectedRows;
}
TSQLResult *TTreePlayer::Query(const char *varexp, const char *selection,
Option_t *, Long64_t nentries, Long64_t firstentry)
{
TTreeFormula **var;
std::vector<TString> cnames;
TString onerow;
Long64_t entry,entryNumber;
Int_t i,nch;
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 (varexp && !strcmp(varexp, "*")) { ncols = nleaves; allvar = 1; }
if (nch == 0 || allvar) {
for (i=0;i<ncols;i++) {
cnames.push_back( ((TLeaf*)leaves->At(i))->GetName() );
}
} else {
ncols = fSelector->SplitNames(varexp,cnames);
}
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));
}
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();
}
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();
}
Int_t ndata = 1;
if (manager && manager->GetMultiplicity()) {
ndata = manager->GetNdata();
}
if (select) {
select->GetNdata();
if (select->EvalInstance(0) == 0) continue;
}
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 (i=0;i<ncols;i++) {
var[i]->EvalInstance(0);
}
loaded = kTRUE;
}
for (i=0;i<ncols;i++) {
aresult = var[i]->PrintValue(0,inst);
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;
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);
}
}
Int_t TTreePlayer::UnbinnedFit(const char *funcname ,const char *varexp, const char *selection,Option_t *option ,Long64_t nentries, Long64_t firstentry)
{
TF1* fitfunc = (TF1*)gROOT->GetFunction(funcname);
if (!fitfunc) { Error("UnbinnedFit", "Unknown function: %s",funcname); return 0; }
Int_t 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));
TString opt = option;
opt.ToUpper();
Foption_t fitOption;
if (opt.Contains("Q")) fitOption.Quiet = 1;
if (opt.Contains("V")){fitOption.Verbose = 1; fitOption.Quiet = 0;}
if (opt.Contains("E")) fitOption.Errors = 1;
if (opt.Contains("M")) fitOption.More = 1;
if (!opt.Contains("D")) fitOption.Nograph = 1;
TString drawOpt = "goff para";
if (!fitOption.Nograph) drawOpt = "";
Long64_t nsel = DrawSelect(varexp, selection,drawOpt, nentries, firstentry);
if (!fitOption.Nograph && GetSelectedRows() <= 0 && GetDimension() > 4) {
Info("UnbinnedFit","Ignore option D with more than 4 variables");
nsel = DrawSelect(varexp, selection,"goff para", nentries, firstentry);
}
Long64_t nrows = GetSelectedRows();
if (nrows <= 0) {
Error("UnbinnedFit", "Cannot fit: no entries selected");
return -1;
}
Int_t ndim = GetDimension();
std::vector<double *> vlist(ndim);
for (int i = 0; i < ndim; ++i)
vlist[i] = fSelector->GetVal(i);
ROOT::Fit::UnBinData * fitdata = new ROOT::Fit::UnBinData(nrows, ndim, vlist.begin());
ROOT::Math::MinimizerOptions minOption;
TFitResultPtr ret = ROOT::Fit::UnBinFit(fitdata,fitfunc, fitOption, minOption);
fTree->SetEstimate(oldEstimate);
if (!fitOption.Nograph && fHistogram) {
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 int(ret);
}
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();
}
}
}