Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions pyfive/h5d.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,21 @@ def __init__(self, dataobject, pseudo_chunking_size_MB=4):
# throws a flake8 wobbly for Python<3.10; match is Py3.10+ syntax
match self.layout_class: # noqa
case 0: #compact storage
raise NotImplementedError("Compact Storage")
self.data = None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it would be more consistent with the rest of the code if we pushed the compact handling into a method called from here.

layout = None
for msg in dataobject.msgs:
if msg["type"] == 8:
layout = msg
break
if layout is None:
raise ValueError("No layout message in compact dataset?")
byts = dataobject.msg_data[msg["offset_to_message"]:msg["offset_to_message"]+msg["size"]]
layout_version = byts[0]
if layout_version == 1 or layout_version == 2:
raise NotImplementedError("Compact layout v1 and v2.")
elif layout_version == 3 or layout_version == 4:
size = int.from_bytes(byts[2:4], "little")
self.data = byts[4:4+size]
case 1: # contiguous storage
self.data_offset, = struct.unpack_from('<Q', dataobject.msg_data, self.property_offset)
case 2: # chunked storage
Expand Down Expand Up @@ -161,7 +175,18 @@ def get_data(self, args, fillvalue):
# throws a flake8 wobbly for Python<3.10; match is Py3.10+ syntax
match self.layout_class: # noqa
case 0: #compact storage
raise NotImplementedError("Compact Storage")
if self.data is None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Similarly, this functionality would be better in a method.

if isinstance(dtype, tuple):
dtype = np.array(fillvalue).dtype
return np.full(self.shape, fillvalue, dtype=dtype)[args]
else:
view = np.frombuffer(
self.data,
dtype=self._dtype,
).reshape(self.shape)
# Create the sub-array
result = view[args]
return result
case 1: # contiguous storage
if self.data_offset == UNDEFINED_ADDRESS:
# no storage is backing array, return an array of
Expand Down
Binary file added tests/compact.hdf5
Binary file not shown.
13 changes: 13 additions & 0 deletions tests/make_compact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import h5py
import numpy as np

f = h5py.File('compact.hdf5', 'w', libver='earliest')
data = np.array([1, 2, 3, 4], dtype=np.int32)
dtype = h5py.h5t.NATIVE_INT32
space = h5py.h5s.create_simple(data.shape)
dcpl = h5py.h5p.create(h5py.h5p.DATASET_CREATE)
dcpl.set_layout(h5py.h5d.COMPACT)
dset_id = h5py.h5d.create(f.id, b"compact", dtype, space, dcpl=dcpl)
dset_id.write(h5py.h5s.ALL, h5py.h5s.ALL, data)

f.close()
19 changes: 19 additions & 0 deletions tests/test_compact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os

import numpy as np
from numpy.testing import assert_array_equal

import pyfive

DIRNAME = os.path.dirname(__file__)
DATASET_CHUNKED_HDF5_FILE = os.path.join(DIRNAME, 'compact.hdf5')


def test_chunked_dataset():

with pyfive.File(DATASET_CHUNKED_HDF5_FILE) as hfile:
data = np.array([1, 2, 3, 4], dtype=np.int32)

# check data
dset1 = hfile['compact']
assert_array_equal(dset1[...], data)
Loading