# Reading ROOT file with Branches

**URL:** https://discourse.julialang.org/t/reading-root-file-with-branches/112014
**Category:** High Energy Physics
**Tags:** hep
**Created:** [March 23, 2024, 10:17am UTC](https://discourse.julialang.org/t/reading-root-file-with-branches/112014 "2024-03-23T10:17:40Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Fourier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fourier/32/38176_2.png) [@Fourier](https://discourse.julialang.org/u/Fourier)
#### Post date: [March 23, 2024, 10:17am UTC](https://discourse.julialang.org/t/reading-root-file-with-branches/112014/1 "2024-03-23T10:17:40Z")

</div>

I have a root file with a tree, branches and leaves, like this:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/e/9/e9f33b16b1c6201edc23790e090aeb5f7b59943f.png)

When I try to read it like using `UnROOT` like this:

```julia-auto
using UnROOT
f = ROOTFile("out_files/pienu00000-00.root")

tree = LazyTree(f,"sim")

```

I get a bounds error:

```julia-auto
ERROR: BoundsError: attempt to access 7-element Vector{Any} at index [-1]
Stacktrace:
  [1] getindex(A::Vector{Any}, i1::Int64)
    @ Base ./essentials.jl:13
  [2] streamerfor(f::ROOTFile, branch::UnROOT.TBranchElement_10)
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/root.jl:160
  [3] UnROOT.JaggType(f::ROOTFile, branch::UnROOT.TBranchElement_10, leaf::UnROOT.TLeafElement)
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/utils.jl:64
  [4] auto_T_JaggT(f::ROOTFile, branch::UnROOT.TBranchElement_10; customstructs::Dict{String, Type})
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/root.jl:365
  [5] auto_T_JaggT
    @ ~/.julia/packages/UnROOT/PnXmk/src/root.jl:360 [inlined]
  [6] LazyBranch(f::ROOTFile, b::UnROOT.TBranchElement_10)
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:117
  [7] LazyBranch(f::ROOTFile, s::String)
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:134
  [8] LazyTree(f::ROOTFile, tree::UnROOT.TTree, treepath::String, branches::Vector{String}; sink::Type{LazyTree})
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:450
  [9] LazyTree
    @ ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:432 [inlined]
 [10] LazyTree(f::ROOTFile, s::String, branches::Vector{String}; kwargs::@Kwargs{})
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:393
 [11] LazyTree(f::ROOTFile, s::String, branches::Vector{String})
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:390
 [12] LazyTree(f::ROOTFile, s::String; kwargs::@Kwargs{})
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:461
 [13] LazyTree(f::ROOTFile, s::String)
    @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:460
 [14] top-level scope
    @ /popos/home/caspar/Documents-old/code/semesterprojekt-pioneer/analysis/analyze.jl:4

```

However reading root files that do not have branches works just fine.

This is how the file looks like within unroot:

```julia-auto
julia> f
ROOTFile with 2 entries and 27 streamers.
out_files/pienu00000-00.root
├─ sim (TTree)
│ ├─ "info"
│ ├─ "init"
│ ├─ "track"
│ ├─ "decay"
│ ├─ "ghost"
│ ├─ "ghostface"
│ └─ "upstream"
└─ PIMCRunHeader (PIMCRunHeader)

```

In `C` I can read it by `branch.leaf`:

```julia-auto
    events = (TTree*)fp->Get("sim");
    unsigned int nEvents = events -> GetEntriesFast();
    int pions = events -> GetEntries("ghost.pdgid==211");

```

So I also tried using  
`tree = LazyTree(f,"sim", "ghost.pdgid")`

But I get another error:

```julia-auto
ERROR: MethodError: no method matching LazyBranch(::ROOTFile, ::Missing)

Closest candidates are:
  LazyBranch(::ROOTFile, ::Union{UnROOT.TBranch, UnROOT.TBranchElement})
   @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:116
  LazyBranch(::ROOTFile, ::AbstractString)
   @ UnROOT ~/.julia/packages/UnROOT/PnXmk/src/iteration.jl:134

```

While it works fine when having a flat root file:

```julia-auto
f = ROOTFile("data/data.root")
tree = LazyTree(f,"events","NJet")

```

# Method where the error occurs

The error occurs here:

```julia-auto
streamerfor(f::ROOTFile, branch::TBranch) = missing
function streamerfor(f::ROOTFile, branch::TBranchElement)
    fID = branch.fID
    # According to ChatGPt: When fID is equal to -1, it means that the
    # TBranch object has not been registered yet in the TTree's list of
    # branches. This can happen, for example, when a TBranch object has been
    # created, but has not been added to a TTree with the TTree::Branch()
    # method.
    #
    # TODO: For now, we force it to be 0 in this case, until someone complains.
    if fID == -1
        fID = 0
    end
    next_streamer = streamerfor(f, branch.fClassName)
    if ismissing(next_streamer)
        return missing
    else
        return next_streamer.streamer.fElements.elements[fID + 1] # one-based indexing in Julia
    end
end

```

Which is located at `~/.julia/dev/UnROOT/src/root.jl`

---

<div class="post-metadata">

### Author: ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)
#### Post date: [March 23, 2024, 11:49am UTC](https://discourse.julialang.org/t/reading-root-file-with-branches/112014/2 "2024-03-23T11:49:28Z")

</div>

