Skip to content

Commit e8703d7

Browse files
committed
Legacy response function converted to FFT
1 parent 775ae92 commit e8703d7

File tree

2 files changed

+54
-50
lines changed

2 files changed

+54
-50
lines changed

c3/generator/devices.py

Lines changed: 9 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from c3.signal.pulse import Carrier
88
from c3.signal.gates import Instruction
99
from c3.c3objs import Quantity, C3obj, hjson_encode
10-
from c3.utils.tf_utils import tf_convolve
10+
from c3.utils.tf_utils import tf_convolve, tf_convolve_legacy
1111

1212
devices = dict()
1313

@@ -513,50 +513,6 @@ def __init__(self, **props):
513513
super().__init__(**props)
514514
self.inputs = props.pop("inputs", 1)
515515
self.outputs = props.pop("outputs", 1)
516-
raise Exception("use ResponseFFT for faster signal generation instead")
517-
518-
def convolve(self, signal: list, resp_shape: list):
519-
"""
520-
Compute the convolution with a function.
521-
522-
Parameters
523-
----------
524-
signal : list
525-
Potentially unlimited signal samples.
526-
resp_shape : list
527-
Samples of the function to model limited bandwidth.
528-
529-
Returns
530-
-------
531-
tf.Tensor
532-
Processed signal.
533-
534-
"""
535-
convolution = tf.zeros(0, dtype=tf.float64)
536-
signal = tf.concat(
537-
[
538-
tf.zeros(len(resp_shape), dtype=tf.float64),
539-
signal,
540-
tf.zeros(len(resp_shape), dtype=tf.float64),
541-
],
542-
0,
543-
)
544-
for p in range(len(signal) - 2 * len(resp_shape)):
545-
convolution = tf.concat(
546-
[
547-
convolution,
548-
tf.reshape(
549-
tf.math.reduce_sum(
550-
tf.math.multiply(
551-
signal[p : p + len(resp_shape)], resp_shape
552-
)
553-
),
554-
shape=[1],
555-
),
556-
],
557-
0,
558-
)
559-
return convolution
560516

561517
def process(self, instr, chan, iq_signal: List[Dict[str, Any]]) -> Dict[str, Any]:
562518
"""
@@ -580,23 +536,26 @@ def process(self, instr, chan, iq_signal: List[Dict[str, Any]]) -> Dict[str, Any
580536
tf.cast(n_ts, tf.int32),
581537
)
582538
cen = tf.cast(
583-
(self.params["rise_time"].get_value() - 1 / self.resolution) / 2, tf.float64
539+
(self.params["rise_time"].get_value() + 1 / self.resolution) / 2, tf.float64
584540
)
585541
sigma = self.params["rise_time"].get_value() / 4
586542
gauss = tf.exp(-((ts - cen) ** 2) / (2 * sigma * sigma))
587543
offset = tf.exp(-((-1 - cen) ** 2) / (2 * sigma * sigma))
588-
# TODO make sure ratio of risetime and resolution is an integer
544+
589545
risefun = gauss - offset
590-
inphase = self.convolve(
546+
inphase = tf_convolve_legacy(
591547
iq_signal[0]["inphase"], risefun / tf.reduce_sum(risefun)
592548
)
593-
quadrature = self.convolve(
549+
quadrature = tf_convolve_legacy(
594550
iq_signal[0]["quadrature"], risefun / tf.reduce_sum(risefun)
595551
)
552+
553+
inphase = tf.math.real(inphase)
554+
quadrature = tf.math.real(quadrature)
596555
self.signal = {
597556
"inphase": inphase,
598557
"quadrature": quadrature,
599-
"ts": self.create_ts(instr.t_start, instr.t_end, centered=True),
558+
"ts": iq_signal[0]["ts"],
600559
}
601560
return self.signal
602561

c3/utils/tf_utils.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,48 @@ def tf_convolve(sig: tf.Tensor, resp: tf.Tensor):
463463
fft_conv = tf.math.reduce_prod(fft_sig_resp, axis=0)
464464
convolution = tf.signal.ifft(fft_conv)
465465
return convolution[:sig_len]
466+
467+
468+
def tf_convolve_legacy(sig: tf.Tensor, resp: tf.Tensor):
469+
"""
470+
Compute the convolution with a time response. LEGACY version. Ensures compatibility with the previous response implementation.
471+
472+
Parameters
473+
----------
474+
sig : tf.Tensor
475+
Signal which will be convoluted, shape: [N]
476+
resp : tf.Tensor
477+
Response function to be convoluted with signal, shape: [M]
478+
479+
Returns
480+
-------
481+
tf.Tensor
482+
convoluted signal of shape [N]
483+
484+
"""
485+
sig = tf.cast(sig, dtype=tf.complex128)
486+
resp = tf.cast(resp, dtype=tf.complex128)
487+
488+
sig_len = len(sig)
489+
resp_len = len(resp)
490+
491+
signal_pad = tf.expand_dims(
492+
tf.concat(
493+
[
494+
tf.zeros(resp_len, dtype=tf.complex128),
495+
sig,
496+
tf.zeros(resp_len, dtype=tf.complex128),
497+
],
498+
axis=0,
499+
),
500+
0,
501+
)
502+
resp_pad = tf.expand_dims(
503+
tf.concat([resp, tf.zeros(sig_len + resp_len, dtype=tf.complex128)], axis=0), 0
504+
)
505+
sig_resp = tf.concat([signal_pad, resp_pad], axis=0)
506+
507+
fft_sig_resp = tf.signal.fft(sig_resp)
508+
fft_conv = tf.math.reduce_prod(fft_sig_resp, axis=0)
509+
convolution = tf.signal.ifft(fft_conv)
510+
return convolution[resp_len - 1 : sig_len + resp_len - 1]

0 commit comments

Comments
 (0)