Skip to content

Commit 080e054

Browse files
philipstarkeychrisjbillingtonrpanderson
committed
Squashed commit of the following:
commit c9de425 Author: Phil Starkey <[email protected]> Date: Thu Jun 25 19:12:29 2020 +1000 Update dependencies in setup.cfg Bumped blacs, labscript and labscript_utils versions to `>=3.0.0` commit d43ced1 Merge: 3863607 1988032 Author: Chris Billington <[email protected]> Date: Wed Jun 24 22:48:26 2020 -0400 Merge pull request #58 from philipstarkey/fix-h5py-file-mode Fix h5py deprecation warnings commit 1988032 Author: philipstarkey <[email protected]> Date: Thu Jun 25 10:48:10 2020 +1000 Fix h5py deprecation warnings Addresses labscript-suite/labscript-utils#47 for this module commit 3863607 Merge: 88eeefe cdd34f8 Author: Phil Starkey <[email protected]> Date: Wed Jun 24 10:51:04 2020 +1000 Merge pull request #54 from rpanderson/dummy_pseudoclock_updates Save clock instructions and add runviewer parser for DummyPseudoclock commit 88eeefe Merge: 55b1bd8 84eb889 Author: Phil Starkey <[email protected]> Date: Wed Jun 24 10:50:09 2020 +1000 Merge pull request #42 from JQIamo/SpinnakerCamera Added SpinnakerCamera commit cdd34f8 Author: philipstarkey <[email protected]> Date: Tue Jun 23 18:34:28 2020 +1000 Implemented review changes commit d2e5679 Author: Russell Anderson <[email protected]> Date: Fri Jun 12 18:47:25 2020 +1000 Save clock instructions (mock PineBlaster) and add runviewer_parser commit 84eb889 Author: philipstarkey <[email protected]> Date: Tue Jun 23 12:49:00 2020 +1000 Implemented review changes commit 55b1bd8 Merge: bb9f6f5 d5fca30 Author: Russell Anderson <[email protected]> Date: Mon Jun 22 18:07:08 2020 +1000 Merge pull request #57 from philipstarkey/master fix docs conf bugs identified in labscript-suite/labscript-utils#57 commit d5fca30 Author: philipstarkey <[email protected]> Date: Sat Jun 20 18:33:55 2020 +1000 fix docs conf bugs identified in labscript-suite/labscript-utils#57 commit bb9f6f5 Merge: 0f1cacd 091110b Author: Russell Anderson <[email protected]> Date: Fri Jun 19 17:57:15 2020 +1000 Merge pull request #56 from philipstarkey/master Empty sphinx project following our template commit 091110b Author: philipstarkey <[email protected]> Date: Fri Jun 19 17:42:46 2020 +1000 Empty sphinx project following our template commit 0f1cacd Author: Russell Anderson <[email protected]> Date: Wed Jun 17 16:39:08 2020 +1000 Added missing devices to README.md commit 5347098 Author: Russell Anderson <[email protected]> Date: Wed Jun 17 11:38:03 2020 +1000 Populated README.md with styling, iconogrpahy, prose, and badges commit bd2505e Author: DSB <[email protected]> Date: Mon May 4 14:27:03 2020 -0400 SpinnakerCamera Adding a camera interface that uses FLIR's newer PySpin/Spinnaker API. DSB Co-authored-by: chrisjbillington <[email protected]> Co-authored-by: Russell Anderson <[email protected]>
1 parent f789345 commit 080e054

19 files changed

+510
-30
lines changed

docs/source/conf.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,10 @@
133133

134134
# whether to use stable or latest version
135135
labscript_suite_doc_version = os.environ.get('READTHEDOCS_VERSION', 'latest')
136-
if labscript_suite_doc_version not in ['stable', 'latest']:
136+
if '.' in labscript_suite_doc_version:
137137
labscript_suite_doc_version = 'stable'
138+
elif labscript_suite_doc_version not in ['stable', 'latest']:
139+
labscript_suite_doc_version = 'latest'
138140

139141
# add intersphinx references for each component
140142
for ls_prog in labscript_suite_programs:
@@ -205,7 +207,7 @@ def setup(app):
205207
app.add_config_value('m2r_anonymous_references', False, 'env')
206208
app.add_config_value('m2r_disable_inline_math', False, 'env')
207209
app.add_directive('mdinclude', MdInclude)
208-
app.add_stylesheet('custom.css')
210+
app.add_css_file('custom.css')
209211

210212
# generate the components.rst file dynamically so it points to stable/latest
211213
# of subprojects correctly

labscript_devices/AlazarTechBoard.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ def init(self):
316316
def transition_to_buffered(self, device_name, h5file, initial_values, fresh):
317317
self.h5file = h5file # We'll need this in transition_to_manual
318318
self.device_name = device_name
319-
with h5py.File(h5file) as hdf5_file:
319+
with h5py.File(h5file, 'r') as hdf5_file:
320320
print("\nUsing "+h5file)
321321
self.atsparam = atsparam = labscript_utils.properties.get(
322322
hdf5_file, device_name, 'device_properties')
@@ -379,7 +379,7 @@ def transition_to_buffered(self, device_name, h5file, initial_values, fresh):
379379

380380
# Store the actual acquisition rate back as an attribute.
381381
# Again, this should be done as an ACQUISITIONS table entry, but not today
382-
with h5py.File(h5file) as hdf5_file:
382+
with h5py.File(h5file, 'r+') as hdf5_file:
383383
hdf5_file['devices'][device_name].attrs.create(
384384
'acquisition_rate', actual_acquisition_rate, dtype='int32')
385385

@@ -585,7 +585,7 @@ def transition_to_manual(self):
585585
# Waits on the acquisition thread, and manages the lock
586586
self.wait_acquisition_complete()
587587
# Write data to HDF5 file
588-
with h5py.File(self.h5file) as hdf5_file:
588+
with h5py.File(self.h5file, 'r+') as hdf5_file:
589589
grp = hdf5_file.create_group('/data/traces/'+self.device_name)
590590
if self.channels & ats.CHANNEL_A:
591591
dsetA = grp.create_dataset(

labscript_devices/DummyPseudoclock/labscript_devices.py

Lines changed: 94 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,109 @@
1515
# and labscript. The device is a PseudoclockDevice, and can be the sole device
1616
# in a connection table or experiment.
1717

18-
import labscript_utils.h5_lock
19-
import h5py
20-
from labscript import PseudoclockDevice, Pseudoclock, ClockLine
18+
from labscript import PseudoclockDevice, Pseudoclock, ClockLine, config, LabscriptError
19+
import numpy as np
20+
21+
class _DummyPseudoclock(Pseudoclock):
22+
def add_device(self, device):
23+
if isinstance(device, ClockLine):
24+
# only allow one child
25+
if self.child_devices:
26+
raise LabscriptError('The pseudoclock of the DummyPseudoclock %s only supports 1 clockline, which is automatically created. Please use the clockline located at %s.clockline'%(self.parent_device.name, self.parent_device.name))
27+
Pseudoclock.add_device(self, device)
28+
else:
29+
raise LabscriptError('You have connected %s to %s (the Pseudoclock of %s), but %s only supports children that are ClockLines. Please connect your device to %s.clockline instead.'%(device.name, self.name, self.parent_device.name, self.name, self.parent_device.name))
2130

2231

2332
class DummyPseudoclock(PseudoclockDevice):
2433

2534
description = 'Dummy pseudoclock'
26-
clock_limit = 1e6
27-
clock_resolution = 1e-6
35+
clock_limit = 10e6
36+
clock_resolution = 25e-9
37+
trigger_delay = 350e-9
38+
wait_delay = 2.5e-6
39+
allowed_children = [_DummyPseudoclock]
40+
max_instructions = 1e5
2841

29-
def __init__(self, name='dummy_pseudoclock', BLACS_connection='dummy_connection', **kwargs):
42+
def __init__(
43+
self, name='dummy_pseudoclock', BLACS_connection='dummy_connection', **kwargs
44+
):
3045
self.BLACS_connection = BLACS_connection
3146
PseudoclockDevice.__init__(self, name, None, None, **kwargs)
32-
self.pseudoclock = Pseudoclock(self.name + '_pseudoclock', self, 'pseudoclock')
33-
self.clockline = ClockLine(name='clockline', pseudoclock=self.pseudoclock, connection='dummy')
47+
self._pseudoclock = _DummyPseudoclock(
48+
name=f'{name}_pseudoclock',
49+
pseudoclock_device=self,
50+
connection='pseudoclock',
51+
)
52+
self._clock_line = ClockLine(
53+
name=f'{name}_clock_line',
54+
pseudoclock=self.pseudoclock,
55+
connection='internal',
56+
)
57+
58+
@property
59+
def pseudoclock(self):
60+
return self._pseudoclock
61+
62+
@property
63+
def clockline(self):
64+
return self._clock_line
65+
66+
def add_device(self, device):
67+
if not self.child_devices and isinstance(device, Pseudoclock):
68+
PseudoclockDevice.add_device(self, device)
69+
elif isinstance(device, Pseudoclock):
70+
raise LabscriptError('The %s %s automatically creates a Pseudoclock because it only supports one. '%(self.description, self.name) +
71+
'Instead of instantiating your own Pseudoclock object, please use the internal' +
72+
' one stored in %s.pseudoclock'%self.name)
73+
else:
74+
raise LabscriptError('You have connected %s (class %s) to %s, but %s does not support children with that class.'%(device.name, device.__class__, self.name, self.name))
3475

3576
def generate_code(self, hdf5_file):
3677
PseudoclockDevice.generate_code(self, hdf5_file)
3778
group = self.init_device_group(hdf5_file)
38-
self.set_property('stop_time', self.stop_time, location='device_properties')
79+
80+
# Compress clock instructions with the same period
81+
# This will halve the number of instructions roughly,
82+
# since the DummyPseudoclock does not have a 'slow clock'
83+
reduced_instructions = []
84+
for instruction in self.pseudoclock.clock:
85+
if instruction == 'WAIT':
86+
# The following period and reps indicates a wait instruction
87+
reduced_instructions.append({'period': 0, 'reps': 1})
88+
continue
89+
reps = instruction['reps']
90+
# period is in quantised units:
91+
period = int(round(instruction['step'] / self.clock_resolution))
92+
if reduced_instructions and reduced_instructions[-1]['period'] == period:
93+
reduced_instructions[-1]['reps'] += reps
94+
else:
95+
reduced_instructions.append({'period': period, 'reps': reps})
96+
# The following period and reps indicates a stop instruction:
97+
reduced_instructions.append({'period': 0, 'reps': 0})
98+
if len(reduced_instructions) > self.max_instructions:
99+
raise LabscriptError(
100+
"%s %s has too many instructions. It has %d and can only support %d"
101+
% (
102+
self.description,
103+
self.name,
104+
len(reduced_instructions),
105+
self.max_instructions,
106+
)
107+
)
108+
# Store these instructions to the h5 file:
109+
dtypes = [('period', int), ('reps', int)]
110+
pulse_program = np.zeros(len(reduced_instructions), dtype=dtypes)
111+
for i, instruction in enumerate(reduced_instructions):
112+
pulse_program[i]['period'] = instruction['period']
113+
pulse_program[i]['reps'] = instruction['reps']
114+
group.create_dataset(
115+
'PULSE_PROGRAM', compression=config.compression, data=pulse_program
116+
)
117+
# TODO: is this needed, the PulseBlasters don't save it...
118+
self.set_property(
119+
'is_master_pseudoclock',
120+
self.is_master_pseudoclock,
121+
location='device_properties',
122+
)
123+
self.set_property('stop_time', self.stop_time, location='device_properties')

labscript_devices/DummyPseudoclock/register_classes.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,12 @@
1212
#####################################################################
1313
import labscript_devices
1414

15+
labscript_device_name = 'DummyPseudoclock'
16+
blacs_tab = 'labscript_devices.DummyPseudoclock.blacs_tabs.DummyPseudoclockTab'
17+
parser = 'labscript_devices.DummyPseudoclock.runviewer_parsers.DummyPseudoclockParser'
18+
1519
labscript_devices.register_classes(
16-
'DummyPseudoclock',
17-
BLACS_tab='labscript_devices.DummyPseudoclock.blacs_tabs.DummyPseudoclockTab',
18-
runviewer_parser=None, #TODO make a runviwer parser for Dummy pseudoclock!
20+
labscript_device_name=labscript_device_name,
21+
BLACS_tab=blacs_tab,
22+
runviewer_parser=parser,
1923
)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import labscript_utils.h5_lock # noqa: F401
2+
import h5py
3+
import numpy as np
4+
5+
6+
class DummyPseudoclockParser(object):
7+
clock_resolution = 25e-9
8+
trigger_delay = 350e-9
9+
wait_delay = 2.5e-6
10+
11+
def __init__(self, path, device):
12+
self.path = path
13+
self.name = device.name
14+
self.device = device
15+
16+
def get_traces(self, add_trace, clock=None):
17+
if clock is not None:
18+
times, clock_value = clock[0], clock[1]
19+
clock_indices = np.where((clock_value[1:] - clock_value[:-1]) == 1)[0] + 1
20+
# If initial clock value is 1, then this counts as a rising edge
21+
# (clock should be 0 before experiment) but this is not picked up
22+
# by the above code. So we insert it!
23+
if clock_value[0] == 1:
24+
clock_indices = np.insert(clock_indices, 0, 0)
25+
clock_ticks = times[clock_indices]
26+
27+
# get the pulse program
28+
with h5py.File(self.path, 'r') as f:
29+
pulse_program = f[f'devices/{self.name}/PULSE_PROGRAM'][:]
30+
31+
time = []
32+
states = []
33+
trigger_index = 0
34+
t = 0 if clock is None else clock_ticks[trigger_index] + self.trigger_delay
35+
trigger_index += 1
36+
37+
clock_factor = self.clock_resolution / 2.0
38+
39+
for row in pulse_program:
40+
if row['period'] == 0:
41+
# special case
42+
if row['reps'] == 1: # WAIT
43+
if clock is not None:
44+
t = clock_ticks[trigger_index] + self.trigger_delay
45+
trigger_index += 1
46+
else:
47+
t += self.wait_delay
48+
else:
49+
for i in range(row['reps']):
50+
for j in range(1, -1, -1):
51+
time.append(t)
52+
states.append(j)
53+
t += row['period'] * clock_factor
54+
55+
clock = (np.array(time), np.array(states))
56+
57+
clocklines_and_triggers = {}
58+
for pseudoclock_name, pseudoclock in self.device.child_list.items():
59+
for clock_line_name, clock_line in pseudoclock.child_list.items():
60+
if clock_line.parent_port == 'internal':
61+
clocklines_and_triggers[clock_line_name] = clock
62+
add_trace(clock_line_name, clock, self.name, clock_line.parent_port)
63+
64+
return clocklines_and_triggers

labscript_devices/FunctionRunner/labscript_devices.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def func(shot_context, t, ...):
5050
recommended place to do it is within the group 'data/<device_name>', for
5151
example:
5252
53-
with h5py.File(self.h5_file) as f:
53+
with h5py.File(self.h5_file, 'r+') as f:
5454
data_group = f['data'].create_group(self.device_name)
5555
# save datasets/attributes within this group
5656

labscript_devices/IMAQdxCamera/blacs_workers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ def transition_to_manual(self):
429429

430430
print(f"Saving {len(self.images)}/{len(self.exposures)} images.")
431431

432-
with h5py.File(self.h5_filepath) as f:
432+
with h5py.File(self.h5_filepath, 'r+') as f:
433433
# Use orientation for image path, device_name if orientation unspecified
434434
if self.orientation is not None:
435435
image_path = 'images/' + self.orientation

labscript_devices/LightCrafterDMD.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ def program_manual(self, values):
317317
return {}
318318

319319
def transition_to_buffered(self, device_name, h5file, initial_values, fresh):
320-
with h5py.File(h5file) as hdf5_file:
320+
with h5py.File(h5file, 'r') as hdf5_file:
321321
group = hdf5_file['/devices/'+device_name]
322322
if 'IMAGE_TABLE' in group:
323323
table_data = group['IMAGE_TABLE'][:]

labscript_devices/NovaTechDDS9M.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ def transition_to_buffered(self,device_name,h5file,initial_values,fresh):
457457
self.final_values = {}
458458
static_data = None
459459
table_data = None
460-
with h5py.File(h5file) as hdf5_file:
460+
with h5py.File(h5file, 'r') as hdf5_file:
461461
group = hdf5_file['/devices/'+device_name]
462462
# If there are values to set the unbuffered outputs to, set them now:
463463
if 'STATIC_DATA' in group:

labscript_devices/PhaseMatrixQuickSyn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ def transition_to_buffered(self,device_name,h5file,initial_values,fresh):
333333
self.initial_values = initial_values
334334
# Store the final values to for use during transition_to_static:
335335
self.final_values = {}
336-
with h5py.File(h5file) as hdf5_file:
336+
with h5py.File(h5file, 'r') as hdf5_file:
337337
group = hdf5_file['/devices/'+device_name]
338338
# If there are values to set the unbuffered outputs to, set them now:
339339
if 'STATIC_DATA' in group:

0 commit comments

Comments
 (0)