I am trying to make some ROOT tree with the several nested TClonesArrays in it.
It was not a big deal to create and fill such a tree, but to read it.
In the attachment I put two examples of working/not working reading procedure.
The only difference between these two examples is the line 68 in the converter program where I start to add TClonesArray into TClonesArray. treeMWE.zip (9.6 KB)
In the “not working” case the program succeed to read one entry from the ROOT tree and then crashes.
So, how to read such trees with many nested TClonesArray properly?
Thanks for the post.
We can support you for this usecase, but before that, could I ask you why you opted for nested TClonesArray for your data model? Couldn’t something simpler, maybe coming from the STL, be more adequate?
Unfortunately I have some complex set of ASCII files which must be converted to the ROOT trees format and TClonesArray was the first thing which came into my mind to keep the tree structure in a clean logical way:
Tree
event_1
int some
float event
double info
TClonesArray particles_vector
px, py, pz, x, y, z ... etc
TClonesArray timestep (1...n)
int step
float info
TClonesArray baryons
px, py, pz, x, y, z ... and a lot of other fields
event_2
...
event_n
For this purpose you are likely to be as well served by std::vector:
That said the problem in your example is the missing implementation of TimeStep& operator =(const TimeStep& in) and/or TimeStep::TimeStep(const TimeStep &in which concretely means that becomes of the line:
new ((*fTimesteps)[iter]) TimeStep(*timestep);
multiple TimeStep instances share the same pointer to the same TClonesArray.
Yes, thank you! I forgot to implement the TimeStep::TimeStep(const TimeStep &in) constructor, my fault.
For this purpose you are likely to be as well served by std::vector
As far as I understand, ROOT does not work normally with the std::vectors.
Here is a small MWE: mwectors.cc (814 Bytes)
A tree with the event (branch ev_b) and particle (branch p_x) is filled.
Then if you open the resulting file in the Browser, you will find that there are 100 entries in the ‘p_x’ branch – as expected, but 55 entires in the ‘ev_b’ branch… Seems like it because of the tree->Fill() method, but the ev_b vector must not be cleared because it contain the event-wise information.
Moreover, it seems like it does not like a little more complex vectors like std::vector<std::array<float, 4>> – the corresponding branch does not even appear in the TBrowser.
So, fortunately or not, the standard “TClonesArrays within TClonesArrays” approach does the work well
This is the one case we don’t support yet. To store an std::array within a std::vector you need to enclose the std::array in a wrapper class (and generate the dictionary for that class and for the vector containing that wrapper class).
as expected, but 55 entires in the ‘ev_b’ branch…`
For the code in mwectors.cc this is exactly what I expects, since the vector ev_b is never cleared, the instance stored in the first entry contains one element, the instance stored in the second entry contains 2 elements, etc. And when you plot that vector, they are all plotted and 1+2+3+4+5+6+7+8+9+10 is 55.