GetListOfLeaves() for branches with vectors

Hello,

I am trying to read a dummy tree with two branches: the first one, with name ‘particle’, contains objects of some class (Susy::Particle, but in general it could be any non-basic type); the second one, with name ‘partVec’, contains a std::vector of the same type of objects. The dictionary for this object is generated with rootcint, and loaded at runtime as a shared library.
What I am trying to do is:

  • determine the type of each leaf
  • allocate an object of that type
  • do a TBranch::SetBranchAddress(AddressOf(object)) and read the tree re-using the object initially allocated

While this seems to be doable for the branch with a single object, I am having some difficulty with the case where the branch holds a vector. In particular, I cannot determine the type with

br.GetLeaf(l.GetName()).GetTypeName(). An example code showing this is below:

#!/bin/env python                                                                                                                                                                                         

import ROOT as r

r.gSystem.Load("libPhysics.so")
r.gSystem.Load("/tmp/supy-dev/supy//cpp/libSusy.so")
filename='/tmp/supy-dev/supy/tests/wrapobject/nonflat_typetree.root'
f = r.TFile.Open(filename)
tree = f.tree
branchnames = ['particle','partVec']

line = '-'*64
buffers = {}

for branchname in branchnames :
    print line
    br = tree.GetBranch(branchname)
    print 'branch ',branchname,' with type ',type(br)
    print 'list of leaves for branch ',br.GetName()
    for l in br.GetListOfLeaves():
        lname, ltype = l.GetName(), br.GetLeaf(l.GetName()).GetTypeName()
        print '-> ',lname,' with type ',ltype
        # # the following two lines do not work for vectors                                                                                                                                               
        # rootKnownType = getattr (r, ltype)                                                                                                                                                              
        # buffers[lname] = rootKnownType()                                                                                                                                                                
print line
print 'rely on PyROOT automagic'
tree.GetEntry(0)
for bn in branchnames :
    br = getattr(tree, bn)
    print 'tree.',bn,' : ',type(br)

producing this output:

$ python dumpinfo.py
----------------------------------------------------------------
branch  particle  with type  <class '__main__.TBranchElement'>
list of leaves for branch  particle
->  particle  with type  Susy::Particle
----------------------------------------------------------------
branch  partVec  with type  <class '__main__.TBranchElement'>
list of leaves for branch  partVec
->  partVec_  with type  Int_t
----------------------------------------------------------------
rely on PyROOT automagic
tree. particle  :  <class '__main__.Susy::Particle'>
tree. partVec  :  <class '__main__.vector<Susy::Particle,allocator<Susy::Particle> >'>

I do not understand why the “vector branch” apparently has one leaf with type ‘Int_t’.
However, I see that the default PyROOT branch access can correctly determine that the branch holds a “vectorSusy::Particle”, so it should be possible to do the same in my test.
Could someone please advise me on how this can be done?

Best regards,

Davide

P.S. the code to create the dummy tree is available at the following link, although what I describe is not specific to this tree or class:
github.com/elaird/supy/blob/dev … lat.py#L46
The dictionary generation happens here : github.com/elaird/supy/blob/dev … p/Makefile

Hi,

the relevant code from TTreeGetAttr from Pythonize.cxx:[code]
// search for branch first (typical for objects)
TBranch* branch = tree->GetBranch( name );
if ( ! branch ) {
// for benefit of naming of sub-branches, the actual name may have a trailing '.'
branch = tree->GetBranch( (std::string( name ) + ‘.’ ).c_str() );
}

  if ( branch ) {
  // found a branched object, wrap its address for the object it represents
     TClass* klass = TClass::GetClass( branch->GetClassName() );
     if ( klass && branch->GetAddress() )
        return BindRootObjectNoCast( *(char**)branch->GetAddress(), klass );
  }[/code]

So, for objects, you’ll want to use branch.GetClassName(), instead of the type name returned by the leaf.

HTH,
Wim

Thank you, Wim!
That’s exactly what I was trying to do.
Cheers,

Davide