[ROOT] TTree split/fill problem

From: Susan Kasahara (schubert@physics.umn.edu)
Date: Sun Sep 29 2002 - 01:28:39 MEST


Hi root team,
I am having a problem filling data to a root tree that has been created with a main
branch split at level 99 and has branch layering that exceed 3 levels.
For example, I create a TTree:

  TTree* tree = new TTree("T","Demo tree");
  Event* event = 0;
  tree -> Branch("event","Event",&event,64000,99);

The class Event has a structure such that this automatically creates a branch:
  "fEvtHdr.fVertex.fTime.fSec"
but, I find that:
   event = Event(event data args,...);
   tree -> Fill();
does not fill the data is this 4-level branch filled correctly.  On the other hand, if
I change the Event class to produce a branch structure  with no more than 3 levels:

  "fEvtHdr.fVertex.fTime"

The branch data is filled correctly.
     To illustrate the problem, I've modified the $ROOTSYS/test/Event example to contain
the structure illustrated above and attach this modified Event class.  To run it, I type:
[kasahara]$ Event 400 1 99 1
If successful, I expect that every
  "fEvtHdr.fVertex.fTime.fSec" entry should be filled with the value 10, and every
  "fEvtHdr.fVertex.fTime.fNanoSec" entry should be filled with the value 100.  But using
But by using TTree::Scan, I see that the contents are incorrect.

Thanks in advance for your help,
-Sue








#ifndef ROOT_Event
#define ROOT_Event

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// Event                                                                //
//                                                                      //
// Description of the event and track parameters                        //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TObject.h"
#include "TClonesArray.h"
#include "TRefArray.h"
#include "TRef.h"
#include "TH1.h"
#include "TMath.h"


class TDirectory;

class Track : public TObject {

private:
   Float_t      fPx;           //X component of the momentum
   Float_t      fPy;           //Y component of the momentum
   Float_t      fPz;           //Z component of the momentum
   Float_t      fRandom;       //A random track quantity
   Float_t      fMass2;        //The mass square of this particle
   Float_t      fBx;           //X intercept at the vertex
   Float_t      fBy;           //Y intercept at the vertex
   Float_t      fMeanCharge;   //Mean charge deposition of all hits of this track
   Float_t      fXfirst;       //X coordinate of the first point
   Float_t      fXlast;        //X coordinate of the last point
   Float_t      fYfirst;       //Y coordinate of the first point
   Float_t      fYlast;        //Y coordinate of the last point
   Float_t      fZfirst;       //Z coordinate of the first point
   Float_t      fZlast;        //Z coordinate of the last point
   Float_t      fCharge;       //Charge of this track
   Float_t      fVertex[3];    //Track vertex position
   Int_t        fNpoint;       //Number of points for this track
   Short_t      fValid;        //Validity criterion
   Int_t        fNsp;          //Number of points for this track with a special value
   Float_t*     fPointValue;   //[fNsp] a special quantity for some point.

public:
   Track() { fPointValue = 0; }
   Track(Float_t random);
   virtual ~Track() {Clear();}
   void          Clear(Option_t *option="") { delete [] fPointValue; fPointValue=0; }
   Float_t       GetPx() const { return fPx; }
   Float_t       GetPy() const { return fPy; }
   Float_t       GetPz() const { return fPz; }
   Float_t       GetPt() const { return TMath::Sqrt(fPx*fPx + fPy*fPy); }
   Float_t       GetRandom() const { return fRandom; }
   Float_t       GetBx() const { return fBx; }
   Float_t       GetBy() const { return fBy; }
   Float_t       GetMass2() const { return fMass2; }
   Float_t       GetMeanCharge() const { return fMeanCharge; }
   Float_t       GetXfirst() const { return fXfirst; }
   Float_t       GetXlast()  const { return fXlast; }
   Float_t       GetYfirst() const { return fYfirst; }
   Float_t       GetYlast()  const { return fYlast; }
   Float_t       GetZfirst() const { return fZfirst; }
   Float_t       GetZlast()  const { return fZlast; }
   Float_t       GetCharge() const { return fCharge; }
   Float_t       GetVertex(Int_t i=0) {return (i<3)?fVertex[i]:0;}
   Int_t         GetNpoint() const { return fNpoint; }
   Short_t       GetValid()  const { return fValid; }
   virtual void  SetValid(Int_t valid=1) { fValid = valid; }
   Int_t         GetN() const { return fNsp; }
   Float_t       GetPointValue(Int_t i=0) const { return (i<fNsp)?fPointValue[i]:0; }

