簡體   English   中英

使用astype在H5py中創建對HDF數據集的引用

[英]Creating reference to HDF dataset in H5py using astype

h5py文檔中 ,我看到我可以使用astype方法為數據集投射HDF數據集作為另一種類型。 這將返回一個context Manager,它可以即時執行轉換。

但是,我想讀取存儲為uint16的數據集,然后將其轉換為float32類型。 之后,我想從另一個函數中提取此數據集中的各種切片作為轉換類型float32 文檔將使用解釋為

with dataset.astype('float32'):
   castdata = dataset[:]

這將導致整個數據集被讀入並轉換為float32 ,這不是我想要的。 我想引用數據集,但是將其轉換為與numpy.astype相當的float32 如何創建對.astype('float32')對象的引用,以便我可以將它傳遞給另一個函數使用?

一個例子:

import h5py as HDF
import numpy as np
intdata = (100*np.random.random(10)).astype('uint16')

# create the HDF dataset
def get_dataset_as_float():
    hf = HDF.File('data.h5', 'w')
    d = hf.create_dataset('data', data=intdata)
    print(d.dtype)
    # uint16

    with d.astype('float32'):
    # This won't work since the context expires. Returns a uint16 dataset reference
       return d

    # this works but causes the entire dataset to be read & converted
    # with d.astype('float32'):
    #   return d[:]

此外,似乎astype上下文僅適用於訪問數據元素。 這意味着

def use_data():
   d = get_data_as_float()
   # this is a uint16 dataset

   # try to use it as a float32
   with d.astype('float32'):
       print(np.max(d))   # --> output is uint16
       print(np.max(d[:]))   # --> output is float32, but entire data is loaded

那么使用astype是不是一種簡潔的方式?

d.astype()返回一個AstypeContext對象。 如果您查看AstypeContext的源代碼,您將更好地了解正在發生的事情:

class AstypeContext(object):

    def __init__(self, dset, dtype):
        self._dset = dset
        self._dtype = numpy.dtype(dtype)

    def __enter__(self):
        self._dset._local.astype = self._dtype

    def __exit__(self, *args):
        self._dset._local.astype = None

輸入AstypeContext ,數據集的._local.astype屬性會更新為新的所需類型,當您退出上下文時,它會更改回原始值。

因此,您可以或多或少地獲得您正在尋找的行為:

def get_dataset_as_type(d, dtype='float32'):

    # creates a new Dataset instance that points to the same HDF5 identifier
    d_new = HDF.Dataset(d.id)

    # set the ._local.astype attribute to the desired output type
    d_new._local.astype = np.dtype(dtype)

    return d_new

當你現在從d_new讀取時,你會得到float32 numpy數組而不是uint16

d = hf.create_dataset('data', data=intdata)
d_new = get_dataset_as_type(d, dtype='float32')

print(d[:])
# array([81, 65, 33, 22, 67, 57, 94, 63, 89, 68], dtype=uint16)
print(d_new[:])
# array([ 81.,  65.,  33.,  22.,  67.,  57.,  94.,  63.,  89.,  68.], dtype=float32)

print(d.dtype, d_new.dtype)
# uint16, uint16

請注意,這不更新.dtype的屬性d_new (這似乎是不可變的)。 如果您還想更改dtype屬性,則可能需要子類化h5py.Dataset才能執行此操作。

astype的文檔似乎意味着將它全部讀入一個新的位置是它的目的。 因此,如果要在單獨的場合重復使用具有許多功能的浮動鑄造,則return d[:]是最合理的。

如果你知道你需要什么鑄造而且只需要它一次,你就可以改變一些事情並做一些事情:

def get_dataset_as_float(intdata, *funcs):
    with HDF.File('data.h5', 'w') as hf:
        d = hf.create_dataset('data', data=intdata)
        with d.astype('float32'):
            d2 = d[...]
            return tuple(f(d2) for f in funcs)

在任何情況下,您都希望在離開函數之前確保hf已關閉,否則您將在以后遇到問題。

一般來說,我建議完全分離轉換和數據集的加載/創建,並將數據集作為函數的參數之一傳遞。

以上可以稱如下:

In [16]: get_dataset_as_float(intdata, np.min, np.max, np.mean)
Out[16]: (9.0, 87.0, 42.299999)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM