with update how create python hdf5 h5py

python - update - Combinando archivos hdf5



install hdf5 ubuntu (5)

Tengo varios archivos hdf5, cada uno de los cuales tiene un solo conjunto de datos. Los conjuntos de datos son demasiado grandes para contener en la memoria RAM. Me gustaría combinar estos archivos en un solo archivo que contenga todos los conjuntos de datos por separado (es decir, no concatenar los conjuntos de datos en un solo conjunto de datos).

Una forma de hacerlo es crear un archivo hdf5 y luego copiar los conjuntos de datos uno por uno. Esto será lento y complicado porque tendrá que ser una copia en búfer.

¿Hay una manera más simple de hacer esto? Parece que debería haberlo, ya que básicamente se trata de crear un archivo contenedor.

Estoy usando python / h5py.


Encontré una solución que no es de python utilizando h5copy de las herramientas oficiales de hdf5. h5copy puede copiar conjuntos de datos individuales especificados de un archivo hdf5 en otro archivo hdf5 existente.

Si alguien encuentra una solución basada en python / h5py, me encantaría saberlo.


Este es en realidad uno de los casos de uso de HDF5. Si solo desea poder acceder a todos los conjuntos de datos desde un solo archivo y no le importa cómo se almacenan en el disco, puede usar enlaces externos . Desde el sitio web de HDF5 :

Los enlaces externos permiten que un grupo incluya objetos en otro archivo HDF5 y permite que la biblioteca acceda a esos objetos como si estuvieran en el archivo actual. De esta manera, puede parecer que un grupo contiene directamente conjuntos de datos, tipos de datos con nombre e incluso grupos que realmente están en un archivo diferente. Esta función se implementa a través de un conjunto de funciones que crean y administran los enlaces, definen y recuperan rutas a objetos externos e interpretan los nombres de los enlaces:

Aquí está cómo hacerlo en h5py :

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

Tenga cuidado: al abrir myfile , debe abrirlo con ''a'' si es un archivo existente. Si lo abres con ''w'' , borrará su contenido.

Esto sería mucho más rápido que copiar todos los conjuntos de datos en un nuevo archivo. No sé qué tan rápido sería el acceso a otherfile.hdf5 , pero operar en todos los conjuntos de datos sería transparente, es decir, h5py vería que todos los conjuntos de datos residen en foo.hdf5 .


Para actualizar esto, con HDF5 versión 1.10 viene una nueva característica que podría ser útil en este contexto llamada "Conjuntos de datos virtuales".
Aquí encontrará un breve tutorial y algunas explicaciones: Conjuntos de datos virtuales .
Aquí explicaciones y documentación más completa y detallada de la característica:
Datasets virtuales extra doc .
Y aquí la solicitud de extracción combinada en h5py para incluir la API de conjuntos de datos virtuales en h5py:
h5py Virtual Datasets PR, pero no sé si ya está disponible en la versión actual de h5py o vendrá más adelante.


Por lo general uso la herramienta ipython y h5copy , esto es mucho más rápido en comparación con una solución de python pura. Una vez instalado h5copy.

Solución de consola MWE

#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}

Solución de consola automatizada

Para automatizar completamente el proceso, suponiendo que está trabajando en la carpeta donde se almacenan los archivos que se fusionarán:

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}

Crea un nuevo grupo para cada archivo .h5 agregado

Si desea mantener el conjunto de datos anterior separado dentro de la salida.h5, primero debe crear el grupo utilizando el indicador -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}


Una solución es utilizar la interfaz h5py para la function H5Ocopy bajo nivel de la API HDF5, en particular la 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''

Lo anterior se generó con la versión 2.0.1-2+b1 y la versión 0.13.1-2+deb7u1 sobre la versión 2.7.3-4+deb7u1 de 2.7.3-4+deb7u1 partir de una instalación de vainilla más o menos de Debian Wheezy. Los archivos f1.h5 y f2.h5 no existían antes de ejecutar lo anterior. Tenga en cuenta que, por salotz , para Python 3, los nombres del conjunto de datos / grupo deben ser bytes (por ejemplo, b"val" ), no str .

El hf1.flush() en el comando [7] es crucial, ya que la interfaz de bajo nivel aparentemente siempre se basará en la versión del archivo .h5 almacenado en el disco, no en la memoria caché. La copia de conjuntos de datos a / desde grupos que no se encuentran en la raíz de un File puede lograrse proporcionando el ID de ese grupo utilizando, por ejemplo, hf1.get("g1").id .

Tenga en cuenta que h5py.h5o.copy fallará con una excepción (sin clobber) si ya existe un objeto con el nombre indicado en la ubicación de destino.