'''save/load from HDF5 routines
-------
'''
from .omas_utils import *
from .omas_core import ODS
def dict2hdf5(filename, dictin, groupname='', recursive=True, lists_as_dicts=False, compression=None):
"""
Utility function to save hierarchy of dictionaries containing numpy-compatible objects to hdf5 file
:param filename: hdf5 file to save to
:param dictin: input dictionary
:param groupname: group to save the data in
:param recursive: traverse the dictionary
:param lists_as_dicts: convert lists to dictionaries with integer strings
:param compression: gzip compression level
"""
import h5py
if isinstance(filename, str):
with h5py.File(filename, 'w') as g:
dict2hdf5(g, dictin, recursive=recursive, lists_as_dicts=lists_as_dicts, compression=compression)
return
else:
parent = filename
if isinstance(dictin, ODS):
dictin = dictin.omas_data
if groupname:
g = parent.create_group(groupname)
else:
g = parent
for key, item in list(dictin.items()):
if isinstance(item, ODS):
item = item.omas_data
if isinstance(item, dict):
if recursive:
dict2hdf5(g, item, str(key), recursive=recursive, lists_as_dicts=lists_as_dicts, compression=compression)
elif lists_as_dicts and isinstance(item, (list, tuple)) and not isinstance(item, numpy.ndarray):
item = {'%d' % k: v for k, v in enumerate(item)}
dict2hdf5(g, item, key, recursive=recursive, lists_as_dicts=lists_as_dicts, compression=compression)
else:
if item is None:
item = '_None'
tmp = numpy.array(item)
if tmp.dtype.name.lower().startswith('u') or tmp.dtype.name.lower().startswith('s'):
tmp = tmp.astype('S')
elif tmp.dtype.name.lower().startswith('o'):
if is_uncertain(tmp):
g.create_dataset(key + '_error_upper', std_devs(tmp).shape, dtype=std_devs(tmp).dtype, compression=compression)[
...
] = std_devs(tmp)
tmp = nominal_values(tmp)
else:
continue
if tmp.shape == ():
g.create_dataset(key, tmp.shape, dtype=tmp.dtype)[...] = tmp
else:
g.create_dataset(key, tmp.shape, dtype=tmp.dtype, compression=compression)[...] = tmp
return g
[docs]def save_omas_h5(ods, filename):
"""
Save an ODS to HDF5
:param ods: OMAS data set
:param filename: filename or file descriptor to save to
"""
return dict2hdf5(filename, ods, lists_as_dicts=True)
def convertDataset(ods, data):
"""
Recursive utility function to map HDF5 structure to ODS
:param ods: input ODS to be populated
:param data: HDF5 dataset of group
"""
import h5py
keys = data.keys()
try:
keys = sorted(list(map(int, keys)))
except ValueError:
pass
for oitem in keys:
item = str(oitem)
if item.endswith('_error_upper'):
continue
if isinstance(data[item], h5py.Dataset):
if item + '_error_upper' in data:
if isinstance(data[item][()], (float, numpy.floating)):
ods.setraw(item, ufloat(data[item][()], data[item + '_error_upper'][()]))
else:
ods.setraw(item, uarray(data[item][()], data[item + '_error_upper'][()]))
else:
ods.setraw(item, data[item][()])
elif isinstance(data[item], h5py.Group):
convertDataset(ods.setraw(oitem, ods.same_init_ods()), data[item])
[docs]def load_omas_h5(filename, consistency_check=True, imas_version=omas_rcparams['default_imas_version'], cls=ODS):
"""
Load ODS or ODC from HDF5
:param filename: filename or file descriptor to load from
:param consistency_check: verify that data is consistent with IMAS schema
:param imas_version: imas version to use for consistency check
:param cls: class to use for loading the data
:return: OMAS data set
"""
import h5py
ods = cls(imas_version=imas_version, consistency_check=False)
with h5py.File(filename, 'r') as data:
convertDataset(ods, data)
ods.consistency_check = consistency_check
return ods
[docs]def through_omas_h5(ods, method=['function', 'class_method'][1]):
"""
Test save and load OMAS HDF5
:param ods: ods
:return: ods
"""
filename = omas_testdir(__file__) + '/test.h5'
ods = copy.deepcopy(ods) # make a copy to make sure save does not alter entering ODS
if method == 'function':
save_omas_h5(ods, filename)
ods1 = load_omas_h5(filename)
else:
ods.save(filename)
ods1 = ODS().load(filename)
return ods1