Rene Brun
Witold Przygoda wrote:
> =
> Hallo,
> =
> excuse me if I repeat the well known question but this is
> a very important problem to me.
> =
> I will show it on an easy example.
> Imagine that I have hit class like this:
> =
> class MyHits : public TObject {
> =
> public:
> =
> int SimpleType;
> MyDataClass finalData[3];
> =
> // of course Streamer function defined in .cc file
> =
> MyHits();
> virtual ~MyHits();
> ClassDef(MyHits,1)
> =
> };
> =
> MyDataClass : public TObject {
> =
> int SimpleType;
> int someData[10];
> float *myArrayPtr;
> =
> // again I provide Streamer which takes care of pointer also
> =
> MyDataClass();
> virtual ~MyDataClass();
> ClassDef(MyDataClass,1)
> };
> =
> What I know:
> I can write it to one branch (just dumping data into one solid
> block without spliting). This works fine and I can read so
> created file, fill back data structure, make loops over events
> and fill some histograms.
> =
> What I would like and don=B4t know:
> It is demanded by some people to provide them much easier (and faster!)=
> way to access all data. I do not want to define the detailed (leaf by
> leaf) structure of my branch(es) but to stay with Streamer-mechanism.
> I know I can set up split mode and each variable will create another
> branch.
> =
> My question: I failed with having access to array myData (of type
> MyDataClass). The branch seems to be not created. Is it possible
> (and how) finally to have the access like
> T.Draw("simpleType");
> =
> also to T.Draw("myData[0].SimpleType");
> T.Draw("myData[1].someData");
> T.Draw("myData[1].someData[3]");
> (I know it is wrong what I write above but I hope it explains
> my wish). In other words how to use Streamer method of storing
> of my Class(es) into root-file (branch) and the pointers (keys) to all
> fields of my Class (and also fields of component which is of another
> class type).
> =
> Thank you a lot in advance,
> =
> Witek Przygoda
The rules for the split mode are described at URL:
http://root.cern.ch/root/HowtoWritTree.html
In particular, the split mode cannot support yet the case
of an array of objects. In your case, you also have a pointer
to an array of floats.
I have modified your classes, such that , at least, you can run
rootcint and use the non-split mode.
I also show an example of macro to generate a file with a Tree (wit.C)
and another macro to analyze this tree (wit2.C)
//file witold.h
#ifndef ROOT_event
#define ROOT_event
#include <TObject.h>
class MyDataClass : public TObject {
public:
int event;
int SimpleType;
int someData[10];
float *myArrayPtr;
// again I provide Streamer which takes care of pointer also
MyDataClass();
MyDataClass(const MyDataClass &dc);
virtual ~MyDataClass();
void SetType(int typ);
ClassDef(MyDataClass,1)
};
class MyHits : public TObject {
public:
int SimpleType;
MyDataClass finalData[3];
// of course Streamer function defined in .cc file
MyHits();
MyHits(const MyHits &mh);
virtual ~MyHits();
int Type(int n) {return finalData[n].SimpleType;}
int Data(int n, int i=3D0) {return finalData[n].someData[i];}
float ArrayPtr(int n, int i =3D 0) {return finalData[n].myArrayPtr[i];}
ClassDef(MyHits,1)
};
#endif
//--------file witold.C
#include "witold.h"
Int_t event =3D 0;
ClassImp(MyDataClass)
MyDataClass::MyDataClass()
{
SimpleType =3D 1;
for (int i=3D0;i<10;i++) someData[i]=3Di;
myArrayPtr =3D new float[8];
for (int j=3D0;j<8;j++) myArrayPtr[j] =3D 1.1+10.*j;
}
MyDataClass::MyDataClass(const MyDataClass &dc)
{
}
MyDataClass::~MyDataClass()
{
delete [] myArrayPtr;
myArrayPtr =3D 0;
}
void MyDataClass::SetType(int typ)
{
SimpleType =3D typ;
}
ClassImp(MyHits)
MyHits::MyHits()
{
SimpleType =3D 2;
}
MyHits::MyHits(const MyHits &mh)
{
}
MyHits::~MyHits()
{
}
//_______________________________________________________________________=
_______
void MyDataClass::Streamer(TBuffer &R__b)
{
// Stream an object of class MyDataClass.
if (R__b.IsReading()) {
Version_t R__v =3D R__b.ReadVersion(); if (R__v) { }
TObject::Streamer(R__b);
R__b >> SimpleType;
R__b.ReadFastArray(someData,10);
if (!myArrayPtr) myArrayPtr =3D new float[8];
R__b.ReadFastArray(myArrayPtr,8);
} else {
R__b.WriteVersion(MyDataClass::IsA());
TObject::Streamer(R__b);
R__b << SimpleType;
R__b.WriteFastArray(someData, 10);
R__b.WriteFastArray(myArrayPtr, 8); // I put a constant here
}
}
//_______________________________________________________________________=
_______
void MyHits::Streamer(TBuffer &R__b)
{
// Stream an object of class MyHits.
if (R__b.IsReading()) {
Version_t R__v =3D R__b.ReadVersion(); if (R__v) { }
TObject::Streamer(R__b);
R__b >> SimpleType;
int R__i;
for (R__i=3D0; R__i < 3; R__i++)
finalData[R__i].Streamer(R__b);
} else {
R__b.WriteVersion(MyHits::IsA());
TObject::Streamer(R__b);
R__b << SimpleType;
int R__i;
for (R__i=3D0; R__i < 3; R__i++)
finalData[R__i].Streamer(R__b);
}
}
//--------file wLinkDef.h
#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class MyDataClass-;
#pragma link C++ class MyHits-;
#endif
//--example of commands to run rootcint/compile on hp-ux
rootcint -f wcint.C -c witold.h wLinkDef.h
CC +a1 +z -I$ROOTSYS/include -c wcint.C witold.C
CC -b -g +a1 -z wcint.o witold.o -o witold.so
//------example of macro to generate a Tree (wit.C)
{
gROOT->Reset();
gSystem->Load("witold.so");
TFile f("witold.root","recreate");
MyHits *mh =3D new MyHits();
TTree *T =3D new TTree("T","witold tree");
T->Branch("hits","MyHits",&mh,32000,0);
=
for (Int_t i=3D0;i<100;i++) {
mh->finalData[0].SetType(i);
mh->finalData[1].SetType(1000+i);
mh->finalData[2].SetType(2000+i);
T->Fill();
}
T->Print();
T->Write();
}
//------example of macro toanalyze the Tree (wit2.C)
{
gROOT->Reset();
gSystem->Load("witold.so");
TFile f("witold.root");
MyHits *mh =3D new MyHits();
TTree *T =3D (TTree*)f.Get("T");
T->SetBranchAddress("hits",&mh);
TH1F *h1 =3D new TH1F("h1","Types",100,0,3000);
Int_t nentries =3D T->GetEntries();
for (Int_t i=3D0;i<nentries;i++) {
T->GetEvent(i);
h1->Fill(mh->Type(0));
h1->Fill(mh->Type(1));
h1->Fill(mh->Type(2));
}
h1->Draw();
}