That part of the ROOT specification is a bit unclear as you can see from my comments 😉 I’ll follow up in the git issue you created [Reading a file with Branches and Leafs · Issue #323 · JuliaHEP/UnROOT.jl · GitHub](https://github.com/JuliaHEP/UnROOT.jl/issues/323)

---

<div class="post-metadata">

### Author: ![tamasgal](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamasgal/32/27946_2.png) [@tamasgal](https://discourse.julialang.org/u/tamasgal)
#### Post date: [March 23, 2024, 7:55pm UTC](https://discourse.julialang.org/t/reading-root-file-with-branches/112014/3 "2024-03-23T19:55:32Z")

</div>

For the sake of completeness, there was a bug in UnROOT.jl which is now fixed (in v0.10.26) and the other issue was that the full path to the branch is a little bit different (that probably needs a better documentation, it’s not the first time that people are confused).

Long story short, here is the happy end, with some fancy regex to read multiple sub-branches and return a lazy table-like instance:

```julia
julia> using UnROOT

julia> f = ROOTFile("test/samples/issue323.root")
ROOTFile with 2 entries and 27 streamers.
test/samples/issue323.root
├─ sim (TTree)
│ ├─ "info"
│ ├─ "init"
│ ├─ "track"
│ ├─ "decay"
│ ├─ "ghost"
│ ├─ "ghostface"
│ └─ "upstream"
└─ PIMCRunHeader (PIMCRunHeader)

julia> t = LazyTree(f, "sim", [r"ghost/ghost\.(.*)" => s"\1"])
 Row │ ypos ghostID time stepID fUniqueID xmom pd ⋯
     │ SubArray{Float3 SubArray{Int32, SubArray{Float3 SubArray{Int32, SubArray{UInt32 SubArray{Float3 Su ⋯
─────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────
 1 │ [982.0, 6.83] [110000, 11000 [3230.0, 36.4] [0, 0] [0, 0] [-25.6, -29.5] [- ⋯
 2 │ [2590.0] [110000] [29.7] [0] [0] [21.9] [1 ⋯
 3 │ [258.0, -2230. [110000, 11000 [774.0, 48.0] [0, 0] [0, 0] [-44.3, 22.1] [- ⋯
 4 │ [-1850.0] [110000] [60.6] [0] [0] [14.1] [1 ⋯
 5 │ [] [] [] [] [] [] [] ⋯
 6 │ [512.0] [110000] [587.0] [0] [0] [-11.5] [- ⋯
 7 │ [-11.0] [110000] [40.8] [0] [0] [-2.61] [2 ⋯
 8 │ [2890.0] [110000] [28.7] [0] [0] [-8.56] [1 ⋯
 9 │ [] [] [] [] [] [] [] ⋯
 10 │ [28.1] [110000] [41.0] [0] [0] [-0.453] [2 ⋯
 11 │ [2660.0] [110000] [799.0] [0] [0] [-4.84] [- ⋯
 12 │ [12.0] [110000] [41.0] [0] [0] [2.28] [2 ⋯
 13 │ [33.0] [110000] [41.8] [0] [0] [-4.04] [2 ⋯
 14 │ [-0.84] [110000] [40.5] [0] [0] [-5.09] [2 ⋯
 15 │ [664.0] [110000] [311.0] [0] [0] [-3.08] [1 ⋯
 16 │ [] [] [] [] [] [] [] ⋯
 17 │ [-1220.0] [110000] [640.0] [0] [0] [7.4] [1 ⋯
 18 │ [-2290.0, -269 [110000, 11000 [1410.0, 1410. [0, 0, 0] [0, 0, 0] [0.0214, 0.01, [2 ⋯
 19 │ [906.0] [110000] [8140.0] [0] [0] [41.8] [- ⋯
 20 │ [3430.0] [110000] [4960.0] [0] [0] [-13.3] [- ⋯
 21 │ [] [] [] [] [] [] [] ⋯
 22 │ [5.71] [110000] [41.0] [0] [0] [6.6] [2 ⋯
 23 │ [] [] [] [] [] [] [] ⋯
 24 │ [1330.0] [110000] [1250.0] [0] [0] [-24.4] [1 ⋯
 25 │ [-1050.0] [110000] [23.5] [0] [0] [10.1] [1 ⋯
 26 │ [-280.0, -2400 [110000, 11000 [1150.0, 39.1] [0, 0] [0, 0] [0.412, -13.6] [2 ⋯
 27 │ [] [] [] [] [] [] [] ⋯
 28 │ [-12.8] [110000] [1150.0] [0] [0] [10.7] [- ⋯
 29 │ [2770.0, 2080. [110000, 11000 [1610.0, 20.5] [0, 0] [0, 0] [20.8, -15.4] [- ⋯
 30 │ [262.0, -866.0 [110000, 11000 [36.3, 35.7] [0, 0] [0, 0] [-17.5, 5.21] [1 ⋯
 31 │ [] [] [] [] [] [] [] ⋯
  ⋮ │ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋱
                                                                                  7 columns and 1169 rows omitted

julia> t.time[23:42]
20-element Vector{Vector{Float32}}:
 []
 [1248.5364]
 [23.53635]
 [1154.8237, 39.09293]
 []
 [1154.2357]
 [1608.5714, 20.453718]
 [36.331398, 35.730732]
 []
 [2756.7627]
 [4619.069, 41.54856]
 [618.69916, 51.805447]
 []
 [2412.702]
 [2667.897, 2671.2146]
 [41.457493, 86.87225]
 [2779.9707]
 [2550.0178]
 [3598.2415, 30.367851]
 [2836.5977, 38.199326]

julia>

```

---

<div class="post-metadata">

### Author: ![Fourier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fourier/32/38176_2.png) [@Fourier](https://discourse.julialang.org/u/Fourier)
#### Post date: [March 23, 2024, 8:27pm UTC](https://discourse.julialang.org/t/reading-root-file-with-branches/112014/4 "2024-03-23T20:27:16Z")

</div>

Thank you so much! 😃
