How to read TTree with two branches using the same struct?

Hi,

I have a TTree created by the code shown here:

[code]#include “TTree.h”
#include “TFile.h”
#include “TRandom2.h”
typedef struct {
unsigned bin[2];
float eff_a[2], eff_b[2];
} MyStruct;

void test_struct() {
TFile *f= new TFile(“test_struct.root”, “RECREATE”);
TTree *T= new TTree(“T”,“T”);
MyStruct s1, s2;
T->Branch(“s1”, &s1, “bin[2]/i:eff_a[2]/F:eff_b[2]”);
T->Branch(“s2”, &s2, “bin[2]/i:eff_a[2]/F:eff_b[2]”);

TRandom2 rnd;
for ( int i=0; i<10; i++) {
s1.bin[0]= i;
s1.bin[1]= i10;
s1.eff_a[0]= rnd.Uniform();
s1.eff_a[1]= rnd.Uniform();
s1.eff_b[0]= rnd.Uniform();
s1.eff_b[1]= rnd.Uniform();
s2.bin[0]= 100+i;
s2.bin[1]= 100+i
10;
s2.eff_a[0]= rnd.Uniform();
s2.eff_a[1]= rnd.Uniform();
s2.eff_b[0]= rnd.Uniform();
s2.eff_b[1]= rnd.Uniform();
T->Fill();
}
T->Write();
f->Close();
}
[/code]

which has two branches using the same C struct

[code]root [1] T->Print()


*Tree :T : T *
*Entries : 10 : Total = 2238 bytes File Size = 1090 *

  •    :          : Tree compression factor =   1.01                       *
    

*Br 0 :s1 : bin[2]/i:eff_a[2]/F:eff_b[2] *
*Entries : 10 : Total Size= 958 bytes File Size = 300 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.02 *

*Br 1 :s2 : bin[2]/i:eff_a[2]/F:eff_b[2] *
*Entries : 10 : Total Size= 958 bytes File Size = 304 *
*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.01 *

[/code]

How do I read it using pyroot? I can just do T.bin[0], I will get the one in the first branch, not the second. Looking at the example in $ROOTSYS/tutorials/pyroot/staff.py, I am still not sure how to get the second branch. (A small root file is attached)
test_struct.root (5.49 KB)

Hi,

you’d have to create s1 and s2 structs to hold the values and use SetBranchAddress(), like you would in C++. The shortcut using member access does not work as it would require a two-step lookup (T.s2.bin), and the internal code is only expecting one step.

As an alternate, you could change the labels in the .C code by calling them bin2, etc. They’re just labels and do not need to match the member names in the struct.

Cheers,
Wim

Thanks. This works.

#!/usr/bin/env python from ROOT import * gROOT.ProcessLine( "struct MyStruct {\ unsigned bin[2];\ float eff_a[2], eff_b[2];\ } ;"); T = TChain("T") T.Add("test_struct.root") s1= MyStruct() s2= MyStruct() T.SetBranchAddress("s1", AddressOf(s1, "bin") ); T.SetBranchAddress("s2", AddressOf(s2, "bin") ); for i in xrange(T.GetEntries()): T.GetEntry(i) print s1.bin[0], s1.bin[1], s2.bin[0], s2.bin[1] print s1.eff_a[0], s1.eff_a[1], s2.eff_a[0], s2.eff_a[1] print s1.eff_b[0], s1.eff_b[1], s2.eff_b[0], s2.eff_b[1]