-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathHDF5Ext.jl
More file actions
105 lines (89 loc) · 2.77 KB
/
HDF5Ext.jl
File metadata and controls
105 lines (89 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
module HDF5Ext
import YAXArrayBase: YAXArrayBase as YAB
using HDF5
"""
HDF5Dataset
Dataset backend to read HDF5 files using HDF5.jl
"""
struct HDF5Dataset
filename::String
mode::String
handle::Base.RefValue{Union{Nothing,HDF5.File}}
end
function HDF5Dataset(filename; mode="r")
HDF5Dataset(filename, mode, Ref{Union{Nothing,HDF5.File}}(nothing))
end
function dsopen(f, ds::HDF5Dataset)
if ds.handle[] === nothing || !Base.isopen(ds.handle[])
HDF5.h5open(f, ds.filename, ds.mode)
else
f(ds.handle[])
end
end
function YAB.open_dataset_handle(f, ds::HDF5Dataset)
if ds.handle[] === nothing || !Base.isopen(ds.handle[])
try
ds.handle[] = HDF5.h5open(ds.filename, ds.mode)
f(ds)
finally
ds.handle[] = nothing
end
else
f(ds)
end
end
function __init__()
@debug "new driver key :HDF5, updating backendlist."
YAB.backendlist[:HDF5] = HDF5Dataset
push!(YAB.backendregex, r".h5$" => HDF5Dataset)
end
function get_all_paths(file, prefix="")
paths = String[]
for key in keys(file)
full_path = isempty(prefix) ? key : "$prefix/$key"
obj = file[key]
if isa(obj, HDF5.Dataset)
push!(paths, full_path)
elseif isa(obj, HDF5.Group)
append!(paths, get_all_paths(obj, full_path))
end
end
return paths
end
function get_dims(f, var)
dims = String[]
ds = f[var]
if haskey(ds, "DIMENSION_LIST")
dimension_list = read_attribute(ds, "DIMENSION_LIST")
for dimensions in dimension_list
for dim_ref in dimensions
push!(dims, HDF5.name(f[dim_ref]))
end
end
end
return dims
end
"Return a list of variable names"
YAB.get_varnames(ds::HDF5Dataset) = dsopen(get_all_paths, ds)
"Return a list of dimension names for a given variable"
YAB.get_var_dims(ds::HDF5Dataset, name) = dsopen(x -> get_dims(x, name), ds)
function get_var_attrs(file, name)
attributes = Dict(attrs(file[name]))
pop!(attributes, "DIMENSION_LIST", nothing) # Remove DIMENSION_LIST if present
return attributes
end
"Return a dict with the attributes for a given variable"
YAB.get_var_attrs(ds::HDF5Dataset, name) = dsopen(v -> get_var_attrs(v, name), ds)
"Return a dict with global attributes for the dataset"
YAB.get_global_attrs(ds::HDF5Dataset) = dsopen(h5 -> Dict(attrs(h5)), ds)
"Return a DiskArray handle to a dataset"
function YAB.get_var_handle(ds::HDF5Dataset, i; persist=true)
if persist || ds.handle[] === nothing
s, et = NetCDF.open(j -> (size(j), eltype(j)), ds.filename, i)
NetCDFVariable{et,length(s)}(ds.filename, i, s)
else
ds.handle[][i]
end
end
Base.haskey(ds::HDF5Dataset, k) = dsopen(h5 -> haskey(h5, k), ds)
end