Deprecated Code Suggestions

See also

Download the notebook: deprecated.ipynb

As of quantify-scheduler==0.10.0, deprecation warnings are shown by default (as FutureWarning).

Compilation Setup

from quantify_core.data import handling as dh
from quantify_core.measurement.control import MeasurementControl
from quantify_scheduler.instrument_coordinator import InstrumentCoordinator
from quantify_scheduler.instrument_coordinator.components.qblox import ClusterComponent

from qblox_instruments import Cluster, ClusterType
from qcodes import Instrument

dh.set_datadir(dh.default_datadir())

Instrument.close_all()
meas_ctrl = MeasurementControl("meas_ctrl")
ic = InstrumentCoordinator("ic")

cluster = Cluster(
    "cluster",
    dummy_cfg={
        1: ClusterType.CLUSTER_QRM_RF,
    },
)

ic_cluster = ClusterComponent(cluster)
ic.add_component(ic_cluster)

# Always picks the first module of a certain type, and ignores the others of same type!
qcm_rf, qrm_rf, qcm, qrm = [None] * 4
for module in cluster.modules:
    try:
        if module.is_rf_type:
            if module.is_qcm_type:
                if qcm_rf is None:
                    qcm_rf = module
            else:
                if qrm_rf is None:
                    qrm_rf = module
        else:
            if module.is_qcm_type:
                if qcm is None:
                    qcm = module
            else:
                if qrm is None:
                    qrm = module
    except KeyError:
        continue

print(f"qcm    => {qcm}\nqrm    => {qrm}\nqcm_rf => {qcm_rf}\nqrm_rf => {qrm_rf}")
Data will be saved in:
/home/rsoko/quantify-data
qcm    => None
qrm    => None
qcm_rf => None
qrm_rf => <QcmQrm: cluster_module1 of Cluster: cluster>
from quantify_scheduler.device_under_test.quantum_device import QuantumDevice
from quantify_scheduler.device_under_test.transmon_element import BasicTransmonElement

q0 = BasicTransmonElement("q0")

quantum_device = QuantumDevice("quantum_device")
quantum_device.add_element(q0)
quantum_device.instr_measurement_control(meas_ctrl.name)
quantum_device.instr_instrument_coordinator(ic.name)

q0.clock_freqs.f01(7.3e9)
q0.clock_freqs.f12(7.0e9)
q0.clock_freqs.readout(8.2e9)
q0.measure.acq_delay(100e-9)
q0.measure.acq_channel(0)
q0.measure.pulse_amp(0.2)

device_cfg = quantum_device.generate_device_config()
hardware_cfg = {
    "backend": "quantify_scheduler.backends.qblox_backend.hardware_compile",
    "cluster": {
        "ref": "internal",
        "instrument_type": "Cluster",
        f"cluster_module{qrm_rf.slot_idx}": {
            "instrument_type": "QRM_RF",
            "complex_output_0": {
                "lo_freq": 2e9,
                "portclock_configs": [
                    {
                        "port": "q0:res",
                        "clock": "q0.ro",
                    },
                ],
            },
        },
    },
}
from quantify_scheduler import Schedule
from quantify_scheduler.operations.gate_library import Measure, Reset
from quantify_scheduler.operations.pulse_library import DRAGPulse
from quantify_scheduler.resources import ClockResource


def simple_trace_sched(
    repetitions: int,
    pulse_amp: float = 0.2, 
) -> Schedule:
    sched = Schedule("Simple trace schedule", repetitions)

    port = "q0:res"
    clock = "q0.ro"

    sched.add(Reset("q0"))
    sched.add(Measure("q0", acq_index=0, acq_protocol="Trace"))
    sched.add(
        DRAGPulse(
            G_amp=pulse_amp,
            D_amp=0,
            phase=0,
            duration=160e-9,
            port=port,
            clock=clock,
        )
    )

    return sched


sched = simple_trace_sched(repetitions=1)

1. acq_channel

In the Measure and CRCount classes, the acq_channel parameter has been removed from the initializers. For gate-level operations, the acquisition channel can be set in the DeviceElement subclasses, such as BasicTransmonElement, instead. See, for example, q0.measure.acq_channel(0) in the Compilation Setup.

