Source code for astropy.io.misc.hdf5
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""
This package contains functions for reading and writing HDF5 tables that are
not meant to be used directly, but instead are available as readers/writers in
`astropy.table`. See :ref:`table_io` for more details.
"""
from __future__ import print_function
import os
import numpy as np
from ... import log
HDF5_SIGNATURE = '\x89HDF\r\n\x1a\n'
__all__ = ['read_table_hdf5', 'write_table_hdf5']
def is_hdf5(origin, args, kwargs):
if isinstance(args[0], basestring):
if os.path.exists(args[0]):
with open(args[0], 'rb') as f:
if f.read(8) == HDF5_SIGNATURE:
return True
else:
return False
elif args[0].endswith('.hdf5') or args[0].endswith('.h5'):
return True
try:
import h5py
except ImportError:
return False
else:
return isinstance(args[0], (h5py.highlevel.File, h5py.highlevel.Group))
[docs]def read_table_hdf5(input, path=None):
"""
Read a Table object from an HDF5 file
This requires `h5py <http://alfven.org/wp/hdf5-for-python/>`_ to be
installed.
Parameters
----------
input : str or `h5py.highlevel.File` or `h5py.highlevel.Group`
If a string, the filename to read the table from. If an h5py object,
either the file or the group object to read the table from.
path : str
The path from which to read the table inside the HDF5 file.
This should be relative to the input file or group.
"""
try:
import h5py
except ImportError:
raise Exception("h5py is required to read and write HDF5 files")
if path is None:
raise ValueError("table path should be set via the path= argument")
elif path.endswith('/'):
raise ValueError("table path should end with table name, not /")
if '/' in path:
group, name = path.rsplit('/', 1)
else:
group, name = None, path
if isinstance(input, (h5py.highlevel.File, h5py.highlevel.Group)):
f, g = None, input
if group:
try:
g = g[group]
except KeyError:
raise IOError("Group {0} does not exist".format(group))
else:
f = h5py.File(input, 'r')
try:
g = f[group] if group else f
except KeyError:
raise IOError("Group {0} does not exist".format(group))
# Check whether table exists
if name not in g.keys():
raise IOError("Table {0} does not exist".format(path))
# Read the table from the file
dset = g[name]
# Create a Table object
from ...table import Table
table = Table(np.array(dset))
# Read the meta-data from the file
table.meta.update(dset.attrs)
if f is not None:
f.close()
return table
[docs]def write_table_hdf5(table, output, path=None, compression=False,
append=False, overwrite=False):
"""
Write a Table object to an HDF5 file
This requires `h5py <http://alfven.org/wp/hdf5-for-python/>`_ to be
installed.
Parameters
----------
output : str or `h5py.highlevel.File` or `h5py.highlevel.Group`
If a string, the filename to write the table to. If an h5py object,
either the file or the group object to write the table to.
compression : bool
Whether to compress the table inside the HDF5 file.
path : str
The path to which to write the table inside the HDF5 file.
This should be relative to the input file or group.
append : bool
Whether to append the table to an existing HDF5 file.
overwrite : bool
Whether to overwrite any existing file without warning.
"""
try:
import h5py
except ImportError:
raise Exception("h5py is required to read and write HDF5 files")
if path is None:
raise ValueError("table path should be set via the path= argument")
elif path.endswith('/'):
raise ValueError("table path should end with table name, not /")
if '/' in path:
group, name = path.rsplit('/', 1)
else:
group, name = None, path
if isinstance(output, h5py.highlevel.File) or \
isinstance(output, h5py.highlevel.Group):
f, g = None, output
if group:
try:
g = g[group]
except KeyError:
g = g.create_group(group)
else:
if os.path.exists(output) and not append:
if overwrite:
os.remove(output)
else:
raise IOError("File exists: {0}".format(output))
# Open the file for appending or writing
f = h5py.File(output, 'a' if append else 'w')
if group:
if append:
if group in f.keys():
g = f[group]
else:
g = f.create_group(group)
else:
g = f.create_group(group)
else:
g = f
# Check whether table already exists
if name in g.keys():
raise IOError("Table {0} already exists".format(path))
# Write the table to the file
dset = g.create_dataset(name, data=table._data, compression=compression)
# Write the meta-data to the file
for key in table.meta:
if isinstance(table.meta[key], basestring):
# Use np.string_ to ensure that fixed-length attributes are used.
dset.attrs[key] = np.string_(table.meta[key])
else:
try:
dset.attrs[key] = table.meta[key]
except TypeError:
log.warn("Attribute `{0}` of type {1} cannot be written to "
"HDF5 files - skipping".format(key,
type(table.meta[key])))
if f is not None:
f.close()