Skip to content

Commit 511975b

Browse files
authored
Merge pull request #107 from Json-To-String/master
adding logic to handle KeyError: "Unable to open object (object 'connection table' doesn't exist)" on initial run
2 parents 7a84e38 + 9858c9c commit 511975b

File tree

1 file changed

+74
-65
lines changed

1 file changed

+74
-65
lines changed

blacs/front_panel_settings.py

Lines changed: 74 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
from labscript_utils.connections import ConnectionTable
2626

27-
logger = logging.getLogger('BLACS.FrontPanelSettings')
27+
logger = logging.getLogger('BLACS.FrontPanelSettings')
2828

2929
def _ensure_str(s):
3030
"""convert bytestrings and numpy strings to python strings"""
@@ -36,7 +36,7 @@ def __init__(self,settings_path,connection_table):
3636
self.connection_table = connection_table
3737
with h5py.File(settings_path,'a') as h5file:
3838
pass
39-
39+
4040
def setup(self,blacs):
4141
self.tablist = blacs.tablist
4242
self.attached_devices = blacs.attached_devices
@@ -46,7 +46,7 @@ def setup(self,blacs):
4646
self.blacs = blacs
4747

4848
def restore(self):
49-
49+
5050
# Get list of DO/AO
5151
# Does the object have a name?
5252
# yes: Then, find the device in the BLACS connection table that matches that name
@@ -63,31 +63,40 @@ def restore(self):
6363
# no: Restore as is
6464
#
6565
# Display errors, give option to cancel starting of BLACS so that the connection table can be edited
66-
66+
6767
# Create saved connection table
6868
settings = {}
6969
question = {}
7070
error = {}
7171
tab_data = {'BLACS settings':{}}
72+
73+
# See if connection table exists in apparatus h5 file
74+
with h5py.File(self.settings_path, 'r') as h5file:
75+
if 'connection table' not in h5file:
76+
logger.info('Front panel settings connection table not found!')
77+
78+
# TODO: tab_data will be passed into restore_window next, populate this
79+
return settings, question, error, tab_data
80+
7281
try:
7382
saved_ct = ConnectionTable(self.settings_path, logging_prefix='BLACS', exceptions_in_thread=True)
7483
ct_match,error = self.connection_table.compare_to(saved_ct)
75-
84+
7685
with h5py.File(self.settings_path,'r') as hdf5_file:
7786
# Get Tab Data
7887
dataset = hdf5_file['/front_panel'].get('_notebook_data',[])
79-
88+
8089
for row in dataset:
8190
tab_name = _ensure_str(row['tab_name'])
8291
tab_data.setdefault(tab_name,{})
8392
try:
8493
tab_data[tab_name] = {'notebook':row['notebook'], 'page':row['page'], 'visible':row['visible'], 'data':eval(_ensure_str(row['data']))}
8594
except Exception:
8695
logger.info("Could not load tab data for %s"%tab_name)
87-
96+
8897
#now get dataset attributes
8998
tab_data['BLACS settings'] = dict(dataset.attrs)
90-
99+
91100
# Get the front panel values
92101
if 'front_panel' in hdf5_file["/front_panel"]:
93102
dataset = hdf5_file["/front_panel"].get('front_panel', [])
@@ -101,7 +110,7 @@ def restore(self):
101110
else:
102111
data_dict[columns[i]] = row[i]
103112
settings,question,error = self.handle_return_code(data_dict,result,settings,question,error)
104-
113+
105114
# Else Legacy restore from GTK save data!
106115
else:
107116
# open Datasets
@@ -119,7 +128,7 @@ def restore(self):
119128
logger.info("Could not load saved settings")
120129
logger.info(str(e))
121130
return settings,question,error,tab_data
122-
131+
123132
def handle_return_code(self,row,result,settings,question,error):
124133
# 1: Restore to existing device
125134
# 2: Send to new device
@@ -131,7 +140,7 @@ def handle_return_code(self,row,result,settings,question,error):
131140
if type(result) == tuple:
132141
connection = result[1]
133142
result = result[0]
134-
143+
135144
if result == 1:
136145
settings.setdefault(row['device_name'],{})
137146
settings[row['device_name']][row['channel']] = row
@@ -145,10 +154,10 @@ def handle_return_code(self,row,result,settings,question,error):
145154
error[row['device_name']+'_'+row['channel']] = row,"missing"
146155
elif result == -2:
147156
error[row['device_name']+'_'+row['channel']] = row,"changed"
148-
157+
149158
return settings,question,error
150-
151-
def check_row(self,row,ct_match,blacs_ct,saved_ct):
159+
160+
def check_row(self,row,ct_match,blacs_ct,saved_ct):
152161
# If it has a name
153162
if row[0] != "-":
154163
if ct_match:
@@ -158,21 +167,21 @@ def check_row(self,row,ct_match,blacs_ct,saved_ct):
158167
# Find if this device is in the connection table
159168
connection = blacs_ct.find_by_name(row[0])
160169
connection2 = saved_ct.find_by_name(row[0])
161-
170+
162171
if connection:
163172
# compare the two connections, see what differs
164173
# if compare fails only on parent, connected to:
165174
# send to new parent
166175
# else:
167176
# show error, device parameters not compatible with saved data
168177
result,error = connection.compare_to(connection2)
169-
178+
170179
allowed_length = 0
171180
if "parent_port" in error:
172181
allowed_length += 1
173-
182+
174183
if len(error) > allowed_length:
175-
return -2 # failure, device parameters not compatible
184+
return -2 # failure, device parameters not compatible
176185
elif error == {} and connection.parent.name == connection2.parent.name:
177186
return 1 # All details about this device match
178187
else:
@@ -190,46 +199,46 @@ def check_row(self,row,ct_match,blacs_ct,saved_ct):
190199
else:
191200
# restore to device
192201
return 1
193-
194-
@inmain_decorator(wait_for_return=True)
202+
203+
@inmain_decorator(wait_for_return=True)
195204
def get_save_data(self):
196205
tab_data = {}
197206
notebook_data = {}
198207
window_data = {}
199208
plugin_data = {}
200-
209+
201210
# iterate over all tabs
202211
for device_name,tab in self.tablist.items():
203212
tab_data[device_name] = {'front_panel':tab.settings['front_panel_settings'], 'save_data': tab.get_all_save_data()}
204-
213+
205214
# Find the notebook the tab is in
206-
#
207-
# By default we assume it is in notebook0, on page 0. This way, if a tab gets lost somewhere,
208-
# and isn't found to be a child of any notebook we know about,
215+
#
216+
# By default we assume it is in notebook0, on page 0. This way, if a tab gets lost somewhere,
217+
# and isn't found to be a child of any notebook we know about,
209218
# it will revert back to notebook 1 when the file is loaded upon program restart!
210-
current_notebook_name = 0
219+
current_notebook_name = 0
211220
page = 0
212221
visible = False
213-
222+
214223
for notebook_name,notebook in self.notebook.items():
215-
if notebook.indexOf(tab._ui) != -1:
216-
current_notebook_name = notebook_name
217-
page = notebook.indexOf(tab._ui)
218-
visible = True if notebook.currentIndex() == page else False
224+
if notebook.indexOf(tab._ui) != -1:
225+
current_notebook_name = notebook_name
226+
page = notebook.indexOf(tab._ui)
227+
visible = True if notebook.currentIndex() == page else False
219228
break
220-
229+
221230
notebook_data[device_name] = {"notebook":current_notebook_name,"page":page, "visible":visible}
222-
231+
223232
# iterate over all plugins
224233
for module_name, plugin in self.blacs.plugins.items():
225234
try:
226235
plugin_data[module_name] = plugin.get_save_data()
227236
except Exception as e:
228237
logger.error('Could not save data for plugin %s. Error was: %s'%(module_name,str(e)))
229-
238+
230239
# save window data
231-
# Size of window
232-
window_data["_main_window"] = {"width":self.window.normalGeometry().width(),
240+
# Size of window
241+
window_data["_main_window"] = {"width":self.window.normalGeometry().width(),
233242
"height":self.window.normalGeometry().height(),
234243
"xpos":self.window.normalGeometry().x(),
235244
"ypos":self.window.normalGeometry().y(),
@@ -242,24 +251,24 @@ def get_save_data(self):
242251
# Pane positions
243252
for name,pane in self.panes.items():
244253
window_data[name] = pane.sizes()
245-
254+
246255
return tab_data,notebook_data,window_data,plugin_data
247-
256+
248257
@inmain_decorator(wait_for_return=True)
249-
def save_front_panel_to_h5(self,current_file,states,tab_positions,window_data,plugin_data,silent = {}, force_new_conn_table = False):
258+
def save_front_panel_to_h5(self,current_file,states,tab_positions,window_data,plugin_data,silent = {}, force_new_conn_table = False):
250259
# Save the front panel!
251260

252-
# Does the file exist?
261+
# Does the file exist?
253262
# Yes: Check connection table inside matches current connection table. Does it match?
254263
# Yes: Does the file have a front panel already saved in it?
255264
# Yes: Can we overwrite?
256265
# Yes: Delete front_panel group, save new front panel
257266
# No: Create error dialog!
258267
# No: Save front panel in here
259-
#
268+
#
260269
# No: Return
261270
# No: Create new file, place inside the connection table and front panel
262-
271+
263272
if os.path.isfile(current_file):
264273
save_conn_table = True if force_new_conn_table else False
265274
result = False
@@ -270,10 +279,10 @@ def save_front_panel_to_h5(self,current_file,states,tab_positions,window_data,pl
270279
except Exception:
271280
# no connection table is present, so also save the connection table!
272281
save_conn_table = True
273-
282+
274283
# if save_conn_table is True, we don't bother checking to see if the connection tables match, because save_conn_table is only true when the connection table doesn't exist in the current file
275284
# As a result, if save_conn_table is True, we ignore connection table checking, and save the connection table in the h5file.
276-
285+
277286
if save_conn_table or result:
278287
with h5py.File(current_file,'r+') as hdf5_file:
279288
if hdf5_file['/'].get('front_panel') != None:
@@ -288,18 +297,18 @@ def save_front_panel_to_h5(self,current_file,states,tab_positions,window_data,pl
288297
message.setIcon(QMessageBox.Question)
289298
message.setWindowTitle("BLACS")
290299
resp = message.exec_()
291-
300+
292301
if resp == QMessageBox.Yes :
293-
overwrite = True
302+
overwrite = True
294303
else:
295304
overwrite = silent["overwrite"]
296-
305+
297306
if overwrite:
298307
# Delete Front panel group, save new front panel
299308
del hdf5_file['/front_panel']
300309
self.store_front_panel_in_h5(hdf5_file,states,tab_positions,window_data,plugin_data,save_conn_table)
301310
else:
302-
if not silent:
311+
if not silent:
303312
message = QMessageBox()
304313
message.setText("Front Panel not saved.")
305314
message.setIcon(QMessageBox.Information)
@@ -308,7 +317,7 @@ def save_front_panel_to_h5(self,current_file,states,tab_positions,window_data,pl
308317
else:
309318
logger.info("Front Panel not saved as it already existed in the h5 file '"+current_file+"'")
310319
return
311-
else:
320+
else:
312321
# Save Front Panel in here
313322
self.store_front_panel_in_h5(hdf5_file,states,tab_positions,window_data,plugin_data,save_conn_table)
314323
else:
@@ -318,32 +327,32 @@ def save_front_panel_to_h5(self,current_file,states,tab_positions,window_data,pl
318327
message.setText("The Front Panel was not saved as the file selected contains a connection table which is not a subset of the BLACS connection table.")
319328
message.setIcon(QMessageBox.Information)
320329
message.setWindowTitle("BLACS")
321-
message.exec_()
330+
message.exec_()
322331
else:
323332
logger.info("Front Panel not saved as the connection table in the h5 file '"+current_file+"' didn't match the current connection table.")
324333
return
325334
else:
326335
with h5py.File(current_file,'w') as hdf5_file:
327-
# save connection table, save front panel
336+
# save connection table, save front panel
328337
self.store_front_panel_in_h5(hdf5_file,states,tab_positions,window_data,plugin_data,save_conn_table=True)
329-
338+
330339
@inmain_decorator(wait_for_return=True)
331340
def store_front_panel_in_h5(self, hdf5_file,tab_data,notebook_data,window_data,plugin_data,save_conn_table=False,save_queue_data=True):
332341
if save_conn_table:
333342
if 'connection table' in hdf5_file:
334343
del hdf5_file['connection table']
335344
hdf5_file.create_dataset('connection table', data=self.connection_table.raw_table)
336-
345+
337346
data_group = hdf5_file['/'].create_group('front_panel')
338-
347+
339348
front_panel_list = []
340-
other_data_list = []
349+
other_data_list = []
341350
front_panel_dtype = [('name','a256'),('device_name','a256'),('channel','a256'),('base_value',float),('locked',bool),('base_step_size',float),('current_units','a256')]
342351
max_od_length = 2 # empty dictionary
343-
352+
344353
# Iterate over each device within a class
345354
for device_name, device_state in tab_data.items():
346-
logger.debug("saving front panel for device:" + device_name)
355+
logger.debug("saving front panel for device:" + device_name)
347356
# Insert front panel data into dataset
348357
for hardware_name, data in device_state["front_panel"].items():
349358
if data != {}:
@@ -359,29 +368,29 @@ def store_front_panel_in_h5(self, hdf5_file,tab_data,notebook_data,window_data,p
359368
data['base_step_size'] if 'base_step_size' in data else 0,
360369
data['current_units'] if 'current_units' in data else ''
361370
)
362-
)
371+
)
363372
else:
364373
logger.warning('Could not save data for channel %s on device %s because the output value (in base units) was not a string or could not be coerced to a float without loss of precision'%(hardware_name, device_name))
365-
374+
366375
# Save "other data"
367376
od = repr(device_state["save_data"])
368-
other_data_list.append(od)
369-
max_od_length = len(od) if len(od) > max_od_length else max_od_length
370-
377+
other_data_list.append(od)
378+
max_od_length = len(od) if len(od) > max_od_length else max_od_length
379+
371380
# Create datasets
372381
if front_panel_list:
373382
front_panel_array = numpy.empty(len(front_panel_list),dtype=front_panel_dtype)
374383
for i, row in enumerate(front_panel_list):
375384
front_panel_array[i] = row
376385
data_group.create_dataset('front_panel',data=front_panel_array)
377-
386+
378387
# Save tab data
379388
i = 0
380389
tab_data = numpy.empty(len(notebook_data),dtype=[('tab_name','a256'),('notebook','a2'),('page',int),('visible',bool),('data','a'+str(max_od_length))])
381390
for device_name,data in notebook_data.items():
382391
tab_data[i] = (device_name,data["notebook"],data["page"],data["visible"],other_data_list[i])
383392
i += 1
384-
393+
385394
# Save BLACS Main GUI Info
386395
dataset = data_group.create_dataset("_notebook_data",data=tab_data)
387396
dataset.attrs["window_width"] = window_data["_main_window"]["width"]
@@ -398,7 +407,7 @@ def store_front_panel_in_h5(self, hdf5_file,tab_data,notebook_data,window_data,p
398407
for pane_name,pane_position in window_data.items():
399408
if pane_name != "_main_window":
400409
dataset.attrs[pane_name] = pane_position
401-
410+
402411
# Save analysis server settings:
403412
#dataset = data_group.create_group("analysis_server")
404413
#dataset.attrs['send_for_analysis'] = self.blacs.analysis_submission.toggle_analysis.get_active()

0 commit comments

Comments
 (0)