h5py中的引用数组
我在使用h5py这个库。我想在我的HDF5文件里创建一个复合数据集,包含字符串(第一列)和区域引用(第二列)。为此,我正在尝试定义一个包含字符串和引用的numpy数据类型。
但是在这之前,我就遇到了问题,无法定义一个包含HDF5区域引用的numpy数据类型数组。
##map_h5py.py
import h5py
import numpy as np
h = h5py.File('testing_mapping.h5', 'a')
cell_names = ['cell0', 'cell1', 'cell2', 'cell3']
dummy_data = np.random.rand(4,20)
##create random data
dset = h.create_dataset('/data/Vm', data=dummy_data, dtype='float32')
#declare a data type
sp_type = np.dtype([('ref',h5py.special_dtype(ref=h5py.RegionReference))])
##this works - 1
refs_list = []
for ii in range(dset.shape[0]):
refs_list.append(dset.regionref[ii])
h.create_dataset('/map/Vm_list', data=refs_list, dtype=h5py.special_dtype(ref=h5py.RegionReference))
##this doesn't - 2
ref_dset = h.create_dataset('/map/Vm_pre', shape=(dset.shape[0],), dtype=sp_type)
for ii in range(dset.shape[0]):
ref_dset[ii] = dset.regionref[ii]
# #this doesn't - 3
ref_numpy = np.zeros(dset.shape[0], dtype=sp_type)
for ii in range(dset.shape[0]):
ref_numpy[ii] = dset.regionref[ii]
h.create_dataset('/map/Vm_post', data=ref_numpy, dtype=sp_type)
h.close()
在第2和第3种情况下出现的错误是:
ref_numpy[ii] = dset.regionref[ii]
ValueError: Setting void-array with object members using buffer.
1 个回答
1
我也遇到过同样的问题,所以在h5py上创建了一个问题(不过,这个问题可能更应该发给numpy - 见下文)。在这里,我会把那个问题中的重要信息复制过来,帮助大家理解为什么会出现这个问题,以及如何解决它。
下面是一个比较简单的例子,展示了明显的赋值方式为什么不管用:
with h5py.File('tst.hdf5', mode='w') as f:
ds1 = f.create_dataset('ds1', shape=(1,), dtype=np.dtype([('objfield', h5py.special_dtype(ref=h5py.Reference))]))
ds2 = f.create_dataset('ds2', shape=(), dtype=np.int)
# All these lines raise ValueError:
# ds1[0, 'objfield'] = ds2.ref
# ds1[0, 'objfield'] = (ds2.ref,)
# ds1[0, 'objfield'] = np.array(ds2.ref)
# ds1[0, 'objfield'] = np.array((ds2.ref,))
# ds1[0, 'objfield'] = np.array((ds2.ref,), dtype=h5py.special_dtype(ref=h5py.Reference))
# ds1[0, 'objfield'] = np.array(ds2.ref, dtype=np.dtype([('objfield', h5py.special_dtype(ref=h5py.Reference))]))
# Only this one works:
ds1[0, 'objfield'] = np.array((ds2.ref,), dtype=np.dtype([('objfield', h5py.special_dtype(ref=h5py.Reference))]))
最后一行是我想出的一个解决方法。
当错误发生时,是在这段代码中抛出的:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-19-63893646daac> in <module>()
4
5 # All these lines raise ValueError:
----> 6 ds1[0, 'objfield'] = ds2.ref
7 # ds1[0, 'objfield'] = (ds2.ref,)
8 # ds1[0, 'objfield'] = np.array(ds2.ref)
/usr/local/lib/python2.7/dist-packages/h5py/_hl/dataset.pyc in __setitem__(self, args, val)
506 val = numpy.asarray(val, dtype=dtype, order='C')
507 if cast_compound:
--> 508 val = val.astype(numpy.dtype([(names[0], dtype)]))
509 else:
510 val = numpy.asarray(val, order='C')
ValueError: Setting void-array with object members using buffer.
在查看dataset.py中的这段代码后,发现这个错误其实可以用普通的numpy轻松复现,根本不需要HDF:
objarr = np.array(123, dtype=np.dtype('O'))
objarr.astype(np.dtype([('field', np.dtype('O'))]))
这里的第二行代码就会抛出完全相同的错误。另一方面,和HDF的例子类似,这段代码是可以正常工作的:
objarr = np.array((123, ), dtype=np.dtype([('field', np.dtype('O'))]))
objarr = np.asarray(objarr, dtype=np.dtype('O'))
objarr = objarr.astype(np.dtype([('field', np.dtype('O'))]))
所以,现在你至少知道了为什么会出现这个问题,以及如何解决它 :) 如果你想了解更多,可以关注上面提到的问题,看看开发者们的回答(现在还没有人回复)。