helper macro for analysis

From: Richard Dubois (richard@SLAC.stanford.edu)
Date: Thu Mar 18 1999 - 22:48:58 MET


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