Combinaison de fichiers hdf5

J'ai un certain nombre de fichiers hdf5, chacun ayant un seul ensemble de données. Les jeux de données sont trop volumineux pour être conservés en RAM. Je voudrais combiner ces fichiers en un seul fichier contenant tous les ensembles de données séparément (c'est-à-dire pas pour concaténer les ensembles de données en un seul ensemble de données).

Une façon de le faire est de créer un fichier hdf5, puis de copier les jeux de données un par un. Ce sera lent et compliqué car il devra être copié en mémoire tampon.

Est-il un moyen plus simple de le faire cette? On dirait qu'il devrait y en avoir, car il s'agit essentiellement de créer un fichier conteneur.

J'utilise python / h5py.

21
demandé sur Bitwise 2013-08-28 19:32:59

5 réponses

Une solution consiste à utiliser l'interface h5py pour le bas niveau H5Ocopy fonction de L'API HDF5, en particulier le h5py.h5o.copy fonction :

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'

Ce qui précède a été généré avec h5py version 2.0.1-2+b1 et la version iPython 0.13.1-2+deb7u1 au sommet de la version Python 2.7.3-4+deb7u1 à partir d'une installation plus ou moins vanille de Debian Wheezy. Les fichiers f1.h5 et f2.h5 n'existaient pas avant l'exécution de ce qui précède. Notez que, par salotz, pour Python 3 du dataset/noms de groupe besoin d'être bytes (par exemple, b"val"), pas str.

La commande hf1.flush() in {[14] } est cruciale, car l'interface de bas niveau sera apparemment toujours tirée de la version du fichier .h5 stocké sur le disque, pas de la mémoire cache. La copie d'ensembles de données vers / depuis des groupes qui ne sont pas à la racine d'un File peut être réalisée en fournissant l'ID de ce groupe en utilisant, par exemple, hf1.get("g1").id.

Remarque que h5py.h5o.copy échouera avec une exception (pas de tabasser) si un objet du nom indiqué existe déjà dans l'emplacement de destination.

10
répondu hBy2Py 2018-06-18 21:22:46

C'est en fait l'un des cas d'utilisation de HDF5. Si vous voulez juste être en mesure d'accéder à tous les ensembles de données à partir d'un seul fichier, et ne se soucient pas de la façon dont ils sont réellement stockés sur le disque, vous pouvez utiliser Liens externes. Du 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, nommés types de données, et même les groupes qui sont réellement dans un fichier différent. Cette fonctionnalité est implémentée via une suite de fonctions qui créent et gèrent les liens, définissent et récupèrent des chemins vers des objets externes et interprètent les noms de liens:

Voici comment le faire en h5py:

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

Attention: lors de l'ouverture de myfile, vous devez l'ouvrir avec 'a' si c'est un fichier existant. Si vous l'ouvrez avec 'w', il effacera son contenu.

Ce 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, mais fonctionner sur tous les ensembles de données serait transparent - c'est-à-dire que h5py verrait tous les ensembles de données comme résidant dans foo.hdf5.

28
répondu Yossarian 2018-09-30 06:22:22

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

Si quelqu'un trouve une solution basée sur python/h5py, je serais heureux d'en entendre parler.

10
répondu Bitwise 2013-08-28 16:57:50

J'ai l'habitude d'utiliser ipython et h5copy outil de ensemble, c'est beaucoup plus rapide par rapport à un pur python solution. 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 travaillez 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 voulez garder l'ensemble de données précédent séparé à l'intérieur sortie.h5, vous devez d'abord créer le groupe en utilisant le drapeau -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}
1
répondu G M 2016-10-25 07:56:23

Pour mettre à jour à ce sujet, avec la version HDF5 1.10 vient une nouvelle fonctionnalité qui pourrait être utile dans ce contexte appelé "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 pour la fonctionnalité:
jeux de données virtuels extra doc .
Et voici la requête d'extraction fusionnée dans h5py pour inclure l'API virtual datasets dans h5py:
h5py jeux de données virtuels PR mais je ne sais pas si elle est déjà disponible dans la version h5py actuelle ou viendra plus tard.

1
répondu fedepad 2016-12-14 15:19:15