Hi, Usually during "rapid prototyping" I modify my code a lot, switch some parts on, some off, ... . Unfortunately, I usually ( very often ) forget to SetBranchStatus, enabling/disabling appropriate ( currently used ) ntuple branches. This leads to very difficult to find bugs ( or slows down the analysis, if unneeded branches are "on" ). I finally decided to implement a new MakeClass routine which loads appropriate branches on demand ( during first use of any leaf that belongs to the branch ). Please find attached the MakeClass.cxx macro, the automatically generated ( $ROOTSYS/test/hsimple.root related ) ntuple.hpp file, the ntuple.cxx file ( modified to demonstrate the way one uses it ) and the Linux EGCS Makefile ( to try to create the shared library ). For the time being the MakeClass.cxx macro is quite dumb. Feel free to add something to it ... . The only "disadvantage" that I see is that accessing a "leaf" requires to call "leaf()" ( instead of "leaf", as in the original MakeClass ) The additional advantage of this macro is that one can easily build the shared library from it ( which is impossible if one uses the original TTree::MakeClass macro ). ( Of course, I know - calling a function is always slower then accessing directly a variable, but ... if I subtract the time spent to find missing SetBranchStatus and the time spent to load unneeded branches ... .) Jacek. //_____________________________________________________________________________ Int_t MakeClass(TTree *t, const char *classname = 0) { //====> //*-*-*-*-*-*-*Generate skeleton analysis class for this Tree*-*-*-*-*-*-* //*-* ============================================== // // The following files are produced: classname.hpp and classname.cxx // if classname is NULL, classname will be nameoftree. // // The generated code in classname.hpp 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");) // - T->MakeClass("MyClass"); // where T is the name of the Tree in file myfile.root // and MyClass.hpp, MyClass.cxx the name of the files created by this function. // In a Root session, you can do: // Root > .L MyClass.cxx // Root > MyClass t // Root > t.GetEvent(12); // Fill t data members 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.hpp",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.hpp===================== // 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_hpp\n",classname); fprintf(fp,"#define %s_hpp\n",classname); fprintf(fp,"\n"); fprintf(fp,"#ifndef __CINT__\n"); fprintf(fp,"#include \"TROOT.h\"\n"); fprintf(fp,"#include \"TBranch.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 *%s;\n",head,leafobj->GetTypeName(), leafobj->GetName()); continue; } if (leafcount) { len = leafcount->GetMaximum(); if (twodim) { fprintf(fp," %-15s %s[%d]%s;\n",leaf->GetTypeName(), branchname,len,(char*)(twodim+1)); } else { fprintf(fp," %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len); } } else { fprintf(fp," %-15s leaf_%s;\n",leaf->GetTypeName(), branchname); fprintf(fp," %-15s %s(void) {",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); fprintf(fp," %-15s %s(%s value) {return leaf_%s = value;}\n",leaf->GetTypeName(), branchname, leaf->GetTypeName(), branchname); } } // generate class member functions prototypes fprintf(fp,"\n"); fprintf(fp," %s(TTree *tree = 0);\n",classname); fprintf(fp," ~%s() {;}\n",classname); 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,"// Read specified event from the Tree into data members\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\",%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;\n"); fprintf(fp," 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,"\n"); fprintf(fpc,"#include \"%s\"\n",thead); 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,"\n// This is the loop skeleton\n"); fprintf(fpc," if (fTree == 0) return;\n"); fprintf(fpc,"\n Stat_t nentries = fTree->GetEntries();\n"); fprintf(fpc,"\n Int_t nbytes = 0, nb = 0;\n"); fprintf(fpc," for (Int_t i=0; i<nentries;i++) {\n"); fprintf(fpc," nb = fTree->GetEvent(i); nbytes += nb;\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 // (Wed Apr 14 20:24:13 1999 by ROOT version 2.21/08) // from TTree ntuple/Demo ntuple // found on file: hsimple.root ////////////////////////////////////////////////////////// #ifndef ntuple_hpp #define ntuple_hpp #ifndef __CINT__ #include "TROOT.h" #include "TBranch.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(void) {if (branch_px) return leaf_px;branch_pointer_px->GetEvent(fEvent);branch_px = 1; return leaf_px;} Float_t px(Float_t value) {return leaf_px = value;} Float_t leaf_py; Float_t py(void) {if (branch_py) return leaf_py;branch_pointer_py->GetEvent(fEvent);branch_py = 1; return leaf_py;} Float_t py(Float_t value) {return leaf_py = value;} Float_t leaf_pz; Float_t pz(void) {if (branch_pz) return leaf_pz;branch_pointer_pz->GetEvent(fEvent);branch_pz = 1; return leaf_pz;} Float_t pz(Float_t value) {return leaf_pz = value;} Float_t leaf_random; Float_t random(void) {if (branch_random) return leaf_random;branch_pointer_random->GetEvent(fEvent);branch_random = 1; return leaf_random;} Float_t random(Float_t value) {return leaf_random = value;} Float_t leaf_i; Float_t i(void) {if (branch_i) return leaf_i;branch_pointer_i->GetEvent(fEvent);branch_i = 1; return leaf_i;} Float_t i(Float_t value) {return leaf_i = value;} ntuple(TTree *tree = 0); ~ntuple() {;} 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) { // Read specified event from the Tree into data members 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.hpp" #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 if (fTree == 0) return; 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 = fTree->GetEntries(); Int_t nbytes = 0, nb = 0; for (Int_t l=0; l<nentries;l++) { nb = fTree->GetEvent(l); nbytes += nb; 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 = hpp 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:31 MET