Подтвердить что ты не робот

Объединение файлов hdf5

У меня есть несколько файлов hdf5, каждый из которых имеет один набор данных. Наборы данных слишком велики для хранения в ОЗУ. Я хотел бы объединить эти файлы в один файл, содержащий все наборы данных отдельно (т.е. не, чтобы объединить наборы данных в один набор данных).

Один из способов сделать это - создать файл hdf5, а затем скопировать данные по одному. Это будет медленным и сложным, потому что нужно будет буферизовать копию.

Есть ли более простой способ сделать это? Похоже, что должно быть, так как это просто создание файла контейнера.

Я использую python/h5py.

4b9b3361

Ответ 1

Одним из решений является использование интерфейса h5py для низкоуровневой H5Ocopy функция:

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 version 2.0.1-2+b1 и версия iPython 0.13.1-2+deb7u1 поверх версии Python 2.7.3-4+deb7u1 из более или менее ванильной установки Debian Wheezy. Файлы f1.h5 и f2.h5 не существовали до выполнения вышеуказанного.

Команда hf1.flush() в команде [7] имеет решающее значение, так как интерфейс низкого уровня, по-видимому, всегда будет извлекаться из версии файла .h5, хранящегося на диске, а не в кэше в памяти. Копирование наборов данных в/из групп не в корневом каталоге File может быть достигнуто путем подачи идентификатора этой группы с использованием, например, hf1.get("g1").id.

Обратите внимание, что h5py.h5o.copy завершится с исключением (без clobber), если объект указанного имени уже существует в месте назначения.

Ответ 2

Это фактически один из вариантов использования HDF5. Если вы просто хотите иметь доступ ко всем наборам данных из одного файла, и им все равно, как они фактически хранятся на диске, вы можете использовать external ссылки. На веб-сайте HDF5:

Внешние ссылки позволяют группе включать объекты в другой файл HDF5 и позволяют библиотеке обращаться к этим объектам так, как если бы они находились в текущем файле. Таким образом, группа может, как представляется, напрямую содержать наборы данных, имена типов данных и даже группы, которые фактически находятся в другом файле. Эта функция реализована с помощью набора функций, которые создают и управляют ссылками, определяют и извлекают пути к внешним объектам и интерпретируют имена ссылок:

Здесь, как это сделать в h5py:

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

Это будет намного быстрее, чем копирование всех наборов данных в новый файл. Я не знаю, насколько бы быстрым был доступ к otherfile.hdf5, но работа на всех наборах данных была бы прозрачной - то есть h5py увидит все наборы данных как находящиеся в foo.hdf5.

Ответ 3

Я нашел решение, отличное от python, используя h5copy из официальных инструментов hdf5. h5copy может копировать отдельные указанные наборы данных из файла hdf5 в другой существующий файл hdf5.

Если кто-то найдет решение на основе python/h5py, я был бы рад услышать об этом.

Ответ 4

Я обычно использую ipython и h5copy tool togheter, это намного быстрее по сравнению с чистым решением 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}

Ответ 5

Чтобы обновить эту версию, в HDF5 версии 1.10 появилась новая функция, которая может быть полезна в этом контексте под названием "Виртуальные наборы данных".
Здесь вы найдете краткое руководство и некоторые пояснения: Виртуальные наборы данных.
Здесь более полные и подробные объяснения и документация по этой функции:
Дополнительные данные Datasets.
И здесь объединенный запрос pull в h5py для включения API виртуальных datatsets в h5py:
h5py Virtual Datasets PR, но я не знаю, уже ли он доступен в текущей версии h5py или будет позже.