Read a TTree containing Event class with several layers

Hi there !

I just signed up to this forum – Thanks for being there !

I’m using a C++ Event class with several layers (Each event has a vector of detector stations, each detector station has a vector of detector channels) to write a tree within a C program (find the class definitions attached in a tar archive).

I want to use python to read the tree from the file. In principle, I want to implement pyROOT code corresponding to the c program read.c – which works fine – in the attachment. My naive conversion to python code does not work because I don’t know how to pass the pointer of my Event class instance to the SetAddress method:

root_file = TFile ('20TeV_Gamma.root')
data = root_file.Get('data')
EventInstance = Event()
EventBranch = data.GetBranch('Event')

### here comes the problematic part: ###
EventBranch.SetAddress(EventInstance)
nentries = data.GetEntriesFast()
print 'data tree has %d entries.' % nentries
for ientry in range(0,nentries):
  data.GetEntry(ientry)
  for istation in range(0,EventInstance.DetectorStationVector.size()):
    nphotons = EventInstance.DetectorStationVector.at(istation).DetectorChannelVectoEventBranch..at(0).hTime.Integral(1,4000)
    print "nphotons = %f" % nphotons

I tried to use EventBranch.SetAddress(byref(EventInstance)) which didn’t help. Checking the value of data.Event.DetectorStationVector, I get something which makes sense:

print data.Event.DetectorStationVector

<ROOT.vector object at 0x944e998>

Maybe this is a point where I can further build some usefule code ?

I’d be gratefule for any input !

Cheers,
Martin
class_files_and_code.tar.gz (236 KB)

Martin,

you can either do this on the tree:data.SetBranchAddress( 'Event', EventInstance )
as the SetBranchAddress() is explicitly pythonized to do the right thing when given a PyROOT-bound object, be it the object itself or an address to it. Or you can do:EventBranch.SetAddress( ROOT.AddressOf( EventInstance ) )
where you have to explicitly use AddressOf(), b/c TBranch::SetAddress() is not pythonized.

HTH,
Wim

Hi Wim,
thanks a lot, that works ! However, now I ran into trouble retrieving the vectors in the Event Branch. I tried:

for ientry in range(0,nentries):
  data.GetEntry(ientry)
  print EventInstance.MCEnergy
  dsv = ROOT.MakeNullPointer( ROOT.vector("DetectorStation") )
  dsv = EventInstance.DetectorStationVector
  print dsv
  print dsv.size()

The output is:
TH1::Build:0: RuntimeWarning: Replacing existing histogram: hTime0_0_0 (Potential memory leak).
20.0
<ROOT.vector object at 0x97e4b40>
Traceback (most recent call last):
File “readv2.py”, line 36, in ?
print dsv.size()
AttributeError: 'vector<DetectorStation,allocator ’ object has no attribute ‘size’

I tried different things but am confused. How can I properly use my vector in python ?

Thank you,
Martin

Martin,

should be the same way as when using it in CINT: by providing a dictionary. In the example code you were pre-loading a .so. Perhaps the dictionary is already available in a release? If not, you can use ACLiC, with e.g. MyDict.h as:[code]#include “DetectorStation.h”
#include

#ifdef CINT
#pragma link C++ class std::vector< DetectorStation >;
#pragma link C++ class std::vector< DetectorStation >::iterator;
#else
template class std::vector< DetectorStation >;
#endif[/code]
and in the python code:ROOT.gROOT.LoadMacro( 'MyDict.h+' )
HTH,
Wim