Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Codec for compression for use with LINDI #1193

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# HDMF Changelog

## HDMF 3.14.6 (Upcoming)

### Enhancements
- Allow Codec for compression for use with LINDI

## HDMF 3.14.5 (September 17, 2024)

### Enhancements
Expand Down
61 changes: 21 additions & 40 deletions src/hdmf/backends/hdf5/h5_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
import logging

from ...array import Array
from ...data_utils import DataIO, AbstractDataChunkIterator, append_data
from ...data_utils import DataIO, AbstractDataChunkIterator
from ...query import HDMFDataset, ReferenceResolver, ContainerResolver, BuilderResolver
from ...region import RegionSlicer
from ...spec import SpecWriter, SpecReader
from ...utils import docval, getargs, popargs, get_docval, get_data_shape
from ...utils import docval, getargs, popargs, get_docval


class HDF5IODataChunkIteratorQueue(deque):
Expand Down Expand Up @@ -108,20 +108,6 @@
def shape(self):
return self.dataset.shape

def append(self, arg):
# Get Builder
builder = self.io.manager.get_builder(arg)
if builder is None:
raise ValueError(
"The container being appended to the dataset has not yet been built. "
"Please write the container to the file, then open the modified file, and "
"append the read container to the dataset."
)

# Get HDF5 Reference
ref = self.io._create_ref(builder)
append_data(self.dataset, ref)


class DatasetOfReferences(H5Dataset, ReferenceResolver, metaclass=ABCMeta):
"""
Expand Down Expand Up @@ -463,8 +449,9 @@
'doc': 'Chunk shape or True to enable auto-chunking',
'default': None},
{'name': 'compression',
'type': (str, bool, int),
'type': (str, bool, int, 'Codec'),
'doc': 'Compression strategy. If a bool is given, then gzip compression will be used by default.' +
'Codec only applies to LINDI.' +
'http://docs.h5py.org/en/latest/high/dataset.html#dataset-compression',
'default': None},
{'name': 'compression_opts',
Expand Down Expand Up @@ -543,13 +530,17 @@
self.__iosettings.pop('compression_opts', None)
# Validate the compression options used
self._check_compression_options()
# Confirm that the compressor is supported by h5py
if not self.filter_available(self.__iosettings.get('compression', None),
self.__allow_plugin_filters):
msg = "%s compression may not be supported by this version of h5py." % str(self.__iosettings['compression'])
if not self.__allow_plugin_filters:
msg += " Set `allow_plugin_filters=True` to enable the use of dynamically-loaded plugin filters."
raise ValueError(msg)
# Confirm that the compressor is supported by h5py (unless we are using Codec with LINDI)
if isinstance(self.__iosettings.get('compression', None), str):
if not self.filter_available(self.__iosettings.get('compression', None),
self.__allow_plugin_filters):
msg = (

Check warning on line 537 in src/hdmf/backends/hdf5/h5_utils.py

View check run for this annotation

Codecov / codecov/patch

src/hdmf/backends/hdf5/h5_utils.py#L537

Added line #L537 was not covered by tests
f"{self.__iosettings['compression']} compression may not be supported "
"by this version of h5py."
)
if not self.__allow_plugin_filters:
msg += " Set `allow_plugin_filters=True` to enable the use of dynamically-loaded plugin filters."
raise ValueError(msg)

Check warning on line 543 in src/hdmf/backends/hdf5/h5_utils.py

View check run for this annotation

Codecov / codecov/patch

src/hdmf/backends/hdf5/h5_utils.py#L542-L543

Added lines #L542 - L543 were not covered by tests
# Check possible parameter collisions
if isinstance(self.data, Dataset):
for k in self.__iosettings.keys():
Expand Down Expand Up @@ -628,11 +619,12 @@
if szip_opts_error:
raise ValueError("SZIP compression filter compression_opts"
" must be a 2-tuple ('ec'|'nn', even integer 0-32).")
# Warn if compressor other than gzip is being used
if self.__iosettings['compression'] not in ['gzip', h5py_filters.h5z.FILTER_DEFLATE]:
warnings.warn(str(self.__iosettings['compression']) + " compression may not be available "
"on all installations of HDF5. Use of gzip is recommended to ensure portability of "
"the generated HDF5 files.", stacklevel=4)
# Warn if compressor other than gzip is being used (Unless we are using Codec with LINDI)
if isinstance(self.__iosettings['compression'], str):
if self.__iosettings['compression'] not in ['gzip', h5py_filters.h5z.FILTER_DEFLATE]:
warnings.warn(str(self.__iosettings['compression']) + " compression may not be available "

Check warning on line 625 in src/hdmf/backends/hdf5/h5_utils.py

View check run for this annotation

Codecov / codecov/patch

src/hdmf/backends/hdf5/h5_utils.py#L625

Added line #L625 was not covered by tests
"on all installations of HDF5. Use of gzip is recommended to ensure portability of "
"the generated HDF5 files.", stacklevel=4)

@staticmethod
def filter_available(filter, allow_plugin_filters):
Expand Down Expand Up @@ -672,14 +664,3 @@
if isinstance(self.data, Dataset) and not self.data.id.valid:
return False
return super().valid

@property
def maxshape(self):
if 'maxshape' in self.io_settings:
return self.io_settings['maxshape']
elif hasattr(self.data, 'maxshape'):
return self.data.maxshape
elif hasattr(self, "shape"):
return self.shape
else:
return get_data_shape(self.data)
Loading