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