Only support scalars and numpy arrays in HDF5 output. Update documentation. Closes #145

This commit is contained in:
Sebastien Bourdeauducq 2015-10-28 18:33:42 +08:00
parent ec328cf5e1
commit 40b4129c65
3 changed files with 27 additions and 30 deletions

View File

@ -208,9 +208,15 @@ class HasEnvironment:
broadcast=False, persist=False, save=True): broadcast=False, persist=False, save=True):
"""Sets the contents and handling modes of a dataset. """Sets the contents and handling modes of a dataset.
If the dataset is broadcasted, it must be PYON-serializable.
If the dataset is saved, it must be a scalar (``bool``, ``int``,
``float`` or NumPy scalar) or a NumPy array.
:param broadcast: the data is sent in real-time to the master, which :param broadcast: the data is sent in real-time to the master, which
dispatches it. Returns a Notifier that can be used to mutate the dataset. dispatches it. Returns a Notifier that can be used to mutate the
:param persist: the master should store the data on-disk. Implies broadcast. dataset.
:param persist: the master should store the data on-disk. Implies
broadcast.
:param save: the data is saved into the local storage of the current :param save: the data is saved into the local storage of the current
run (archived as a HDF5 file). run (archived as a HDF5 file).
""" """

View File

@ -138,21 +138,17 @@ _type_to_hdf5 = {
def result_dict_to_hdf5(f, rd): def result_dict_to_hdf5(f, rd):
for name, data in rd.items(): for name, data in rd.items():
if isinstance(data, list): flag = None
el_ty = type(data[0]) # beware: isinstance(True/False, int) == True
for d in data: if isinstance(data, bool):
if type(d) != el_ty: data = np.int8(data)
raise TypeError("All list elements must have the same" flag = "py_bool"
" type for HDF5 output") elif isinstance(data, int):
try: data = np.int64(data)
el_ty_h5 = _type_to_hdf5[el_ty] flag = "py_int"
except KeyError:
raise TypeError("List element type {} is not supported for" if isinstance(data, np.ndarray):
" HDF5 output".format(el_ty)) dataset = f.create_dataset(name, data=data)
dataset = f.create_dataset(name, (len(data), ), el_ty_h5)
dataset[:] = data
elif isinstance(data, np.ndarray):
f.create_dataset(name, data=data)
else: else:
ty = type(data) ty = type(data)
if ty is str: if ty is str:
@ -163,10 +159,13 @@ def result_dict_to_hdf5(f, rd):
ty_h5 = _type_to_hdf5[ty] ty_h5 = _type_to_hdf5[ty]
except KeyError: except KeyError:
raise TypeError("Type {} is not supported for HDF5 output" raise TypeError("Type {} is not supported for HDF5 output"
.format(ty)) .format(ty)) from None
dataset = f.create_dataset(name, (), ty_h5) dataset = f.create_dataset(name, (), ty_h5)
dataset[()] = data dataset[()] = data
if flag is not None:
dataset.attrs[flag] = np.int8(1)
class DatasetManager: class DatasetManager:
def __init__(self, ddb): def __init__(self, ddb):

View File

@ -9,25 +9,17 @@ from artiq.master.worker_db import result_dict_to_hdf5
class TypesCase(unittest.TestCase): class TypesCase(unittest.TestCase):
def test_types(self): def test_types(self):
d = { d = {
"bool": True,
"int": 42, "int": 42,
"float": 42.0, "float": 42.0,
"string": "abcdef", "string": "abcdef",
"intlist": [1, 2, 3],
"floatlist": [1.0, 2.0, 3.0]
} }
for size in 8, 16, 32, 64: for size in 8, 16, 32, 64:
signed = getattr(np, "int" + str(size)) d["i"+str(size)] = getattr(np, "int" + str(size))(42)
unsigned = getattr(np, "uint" + str(size)) d["u"+str(size)] = getattr(np, "uint" + str(size))(42)
d["i"+str(size)] = signed(42)
d["u"+str(size)] = unsigned(42)
d["i{}list".format(size)] = [signed(x) for x in range(3)]
d["u{}list".format(size)] = [unsigned(x) for x in range(3)]
for size in 16, 32, 64: for size in 16, 32, 64:
ty = getattr(np, "float" + str(size)) d["f"+str(size)] = getattr(np, "float" + str(size))(42)
d["f"+str(size)] = ty(42)
d["f{}list".format(size)] = [ty(x) for x in range(3)]
with h5py.File("h5types.h5", "w") as f: with h5py.File("h5types.h5", "w") as f:
result_dict_to_hdf5(f, d) result_dict_to_hdf5(f, d)