{ "cells": [ { "cell_type": "markdown", "id": "ca86fc35", "metadata": {}, "source": [ "(sec-acquisitions)=\n", "\n", "\n", "# Tutorial: Acquisitions\n", "\n", "```{seealso}\n", "The complete source code of this tutorial can be found in\n", "\n", "{nb-download}`Acquisitions.ipynb`\n", "```\n", "\n", "## Introduction\n", "\n", "In this tutorial we give examples of how to add acquisitions to schedules, and how to retrieve acquisition results using the {class}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator`.\n", "More specifically, this tutorial only describes acquisitions with {class}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator` with Qblox backend with transmon qubits (or Qblox backend with NV center in case of trigger count). See {ref}`sec-tutorial-schedulegettable` for a tutorial on how to perform acquisitions with {class}`~quantify_scheduler.gettables.ScheduleGettable`, and see {ref}`sec-backend-zhinst` for help on how to perform experiments with the Zurich Instruments backend.\n", "\n", "This tutorial assumes you are familiar with compiling schedules and running simple pulses on the Qblox hardware. We also assume, that you have basic familiarity with `xarray` (see [xarray introduction](https://quantify-os.org/docs/quantify-core/dev/dev/design/dataset/Xarray%20introduction.html) and the [official documentation](https://docs.xarray.dev/en/stable/user-guide/data-structures.html)).\n", "\n", "The basic structure of the returned acquisition data is that it is an {class}`xarray.Dataset`, which consists of multiple {class}`xarray.DataArray`. Each of these {class}`xarray.DataArray`s correspond to one acquisition channel.\n", "\n", "Important to note, this tutorial is Qblox-specific with regard to setting up the hardware configuration and setting up the physical wiring for the hardware, but the schedules and protocols and the return data formats are backend independent.\n", "\n", "### Initial setup\n", "\n", "First, we set up the connection to the cluster and hardware configuration." ] }, { "cell_type": "code", "execution_count": 1, "id": "553040ac", "metadata": { "mystnb": { "remove_code_outputs": true } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Data will be saved in:\n", "/root/quantify-data\n" ] } ], "source": [ "from quantify_core.data import handling as dh\n", "dh.set_datadir(dh.default_datadir())" ] }, { "cell_type": "markdown", "id": "da9a6b69", "metadata": {}, "source": [ "In this tutorial we will use the Qblox dummy device, but for real hardware, the ip address can be provided (without the `dummy_cfg` argument)." ] }, { "cell_type": "code", "execution_count": 2, "id": "4c27f9af", "metadata": {}, "outputs": [], "source": [ "from qblox_instruments import Cluster, ClusterType\n", "from quantify_scheduler.qblox import ClusterComponent, start_dummy_cluster_armed_sequencers\n", "\n", "cluster = Cluster(\"cluster0\",\n", " identifier=\"\",\n", " dummy_cfg={1: ClusterType.CLUSTER_QRM},\n", " )\n", "cluster_component = ClusterComponent(cluster)\n", "\n", "# Temporarily fixing dummy cluster's deficiency.\n", "cluster.start_sequencer = lambda : start_dummy_cluster_armed_sequencers(cluster_component)" ] }, { "cell_type": "code", "execution_count": 3, "id": "552d3400", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import BasicTransmonElement, QuantumDevice\n", "\n", "device = QuantumDevice(\"device\")\n", "transmon0 = BasicTransmonElement(\"q0\")\n", "transmon0.clock_freqs.readout(6e9)\n", "transmon0.clock_freqs.f01(5.8e9)\n", "transmon0.rxy.amp180(0.325)\n", "\n", "device.add_element(transmon0)\n", "transmon1 = BasicTransmonElement(\"q1\")\n", "transmon1.clock_freqs.readout(6e9)\n", "device.add_element(transmon1)\n", "device.instr_instrument_coordinator(\"instrument_coordinator\")" ] }, { "cell_type": "code", "execution_count": 4, "id": "39592d80", "metadata": {}, "outputs": [], "source": [ "hardware_config = {\n", " \"version\": \"0.2\",\n", " \"config_type\": \"quantify_scheduler.backends.qblox_backend.QbloxHardwareCompilationConfig\",\n", " \"hardware_description\": {\n", " \"cluster0\": {\n", " \"instrument_type\": \"Cluster\",\n", " \"modules\": {\n", " \"1\": {\n", " \"instrument_type\": \"QRM\"\n", " }\n", " },\n", " \"ref\": \"internal\"\n", " }\n", " },\n", " \"hardware_options\": {\n", " \"modulation_frequencies\": {\n", " \"q0:res-q0.ro\": {\n", " \"interm_freq\": 0\n", " },\n", " \"q1:res-q1.ro\": {\n", " \"interm_freq\": 0\n", " },\n", " \"q0:mw-q0.01\": {\n", " \"interm_freq\": 0\n", " }\n", " }\n", " },\n", " \"connectivity\": {\n", " \"graph\": [\n", " [\"cluster0.module1.complex_output_0\", \"q0:res\"],\n", " [\"cluster0.module1.complex_input_0\", \"q0:res\"],\n", " [\"cluster0.module1.complex_output_0\", \"q1:res\"],\n", " [\"cluster0.module1.complex_output_0\", \"q0:mw\"]\n", " ]\n", " }\n", "}\n", "\n", "device.hardware_config(hardware_config)" ] }, { "cell_type": "markdown", "id": "3e1ccb2b", "metadata": {}, "source": [ "Note here, we used the internal mixer, so `\"interm_freq\"` was set to `0`.\n", "\n", "We set up the {class}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator`, and we will use the cluster component." ] }, { "cell_type": "code", "execution_count": 5, "id": "25ac8136", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import InstrumentCoordinator\n", "instrument_coordinator = InstrumentCoordinator(\"instrument_coordinator\")" ] }, { "cell_type": "code", "execution_count": 6, "id": "ae8c0f17", "metadata": {}, "outputs": [], "source": [ "instrument_coordinator.add_component(cluster_component)" ] }, { "cell_type": "markdown", "id": "1199aabb", "metadata": {}, "source": [ "## Pulse-level acquisitions\n", "\n", "Pulse-level acquisitions define when and how to store and retrieve input signals coming from the device. They are described by their timing information (start time and length), protocol, `acq_channel` and `acq_index_`.\n", "\n", "* Timing information specifies when the acquisition happens on the schedule,\n", "* protocol defines which common hardware and software formatting is done on the input signal.\n", "* `acq_channel` and `acq_index_` together identify each acquisition for the user in the returned dataset.\n", "\n", "In the following subsections we give examples for each supported acquisition protocol.\n", "\n", "We assume, that these tutorials are run on a Qblox QRM cluster module. On the QRM module {math}`\\text{O}^{[1]}` is connected to {math}`\\text{I}^{[1]}` and {math}`\\text{O}^{[2]}` is connected to {math}`\\text{I}^{[2]}`.\n", "\n", "It takes some time before the sent-out signal appears on the input of the QRM, this is the `time_of_flight`." ] }, { "cell_type": "code", "execution_count": 7, "id": "e0a2504e", "metadata": {}, "outputs": [], "source": [ "time_of_flight = 148e-9" ] }, { "cell_type": "markdown", "id": "cede2d39", "metadata": {}, "source": [ "### Trace acquisition\n", "\n", "One of the simplest protocols is the trace (or scope) acquisition protocol. With this protocol, you can retrieve the input signal in very small timesteps (on nanosecond timescale) for a relatively long time (on microsecond timescale). In this subsection we will send out a DRAG pulse on the output, then measure it with the input of the QRM, and plot the retrieved data. The exact duration of the acquisition and sample times depend on the hardware.\n", "\n", "#### Setting up the schedule\n", "\n", "Let's define the duration of the DRAG pulse using the parameter `pulse_duration`. We define a separate parameter `acq_duration`, allowing the acquisition duration to be larger than the duration of the pulse\n", "(e.g., in case the `time_of_flight` was not yet calibrated)." ] }, { "cell_type": "code", "execution_count": 8, "id": "87496c4a", "metadata": {}, "outputs": [], "source": [ "pulse_duration = 1e-6\n", "acq_duration = pulse_duration" ] }, { "cell_type": "markdown", "id": "f59f3039", "metadata": {}, "source": [ "The schedule is very simple, we transmit the pulse and then we start the trace acquisition which occurs `time_of_flight` seconds after the pulse." ] }, { "cell_type": "code", "execution_count": 9, "id": "42ad59b5", "metadata": { "mystnb": { "remove_code_outputs": true } }, "outputs": [ { "data": { "text/plain": [ "{'name': 'cb7d9bbc-31ee-46b6-97c9-182b0440d36c', 'operation_id': '-4122171037765324125', 'timing_constraints': [{'rel_time': 1.48e-07, 'ref_schedulable': None, 'ref_pt_new': None, 'ref_pt': 'start'}], 'label': 'cb7d9bbc-31ee-46b6-97c9-182b0440d36c'}" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from quantify_scheduler import Schedule\n", "from quantify_scheduler.operations import IdlePulse, DRAGPulse, Trace\n", "\n", "schedule = Schedule(\"trace_acquisition_tutorial\")\n", "schedule.add(IdlePulse(duration=1e-6))\n", "\n", "schedule.add(\n", " DRAGPulse(\n", " G_amp=0.2,\n", " D_amp=0.2,\n", " duration=pulse_duration,\n", " phase=0,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " ),\n", ")\n", "schedule.add(\n", " Trace(\n", " duration=acq_duration,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " acq_channel=0,\n", " acq_index=0,\n", " ),\n", " ref_pt=\"start\",\n", " rel_time=time_of_flight\n", ")" ] }, { "cell_type": "code", "execution_count": 10, "id": "31c04a66", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "from qblox_instruments import DummyBinnedAcquisitionData, DummyScopeAcquisitionData\n", "import numpy as np\n", "from quantify_scheduler.waveforms import drag\n", "\n", "def drag_pulse_waveform():\n", " duration=1e-6\n", " t = np.arange(0, duration, 1e-9)\n", " wave = drag(t=t, G_amp=0.1, D_amp=0.1, duration=duration, nr_sigma=4)\n", "\n", " return [ (wave[i].real, wave[i].imag) for i in range(len(t)) ]\n", "\n", "dummy_slot_idx = 1\n", "dummy_scope_acquisition_data = DummyScopeAcquisitionData(\n", " data=drag_pulse_waveform(), out_of_range=(False, False), avg_cnt=(0, 0)\n", ")\n", "\n", "cluster.set_dummy_scope_acquisition_data(\n", " slot_idx=dummy_slot_idx,\n", " sequencer=None,\n", " data=dummy_scope_acquisition_data\n", ")" ] }, { "cell_type": "markdown", "id": "84ff7702", "metadata": {}, "source": [ "Let's compile the schedule." ] }, { "cell_type": "code", "execution_count": 11, "id": "3732d506", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import SerialCompiler\n", "\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(schedule=schedule, config=device.generate_compilation_config())" ] }, { "cell_type": "markdown", "id": "1605478b", "metadata": {}, "source": [ "#### Running the schedule, retrieving acquisition\n", "\n", "The compiled schedule can be run, and the acquisitions can be retrieved with the {func}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator.retrieve_acquisition` function." ] }, { "cell_type": "code", "execution_count": 12, "id": "fbbf8a55", "metadata": {}, "outputs": [], "source": [ "instrument_coordinator.prepare(compiled_schedule)\n", "instrument_coordinator.start()\n", "instrument_coordinator.wait_done(timeout_sec=10)\n", "\n", "acquisition = instrument_coordinator.retrieve_acquisition()" ] }, { "cell_type": "code", "execution_count": 13, "id": "fbd2d18d", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 24kB\n",
       "Dimensions:        (acq_index_0: 1, trace_index_0: 1000)\n",
       "Coordinates:\n",
       "  * acq_index_0    (acq_index_0) int64 8B 0\n",
       "  * trace_index_0  (trace_index_0) int64 8kB 0 1 2 3 4 5 ... 995 996 997 998 999\n",
       "Data variables:\n",
       "    0              (acq_index_0, trace_index_0) complex128 16kB 0j 0j ... 0j 0j
" ], "text/plain": [ " Size: 24kB\n", "Dimensions: (acq_index_0: 1, trace_index_0: 1000)\n", "Coordinates:\n", " * acq_index_0 (acq_index_0) int64 8B 0\n", " * trace_index_0 (trace_index_0) int64 8kB 0 1 2 3 4 5 ... 995 996 997 998 999\n", "Data variables:\n", " 0 (acq_index_0, trace_index_0) complex128 16kB 0j 0j ... 0j 0j" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "acquisition" ] }, { "cell_type": "markdown", "id": "496e16ce", "metadata": {}, "source": [ "The acquisition data is stored as an {class}`xarray.Dataset`. While it typically consists of multiple {class}`xarray.DataArray`s, this particular dataset contains only one {class}`xarray.DataArray`. This array corresponds to `acq_channel=0` as that was the only acquisition channel we used. Each `acq_index_` value represents a 1 ns measurement, given that the Qblox backend employs a trace acquisition with a granularity of 1 ns. The real and imaginary parts of the data correspond to the I and Q components, respectively.\n", "\n", "We can also plot these results with the following commands. Notice, that because the data is an {class}`xarray.Dataset`, it's very easy to plot and format the data. We only ran the schedule once, so `repetition=0`." ] }, { "cell_type": "code", "execution_count": 14, "id": "d2c662b9", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "\n", "fig, axs = plt.subplots(1)\n", "\n", "acquisition[0].real.plot(ax=axs, label=\"I\")\n", "acquisition[0].imag.plot(ax=axs, label=\"Q\")\n", "\n", "axs.set_title(\"\")\n", "axs.set_ylabel(\"\")\n", "axs.legend()\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "26adf41f", "metadata": {}, "source": [ "(sec-ssb)=\n", "### Single-sideband integration acquisition\n", "\n", "The single-sideband integration protocol involves integrating the complex input signal over a given time period. The integration weight is a square window, and this window's length is the same as the acquisition length. The signal is demodulated using the specified clock before the integration happens.\n", "\n", "In this tutorial, we will send 4 square pulses out, and measure it in 4 separate bins, indexed by all combinations of `acq_channel=0,1` and `acq_index_=0,1`. We will also send out purely real and imaginary pulses (or purely I and purely Q pulses), and observe that they appear as real and imaginary acquisitions. In the case of single-sideband integration the integration happens after demodulation.\n", "\n", "\n", "Typically, different acquisition channels are usually set up to refer to different qubits. However, in our simple example, we only use a single qubit port-clock combination for both acquisition channels.\n", "\n", "#### Setting up the schedule\n", "\n", "Let's define how much time the pulse takes with `pulse_duration`. We define a separate parameter `acq_duration`, allowing the integration time to be larger than the duration of the pulse\n", "(e.g., in case the `time_of_flight` was not yet calibrated)." ] }, { "cell_type": "code", "execution_count": 15, "id": "23b5cfd7", "metadata": {}, "outputs": [], "source": [ "pulse_duration = 120e-9\n", "acq_duration = pulse_duration" ] }, { "cell_type": "markdown", "id": "0d956b14", "metadata": {}, "source": [ "We define a simple helper function that sends out the square pulse with `pulse_level` complex amplitude, and then measures it after `time_of_flight` seconds." ] }, { "cell_type": "code", "execution_count": 16, "id": "8a50cfe6", "metadata": { "mystnb": { "remove_code_outputs": true } }, "outputs": [], "source": [ "from quantify_scheduler import Schedule\n", "from quantify_scheduler.operations import IdlePulse, SquarePulse, SSBIntegrationComplex\n", "from quantify_scheduler.enums import BinMode\n", "\n", "schedule = Schedule(\"ssb_acquisition_tutorial\")\n", "schedule.add(IdlePulse(duration=1e-6))\n", "\n", "def pulse_and_acquisition(pulse_level, acq_channel, acq_index, schedule, bin_mode=BinMode.AVERAGE):\n", " schedule.add(\n", " SquarePulse(\n", " duration=pulse_duration,\n", " amp=pulse_level,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " ),\n", " ref_pt=\"end\",\n", " rel_time=1e-6, # Idle time before the pulse is played\n", " )\n", " schedule.add(\n", " SSBIntegrationComplex(\n", " duration=acq_duration,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " acq_channel=acq_channel,\n", " acq_index=acq_index,\n", " bin_mode=bin_mode,\n", " ),\n", " ref_pt=\"start\",\n", " rel_time=time_of_flight\n", " )\n", "\n", "pulse_and_acquisition(pulse_level=0.125, acq_channel=0, acq_index=0, schedule=schedule)\n", "pulse_and_acquisition(pulse_level=0.125j, acq_channel=0, acq_index=1, schedule=schedule)\n", "pulse_and_acquisition(pulse_level=0.25, acq_channel=1, acq_index=0, schedule=schedule)\n", "pulse_and_acquisition(pulse_level=0.25j, acq_channel=1, acq_index=1, schedule=schedule)" ] }, { "cell_type": "markdown", "id": "b2989b10", "metadata": {}, "source": [ "Notice, that the amplitude is double in the case of `acq_channel=1` compared to `acq_channel=0`. Also, the amplitude is complex: in case `acq_index_=0` the amplitude is real, and in case `acq_index_=1` the amplitude is imaginary." ] }, { "cell_type": "code", "execution_count": 17, "id": "1295a4d9", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "from qblox_instruments import DummyBinnedAcquisitionData, DummyScopeAcquisitionData\n", "\n", "dummy_slot_idx = 1\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0)\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=1)\n", "dummy_data_0 = [\n", " DummyBinnedAcquisitionData(data=(16, 0), thres=0, avg_cnt=0),\n", " DummyBinnedAcquisitionData(data=(0, 16), thres=0, avg_cnt=0),\n", "]\n", "cluster.set_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0, acq_index_name=\"0\", data=dummy_data_0)\n", "dummy_data_1 = [\n", " DummyBinnedAcquisitionData(data=(32, 0), thres=0, avg_cnt=0),\n", " DummyBinnedAcquisitionData(data=(0, 32), thres=0, avg_cnt=0),\n", "]\n", "cluster.set_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0, acq_index_name=\"1\", data=dummy_data_1)" ] }, { "cell_type": "markdown", "id": "2a235b34", "metadata": {}, "source": [ "Let's compile the schedule." ] }, { "cell_type": "code", "execution_count": 18, "id": "64c35396", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import SerialCompiler\n", "\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(schedule=schedule, config=device.generate_compilation_config())" ] }, { "cell_type": "markdown", "id": "0274554d", "metadata": {}, "source": [ "#### Running the schedule, retrieving acquisition\n", "\n", "Let's run the schedule, and retrieve the acquisitions." ] }, { "cell_type": "code", "execution_count": 19, "id": "f5fb7df5", "metadata": {}, "outputs": [], "source": [ "instrument_coordinator.prepare(compiled_schedule)\n", "instrument_coordinator.start()\n", "instrument_coordinator.wait_done(timeout_sec=10)\n", "\n", "acquisition = instrument_coordinator.retrieve_acquisition()" ] }, { "cell_type": "code", "execution_count": 20, "id": "0447585e", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 96B\n",
       "Dimensions:      (acq_index_0: 2, acq_index_1: 2)\n",
       "Coordinates:\n",
       "  * acq_index_0  (acq_index_0) int64 16B 0 1\n",
       "  * acq_index_1  (acq_index_1) int64 16B 0 1\n",
       "Data variables:\n",
       "    0            (acq_index_0) complex128 32B (0.13333333333333333+0j) 0.1333...\n",
       "    1            (acq_index_1) complex128 32B (0.26666666666666666+0j) 0.2666...
" ], "text/plain": [ " Size: 96B\n", "Dimensions: (acq_index_0: 2, acq_index_1: 2)\n", "Coordinates:\n", " * acq_index_0 (acq_index_0) int64 16B 0 1\n", " * acq_index_1 (acq_index_1) int64 16B 0 1\n", "Data variables:\n", " 0 (acq_index_0) complex128 32B (0.13333333333333333+0j) 0.1333...\n", " 1 (acq_index_1) complex128 32B (0.26666666666666666+0j) 0.2666..." ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "acquisition" ] }, { "cell_type": "markdown", "id": "2836bea0", "metadata": {}, "source": [ "There are now two {class}`xarray.DataArray`s in this {class}`xarray.Dataset`. These correspond to `acq_channel=0` and `acq_channel=1`. Both of these `DataArrays` have the following two dimensions: `acq_index_` and `repetition`. Because the schedule was run only once, `repetition=0` for all values.\n", "\n", "As expected, the single side band integration produced a single complex number in each bin. One purely real value in `acq_index_=0` and one purely imaginary value in `acq_index_=1`. Notice how these values are twice as much for `acq_index_=1` as compared to those for `acq_index_=0`.\n", "\n", "#### Bin modes and repetitions\n", "\n", "`quantify-scheduler` offers two kinds of bin modes, that deal with repeated schedules:\n", "\n", "- **Average** bin mode: Enables repeated measurements and averaging for reduced errors.\n", "- **Append** bin mode: Allows repeating measurements and retrieving data for each repetition individually.\n", "\n", "```{note}\n", "`QuantumDevice.cfg_sched_repetitions` has no effect in running via {class}`~quantify_scheduler.instrument_coordinator.instrument_coordinator.InstrumentCoordinator` directly;\n", "it only has effect when using {class}`~quantify_scheduler.gettables.ScheduleGettable` (also see {ref}`Tutorial: ScheduleGettable `).\n", "```\n", "\n", "```{note}\n", "Important: Mixing bin modes is not allowed, all bin modes must be the same for each acquisition in one schedule.\n", "```\n", "\n", "To determine the number of times you want `quantify-scheduler` to execute the schedule, you can set the `repetitions` argument or attribute for the `Schedule` object. By specifying a value for `repetitions`, you can control the number of times the schedule will run. For example, if you set `repetitions` to `8`, the following code snippet demonstrates a schedule that would execute eight times:\n", "\n", "```{code-block} ipython3\n", "schedule = Schedule(\"Repeated schedule\", repetitions=8)\n", "```\n", "\n", "##### Average bin mode\n", "\n", "To specify which bin mode you would like to use, set the `bin_mode` argument for each acquisition operation. By default, they are set to `BinMode.AVERAGE`.\n", "\n", "```{code-block} ipython3\n", "from quantify_scheduler.enums import BinMode\n", "\n", "schedule.add(\n", " SSBIntegrationComplex(\n", " duration=acq_duration,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " acq_channel=acq_channel,\n", " acq_index=acq_index,\n", " bin_mode=BinMode.AVERAGE,\n", " )\n", ")\n", "```\n", "\n", "```{note}\n", "Trace acquisitions only work with average bin mode. Integration-type acquisitions can be used with append bin mode too.\n", "```\n", "\n", "##### Append bin mode\n", "\n", "Let's create a schedule which is run 3 times in a row in append mode." ] }, { "cell_type": "code", "execution_count": 21, "id": "b2aac5e3", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import Schedule\n", "from quantify_scheduler.operations import IdlePulse, SquarePulse, SSBIntegrationComplex\n", "from quantify_scheduler.enums import BinMode\n", "\n", "schedule = Schedule(\"append_tutorial\", repetitions=3)\n", "schedule.add(IdlePulse(duration=1e-6))\n", "\n", "pulse_and_acquisition(pulse_level=0.125, acq_channel=0, acq_index=0, schedule=schedule, bin_mode=BinMode.APPEND)\n", "pulse_and_acquisition(pulse_level=0.25, acq_channel=0, acq_index=1, schedule=schedule, bin_mode=BinMode.APPEND)" ] }, { "cell_type": "code", "execution_count": 22, "id": "73e312f3", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "from qblox_instruments import DummyBinnedAcquisitionData, DummyScopeAcquisitionData\n", "\n", "dummy_slot_idx = 1\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0)\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=1)\n", "dummy_data_0 = [\n", " DummyBinnedAcquisitionData(data=(16, 0), thres=0, avg_cnt=0),\n", " DummyBinnedAcquisitionData(data=(32, 0), thres=0, avg_cnt=0),\n", "] * 3\n", "cluster.set_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0, acq_index_name=\"0\", data=dummy_data_0)" ] }, { "cell_type": "markdown", "id": "5e610b6c", "metadata": {}, "source": [ "Let's compile the schedule." ] }, { "cell_type": "code", "execution_count": 23, "id": "a43510d3", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import SerialCompiler\n", "\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(schedule=schedule, config=device.generate_compilation_config())" ] }, { "cell_type": "markdown", "id": "3cb56349", "metadata": {}, "source": [ "And retrieve the acquisitions" ] }, { "cell_type": "code", "execution_count": 24, "id": "5126b838", "metadata": {}, "outputs": [], "source": [ "instrument_coordinator.prepare(compiled_schedule)\n", "instrument_coordinator.start()\n", "instrument_coordinator.wait_done(timeout_sec=10)\n", "\n", "acquisition = instrument_coordinator.retrieve_acquisition()" ] }, { "cell_type": "code", "execution_count": 25, "id": "24841ec4", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 112B\n",
       "Dimensions:      (acq_index_0: 2, repetition: 3)\n",
       "Coordinates:\n",
       "  * acq_index_0  (acq_index_0) int64 16B 0 1\n",
       "Dimensions without coordinates: repetition\n",
       "Data variables:\n",
       "    0            (repetition, acq_index_0) complex128 96B (0.1333333333333333...
" ], "text/plain": [ " Size: 112B\n", "Dimensions: (acq_index_0: 2, repetition: 3)\n", "Coordinates:\n", " * acq_index_0 (acq_index_0) int64 16B 0 1\n", "Dimensions without coordinates: repetition\n", "Data variables:\n", " 0 (repetition, acq_index_0) complex128 96B (0.1333333333333333..." ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "acquisition" ] }, { "cell_type": "markdown", "id": "c95b020e", "metadata": {}, "source": [ "Notice, that now we have `3*2` acquisition values, as expected: with 3 repetitions, and for each repetition 2 acquisitions. Let's select the values for the second run." ] }, { "cell_type": "code", "execution_count": 26, "id": "328cdd34", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.DataArray 0 (acq_index_0: 2)> Size: 32B\n",
       "array([0.13333333+0.j, 0.26666667+0.j])\n",
       "Coordinates:\n",
       "  * acq_index_0  (acq_index_0) int64 16B 0 1\n",
       "Attributes:\n",
       "    acq_protocol:  SSBIntegrationComplex
" ], "text/plain": [ " Size: 32B\n", "array([0.13333333+0.j, 0.26666667+0.j])\n", "Coordinates:\n", " * acq_index_0 (acq_index_0) int64 16B 0 1\n", "Attributes:\n", " acq_protocol: SSBIntegrationComplex" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "acquisition[0].sel(repetition=1)" ] }, { "cell_type": "markdown", "id": "bad76202", "metadata": {}, "source": [ "As expected, it has only two values, and the value of `acq_index_=1` is double that of `acq_index_=0`.\n", "\n", "(sec-weighted-ssb)=\n", "### Weighted single-sideband integration acquisition\n", "\n", "_Weighted_ single-sideband (SBB) integration works almost the same as regular SSB integration. In weighted SSB integration, the acquired (demodulated) data points are multiplied together with points of a _weight_ waveform. The relevant acquisition class is {class}`~quantify_scheduler.operations.acquisition_library.NumericalSeparatedWeightedIntegration`.\n", "\n", "The weights can be provided in the form of two numerical arrays, `weights_a` for the I-path and `weights_b` for the Q-path of the acquisition signal, together with the sampling rate (`weights_sampling_rate`) of these arrays. The `quantify-scheduler` hardware backends will resample the weights if needed to match the hardware sampling rate. Note that the length of the weights arrays determines the integration time of the acquisition. All values in the weight arrays must be in the range `[-1, 1]`.\n", "\n", "As an example, we create a simple schedule using weighted integration below. The setup is the same as in the {ref}`sec-ssb` section. To show the effect of weighted integration, we will measure a square pulse three times with different weights:\n", "\n", "* an array with all values `1.0` (which is the same as a normal SSB integration),\n", "* an array with all values `0.5`,\n", "* a sine function with amplitude `1.0` and an average of `0.0`." ] }, { "cell_type": "code", "execution_count": 27, "id": "27585b0e", "metadata": { "mystnb": { "remove_code_outputs": true } }, "outputs": [ { "data": { "text/plain": [ "Schedule \"weighted_acquisition_tutorial\" containing (5) 7 (unique) operations." ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from quantify_scheduler.operations import NumericalSeparatedWeightedIntegration\n", "\n", "\n", "schedule = Schedule(\"weighted_acquisition_tutorial\")\n", "schedule.add(IdlePulse(duration=1e-6))\n", "\n", "\n", "def add_pulse_and_weighted_acquisition_to_schedule(\n", " weights_a,\n", " weights_b,\n", " acq_index,\n", " schedule,\n", " acq_channel=0,\n", " weights_sampling_rate=1e9,\n", " bin_mode=BinMode.APPEND,\n", "):\n", " schedule.add(\n", " SquarePulse(\n", " duration=1e-6,\n", " amp=0.5,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " ),\n", " ref_pt=\"end\",\n", " rel_time=1e-6, # Idle time before the pulse is played\n", " )\n", " schedule.add(\n", " NumericalSeparatedWeightedIntegration(\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " weights_a=weights_a,\n", " weights_b=weights_b,\n", " weights_sampling_rate=weights_sampling_rate,\n", " acq_channel=acq_channel,\n", " acq_index=acq_index,\n", " bin_mode=bin_mode,\n", " ),\n", " ref_pt=\"start\",\n", " rel_time=time_of_flight,\n", " )\n", " return schedule\n", "\n", "\n", "square_weights = np.ones(1000)\n", "add_pulse_and_weighted_acquisition_to_schedule(\n", " weights_a=square_weights,\n", " weights_b=square_weights,\n", " weights_sampling_rate=1e9,\n", " acq_channel=0,\n", " acq_index=0,\n", " schedule=schedule,\n", ")\n", "\n", "half_value_weights = square_weights / 2\n", "add_pulse_and_weighted_acquisition_to_schedule(\n", " weights_a=half_value_weights,\n", " weights_b=square_weights,\n", " acq_index=1,\n", " schedule=schedule,\n", ")\n", "\n", "sine_weights = np.sin(2 * np.pi * np.linspace(0, 1, 1000))\n", "add_pulse_and_weighted_acquisition_to_schedule(\n", " weights_a=sine_weights,\n", " weights_b=square_weights,\n", " acq_index=2,\n", " schedule=schedule,\n", ")" ] }, { "cell_type": "markdown", "id": "d7902acb", "metadata": {}, "source": [ "Note that the lengths of the arrays are all 1000. With the specified sampling rate, this corresponds to an acquisition duration of 1 μs." ] }, { "cell_type": "code", "execution_count": 28, "id": "c36a1a86", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "dummy_slot_idx = 1\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0)\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=1)\n", "dummy_data_0 = [\n", " DummyBinnedAcquisitionData(data=(0.5, 0), thres=0, avg_cnt=0),\n", " DummyBinnedAcquisitionData(data=(0.25, 0), thres=0, avg_cnt=0),\n", " DummyBinnedAcquisitionData(data=(0, 0), thres=0, avg_cnt=0),\n", "]\n", "cluster.set_dummy_binned_acquisition_data(\n", " slot_idx=dummy_slot_idx, sequencer=0, acq_index_name=\"0\", data=dummy_data_0\n", ")" ] }, { "cell_type": "markdown", "id": "a115deaf", "metadata": {}, "source": [ "Let's compile the schedule." ] }, { "cell_type": "code", "execution_count": 29, "id": "07354d59", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import SerialCompiler\n", "\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(\n", " schedule=schedule, config=device.generate_compilation_config()\n", ")" ] }, { "cell_type": "markdown", "id": "ed773bc5", "metadata": {}, "source": [ "And retrieve the acquisitions" ] }, { "cell_type": "code", "execution_count": 30, "id": "0ced73fb", "metadata": {}, "outputs": [], "source": [ "instrument_coordinator.prepare(compiled_schedule)\n", "instrument_coordinator.start()\n", "instrument_coordinator.wait_done(timeout_sec=10)\n", "\n", "acquisition = instrument_coordinator.retrieve_acquisition()" ] }, { "cell_type": "code", "execution_count": 31, "id": "79751fab", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 72B\n",
       "Dimensions:      (acq_index_0: 3, repetition: 1)\n",
       "Coordinates:\n",
       "  * acq_index_0  (acq_index_0) int64 24B 0 1 2\n",
       "Dimensions without coordinates: repetition\n",
       "Data variables:\n",
       "    0            (repetition, acq_index_0) complex128 48B (0.4999998806742098...
" ], "text/plain": [ " Size: 72B\n", "Dimensions: (acq_index_0: 3, repetition: 1)\n", "Coordinates:\n", " * acq_index_0 (acq_index_0) int64 24B 0 1 2\n", "Dimensions without coordinates: repetition\n", "Data variables:\n", " 0 (repetition, acq_index_0) complex128 48B (0.4999998806742098..." ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "acquisition" ] }, { "cell_type": "markdown", "id": "2e9bddba", "metadata": {}, "source": [ "The data set contains three data points corresponding to the acquisitions we scheduled. The first acquisition with the maximum amplitude (1.0) square weights shows the highest voltage, the second one with the weights halved also shows half the voltage. The third, corresponding to the sinusoidal weights with an average of 0, shows 0 as expected.\n", "\n", "As a final note, weighted integration can also be scheduled at the {ref}`gate-level ` by specifying `\"NumericalSeparatedWeightedIntegration\"` as the acquisition protocol and providing the weights in the quantum device element {attr}`.BasicTransmonElement.measure`, for example:\n", "\n", "```\n", ".measure.acq_weights_a(sine_weights)\n", ".measure.acq_weights_b(square_weights)\n", "```\n", "\n", "(thresholded_acquisition_explanation)=\n", "### Thresholded acquisition\n", "With thresholded acquisition, we can map a complex input signal to either a 0 or a 1, by comparing the data to a threshold value. It is similar to the {ref}`single-sideband integration protocol ` described above, but after integration the I-Q data points are first rotated by an angle and then compared to a threshold value to assign the results to either a \"0\" or to a \"1\". See the illustration below.\n", "\n", "```{figure} /images/thresholded_acquisition_explanation.svg\n", ":align: center\n", "\n", "Illustration of the acquisition threshold.\n", "```\n", "\n", "Here the threshold line is controlled by the qubit settings: `acq_rotation` and `acq_threshold`. By default (left figure) we have `acq_rotation=0` and `acq_threshold=0`, where every measured (integrated) data point with I<0 is assigned the state \"0\", and the remaining data points are assigned the state \"1\". The first setting, `acq_rotation`, rotates the threshold line by an angle in degrees (0 - 360), clockwise. The second setting, `acq_threshold`, sets the threshold that is compared to the rotated integrated acquisition result.\n", "\n", "```{admonition} Note\n", "Thresholded acquisition is currently only supported by the Qblox backend.\n", "\n", "The `qblox-instruments` parameter `thresholded_acq_threshold` corresponds to a voltage obtained from an integrated acquisition, **before** normalizing with respect to the integration time.\n", "The `quantify-scheduler` parameter `acq_threshold` corresponds to an acquired voltage **after** normalizing with respect to the integration time (e.g. as obtained from a single side band integration).\n", "```\n", "\n", "#### Setting up the schedule\n", "\n", "Let's imagine a simple experiment where we prepare a qubit in the ground state, apply a {math}`\\pi`-rotation and then measure the outcome.\n", "This experiment is then repeated 200 times. The corresponding schedule would look like:" ] }, { "cell_type": "code", "execution_count": 32, "id": "38bcfc6b", "metadata": { "tags": [ "remove-output" ] }, "outputs": [ { "data": { "text/plain": [ "{'name': '4cdd2f5c-32fd-48c4-8034-423d7c8ba864', 'operation_id': '-3861825782012414120', 'timing_constraints': [{'rel_time': 1.48e-07, 'ref_schedulable': None, 'ref_pt_new': None, 'ref_pt': 'start'}], 'label': '4cdd2f5c-32fd-48c4-8034-423d7c8ba864'}" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from quantify_scheduler.operations import Reset, X\n", "\n", "pulse_duration = 1e-6\n", "acq_duration = pulse_duration\n", "pulse_level = 0.25\n", "\n", "schedule = Schedule(\"ssb_acquisition\", repetitions=200)\n", "\n", "schedule.add(Reset(\"q0\"))\n", "schedule.add(X(\"q0\"))\n", "\n", "schedule.add(\n", " SquarePulse(\n", " duration=pulse_duration,\n", " amp=pulse_level,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " ),\n", " ref_pt=\"end\",\n", " rel_time=1e-6, # Idle time before the pulse is played\n", ")\n", "schedule.add(\n", " SSBIntegrationComplex(\n", " duration=acq_duration,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " acq_channel=0,\n", " acq_index=0,\n", " bin_mode=BinMode.APPEND,\n", " ),\n", " ref_pt=\"start\",\n", " rel_time=time_of_flight\n", ")" ] }, { "cell_type": "code", "execution_count": 33, "id": "c5c69723", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "from scipy.stats import norm\n", "import numpy as np\n", "np.random.seed(0)\n", "\n", "x = 0.1 + 0.03j\n", "y = -0.15 - 0.1j\n", "s = 0.03\n", "\n", "i = np.concatenate(\n", " (norm.rvs(np.real(x), s, 100),\n", " norm.rvs(np.real(y), s, 100))\n", ")\n", "q = np.concatenate((\n", " norm.rvs(np.imag(x), s, 100),\n", " norm.rvs(np.imag(y), s, 100)\n", "))\n", "\n", "b = -np.real(y-x)/np.imag(y-x)\n", "a = -1/2*np.real(x+y)*b\n", "rot = np.arctan(-b)-np.pi/2\n", "threshold = -a*b/np.sqrt(1+b*b)\n", "\n", "dummy_slot_idx = 1\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=1)\n", "\n", "dummy_data_0 = [\n", " DummyBinnedAcquisitionData(data=(1e3*a, 1e3*b), thres=0, avg_cnt=0)\n", " for a, b in zip(i,q)\n", "]\n", "cluster.set_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=1, acq_index_name=\"0\", data=dummy_data_0)" ] }, { "cell_type": "markdown", "id": "4b17f567", "metadata": {}, "source": [ "Next, after compiling the schedule and retrieving the acquisitions from the hardware," ] }, { "cell_type": "code", "execution_count": 34, "id": "5464da01", "metadata": {}, "outputs": [], "source": [ "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(schedule=schedule, config=device.generate_compilation_config())\n", "\n", "instrument_coordinator.prepare(compiled_schedule)\n", "instrument_coordinator.start()\n", "instrument_coordinator.wait_done(timeout_sec=10)\n", "\n", "acquisition = instrument_coordinator.retrieve_acquisition()" ] }, { "cell_type": "markdown", "id": "30830438", "metadata": {}, "source": [ "we might obtain the following data:" ] }, { "cell_type": "code", "execution_count": 35, "id": "e13e70e0", "metadata": {}, "outputs": [ { "data": { "image/png": "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JwgPD0dSUpLutXvuuQfbt2+3W7xEZF9MlojI7e3btw9Dhgxp8dqMGTNQU1ODf//737rXBEHAp59+ipkzZ8LDw0P3+vDhw5GRkYGamhq7xUxE9sNkiYjc3rlz59C5c+cWrwUHB+P+++9vMRW3e/duFBQUYNasWS2O7dy5M2pra6HRaOwSLxHZF5MlInJ7N2/ehK+vb5vXn3jiCfz444/Iy8sDAGzatAljxoxBTExMi+PatWsHAG2m7IjINTBZIiK3FxISgmvXrrV5fcKECejWrRs++eQTVFRU4L///a+usLu50tJSAECnTp1sHisR2Z+n3AEQEclt0KBBelezKZVKzJo1Cx9//DG6dOkCb29vPPjgg22Oy8rKQteuXRESEmKPcInIzjiyRERub9KkSTh58qTe0aVZs2ahsLAQL774IqZPn66bcmtu3759uPPOO+0RKhHJgMkSEbm9fv36YfDgwdixY0eb73Xr1g2JiYm4du0annjiiTbfr66uxldffYU5c+bYI1QikoFCEARB7iCIiOT23Xff4U9/+hOysrKgVIr/d+T777+PL7/8Ej/88IMNoyMiObFmiYgIwOTJk5GTk4PCwkJERESIPs/LywvvvPOODSMjIrlxZImIiIjICNYsERERERnBZImIiIjICCZLREREREYwWSIiIiIygskSERERkRFMloiIiIiMYLJEREREZASTJSIiIiIjmCwRERERGfH/AcqIkk5hHzQjAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "threshold, rotation = -0.043, 332.5\n", "plt.scatter(np.real(acquisition[0]), np.imag(acquisition[0]))\n", "plt.axline((0, threshold*np.cos(np.deg2rad(rotation))), slope = 1/np.tan(np.deg2rad(rotation)))\n", "plt.xlabel(\"I(V)\")\n", "plt.ylabel(\"Q(V)\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "511de3f4", "metadata": {}, "source": [ "Where the two clusters of data correspond to the two qubit states of `q0`: {math}`|0\\rangle` and {math}`|1\\rangle`. The threshold line was chosen as the bisector of the centroids of the two clusters of data.\n", "\n", "To assign each cluster to one state, we can set the qubit parameters {attr}`BasicTransmonElement.measure.acq_threshold` and {attr}`BasicTransmonElement.measure.acq_rotation` and run the experiment with the `ThresholdedAcquisition` protocol." ] }, { "cell_type": "code", "execution_count": 36, "id": "1f2a22aa", "metadata": { "tags": [ "remove-output" ] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 808B\n",
       "Dimensions:      (acq_index_0: 1, repetition: 200)\n",
       "Coordinates:\n",
       "  * acq_index_0  (acq_index_0) int64 8B 0\n",
       "Dimensions without coordinates: repetition\n",
       "Data variables:\n",
       "    0            (repetition, acq_index_0) int32 800B 0 0 0 0 0 0 ... 0 0 0 0 0
" ], "text/plain": [ " Size: 808B\n", "Dimensions: (acq_index_0: 1, repetition: 200)\n", "Coordinates:\n", " * acq_index_0 (acq_index_0) int64 8B 0\n", "Dimensions without coordinates: repetition\n", "Data variables:\n", " 0 (repetition, acq_index_0) int32 800B 0 0 0 0 0 0 ... 0 0 0 0 0" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from quantify_scheduler.operations import ThresholdedAcquisition\n", "\n", "# Set the threshold values\n", "transmon0.measure.acq_threshold(-0.043)\n", "transmon0.measure.acq_rotation(332.5)\n", "\n", "thres_acq_sched = Schedule(\"thresholded_acquisition\", repetitions=200)\n", "thres_acq_sched.add(Reset(\"q0\"))\n", "thres_acq_sched.add(X(\"q0\"))\n", "\n", "thres_acq_sched.add(\n", " SquarePulse(\n", " duration=pulse_duration,\n", " amp=pulse_level,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " ),\n", " ref_pt=\"end\",\n", " rel_time=1e-6, # Idle time before the pulse is played\n", ")\n", "thres_acq_sched.add(\n", " ThresholdedAcquisition(\n", " duration=acq_duration,\n", " port=\"q0:res\",\n", " clock=\"q0.ro\",\n", " acq_channel=0,\n", " acq_index=0,\n", " bin_mode=BinMode.APPEND,\n", " ),\n", " ref_pt=\"start\",\n", " rel_time=time_of_flight\n", ")\n", "\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(schedule=thres_acq_sched, config=device.generate_compilation_config())\n", "\n", "instrument_coordinator.prepare(compiled_schedule)\n", "instrument_coordinator.start()\n", "instrument_coordinator.wait_done(timeout_sec=10)\n", "\n", "acquisition = instrument_coordinator.retrieve_acquisition()\n", "acquisition" ] }, { "cell_type": "code", "execution_count": 37, "id": "5eaa2df9", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 2kB\n",
       "Dimensions:      (acq_index_0: 1, repetitions: 200)\n",
       "Coordinates:\n",
       "  * acq_index_0  (acq_index_0) int64 8B 0\n",
       "Dimensions without coordinates: repetitions\n",
       "Data variables:\n",
       "    0            (repetitions, acq_index_0) float64 2kB 1.0 0.0 1.0 ... 1.0 0.0
" ], "text/plain": [ " Size: 2kB\n", "Dimensions: (acq_index_0: 1, repetitions: 200)\n", "Coordinates:\n", " * acq_index_0 (acq_index_0) int64 8B 0\n", "Dimensions without coordinates: repetitions\n", "Data variables:\n", " 0 (repetitions, acq_index_0) float64 2kB 1.0 0.0 1.0 ... 1.0 0.0" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# qblox-instruments doesn't support retrieving dummy thresholded data yet.\n", "import xarray as xr\n", "array = np.concatenate((np.ones(100), np.zeros(100)))\n", "np.random.shuffle(array)\n", "acquisition[0] = xr.DataArray(array.reshape((200,1)), dims=['repetitions', 'acq_index_0'])\n", "acquisition" ] }, { "cell_type": "markdown", "id": "0f819e32", "metadata": {}, "source": [ "The retrieved dataset contains the integrated acquired results and contains in this case equal amounts of 0s and 1s (corresponding to the two clusters)." ] }, { "cell_type": "code", "execution_count": 38, "id": "a9fb07f4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "state 0: [100]\n", "state 1: [100]\n" ] } ], "source": [ "print(\"state 0: \", sum(acquisition[0].values==0))\n", "print(\"state 1: \", sum(acquisition[0].values==1))" ] }, { "cell_type": "markdown", "id": "7b3f55eb", "metadata": {}, "source": [ "The above schedule was run in the bin mode `BinMode.APPEND`, rerunning the schedule with `BinMode.AVERAGE` will average the thresholded values and in this case produce the single number, 0.5.\n", "\n", "(sec-acquisitions-trigger-count)=\n", "### Trigger count acquisition\n", "\n", "The trigger count acquisition protocol is used for measuring how many times the input signal goes over some limit.\n", "This protocol is used, for example, in the case of an NV center type of qubit, or other types of qubit, where counting the number of photons (indirectly as an electrical signal) is important.\n", "\n", "The trigger count protocol is currently only implemented for the Qblox backend, and it is available on two module types: the **QRM** (baseband) and the **QTM**. Please also see {ref}`sec-qblox-acquisition-details` for more information on Qblox module-specific behavior of this operation.\n", "\n", "Like the {ref}`single-sideband integration protocol `, the {class}`~quantify_scheduler.operations.acquisition_library.TriggerCount` protocol also offers two bin modes: **average** and **append**. The **average** mode can only be used with the QRM, and the **append** mode can be used with both the QRM and the QTM.\n", "\n", "The **append** bin mode is quite similar to the {ref}`single-sideband integration protocol ` case. Instead of the integrated acquisition result, the data will consist of the total number of triggers counted during each acquisition.\n", "Let's consider an example where we execute a schedule three times:\n", "\n", "- during the 1st run, three triggers are acquired,\n", "- during the 2nd run, one trigger is acquired,\n", "- during the 3rd run, one trigger is acquired.\n", "\n", "The result would then be the list `[3, 1, 1]`.\n", "\n", "In the **average** bin mode, the result is a _distribution_ that maps the trigger count numbers to the number of occurrences of each trigger count number.\n", "This provides insights into the overall occurrence of triggers when running the acquisition multiple times. Let's consider the exact same experimental example as above, where a schedule is executed three times.\n", "\n", "The overall distribution of triggers would be: trigger count of 1 occurred twice, and trigger count of 3 occurred once. Hence, the resulting dictionary would be: `{1: 2, 3: 1}`.\n", "The dictionary notation shows the number of triggers as keys and their corresponding frequencies as values.\n", "\n", "Note, the threshold is set for the QRM via the field {class}`~quantify_scheduler.backends.types.qblox.SequencerOptions.ttl_acq_threshold` in {ref}`sec-qblox-sequencer-options`, while for the QTM this threshold is set via the field `in_threshold_primary` in the {ref}`sec-qblox-digitization-thresholds` hardware option.\n", "\n", "#### Setup and schedule\n", "\n", "In this tutorial we will explain how **average bin mode** works in the {class}`~quantify_scheduler.operations.acquisition_library.TriggerCount` protocol (also see the introduction above).\n", "We create a schedule that consists of an acquisition operation that measures the trigger signals.\n", "In this tutorial we assume trigger signals are generated from an external source (we do not generate these from the control hardware)." ] }, { "cell_type": "code", "execution_count": 39, "id": "b3b87f33", "metadata": { "mystnb": { "remove_code_outputs": true } }, "outputs": [], "source": [ "from quantify_scheduler import BasicElectronicNVElement, GenericInstrumentCoordinatorComponent, MockLocalOscillator, QuantumDevice\n", "\n", "nv_device = QuantumDevice(name=\"nv_device\")\n", "qe0 = BasicElectronicNVElement(\"qe0\")\n", "qe0.clock_freqs.ge0.set(470.4e12)\n", "nv_device.add_element(qe0)\n", "nv_device.instr_instrument_coordinator(\"instrument_coordinator\")\n", "\n", "red_laser = MockLocalOscillator(\"red_laser\")\n", "ic_red_laser = GenericInstrumentCoordinatorComponent(red_laser)\n", "instrument_coordinator.add_component(ic_red_laser)\n", "\n", "hardware_cfg_trigger_count = config = {\n", " \"config_type\": \"quantify_scheduler.backends.qblox_backend.QbloxHardwareCompilationConfig\",\n", " \"hardware_description\": {\n", " \"cluster0\": {\n", " \"instrument_type\": \"Cluster\",\n", " \"modules\": {\n", " 1: {\n", " \"instrument_type\": \"QRM\"\n", " }\n", " },\n", " \"ref\": \"internal\"\n", " },\n", " \"optical_mod_red_laser\": {\n", " \"instrument_type\": \"OpticalModulator\"\n", " },\n", " \"red_laser\": {\n", " \"instrument_type\": \"LocalOscillator\",\n", " \"power\": 1\n", " }\n", " },\n", " \"hardware_options\": {\n", " \"modulation_frequencies\": {\n", " \"qe0:optical_readout-qe0.ge0\": {\n", " \"lo_freq\": None,\n", " \"interm_freq\": 50000000.0\n", " }\n", " },\n", " \"sequencer_options\": {\n", " \"qe0:optical_readout-qe0.ge0\": {\n", " \"ttl_acq_threshold\": 0.5\n", " }\n", " }\n", " },\n", " \"connectivity\": {\n", " \"graph\": [\n", " (\"cluster0.module1.real_input_0\", \"optical_mod_red_laser.if\"),\n", " (\"red_laser.output\", \"optical_mod_red_laser.lo\"),\n", " (\"optical_mod_red_laser.out\", \"qe0:optical_readout\")\n", " ]\n", " }\n", "}\n", "\n", "nv_device.hardware_config(hardware_cfg_trigger_count)" ] }, { "cell_type": "markdown", "id": "f137a550", "metadata": {}, "source": [ "The hardware should run the trigger count acquisition 3 times, and the schedule contains one trigger count acquisition, we therefore set `repetitions=3` for the schedule.\n", "The input signals are the following: the first time the schedule runs there are 3 trigger signals, the second time there is 1 trigger signal, and third time there is again 1 trigger signal." ] }, { "cell_type": "code", "execution_count": 40, "id": "1be6f689", "metadata": { "mystnb": { "remove_code_outputs": true } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/usr/local/lib/python3.9/site-packages/quantify_scheduler/operations/acquisition_library.py:739: FutureWarning: average is deprecated for the TriggerCount acquisition protocol, and will be removed in quantify-scheduler>=0.24.0. Use distribution instead, which has the same effect.\n", " warnings.warn(\n" ] }, { "data": { "text/plain": [ "{'name': '1277a6f7-9e50-4884-8de5-c4e0fe0b066e', 'operation_id': '2682036195041013017', 'timing_constraints': [{'rel_time': 0, 'ref_schedulable': None, 'ref_pt_new': None, 'ref_pt': None}], 'label': '1277a6f7-9e50-4884-8de5-c4e0fe0b066e'}" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from quantify_scheduler import Schedule\n", "from quantify_scheduler.operations import IdlePulse, SquarePulse, TriggerCount\n", "from quantify_scheduler.enums import BinMode\n", "\n", "acq_duration = 120e-9\n", "\n", "schedule = Schedule(\"trigger_count_acquisition_tutorial\", repetitions=3)\n", "schedule.add(IdlePulse(duration=1e-6))\n", "\n", "schedule.add(\n", " TriggerCount(\n", " t0=0,\n", " duration=acq_duration,\n", " port=\"qe0:optical_readout\",\n", " clock=\"qe0.ge0\",\n", " acq_channel=0,\n", " bin_mode=BinMode.AVERAGE,\n", " )\n", ")" ] }, { "cell_type": "markdown", "id": "fb29da88", "metadata": {}, "source": [ "It's important in using {class}`~quantify_scheduler.operations.acquisition_library.TriggerCount` acquisitions that the acquisition channel is identical for all acquisitions in a schedule,\n", "leading to a single distribution in case of average bin mode (and a single list in case of append bin mode).\n", "In this example, if instead there would be 3 acquisitions in the schedule, and all of the acquisition channels were different and then only running the schedule once,\n", "we would get 3 separate distributions (one per acquisition channel)." ] }, { "cell_type": "code", "execution_count": 41, "id": "0b380ca3", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "from qblox_instruments import DummyBinnedAcquisitionData, DummyScopeAcquisitionData\n", "\n", "dummy_slot_idx = 1\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0)\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=1)\n", "dummy_data_0 = [\n", " DummyBinnedAcquisitionData(data=(16, 0), thres=0, avg_cnt=3),\n", " DummyBinnedAcquisitionData(data=(16, 0), thres=0, avg_cnt=1),\n", " DummyBinnedAcquisitionData(data=(16, 0), thres=0, avg_cnt=1),\n", "]\n", "cluster.set_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0, acq_index_name=\"0\", data=dummy_data_0)" ] }, { "cell_type": "markdown", "id": "40a1bdaf", "metadata": {}, "source": [ "Let's compile the schedule." ] }, { "cell_type": "code", "execution_count": 42, "id": "ea4d0729", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import SerialCompiler\n", "\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(schedule=schedule, config=nv_device.generate_compilation_config())" ] }, { "cell_type": "markdown", "id": "466436cb", "metadata": {}, "source": [ "#### Running the schedule, retrieving acquisition\n", "\n", "Let's run the schedule, and retrieve the acquisitions." ] }, { "cell_type": "code", "execution_count": 43, "id": "3672956f", "metadata": {}, "outputs": [], "source": [ "instrument_coordinator.prepare(compiled_schedule)\n", "instrument_coordinator.start()\n", "instrument_coordinator.wait_done(timeout_sec=10)\n", "\n", "acquisition = instrument_coordinator.retrieve_acquisition()" ] }, { "cell_type": "code", "execution_count": 44, "id": "dd18dfc6", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 40B\n",
       "Dimensions:     (repetition: 1, counts: 2)\n",
       "Coordinates:\n",
       "  * repetition  (repetition) int64 8B 0\n",
       "  * counts      (counts) int64 16B 1 3\n",
       "Data variables:\n",
       "    0           (repetition, counts) int64 16B 2 1
" ], "text/plain": [ " Size: 40B\n", "Dimensions: (repetition: 1, counts: 2)\n", "Coordinates:\n", " * repetition (repetition) int64 8B 0\n", " * counts (counts) int64 16B 1 3\n", "Data variables:\n", " 0 (repetition, counts) int64 16B 2 1" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "acquisition" ] }, { "cell_type": "markdown", "id": "c0a9227b", "metadata": {}, "source": [ "There were three trigger acquisitions overall. In the first acquisition 3 triggers were sent-out, and in the second and third case, only one. So, we expect to see that one trigger was measured twice, and 3 triggers were measured only once. The data shows exactly this. At `acq_channel=0` (corresponding to the `0` key in the `Dataset`) the values are `2` and `1`, with `counts` for `1` and `3` respectively.\n", "\n", "(sec-acquisitions-timetag)=\n", "### Timetag and TimetagTrace acquisitions\n", "\n", "The Timetag and TimetagTrace acquisitions have their own dedicated tutorial: {ref}`sec-timetagging`.\n", "\n", "## Gate-level acquisitions\n", "\n", "In the previous section the schedule was defined on the hardware level, in terms of signals and pulses. In this section we will address the acquisitions in terms of qubits. To do that, first, we need to set up a qubit. See {ref}`sec-tutorial-ops-qubits` for an introduction to how to set up a schedule on the gate-level. Integration type acquisitions and trigger count acquisitions make sense on the gate-level, depending on the physical implementation of your qubit.\n", "\n", "In this tutorial we will set up a simple single sideband integration acquisition on the gate-level. In the case of a transmon qubit, a {class}`~quantify_scheduler.operations.gate_library.Measure` gate first sends out an acquisition pulse, and then acquires the signal. The {class}`~quantify_scheduler.device_under_test.quantum_device.QuantumDevice` stores the parameters of how the measurement gate is translated to device level operations by `quantify-scheduler`.\n", "\n", "Let's see what is the effect of modifying the amplitude of the acquisition pulse on the acquisition result.\n", "Let's set up the time of flight as before, but now on the {class}`~quantify_scheduler.device_under_test.quantum_device.QuantumDevice`, and set up the amplitude of the acquisition pulse, which is a square pulse in this case." ] }, { "cell_type": "code", "execution_count": 45, "id": "4a3ea95c", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "device.remove_element(\"q0\")\n", "transmon0.close()" ] }, { "cell_type": "code", "execution_count": 46, "id": "acda4680", "metadata": {}, "outputs": [], "source": [ "time_of_flight = 148e-9\n", "pulse_duration = 120e-9\n", "acq_duration = pulse_duration" ] }, { "cell_type": "code", "execution_count": 47, "id": "d66f110a", "metadata": {}, "outputs": [], "source": [ "transmon0 = BasicTransmonElement(\"q0\")\n", "transmon0.clock_freqs.readout(6e9)\n", "transmon0.measure.pulse_amp(0.125)\n", "transmon0.measure.pulse_duration(pulse_duration)\n", "transmon0.measure.acq_delay(time_of_flight)\n", "transmon0.measure.integration_time(acq_duration)\n", "transmon0.measure.acq_channel(2)\n", "device.add_element(transmon0)" ] }, { "cell_type": "markdown", "id": "70ccc359", "metadata": {}, "source": [ "Similar to the previous setup, the pulse has an amplitude of 0.125 and matches the duration of the acquisition. In this case, `quantify-scheduler` will use the port `\":res\"` for both the acquisition pulse and acquisition itself, specifically `\"q0:res\"`. Note, we set the `acq_channel` to `2` for the sake of the example.\n", "\n", "The relevant hardware configuration is the following.\n", "\n", "```{code-block} python\n", "\"portclock_configs\": [\n", " {\"port\": \"q0:res\", \"clock\": \"q0.ro\", \"interm_freq\": 0},\n", " ]\n", "```\n", "\n", "### Creating and running the schedule\n", "\n", "The qubit is now set up, and we can create the schedule." ] }, { "cell_type": "code", "execution_count": 48, "id": "0a7000fb", "metadata": { "mystnb": { "remove_code_outputs": true } }, "outputs": [ { "data": { "text/plain": [ "{'name': 'a177bb0f-126d-4416-813a-e51f4ca5c757', 'operation_id': '3187667708041838487', 'timing_constraints': [{'rel_time': 1e-06, 'ref_schedulable': None, 'ref_pt_new': None, 'ref_pt': None}], 'label': 'a177bb0f-126d-4416-813a-e51f4ca5c757'}" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from quantify_scheduler import Schedule\n", "from quantify_scheduler.operations import IdlePulse, Measure\n", "\n", "schedule = Schedule(\"gate_level_ssb_acquisition_tutorial\")\n", "\n", "schedule.add(IdlePulse(duration=1e-6))\n", "\n", "schedule.add(\n", " Measure(\"q0\", acq_index=0),\n", " rel_time=1e-6,\n", ")" ] }, { "cell_type": "code", "execution_count": 49, "id": "cc80895d", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "from qblox_instruments import DummyBinnedAcquisitionData, DummyScopeAcquisitionData\n", "\n", "dummy_slot_idx = 1\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0)\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=1)\n", "dummy_data_0 = [\n", " DummyBinnedAcquisitionData(data=(16, 0), thres=0, avg_cnt=0),\n", "]\n", "cluster.set_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0, acq_index_name=\"0\", data=dummy_data_0)" ] }, { "cell_type": "markdown", "id": "bb72e7d3", "metadata": {}, "source": [ "Let's compile the schedule." ] }, { "cell_type": "code", "execution_count": 50, "id": "46611a89", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import SerialCompiler\n", "\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(schedule=schedule, config=device.generate_compilation_config())" ] }, { "cell_type": "markdown", "id": "2b7c095f", "metadata": {}, "source": [ "#### Running the schedule, retrieving acquisition\n", "\n", "Let's run the schedule, and retrieve the acquisitions." ] }, { "cell_type": "code", "execution_count": 51, "id": "4e623fc7", "metadata": {}, "outputs": [], "source": [ "instrument_coordinator.prepare(compiled_schedule)\n", "instrument_coordinator.start()\n", "instrument_coordinator.wait_done(timeout_sec=10)\n", "\n", "acquisition = instrument_coordinator.retrieve_acquisition()" ] }, { "cell_type": "code", "execution_count": 52, "id": "10257f8b", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 24B\n",
       "Dimensions:      (acq_index_2: 1)\n",
       "Coordinates:\n",
       "  * acq_index_2  (acq_index_2) int64 8B 0\n",
       "Data variables:\n",
       "    2            (acq_index_2) complex128 16B (0.13333333333333333+0j)
" ], "text/plain": [ " Size: 24B\n", "Dimensions: (acq_index_2: 1)\n", "Coordinates:\n", " * acq_index_2 (acq_index_2) int64 8B 0\n", "Data variables:\n", " 2 (acq_index_2) complex128 16B (0.13333333333333333+0j)" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "acquisition" ] }, { "cell_type": "markdown", "id": "bae8ab6e", "metadata": {}, "source": [ "Notice, that the result is only one number at `acq_channel=2`.\n", "\n", "#### Modifying the readout pulse amplitude\n", "\n", "Let's see what the effect on the measurement is if we double the pulse amplitude of the readout pulse" ] }, { "cell_type": "code", "execution_count": 53, "id": "6c52cae8", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "device.remove_element(\"q0\")" ] }, { "cell_type": "code", "execution_count": 54, "id": "213cd15e", "metadata": {}, "outputs": [], "source": [ "transmon0.measure.pulse_amp(0.25)\n", "device.add_element(transmon0)" ] }, { "cell_type": "markdown", "id": "91cae6ad", "metadata": {}, "source": [ "The amplitude of the read-out pulse is now `0.25`, double what it was." ] }, { "cell_type": "code", "execution_count": 55, "id": "f5d8aef4", "metadata": { "tags": [ "remove-cell" ] }, "outputs": [], "source": [ "from qblox_instruments import DummyBinnedAcquisitionData, DummyScopeAcquisitionData\n", "\n", "dummy_slot_idx = 1\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0)\n", "cluster.delete_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=1)\n", "dummy_data_0 = [\n", " DummyBinnedAcquisitionData(data=(32, 0), thres=0, avg_cnt=0),\n", "]\n", "cluster.set_dummy_binned_acquisition_data(slot_idx=dummy_slot_idx, sequencer=0, acq_index_name=\"0\", data=dummy_data_0)" ] }, { "cell_type": "markdown", "id": "a6cf7455", "metadata": {}, "source": [ "Let's compile the schedule." ] }, { "cell_type": "code", "execution_count": 56, "id": "bbe5185a", "metadata": {}, "outputs": [], "source": [ "from quantify_scheduler import SerialCompiler\n", "\n", "compiler = SerialCompiler(name=\"compiler\")\n", "compiled_schedule = compiler.compile(schedule=schedule, config=device.generate_compilation_config())" ] }, { "cell_type": "markdown", "id": "fd962a14", "metadata": {}, "source": [ "Let's run the schedule, and retrieve the acquisitions." ] }, { "cell_type": "code", "execution_count": 57, "id": "401053d1", "metadata": {}, "outputs": [], "source": [ "instrument_coordinator.prepare(compiled_schedule)\n", "instrument_coordinator.start()\n", "instrument_coordinator.wait_done(timeout_sec=10)\n", "\n", "acquisition = instrument_coordinator.retrieve_acquisition()" ] }, { "cell_type": "code", "execution_count": 58, "id": "f5ddcb14", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "
<xarray.Dataset> Size: 24B\n",
       "Dimensions:      (acq_index_2: 1)\n",
       "Coordinates:\n",
       "  * acq_index_2  (acq_index_2) int64 8B 0\n",
       "Data variables:\n",
       "    2            (acq_index_2) complex128 16B (0.26666666666666666+0j)
" ], "text/plain": [ " Size: 24B\n", "Dimensions: (acq_index_2: 1)\n", "Coordinates:\n", " * acq_index_2 (acq_index_2) int64 8B 0\n", "Data variables:\n", " 2 (acq_index_2) complex128 16B (0.26666666666666666+0j)" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "acquisition" ] }, { "cell_type": "markdown", "id": "b01a5d60", "metadata": {}, "source": [ "As you can see, because the measurement read-out pulse is now double in amplitude, the measured (acquired) value is now also double compared to the previous case." ] } ], "metadata": { "jupytext": { "text_representation": { "extension": ".md", "format_name": "myst", "format_version": 0.13, "jupytext_version": "1.14.5" } }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "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.20" }, "source_map": [ 12, 40, 47, 51, 65, 81, 120, 126, 131, 133, 149, 151, 162, 165, 169, 203, 227, 231, 236, 242, 250, 252, 258, 270, 287, 290, 294, 334, 338, 356, 360, 365, 371, 379, 381, 436, 448, 461, 465, 470, 474, 482, 484, 488, 490, 507, 580, 584, 598, 602, 609, 613, 621, 623, 658, 696, 729, 733, 742, 746, 753, 759, 806, 815, 819, 822, 859, 919, 924, 948, 955, 969, 973, 978, 984, 992, 994, 1012, 1019, 1025, 1034, 1050, 1068, 1080, 1084, 1089, 1095, 1103, 1105, 1113, 1119, 1122, 1126, 1138, 1142, 1147, 1151, 1159, 1161 ] }, "nbformat": 4, "nbformat_minor": 5 }