   ClassDef(Track,2)  //A track segment
};

class EventTime {

private:
   Int_t     fSec;
   Int_t     fNanoSec;

public:
   EventTime() : fSec(0), fNanoSec(0) { }
   virtual ~EventTime() { }
   void   Set(Int_t sec, Int_t nanosec) { fSec = sec; fNanoSec = nanosec; }
   Int_t  GetSec() const { return fSec; }
   Int_t  GetNanoSec() const { return fNanoSec; }

   ClassDef(EventTime,1)  //Event Time
};

class EventVertex {

private:
   EventTime  fTime;
   // other data members

public:
   EventVertex() : fTime() { }
   virtual ~EventVertex() { }
   void   Set(Int_t sec, Int_t nanosec) { fTime.Set(sec,nanosec); }
 
   ClassDef(EventVertex,1)  //Event Vertex
};

class EventHeader {

private:
   Int_t     fEvtNum;
   Int_t     fRun;
   Int_t     fDate;
   EventVertex fVertex;

public:
   EventHeader() : fEvtNum(0), fRun(0), fDate(0), fVertex() { }
   virtual ~EventHeader() { }
   void   Set(Int_t i, Int_t r, Int_t d, Int_t sec, Int_t nsec) 
               { fEvtNum = i; fRun = r; fDate = d; fVertex.Set(sec,nsec); }
   Int_t  GetEvtNum() const { return fEvtNum; }
   Int_t  GetRun() const { return fRun; }
   Int_t  GetDate() const { return fDate; }

   ClassDef(EventHeader,1)  //Event Header
};


class Event : public TObject {

private:
   char           fType[20];          //event type
   char          *fEventName;         //run+event number in character format
   Int_t          fNtrack;            //Number of tracks
   Int_t          fNseg;              //Number of track segments
   Int_t          fNvertex;
   UInt_t         fFlag;
   Float_t        fTemperature;
   Int_t          fMeasures[10];
   Float_t        fMatrix[4][4];
   Float_t       *fClosestDistance;   //[fNvertex]
   EventHeader    fEvtHdr;
   TClonesArray  *fTracks;            //->array with all tracks
   TRefArray     *fHighPt;            //array of High Pt tracks only
   TRefArray     *fMuons;             //array of Muon tracks only
   TRef           fLastTrack;         //reference pointer to last track
   TRef           fWebHistogram;      //EXEC:GetWebHistogram reference to an histogram in a TWebFile
   TH1F          *fH;                 //->

   static TClonesArray *fgTracks;
   static TH1F         *fgHist;

public:
   Event();
   virtual ~Event();
   void          Build(Int_t ev, Int_t arg5=600, Float_t ptmin=1);
   void          Clear(Option_t *option ="");
   static void   Reset(Option_t *option ="");
   void          ResetHistogramPointer() {fH=0;}
   void          SetNseg(Int_t n) { fNseg = n; }
   void          SetNtrack(Int_t n) { fNtrack = n; }
   void          SetNvertex(Int_t n) { fNvertex = n; SetRandomVertex(); }
   void          SetFlag(UInt_t f) { fFlag = f; }
   void          SetTemperature(Float_t t) { fTemperature = t; }
   void          SetType(char *type) {strcpy(fType,type);}
   void          SetHeader(Int_t i, Int_t run, Int_t date, Float_t random, 
                           Int_t sec, Int_t nsec);
   Track        *AddTrack(Float_t random, Float_t ptmin=1);
   void          SetMeasure(UChar_t which, Int_t what);
   void          SetMatrix(UChar_t x, UChar_t y, Float_t what) { if (x<3&&y<3) fMatrix[x][y]=what;}
   void          SetRandomVertex();

