Skip to content

Commit

Permalink
Run.get_* methods should open the HDF5 file in read-only mode
Browse files Browse the repository at this point in the history
Fixes #42

Also addressed labscript-suite/labscript-utils#47 (removing h5py deprecation warnings) for this module

Also fixed an issue where calling `set_group` on a `Run` inside a `Sequence` could disable the read-only mode of the `Run` object.

Added `no_write` support to `Sequence`.
  • Loading branch information
philipstarkey committed Jun 24, 2020
1 parent 74dfc19 commit 2d8a80e
Showing 1 changed file with 46 additions and 32 deletions.
78 changes: 46 additions & 32 deletions lyse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,10 @@ def globals_diff(run1, run2, group=None):
class Run(object):
def __init__(self,h5_path,no_write=False):
self.no_write = no_write
self._no_group = None
self.h5_path = h5_path
if not self.no_write:
with h5py.File(h5_path) as h5_file:
if not 'results' in h5_file:
h5_file.create_group('results')
self._create_group_if_not_exists(h5_path, '/', 'results')

try:
if not self.no_write:
Expand All @@ -118,48 +117,65 @@ def __init__(self,h5_path,no_write=False):
frame = inspect.currentframe()
__file__ = frame.f_back.f_globals['__file__']
self.group = os.path.basename(__file__).split('.py')[0]
with h5py.File(h5_path) as h5_file:
if not self.group in h5_file['results']:
h5_file['results'].create_group(self.group)
self._create_group_if_not_exists(h5_path, 'results', self.group)
except KeyError:
# sys.stderr.write('Warning: to write results, call '
# 'Run.set_group(groupname), specifying the name of the group '
# 'you would like to save results to. This normally comes from '
# 'the filename of your script, but since you\'re in interactive '
# 'mode, there is no scipt name. Opening in read only mode for '
# 'the moment.\n')

# Backup the value of self.no_write for restoration once the group
# is set
self._no_group = (True, self.no_write)
self.no_write = True

def _create_group_if_not_exists(self, h5_path, location, groupname):
"""Creates a group in the HDF5 file at `location` if it does not exist.
Only opens the h5 file in write mode if a group must be created.
This ensures the last modified time of the file is only updated if
the file is actually written to."""
create_group = False
with h5py.File(h5_path, 'r') as h5_file:
if not groupname in h5_file[location]:
create_group = True
if create_group:
with h5py.File(h5_path, 'r+') as h5_file:
h5_file[location].create_group(groupname)

def set_group(self, groupname):
self.group = groupname
with h5py.File(self.h5_path) as h5_file:
if not self.group in h5_file['results']:
h5_file['results'].create_group(self.group)
self.no_write = False
self._create_group_if_not_exists(self.h5_path, '/', 'results')
# restore no_write attribute now we have set the group
if self._no_group is not None and self._no_group[0]:
self.no_write = self._no_group[1]
self._no_group = None

def trace_names(self):
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
try:
return list(h5_file['data']['traces'].keys())
except KeyError:
return []

def get_attrs(self, group):
"""Returns all attributes of the specified group as a dictionary."""
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
if not group in h5_file:
raise Exception('The group \'%s\' does not exist'%group)
return get_attributes(h5_file[group])

def get_trace(self,name):
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
if not name in h5_file['data']['traces']:
raise Exception('The trace \'%s\' doesn not exist'%name)
trace = h5_file['data']['traces'][name]
return array(trace['t'],dtype=float),array(trace['values'],dtype=float)

def get_result_array(self,group,name):
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
if not group in h5_file['results']:
raise Exception('The result group \'%s\' doesn not exist'%group)
if not name in h5_file['results'][group]:
Expand All @@ -169,7 +185,7 @@ def get_result_array(self,group,name):
def get_result(self, group, name):
"""Return 'result' in 'results/group' that was saved by
the save_result() method."""
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
if not group in h5_file['results']:
raise Exception('The result group \'%s\' does not exist'%group)
if not name in h5_file['results'][group].attrs.keys():
Expand Down Expand Up @@ -288,7 +304,7 @@ def save_result_arrays(self, *args, **kwargs):
self.save_result_array(name, value, **kwargs)

def get_image(self,orientation,label,image):
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
if not 'images' in h5_file:
raise Exception('File does not contain any images')
if not orientation in h5_file['images']:
Expand All @@ -307,13 +323,13 @@ def get_images(self,orientation,label, *images):

def get_all_image_labels(self):
images_list = {}
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
for orientation in h5_file['/images'].keys():
images_list[orientation] = list(h5_file['/images'][orientation].keys())
return images_list

def get_image_attributes(self, orientation):
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
if not 'images' in h5_file:
raise Exception('File does not contain any images')
if not orientation in h5_file['images']:
Expand All @@ -322,18 +338,18 @@ def get_image_attributes(self, orientation):

def get_globals(self,group=None):
if not group:
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
return dict(h5_file['globals'].attrs)
else:
try:
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
return dict(h5_file['globals'][group].attrs)
except KeyError:
return {}

def get_globals_raw(self, group=None):
globals_dict = {}
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
if group == None:
for obj in h5_file['globals'].values():
temp_dict = dict(obj.attrs)
Expand Down Expand Up @@ -374,7 +390,7 @@ def append_expansion(name, obj):
for key, val in temp_dict.items():
if val:
expansion_dict[key] = val
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
h5_file['globals'].visititems(append_expansion)
return expansion_dict

Expand All @@ -385,12 +401,12 @@ def append_units(name, obj):
temp_dict = dict(obj.attrs)
for key, val in temp_dict.items():
units_dict[key] = val
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
h5_file['globals'].visititems(append_units)
return units_dict

def globals_groups(self):
with h5py.File(self.h5_path) as h5_file:
with h5py.File(self.h5_path, 'r') as h5_file:
try:
return list(h5_file['globals'].keys())
except KeyError:
Expand All @@ -401,14 +417,13 @@ def globals_diff(self, other_run, group=None):


class Sequence(Run):
def __init__(self,h5_path,run_paths):
def __init__(self, h5_path, run_paths, no_write=False):
if isinstance(run_paths, pandas.DataFrame):
run_paths = run_paths['filepath']
self.h5_path = h5_path
self.no_write = False
with h5py.File(h5_path) as h5_file:
if not 'results' in h5_file:
h5_file.create_group('results')
self.no_write = no_write
if not self.no_write:
self._create_group_if_not_exists(h5_path, '/', 'results')

self.runs = {path: Run(path,no_write=True) for path in run_paths}

Expand All @@ -419,9 +434,8 @@ def __init__(self,h5_path,run_paths):
try:
__file__ = frame.f_back.f_locals['__file__']
self.group = os.path.basename(__file__).split('.py')[0]
with h5py.File(h5_path) as h5_file:
if not self.group in h5_file['results']:
h5_file['results'].create_group(self.group)
if not self.no_write:
self._create_group_if_not_exists(h5_path, 'results', self.group)
except KeyError:
sys.stderr.write('Warning: to write results, call '
'Sequence.set_group(groupname), specifying the name of the group '
Expand Down

0 comments on commit 2d8a80e

Please sign in to comment.