Skip to content

Commit

Permalink
Add close and do-block-syntax (#70)
Browse files Browse the repository at this point in the history
* Add Base.close and do-block syntax for ROOTFile

* Add tests for do-syntax

* Close dangling filepointers

* Bump version number
  • Loading branch information
tamasgal authored Aug 3, 2021
1 parent cda0c7a commit aec9e5f
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 8 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "UnROOT"
uuid = "3cd96dde-e98d-4713-81e9-a4a1b0235ce9"
authors = ["Tamas Gal", "Jerry Ling", "Johannes Schumann", "Nick Amin"]
version = "0.3.5"
version = "0.3.6"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Expand Down
2 changes: 1 addition & 1 deletion src/UnROOT.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module UnROOT

export ROOTFile, LazyBranch, LazyTree

import Base: keys, get, getindex, getproperty, show, length, iterate, position, ntoh, lock, unlock, reinterpret
import Base: close, keys, get, getindex, getproperty, show, length, iterate, position, ntoh, lock, unlock, reinterpret
ntoh(b::Bool) = b

import AbstractTrees: children, printnode, print_tree
Expand Down
12 changes: 12 additions & 0 deletions src/root.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ struct ROOTFile
customstructs::Dict{String, Type}
lk::ReentrantLock
end
function close(f::ROOTFile)
# TODO: should we take care of the lock?
close(f.fobj)
end
function ROOTFile(f::Function, args...; pv...)
rootfile = ROOTFile(args...; pv...)
try
f(rootfile)
finally
close(rootfile)
end
end
lock(f::ROOTFile) = lock(f.lk)
unlock(f::ROOTFile) = unlock(f.lk)
function Base.hash(rf::ROOTFile, h::UInt)
Expand Down
43 changes: 37 additions & 6 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,13 @@ end


@testset "ROOTFile" begin
rootfile = ROOTFile(joinpath(SAMPLES_DIR, "tree_with_histos.root"))
@test 100 == rootfile.header.fBEGIN
@test 1 == length(rootfile.directory.keys)
@test "t1" keys(rootfile)
for key in keys(rootfile)
rootfile[key]
ROOTFile(joinpath(SAMPLES_DIR, "tree_with_histos.root")) do rootfile
@test 100 == rootfile.header.fBEGIN
@test 1 == length(rootfile.directory.keys)
@test "t1" keys(rootfile)
for key in keys(rootfile)
rootfile[key]
end
end

rootfile = ROOTFile(joinpath(SAMPLES_DIR, "tree_with_custom_struct.root"))
Expand All @@ -104,11 +105,13 @@ end
for key in keys(rootfile)
rootfile[key]
end
close(rootfile)

rootfile = ROOTFile(joinpath(SAMPLES_DIR, "histograms.root"))
for branch in ["one", "two", "three"]
@test branch in keys(rootfile)
end
close(rootfile)

rootfile = ROOTFile(joinpath(SAMPLES_DIR, "km3net_online.root"))
@test 100 == rootfile.header.fBEGIN
Expand All @@ -126,13 +129,15 @@ end
# for key in keys(rootfile)
# @test !ismissing(rootfile[key])
# end
close(rootfile)
end

@testset "readbasketsraw()" begin
array_md5 = [0xb4, 0xe9, 0x32, 0xe8, 0xfb, 0xff, 0xcf, 0xa0, 0xda, 0x75, 0xe0, 0x25, 0x34, 0x9b, 0xcd, 0xdf]
rootfile = ROOTFile(joinpath(SAMPLES_DIR, "km3net_online.root"))
data, offsets = UnROOT.array(rootfile, "KM3NET_EVENT/KM3NET_EVENT/snapshotHits"; raw=true)
@test array_md5 == md5(data)
close(rootfile)

rootfile = ROOTFile(joinpath(SAMPLES_DIR, "tree_with_jagged_array.root"))
data, offsets = UnROOT.array(rootfile, "t1/int32_array"; raw=true)
Expand All @@ -144,13 +149,15 @@ end
rootfile = ROOTFile(joinpath(SAMPLES_DIR, "tree_with_vector_multiple_baskets.root"))
data, offsets = UnROOT.array(rootfile, "t1/b1"; raw=true)
@test unique(diff(offsets)) == [18]
close(rootfile)
end

@testset "No (basket) compression" begin
rootfile = ROOTFile(joinpath(SAMPLES_DIR, "uncomressed_lz4_int32.root"))
arr = UnROOT.array(rootfile, "t1/int32_array")
@test length(arr) == 3
@test all(arr .== [[1,2], [], [3]])
close(rootfile)
end

@testset "Compressions" begin
Expand All @@ -159,10 +166,13 @@ end
arr = UnROOT.array(rootfile, "t1/float_array")
@test 100000 == length(arr)
@test [0.0, 1.0588236, 2.1176472, 3.1764705, 4.2352943] arr[1:5] atol=1e-7
close(rootfile)

rootfile = ROOTFile(joinpath(SAMPLES_DIR, "tree_with_large_array_lz4.root"))
arr = collect(rootfile["t1/float_array"])
@test 100000 == length(arr)
@test [0.0, 1.0588236, 2.1176472, 3.1764705, 4.2352943] arr[1:5] atol=1e-7
close(rootfile)
end

@testset "ROOTDirectoryHeader" begin
Expand All @@ -176,6 +186,7 @@ end
@test 100 == header.fSeekDir
@test 0 == header.fSeekParent
@test 1398 == header.fSeekKeys
close(rootfile)

# rootfile = ROOTFile(joinpath(SAMPLES_DIR, "km3net_online.root"))
# header = rootfile.directory.header
Expand All @@ -187,6 +198,7 @@ end
# @test 100 == header.fSeekDir
# @test 0 == header.fSeekParent
# @test 1619244 == header.fSeekKeys
# close(rootfile)
end

@testset "LazyBranch and LazyTree" begin
Expand All @@ -204,6 +216,7 @@ end
@test [row.int32_array for row in table[20:30]] == BA[20:30]
@test sum(table.int32_array) == sum(row.int32_array for row in table)
@test [row.int32_array for row in table] == BA
close(rootfile)
end

@testset "TLorentzVector" begin
Expand All @@ -217,6 +230,7 @@ end
@test eltype(branch) === LorentzVectors.LorentzVector{Float64}
@test tree[1].LV.x == 1.0
@test tree[1].LV.t == 4.0
close(rootfile)
end

@testset "TNtuple" begin
Expand All @@ -226,6 +240,7 @@ end
@test arrs[1] 0:99
@test arrs[2] arrs[1] .+ arrs[1] ./ 13
@test arrs[3] arrs[1] .+ arrs[1] ./ 17
close(rootfile)
end

@testset "Singly jagged branches" begin
Expand All @@ -235,6 +250,7 @@ end
@test data[1] == Int32[]
@test data[1:2] == [Int32[], Int32[0]]
@test data[end] == Int32[90, 91, 92, 93, 94, 95, 96, 97, 98]
close(rootfile)

# 64bits T
T = Float64
Expand All @@ -245,6 +261,7 @@ end
@test data[1] == T[]
@test data[1:2] == [T[], T[0]]
@test data[end] == T[90, 91, 92, 93, 94, 95, 96, 97, 98]
close(rootfile)
end

@testset "Doubly jagged branches" begin
Expand All @@ -257,6 +274,7 @@ end
@test UnROOT.array(rootfile, "t1/bf") == vvf
@test rootfile["t1/bf"] == vvf
@test eltype(eltype(eltype(rootfile["t1/bf"]))) === Float32
close(rootfile)
end

@testset "NanoAOD" begin
Expand All @@ -273,6 +291,7 @@ end
@test sort(propertynames(tree)) == sort([:Muon_pt, :Muon_eta, :Muon_phi, :Muon_charge])
tree = LazyTree(rootfile, "Events", r"Muon_(pt|eta)$")
@test sort(propertynames(tree)) == sort([:Muon_pt, :Muon_eta])
close(rootfile)
end

@testset "Branch filtering" begin
Expand All @@ -294,6 +313,7 @@ end
for f in files
r = ROOTFile(joinpath(SAMPLES_DIR, f))
show(_io, r)
close(r)
end
end
# Custom bootstrap things
Expand Down Expand Up @@ -338,6 +358,7 @@ end
@test headers[1].overlays == 6
@test headers[2].overlays == 21
@test headers[3].overlays == 0
close(f)
end

# Histograms
Expand Down Expand Up @@ -379,9 +400,12 @@ end
@test f[k][:fN] == [0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]
end

close(f)

f = ROOTFile(joinpath(SAMPLES_DIR, "cms_ntuple_wjet.root"))
binlabels = ["Root", "Weight", "Preselection", "SelectGenPart", "GoodRunsList", "EventFilters", "SelectLeptons", "SelectJets", "Trigger", "ObjectsSelection", "SSPreselection", "NjetGeq4", "AK4CategTagHiggsJets", "AK4CategTagVBSJets", "AK4CategChannels", "AK4CategPresel"]
@test f["AK4CategPresel_cutflow"][:fXaxis_fModLabs].objects == binlabels
close(f)
end


Expand All @@ -392,6 +416,7 @@ end
@test 2 == length(keys(rootfile))
@test [1.0, 2.0, 3.0] == UnROOT.array(rootfile, "TreeD/nums")
@test [1.0, 2.0, 3.0] == UnROOT.array(rootfile, "TreeF/nums")
close(rootfile)

# issue 55
rootfile = ROOTFile(joinpath(SAMPLES_DIR, "cms_ntuple_wjet.root"))
Expand All @@ -402,10 +427,12 @@ end
@test Float32[69.96958, 25.149912, 131.66693, 150.56802] == pts1[1:4]
@test pts1 == pts2
@test pts3[1:2] == [[454.0, 217.5, 89.5, 30.640625], [184.375, 33.28125, 32.28125, 28.46875]]
close(rootfile)

# issue 61
rootfile = ROOTFile(joinpath(SAMPLES_DIR, "issue61.root"))
@test rootfile["Events/Jet_pt"][:] == Vector{Float32}[[], [27.324587, 24.889547, 20.853024], [], [20.33066], [], []]
close(rootfile)
end

@testset "jagged subbranch type by leaf" begin
Expand All @@ -417,6 +444,8 @@ end
ids_jagged = UnROOT.array(rootfile, "E/Evt/trks/trks.id")
@test all(ids_jagged[1] .== collect(1:56))
@test all(ids_jagged[9] .== collect(1:54))

close(rootfile)
end

@testset "Type stability" begin
Expand All @@ -441,4 +470,6 @@ end

@test isfullystable(f1)
@test isfullystable(f2)

close(rootfile)
end

2 comments on commit aec9e5f

@tamasgal
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/42108

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.6 -m "<description of version>" aec9e5f8f06a957d6bf1895cd9ef8b6ad0e40989
git push origin v0.3.6

Please sign in to comment.