   Float_t       GetClosestDistance(Int_t i) {return fClosestDistance[i];}
   char         *GetType() {return fType;}
   Int_t         GetNtrack() const { return fNtrack; }
   Int_t         GetNseg() const { return fNseg; }
   Int_t         GetNvertex() const { return fNvertex; }
   UInt_t        GetFlag() const { return fFlag; }
   Float_t       GetTemperature() const { return fTemperature; }
   EventHeader  *GetHeader() { return &fEvtHdr; }
   TClonesArray *GetTracks() const {return fTracks;}
   TRefArray    *GetHighPt() const {return fHighPt;}
   TRefArray    *GetMuons()  const {return fMuons;}
   Track        *GetLastTrack() const {return (Track*)fLastTrack.GetObject();}
   TH1F         *GetHistogram() const {return fH;}
   TH1          *GetWebHistogram()  const {return (TH1*)fWebHistogram.GetObject();}
   Int_t         GetMeasure(UChar_t which) { return (which<10)?fMeasures[which]:0; }
   Float_t       GetMatrix(UChar_t x, UChar_t y) { return (x<4&&y<4)?fMatrix[x][y]:0; }

   ClassDef(Event,1)  //Event structure
};



class HistogramManager {

private:
   TH1F  *fNtrack;
   TH1F  *fNseg;
   TH1F  *fTemperature;
   TH1F  *fPx;
   TH1F  *fPy;
   TH1F  *fPz;
   TH1F  *fRandom;
   TH1F  *fMass2;
   TH1F  *fBx;
   TH1F  *fBy;
   TH1F  *fMeanCharge;
   TH1F  *fXfirst;
   TH1F  *fXlast;
   TH1F  *fYfirst;
   TH1F  *fYlast;
   TH1F  *fZfirst;
   TH1F  *fZlast;
   TH1F  *fCharge;
   TH1F  *fNpoint;
   TH1F  *fValid;

public:
   HistogramManager(TDirectory *dir);
   virtual ~HistogramManager();

   void Hfill(Event *event);

   ClassDef(HistogramManager,1)  //Manages all histograms
};

#endif


// @(#)root/test:$Name:  $:$Id: Event.cxx,v 1.19 2002/08/20 15:21:42 brun Exp $
// Author: Rene Brun   19/08/96

////////////////////////////////////////////////////////////////////////
//
//                       Event and Track classes
//                       =======================
//
//  The Event class is a naive/simple example of an event structure.
//     public:
//        char           fType[20];
//        Int_t          fNtrack;
//        Int_t          fNseg;
//        Int_t          fNvertex;
//        UInt_t         fFlag;
//        Float_t        fTemperature;
//        Int_t          fMeasures[10];
//        Float_t        fMatrix[4][4];
//        Float_t       *fClosestDistance; //[fNvertex] indexed array! 
//        EventHeader    fEvtHdr;
//        TClonesArray  *fTracks;
//        TRefArray     *fHighPt;            //array of High Pt tracks only
//        TRefArray     *fMuons;             //array of Muon tracks only
//        TRef           fLastTrack;         //pointer to last track
//        TRef           fHistoWeb;          //EXEC:GetHistoWeb reference to an histogram in a TWebFile
//        TH1F          *fH;
//
//   The EventHeader class has 3 data members (integers):
//     public:
//        Int_t          fEvtNum;
//        Int_t          fRun;
//        Int_t          fDate;
//
//
//   The Event data member fTracks is a pointer to a TClonesArray.
//   It is an array of a variable number of tracks per event.
//   Each element of the array is an object of class Track with the members:
//     private:
//        Float_t      fPx;           //X component of the momentum
//        Float_t      fPy;           //Y component of the momentum
//        Float_t      fPz;           //Z component of the momentum
//        Float_t      fRandom;       //A random track quantity
//        Float_t      fMass2;        //The mass square of this particle
//        Float_t      fBx;           //X intercept at the vertex
//        Float_t      fBy;           //Y intercept at the vertex
//        Float_t      fMeanCharge;   //Mean charge deposition of all hits of this track
//        Float_t      fXfirst;       //X coordinate of the first point
//        Float_t      fXlast;        //X coordinate of the last point
//        Float_t      fYfirst;       //Y coordinate of the first point
//        Float_t      fYlast;        //Y coordinate of the last point
//        Float_t      fZfirst;       //Z coordinate of the first point
//        Float_t      fZlast;        //Z coordinate of the last point
//        Float_t      fCharge;       //Charge of this track
//        Float_t      fVertex[3];    //Track vertex position
//        Int_t        fNpoint;       //Number of points for this track
//        Short_t      fValid;        //Validity criterion
//
//   An example of a batch program to use the Event/Track classes is given
//   in this directory: MainEvent.
//   Look also in the same directory at the following macros:
//     - eventa.C  an example how to read the tree
//     - eventb.C  how to read events conditionally
//
//   During the processing of the event (optionally) also a large number
//   of histograms can be filled. The creation and handling of the
//   histograms is taken care of by the HistogramManager class.
//
////////////////////////////////////////////////////////////////////////

