Rene pointed me at TTree::MakeClass() as a way to auto build a helper macro from a tree structure. It creates a class with some handy member functions; the definition and some boilerplate implementation are hidden in the .h file, while the user puts his analysis in the .C file which contains the event loop code. I thought this was neat, but wanted more helper functions: o give a simple Go(Int_t nEvent) function that will execute the event loop o allow the Go loop to carry on from where it left off (ie not always start over from the first event) o allow starting at any event (including first event as a special 'rewind') o Reset() all histograms o re-initialize to a different root file without redefining the macro Organizationally, I liked hiding the boilerplate and having the user put his code and histograms in the one .C file. I wanted to take that a step further and put the actual looping code itself into the .h file, letting the user define - in the same file - only the histograms and the code inside the for loop over events. eg MyEvent::Go would call MyEvent::Anal in the middle of the event loop. I'll include the code that I came up with here. I failed in two regards: 1. the re-init code fails. Once I've switched to a new TFile, something is clearly not un-connected and fails. 2. I could not separate the loop code from the user analysis and histograms. It generally failed trying to fill the histogram. If successful, this would allow different .h files for: reading from file, running eg a FastMC interacively; from the user's analysis code. If this is of interest to anyone and they can figure out how I can fix these failures, I'd like to hear about it! Item 2. _________________________ MyEvent.h _________________________________ ////////////////////////////////////////////////////////// // This class is intended to provide useful manipulation // of the Root Event loop. Users put their analysis code // into the Go function (in MyEvent.C). They should not // need to look at MyEvent.h (except to see the interface) // // It is targetted at the LCD Event structure, which has // Event as the main branch with sub-branches. This version // handles the case of reading back from a file. At the moment // there must be separate versions for running the FastMC and // FullRecon interactively. // // allows for: // init and re-init use of a Root file // clear all histograms // 'go n events' allowing to continue on in the file // or 'rewind' // // Example of use: // // .x startmacro.C // load shared libs // .L MyEvent.C // 'complile' class // MyEvent* m = new MyEvent("MyRootFile.root"); // create MyEvent object // m->Go(500); // loop over 500 events. Go contains your analysis code // ... look at histograms ... // m->Go() // look at remainder of file // ... look at histograms ... // m->Init("AnotherRootFile.root"); // m->Go(50); // ... and so on ... // // After editing your Go function, you need to issue a gROOT->Reset() and // repeat the above sequence starting from the .L MyEvent.C. // // Version 0.1 17-Mar-1999 Richard Creation ////////////////////////////////////////////////////////// #ifndef MyEvent_h #define MyEvent_h class MyEvent { public : TFile* f; // input file TTree *fTree; //pointer to the analyzed TTree Event* event; MyEvent() {}; // default ctr MyEvent(char* rootFileName); // ctr with root file name ~MyEvent() {;} // default dtr void StartWithEvent(Int_t event); // start next Go with this event void Init(char* rootFileName); // re-init with this root file void AllHistClear(); // Reset() all user histograms void AllHistDelete(); // delete all user histograms void MakeHistList(); // make list of user histograms void Rewind(); // reset for next Go to start at beginning of file void Go(Int_t nEvent=100000); // loop over events private: Int_t m_StartEvent; // starting event Int_t HistsDefined; // flag for whether histograms have been defined TObjArray* HistList; // list of user histograms }; #endif MyEvent::MyEvent(char* rootFileName) { // set up root file and init things printf(" opening file %s \n",rootFileName); f = 0; fTree = 0; event = 0; Init(rootFileName); m_StartEvent = 0; } void MyEvent::StartWithEvent(Int_t event) { m_StartEvent = event; } void MyEvent::Init(char* rootFileName) { // re-initialize file, tree, event HistsDefined = 1; HistList = 0; AllHistDelete(); // Set branch addresses if (f) { delete event; delete fTree; delete f; } f = new TFile(rootFileName); fTree = (TTree*)gDirectory->Get("T"); event = new Event(); fTree->SetBranchAddress("Event",&event); } void MyEvent::Rewind() { // Start input file at beginning m_StartEvent = 0; return; } void MyEvent::MakeHistList() { // make a TObjArray of histograms if (HistList) delete HistList; HistList = new TObjArray(); TList* list = gDirectory->GetList(); TIter iter(list); TObject* obj = 0; while (obj=iter.Next()) { if (obj->InheritsFrom("TH1")) { HistList->Add(obj); } } } void MyEvent::AllHistClear() { for (Int_t i=0; i < HistList->GetEntries(); i++) { TObject* obj = HistList->At(i); ((TH1*)HistList->At(i))->Reset(); } } void MyEvent::AllHistDelete() { if (HistList) { for (Int_t i=0; i < HistList->GetEntries(); i++) { TObject* obj = HistList->At(i)->Reset(); obj->SetDirectory(0); delete obj; } delete HistList; } } _________________________ MyEvent.C _________________________________ #include "MyEvent.h" void MyEvent::Go(Int_t numEvents) { // This is the loop skeleton // To read only selected branches, Insert statements like: // fTree->SetBranchStatus("*",0); // disable all branches // fTree->SetBranchStatus("branchname",1); // activate branchname if (fTree == 0) return; Int_t nentries = fTree->GetEntries(); Int_t curI; Int_t nMax = TMath::Min(numEvents,nentries) + m_StartEvent; if (HistsDefined == 1) { // define histograms here ________________________________________ TH1F *NTRACKS = new TH1F("NTRACKS","Track Multiplicity",50, 0., 50.0); TH1F *NCLUSTERS = new TH1F("NCLUSTERS","Cluster Multiplicity",50, 0., 50.0); TH1F *CLSTHETA = new TH1F("CLSTHETA","Cluster Theta",50, -0.2, 4.0); // end histogram definition ________________________________________ MakeHistList(); HistsDefined = 0; } Int_t nbytes = 0, nb = 0; for (Int_t ievent=m_StartEvent; ievent<nMax; ievent++, curI=ievent) { nb = fTree->GetEvent(ievent); nbytes += nb; // start analysis code _______________________________________ Int_t nTrack = event->Tracks()->GetEntries(); NTRACKS->Fill(nTrack); if (nTrack < 5) continue; Int_t nClus = event->ClusterLst()->GetEntries(); NCLUSTERS->Fill(nClus); for (Int_t icls=0; icls<nClus; icls++) { Cluster* cls = (Cluster*)event->ClusterLst()->At(icls); Float_t cth = cls->GetEnergyTheta(); CLSTHETA->Fill(cth); } // end analysis code in event loop ___________________________ } m_StartEvent = curI; } -- Richard Dubois SLD, Stanford Linear Accelerator Center Richard@slac.stanford.edu http://www.slac.stanford.edu/~richard/ 650-926-3824 650-926-2923 (FAX)
This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:30 MET