Skip to content

Commit

Permalink
Save clock instructions (mock PineBlaster) and add runviewer_parser
Browse files Browse the repository at this point in the history
  • Loading branch information
rpanderson committed Jun 23, 2020
1 parent 55b1bd8 commit d2e5679
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 12 deletions.
84 changes: 75 additions & 9 deletions labscript_devices/DummyPseudoclock/labscript_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,90 @@
# and labscript. The device is a PseudoclockDevice, and can be the sole device
# in a connection table or experiment.

import labscript_utils.h5_lock
import h5py
from labscript import PseudoclockDevice, Pseudoclock, ClockLine
from labscript import PseudoclockDevice, Pseudoclock, ClockLine, config, LabscriptError
import numpy as np


class DummyPseudoclock(PseudoclockDevice):

description = 'Dummy pseudoclock'
clock_limit = 1e6
clock_resolution = 1e-6
clock_limit = 10e6
clock_resolution = 25e-9
clock_type = 'fast clock'
trigger_delay = 350e-9
wait_delay = 2.5e-6
allowed_children = None
max_instructions = 1e5

def __init__(self, name='dummy_pseudoclock', BLACS_connection='dummy_connection', **kwargs):
def __init__(
self, name='dummy_pseudoclock', BLACS_connection='dummy_connection', **kwargs
):
self.BLACS_connection = BLACS_connection
PseudoclockDevice.__init__(self, name, None, None, **kwargs)
self.pseudoclock = Pseudoclock(self.name + '_pseudoclock', self, 'pseudoclock')
self.clockline = ClockLine(name='clockline', pseudoclock=self.pseudoclock, connection='dummy')
self._pseudoclock = Pseudoclock(
name=f'{name}_pseudoclock',
pseudoclock_device=self,
connection='pseudoclock',
)
self._clock_line = ClockLine(
name=f'{name}_clock_line',
pseudoclock=self.pseudoclock,
connection='internal',
)

@property
def pseudoclock(self):
return self._pseudoclock

@property
def clockline(self):
return self._clock_line

def generate_code(self, hdf5_file):
PseudoclockDevice.generate_code(self, hdf5_file)
group = self.init_device_group(hdf5_file)
self.set_property('stop_time', self.stop_time, location='device_properties')

# Compress clock instructions with the same period
# This will halve the number of instructions roughly,
# since the DummyPseudoclock does not have a 'slow clock'
reduced_instructions = []
for instruction in self.pseudoclock.clock:
if instruction == 'WAIT':
# The following period and reps indicates a wait instruction
reduced_instructions.append({'period': 0, 'reps': 1})
continue
reps = instruction['reps']
# period is in quantised units:
period = int(round(instruction['step'] / self.clock_resolution))
if reduced_instructions and reduced_instructions[-1]['period'] == period:
reduced_instructions[-1]['reps'] += reps
else:
reduced_instructions.append({'period': period, 'reps': reps})
# The following period and reps indicates a stop instruction:
reduced_instructions.append({'period': 0, 'reps': 0})
if len(reduced_instructions) > self.max_instructions:
raise LabscriptError(
"%s %s has too many instructions. It has %d and can only support %d"
% (
self.description,
self.name,
len(reduced_instructions),
self.max_instructions,
)
)
# Store these instructions to the h5 file:
dtypes = [('period', int), ('reps', int)]
pulse_program = np.zeros(len(reduced_instructions), dtype=dtypes)
for i, instruction in enumerate(reduced_instructions):
pulse_program[i]['period'] = instruction['period']
pulse_program[i]['reps'] = instruction['reps']
group.create_dataset(
'PULSE_PROGRAM', compression=config.compression, data=pulse_program
)
# TODO: is this needed, the PulseBlasters don't save it...
self.set_property(
'is_master_pseudoclock',
self.is_master_pseudoclock,
location='device_properties',
)
self.set_property('stop_time', self.stop_time, location='device_properties')
10 changes: 7 additions & 3 deletions labscript_devices/DummyPseudoclock/register_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@
#####################################################################
import labscript_devices

labscript_device_name = 'DummyPseudoclock'
blacs_tab = 'labscript_devices.DummyPseudoclock.blacs_tabs.DummyPseudoclockTab'
parser = 'labscript_devices.DummyPseudoclock.runviewer_parsers.DummyPseudoclockParser'

labscript_devices.register_classes(
'DummyPseudoclock',
BLACS_tab='labscript_devices.DummyPseudoclock.blacs_tabs.DummyPseudoclockTab',
runviewer_parser=None, #TODO make a runviwer parser for Dummy pseudoclock!
labscript_device_name=labscript_device_name,
BLACS_tab=blacs_tab,
runviewer_parser=parser,
)
65 changes: 65 additions & 0 deletions labscript_devices/DummyPseudoclock/runviewer_parsers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import labscript_utils.h5_lock # noqa: F401
import h5py
import numpy as np


class DummyPseudoclockParser(object):
clock_resolution = 25e-9
clock_type = 'fast clock'
trigger_delay = 350e-9
wait_delay = 2.5e-6

def __init__(self, path, device):
self.path = path
self.name = device.name
self.device = device

def get_traces(self, add_trace, clock=None):
if clock is not None:
times, clock_value = clock[0], clock[1]
clock_indices = np.where((clock_value[1:] - clock_value[:-1]) == 1)[0] + 1
# If initial clock value is 1, then this counts as a rising edge
# (clock should be 0 before experiment) but this is not picked up
# by the above code. So we insert it!
if clock_value[0] == 1:
clock_indices = np.insert(clock_indices, 0, 0)
clock_ticks = times[clock_indices]

# get the pulse program
with h5py.File(self.path, 'r') as f:
pulse_program = f[f'devices/{self.name}/PULSE_PROGRAM'][:]

time = []
states = []
trigger_index = 0
t = 0 if clock is None else clock_ticks[trigger_index] + self.trigger_delay
trigger_index += 1

clock_factor = self.clock_resolution / 2.0

for row in pulse_program:
if row['period'] == 0:
# special case
if row['reps'] == 1: # WAIT
if clock is not None:
t = clock_ticks[trigger_index] + self.trigger_delay
trigger_index += 1
else:
t += self.wait_delay
else:
for i in range(row['reps']):
for j in range(1, -1, -1):
time.append(t)
states.append(j)
t += row['period'] * clock_factor

clock = (np.array(time), np.array(states))

clocklines_and_triggers = {}
for pseudoclock_name, pseudoclock in self.device.child_list.items():
for clock_line_name, clock_line in pseudoclock.child_list.items():
if clock_line.parent_port == 'internal':
clocklines_and_triggers[clock_line_name] = clock
add_trace(clock_line_name, clock, self.name, clock_line.parent_port)

return clocklines_and_triggers

0 comments on commit d2e5679

Please sign in to comment.