#include "TRandom.h"
#include "TDirectory.h"
#include "TProcessID.h"

#include "Event.h"


ClassImp(EventTime)
ClassImp(EventHeader)
ClassImp(Event)
ClassImp(Track)
ClassImp(HistogramManager)

TClonesArray *Event::fgTracks = 0;
TH1F *Event::fgHist = 0;

//______________________________________________________________________________
Event::Event()
{
   // Create an Event object.
   // When the constructor is invoked for the first time, the class static
   // variable fgTracks is 0 and the TClonesArray fgTracks is created.

   if (!fgTracks) fgTracks = new TClonesArray("Track", 1000);
   fTracks = fgTracks;
   fHighPt = new TRefArray;
   fMuons  = new TRefArray;
   fNtrack = 0;
   fH      = 0;
   Int_t i0,i1;
   for (i0 = 0; i0 < 4; i0++) {
      for (i1 = 0; i1 < 4; i1++) {
         fMatrix[i0][i1] = 0.0;
      }
   }
   for (i0 = 0; i0 <10; i0++) fMeasures[i0] = 0;
   fClosestDistance = 0;
   fEventName = 0;
   fWebHistogram.SetAction(this);
}

//______________________________________________________________________________
Event::~Event()
{
   Clear();
   if (fH == fgHist) fgHist = 0;
   delete fH; fH = 0;
   delete fHighPt; fHighPt = 0;
   delete fMuons;  fMuons = 0;
   delete [] fClosestDistance;
   if (fEventName) delete [] fEventName;
}

//______________________________________________________________________________
void Event::Build(Int_t ev, Int_t arg5, Float_t ptmin) {
  char etype[20];
  Float_t sigmat, sigmas;
  gRandom->Rannor(sigmat,sigmas);
  Int_t ntrack   = Int_t(arg5 +arg5*sigmat/120.);
  Float_t random = gRandom->Rndm(1);

  //Save current Object count
  Int_t ObjectNumber = TProcessID::GetObjectCount();
  Clear();
  fHighPt->Delete();
  fMuons->Delete();
  
  Int_t nch = 15;
  if (ev > 100)   nch += 3;
  if (ev > 10000) nch += 3;
  if (fEventName) delete [] fEventName;
  fEventName = new char[nch];
  sprintf(fEventName,"Event%d_Run%d",ev,200);
  sprintf(etype,"type%d",ev%5);
  SetType(etype);
  SetHeader(ev, 200, 960312, random, 10, 100);
  SetNseg(Int_t(10*ntrack+20*sigmas));
  SetNvertex(Int_t(1+20*gRandom->Rndm()));
  SetFlag(UInt_t(random+0.5));
  SetTemperature(random+20.);

  for(UChar_t m = 0; m < 10; m++) {
     SetMeasure(m, Int_t(gRandom->Gaus(m,m+1)));
  }
  for(UChar_t i0 = 0; i0 < 4; i0++) {
    for(UChar_t i1 = 0; i1 < 4; i1++) {
       SetMatrix(i0,i1,gRandom->Gaus(i0*i1,1));
    }
  }

   //  Create and Fill the Track objects
  for (Int_t t = 0; t < ntrack; t++) AddTrack(random,ptmin);
  
  //Restore Object count 
  //To save space in the table keeping track of all referenced objects
  //we assume that our events do not address each other. We reset the 
  //object count to what it was at the beginning of the event.
  TProcessID::SetObjectCount(ObjectNumber);
}  

