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