Skip to content

Commit

Permalink
Add support for reading H5T_ARRAY
Browse files Browse the repository at this point in the history
  • Loading branch information
timholy committed Nov 21, 2013
1 parent ff40eb3 commit 5679103
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 5 deletions.
62 changes: 57 additions & 5 deletions src/plain.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

module HDF5

include("datafile.jl")

## Add methods to...
import Base: close, convert, done, dump, endof, flush, getindex, has, isempty, isvalid, length, names, ndims, next, read, setindex!, show, size, start, write
import Base: close, convert, done, dump, eltype, endof, flush, getindex, has, isempty, isvalid, length, names, ndims, next, read, setindex!, show, size, start, write

include("datafile.jl")

## C types
typealias C_time_t Int
Expand Down Expand Up @@ -388,6 +388,13 @@ end
# An empty array type
type EmptyArray{T}; end

# Stub types to encode fixed-size arrays for H5T_ARRAY
immutable DimSize{N}; end # Int-wrapper (can't use tuple of Int as param)
immutable FixedArray{T,D<:(DimSize...)}; end
dimsize{N}(::Type{DimSize{N}}) = N
size{T,D}(::Type{FixedArray{T,D}}) = map(dimsize, D)::(Int...)
eltype{T,D}(::Type{FixedArray{T,D}}) = T

# VLEN objects
type HDF5Vlen{T}
data
Expand Down Expand Up @@ -965,9 +972,7 @@ function read{T<:HDF5BitsKind}(obj::DatasetOrAttribute, ::Type{T})
end
# Read array of BitsKind
function read{T<:HDF5BitsKind}(obj::DatasetOrAttribute, ::Type{Array{T}})
local data
dims = size(obj)
dspace = dataspace(obj)
data = Array(T, dims...)
readarray(obj, hdf5_type_id(T), data)
data
Expand All @@ -976,6 +981,38 @@ end
function read{T<:BitsKindOrByteString}(obj::DatasetOrAttribute, ::Type{EmptyArray{T}})
Array(T, 0)
end
# Fixed-size arrays (H5T_ARRAY)
function read{A<:FixedArray}(obj::DatasetOrAttribute, ::Type{A})
T = eltype(A)
sz = size(A)
data = Array(T, sz)
readarray(obj, hdf5_type_id(T), data)
data
end
function read{A<:FixedArray}(obj::DatasetOrAttribute, ::Type{Array{A}})
T = eltype(A)
if !(T<:HDF5BitsKind)
error("Sorry, not yet supported")
end
sz = size(A)
dims = size(obj)
data = Array(T, tuple(sz..., dims...))
nd = length(sz)
hsz = Hsize[convert(Hsize,sz[nd-i+1]) for i = 1:nd]
memtype_id = h5t_array_create(hdf5_type_id(T), convert(Cuint, length(sz)), hsz)
try
h5d_read(obj.id, memtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, data)
finally
h5t_close(memtype_id)
end
ret = Array(Array{T}, dims)
# Because of garbage-collection concerns, it's best to copy the data
L = prod(sz)
for i = 1:prod(dims)
ret[i] = reshape(data[(i-1)*L+1:i*L], sz)
end
ret
end