//______________________________________________________________________________
Track *Event::AddTrack(Float_t random, Float_t ptmin)
{
   // Add a new track to the list of tracks for this event.
   // To avoid calling the very time consuming operator new for each track,
   // the standard but not well know C++ operator "new with placement"
   // is called. If tracks[i] is 0, a new Track object will be created
   // otherwise the previous Track[i] will be overwritten.

   TClonesArray &tracks = *fTracks;
   Track *track = new(tracks[fNtrack++]) Track(random);
   //Save reference to last Track in the collection of Tracks
   fLastTrack = track;
   //Save reference in fHighPt if track is a high Pt track
   if (track->GetPt() > ptmin)   fHighPt->Add(track);
   //Save reference in fMuons if track is a muon candidate
   if (track->GetMass2() < 0.11) fMuons->Add(track);
   return track;
}

//______________________________________________________________________________
void Event::Clear(Option_t *option)
{
   fTracks->Clear("C"); //will also call Track::Clear
   fHighPt->Delete();
   fMuons->Delete();
}

//______________________________________________________________________________
void Event::Reset(Option_t *option)
{
// Static function to reset all static objects for this event
//   fgTracks->Delete(option);

   delete fgTracks; fgTracks = 0;
   fgHist   = 0;
}

//______________________________________________________________________________
void Event::SetHeader(Int_t i, Int_t run, Int_t date, Float_t random, 
                                                Int_t sec, Int_t nsec)
{
   fNtrack = 0;
   fEvtHdr.Set(i, run, date,sec,nsec);
   if (!fgHist) fgHist = new TH1F("hstat","Event Histogram",100,0,1);
   fH = fgHist;
   fH->Fill(random);
}

//______________________________________________________________________________
void Event::SetMeasure(UChar_t which, Int_t what) {
   if (which<10) fMeasures[which] = what;
}

//______________________________________________________________________________
void Event::SetRandomVertex() {
   // This delete is to test the relocation of variable length array
   if (fClosestDistance) delete [] fClosestDistance;
   if (!fNvertex) {
      fClosestDistance = 0;
      return;
   }
   fClosestDistance = new Float_t[fNvertex];
   for (Int_t k = 0; k < fNvertex; k++ ) {
      fClosestDistance[k] = gRandom->Gaus(1,1);
   }
}

//______________________________________________________________________________
Track::Track(Float_t random) : TObject()
{
   // Create a track object.
   // Note that in this example, data members do not have any physical meaning.

   Float_t a,b,px,py;
   gRandom->Rannor(px,py);
   fPx = px;
   fPy = py;
   fPz = TMath::Sqrt(px*px+py*py);
   fRandom = 1000*random;
   if (fRandom < 10) fMass2 = 0.106;
   else if (fRandom < 100) fMass2 = 0.8;
   else if (fRandom < 500) fMass2 = 4.5;
   else if (fRandom < 900) fMass2 = 8.9;
   else  fMass2 = 9.8;
   gRandom->Rannor(a,b);
   fBx = 0.1*a;
   fBy = 0.1*b;
   fMeanCharge = 0.01*gRandom->Rndm(1);
   gRandom->Rannor(a,b);
   fXfirst = a*10;
   fXlast  = b*10;
   gRandom->Rannor(a,b);
   fYfirst = a*12;
   fYlast  = b*16;
   gRandom->Rannor(a,b);
   fZfirst = 50 + 5*a;
   fZlast  = 200 + 10*b;
   fCharge = Float_t(Int_t(3*gRandom->Rndm(1)) - 1);
   fVertex[0] = gRandom->Gaus(0,0.1);
   fVertex[1] = gRandom->Gaus(0,0.2);
   fVertex[2] = gRandom->Gaus(0,10);
   fNpoint = Int_t(60+10*gRandom->Rndm(1));
   fNsp = Int_t(3*gRandom->Rndm(1));
   if (fNsp) {
      fPointValue = new Float_t[fNsp];
      for(int i=0; i<fNsp; i++) {
         fPointValue[i] = i+1;
      }
   } else {
      fPointValue = 0;
   }
   fValid  = Int_t(0.6+gRandom->Rndm(1));
}

