How to use SetBranchAddress in pyroot?

Dear CRAB expert:

/afs/cern.ch/sw/lcg/app/releases/ROOT/5.26.00/x86_64-slc5-gcc43-opt/root/tutorials/pyroot/staff.py shows us how to read data from an ascii file and create a root file with a Tree.

But how to read a tree in pyroot, e.g. how to apply milk1->SetBranchAddress(“production”,&production) in pyroot? Do we have such an example? I can’t find such example in /afs/cern.ch/sw/lcg/app/releases/ROOT/5.26.00/x86_64-slc5-gcc43-opt/root/tutorials/pyroot/..

Thanks,Gang

Here is what I would like to do, I think I need to call ‘SetBranchAddress’ before defining mlp1:

def test(list0,list1,list2,list3,list4,list5):

    train_file = TFile("milk.root","read")
    milk =  train_file.Get("milk")
    milk.SetBranchAddress("price5",AddressOf(milk,'price5'))
    milk.SetBranchAddress("price4",AddressOf(milk,'price4'))
    milk.SetBranchAddress("price3",AddressOf(milk,'price3'))
    milk.SetBranchAddress("price2",AddressOf(milk,'price2'))
    milk.SetBranchAddress("price1",AddressOf(milk,'price1'))
    milk.SetBranchAddress("price0",AddressOf(milk,'price0'))
    mlp1 = TMultiLayerPerceptron("price0,price1,price2,price3,price4:10:price5",milk)
    mlpa = TMLPAnalyzer(mlp1)
    mlpa.GatherInformations()
    mlpa.CheckNetwork()
    mlp1.LoadWeights("milk.txt")
    for i in range(len(list5)):
            params = array( 'd', [0.]*5 )
            params[0] = list0[i]
            params[1] = list1[i]
            params[2] = list2[i]
            params[3] = list3[i]
            params[4] = list4[i]
            val = mlp1.Evaluate(0,params)
    del mlp1

But seems milk.SetBranchAddress(“price0”,AddressOf(milk,‘price0’)) is not a correct format, then how should I change it?

Gang,

did you add the gROOT.ProcessLine() to define the “milk” data structure? Beyond that, the AddressOf() should take an instance of that data structure, not the TTree instance.

[code]gROOT.ProcessLine(
“struct milk_t {
Float_t price5;
Float_t price4;
Float_t price3;
Float_t price2;
Float_t price1;
Float_t price0;
}” )

train_file = TFile(“milk.root”,“read”)
milk_tree = train_file.Get(“milk”)

milk = milk_t()

milk_tree.SetBranchAddress(“price5”,AddressOf(milk,‘price5’))[/code]
Cheers,
Wim

Hi, wlav:

I used the following script to read a tree but seems there is some problem:

from ROOT import *
import re, array
from array import array

gROOT.ProcessLine(
“struct staff_t {
Float_t e1;
Float_t e2;
Float_t e3;
Float_t e4;
Float_t e5;
Float_t e6;
Float_t e7;
Float_t e8;
Float_t e9;
Float_t e10;
Float_t e11;
Float_t e12;
Float_t e13;
Float_t e14;
Float_t e15;
Float_t e16;
Float_t e17;
Float_t e18;
Float_t e19;
Float_t e20;
Float_t e21;
Float_t e22;
Int_t type;
}” )

def main():
fout = TFile("…/ntuple/SinglePhotonPt70.root",“read”)
tree_shape = fout.Get(“shape”)
staff = staff_t()
tree_shape.SetBranchAddress(“e17”,AddressOf(staff,“e17”))
tree_shape.SetBranchAddress(“e18”,AddressOf(staff,“e18”))
ntrain = 200
tree_shape.GetEntry(3)
print staff.e17
fout.Close()

if name == ‘main’:
main()

[qing1981] /home/qing/mlp/HG/frontandrear/row0/train > python train.py
-2.0

But running directly in ROOT enviroment I see:
root [8] TFile *f = new TFile(“SinglePhotonPt70.root”,“r”)
root [8] TTree shape = f->Get(“shape”)
root [7] shape.Show(3)
======> EVENT:3
e1 = 0.000301376
e2 = 6.96881e-05
e3 = 0.000457254
e4 = 0.00300541
e5 = 0.00195023
e6 = 0
e7 = 0.000273012
e8 = 0.000194536
e9 = 0
e10 = 0
e11 = 0
e12 = 0.000434826
e13 = 0
e14 = 0.000269296
e15 = 0.000755217
e16 = 0.00070135
e17 = 0.0011846
e18 = 0.00373352
e19 = 0.00198983
e20 = 0.000322323
e21 = 0
e22 = 0
type = 1

