15
15
# and labscript. The device is a PseudoclockDevice, and can be the sole device
16
16
# in a connection table or experiment.
17
17
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 ))
21
30
22
31
23
32
class DummyPseudoclock (PseudoclockDevice ):
24
33
25
34
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
28
41
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
+ ):
30
45
self .BLACS_connection = BLACS_connection
31
46
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 ))
34
75
35
76
def generate_code (self , hdf5_file ):
36
77
PseudoclockDevice .generate_code (self , hdf5_file )
37
78
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' )
0 commit comments