//______________________________________________________________________________
HistogramManager::HistogramManager(TDirectory *dir)
{
   // Create histogram manager object. Histograms will be created
   // in the "dir" directory.

   // Save current directory and cd to "dir".
   TDirectory *saved = gDirectory;
   dir->cd();

   fNtrack      = new TH1F("hNtrack",    "Ntrack",100,575,625);
   fNseg        = new TH1F("hNseg",      "Nseg",100,5800,6200);
   fTemperature = new TH1F("hTemperature","Temperature",100,19.5,20.5);
   fPx          = new TH1F("hPx",        "Px",100,-4,4);
   fPy          = new TH1F("hPy",        "Py",100,-4,4);
   fPz          = new TH1F("hPz",        "Pz",100,0,5);
   fRandom      = new TH1F("hRandom",    "Random",100,0,1000);
   fMass2       = new TH1F("hMass2",     "Mass2",100,0,12);
   fBx          = new TH1F("hBx",        "Bx",100,-0.5,0.5);
   fBy          = new TH1F("hBy",        "By",100,-0.5,0.5);
   fMeanCharge  = new TH1F("hMeanCharge","MeanCharge",100,0,0.01);
   fXfirst      = new TH1F("hXfirst",    "Xfirst",100,-40,40);
   fXlast       = new TH1F("hXlast",     "Xlast",100,-40,40);
   fYfirst      = new TH1F("hYfirst",    "Yfirst",100,-40,40);
   fYlast       = new TH1F("hYlast",     "Ylast",100,-40,40);
   fZfirst      = new TH1F("hZfirst",    "Zfirst",100,0,80);
   fZlast       = new TH1F("hZlast",     "Zlast",100,0,250);
   fCharge      = new TH1F("hCharge",    "Charge",100,-1.5,1.5);
   fNpoint      = new TH1F("hNpoint",    "Npoint",100,50,80);
   fValid       = new TH1F("hValid",     "Valid",100,0,1.2);

   // cd back to original directory
   saved->cd();
}

//______________________________________________________________________________
HistogramManager::~HistogramManager()
{
   // Clean up all histograms.

   // Nothing to do. Histograms will be deleted when the directory
   // in which tey are stored is closed.
}

//______________________________________________________________________________
void HistogramManager::Hfill(Event *event)
{
   // Fill histograms.

   fNtrack->Fill(event->GetNtrack());
   fNseg->Fill(event->GetNseg());
   fTemperature->Fill(event->GetTemperature());

   for (Int_t itrack = 0; itrack < event->GetNtrack(); itrack++) {
      Track *track = (Track*)event->GetTracks()->UncheckedAt(itrack);
      fPx->Fill(track->GetPx());
      fPy->Fill(track->GetPy());
      fPz->Fill(track->GetPz());
      fRandom->Fill(track->GetRandom());
      fMass2->Fill(track->GetMass2());
      fBx->Fill(track->GetBx());
      fBy->Fill(track->GetBy());
      fMeanCharge->Fill(track->GetMeanCharge());
      fXfirst->Fill(track->GetXfirst());
      fXlast->Fill(track->GetXlast());
      fYfirst->Fill(track->GetYfirst());
      fYlast->Fill(track->GetYlast());
      fZfirst->Fill(track->GetZfirst());
      fZlast->Fill(track->GetZlast());
      fCharge->Fill(track->GetCharge());
      fNpoint->Fill(track->GetNpoint());
      fValid->Fill(track->GetValid());
   }
}


#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class EventTime+;
#pragma link C++ class EventVertex+;
#pragma link C++ class EventHeader+;
#pragma link C++ class Event+;
#pragma link C++ class HistogramManager+;
#pragma link C++ class Track+;

#endif



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:51:11 MET