2. Qcompile => SerialCompiler

The qcompile, device_compile and hardware_compile compilation functions have been replaced by the SerialCompiler. For step-by-step guides on how to perform compilation to the device level and hardware, please see Compiling to Hardware and Operations and Qubits. A brief example is shown below.

First, run Compilation Setup.

# Old way:
# from quantify_scheduler.compilation import qcompile

# compiled_schedule = qcompile(sched, device_cfg, hardware_cfg)
from quantify_scheduler.backends.graph_compilation import SerialCompiler

quantum_device.hardware_config(hardware_cfg)

compiler = SerialCompiler(name="compiler")
compiled_schedule = compiler.compile(
    schedule=sched, config=quantum_device.generate_compilation_config()
)
compiled_schedule.timing_table
/home/rsoko/.anaconda3/envs/tmp/lib/python3.9/site-packages/quantify_scheduler/schedules/schedule.py:451: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.
  timing_table = pd.concat(timing_table_list, ignore_index=True)
  waveform_op_id port clock is_acquisition abs_time duration operation wf_idx
0 Reset('q0')_acq_0 None cl0.baseband False 0.0 ns 200,000.0 ns Reset('q0') 0
1 Measure('q0', acq_index=0, acq_protocol="Trace", bin_mode=None)_acq_0 None q0.ro False 200,000.0 ns 0.0 ns Measure('q0', acq_index=0, acq_protocol="Trace", bin_mode=None) 0
2 Measure('q0', acq_index=0, acq_protocol="Trace", bin_mode=None)_acq_1 q0:res q0.ro False 200,000.0 ns 300.0 ns Measure('q0', acq_index=0, acq_protocol="Trace", bin_mode=None) 1
3 Measure('q0', acq_index=0, acq_protocol="Trace", bin_mode=None)_acq_0 q0:res q0.ro True 200,100.0 ns 1,000.0 ns Measure('q0', acq_index=0, acq_protocol="Trace", bin_mode=None) 0
4 DRAGPulse(G_amp=0.2,D_amp=0,phase=0,duration=1.6e-07,port='q0:res',clock='q0.ro',reference_magnitude=None,t0=0)_acq_0 q0:res q0.ro False 201,100.0 ns 160.0 ns DRAGPulse(G_amp=0.2,D_amp=0,phase=0,duration=1.6e-07,port='q0:res',clock='q0.ro',reference_magnitude=None,t0=0) 0

3. add_pulse_information_transmon => compile_circuit_to_device

The compilation step add_pulse_information_transmon has been replaced by compile_circuit_to_device. For steps on how to add device configuration to your compilation steps, please see Operations and Qubits.

4. Qblox Hardware Configuration

In quantify-scheduler 0.8.0, the schema for the Qblox hardware configuration was revised. From version 0.13.0, old hardware configurations will no longer be automatically converted. Below is a summary of the changes.

  1. seqx => portclock_configs

  2. latency_correction => standalone/top-level latency_corrections

  3. line_gain_db removed

The code below can be used to convert old-style to new-style hardware configurations. Note that helper function convert_hw_config_to_portclock_configs_spec will be removed in version 0.16.0.

depr_hardware_cfg = {
    "backend": "quantify_scheduler.backends.qblox_backend.hardware_compile",
    "cluster": {
        "ref": "internal",
        "instrument_type": "Cluster",
        "cluster_module1": {
            "instrument_type": "QRM_RF",
            "complex_output_0": {
                "line_gain_db": 0,
                "seq0": {
                    "port": "q6:res",
                    "clock": "q6.ro",
                    "latency_correction": 4e-9,
                },
                "seq1": {
                    "port": "q1:res",
                    "clock": "q1.ro",
                },
            },
        },
    },
}
from quantify_scheduler.backends.qblox.helpers import (
    convert_hw_config_to_portclock_configs_spec,
)

new_hardware_cfg = convert_hw_config_to_portclock_configs_spec(depr_hardware_cfg)


fnc = lambda sub: {
    key1: fnc(val1) if isinstance(val1, dict) else val1
    for key1, val1 in sub.items()
    if key1 != "line_gain_db"
}

