2
2
import tempfile
3
3
import warnings
4
4
import hjson
5
- from typing import Callable , Dict , Any
5
+ from typing import Callable , Dict , Any , List
6
6
import tensorflow as tf
7
7
import numpy as np
8
8
from c3 .signal .pulse import Envelope , Carrier
@@ -26,7 +26,7 @@ class Device(C3obj):
26
26
27
27
Parameters
28
28
----------
29
- resolution: np.float64
29
+ resolution: float
30
30
Number of samples per second this device operates at.
31
31
"""
32
32
@@ -69,32 +69,32 @@ def asdict(self) -> Dict[str, Any]:
69
69
def __str__ (self ) -> str :
70
70
return hjson .dumps (self .asdict (), default = hjson_encode )
71
71
72
- def calc_slice_num (self , t_start : np . float64 , t_end : np . float64 ) -> None :
72
+ def calc_slice_num (self , t_start : float = 0.0 , t_end : float = 0.0 ) -> None :
73
73
"""
74
74
Effective number of time slices given start, end and resolution.
75
75
76
76
Parameters
77
77
----------
78
- t_start: np.float64
78
+ t_start: float
79
79
Starting time for this device.
80
- t_end: np.float64
80
+ t_end: float
81
81
End time for this device.
82
82
"""
83
83
res = self .resolution
84
84
self .slice_num = int (np .abs (t_start - t_end ) * res )
85
85
# return self.slice_num
86
86
87
87
def create_ts (
88
- self , t_start : np . float64 , t_end : np . float64 , centered : bool = True
88
+ self , t_start : float = 0 , t_end : float = 0 , centered : bool = True
89
89
) -> tf .constant :
90
90
"""
91
91
Compute time samples.
92
92
93
93
Parameters
94
94
----------
95
- t_start: np.float64
95
+ t_start: float
96
96
Starting time for this device.
97
- t_end: np.float64
97
+ t_end: float
98
98
End time for this device.
99
99
centered: boolean
100
100
Sample in the middle of an interval, otherwise at the beginning.
@@ -121,6 +121,31 @@ def create_ts(
121
121
ts = tf .linspace (t_start , t_end , num )
122
122
return ts
123
123
124
+ def process (
125
+ self , instr : Instruction , chan : str , signals : List [Dict [str , Any ]]
126
+ ) -> Dict [str , Any ]:
127
+ """To be implemented by inheriting class.
128
+
129
+ Parameters
130
+ ----------
131
+ instr : Instruction
132
+ Information about the instruction or gate to be excecuted.
133
+ chan : str
134
+ Identifier of the drive line
135
+ signals : List[Dict[str, Any]]
136
+ List of potentially multiple input signals to this device.
137
+
138
+ Returns
139
+ -------
140
+ Dict[str, Any]
141
+ Output signal of this device.
142
+
143
+ Raises
144
+ ------
145
+ NotImplementedError
146
+ """
147
+ raise NotImplementedError ()
148
+
124
149
125
150
@dev_reg_deco
126
151
class Readout (Device ):
@@ -176,7 +201,7 @@ def __init__(self, **props):
176
201
self .outputs = props .pop ("outputs" , 1 )
177
202
178
203
def process (
179
- self , instr : Instruction , chan : str , mixed_signal : Dict [str , Any ]
204
+ self , instr : Instruction , chan : str , mixed_signal : List [ Dict [str , Any ] ]
180
205
) -> Dict [str , Any ]:
181
206
"""Transform signal from value of V to Hz.
182
207
@@ -191,8 +216,8 @@ def process(
191
216
Waveform as control amplitudes
192
217
"""
193
218
v2hz = self .params ["V_to_Hz" ].get_value ()
194
- self .signal ["values" ] = mixed_signal ["values" ] * v2hz
195
- self .signal ["ts" ] = mixed_signal ["ts" ]
219
+ self .signal ["values" ] = mixed_signal [0 ][ "values" ] * v2hz
220
+ self .signal ["ts" ] = mixed_signal [0 ][ "ts" ]
196
221
return self .signal
197
222
198
223
@@ -202,7 +227,7 @@ class Crosstalk(Device):
202
227
Device to phenomenologically include crosstalk in the model by explicitly mixing
203
228
drive lines.
204
229
205
- Parameters
230
+ Parameters^
206
231
----------
207
232
208
233
crosstalk_matrix: tf.constant
@@ -234,7 +259,9 @@ def __init__(self, **props):
234
259
self .outputs = props .pop ("outputs" , 1 )
235
260
self .params ["crosstalk_matrix" ] = props .pop ("crosstalk_matrix" , None )
236
261
237
- def process (self , signal : Dict [str , Any ]) -> Dict [str , Any ]:
262
+ def process (
263
+ self , instr : Instruction , chan : str , signals : List [Dict [str , Any ]]
264
+ ) -> Dict [str , Any ]:
238
265
"""
239
266
Mix channels in the input signal according to a crosstalk matrix.
240
267
@@ -258,11 +285,11 @@ def process(self, signal: Dict[str, Any]) -> Dict[str, Any]:
258
285
259
286
"""
260
287
xtalk = self .params ["crosstalk_matrix" ]
261
- signals = [signal [ch ]["values" ] for ch in self .crossed_channels ]
262
- crossed_signals = xtalk .get_value () @ signals
288
+ signal = [signals [ 0 ] [ch ]["values" ] for ch in self .crossed_channels ]
289
+ crossed_signals = xtalk .get_value () @ signal
263
290
for indx , ch in enumerate (self .crossed_channels ):
264
- signal [ch ]["values" ] = crossed_signals [indx ]
265
- return signal
291
+ signals [ 0 ] [ch ]["values" ] = crossed_signals [indx ]
292
+ return signals [ 0 ]
266
293
267
294
268
295
@dev_reg_deco
@@ -277,7 +304,7 @@ def __init__(self, **props):
277
304
self .sampling_method = props .pop ("sampling_method" , "nearest" )
278
305
279
306
def process (
280
- self , instr : Instruction , chan : str , awg_signal : Dict [str , Any ]
307
+ self , instr : Instruction , chan : str , awg_signal : List [ Dict [str , Any ] ]
281
308
) -> Dict [str , Any ]:
282
309
"""Resample the awg values to higher resolution.
283
310
@@ -297,12 +324,12 @@ def process(
297
324
Inphase and Quadrature compontent of the upsampled signal.
298
325
"""
299
326
ts = self .create_ts (instr .t_start , instr .t_end , centered = True )
300
- old_dim = awg_signal ["inphase" ].shape [0 ]
327
+ old_dim = awg_signal [0 ][ "inphase" ].shape [0 ]
301
328
new_dim = ts .shape [0 ]
302
329
# TODO add following zeros
303
330
inphase = tf .reshape (
304
331
tf .image .resize (
305
- tf .reshape (awg_signal ["inphase" ], shape = [1 , old_dim , 1 ]),
332
+ tf .reshape (awg_signal [0 ][ "inphase" ], shape = [1 , old_dim , 1 ]),
306
333
size = [1 , new_dim ],
307
334
method = self .sampling_method ,
308
335
),
@@ -311,7 +338,7 @@ def process(
311
338
inphase = tf .cast (inphase , tf .float64 )
312
339
quadrature = tf .reshape (
313
340
tf .image .resize (
314
- tf .reshape (awg_signal ["quadrature" ], shape = [1 , old_dim , 1 ]),
341
+ tf .reshape (awg_signal [0 ][ "quadrature" ], shape = [1 , old_dim , 1 ]),
315
342
size = [1 , new_dim ],
316
343
method = self .sampling_method ,
317
344
),
@@ -335,7 +362,7 @@ def __init__(self, **props):
335
362
# super().__init__(**props)
336
363
337
364
def process (
338
- self , instr : Instruction , chan : str , Hz_signal : Dict [str , Any ]
365
+ self , instr : Instruction , chan : str , Hz_signal : List [ Dict [str , Any ] ]
339
366
) -> Dict [str , Any ]:
340
367
"""Apply a filter function to the signal."""
341
368
raise Exception ("C3:ERROR Not yet implemented." )
@@ -560,9 +587,11 @@ def process(self, instr, chan, iq_signal):
560
587
offset = tf .exp (- ((- 1 - cen ) ** 2 ) / (2 * sigma * sigma ))
561
588
# TODO make sure ratio of risetime and resolution is an integer
562
589
risefun = gauss - offset
563
- inphase = self .convolve (iq_signal ["inphase" ], risefun / tf .reduce_sum (risefun ))
590
+ inphase = self .convolve (
591
+ iq_signal [0 ]["inphase" ], risefun / tf .reduce_sum (risefun )
592
+ )
564
593
quadrature = self .convolve (
565
- iq_signal ["quadrature" ], risefun / tf .reduce_sum (risefun )
594
+ iq_signal [0 ][ "quadrature" ], risefun / tf .reduce_sum (risefun )
566
595
)
567
596
self .signal = {
568
597
"inphase" : inphase ,
@@ -602,7 +631,7 @@ def process(self, instr, chan, iq_signal):
602
631
Bandwidth limited IQ signal.
603
632
604
633
"""
605
- res_diff = (iq_signal ["ts" ][1 ] - iq_signal ["ts" ][0 ]) / self .resolution - 1
634
+ res_diff = (iq_signal [0 ][ "ts" ][1 ] - iq_signal [ 0 ] ["ts" ][0 ]) / self .resolution - 1
606
635
if res_diff > 1e-8 :
607
636
raise Exception (
608
637
"C3:Error:Actual time resolution differs from desired by {res_diff:1.3g}."
@@ -621,17 +650,17 @@ def process(self, instr, chan, iq_signal):
621
650
offset = tf .exp (- ((- 1 - cen ) ** 2 ) / (2 * sigma * sigma ))
622
651
623
652
risefun = gauss - offset
624
- inphase = tf_convolve (iq_signal ["inphase" ], risefun / tf .reduce_sum (risefun ))
653
+ inphase = tf_convolve (iq_signal [0 ][ "inphase" ], risefun / tf .reduce_sum (risefun ))
625
654
quadrature = tf_convolve (
626
- iq_signal ["quadrature" ], risefun / tf .reduce_sum (risefun )
655
+ iq_signal [0 ][ "quadrature" ], risefun / tf .reduce_sum (risefun )
627
656
)
628
657
629
658
inphase = tf .math .real (inphase )
630
659
quadrature = tf .math .real (quadrature )
631
660
self .signal = {
632
661
"inphase" : inphase ,
633
662
"quadrature" : quadrature ,
634
- "ts" : iq_signal ["ts" ],
663
+ "ts" : iq_signal [0 ][ "ts" ],
635
664
}
636
665
return self .signal
637
666
@@ -845,7 +874,7 @@ def __init__(self, **props):
845
874
self .inputs = props .pop ("inputs" , 2 )
846
875
self .outputs = props .pop ("outputs" , 1 )
847
876
848
- def process (self , instr : Instruction , chan : str , in1 : dict , in2 : dict ):
877
+ def process (self , instr : Instruction , chan : str , inputs : List [ Dict [ str , Any ]] ):
849
878
"""Combine signal from AWG and LO.
850
879
851
880
Parameters
@@ -860,6 +889,7 @@ def process(self, instr: Instruction, chan: str, in1: dict, in2: dict):
860
889
dict
861
890
Mixed signal.
862
891
"""
892
+ in1 , in2 = inputs
863
893
i1 = in1 ["inphase" ]
864
894
q1 = in1 ["quadrature" ]
865
895
i2 = in2 ["inphase" ]
@@ -1004,7 +1034,9 @@ def __init__(self, **props):
1004
1034
self .freq_noise = props .pop ("freq_noise" , 0 )
1005
1035
self .amp_noise = props .pop ("amp_noise" , 0 )
1006
1036
1007
- def process (self , instr : Instruction , chan : str ) -> dict :
1037
+ def process (
1038
+ self , instr : Instruction , chan : str , signal : List [Dict [str , Any ]]
1039
+ ) -> dict :
1008
1040
# TODO check somewhere that there is only 1 carrier per instruction
1009
1041
ts = self .create_ts (instr .t_start , instr .t_end , centered = True )
1010
1042
dt = ts [1 ] - ts [0 ]
@@ -1099,7 +1131,7 @@ def asdict(self) -> dict:
1099
1131
# TODO create DC function
1100
1132
1101
1133
# TODO make AWG take offset from the previous point
1102
- def create_IQ (self , instr : Instruction , chan : str ) -> dict :
1134
+ def create_IQ (self , instr : Instruction , chan : str , inputs ) -> dict :
1103
1135
"""
1104
1136
Construct the in-phase (I) and quadrature (Q) components of the signal.
1105
1137
These are universal to either experiment or simulation.
@@ -1137,7 +1169,7 @@ def create_IQ(self, instr: Instruction, chan: str) -> dict:
1137
1169
}
1138
1170
return self .signal [chan ]
1139
1171
1140
- def create_IQ_pwc (self , instr : Instruction , chan : str ) -> dict :
1172
+ def create_IQ_pwc (self , instr : Instruction , chan : str , inputs ) -> dict :
1141
1173
"""
1142
1174
Construct the in-phase (I) and quadrature (Q) components of the signal.
1143
1175
These are universal to either experiment or simulation.
0 commit comments