SetBranchAddress in pyroot when reading from a TChain

Hi,

I’ve attached a very simple python script (ROOT is ‘5.34/10’) that tries to read an int from a branch using SetBranchAddress.
I compile a C struct that has a single data member and then use TChain::SetBranchAddress to have the
branch point to the struct member using ROOT.AddressOf().

import ROOT
c = ROOT.TChain('Events')
c.Add('histo.root')
ROOT.gROOT.ProcessLine('.L struct1.C')
s=ROOT.MyStruct_0_0()
c.SetBranchAddress("ngoodVertices", ROOT.AddressOf(s, "ngoodVertices"))
c.GetEntry(0)
print s.ngoodVertices, c.ngoodVertices, c.GetLeaf('ngoodVertices').GetValue()

However, the last print statement gives

1103626240 25.0 25.0

hence, the struct does not have the correct value, while other accessors do work.

I must be doing something basic that is wrong but a similar code that instead writes to a TTree does in fact work.
If somebody could have a brief look I’d be happy.

The zip attached should be self contained.

Cheers,
Robert
test.tar.gz (43.9 KB)

Float_t ngoodVertices;

Yes, this was a stupid error on my side that I introduced when I stripped off any CMS related includes.
Thank you, the script works now.

Maybe there is a similar triviality going on in the original problem.
I do not know whether it is possible for you to look at ngoodVertices in
/afs/hephy.at/scratch/s/schoefbeck/CMS/CMSSW_7_0_6_patch1/src/Workspace/RA4Analysis/CSA14/tmp/histoEDM.root
It is an alias to int_BasicTupelizer_ngoodVertices_Tupelizer.obj
and c.GetBranch(‘int_BasicTupelizer_ngoodVertices_Tupelizer.obj’).GetTypeName() gives ‘Int_t’

I use

struct MyStruct_0_0{ Int_t ngoodVertices; };
which you can find in
/afs/hephy.at/scratch/s/schoefbeck/CMS/CMSSW_7_0_6_patch1/src/Workspace/RA4Analysis/CSA14/tmp/struct2.C

The script at
/afs/hephy.at/scratch/s/schoefbeck/CMS/CMSSW_7_0_6_patch1/src/Workspace/RA4Analysis/CSA14/tmp/test2.py
does show a similar problem though.
The relevant piece is

ROOT.gROOT.ProcessLine('.L struct2.C')
s=ROOT.MyStruct_0_0()
c.SetBranchAddress(c.GetAlias("ngoodVertices"), ROOT.AddressOf(s, "ngoodVertices"))
c.GetEntry(0)
print s.ngoodVertices,  c.GetLeaf(c.GetAlias("ngoodVertices")).GetValue()

It gives some warnings for missing dictionaries but I checked that the result is independent of the includes.
The print gives

2054749928 17.0

I guess I’m overlooking another stupid thing?

Thanks,
Robert

You are trying to retrieve a subbranch “obj” which belongs to a master branch “int_BasicTupelizer_ngoodVertices_Tupelizer.” (note the dot character at the end of the master branch name), so you’ve got objects which were written with splitlevel >= 1.
I’d say this kind of games is reserved for “advanced users” only, so you’re asking for trouble.
You’ better have a look at an “analysis skeleton”: Export leaf histogram to ascii
test2.py (619 Bytes)

Thanks a lot!

Hi Wile,

I read the MakeClass documentation but the problem is that it creates a very large class even when I mute branches with SetBranchStatus. Moreover, I would have to edit it and this is difficult on the fly.

I follow the parallel thread on a very similar issue.
I would like to read floats_JetTupelizer_jetsPt_Tupelizer.obj from a file like this:

*............................................................................* *Branch :floats_JetTupelizer_jetsPt_Tupelizer. * *Entries : 46106 : BranchElement (see below) * *............................................................................* *Br 150 :floats_JetTupelizer_jetsPt_Tupelizer.present : Bool_t * *Entries : 46106 : Total Size= 51880 bytes File Size = 5597 * *Baskets : 40 : Basket Size= 12292 bytes Compression= 9.05 * *............................................................................* *Br 151 :floats_JetTupelizer_jetsPt_Tupelizer.obj : vector<float> * *Entries : 46106 : Total Size= 4449329 bytes File Size = 3593456 * *Baskets : 47 : Basket Size= 126976 bytes Compression= 1.24 * *............................................................................*

but the code at

does not work:

import ROOT
import sys, glob
ROOT.gROOT.ProcessLine(
        "struct var_t { std::vector<float> jetsPt; };")
files = ["/afs/hephy.at/scratch/s/schoefbeck/CMS/CMSSW_7_0_6_patch1/src/Workspace/RA4Analysis/CSA14/tmp/histoEDM.root"]
chain = ROOT.TChain("Events")
for file in files:
    print "Adding file: " + file
    chain.Add(file)
chain.SetMakeClass(1)
chain.SetBranchStatus("*", 0)
entries = chain.GetEntries()
print "Number of entries = " + str(entries)
var = ROOT.var_t()
chain.SetBranchStatus("floats_JetTupelizer_jetsPt_Tupelizer.obj", 1)
chain.SetBranchAddress("floats_JetTupelizer_jetsPt_Tupelizer.obj", ROOT.AddressOf(var, "jetsPt"))
print var.jetsPt
chain.GetEntry(0)

In fact, the GetEntry hangs. Any idea why?
In a first attempt with many such products I produced a segfault.

Thanks,
Robert

OK, I think I fixed it.

The point is to compile the class in the processline.

Future CMS users trying to evade fwlite for some reason or the other may
try to do something like

...

ROOT.gROOT.ProcessLine('.L MyClass.C+')

...

chain.SetMakeClass(1)
chain.SetBranchStatus("*", 0)
entries = chain.GetEntries()

chain.SetBranchStatus("floats_JetTupelizer_jetsPt_Tupelizer.obj", 1)
chain.SetBranchAddress("floats_JetTupelizer_jetsPt_Tupelizer.obj", ROOT.AddressOf(var, "jetsPt"))

where

#ifndef MyStruct #define MyStruct #include<vector> struct var_t { std::vector<float> jetsPt; }; #endif