new_hardware_cfg = fnc(new_hardware_cfg)
/tmp/ipykernel_23659/2486791990.py:5: FutureWarning: Function quantify_scheduler.backends.qblox.helpers.convert_hw_config_to_portclock_configs_spec() is deprecated and will be removed in quantify-scheduler-0.16.0. `convert_hw_config_to_portclock_configs_spec` will be removed in a future version.
  new_hardware_cfg = convert_hw_config_to_portclock_configs_spec(depr_hardware_cfg)
import json

print(json.dumps(new_hardware_cfg, indent=4))
{
    "backend": "quantify_scheduler.backends.qblox_backend.hardware_compile",
    "cluster": {
        "ref": "internal",
        "instrument_type": "Cluster",
        "cluster_module1": {
            "instrument_type": "QRM_RF",
            "complex_output_0": {
                "portclock_configs": [
                    {
                        "port": "q6:res",
                        "clock": "q6.ro"
                    },
                    {
                        "port": "q1:res",
                        "clock": "q1.ro"
                    }
                ]
            }
        }
    },
    "latency_corrections": {
        "q6:res-q6.ro": 4e-09
    }
}

5. TransmonElement => BasicTransmonElement

In quantify-scheduler 0.7.0, the BasicTransmonElement class was added and replaced the TransmonElement class.

Hide code cell content
from qcodes import Instrument

Instrument.close_all()
# Before:
# from quantify_scheduler.device_under_test.transmon_element import TransmonElement

# transmon = TransmonElement("transmon")
# print(f"{transmon.name}: {list(transmon.parameters.keys())}")

# After:
from quantify_scheduler.device_under_test.transmon_element import BasicTransmonElement

basic = BasicTransmonElement("basic")
print(f"{basic.name}: {list(basic.parameters.keys()) + list(basic.submodules.keys())}")
for submodule_name, submodule in basic.submodules.items():
    print(f"{basic.name}.{submodule_name}: {list(submodule.parameters.keys())}")
basic: ['IDN', 'reset', 'rxy', 'measure', 'ports', 'clock_freqs']
basic.reset: ['duration']
basic.rxy: ['amp180', 'motzoi', 'duration']
basic.measure: ['pulse_type', 'pulse_amp', 'pulse_duration', 'acq_channel', 'acq_delay', 'integration_time', 'reset_clock_phase', 'acq_weights_a', 'acq_weights_b', 'acq_weights_sampling_rate', 'acq_weight_type']
basic.ports: ['microwave', 'flux', 'readout']
basic.clock_freqs: ['f01', 'f12', 'readout']

The block below shows how the attributes of the TransmonElement (transmon) are converted to attributes of the BasicTransmonElement (basic).

transmon.IDN                                         =>    basic.IDN
transmon.instrument_coordinator                      =>    None
transmon.init_duration                               =>    basic.reset.duration
transmon.mw_amp180                                   =>    basic.rxy.amp180
transmon.mw_motzoi                                   =>    basic.rxy.motzoi
transmon.mw_pulse_duration                           =>    basic.rxy.duration
transmon.mw_ef_amp180                                =>    None
transmon.mw_port                                     =>    basic.ports.microwave
transmon.fl_port                                     =>    basic.ports.flux
transmon.ro_port                                     =>    basic.ports.readout
transmon.mw_01_clock                                 =>    no longer settable, always "basic.01"
transmon.mw_12_clock                                 =>    no longer settable, always "basic.12"
transmon.ro_clock                                    =>    no longer settable, always "basic.ro"
transmon.freq_01                                     =>    basic.clock_freqs.f01
transmon.freq_12                                     =>    basic.clock_freqs.f12
transmon.ro_freq                                     =>    basic.clock_freqs.readout
transmon.ro_pulse_amp                                =>    basic.measure.pulse_amp
transmon.ro_pulse_duration                           =>    basic.measure.pulse_duration
transmon.ro_pulse_type                               =>    basic.measure.pulse_type
transmon.ro_pulse_delay                              =>    via:	schedule.add(..., rel_time=...)
transmon.ro_acq_channel                              =>    basic.measure.acq_channel
transmon.ro_acq_delay                                =>    basic.measure.acq_delay
transmon.ro_acq_integration_time                     =>    basic.measure.integration_time
transmon.spec_pulse_duration                         =>    via:	schedule.add(SpectroscopyOperation("basic")), not implemented for BasicTransmonElement, see BasicElectronicNVElement.spectroscopy_operation
transmon.spec_pulse_frequency                        =>    via:	schedule.add(SpectroscopyOperation("basic")), not implemented for BasicTransmonElement, see BasicElectronicNVElement.spectroscopy_operation
transmon.spec_pulse_amp                              =>    via:	schedule.add(SpectroscopyOperation("basic")), not implemented for BasicTransmonElement, see BasicElectronicNVElement.spectroscopy_operation
transmon.spec_pulse_clock                            =>    via:	schedule.add(SpectroscopyOperation("basic")), not implemented for BasicTransmonElement, see BasicElectronicNVElement.spectroscopy_operation
transmon.acquisition                                 =>    via:	schedule.add(Measure("basic", acq_protocol=...))
transmon.ro_acq_weight_type                          =>    basic.measure.acq_weight_type
schedule.add(Measure("transmon", acq_channel=...))   =>    basic.measure.acq_channel

