Hi,
Please find attached a slightly modified "set" :
- MakeClass.cxx - the modified MakeClass macro
- ntuple.hxx, ntuple.cxx - example files generated for the
$ROOTSYS/tutorials/hsimple.root file
- Makefile - Linux EGCS Makefile which creates the ntuple.so
The MakeClass macro possibly now works not only for trivial ntuples, but
also for ntuples with arrays and other objects.
Due to current CINT limitations ( as shipped with root 2.21/08 ), one
cannot write 'x=leaf()[]; leaf()[]=y', one must say 'tmp=leaf(); x=tmp[];
tmp[]=y'. This was fixed in the development version of CINT, so the next
root version should have it.
Due to current CINT limitations one cannot use code generated by this
macro for multi-dimensional arrays directly in CINT ( as a CINT macro ),
one needs to compile the analysis code and create the shared library.
Have fun,
Jacek.
P.S. The main difference to the previous version is a "bug" fix - the
Loop() function called fTree->GetEvent() instead of it's own
GetEvent() ( the same "bug" is present in the original
TTree::MakeClass function ). To get rid of "fTree" in the Loop() I
implemented also the GetEntries() function. On this occasion I
noticed another "bug" ( "feature" ) of the TTree::GetEvent() function
- in case ALL branches are "off" ( one set 'SetBranchStatus("*",0);' )
the TTree::GetEvent() reads the WHOLE event ( all branches !!! ). For
me, in this case, it should read NOTHING. Jacek.
//_____________________________________________________________________________
Int_t MakeClass(TTree *t, const char *classname = 0)
{
//====>
//*-*-*-*-*-*-*Generate skeleton analysis class for this Tree*-*-*-*-*-*-*
//*-* ==============================================
//
// The following files are produced: classname.hxx and classname.cxx
// if classname is NULL, classname will be nameoftree.
//
// The generated code in classname.hxx includes the following:
// - Identification of the original Tree and Input file name
// - Definition of analysis class (data and functions)
// - the following class functions:
// -constructor (connecting by default the Tree file)
// -GetEvent(Int_t event)
// -Init(TTree *tree) to initialize a new TTree
// -Show(Int_t event) to read and Dump event
//
// The generated code in classname.cxx includes only the main
// analysis function Loop.
//
// To use this function:
// - connect your Tree file (eg: TFile f("myfile.root");)
// - MakeClass(T,"MyClass");
// where T is the name of the Tree in the myfile.root file,
// and MyClass.hxx, MyClass.cxx are names of files created by this function.
// In a Root session, you can do:
// Root > .L MyClass.cxx
// Root > MyClass t
// Root > t.GetEvent(12); // Prepare to fill t with event number 12
// Root > t.Show(); // Show values of event 12
// Root > t.Show(16); // Read and show values of event 16
// Root > t.Loop(); // Loop on all events
//
//====>
// Check against an invalid Tree pointer
if (!t) return 1;
if (!t->IsA()->InheritsFrom("TTree")) {
printf("Attempt to MakeClass for a non-TTree object\n");
return 2;
}
// Connect output files
char *thead = new char[256];
if (!classname) classname = t->GetName();
sprintf(thead,"%s.hxx",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.cxx",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 (t->GetDirectory() && t->GetDirectory()->GetFile())
strcpy(treefile,t->GetDirectory()->GetFile()->GetName());
else strcpy(treefile,"Memory Directory");
//======================Generate classname.hxx=====================
// Print header
TObjArray *leaves = t->GetListOfLeaves();
Int_t nleaves = leaves->GetEntriesFast();
TDatime td;
fprintf(fp,"//////////////////////////////////////////////////////////\n");
fprintf(fp,"// This class has been automatically generated \n");
fprintf(fp,"// (%s by ROOT version%s)\n",td.AsString(),gROOT->GetVersion());
fprintf(fp,"// from TTree %s/%s\n",t->GetName(),t->GetTitle());
fprintf(fp,"// found on file: %s\n",treefile);
fprintf(fp,"//////////////////////////////////////////////////////////\n");
fprintf(fp,"\n");
fprintf(fp,"\n");
fprintf(fp,"#ifndef %s_hxx\n",classname);
fprintf(fp,"#define %s_hxx\n",classname);
fprintf(fp,"\n");
fprintf(fp,"#ifndef __CINT__\n");
fprintf(fp,"#include \"TROOT.h\"\n");
fprintf(fp,"#include \"TTree.h\"\n");
fprintf(fp,"#include \"TFile.h\"\n");
fprintf(fp,"#else\n");
fprintf(fp,"class TBranch;\n");
fprintf(fp,"class TTree;\n");
fprintf(fp,"class TFile;\n");
fprintf(fp,"#endif\n");
fprintf(fp,"\n");
fprintf(fp,"class %s {\n",classname);
fprintf(fp," public :\n");
fprintf(fp," TTree *fTree; // pointer to the analyzed TTree\n");
fprintf(fp," Int_t fEvent; // current Event number\n");
// First loop on all branches to generate branch declarations
fprintf(fp," // declaration of branches\n");
Int_t nb, i;
nb = t->GetListOfBranches().GetEntriesFast();
for (i=0;i<nb;i++) {
branch = (TBranch*)t->GetListOfBranches().UncheckedAt(i);
fprintf(fp,"%s%-15s branch_%s;\n"," ","Int_t", branch->GetName());
fprintf(fp,"%s%-15s *branch_pointer_%s;\n"," ","TBranch", branch->GetName());
}
// First loop on all leaves to generate leaf declarations
fprintf(fp," // declaration of leaves\n");
Int_t len, l;
TLeaf *leafcount;
TLeafObject *leafobj;
char *bname;
const char *headOK = " ";
const char *headcom = " //";
const char *head;
char branchname[64];
for (l=0;l<nleaves;l++) {
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
len = leaf->GetLen();
leafcount =leaf->GetLeafCount();
TBranch *branch = leaf->GetBranch();
if (leafcount) strcpy(branchname,branch->GetName());
else strcpy(branchname,leaf->GetTitle());
char *twodim = (char*)strstr(leaf->GetTitle(),"][");
bname = branchname;
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
if (branch->IsA() == TBranchObject::Class()) {
if (branch->GetListOfBranches()->GetEntriesFast()) continue;
leafobj = (TLeafObject*)leaf;
if (leafobj->GetClass()) head = headOK;
else head = headcom;
fprintf(fp,"%s%-15s *leaf_%s;\n",head,leafobj->GetTypeName(),leafobj->GetName());
fprintf(fp,"%s%-15s *%s() {",head,leafobj->GetTypeName(),leafobj->GetName());
fprintf(fp,"if (branch_%s) return leaf_%s;",branch->GetName(),leafobj->GetName());
fprintf(fp,"branch_pointer_%s->GetEvent(fEvent);",branch->GetName());
fprintf(fp,"branch_%s = 1;return leaf_%s;}\n",branch->GetName(),leafobj->GetName());
continue;
}
if (leafcount) {
len = leafcount->GetMaximum();
if (twodim) {
fprintf(fp," %-15s leaf_%s[%d]%s;\n",leaf->GetTypeName(),branchname,len,(char*)(twodim+1));
// fprintf(fp," %-15s (&%s())[%d]%s {",leaf->GetTypeName(),branchname,len,(char*)(twodim+1));
fprintf(fp," %-15s (*%s())%s {",leaf->GetTypeName(),branchname,(char*)(twodim+1));
fprintf(fp,"if (branch_%s) return leaf_%s;",branch->GetName(),branchname);
fprintf(fp,"branch_pointer_%s->GetEvent(fEvent);",branch->GetName());
fprintf(fp,"branch_%s = 1;return leaf_%s;}\n",branch->GetName(),branchname);
} else {
fprintf(fp," %-15s leaf_%s[%d];\n",leaf->GetTypeName(),branchname,len);
// fprintf(fp," %-15s (&%s())[%d] {",leaf->GetTypeName(),branchname,len);
fprintf(fp," %-15s *s() {",leaf->GetTypeName(),branchname);
fprintf(fp,"if (branch_%s) return leaf_%s;",branch->GetName(),branchname);
fprintf(fp,"branch_pointer_%s->GetEvent(fEvent);",branch->GetName());
fprintf(fp,"branch_%s = 1;return leaf_%s;}\n",branch->GetName(),branchname);
}
} else {
fprintf(fp," %-15s leaf_%s;\n",leaf->GetTypeName(),branchname);
fprintf(fp," %-15s &%s() {",leaf->GetTypeName(),branchname);
fprintf(fp,"if (branch_%s) return leaf_%s;",branch->GetName(),branchname);
fprintf(fp,"branch_pointer_%s->GetEvent(fEvent);",branch->GetName());
fprintf(fp,"branch_%s = 1;return leaf_%s;}\n",branch->GetName(),branchname);
}
}
// Generate class member functions prototypes
fprintf(fp,"\n");
fprintf(fp," %s(TTree *tree = 0);\n",classname);
fprintf(fp," ~%s() {;}\n",classname);
fprintf(fp," Stat_t GetEntries() {if (!fTree) return 0;return fTree->GetEntries();}\n");
fprintf(fp," Int_t GetEvent(Int_t event);\n");
fprintf(fp," void Init(TTree *tree);\n");
fprintf(fp," void Loop();\n");
fprintf(fp," void Show(Int_t event = -1);\n");
fprintf(fp,"};\n");
fprintf(fp,"\n");
fprintf(fp,"#endif\n");
fprintf(fp,"\n");
fprintf(fp,"#ifdef %s_cxx\n",classname);
fprintf(fp,"\n");
// Generate code for class constructor
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");
fprintf(fp," TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(\"%s\");\n",treefile);
fprintf(fp," if (!f) {\n");
fprintf(fp," f = new TFile(\"%s\");\n",treefile);
fprintf(fp," }\n");
fprintf(fp," tree = (TTree*)gDirectory->Get(\"%s\");\n\n",t->GetName());
fprintf(fp," }\n");
fprintf(fp," Init(tree);\n");
fprintf(fp,"}\n");
fprintf(fp,"\n");
// Generate code for class member function GetEvent()
fprintf(fp,"Int_t %s::GetEvent(Int_t event)\n",classname);
fprintf(fp,"{\n");
fprintf(fp," // Prepare to read specified event from the Tree.\n");
fprintf(fp," if (!fTree) return 0;\n");
fprintf(fp," // if (fEvent==event) return 1;\n");
nb = t->GetListOfBranches().GetEntriesFast();
for (i=0;i<nb;i++) {
branch = (TBranch*)t->GetListOfBranches().UncheckedAt(i);
fprintf(fp," branch_%s = 0;\n",branch->GetName());
}
fprintf(fp," fEvent = event;\n");
fprintf(fp," return 1;\n");
fprintf(fp,"}\n");
fprintf(fp,"\n");
// Generate code for class member function Init()
fprintf(fp,"void %s::Init(TTree *tree)\n",classname);
fprintf(fp,"{\n");
fprintf(fp," // Set branch addresses.\n");
fprintf(fp," if (tree == 0) return;\n");
fprintf(fp," fTree = tree;\n");
for (l=0;l<nleaves;l++) {
TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
len = leaf->GetLen();
leafcount =leaf->GetLeafCount();
TBranch *branch = leaf->GetBranch();
if (leafcount) strcpy(branchname,branch->GetName());
else strcpy(branchname,leaf->GetTitle());
bname = branchname;
while (*bname) {if (*bname == '.') *bname='_'; bname++;}
char *brak = strstr(branchname,"[");
if (brak) *brak = 0;
head = headOK;
if (branch->IsA() == TBranchObject::Class()) {
if (branch->GetListOfBranches()->GetEntriesFast()) continue;
leafobj = (TLeafObject*)leaf;
if (!leafobj->GetClass()) head = headcom;
strcpy(branchname,branch->GetName());
}
if (leafcount) len = leafcount->GetMaximum()+1;
if (len > 1) fprintf(fp,"%sfTree->SetBranchAddress(\"%s\",leaf_%s);\n",head,branch->GetName(),branchname);
else fprintf(fp,"%sfTree->SetBranchAddress(\"%s\",&leaf_%s);\n",head,branch->GetName(),branchname);
}
fprintf(fp," fTree->SetBranchStatus(\"*\",0); // disable all branches\n");
nb = t->GetListOfBranches().GetEntriesFast();
for (i=0;i<nb;i++) {
branch = (TBranch*)t->GetListOfBranches().UncheckedAt(i);
fprintf(fp," branch_%s = 0;\n",branch->GetName());
fprintf(fp," branch_pointer_%s = fTree->GetBranch(\"%s\");\n",branch->GetName(),branch->GetName());
}
fprintf(fp," fEvent = -1;\n");
fprintf(fp,"}\n");
fprintf(fp,"\n");
// Generate code for class member function Show()
fprintf(fp,"void %s::Show(Int_t event)\n",classname);
fprintf(fp,"{\n");
fprintf(fp," // Print contents of event.\n");
fprintf(fp," // If event is not specified, print current event.\n");
fprintf(fp," if (!fTree) return;\n");
fprintf(fp," if (event>=0) fEvent = event; else event = fEvent;\n");
fprintf(fp," if (fEvent<0) return;\n");
fprintf(fp," fTree->SetBranchStatus(\"*\",1); // enable all branches\n");
fprintf(fp," fTree->Show(fEvent);\n");
fprintf(fp," fTree->SetBranchStatus(\"*\",0); // disable all branches\n");
nb = t->GetListOfBranches().GetEntriesFast();
for (i=0;i<nb;i++) {
branch = (TBranch*)t->GetListOfBranches().UncheckedAt(i);
fprintf(fp," branch_%s = 1;\n",branch->GetName());
}
fprintf(fp,"}\n");
fprintf(fp,"\n");
fprintf(fp,"#endif\n");
fprintf(fp,"\n");
//======================Generate classname.cxx=====================
// Generate code for class member function Loop()
fprintf(fpc,"#ifndef %s_cxx\n",classname);
fprintf(fpc,"#define %s_cxx\n",classname);
fprintf(fpc,"#endif\n");
fprintf(fpc,"#include \"%s\"\n",thead);
fprintf(fpc,"#undef %s_cxx\n",classname);
fprintf(fpc,"\n");
fprintf(fpc,"#ifndef __CINT__\n");
fprintf(fpc,"// Place here all ROOT related includes that you need.\n");
fprintf(fpc,"#endif\n");
fprintf(fpc,"\n");
fprintf(fpc,"void %s::Loop()\n",classname);
fprintf(fpc,"{\n");
fprintf(fpc," // This is the loop skeleton.\n");
// fprintf(fpc,"\n if (fTree == 0) return;\n");
fprintf(fpc,"\n Stat_t nentries = GetEntries();\n");
fprintf(fpc,"\n Int_t ne = 0, nevents = 0;\n");
fprintf(fpc," for (Int_t i=0; i<nentries; i++) {\n");
fprintf(fpc," ne = GetEvent(i); nevents += ne;\n");
fprintf(fpc," \n");
fprintf(fpc," }\n");
fprintf(fpc,"}\n");
fprintf(fpc,"\n");
printf("Files: %s and %s generated from Tree: %s\n",thead,tcimp,t->GetName());
delete [] thead;
delete [] tcimp;
delete [] treefile;
fclose(fp);
fclose(fpc);
return 0;
}
//_____________________________________________________________________________
//////////////////////////////////////////////////////////
// This class has been automatically generated
// (Fri Apr 23 18:57:27 1999 by ROOT version 2.21/08)
// from TTree ntuple/Demo ntuple
// found on file: hsimple.root
//////////////////////////////////////////////////////////
#ifndef ntuple_hxx
#define ntuple_hxx
#ifndef __CINT__
#include "TROOT.h"
#include "TTree.h"
#include "TFile.h"
#else
class TBranch;
class TTree;
class TFile;
#endif
class ntuple {
public :
TTree *fTree; // pointer to the analyzed TTree
Int_t fEvent; // current Event number
// declaration of branches
Int_t branch_px;
TBranch *branch_pointer_px;
Int_t branch_py;
TBranch *branch_pointer_py;
Int_t branch_pz;
TBranch *branch_pointer_pz;
Int_t branch_random;
TBranch *branch_pointer_random;
Int_t branch_i;
TBranch *branch_pointer_i;
// declaration of leaves
Float_t leaf_px;
Float_t &px() {if (branch_px) return leaf_px;branch_pointer_px->GetEvent(fEvent);branch_px = 1;return leaf_px;}
Float_t leaf_py;
Float_t &py() {if (branch_py) return leaf_py;branch_pointer_py->GetEvent(fEvent);branch_py = 1;return leaf_py;}
Float_t leaf_pz;
Float_t &pz() {if (branch_pz) return leaf_pz;branch_pointer_pz->GetEvent(fEvent);branch_pz = 1;return leaf_pz;}
Float_t leaf_random;
Float_t &random() {if (branch_random) return leaf_random;branch_pointer_random->GetEvent(fEvent);branch_random = 1;return leaf_random;}
Float_t leaf_i;
Float_t &i() {if (branch_i) return leaf_i;branch_pointer_i->GetEvent(fEvent);branch_i = 1;return leaf_i;}
ntuple(TTree *tree = 0);
~ntuple() {;}
Stat_t GetEntries() {if (!fTree) return 0;return fTree->GetEntries();}
Int_t GetEvent(Int_t event);
void Init(TTree *tree);
void Loop();
void Show(Int_t event = -1);
};
#endif
#ifdef ntuple_cxx
ntuple::ntuple(TTree *tree)
{
// If parameter tree is not specified (or zero), connect the file
// used to generate this class and read the Tree.
if (tree == 0) {
TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject("hsimple.root");
if (!f) {
f = new TFile("hsimple.root");
}
tree = (TTree*)gDirectory->Get("ntuple");
}
Init(tree);
}
Int_t ntuple::GetEvent(Int_t event)
{
// Prepare to read specified event from the Tree.
if (!fTree) return 0;
// if (fEvent==event) return 1;
branch_px = 0;
branch_py = 0;
branch_pz = 0;
branch_random = 0;
branch_i = 0;
fEvent = event;
return 1;
}
void ntuple::Init(TTree *tree)
{
// Set branch addresses.
if (tree == 0) return;
fTree = tree;
fTree->SetBranchAddress("px",&leaf_px);
fTree->SetBranchAddress("py",&leaf_py);
fTree->SetBranchAddress("pz",&leaf_pz);
fTree->SetBranchAddress("random",&leaf_random);
fTree->SetBranchAddress("i",&leaf_i);
fTree->SetBranchStatus("*",0); // disable all branches
branch_px = 0;
branch_pointer_px = fTree->GetBranch("px");
branch_py = 0;
branch_pointer_py = fTree->GetBranch("py");
branch_pz = 0;
branch_pointer_pz = fTree->GetBranch("pz");
branch_random = 0;
branch_pointer_random = fTree->GetBranch("random");
branch_i = 0;
branch_pointer_i = fTree->GetBranch("i");
fEvent = -1;
}
void ntuple::Show(Int_t event)
{
// Print contents of event.
// If event is not specified, print current event.
if (!fTree) return;
if (event>=0) fEvent = event; else event = fEvent;
if (fEvent<0) return;
fTree->SetBranchStatus("*",1); // enable all branches
fTree->Show(fEvent);
fTree->SetBranchStatus("*",0); // disable all branches
branch_px = 1;
branch_py = 1;
branch_pz = 1;
branch_random = 1;
branch_i = 1;
}
#endif
#ifndef ntuple_cxx
#define ntuple_cxx
#endif
#include "ntuple.hxx"
#undef ntuple_cxx
#ifndef __CINT__
// Place here all ROOT related includes that you need.
#include "TH1.h"
#include "TH2.h"
#include "TCanvas.h"
#endif
void ntuple::Loop()
{
// This is the loop skeleton.
TH1F *h_px= new TH1F("px","px",100,-4,4);
TH1F *h_py= new TH1F("py","py",100,-5,5);
TH1F *h_pz= new TH1F("pz","pz",100,0,20);
TH1F *h_random= new TH1F("random","random",100,0,1);
TH1F *h_i= new TH1F("i","i",100,0,30000);
TH2F *h_pxpz= new TH2F("pxpz","pxpz",100,0,20,100,-4,4);
Stat_t nentries = GetEntries();
Int_t ne = 0, nevents = 0;
for (Int_t l=0; l<nentries; l++) {
ne = GetEvent(l); nevents += ne;
h_px->Fill(px());
h_py->Fill(py());
h_pz->Fill(pz());
h_random->Fill(random());
h_i->Fill(i());
h_pxpz->Fill(pz(),px());
}
TCanvas *c = new TCanvas("c");
c->Divide(2,3);
c->cd(1);
h_px->Draw();
c->cd(2);
h_py->Draw();
c->cd(3);
h_pz->Draw();
c->cd(4);
h_random->Draw();
c->cd(5);
h_i->Draw();
c->cd(6);
h_pxpz->Draw();
}
SrcSuf = cxx
IncSuf = hxx
ObjSuf = o
ExeSuf =
DllSuf = so
OutPutOpt = -o
ROOTLIBS = -L$(ROOTSYS)/lib -lNew -lBase -lCint -lClib -lCont -lFunc \
-lGraf -lGraf3d -lHist -lHtml -lMatrix -lMeta -lMinuit -lNet \
-lPhysics -lPostscript -lProof -lTree -lUnix -lZip
ROOTGLIBS = -lGpad -lGui -lGX11 -lX3d
# Linux with egcs
EGCS = /opt/egcs/pro
CXX = g++
CXXFLAGS = -g -O2 -Wall -fno-rtti -fno-exceptions -fPIC -I$(ROOTSYS)/include
LD = g++
LDFLAGS = -g -O2 -Wl,-rpath,$(EGCS)/lib:$(ROOTSYS)/lib
SOFLAGS = -shared
LIBS = $(ROOTLIBS) -lm -ldl -rdynamic
GLIBS = $(ROOTLIBS) $(ROOTGLIBS) -L/usr/X11R6/lib \
-lXpm -lX11 -lm -ldl -rdynamic
#------------------------------------------------------------------------------
NTUPLEO = ntuple.$(ObjSuf) ntupleDict.$(ObjSuf)
NTUPLES = ntuple.$(SrcSuf) ntupleDict.$(SrcSuf)
NTUPLESO = ntuple.$(DllSuf)
OBJS = $(NTUPLEO)
PROGRAMS = $(NTUPLESO)
all: $(PROGRAMS)
$(NTUPLESO): $(NTUPLEO)
$(LD) $(SOFLAGS) $(LDFLAGS) $(NTUPLEO) $(OutPutOpt) $(NTUPLESO)
clean:
@rm -f $(OBJS) *Dict.* core
.SUFFIXES: .$(SrcSuf)
###
ntuple.$(ObjSuf): ntuple.$(SrcSuf) ntuple.$(IncSuf)
ntupleDict.$(SrcSuf): ntuple.$(IncSuf)
@echo "Generating dictionary ntupleDict..."
@$(ROOTSYS)/bin/rootcint -f ntupleDict.$(SrcSuf) -c ntuple.$(IncSuf)
.$(SrcSuf).$(ObjSuf):
$(CXX) $(CXXFLAGS) -c $<
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:32 MET