{ "cells": [ { "cell_type": "markdown", "id": "6f4df022", "metadata": {}, "source": [ "# Deprecated Code Suggestions\n", "\n", "```{seealso}\n", "Download the notebook: {nb-download}`deprecated.ipynb`\n", "```\n", "\n", "- {ref}`1. acq_channel`\n", "- {ref}`2. Qcompile => SerialCompiler`\n", "- {ref}`3. add_pulse_information_transmon => compile_circuit_to_device`\n", "- {ref}`4. Qblox Hardware Configuration`\n", "- {ref}`5. TransmonElement => BasicTransmonElement`\n", "- {ref}`6. Instruction-generated pulses (Qblox only)`\n", "\n", "As of `quantify-scheduler==0.10.0`, deprecation warnings are shown by default (as `FutureWarning`).\n", "\n", "## Compilation Setup" ] }, { "cell_type": "code", "execution_count": 1, "id": "e41b456e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Data will be saved in:\n", "/home/rsoko/quantify-data\n", "qcm => None\n", "qrm => None\n", "qcm_rf => None\n", "qrm_rf => \n" ] } ], "source": [ "from quantify_core.data import handling as dh\n", "from quantify_core.measurement.control import MeasurementControl\n", "from quantify_scheduler.instrument_coordinator import InstrumentCoordinator\n", "from quantify_scheduler.instrument_coordinator.components.qblox import ClusterComponent\n", "\n", "from qblox_instruments import Cluster, ClusterType\n", "from qcodes import Instrument\n", "\n", "dh.set_datadir(dh.default_datadir())\n", "\n", "Instrument.close_all()\n", "meas_ctrl = MeasurementControl(\"meas_ctrl\")\n", "ic = InstrumentCoordinator(\"ic\")\n", "\n", "cluster = Cluster(\n", " \"cluster\",\n", " dummy_cfg={\n", " 1: ClusterType.CLUSTER_QRM_RF,\n", " },\n", ")\n", "\n", "ic_cluster = ClusterComponent(cluster)\n", "ic.add_component(ic_cluster)\n", "\n", "# Always picks the first module of a certain type, and ignores the others of same type!\n", "qcm_rf, qrm_rf, qcm, qrm = [None] * 4\n", "for module in cluster.modules:\n", " try:\n", " if module.is_rf_type:\n", " if module.is_qcm_type:\n", " if qcm_rf is None:\n", " qcm_rf = module\n", " else:\n", " if qrm_rf is None:\n", " qrm_rf = module\n", " else:\n", " if module.is_qcm_type:\n", " if qcm is None:\n", " qcm = module\n", " else:\n", " if qrm is None:\n", " qrm = module\n", " except KeyError:\n", " continue\n", "\n", "print(f\"qcm => {qcm}\\nqrm => {qrm}\\nqcm_rf => {qcm_rf}\\nqrm_rf => {qrm_rf}\")" ] }, { "cell_type": "code", "execution_count": 2, "id": "52aaec43", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler.device_under_test.quantum_device import QuantumDevice\n", "from quantify_scheduler.device_under_test.transmon_element import BasicTransmonElement\n", "\n", "q0 = BasicTransmonElement(\"q0\")\n", "\n", "quantum_device = QuantumDevice(\"quantum_device\")\n", "quantum_device.add_element(q0)\n", "quantum_device.instr_measurement_control(meas_ctrl.name)\n", "quantum_device.instr_instrument_coordinator(ic.name)\n", "\n", "q0.clock_freqs.f01(7.3e9)\n", "q0.clock_freqs.f12(7.0e9)\n", "q0.clock_freqs.readout(8.2e9)\n", "q0.measure.acq_delay(100e-9)\n", "q0.measure.acq_channel(0)\n", "q0.measure.pulse_amp(0.2)\n", "\n", "device_cfg = quantum_device.generate_device_config()" ] }, { "cell_type": "code", "execution_count": 3, "id": "2fed3dcf", "metadata": {}, "outputs": [], "source": [ "hardware_cfg = {\n", " \"backend\": \"quantify_scheduler.backends.qblox_backend.hardware_compile\",\n", " \"cluster\": {\n", " \"ref\": \"internal\",\n", " \"instrument_type\": \"Cluster\",\n", " f\"cluster_module{qrm_rf.slot_idx}\": {\n", " \"instrument_type\": \"QRM_RF\",\n", " \"complex_output_0\": {\n", " \"lo_freq\": 2e9,\n", " \"portclock_configs\": [\n", " {\n", " \"port\": \"q0:res\",\n", " \"clock\": \"q0.ro\",\n", " },\n", " ],\n", " },\n", " },\n", " },\n", "}" ] }, { "cell_type": "code", "execution_count": 4, "id": "efd8c8b7", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import Schedule\n", "from quantify_scheduler.operations.gate_library import Measure, Reset\n", "from quantify_scheduler.operations.pulse_library import DRAGPulse\n", "from quantify_scheduler.resources import ClockResource\n", "\n", "\n", "def simple_trace_sched(\n", " repetitions: int,\n", " pulse_amp: float = 0.2, \n", ") -> Schedule:\n", " sched = Schedule(\"Simple trace schedule\", repetitions)\n", "\n", " port = \"q0:res\"\n", " clock = \"q0.ro\"\n", "\n", " sched.add(Reset(\"q0\"))\n", " sched.add(Measure(\"q0\", acq_index=0, acq_protocol=\"Trace\"))\n", " sched.add(\n", " DRAGPulse(\n", " G_amp=pulse_amp,\n", " D_amp=0,\n", " phase=0,\n", " duration=160e-9,\n", " port=port,\n", " clock=clock,\n", " )\n", " )\n", "\n", " return sched\n", "\n", "\n", "sched = simple_trace_sched(repetitions=1)" ] }, { "cell_type": "markdown", "id": "e38d9b1b", "metadata": {}, "source": [ "## 1. acq_channel\n", "\n", "In the {class}`~quantify_scheduler.operations.gate_library.Measure` and {class}`~quantify_scheduler.operations.nv_native_library.CRCount` classes, the `acq_channel` parameter has been removed from the initializers. For gate-level operations, the acquisition channel can be set in the {class}`~quantify_scheduler.device_under_test.device_element.DeviceElement` subclasses, such as {class}`~quantify_scheduler.device_under_test.transmon_element.BasicTransmonElement`, instead. See, for example, `q0.measure.acq_channel(0)` in the {ref}`Compilation Setup`.\n", "\n", "## 2. Qcompile => SerialCompiler\n", "\n", "The `qcompile`, `device_compile` and `hardware_compile` compilation functions have been replaced by the {class}`~quantify_scheduler.backends.graph_compilation.SerialCompiler`. For step-by-step guides on how to perform compilation to the device level and hardware, please see {ref}`Compiling to Hardware` and {ref}`Operations and Qubits`. A brief example is shown below.\n", "\n", "First, run {ref}`Compilation Setup`." ] }, { "cell_type": "code", "execution_count": 5, "id": "ee4dcf84", "metadata": {}, "outputs": [], "source": [ "# Old way:\n", "# from quantify_scheduler.compilation import qcompile\n", "\n", "# compiled_schedule = qcompile(sched, device_cfg, hardware_cfg)" ] }, { "cell_type": "code", "execution_count": 6, "id": "abb73951", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler.backends.graph_compilation import SerialCompiler\n", "\n", "quantum_device.hardware_config(hardware_cfg)\n", "\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(\n", " schedule=sched, config=quantum_device.generate_compilation_config()\n", ")" ] }, { "cell_type": "code", "execution_count": 7, "id": "cb7660c4", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/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.\n", " timing_table = pd.concat(timing_table_list, ignore_index=True)\n" ] }, { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 waveform_op_idportclockis_acquisitionabs_timedurationoperationwf_idx
0Reset('q0')_acq_0Nonecl0.basebandFalse0.0 ns200,000.0 nsReset('q0')0
1Measure('q0', acq_index=0, acq_protocol=\"Trace\", bin_mode=None)_acq_0Noneq0.roFalse200,000.0 ns0.0 nsMeasure('q0', acq_index=0, acq_protocol=\"Trace\", bin_mode=None)0
2Measure('q0', acq_index=0, acq_protocol=\"Trace\", bin_mode=None)_acq_1q0:resq0.roFalse200,000.0 ns300.0 nsMeasure('q0', acq_index=0, acq_protocol=\"Trace\", bin_mode=None)1
3Measure('q0', acq_index=0, acq_protocol=\"Trace\", bin_mode=None)_acq_0q0:resq0.roTrue200,100.0 ns1,000.0 nsMeasure('q0', acq_index=0, acq_protocol=\"Trace\", bin_mode=None)0
4DRAGPulse(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_0q0:resq0.roFalse201,100.0 ns160.0 nsDRAGPulse(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
\n" ], "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "compiled_schedule.timing_table" ] }, { "cell_type": "markdown", "id": "81eebf60", "metadata": {}, "source": [ "## 3. add_pulse_information_transmon => compile_circuit_to_device\n", "\n", "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 {ref}`Operations and Qubits`.\n", "\n", "## 4. Qblox Hardware Configuration\n", "\n", "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.\n", "\n", "1. `seqx` => `portclock_configs` \n", "1. `latency_correction` => standalone/top-level `latency_corrections`\n", "1. `line_gain_db` removed\n", "\n", "The code below can be used to convert old-style to new-style hardware configurations.\n", "Note that helper function `convert_hw_config_to_portclock_configs_spec` will be removed in version 0.16.0." ] }, { "cell_type": "code", "execution_count": 8, "id": "f2ae9c43", "metadata": {}, "outputs": [], "source": [ "depr_hardware_cfg = {\n", " \"backend\": \"quantify_scheduler.backends.qblox_backend.hardware_compile\",\n", " \"cluster\": {\n", " \"ref\": \"internal\",\n", " \"instrument_type\": \"Cluster\",\n", " \"cluster_module1\": {\n", " \"instrument_type\": \"QRM_RF\",\n", " \"complex_output_0\": {\n", " \"line_gain_db\": 0,\n", " \"seq0\": {\n", " \"port\": \"q6:res\",\n", " \"clock\": \"q6.ro\",\n", " \"latency_correction\": 4e-9,\n", " },\n", " \"seq1\": {\n", " \"port\": \"q1:res\",\n", " \"clock\": \"q1.ro\",\n", " },\n", " },\n", " },\n", " },\n", "}" ] }, { "cell_type": "code", "execution_count": 9, "id": "83185ad5", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/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.\n", " new_hardware_cfg = convert_hw_config_to_portclock_configs_spec(depr_hardware_cfg)\n" ] } ], "source": [ "from quantify_scheduler.backends.qblox.helpers import (\n", " convert_hw_config_to_portclock_configs_spec,\n", ")\n", "\n", "new_hardware_cfg = convert_hw_config_to_portclock_configs_spec(depr_hardware_cfg)\n", "\n", "\n", "fnc = lambda sub: {\n", " key1: fnc(val1) if isinstance(val1, dict) else val1\n", " for key1, val1 in sub.items()\n", " if key1 != \"line_gain_db\"\n", "}\n", "\n", "new_hardware_cfg = fnc(new_hardware_cfg)" ] }, { "cell_type": "code", "execution_count": 10, "id": "2166febb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"backend\": \"quantify_scheduler.backends.qblox_backend.hardware_compile\",\n", " \"cluster\": {\n", " \"ref\": \"internal\",\n", " \"instrument_type\": \"Cluster\",\n", " \"cluster_module1\": {\n", " \"instrument_type\": \"QRM_RF\",\n", " \"complex_output_0\": {\n", " \"portclock_configs\": [\n", " {\n", " \"port\": \"q6:res\",\n", " \"clock\": \"q6.ro\"\n", " },\n", " {\n", " \"port\": \"q1:res\",\n", " \"clock\": \"q1.ro\"\n", " }\n", " ]\n", " }\n", " }\n", " },\n", " \"latency_corrections\": {\n", " \"q6:res-q6.ro\": 4e-09\n", " }\n", "}\n" ] } ], "source": [ "import json\n", "\n", "print(json.dumps(new_hardware_cfg, indent=4))" ] }, { "cell_type": "markdown", "id": "2bba8d9a", "metadata": {}, "source": [ "## 5. TransmonElement => BasicTransmonElement\n", "\n", "In quantify-scheduler 0.7.0, the {class}`~quantify_scheduler.device_under_test.transmon_element.BasicTransmonElement` class was added and replaced the `TransmonElement` class." ] }, { "cell_type": "code", "execution_count": 11, "id": "14b78fc5", "metadata": { "tags": [ "hide-cell" ] }, "outputs": [], "source": [ "from qcodes import Instrument\n", "\n", "Instrument.close_all()" ] }, { "cell_type": "code", "execution_count": 12, "id": "8a2e0b81", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "basic: ['IDN', 'reset', 'rxy', 'measure', 'ports', 'clock_freqs']\n", "basic.reset: ['duration']\n", "basic.rxy: ['amp180', 'motzoi', 'duration']\n", "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']\n", "basic.ports: ['microwave', 'flux', 'readout']\n", "basic.clock_freqs: ['f01', 'f12', 'readout']\n" ] } ], "source": [ "# Before:\n", "# from quantify_scheduler.device_under_test.transmon_element import TransmonElement\n", "\n", "# transmon = TransmonElement(\"transmon\")\n", "# print(f\"{transmon.name}: {list(transmon.parameters.keys())}\")\n", "\n", "# After:\n", "from quantify_scheduler.device_under_test.transmon_element import BasicTransmonElement\n", "\n", "basic = BasicTransmonElement(\"basic\")\n", "print(f\"{basic.name}: {list(basic.parameters.keys()) + list(basic.submodules.keys())}\")\n", "for submodule_name, submodule in basic.submodules.items():\n", " print(f\"{basic.name}.{submodule_name}: {list(submodule.parameters.keys())}\")" ] }, { "cell_type": "markdown", "id": "1d226f16", "metadata": {}, "source": [ "The block below shows how the attributes of the `TransmonElement` (`transmon`) are converted to attributes of the `BasicTransmonElement` (`basic`).\n", "\n", "```\n", "transmon.IDN => basic.IDN\n", "transmon.instrument_coordinator => None\n", "transmon.init_duration => basic.reset.duration\n", "transmon.mw_amp180 => basic.rxy.amp180\n", "transmon.mw_motzoi => basic.rxy.motzoi\n", "transmon.mw_pulse_duration => basic.rxy.duration\n", "transmon.mw_ef_amp180 => None\n", "transmon.mw_port => basic.ports.microwave\n", "transmon.fl_port => basic.ports.flux\n", "transmon.ro_port => basic.ports.readout\n", "transmon.mw_01_clock => no longer settable, always \"basic.01\"\n", "transmon.mw_12_clock => no longer settable, always \"basic.12\"\n", "transmon.ro_clock => no longer settable, always \"basic.ro\"\n", "transmon.freq_01 => basic.clock_freqs.f01\n", "transmon.freq_12 => basic.clock_freqs.f12\n", "transmon.ro_freq => basic.clock_freqs.readout\n", "transmon.ro_pulse_amp => basic.measure.pulse_amp\n", "transmon.ro_pulse_duration => basic.measure.pulse_duration\n", "transmon.ro_pulse_type => basic.measure.pulse_type\n", "transmon.ro_pulse_delay => via:\tschedule.add(..., rel_time=...)\n", "transmon.ro_acq_channel => basic.measure.acq_channel\n", "transmon.ro_acq_delay => basic.measure.acq_delay\n", "transmon.ro_acq_integration_time => basic.measure.integration_time\n", "transmon.spec_pulse_duration => via:\tschedule.add(SpectroscopyOperation(\"basic\")), not implemented for BasicTransmonElement, see BasicElectronicNVElement.spectroscopy_operation\n", "transmon.spec_pulse_frequency => via:\tschedule.add(SpectroscopyOperation(\"basic\")), not implemented for BasicTransmonElement, see BasicElectronicNVElement.spectroscopy_operation\n", "transmon.spec_pulse_amp => via:\tschedule.add(SpectroscopyOperation(\"basic\")), not implemented for BasicTransmonElement, see BasicElectronicNVElement.spectroscopy_operation\n", "transmon.spec_pulse_clock => via:\tschedule.add(SpectroscopyOperation(\"basic\")), not implemented for BasicTransmonElement, see BasicElectronicNVElement.spectroscopy_operation\n", "transmon.acquisition => via:\tschedule.add(Measure(\"basic\", acq_protocol=...))\n", "transmon.ro_acq_weight_type => basic.measure.acq_weight_type\n", "schedule.add(Measure(\"transmon\", acq_channel=...)) => basic.measure.acq_channel\n", "```\n", "\n", "Both classes will generate the same device configuration." ] }, { "cell_type": "code", "execution_count": 13, "id": "ee1c582a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'backend': ,\n", " 'clocks': {'basic.01': nan, 'basic.12': nan, 'basic.ro': nan},\n", " 'edges': {},\n", " 'elements': {'basic': {'Rxy': {'factory_func': ,\n", " 'factory_kwargs': {'amp180': nan,\n", " 'clock': 'basic.01',\n", " 'duration': 2e-08,\n", " 'motzoi': 0,\n", " 'port': 'basic:mw',\n", " 'reference_magnitude': None},\n", " 'gate_info_factory_kwargs': ['theta', 'phi']},\n", " 'measure': {'factory_func': ,\n", " 'factory_kwargs': {'acq_channel': 0,\n", " 'acq_delay': 0,\n", " 'acq_duration': 1e-06,\n", " 'acq_protocol_default': 'SSBIntegrationComplex',\n", " 'acq_weights_a': None,\n", " 'acq_weights_b': None,\n", " 'acq_weights_sampling_rate': None,\n", " 'clock': 'basic.ro',\n", " 'port': 'basic:res',\n", " 'pulse_amp': 0.25,\n", " 'pulse_duration': 3e-07,\n", " 'pulse_type': 'SquarePulse',\n", " 'reference_magnitude': None,\n", " 'reset_clock_phase': True},\n", " 'gate_info_factory_kwargs': ['acq_index',\n", " 'bin_mode',\n", " 'acq_protocol']},\n", " 'reset': {'factory_func': ,\n", " 'factory_kwargs': {'duration': 0.0002},\n", " 'gate_info_factory_kwargs': None}}}}\n" ] } ], "source": [ "import pprint\n", "\n", "# device_config_transmon = transmon.generate_device_config().dict()\n", "# pprint.pprint(device_config_transmon)\n", "\n", "device_config_basic_transmon = basic.generate_device_config().dict()\n", "pprint.pprint(device_config_basic_transmon)" ] }, { "cell_type": "markdown", "id": "85569b70", "metadata": {}, "source": [ "## 6. Instruction-generated pulses (Qblox only)\n", "\n", "Instead of using the ``instruction_generated_pulses_enabled: True`` field in the port-clock configuration for generating long square and staircase pulses (see {ref}`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." ] }, { "cell_type": "code", "execution_count": 14, "id": "89c95478", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler.operations.pulse_factories import (\n", " long_ramp_pulse,\n", " long_square_pulse,\n", " staircase_pulse,\n", ")\n", "\n", "ramp_pulse = long_ramp_pulse(amp=0.5, duration=1e-3, port=\"q0:mw\")\n", "square_pulse = long_square_pulse(amp=0.5, duration=1e-3, port=\"q0:mw\")\n", "staircase_pulse = staircase_pulse(\n", " start_amp=0.0, final_amp=1.0, num_steps=20, duration=1e-4, port=\"q0:mw\"\n", ")" ] }, { "cell_type": "markdown", "id": "e01128f9", "metadata": {}, "source": [ "More complex long waveforms can now also be created, see section {ref}`Long waveform support `." ] } ], "metadata": { "file_format": "mystnb", "kernelspec": { "display_name": "python3", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.18" }, "source_map": [ 6, 25, 74, 95, 117, 150, 162, 169, 180, 182, 199, 224, 241, 245, 251, 262, 276, 315, 323, 329, 341 ] }, "nbformat": 4, "nbformat_minor": 5 }