HDF5.jl
HDF5.jl copied to clipboard
Writing scalar datasets of compound types
Hi,
I recently noticed that datatype()
now works for all kinds of Julia structs! That’s such an awesome feature, allowing me to simplify my code a lot.
There is one remaining issue for me though. If you want to write a scalar dataset, this works fine with normal numbers and Complex
using HDF5
import ForwardDiff.Dual # just an example
f = h5open("test.h5", "w")
dual = Dual{:test}(1.0, 0.1)
# these all work
f["x1"] = 1.0
f["x2"] = 1im
f["x3"] = [dual]
f["x4"] = [complex(dual, dual)]
# these fail
f["x5"] = dual
f["x6"] = complex(dual, dual)
However, x5
and x6
fail with the error
ERROR: MethodError: no method matching unsafe_convert(::Type{Ptr{Nothing}}, ::Dual{:test, Float64, 1})
Closest candidates are:
unsafe_convert(::Union{Type{Ptr{Nothing}}, Type{Ptr{Base.Libc.FILE}}}, ::Base.Libc.FILE)
@ Base libc.jl:94
unsafe_convert(::Type{Ptr{T}}, ::Base.ReshapedArray{T}) where T
@ Base reshapedarray.jl:283
unsafe_convert(::Type{Ptr{T}}, ::Base.Threads.Atomic{T}) where T
@ Base atomics.jl:328
...
Stacktrace:
[1] h5d_write(dataset_id::HDF5.Dataset, mem_type_id::HDF5.Datatype, mem_space_id::Int64, file_space_id::Int64, xfer_plist_id::HDF5.DatasetTransferProperties, buf::Dual{:test, Float64, 1})
@ HDF5.API ~/.julia/packages/HDF5/Ws1wH/src/api/functions.jl:908
[2] write_dataset(dset::HDF5.Dataset, memtype::HDF5.Datatype, x::Dual{:test, Float64, 1}, xfer::HDF5.DatasetTransferProperties)
@ HDF5 ~/.julia/packages/HDF5/Ws1wH/src/datasets.jl:490
[3] write_dataset(dset::HDF5.Dataset, memtype::HDF5.Datatype, x::Dual{:test, Float64, 1})
@ HDF5 ~/.julia/packages/HDF5/Ws1wH/src/datasets.jl:490
[4] write_dataset(parent::HDF5.File, name::String, data::Dual{:test, Float64, 1}; pv::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ HDF5 ~/.julia/packages/HDF5/Ws1wH/src/datasets.jl:320
[5] write_dataset(parent::HDF5.File, name::String, data::Dual{:test, Float64, 1})
@ HDF5 ~/.julia/packages/HDF5/Ws1wH/src/datasets.jl:315
[6] write(parent::HDF5.File, name::String, data::Dual{:test, Float64, 1}; pv::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ HDF5 ~/.julia/packages/HDF5/Ws1wH/src/datasets.jl:342
[7] write(parent::HDF5.File, name::String, data::Dual{:test, Float64, 1})
@ HDF5 ~/.julia/packages/HDF5/Ws1wH/src/datasets.jl:342
[8] setindex!(parent::HDF5.File, val::Dual{:test, Float64, 1}, path::String; pv::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ HDF5 ~/.julia/packages/HDF5/Ws1wH/src/highlevel.jl:107
[9] setindex!(parent::HDF5.File, val::Dual{:test, Float64, 1}, path::String)
@ HDF5 ~/.julia/packages/HDF5/Ws1wH/src/highlevel.jl:90
[10] top-level scope
@ REPL[10]:14
Yeah we don't support those as ScalarTypes
. I'm not sure what would be the best approach here. Technically Dual
is a struct and should be a CompoundData, but since it's <: Real
we can't handle it.
(x5
also fails with structs that are not <: Real
)
Maybe a sensible default would be to consider structs scalar unless they are AbstractArrays (since if they are not, it is not clear how to get elements from them anyway).
Maybe anything coming in via setindex!
that is not an AbstractArray
or a Tuple
should be considered a scalar?