Source code for quantify_scheduler.schedules.trace_schedules

# Repository: https://gitlab.com/quantify-os/quantify-scheduler
# Licensed according to the LICENCE file on the main branch
"""Contains various examples of trace schedules."""
from __future__ import annotations

from typing import TYPE_CHECKING

import numpy as np

if TYPE_CHECKING:
    from quantify_scheduler.device_under_test.device_element import DeviceElement

from quantify_scheduler.enums import BinMode
from quantify_scheduler.operations.acquisition_library import (
    SSBIntegrationComplex,
    Trace,
)
from quantify_scheduler.operations.control_flow_library import LoopOperation
from quantify_scheduler.operations.gate_library import Measure
from quantify_scheduler.operations.pulse_library import (
    IdlePulse,
    SquarePulse,
    VoltageOffset,
)
from quantify_scheduler.resources import ClockResource
from quantify_scheduler.schedules.schedule import Schedule


[docs] def trace_schedule( pulse_amp: float, pulse_duration: float, pulse_delay: float, frequency: float, acquisition_delay: float, integration_time: float, port: str, clock: str, init_duration: float = 200e-6, repetitions: int = 1, ) -> Schedule: """ Generate a schedule to perform raw trace acquisition. Parameters ---------- pulse_amp : The amplitude of the pulse in Volt. pulse_duration The duration of the pulse in seconds. pulse_delay The pulse delay in seconds. frequency The frequency of the pulse and of the data acquisition in Hertz. acquisition_delay The start of the data acquisition with respect to the start of the pulse in seconds. integration_time The time in seconds to integrate. port The location on the device where the pulse should be applied. clock The reference clock used to track the pulse frequency. init_duration The relaxation time or dead time. repetitions The amount of times the Schedule will be repeated. Returns ------- : The Raw Trace acquisition Schedule. """ schedule = Schedule("Raw trace acquisition", repetitions) schedule.add_resource(ClockResource(name=clock, freq=frequency)) schedule.add(IdlePulse(duration=init_duration), label="Dead time") pulse = schedule.add( SquarePulse( duration=pulse_duration, amp=pulse_amp, port=port, clock=clock, ), label="trace_pulse", rel_time=pulse_delay, ) schedule.add( Trace( duration=integration_time, port=port, clock=clock, acq_index=0, acq_channel=0, ), ref_op=pulse, ref_pt="start", rel_time=acquisition_delay, label="acquisition", ) return schedule
[docs] def trace_schedule_circuit_layer( qubit_name: str, repetitions: int = 1, ) -> Schedule: """ Generate a simple schedule at circuit layer to perform raw trace acquisition. Parameters ---------- qubit_name Name of a device element. repetitions The amount of times the Schedule will be repeated. Returns ------- : The Raw Trace acquisition Schedule. """ schedule = Schedule("Raw trace acquisition", repetitions) schedule.add(Measure(qubit_name, acq_protocol="Trace")) return schedule
[docs] def two_tone_trace_schedule( qubit_pulse_amp: float, qubit_pulse_duration: float, qubit_pulse_frequency: float, qubit_pulse_port: str, qubit_pulse_clock: str, ro_pulse_amp: float, ro_pulse_duration: float, ro_pulse_delay: float, ro_pulse_port: str, ro_pulse_clock: str, ro_pulse_frequency: float, ro_acquisition_delay: float, ro_integration_time: float, init_duration: float = 200e-6, repetitions: int = 1, ) -> Schedule: """ Generate a schedule for performing a two-tone raw trace acquisition. Parameters ---------- qubit_pulse_amp The amplitude of the pulse in Volt. qubit_pulse_duration The duration of the pulse in seconds. qubit_pulse_frequency The pulse frequency in Hertz. qubit_pulse_port The location on the device where the qubit pulse should be applied. qubit_pulse_clock The reference clock used to track the pulse frequency. ro_pulse_amp The amplitude of the readout pulse in Volt. ro_pulse_duration The duration of the readout pulse in seconds. ro_pulse_delay The time between the end of the pulse and the start of the readout pulse. ro_pulse_port The location on the device where the readout pulse should be applied. ro_pulse_clock The reference clock used to track the readout pulse frequency. ro_pulse_frequency The readout pulse frequency in Hertz. ro_acquisition_delay The start of the data acquisition with respect to the start of the pulse in seconds. ro_integration_time The integration time of the data acquisition in seconds. init_duration : The relaxation time or dead time. repetitions The amount of times the Schedule will be repeated. Returns ------- : The Two-tone Trace acquisition Schedule. """ schedule = Schedule("Two-tone Trace acquisition", repetitions) schedule.add_resource(ClockResource(name=qubit_pulse_clock, freq=qubit_pulse_frequency)) schedule.add_resource(ClockResource(name=ro_pulse_clock, freq=ro_pulse_frequency)) schedule.add( IdlePulse(duration=init_duration), label="Reset", ) schedule.add( SquarePulse( duration=qubit_pulse_duration, amp=qubit_pulse_amp, port=qubit_pulse_port, clock=qubit_pulse_clock, ), label="qubit_pulse", ) ro_pulse = schedule.add( SquarePulse( duration=ro_pulse_duration, amp=ro_pulse_amp, port=ro_pulse_port, clock=ro_pulse_clock, ), label="readout_pulse", rel_time=ro_pulse_delay, ) schedule.add( Trace( duration=ro_integration_time, port=ro_pulse_port, clock=ro_pulse_clock, acq_index=0, acq_channel=0, ), ref_op=ro_pulse, ref_pt="start", rel_time=ro_acquisition_delay, label="acquisition", ) return schedule
[docs] def long_time_trace( pulse_amp: complex, frequency: float, acquisition_delay: float, integration_time: float, port: str, clock: str, num_points: int, pulse_delay: float = 0, acq_index: int = 0, repetitions: int = 1, ) -> Schedule: """ The function generates a :class:`~Schedule` for a time trace experiment where single side band integration (i.e. ``SSBIntegrationComplex``) is applied repeatedly. Compared to the Trace schedule which returns one point each ns for 16.4 μs (qblox instrument), the long time trace allows the user to customize the integration time and the number of data points in the trace (a minimum of 300 ns (qblox instrument) for the integration time is needed in between two points). The resulting :class:`~Schedule` can be used for quantum experiments involving dynamic processes (charge transition) and time-dependent measurements (Elzerman Readout). Parameters ---------- pulse_amp The amplitude of the pulse in Volt. frequency The frequency of the pulse and of the data acquisition in Hertz. acquisition_delay The start of the data acquisition with respect to the start of the pulse in seconds. integration_time Integration time per point in the trace. A minimum of 300ns is required du to the spacing of acquisition protocols in QbloxInstrument. port The location on the device where the pulse should be applied. clock The reference clock used to track the pulse frequency. num_points Number of points the output long_trace contains. The total time of the long_trace is then nb_pts*integration_time pulse_delay The pulse delay in seconds. acq_index The data register in which the acquisition is stored, by default 0. Describes the "when" information of the measurement, used to label or tag individual measurements in a large circuit. Typically corresponds to the setpoints of a schedule (e.g., tau in a T1 experiment). repetitions The amount of times the Schedule will be repeated. Returns ------- : The custom long Trace acquisition Schedule. """ schedule = Schedule("Long time trace acquisition", repetitions) schedule.add_resource(ClockResource(name=clock, freq=frequency)) pulse_op = VoltageOffset( offset_path_I=np.real(pulse_amp), offset_path_Q=np.imag(pulse_amp), port=port, clock=clock, ) schedule.add(pulse_op) op = SSBIntegrationComplex( port=port, clock=clock, duration=integration_time, acq_channel=0, acq_index=acq_index, bin_mode=BinMode.APPEND, t0=pulse_delay, ) inner = Schedule("inner", repetitions=1) inner.add(op) schedule.add( LoopOperation(body=inner, repetitions=num_points), rel_time=acquisition_delay, ref_pt="start", ) pulse_op_off = VoltageOffset( offset_path_I=0, offset_path_Q=0, port=port, clock=clock, ) # Here rel_time = 4ns have to be add to order properly with the control flow. # Same think Idle pulse has to be added for loops # This has to be removed in a next version. schedule.add(pulse_op_off, rel_time=4e-9) schedule.add(IdlePulse(duration=4e-9)) return schedule
[docs] def long_time_trace_with_qubit( qubit: DeviceElement, num_points: int, acq_index: int = 0, repetitions: int = 1, ) -> Schedule: """ Generate a simple schedule similar to a circuit layer to perform long trace acquisition. Wrapper function for :func:~quantify_scheduler.schedules.long_time_trace to use with a quantum device element.. Parameters ---------- qubit Device Element. num_points Number of points the output custom_long_trace contains. The total time of the custom_long_trace is then nb_pts*integration_time acq_index : The data register in which the acquisition is stored, by default 0. Describes the "when" information of the measurement, used to label or tag individual measurements in a large circuit. Typically corresponds to the setpoints of a schedule (e.g., tau in a T1 experiment). repetitions The amount of times the Schedule will be repeated. Returns ------- : The custom long Trace acquisition Schedule. """ schedule = long_time_trace( pulse_amp=qubit.measure.pulse_amp(), pulse_delay=0, frequency=qubit.clock_freqs.readout(), acquisition_delay=qubit.measure.acq_delay(), integration_time=qubit.measure.integration_time(), port=qubit.ports.readout(), clock=qubit.name + ".ro", num_points=num_points, acq_index=acq_index, repetitions=repetitions, ) return schedule