web-dev-qa-db-fra.com

Combinaison de fichiers hdf5

J'ai un certain nombre de fichiers hdf5, chacun d'entre eux contenant un seul jeu de données. Les jeux de données sont trop volumineux pour être stockés dans la RAM. Je souhaite combiner ces fichiers en un seul fichier contenant tous les jeux de données séparément (c'est-à-dire pas pour concaténer les jeux de données en un seul jeu de données).

Une façon de procéder consiste à créer un fichier hdf5, puis à copier les jeux de données un par un. Ce sera lent et compliqué car il devra être mis en mémoire tampon.

Y a-t-il un moyen plus simple de faire cela? Cela semble être le cas, car il s’agit essentiellement de créer un fichier conteneur.

J'utilise python/h5py.

24
Bitwise

C’est en fait l’un des cas d’utilisation de HDF5 . Si vous souhaitez simplement pouvoir accéder à tous les jeux de données à partir d’un seul fichier, sans vous préoccuper de la façon dont ils sont stockés sur le disque, vous pouvez utiliser liens externes . Sur le site Web HDF5 :

Les liens externes permettent à un groupe d'inclure des objets dans un autre fichier HDF5 et permettent à la bibliothèque d'accéder à ces objets comme s'ils se trouvaient dans le fichier actuel. De cette manière, un groupe peut sembler contenir directement des ensembles de données, des types de données nommés et même des groupes qui se trouvent dans un fichier différent. Cette fonctionnalité est implémentée via une suite de fonctions qui crée et gère les liens, définit et récupère les chemins d'accès aux objets externes et interprète les noms de lien:

Voici comment faire dans h5py :

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

Faites attention: à l’ouverture de myfile, vous devez l’ouvrir avec 'a' s’il s’agit d’un fichier existant. Si vous l'ouvrez avec 'w', son contenu sera effacé.

Cela serait beaucoup plus rapide que de copier tous les jeux de données dans un nouveau fichier. Je ne sais pas à quelle vitesse l'accès à otherfile.hdf5 serait rapide, mais le fonctionnement de tous les jeux de données serait transparent - autrement dit, h5py verrait tous les jeux de données résidant dans foo.hdf5.

30
Yossarian

J'ai trouvé une solution non python en utilisant h5copy à partir des outils officiels hdf5. h5copy peut copier des ensembles de données spécifiés individuels d'un fichier hdf5 dans un autre fichier hdf5 existant.

Si quelqu'un trouve une solution à base de python/h5py, je serais heureux d'en entendre parler.

11
Bitwise

J'utilise habituellement ipython et h5copy tool togheter, c'est beaucoup plus rapide que les solutions python pures. Une fois installé h5copy.

Solution de console 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}

Solution de console automatisée

Pour automatiser complètement le processus en supposant que vous travailliez dans le dossier où les fichiers à fusionner sont stockés:

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}

Créer un nouveau groupe pour chaque fichier .h5 ajouté

Si vous souhaitez conserver le jeu de données précédent dans le fichier output.h5, vous devez d'abord créer le groupe à l'aide de l'indicateur -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 version 1.10 propose une nouvelle fonctionnalité utile dans ce contexte, appelée "jeux de données virtuels".
Vous trouverez ici un bref tutoriel et quelques explications: Jeux de données virtuels .
Voici des explications et une documentation plus complètes et détaillées sur cette fonctionnalité:
Jeux de données virtuels extra doc .
Et voici la demande d'extraction fusionnée dans h5py pour inclure l'API de jeux de données virtuels dans h5py:
h5py Jeux de données virtuels PR mais je ne sais pas s’il est déjà disponible dans la version actuelle de h5py ou le sera ultérieurement.

1
fedepad

Pour utiliser Python (et non IPython) et h5copy pour fusionner des fichiers HDF5, nous pouvons utiliser/ Réponse de 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