web-dev-qa-db-ja.com

hdf5ファイルの結合

多数のhdf5ファイルがあり、それぞれに単一のデータセットがあります。データセットが大きすぎてRAMに保持できません。これらのファイルを組み合わせて、すべてのデータセットを個別に含む単一のファイルにしたいと考えています(つまり、データセットを単一のデータセットに連結するにはnot)。

これを行う1つの方法は、hdf5ファイルを作成してから、データセットを1つずつコピーすることです。これはバッファリングされたコピーである必要があるため、遅くて複雑になります。

これを行うより簡単な方法はありますか?基本的にはコンテナファイルを作成するだけなので、あるはずのように見えます。

私はpython/h5pyを使用しています。

30
Bitwise

1つの解決策は、HDF5 APIの低レベルの_h5py_ function 、特に_H5Ocopy_ function に対して_h5py.h5o.copy_インターフェイスを使用することです。 =:

_In [1]: import h5py as h5

In [2]: hf1 = h5.File("f1.h5")

In [3]: hf2 = h5.File("f2.h5")

In [4]: hf1.create_dataset("val", data=35)
Out[4]: <HDF5 dataset "val": shape (), type "<i8">

In [5]: hf1.create_group("g1")
Out[5]: <HDF5 group "/g1" (0 members)>

In [6]: hf1.get("g1").create_dataset("val2", data="Thing")
Out[6]: <HDF5 dataset "val2": shape (), type "|O8">

In [7]: hf1.flush()

In [8]: h5.h5o.copy(hf1.id, "g1", hf2.id, "newg1")

In [9]: h5.h5o.copy(hf1.id, "val", hf2.id, "newval")

In [10]: hf2.values()
Out[10]: [<HDF5 group "/newg1" (1 members)>, <HDF5 dataset "newval": shape (), type "<i8">]

In [11]: hf2.get("newval").value
Out[11]: 35

In [12]: hf2.get("newg1").values()
Out[12]: [<HDF5 dataset "val2": shape (), type "|O8">]

In [13]: hf2.get("newg1").get("val2").value
Out[13]: 'Thing'
_

上記は_h5py_バージョン_2.0.1-2+b1_およびiPythonバージョン_0.13.1-2+deb7u1_ atop Pythonバージョン_2.7.3-4+deb7u1_から生成されました多かれ少なかれ、Debian Wheezyのバニラインストール。ファイル_f1.h5_および_f2.h5_は、上記を実行する前には存在しませんでした。salotz ごとにPython 3の場合、データセット/グループ名はbytes(eg、_b"val"_)、notstr

コマンド_[7]_のhf1.flush()は重要です。低レベルインターフェイスは、メモリにキャッシュされているバージョンではなく、常にディスクに格納されている_.h5_ファイルのバージョンから描画されるためです。 Fileのルートにないグループとの間でデータセットをコピーするには、たとえばhf1.get("g1").idを使用して、そのグループのIDを指定します。

指定された名前のオブジェクトが宛先の場所にすでに存在する場合、_h5py.h5o.copy_は例外で失敗します(クローバーなし)。

13
hBy2Py

これは実際にはHDF5のユースケースの1つです。単一のファイルからすべてのデータセットにアクセスできるようにしたいだけで、それらが実際にディスクに格納されている方法を気にしない場合は、 外部リンク を使用できます。 HDF5 Webサイト から:

外部リンクを使用すると、グループは別のHDF5ファイルにオブジェクトを含めることができ、ライブラリがそれらのオブジェクトに現在のファイルにあるかのようにアクセスできます。このように、グループには、データセット、名前付きデータ型、および実際には別のファイルにあるグループが直接含まれているように見える場合があります。この機能は、リンクの作成と管理、外部オブジェクトへのパスの定義と取得、リンク名の解釈を行う一連の関数を介して実装されます。

h5pyで行う方法