# Clean up string buffer according to padding mode
function unpad(s::ByteString, pad::Cint)
Expand Down Expand Up @@ -1497,6 +1534,8 @@ function hdf5_to_julia_eltype(objtype)
T = HDF5Vlen{hdf5_to_julia_eltype(HDF5Datatype(super_id))}
elseif class_id == H5T_COMPOUND
T = HDF5Compound
elseif class_id == H5T_ARRAY
T = hdf5array(objtype)
else
error("Class id ", class_id, " is not yet supported")
end
Expand Down Expand Up @@ -1724,8 +1763,11 @@ for (jlname, h5name, outtype, argtypes, argsyms, ex_error) in
(:h5s_get_simple_extent_dims, :H5Sget_simple_extent_dims, Cint, (Hid, Ptr{Hsize}, Ptr{Hsize}), (:space_id, :dims, :maxdims), :(error("Error getting the dimensions for a dataspace"))),
(:h5s_get_simple_extent_ndims, :H5Sget_simple_extent_ndims, Cint, (Hid,), (:space_id,), :(error("Error getting the number of dimensions for a dataspace"))),
(:h5s_get_simple_extent_type, :H5Sget_simple_extent_type, Cint, (Hid,), (:space_id,), :(error("Error getting the dataspace type"))),
(:h5t_array_create, :H5Tarray_create2, Hid, (Hid, Cuint, Ptr{Hsize}), (:basetype_id, :ndims, :sz), :(error("Error creating H5T_ARRAY of id ", basetype_id, " and size ", sz))),
(:h5t_copy, :H5Tcopy, Hid, (Hid,), (:dtype_id,), :(error("Error copying datatype"))),
(:h5t_create, :H5Tcreate, Hid, (Cint, Csize_t), (:class_id, :sz), :(error("Error creating datatype of id ", classid))),
(:h5t_get_array_dims, :H5Tget_array_dims2, Cint, (Hid, Ptr{Hsize}), (:dtype_id, :dims), :(error("Error getting dimensions of array"))),
(:h5t_get_array_ndims, :H5Tget_array_ndims, Cint, (Hid,), (:dtype_id,), :(error("Error getting ndims of array"))),
(:h5t_get_class, :H5Tget_class, Cint, (Hid,), (:dtype_id,), :(error("Error getting class"))),
(:h5t_get_cset, :H5Tget_cset, Cint, (Hid,), (:dtype_id,), :(error("Error getting character set encoding"))),
(:h5t_get_member_class, :H5Tget_member_class, Cint, (Hid, Cuint), (:dtype_id, :index), :(error("Error getting class of compound datatype member #", index))),
Expand Down Expand Up @@ -1855,6 +1897,16 @@ function vlen_get_buf_size(dset::HDF5Dataset, dtype::HDF5Datatype, dspace::HDF5D
sz[1]
end

function hdf5array(objtype)
nd = h5t_get_array_ndims(objtype.id)
dims = Array(Hsize, nd)
h5t_get_array_dims(objtype.id, dims)
eltyp = HDF5Datatype(h5t_get_super(objtype.id))
T = hdf5_to_julia_eltype(eltyp)
dimsizes = ntuple(nd, i->DimSize{int(dims[nd-i+1])}) # reverse order
FixedArray{T, dimsizes}
end

### Property manipulation ###
get_create_properties(dset::HDF5Dataset) = HDF5Properties(h5d_get_create_plist(dset.id))
get_create_properties(g::HDF5Group) = HDF5Properties(h5g_get_create_plist(dset.id))
Expand Down
29 changes: 29 additions & 0 deletions test/readremote.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,29 @@ opq = Array{Uint8}[[0x4f, 0x50, 0x41, 0x51, 0x55, 0x45, 0x30],
[0x4f, 0x50, 0x41, 0x51, 0x55, 0x45, 0x31],
[0x4f, 0x50, 0x41, 0x51, 0x55, 0x45, 0x32],
[0x4f, 0x50, 0x41, 0x51, 0x55, 0x45, 0x33]]
# For H5T_ARRAY
AA = Array{Int,2}[
[ 0 0 0;
0 -1 -2;
0 -2 -4;
0 -3 -6;
0 -4 -8],
[ 0 1 2;
1 1 1;
2 1 0;
3 1 -1;
4 1 -2],
[ 0 2 4;
2 3 4;
4 4 4;
6 5 4;
8 6 4],
[ 0 3 6;
3 5 7;
6 7 8;
9 9 9;
12 11 10]]


const savedir = joinpath(tempdir(), "h5")
if !isdir(savedir)
Expand Down Expand Up @@ -132,3 +155,9 @@ d = read(fid, "DS1")
@assert d.tag == "Character array"
@assert d.data == opq
close(fid)

file = getfile("h5ex_t_array.h5")
fid = h5open(file, "r")
A = read(fid, "DS1")
@assert A == AA
close(fid)

0 comments on commit 5679103

Please sign in to comment.