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)