"""
Reader for the HDF5_ file format.
.. attention::
This Reader loads the entire HDF5_ file in memory. If you need to use any of
the more advanced features of an HDF5_ file, it is best to directly load
the file using H5py_.
.. _HDF5: https://www.hdfgroup.org/
.. _H5py: https://www.h5py.org/
"""
import os
try:
import h5py
except ImportError:
h5py = None
from ..base import Reader
from ..utils import register
[docs]@register
class HDF5Reader(Reader):
"""Reader for the HDF5_ file format."""
[docs] @staticmethod
def can_read(file, **kwargs):
"""The HDF5_ file format has a standard signature_.
The first 8 bytes are ``\\x89HDF\\r\\n\\x1a\\n``.
.. _signature: https://support.hdfgroup.org/HDF5/doc/H5.format.html#Superblock
"""
return Reader.get_bytes(file, 8) == b'\x89HDF\r\n\x1a\n'
[docs] def read(self, **kwargs):
"""Reads the HDF5_ file.
Parameters
----------
**kwargs
All key-value pairs are passed to :class:`~h5py.File`.
"""
if h5py is None:
raise ImportError(
'You must install h5py to read HDF5 files, run\n'
' pip install h5py'
)
def convert(name, obj):
head, tail = os.path.split(name)
s = self['/' + head] if head else self
if isinstance(obj, h5py.Dataset):
s.create_dataset(tail, data=obj[:], **obj.attrs)
elif isinstance(obj, h5py.Group):
s.create_group(tail, **obj.attrs)
else:
assert False, 'Unhandled HDF5Reader object {}'.format(obj)
def h5_open(name):
with h5py.File(name, mode='r', **kwargs) as h5:
self.add_metadata(**h5.attrs)
h5.visititems(convert)
# Calling h5py.File on a file on a mapped drive could raise
# an OSError. This occurred when a local folder was shared
# and then mapped on the same computer. Opening the file
# using open() and then passing in the file handle to
# h5py.File is more universal
if hasattr(self.file, 'read'): # already a file-like object
h5_open(self.file)
else:
with open(self.file, mode='rb') as fp:
h5_open(fp)