From 9a12043b5085deab1eb47f65d3d92324b2f99403 Mon Sep 17 00:00:00 2001 From: Tamas Gal Date: Fri, 31 Mar 2023 12:08:50 +0200 Subject: [PATCH] Custom TObject hook (#232) * Preliminary debugging for generic tobject stuff * Add parser logic * Add tests * Bump version number --- Project.toml | 2 +- src/bootstrap.jl | 27 +++++++++++++++++++++++++++ src/root.jl | 15 +++++++++++---- test/runtests.jl | 11 +++++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/Project.toml b/Project.toml index eb51ffde..65d3ad87 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "UnROOT" uuid = "3cd96dde-e98d-4713-81e9-a4a1b0235ce9" authors = ["Tamas Gal", "Jerry Ling", "Johannes Schumann", "Nick Amin"] -version = "0.10.1" +version = "0.10.2" [deps] AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" diff --git a/src/bootstrap.jl b/src/bootstrap.jl index 70074cf6..efae5b95 100644 --- a/src/bootstrap.jl +++ b/src/bootstrap.jl @@ -885,6 +885,33 @@ function TNtuple(io, tkey::TKey, refs) tree = TTree(io, tkey, refs; top=false) #embeded tree end +""" +Direct parsing of streamed objects which are not sitting on branches. +""" +function parsetobject(io, tkey::TKey, streamer) + # pass the correct parser from f! + io = datastream(io, tkey) + preamble = Preamble(io, Missing) + + @initparse + + # the first entry in the streamer is a TOBject + parsefields!(io, fields, TObject) + + # the second (and last) entry is the actual data streamer (we think) + s = streamer.streamer.fElements.elements[2] + if s.fTypeName == "map" + skip(io, 3*4) # unclear what the first 12 bytes are + # this gives the number of elements + n = readtype(io, Int32) + skip(io, 6) # the usual header stuff? + keys = [readtype(io, String) for i ∈ 1:n] + skip(io, 6) # the usual header stuff? + values = [readtype(io, String) for i ∈ 1:n] + return Dict(zip(keys, values)) + end + error("Unable to parse '$(s.fTypeName)' of '$(tkey.fClassName)'") +end # FIXME preliminary TTree implementation function TTree(io, tkey::TKey, refs; top=true) diff --git a/src/root.jl b/src/root.jl index 7ca3fdd9..3e4925a2 100644 --- a/src/root.jl +++ b/src/root.jl @@ -162,10 +162,17 @@ end return f[first(paths)][join(paths[2:end], "/")] end tkey = f.directory.keys[findfirst(isequal(s), keys(f))] - @debug "Retrieving $s ('$(tkey.fClassName)')" - streamer = getfield(@__MODULE__, Symbol(safename(tkey.fClassName))) - S = streamer(f.fobj, tkey, f.streamers.refs) - return S + typename = safename(tkey.fClassName) + @debug "Retrieving $s ('$(typename)')" + try + streamer = getfield(@__MODULE__, Symbol(typename)) + S = streamer(f.fobj, tkey, f.streamers.refs) + return S + catch UndefVarError + end + + # last resort, try direct parsing + parsetobject(f.fobj, tkey, streamerfor(f, typename)) end # FIXME unify with above? diff --git a/test/runtests.jl b/test/runtests.jl index 78d971f3..d542d106 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -218,6 +218,17 @@ end # close(rootfile) end +@testset "Single TObject subclasses" begin + f = UnROOT.samplefile("triply_jagged_via_custom_class.root") + # map + head = f["Head"] + @test 27 == length(f["Head"]) + @test " 3.3" == head["DAQ"] + @test " CORSIKA 7.640 181111 1211" == head["physics"] + @test "MUSIC seawater 02-03 190204 1643" == head["propag"] + close(f) +end + @testset "LazyBranch and LazyTree" begin rootfile = ROOTFile(joinpath(SAMPLES_DIR, "tree_with_large_array.root")) branch = rootfile["t1"]["int32_array"]