They give different values, one is -2.0 , the other is 0.0011846, any idea?

Thanks,Gang

Gang,

w/o the file to reproduce, it would be hard to see. However, are you certain that this:fout = TFile("../ntuple/SinglePhotonPt70.root","read") and this root [8] TFile *f = new TFile("SinglePhotonPt70.root","r") are pointing to the same file?

Cheers,
Wim

Dear wlav:

The file is > 2MB and can not be uploaded. I put it at qing@lxplus.cern.ch:./public/SinglePhotonPt70.root.

Thanks,Gang

Gang,

if you do tree_shape.Print(), you will find that e1 through e22 are doubles, not floats. Thus, if you change the declaration of staff_t to use Double_t rather than Float_t, you will find that this all works.

Note that this is why I tend to recommend to simply do: tree_shape.GetEntry(3) print tree_shape.e17
and not use SetBranchAddress. Sure, that is a bit slower in execution, but at least the type (which ROOT has stored with the tree) will be correct.

Cheers,
Wim

Hi, Wlav:

Thanks, now it works. But I have one more question, I want to read all leaves automatically, but the following doesn’t work:

list_leaf = [e1,e2,e3,e4,e5]
for i in range(len(list_leaf)):
for j in range(tree_shape.GetEntries()):
tree_shape.GetEntry(j)
print tree_shape.list_leaf[i]

it does not work of course. How should I change the code to reach this purpose?

Thanks,Gang

Gang,

not understanding that code at all. I’ll assume that the e1 etc. in the leaf_list are strings? If so getattr(shape_tree, leaf_list[i]) should do the trick.

Cheers,
Wim

Hi, wlav:

Yes, this is exactly what I want.

Cheers,Gang

Hello everybody,

i’m quite new to python and pyROOT. I have used ROOT with CINT a little, but decided that for future learing i want to use pyroot, which seems to me a lot more comfortable in some ways.
I found my problem to fit in this thread, so i thought it best to post here.

My problem is the following:
I have root files like the one attached, and want to add them to a Chain and access the leafs in a loop.
With CINT i needed to define doubles x1 and x2 and use

TChain *c1 = new TChain("t1");
c1->Add("data.root");
c1->SetBranchAddress("x1",&x1);
c1->SetBranchAddress("x2",&x2);
for (int i=0; i<(c1->GetEntries());++i){
	c1->GetEntry(i);
	atgraph->SetPoint(i,x1,x2);
}

I want to use c1.GetEntry() with pyroot likewise, but can’t get it to work.
This thread hasn’t helped me too much.
In this one however:

is a solution quite related to what i need, it’s a bit complicated though …
if someone could help, i’d be delighted :slight_smile:. regards,
Martin

edit: attachment added
data.root (15.5 KB)

Martin,

it’s better to start a new thread than to reply to an ancient one: your question will be more visible that way.

At issue is that you can not take the address of a double in Python: you’d have to resort to the data members of a struct or to an array of size 1. None of those solution will look pretty.

This may be easier, and seems to be what you want:from ROOT import TChain c1 = TChain('t1') c1.Add('data.root') for event in c1: print event.x1, event.x2
Cheers,
Wim

ok, i’ll remember that.

The solution is superb! Thank you Wim.

Hi experts,

This is what I usually do and it works. Regardless of moving “struct” in C to Python, maybe a simple example would make sense.

var1 = array( 'i', [0] )
tree.SetBranchAddress( "var1", var1 )
	
for i in range( tree.GetEntries() ):
	tree.GetEntry( i )
	print var1[0]

Then it would iterate through individual entry and prints the corresponding “var1”

If things get more complex and now you want to add a new branch which is a array to a different tree, you just need to alter your code a bit, basically the same idea. Use jets_pt as an example,

mxlen = 20
jets_pt = array( 'd', mxlen*[ 0 ] )
treeOUT.Branch( "jets_pt", jets_pt, "jets_pt/D" )

for i in range( treeIN.GetEntries() ) :
	treeIN.GetEntry( i )
	for k in range( len( treeIN.jets_pt ) ) :
		jets_pt[ k ] = treeIN.jets_pt[ k ]
	treeOUT.Fill()

then you could update a new branch to your output tree without changing any existing branches.

credits: http://wlav.web.cern.ch/wlav/pyroot/tpytree.html

Cheers,
Nelson

2 Likes