Problem filling struct into a branch

Hi,

I observe some weired behaviour of the values filled into a branch with the following example macro:

(ROOT version 4.04/02b, but also observed with 5.13/03)

[code]{
gROOT->Reset();
struct p{
int var1;
double var2;
float var3;
float var4;
};

p myp;

TFile fout(“outfile.root”,“RECREATE”);

TTree *mytree = new TTree(“MyTree”,"");
mytree->Branch(“mybranch”, &myp.var1, “var1/I:var2/D:var3/F:var4/F”);

double xmin = 0.;
double xmax = 50.;

for(int i=0; i<10000; i++){
myp.var1 = int(gRandom->Uniform(xmin,xmax));
myp.var2 = double(gRandom->Uniform(xmin,xmax));
myp.var3 = float(gRandom->Uniform(xmin,xmax));
myp.var4 = float(gRandom->Uniform(xmin,xmax));

mytree->Fill();
}
fout.Write();
fout.Close();
}
[/code]

The macro fills four variables of different types with uniform random numbers between 0 and 50. The variables are combined into a struct, and a new TTree is defined to hold the struct in a branch. When I look at the produced file 'outfile.root; using TBrowser, the variable var2 cannot be plotted, the error message is

[quote]root [2] TCanvas::MakeDefCanvas: created default TCanvas with name c1
Error in TCanvas::Range: illegal world coordinates range: x1=0.000000, y1=-1.506184, x2=-0.000000, y2=1.395132
Error in TCanvas::RangeAxis: illegal axis coordinates range: xmin=0.000000, ymin=-1.100000, xmax=0.000000, ymax=1.105000
[/quote]

var3 is completely screwed up (should be flat between 0 and 50):

var4 looks ok again.

The problem also becomes obvious when doing TTree::Scan:

[code]MyTree->Scan(“mybranch.var1:mybranch.var2:mybranch.var3:mybranch.var4”,"","",10,1);


  • Row * mybranch. * mybranch. * mybranch. * mybranch. *

  •    1 *        14 * -1.4e-154 * 2.0043783 * 7.6061248 *
    
  •    2 *        23 * -9.36e-97 * 2.9543454 * 47.021991 *
    
  •    3 *        41 * 9.12e+192 * 2.7318656 * 23.534059 *
    
  •    4 *        48 * 6.805e+38 * 2.6498429 * 36.390750 *
    
  •    5 *         9 * -1.4e-154 * 2.9136180 * 14.843821 *
    
  •    6 *        10 * 9.12e+192 * 2.9103162 * 19.100553 *
    
  •    7 *        12 * -1.08e-19 * 2.9776959 * 15.885233 *
    
  •    8 *         8 * -4.02e-87 * 3.0021505 * 22.360097 *
    
  •    9 *        37 * 1.368e-48 * 3.0241553 * 12.155580 *
    
  •   10 *        48 * -4.9e+173 * 2.8015725 * 27.259946 *
    

[/code]

If I change the order of the types to something else in all necessary places, for example from int/double/float/float to int/float/float/double, then things are ok. So the behaviour is rather unpredictable.

I suspect that I stepped into the trap described on page 187 of the user guide (“Adding a Branch to Hold a List of Variables”), which says that one should not use structures with elements of different length.

If I create one branch for each element of a type, things seem to be ok:

mytree->Branch("mybranch1", &myp.var1, "var1/I");
mytree->Branch("mybranch2", &myp.var2, "var2/D");
mytree->Branch("mybranch34", &myp.var3, "var3/F:var4/F");

but this is rather ugly. In my real example, I want to store 50 quantities in a struct that describes a particle. Is there no way to store a list of variables of different types into a single branch?

In the case of the example macro, the values filled into var2 are obviously wrong, but since the behaviour seems to be unpredicatble, I suspect that the result can also be wrong in a more subtle way, and it might go unnoticed by the user for a long time.

So, since it is dangerous to declare branches in this way, wouldn’t it be good to add some protection inside of ROOT to prevent a user from declaring branches with elements of different types?

Thank you,
Jochen

We keep repeating this again and again.
Do not store in the same branch variables of different sizes.
Use a class instead. ROOT will automatically split your class members
into branches.

Rene

Hello Rene,

Thanks for your answer. I will try to rewrite the struct as a class.

Since this seems to come up frequently, I wonder if it wouldn’t be useful to add some protection in ROOT, for example, issueing a warning if a user defines a branch with elements of different types.

Thank you,
Jochen