Skip to content

Commit 9959cfe

Browse files
Merged in fixed-shot-interval (pull request labscript-suite#50)
Fixed shot interval
2 parents b47ae0d + 45d670d commit 9959cfe

File tree

4 files changed

+174
-8
lines changed

4 files changed

+174
-8
lines changed

experiment_queue.py

+24-6
Original file line numberDiff line numberDiff line change
@@ -442,18 +442,27 @@ def new_rep_name(self, h5_filepath):
442442

443443
def clean_h5_file(self, h5file, new_h5_file, repeat_number=0):
444444
try:
445-
with h5py.File(h5file,'r') as old_file:
446-
with h5py.File(new_h5_file,'w') as new_file:
447-
groups_to_copy = ['devices', 'calibrations', 'script', 'globals', 'connection table',
448-
'labscriptlib', 'waits', 'time_markers']
445+
with h5py.File(h5file, 'r') as old_file:
446+
with h5py.File(new_h5_file, 'w') as new_file:
447+
groups_to_copy = [
448+
'devices',
449+
'calibrations',
450+
'script',
451+
'globals',
452+
'connection table',
453+
'labscriptlib',
454+
'waits',
455+
'time_markers',
456+
'shot_properties',
457+
]
449458
for group in groups_to_copy:
450459
if group in old_file:
451460
new_file.copy(old_file[group], group)
452461
for name in old_file.attrs:
453462
new_file.attrs[name] = old_file.attrs[name]
454463
new_file.attrs['run repeat'] = repeat_number
455464
except Exception as e:
456-
#raise
465+
# raise
457466
self._logger.exception('Clean H5 File Error.')
458467
return False
459468

@@ -542,7 +551,6 @@ def manage(self):
542551

543552
devices_in_use = {}
544553
transition_list = {}
545-
start_time = time.time()
546554
self.current_queue = queue.Queue()
547555

548556
# Function to be run when abort button is clicked
@@ -577,6 +585,16 @@ def restart_function(device_name):
577585
inmain(self._ui.queue_abort_button.clicked.connect,abort_function)
578586
inmain(self._ui.queue_abort_button.setEnabled,True)
579587

588+
##########################################################################################################################################
589+
# Plugin callbacks #
590+
##########################################################################################################################################
591+
for callback in plugins.get_callbacks('pre_transition_to_buffered'):
592+
try:
593+
callback(path)
594+
except Exception:
595+
logger.exception("Plugin callback raised an exception")
596+
597+
start_time = time.time()
580598

581599
with h5py.File(path, 'r') as hdf5_file:
582600
devices_in_use = {}

plugins/cycle_time/__init__.py

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#####################################################################
2+
# #
3+
# /plugins/cycle_time/__init__.py #
4+
# #
5+
# Copyright 2017, Monash Univiersity and contributors #
6+
# #
7+
# This file is part of the program BLACS, in the labscript suite #
8+
# (see http://labscriptsuite.org), and is licensed under the #
9+
# Simplified BSD License. See the license.txt file in the root of #
10+
# the project for the full license. #
11+
# #
12+
#####################################################################
13+
from __future__ import division, unicode_literals, print_function, absolute_import
14+
from labscript_utils import PY2
15+
if PY2:
16+
from Queue import Queue, Empty
17+
from time import time as monotonic
18+
else:
19+
from queue import Queue, Empty
20+
from time import monotonic
21+
import time
22+
import logging
23+
import os
24+
25+
from qtutils import UiLoader, inmain, inmain_decorator
26+
27+
import labscript_utils.h5_lock
28+
import h5py
29+
30+
from qtutils.qt.QtGui import QIcon
31+
from qtutils.qt.QtCore import QSize
32+
33+
from blacs.plugins import PLUGINS_DIR, callback
34+
from labscript_utils.properties import get_attribute
35+
36+
name = "cycle_time"
37+
module = "cycle_time" # should be folder name
38+
logger = logging.getLogger('BLACS.plugin.%s'%module)
39+
40+
41+
class Plugin(object):
42+
def __init__(self, initial_settings):
43+
self.menu = None
44+
self.notifications = {}
45+
self.initial_settings = initial_settings
46+
self.BLACS = None
47+
self.time_of_last_shot = None
48+
self.queue = Queue()
49+
self.target_cycle_time = None
50+
self.delay_after_programming = None
51+
self.next_target_cycle_time = None
52+
self.next_delay_after_programming = None
53+
54+
def plugin_setup_complete(self, BLACS):
55+
self.BLACS = BLACS
56+
self.queue_manager = self.BLACS['experiment_queue']
57+
58+
def get_save_data(self):
59+
return {}
60+
61+
def get_callbacks(self):
62+
return {
63+
'pre_transition_to_buffered': self.pre_transition_to_buffered,
64+
'science_starting': self.science_starting,
65+
}
66+
67+
def _abort(self):
68+
self.queue.put('abort')
69+
70+
@callback(priority=100) # this callback should run after all other callbacks.
71+
def pre_transition_to_buffered(self, h5_filepath):
72+
# Delay according to the settings of the previously run shot, and save the
73+
# settings for the upcoming shot:
74+
self.target_cycle_time = self.next_target_cycle_time
75+
self.delay_after_programming = self.next_delay_after_programming
76+
77+
with h5py.File(h5_filepath) as f:
78+
try:
79+
group = f['shot_properties']
80+
except KeyError:
81+
# Nothing for us to do
82+
return
83+
self.next_target_cycle_time = get_attribute(group, 'target_cycle_time')
84+
self.next_delay_after_programming = get_attribute(
85+
group, 'cycle_time_delay_after_programming'
86+
)
87+
88+
if not self.delay_after_programming:
89+
self.do_delay(h5_filepath)
90+
91+
# this callback should run before the progress bar plugin, but after all other
92+
# callbacks. The priority should be set accordingly.
93+
@callback(priority=100)
94+
def science_starting(self, h5_filepath):
95+
if self.delay_after_programming:
96+
self.do_delay(h5_filepath)
97+
98+
def do_delay(self, h5_filepath):
99+
if self.target_cycle_time is not None and self.time_of_last_shot is not None:
100+
# Wait until it has been self.target_cycle_time since the start of the last
101+
# shot. Otherwise, return immediately.
102+
deadline = self.time_of_last_shot + self.target_cycle_time
103+
inmain(self.BLACS['ui'].queue_abort_button.clicked.connect, self._abort)
104+
# Store the current queue manager status, to restore it after we are done:
105+
previous_status = self.queue_manager.get_status()
106+
while True:
107+
remaining = deadline - monotonic()
108+
if remaining <= 0:
109+
break
110+
self.queue_manager.set_status(
111+
'Waiting {:.1f}s for target cycle time'.format(remaining),
112+
h5_filepath,
113+
)
114+
try:
115+
self.queue.get(timeout=remaining % 0.1)
116+
break # Got an abort
117+
except Empty:
118+
continue
119+
# Disconnect from the abort button:
120+
inmain(self.BLACS['ui'].queue_abort_button.clicked.disconnect, self._abort)
121+
# Restore previous_status:
122+
self.queue_manager.set_status(previous_status, h5_filepath)
123+
124+
self.time_of_last_shot = monotonic()
125+
126+
# The rest of these are boilerplate:
127+
def close(self):
128+
pass
129+
130+
def get_menu_class(self):
131+
return None
132+
133+
def get_notification_classes(self):
134+
return []
135+
136+
def get_setting_classes(self):
137+
return []
138+
139+
def set_menu_instance(self, menu):
140+
self.menu = menu
141+
142+
def set_notification_instances(self, notifications):
143+
self.notifications = notifications
144+
145+

plugins/delete_repeated_shots/controls.ui

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Repeated shots older than this will be deleted from disk.</string>
6464
<item>
6565
<widget class="QLabel" name="label">
6666
<property name="text">
67-
<string>Retain</string>
67+
<string>Retain </string>
6868
</property>
6969
</widget>
7070
</item>

plugins/progress_bar/__init__.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,10 @@ def get_callbacks(self):
132132
return {'science_over': self.on_science_over,
133133
'science_starting': self.on_science_starting}
134134

135-
@callback(priority=100)
135+
# This callback should be run after any callbacks that might have significant time
136+
# delays. For example it should run after the cycle_time science_starting callback.
137+
# The priority should be set accordingly.
138+
@callback(priority=200)
136139
def on_science_starting(self, h5_filepath):
137140
# Tell the mainloop that we're starting a shot:
138141
self.command_queue.put(('start', h5_filepath))

0 commit comments

Comments
 (0)