Skip to content

Commit 11f5aa7

Browse files
authored
Merge pull request #74 from ovillellas/v0.6.x
FIX: keep hdf5 file open for the whole life of imageseries.
2 parents 4224e33 + b315297 commit 11f5aa7

File tree

1 file changed

+36
-40
lines changed

1 file changed

+36
-40
lines changed

hexrd/imageseries/load/hdf5.py

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""HDF5 adapter class
22
"""
33
import h5py
4+
import warnings
45

56
from . import ImageSeriesAdapter
67
from ..imageseriesiter import ImageSeriesIterator
@@ -21,73 +22,68 @@ def __init__(self, fname, **kwargs):
2122
self.__path = kwargs['path']
2223
self.__dataname = kwargs.pop('dataname', 'images')
2324
self.__images = '/'.join([self.__path, self.__dataname])
25+
self.__h5file = h5py.File(self.__h5name, 'r')
26+
self.__image_dataset = self.__h5file[self.__images]
27+
self.__data_group = self.__h5file[self.__path]
2428
self._meta = self._getmeta()
2529

30+
31+
def close(self):
32+
self.__image_dataset = None
33+
self.__data_group = None
34+
self.__h5file.close()
35+
self.__h5file = None
36+
37+
38+
def __del__(self):
39+
# Note this is not ideal, as the use of __del__ is problematic. However,
40+
# it is highly unlikely that the usage of a ImageSeries would pose
41+
# a problem.
42+
#
43+
# A warning will (hopefully) be emitted if an issue arises at some point.
44+
try:
45+
self.close()
46+
except:
47+
warnings.warn("HDF5ImageSeries could not close h5file")
48+
pass
49+
50+
2651
def __getitem__(self, key):
27-
with self._dset as dset:
28-
return dset.__getitem__(key)
52+
return self.__image_dataset[key]
53+
2954

3055
def __iter__(self):
3156
return ImageSeriesIterator(self)
3257

33-
#@memoize
34-
def __len__(self):
35-
with self._dset as dset:
36-
return len(dset)
3758

38-
@property
39-
def _dgroup(self):
40-
# return a context manager to ensure proper file handling
41-
# always use like: "with self._dgroup as dgroup:"
42-
return H5ContextManager(self.__h5name, self.__path)
59+
def __len__(self):
60+
return len(self.__image_dataset)
4361

44-
@property
45-
def _dset(self):
46-
# return a context manager to ensure proper file handling
47-
# always use like: "with self._dset as dset:"
48-
return H5ContextManager(self.__h5name, self.__images)
4962

5063
def _getmeta(self):
5164
mdict = {}
52-
with self._dgroup as dgroup:
53-
for k, v in dgroup.attrs.items():
54-
mdict[k] = v
65+
for k, v in self.__data_group.attrs.items():
66+
mdict[k] = v
5567

5668
return mdict
5769

70+
5871
@property
59-
#@memoize
6072
def metadata(self):
6173
"""(read-only) Image sequence metadata
6274
6375
note: metadata loaded on open and allowed to be modified
6476
"""
6577
return self._meta
6678

79+
6780
@property
6881
def dtype(self):
69-
with self._dset as dset:
70-
return dset.dtype
82+
return self.__image_dataset.dtype
83+
7184

7285
@property
73-
#@memoize so you only need to do this once
7486
def shape(self):
75-
with self._dset as dset:
76-
return dset.shape[1:]
87+
return self.__image_dataset.shape[1:]
7788

7889
pass # end class
79-
80-
81-
class H5ContextManager:
82-
83-
def __init__(self, fname, path):
84-
self._fname = fname
85-
self._path = path
86-
self._f = None
87-
88-
def __enter__(self):
89-
self._f = h5py.File(self._fname, 'r')
90-
return self._f[self._path]
91-
92-
def __exit__(self, *args):
93-
self._f.close()

0 commit comments

Comments
 (0)