Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Browsing a ROOT file... #194

Closed
tamasgal opened this issue Nov 7, 2022 · 6 comments
Closed

Browsing a ROOT file... #194

tamasgal opened this issue Nov 7, 2022 · 6 comments

Comments

@tamasgal
Copy link
Member

tamasgal commented Nov 7, 2022

Yes I know, we are buried in issues but this is something I wanted to discuss for a long time ;)

Currently it's very user-unfriendly to explore a ROOT file's structure when there are some streamers missing because f[...] always tries to directly parse and return a lazy array wherever possible. I think it would be better to make it more explicit so that we don't have too many surprises when invoking Base.getindex.

Here is an example for a file I am debugging:

julia> f = ROOTFile("t.root")
ROOTFile with 5 entries and 53 streamers.
t.root


julia> keys(f)
5-element Vector{String}:
 "Primaries"
 "RDecays"
 "substrate"
 "resonator"
 "pfates"

julia> f["Primaries"]
ERROR: UndefVarError: TAttMarker_1 not defined
Stacktrace:
  [1] stream!(io::IOBuffer, fields::Dict{Symbol, Any}, ::Type{UnROOT.TAttMarker}; check::Bool)
    @ UnROOT ~/Dev/UnROOT.jl/src/streamers.jl:577
...
...
...

As seen above, we are hit with an error end then nothing helps further, although we might have some branches which are well readable.

I think there are two possibilities:

  1. Make getindex typestable and predictable by always returning some kind of an accessor object with a path in a ROOT file. Helper functions are then used to make it to a, something like lazyarray(f, "...") or array(f, "...")
  2. Create a browse function or maybe even reuse Base.keys to bypass the interpretation mechanism

What do you think? I have some prototype implementations but I don't really which direction to go.

@Moelf
Copy link
Member

Moelf commented Nov 8, 2022

I'm kinda of mentally done with legacy ROOT; my hope is to find time to do RNTuple and just ask everyone to use that...

@oschulz
Copy link
Member

oschulz commented Nov 8, 2022

I'm kinda of mentally done with legacy ROOT; my hope is to find time to do RNTuple and just ask everyone to use that...

Amen to that!

@tamasgal
Copy link
Member Author

I agree, however we have a several hundreds of TB of ROOT data already and much more to come 😆 I think the "legacy ROOT" will still have high-demand in the next decade, unfortunately...

I am still not sure how to solve the exploration issue, but I guess I will then implement an additional method like browse(f, "path") to print the tree/branch structure. That will be non-breaking.

@Moelf
Copy link
Member

Moelf commented Nov 12, 2022

first we probably want to clear the mess of difference between:

  • file["tree"]
  • file["tree"]["branch"]
  • file["tree/branch"]
  • LazyTree(file, "tree")

@tamasgal
Copy link
Member Author

tamasgal commented Nov 12, 2022

Yes absolutely ;)

I'd prefer to have it similar to uproot, so that file["tree"] is not behaving like actual data. This was more or less the original design, where we had something like array(file["tree"]) to make it more explicit. But I have no strong opinion which way to go, I am totally undecided.

My main point is that something is needed which allows to explore the structure. Even if file["tree/whatever"] cannot be parsed, it happens (at least for tons of KM3NeT files 😆 ) that file["tree/whatever/foo/pos.x"] works perfectly fine. The problem is that it's very complicated to find out the path.

So in principle, I would start with Base.getindex(f::ROOTFile, s::AbstractString)

UnROOT.jl/src/root.jl

Lines 137 to 147 in 57e49d3

function Base.getindex(f::ROOTFile, s::AbstractString)
S = _getindex(f, s)
if S isa Union{TBranch, TBranchElement}
# try # if we can't construct LazyBranch, just give up (maybe due to custom class)
return LazyBranch(f, S)
# catch
# @warn "Can't automatically create LazyBranch for branch $s. Returning a branch object"
# end
end
S
end

and let that return some new wrapper struct (ROOTPath??) which pretty prints its subtrees/branches.

What do you think?

@tamasgal
Copy link
Member Author

I am totally happy with #199 so let use close this for now ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants