Skip to content

Commit

Permalink
Merge pull request #689 from qiboteam/snz
Browse files Browse the repository at this point in the history
Simplify and refactor SNZ pulse
  • Loading branch information
andrea-pasquale authored Dec 6, 2023
2 parents a984a30 + e0ab920 commit 139ed64
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 24 deletions.
32 changes: 17 additions & 15 deletions src/qibolab/pulses.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,41 +468,43 @@ class SNZ(PulseShape):
"""
Sudden variant Net Zero.
https://arxiv.org/abs/2008.07411
(Supplementary materials: FIG. S1.)
"""

def __init__(self, t_half_flux_pulse=None, b_amplitude=1):
def __init__(self, t_idling, b_amplitude=None):
self.name = "SNZ"
self.pulse: Pulse = None
self.t_half_flux_pulse: float = t_half_flux_pulse
self.b_amplitude: float = b_amplitude
self.t_idling: float = t_idling
self.b_amplitude = b_amplitude

def __eq__(self, item) -> bool:
"""Overloads == operator"""
if super().__eq__(item):
return self.t_half_flux_pulse == item.t_half_flux_pulse and self.b_amplitude == item.b_amplitude
return self.t_idling == item.t_idling and self.b_amplitude == item.b_amplitude
return False

@property
def envelope_waveform_i(self) -> Waveform:
"""The envelope waveform of the i component of the pulse."""

if self.pulse:
if not self.t_half_flux_pulse:
self.t_half_flux_pulse = self.pulse.duration / 2
elif 2 * self.t_half_flux_pulse > self.pulse.duration:
raise ValueError("Pulse shape parameter error: pulse.t_half_flux_pulse <= pulse.duration")
if self.t_idling > self.pulse.duration:
raise ValueError(f"Cannot put idling time {self.t_idling} higher than duration {self.pulse.duration}.")
if self.b_amplitude is None:
self.b_amplitude = self.pulse.amplitude / 2
num_samples = int(np.rint(self.pulse.duration / 1e9 * PulseShape.SAMPLING_RATE))
half_flux_pulse_samples = int(np.rint(num_samples * self.t_half_flux_pulse / self.pulse.duration))
iding_samples = num_samples - 2 * half_flux_pulse_samples
half_pulse_duration = (self.pulse.duration - self.t_idling) / 2
half_flux_pulse_samples = int(np.rint(num_samples * half_pulse_duration / self.pulse.duration))
idling_samples = num_samples - 2 * half_flux_pulse_samples
waveform = Waveform(
np.concatenate(
(
self.pulse.amplitude * np.ones(half_flux_pulse_samples - 1),
np.array([self.pulse.amplitude * self.b_amplitude]),
np.zeros(iding_samples),
-1 * np.array([self.pulse.amplitude * self.b_amplitude]),
-1 * self.pulse.amplitude * np.ones(half_flux_pulse_samples - 1),
np.array([self.b_amplitude]),
np.zeros(idling_samples),
-np.array([self.b_amplitude]),
-self.pulse.amplitude * np.ones(half_flux_pulse_samples - 1),
)
)
)
Expand All @@ -522,7 +524,7 @@ def envelope_waveform_q(self) -> Waveform:
raise ShapeInitError

def __repr__(self):
return f"{self.name}({self.t_half_flux_pulse}, {self.b_amplitude})"
return f"{self.name}({self.t_idling})"


class eCap(PulseShape):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_instruments_zhinst.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_zhpulse(shape):
if shape == "Drag":
pulse = Pulse(0, 40, 0.05, int(3e9), 0.0, Drag(5, 0.4), "ch0", qubit=0)
if shape == "SNZ":
pulse = Pulse(0, 40, 0.05, int(3e9), 0.0, SNZ(10, 0.4), "ch0", qubit=0)
pulse = Pulse(0, 40, 0.05, int(3e9), 0.0, SNZ(10, 0.01), "ch0", qubit=0)
if shape == "IIR":
pulse = Pulse(0, 40, 0.05, int(3e9), 0.0, IIR([10, 1], [0.4, 1], target=Gaussian(5)), "ch0", qubit=0)

Expand Down
16 changes: 8 additions & 8 deletions tests/test_pulses.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_pulses_plot_functions():
p1 = Pulse(0, 40, 0.9, 50e6, 0, Gaussian(5), 0, PulseType.DRIVE, 2)
p2 = Pulse(0, 40, 0.9, 50e6, 0, Drag(5, 2), 0, PulseType.DRIVE, 200)
p3 = FluxPulse(0, 40, 0.9, IIR([-0.5, 2], [1], Rectangular()), 0, 200)
p4 = FluxPulse(0, 40, 0.9, SNZ(t_half_flux_pulse=17, b_amplitude=0.8), 0, 200)
p4 = FluxPulse(0, 40, 0.9, SNZ(t_idling=10), 0, 200)
p5 = Pulse(0, 40, 0.9, 400e6, 0, eCap(alpha=2), 0, PulseType.DRIVE)
p6 = SplitPulse(p5, window_start=10, window_finish=30)
ps = p0 + p1 + p2 + p3 + p4 + p5 + p6
Expand Down Expand Up @@ -155,7 +155,7 @@ def test_pulses_pulse_init():
p8 = Pulse(0, 40, 0.9, 50e6, 0, Gaussian(5), 0, PulseType.DRIVE, 2)
p9 = Pulse(0, 40, 0.9, 50e6, 0, Drag(5, 2), 0, PulseType.DRIVE, 200)
p10 = FluxPulse(0, 40, 0.9, IIR([-1, 1], [-0.1, 0.1001], Rectangular()), 0, 200)
p11 = FluxPulse(0, 40, 0.9, SNZ(t_half_flux_pulse=17, b_amplitude=0.8), 0, 200)
p11 = FluxPulse(0, 40, 0.9, SNZ(t_idling=10, b_amplitude=0.5), 0, 200)
p11 = Pulse(0, 40, 0.9, 400e6, 0, eCap(alpha=2), 0, PulseType.DRIVE)

# initialisation with float duration and start
Expand Down Expand Up @@ -364,7 +364,7 @@ def test_raise_shapeiniterror():
with pytest.raises(ShapeInitError):
shape.envelope_waveform_q

shape = SNZ(0, 0)
shape = SNZ(0)
with pytest.raises(ShapeInitError):
shape.envelope_waveform_i
with pytest.raises(ShapeInitError):
Expand Down Expand Up @@ -924,11 +924,11 @@ def test_pulses_pulseshape_eq():
assert not shape1 == shape5
assert not shape1 == shape6

shape1 = SNZ(17, 0.8)
shape2 = SNZ(17, 0.8)
shape3 = SNZ(18, 0.8)
shape4 = SNZ(17, 0.9)
shape5 = SNZ(18, 0.9)
shape1 = SNZ(5)
shape2 = SNZ(5)
shape3 = SNZ(2)
shape4 = SNZ(2, 0.1)
shape5 = SNZ(2, 0.1)
assert shape1 == shape2
assert not shape1 == shape3
assert not shape1 == shape4
Expand Down

0 comments on commit 139ed64

Please sign in to comment.