myfile = h5py.File('foo.hdf5','a')
myfile['ext link'] = h5py.ExternalLink("otherfile.hdf5", "/path/to/resource")

注意:myfileを開くとき、既存のファイルの場合は'a'で開く必要があります。 'w'で開くと、内容が消去されます。

これは、すべてのデータセットを新しいファイルにコピーするよりもはるかに高速です。 otherfile.hdf5へのアクセス速度はわかりませんが、すべてのデータセットの操作は透過的です。つまり、h5pyはすべてのデータセットをfoo.hdf5にあるものとして認識します。

30
Yossarian

公式のhdf5ツールの h5copy を使用して、Python以外のソリューションを見つけました。 h5copyは、指定された個々のデータセットをhdf5ファイルから別の既存のhdf5ファイルにコピーできます。

誰かがpython/h5pyベースのソリューションを見つけたら、私はそれについて聞いてうれしいです。

11
Bitwise

私は通常 ipython および h5copy ツールを使用しますが、これは純粋なpythonソリューションに比べてはるかに高速です。h5copyをインストールすると、.

コンソールソリューションM.W.E.

#PLESE NOTE THIS IS IPYTHON CONSOLE CODE NOT PURE PYTHON

import h5py
#for every dataset Dn.h5 you want to merge to Output.h5 
f = h5py.File('D1.h5','r+') #file to be merged 
h5_keys = f.keys() #get the keys (You can remove the keys you don't use)
f.close() #close the file
for i in h5_keys:
        !h5copy -i 'D1.h5' -o 'Output.h5' -s {i} -d {i}

自動コンソールソリューション

マージするファイルが保存されているフォルダーで作業していると仮定してプロセスを完全に自動化するには:

import os 
d_names = os.listdir(os.getcwd())
d_struct = {} #Here we will store the database structure
for i in d_names:
   f = h5py.File(i,'r+')
   d_struct[i] = f.keys()
   f.close()

# A) empty all the groups in the new .h5 file 
for i in d_names:
    for j  in d_struct[i]:
        !h5copy -i '{i}' -o 'output.h5' -s {j} -d {j}

追加された.h5ファイルごとに新しいグループを作成します

以前のデータセットをoutput.h5内で分離したままにする場合は、最初にフラグ-pを使用してグループを作成する必要があります。

 # B) Create a new group in the output.h5 file for every input.h5 file
 for i in d_names:
        dataset = d_struct[i][0]
        newgroup = '%s/%s' %(i[:-3],dataset)
        !h5copy -i '{i}' -o 'output.h5' -s {dataset} -d {newgroup} -p
        for j  in d_struct[i][1:]:
            newgroup = '%s/%s' %(i[:-3],j) 
            !h5copy -i '{i}' -o 'output.h5' -s {j} -d {newgroup}
2
G M

これを更新するために、HDF5バージョン1.10には、「仮想データセット」と呼ばれるこのコンテキストで役立つ可能性のある新機能が付属しています。
ここに簡単なチュートリアルといくつかの説明があります: 仮想データセット
機能のより完全で詳細な説明とドキュメントは次のとおりです。
仮想データセットの追加ドキュメント
そして、仮想データセットAPIをh5pyに含めるためのh5pyのプル要求のマージ:
h5py Virtual Datasets PR しかし、それが現在のh5pyバージョンですでに利用可能であるかどうか、または後で来るかどうかはわかりません。

1
fedepad

Python(IPythonではなく)とh5copyを使用してHDF5ファイルをマージするには、次のように構築できます GMの答え

import h5py
import os

d_names = os.listdir(os.getcwd())
d_struct = {} #Here we will store the database structure
for i in d_names:
   f = h5py.File(i,'r+')
   d_struct[i] = f.keys()
   f.close()

for i in d_names:
   for j  in d_struct[i]:
      os.system('h5copy -i %s -o output.h5 -s %s -d %s' % (i, j, j))
0
zilba25