Calling TTree::Branch() with class argument

Hi Root-ers,
I am using ROOT 3.10/02 10 February 2004 and gcc 2.95.4.

I am using an application of Geant4 (version 4.4.0) to MC an experiment. (I know this isn’t a G4 forum - please keep reading just for a minute!) I linked the ROOT libraries to it, so inside the code I can easily instantiate a TTree. I have also written a few classes which I want to use as the Branches of my tree. I can make instances of my classes inside the G4 as well. The problem is that I cannot call TTree::Branch(“instance_of_myClass”,“myClass”,&instance_of_myClass) with my own classes. The documentation page (root.cern.ch/root/html/TTree.html#TTree:Bronch) seems to indicate that classes used for Branch do not need to derive from TObject, however the “class dictionary must be available”. Does this require putting ClassDef() in the header and ClassImp() in the definition after all?
Another question is what does it mean to make the library available? When I make my classes derive from TObject, I can compile them into a shared object i.e. libAllMyClasses.so. From the command line in ROOT I can load this library and use my classes. I have tried adding this library into my G4 Makefile, but in linking I get the error:

/.autofs/home/asharp/work/mulan/tmp/Linux-g++/mulan/libmulan.a(TReadoutWorld.o): In function TReadoutWorld type_info function': /home/asharp/work/mulan/src/TReadoutWorld.cc:45: undefined reference toTReadoutBranch::IsA(void) const’
/home/asharp/work/mulan/src/TReadoutWorld.cc:45: undefined reference to TReadoutBranch::ShowMembers(TMemberInspector &, char *)' /home/asharp/work/mulan/src/TReadoutWorld.cc:45: undefined reference toTReadoutBranch::Streamer(TBuffer &)’
/home/asharp/work/mulan/src/TReadoutWorld.cc:45: undefined reference to TReadoutBranch type_info function' /home/asharp/work/mulan/src/TReadoutWorld.cc:45: undefined reference toTReadoutBranch type_info node’
/.autofs/home/asharp/work/mulan/tmp/Linux-g++/mulan/libmulan.a(TReadoutBranch.o): In function __static_initialization_and_destruction_0': /home/asharp/work/mulan/src/TReadoutBranch.cc:2: undefined reference toROOT::GenerateInitInstance(TReadoutBranch const *)’
/.autofs/home/asharp/work/mulan/tmp/Linux-g++/mulan/libmulan.a(TReadoutBranch.o): In function TReadoutBranch::TReadoutBranch(void)': /home/asharp/work/mulan/src/TReadoutBranch.cc:5: undefined reference toTReadoutBranch virtual table’
after I declare the branch (which works) but try to put it into the tree.

I have also tried removing all ROOT references and compiling my classes with the G4 source; however in that case I get the ROOT error:
Error in TTree::Bronch: Cannot find class:TReadoutWorld
because ROOT doesn’t know about the classes.

If you care to read on, here is the relevant snippet of my code. rootFile and DataTree are already declared in the header. I am trying to make an instance of TReadoutWorld class and use it as a branch of DataTree. Note that TReadoutWorld derives from public TReadoutBranch, which is the reason for the two constructor messages which appear in the output.

MulanDetectorSD::MulanDetectorSD(G4String name)
:G4VSensitiveDetector(name)
{
<<<<<>>>>>>>

G4cout<<“MulanDetectorSD instantiating…”;
DataTree = new TTree(“DataTree”,“ROOT tree for G4 data”);
DataTree->SetDirectory(rootFile);

G4cout<<"\ncalling a new TReadoutWorld"<<G4endl;
TReadoutWorld *worldBranch = new TReadoutWorld();
DataTree->Branch(“worldBranch”,“TReadoutWorld”,&worldBranch);
DataTree->Print();

G4cout<<" done"<<G4endl;
<<<>>>>

}

Although this compiles, when it runs I see this:

MulanDetectorSD instantiating…
calling a new TReadoutWorld // this from the cout above
This is TReadoutBranch::TReadoutBranch() // TReadoutBranch constructor
This is TReadoutWorld::TReadoutWorld() // TReadoutWorld constructor
Error in TTree::Bronch: Cannot find class:TReadoutWorld


*Tree :DataTree : ROOT tree for G4 data *
*Entries : 0 : Total = 223 bytes File Size = 0 *

  •    :          : Tree compression factor =   1.00                       *
    

done

If anyone can help me figure this out - whether the classes have to derive from TObject, and in that case how to link them to my Geant4 application correctly; or, how to make TTree::Branch recognize my classes as valid branches, I would be exceedingly grateful. Thank you very much already for reading this far!!

Best regards,
Andrea Sharp

Hi Andrea,

With versions 3.10/02 or newer, a top level class in a Tree
-does not need to derive from Tobject
-does not need to have a ClassDef or a ClassImp
-but it must have a dictionary
see short example below with aclass.h and aclasstest.C
in a root session just execute .x aclasstest.C

//file aclass.h
class aclass{
public:
aclass() {fA=0; fB=0;}
aset( int a=1,int b=2) {fA=a; fB=b;}

virtual ~aclass( ){;}

private:
int fA;
int fB;
};

//file aclasstest.C
void aclasstest() {
gROOT->ProcessLine(".L aclass.h+");
TFile f(“aclass.root”,“recreate”);
TTree *T = new TTree(“T”,“test”);
aclass *a = new aclass;
T->Branch(“top”,“aclass”,&a,16000,99);
for (int i=0;i<1000;i++) {
a->aset(i,i+1000);
T->Fill();
}
T->Print();
T->Write();
}

Instead of using ACLIC as above, you can generate the dictionary by calling rootcint and create a shared lib with the object module.

Rene

Hi Rene,

Thank you for the code. It turns out that my classes are derived from TObject and the libClassname.so builds correctly. The problem was my makefile for G4; LD_LIBRARY_PATH did not contain the directory where libClassname.so was residing. When it was added, the TTree::Branch call worked just fine.
Best regards,
Andrea Sharp