Skip to content

Reading structs into higher-dimensional Arrays #9

@briederer

Description

@briederer

ROOT offers different ways to store arrays or even structs in TBranches. I added a small ROOT-File (test_array.root.zip) which contains a TTree called 'arrays' which contains a scalar, a 6d-vector and a 2x3-matrix and another TTree called 'structs' which contains again the same scalar as 'arrays' and a struct which resembles again a 2x3-matrix but stored as a 6d-vec and is defined in the following way
struct m23 {double el[6];};

So the file was created in the following way (may be useful when trying to retrieve data in Julia):

struct m23 {double el[6];};

m23 mat_23 = {1.0,2.0,3.0,4.0,5.0,6.0};
int n = 1;
double vec[6] = {1.0,2.0,3.0,4.0,5.0,6.0};
double mat[2][3] = {{1.0,2.0,3.0},{4.0,5.0,6.0}};

TFile *file = new TFile("test_array.root","Recreate");
TTree *tree_arr = new TTree("arrays","tree filled with arrays")
TTree *tree_str = new TTree("structs","tree filled with struct");

tree_arr -> Branch("nInt",&n);
tree_arr -> Branch("6dVec",&vec,"[6]/D");
tree_arr -> Branch("2x3Mat",&mat,"[2][3]/D");
tree_arr -> Fill();

tree_str -> Branch("nInt",&n);
tree_str -> Branch("2x3mat",&mat,"el[6]/D");
tree_str -> Fill();

file -> Write("",TObject::kOverwrite);

In the ROOT command-line the TTrees look like this in the end

root [1] arrays -> Scan();
***********************************************************
*    Row   * Instance *      nInt * 6dVec.6dV * 2x3Mat.2x *
***********************************************************
*        0 *        0 *         1 *         1 *         1 *
*        0 *        1 *         1 *         2 *         2 *
*        0 *        2 *         1 *         3 *         3 *
*        0 *        3 *         1 *         4 *         4 *
*        0 *        4 *         1 *         5 *         5 *
*        0 *        5 *         1 *         6 *         6 *
***********************************************************
root [2] structs -> Scan();
***********************************************
*    Row   * Instance *      nInt * 2x3mat.2x *
***********************************************
*        0 *        0 *         1 *         1 *
*        0 *        1 *         1 *         2 *
*        0 *        2 *         1 *         3 *
*        0 *        3 *         1 *         4 *
*        0 *        4 *         1 *         5 *
*        0 *        5 *         1 *         6 *
***********************************************

When I try to read this in Julia using the UnROOT package I get the following

julia> file=ROOTFile("/hosts/nashome/riederer_bernd/test_array.root")
ROOTFile("/hosts/nashome/riederer_bernd/test_array.root") with 2 entries and 17 streamers.

julia> keys(file)
2-element Array{String,1}:
 "arrays" 
 "structs"

julia> array(file,"arrays")
ERROR: Branches with multiple leaves are not supported yet.
Stacktrace:
 [1] #array#120(::Bool, ::typeof(array), ::ROOTFile, ::String) at ~/.juliapro/JuliaPro_v1.2.0-1/packages/UnROOT/KN5MU/src/root.jl:153
 [2] array(::ROOTFile, ::String) at ~/.juliapro/JuliaPro_v1.2.0-1/packages/UnROOT/KN5MU/src/root.jl:139
 [3] top-level scope at none:0

julia> array(file,"structs")
ERROR: Branches with multiple leaves are not supported yet.
Stacktrace:
 [1] #array#120(::Bool, ::typeof(array), ::ROOTFile, ::String) at ~/.juliapro/JuliaPro_v1.2.0-1/packages/UnROOT/KN5MU/src/root.jl:153
 [2] array(::ROOTFile, ::String) at ~/.juliapro/JuliaPro_v1.2.0-1/packages/UnROOT/KN5MU/src/root.jl:139
 [3] top-level scope at none:0

julia> DataFrame(file,"arrays")
1×3 DataFrame
│ Row │ nInt  │ 6dVec   │ 2x3Mat  │
│     │ Int32 │ Float64 │ Float64 │
├─────┼───────┼─────────┼─────────┤
│ 1   │ 1     │ 1.0     │ 1.0     │

julia> DataFrame(file,"structs")
1×2 DataFrame
│ Row │ nInt  │ 2x3mat  │
│     │ Int32 │ Float64 │
├─────┼───────┼─────────┤
│ 1   │ 1     │ 1.0     │

It seems that, while array is refusing to handle multidimensional objects in a TBranch, the function DataFrame is able to get the scalar and the first entry of each multidimensional object.
I tested this with another file and DataFrame returns correctly all Rows of scalar-entries and next to it in each case the first element of the higher-dimensional object. So it looks like this:

julia> DataFrame(file,"structs")
1×5 DataFrame
│ Row │ nInt  │  2x3mat   │
│     │ Int32 │  Float64  │
├─────┼───────┼───────────┤
│ 1   │ 1     │ mat.el[0] │
│ 2   │ 2     │ mat.el[0] │
│ 3   │ 3     │ mat.el[0] │
│ 4   │ 4     │ mat.el[0] │

I would like to request to extend the support for multidimensional objects at least for the array function.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions