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.