Both classes will generate the same device configuration.

import pprint

# device_config_transmon = transmon.generate_device_config().dict()
# pprint.pprint(device_config_transmon)

device_config_basic_transmon = basic.generate_device_config().dict()
pprint.pprint(device_config_basic_transmon)
{'backend': <function compile_circuit_to_device at 0x7f7d505d3430>,
 'clocks': {'basic.01': nan, 'basic.12': nan, 'basic.ro': nan},
 'edges': {},
 'elements': {'basic': {'Rxy': {'factory_func': <function rxy_drag_pulse at 0x7f7d505e6430>,
                                'factory_kwargs': {'amp180': nan,
                                                   'clock': 'basic.01',
                                                   'duration': 2e-08,
                                                   'motzoi': 0,
                                                   'port': 'basic:mw',
                                                   'reference_magnitude': None},
                                'gate_info_factory_kwargs': ['theta', 'phi']},
                        'measure': {'factory_func': <function dispersive_measurement at 0x7f7d505093a0>,
                                    'factory_kwargs': {'acq_channel': 0,
                                                       'acq_delay': 0,
                                                       'acq_duration': 1e-06,
                                                       'acq_protocol_default': 'SSBIntegrationComplex',
                                                       'acq_weights_a': None,
                                                       'acq_weights_b': None,
                                                       'acq_weights_sampling_rate': None,
                                                       'clock': 'basic.ro',
                                                       'port': 'basic:res',
                                                       'pulse_amp': 0.25,
                                                       'pulse_duration': 3e-07,
                                                       'pulse_type': 'SquarePulse',
                                                       'reference_magnitude': None,
                                                       'reset_clock_phase': True},
                                    'gate_info_factory_kwargs': ['acq_index',
                                                                 'bin_mode',
                                                                 'acq_protocol']},
                        'reset': {'factory_func': <class 'quantify_scheduler.operations.pulse_library.IdlePulse'>,
                                  'factory_kwargs': {'duration': 0.0002},
                                  'gate_info_factory_kwargs': None}}}}

6. Instruction-generated pulses (Qblox only)

Instead of using the instruction_generated_pulses_enabled: True field in the port-clock configuration for generating long square and staircase pulses (see Instruction generated pulses), you can now create long square, staircase and ramp waveforms (that would otherwise not fit in memory), by creating these operations with the following helper functions.

from quantify_scheduler.operations.pulse_factories import (
    long_ramp_pulse,
    long_square_pulse,
    staircase_pulse,
)

ramp_pulse = long_ramp_pulse(amp=0.5, duration=1e-3, port="q0:mw")
square_pulse = long_square_pulse(amp=0.5, duration=1e-3, port="q0:mw")
staircase_pulse = staircase_pulse(
    start_amp=0.0, final_amp=1.0, num_steps=20, duration=1e-4, port="q0:mw"
)

More complex long waveforms can now also be created, see section Long waveform support.