Filling mixed typed TTree with Python

Hi,

I want to fill a TTree with mixed typed values using Python. I followed this tutorial: https://root.cern.ch/how/how-write-ttree-python and below is my attempt for different data types (Int_t and Double_t):

#!/usr/bin/env python3

from ROOT import TFile, TTree
from ROOT import gROOT

gROOT.ProcessLine(r'''
struct MyStruct {
   Int_t a;
   Double_t b;
};
''');
 
from ROOT import MyStruct

f = TFile('test.root', 'recreate')
t = TTree('t', 't')

mystruct = MyStruct()
t.Branch('mystruct', mystruct, 'a/I:b/D')

mystruct.a = 1
mystruct.b = 2.
t.Fill()

f.Write()
f.Close()

The resulting TTree has valid entries for a, but not for b, i.e. in this case b is zero (instead of 2), but I also recognized other (invalid) values when filling entries in a loop. When I use the same data type for both, a and b (similar to the case in the tutorial) everything works fine.

Can you help me to fix this issue?

Best regards.


ROOT Version: 6.16/00
Platform: Not Provided
Compiler: Not Provided


Hi,

I can reproduce the same behaviour also in C++:

{

struct MyStruct { Int_t a; Double_t b; };

TFile f("testcpp.root", "recreate");
TTree t("t", "t");

MyStruct mystruct;
t.Branch("mystruct", &mystruct, "a/I:b/D");

mystruct.a = 1;
mystruct.b = 2.;
t.Fill();

f.Write();
f.Close();

}

If instead of a double I use a float for b, the value is stored correctly.

@pcanal do you know what we are missing?

1 Like

I think it has to do with ROOT expecting contiguous memory for the consecutive members of a struct or object. An odd number of integers leaves a “gap” before the double, which breaks ROOT. So either ensure you have an even number of ints before a double, or put the integers after the doubles, e.g.:

struct MyStruct {
   Double_t b;
   Int_t a;
};

Ok. Thanks for your help. So I guess, it is not a good idea to mix more than two different data types in one struct.

I stopped using objects/structures inside TTrees because of this :slight_smile: but they can be used, just being mindful of the order and sizes.

You can take padding into account and add dummy char[xx] fields so everything is properly aligned. (But beware of 32b/64b)

Or use __attribute__((packed)) (but that isn’t standardized, afaik)

Or simply sort from the ‘largest’ to the ‘smallest’ data type (i.e. double first, then 64 bits longs, and float and 32 bits longs, etc …)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.