Loading CHANGELOG.rst +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ Merged branches and closed issues * Pulsar backend v0.2.2 check. (!48) * Fix for issue with acq delay . (!45) * Fix for issue #52. (!44) * Add artificial detuning to Ramsey schedule (!120) Loading quantify/scheduler/schedules/timedomain_schedules.py +33 −8 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ Module containing schedules for common time domain experiments such as a Rabi an T1 measurement. """ from typing import Union from typing_extensions import Literal import numpy as np from quantify.scheduler.types import Schedule from quantify.scheduler.pulse_library import SquarePulse, IdlePulse, DRAGPulse Loading Loading @@ -150,6 +151,7 @@ def t1_sched( def ramsey_sched( times: Union[np.ndarray, float], artificial_detuning: float, qubit: str, repetitions: int = 1, ) -> Schedule: Loading @@ -168,6 +170,12 @@ def ramsey_sched( ---------- times an array of wait times tau between the pi/2 pulses. artificial_detuning frequency in Hz of the software emulated, or `artificial` qubit detuning, which is implemented by changing the phase of the second pi/2 (recovery) pulse. The artificial detuning changes the observed frequency of the Ramsey oscillation, which can be useful to distinguish a slow oscillation due to a small physical detuning from the decay of the dephasing noise. qubit the name of the qubit e.g., :code:`"q0"` to perform the Ramsey experiment on. repetitions Loading @@ -194,11 +202,18 @@ def ramsey_sched( schedule = Schedule("Ramsey", repetitions) if isinstance(times, float): times = [times] for i, tau in enumerate(times): schedule.add(Reset(qubit), label=f"Reset {i}") schedule.add(X90(qubit)) # FIXME: to be added artificial detuning see #98 # pylint: disable=fixme schedule.add(Rxy(theta=90, phi=0, qubit=qubit), ref_pt="start", rel_time=tau) # the phase of the second pi/2 phase progresses to propagate recovery_phase = np.rad2deg(2 * np.pi * artificial_detuning * tau) schedule.add( Rxy(theta=90, phi=recovery_phase, qubit=qubit), ref_pt="start", rel_time=tau ) schedule.add(Measure(qubit), label=f"Measurement {i}") return schedule Loading @@ -225,7 +240,7 @@ def echo_sched( Parameters ---------- qubit the name of the qubit e.g., "q0" to perform the Echo experiment on. the name of the qubit e.g., "q0" to perform the echo experiment on. times an array of wait times between the repetitions Loading Loading @@ -263,6 +278,7 @@ def echo_sched( def allxy_sched( qubit: str, elt_select_idx: Union[Literal["All"], int] = "ALL", repetitions: int = 1, ) -> Schedule: # pylint: disable=line-too-long Loading @@ -281,6 +297,9 @@ def allxy_sched( ---------- qubit the name of the qubit e.g., :code:`"q0"` to perform the experiment on. elt_select_idx the index of the particular element of the AllXY experiment to exectute - or :code:`"All"` for all elemements of the sequence. repetitions The amount of times the Schedule will be repeated. Loading @@ -305,7 +324,7 @@ def allxy_sched( allxy_combinations = [ [(0, 0), (0, 0)], [(180, 0), (180, 0)], [(180, 0), (180, 0)], [(180, 90), (180, 90)], [(180, 0), (180, 90)], [(180, 90), (180, 0)], [(90, 0), (0, 0)], Loading @@ -327,10 +346,16 @@ def allxy_sched( ] schedule = Schedule("AllXY", repetitions) for i, ((th0, phi0), (th1, phi1)) in enumerate(allxy_combinations): if elt_select_idx in ("ALL", i): schedule.add(Reset(qubit), label=f"Reset {i}") schedule.add(Rxy(qubit=qubit, theta=th0, phi=phi0)) schedule.add(Rxy(qubit=qubit, theta=th1, phi=phi1)) schedule.add(Measure(qubit), label=f"Measurement {i}") elif elt_select_idx > len(allxy_combinations) or elt_select_idx < 0: raise ValueError( f"Invalid index selected: {elt_select_idx}. " "Index must be in range 0 to 21 inclusive." ) return schedule Loading tests/scheduler/schedules/test_timedomain_schedules.py +40 −3 Original line number Diff line number Diff line Loading @@ -271,6 +271,7 @@ class TestRamseySched: cls.sched_kwargs = { "times": np.linspace(4.0e-6, 80e-6, 20), "qubit": "q0", "artificial_detuning": 250e3, "repetitions": 10, } Loading @@ -295,6 +296,7 @@ class TestRamseySched: sched_kwargs = { "times": 3e-6, # a floating point time "qubit": "q0", "artificial_detuning": 250e3, } sched = ts.ramsey_sched(**sched_kwargs) Loading @@ -302,6 +304,9 @@ class TestRamseySched: def test_operations(self): # 4 for a regular Ramsey, more with artificial detuning if self.sched_kwargs["artificial_detuning"]: assert len(self.sched.operations) == 3 + len(self.sched_kwargs["times"]) else: assert len(self.sched.operations) == 4 # init, x90, Rxy(90,0) and measure def test_compiles_qblox_backend(self): Loading Loading @@ -384,10 +389,42 @@ class TestAllXYSched: assert constr["label"][:11] == "Measurement" def test_operations(self): # 7 operations (x90, y90, X180, Y180, idle, reset measurement) # 7 operations (x90, y90, X180, Y180, idle, reset, measurement) assert len(self.sched.operations) == 7 @pytest.mark.xfail # see #89 def test_compiles_qblox_backend(self): # assert that files properly compile qcompile(self.sched, DEVICE_CONFIG, QBLOX_HARDWARE_MAPPING) def test_compiles_zi_backend(self): # assert that files properly compile qcompile(self.sched, DEVICE_CONFIG, ZHINST_HARDWARE_MAPPING) class TestAllXYSchedElement: @classmethod def setup_class(cls): set_datadir(tmp_dir.name) cls.sched_kwargs = { "qubit": "q0", "elt_select_idx": 4, } cls.sched = ts.allxy_sched(**cls.sched_kwargs) cls.sched = qcompile(cls.sched, DEVICE_CONFIG) def test_timing(self): # test that the right operations are added and timing is as expected. for i, constr in enumerate(self.sched.timing_constraints): if i % 4 == 0: assert constr["label"][:5] == "Reset" if (i - 3) % 4 == 0: assert constr["label"][:11] == "Measurement" def test_operations(self): # 4 operations (X180, Y180, reset, measurement) assert len(self.sched.operations) == 4 def test_compiles_qblox_backend(self): # assert that files properly compile qcompile(self.sched, DEVICE_CONFIG, QBLOX_HARDWARE_MAPPING) Loading Loading
CHANGELOG.rst +1 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ Merged branches and closed issues * Pulsar backend v0.2.2 check. (!48) * Fix for issue with acq delay . (!45) * Fix for issue #52. (!44) * Add artificial detuning to Ramsey schedule (!120) Loading
quantify/scheduler/schedules/timedomain_schedules.py +33 −8 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ Module containing schedules for common time domain experiments such as a Rabi an T1 measurement. """ from typing import Union from typing_extensions import Literal import numpy as np from quantify.scheduler.types import Schedule from quantify.scheduler.pulse_library import SquarePulse, IdlePulse, DRAGPulse Loading Loading @@ -150,6 +151,7 @@ def t1_sched( def ramsey_sched( times: Union[np.ndarray, float], artificial_detuning: float, qubit: str, repetitions: int = 1, ) -> Schedule: Loading @@ -168,6 +170,12 @@ def ramsey_sched( ---------- times an array of wait times tau between the pi/2 pulses. artificial_detuning frequency in Hz of the software emulated, or `artificial` qubit detuning, which is implemented by changing the phase of the second pi/2 (recovery) pulse. The artificial detuning changes the observed frequency of the Ramsey oscillation, which can be useful to distinguish a slow oscillation due to a small physical detuning from the decay of the dephasing noise. qubit the name of the qubit e.g., :code:`"q0"` to perform the Ramsey experiment on. repetitions Loading @@ -194,11 +202,18 @@ def ramsey_sched( schedule = Schedule("Ramsey", repetitions) if isinstance(times, float): times = [times] for i, tau in enumerate(times): schedule.add(Reset(qubit), label=f"Reset {i}") schedule.add(X90(qubit)) # FIXME: to be added artificial detuning see #98 # pylint: disable=fixme schedule.add(Rxy(theta=90, phi=0, qubit=qubit), ref_pt="start", rel_time=tau) # the phase of the second pi/2 phase progresses to propagate recovery_phase = np.rad2deg(2 * np.pi * artificial_detuning * tau) schedule.add( Rxy(theta=90, phi=recovery_phase, qubit=qubit), ref_pt="start", rel_time=tau ) schedule.add(Measure(qubit), label=f"Measurement {i}") return schedule Loading @@ -225,7 +240,7 @@ def echo_sched( Parameters ---------- qubit the name of the qubit e.g., "q0" to perform the Echo experiment on. the name of the qubit e.g., "q0" to perform the echo experiment on. times an array of wait times between the repetitions Loading Loading @@ -263,6 +278,7 @@ def echo_sched( def allxy_sched( qubit: str, elt_select_idx: Union[Literal["All"], int] = "ALL", repetitions: int = 1, ) -> Schedule: # pylint: disable=line-too-long Loading @@ -281,6 +297,9 @@ def allxy_sched( ---------- qubit the name of the qubit e.g., :code:`"q0"` to perform the experiment on. elt_select_idx the index of the particular element of the AllXY experiment to exectute - or :code:`"All"` for all elemements of the sequence. repetitions The amount of times the Schedule will be repeated. Loading @@ -305,7 +324,7 @@ def allxy_sched( allxy_combinations = [ [(0, 0), (0, 0)], [(180, 0), (180, 0)], [(180, 0), (180, 0)], [(180, 90), (180, 90)], [(180, 0), (180, 90)], [(180, 90), (180, 0)], [(90, 0), (0, 0)], Loading @@ -327,10 +346,16 @@ def allxy_sched( ] schedule = Schedule("AllXY", repetitions) for i, ((th0, phi0), (th1, phi1)) in enumerate(allxy_combinations): if elt_select_idx in ("ALL", i): schedule.add(Reset(qubit), label=f"Reset {i}") schedule.add(Rxy(qubit=qubit, theta=th0, phi=phi0)) schedule.add(Rxy(qubit=qubit, theta=th1, phi=phi1)) schedule.add(Measure(qubit), label=f"Measurement {i}") elif elt_select_idx > len(allxy_combinations) or elt_select_idx < 0: raise ValueError( f"Invalid index selected: {elt_select_idx}. " "Index must be in range 0 to 21 inclusive." ) return schedule Loading
tests/scheduler/schedules/test_timedomain_schedules.py +40 −3 Original line number Diff line number Diff line Loading @@ -271,6 +271,7 @@ class TestRamseySched: cls.sched_kwargs = { "times": np.linspace(4.0e-6, 80e-6, 20), "qubit": "q0", "artificial_detuning": 250e3, "repetitions": 10, } Loading @@ -295,6 +296,7 @@ class TestRamseySched: sched_kwargs = { "times": 3e-6, # a floating point time "qubit": "q0", "artificial_detuning": 250e3, } sched = ts.ramsey_sched(**sched_kwargs) Loading @@ -302,6 +304,9 @@ class TestRamseySched: def test_operations(self): # 4 for a regular Ramsey, more with artificial detuning if self.sched_kwargs["artificial_detuning"]: assert len(self.sched.operations) == 3 + len(self.sched_kwargs["times"]) else: assert len(self.sched.operations) == 4 # init, x90, Rxy(90,0) and measure def test_compiles_qblox_backend(self): Loading Loading @@ -384,10 +389,42 @@ class TestAllXYSched: assert constr["label"][:11] == "Measurement" def test_operations(self): # 7 operations (x90, y90, X180, Y180, idle, reset measurement) # 7 operations (x90, y90, X180, Y180, idle, reset, measurement) assert len(self.sched.operations) == 7 @pytest.mark.xfail # see #89 def test_compiles_qblox_backend(self): # assert that files properly compile qcompile(self.sched, DEVICE_CONFIG, QBLOX_HARDWARE_MAPPING) def test_compiles_zi_backend(self): # assert that files properly compile qcompile(self.sched, DEVICE_CONFIG, ZHINST_HARDWARE_MAPPING) class TestAllXYSchedElement: @classmethod def setup_class(cls): set_datadir(tmp_dir.name) cls.sched_kwargs = { "qubit": "q0", "elt_select_idx": 4, } cls.sched = ts.allxy_sched(**cls.sched_kwargs) cls.sched = qcompile(cls.sched, DEVICE_CONFIG) def test_timing(self): # test that the right operations are added and timing is as expected. for i, constr in enumerate(self.sched.timing_constraints): if i % 4 == 0: assert constr["label"][:5] == "Reset" if (i - 3) % 4 == 0: assert constr["label"][:11] == "Measurement" def test_operations(self): # 4 operations (X180, Y180, reset, measurement) assert len(self.sched.operations) == 4 def test_compiles_qblox_backend(self): # assert that files properly compile qcompile(self.sched, DEVICE_CONFIG, QBLOX_HARDWARE_MAPPING) Loading