Skip to content

Iterative measurements of ScheduleGettable with multiple acquisitions are not possible

Problem

MeasurementControl fails when executing a schedule with more than one acquisition using the ScheduleGettable. This happens only in iterative mode. However, doing the same measurement in batched mode with batch_size = 1 succeeds.

Possible Solution

I think the output-array evaluation of ScheduleGettable in iterative mode does not work as intended.

Minimal error reproducing example

import numpy as np
import os
from qcodes.instrument.parameter import ManualParameter

from quantify_core.data.handling import get_datadir, set_datadir
from quantify_core.measurement.control import MeasurementControl
from quantify_core.utilities import general

from quantify_scheduler.gettables import ScheduleGettable
from quantify_scheduler.instrument_coordinator.components.qblox import ClusterComponent
from quantify_scheduler.schedules.schedule import Schedule
from quantify_scheduler.device_under_test.quantum_device import QuantumDevice
from quantify_scheduler.device_under_test.transmon_element import BasicTransmonElement
from quantify_scheduler.instrument_coordinator import InstrumentCoordinator
from quantify_scheduler.operations.gate_library import Reset, Rxy, Measure
from quantify_scheduler.operations.pulse_library import IdlePulse

set_datadir("data")

hardware_config = {
    "config_type": "quantify_scheduler.backends.qblox_backend.QbloxHardwareCompilationConfig",
    "hardware_description": {
        "cluster0": {
            "instrument_type": "Cluster",
            "modules": {
                "1": {"instrument_type": "QRM"},
            },
            "sequence_to_file": False,
            "ref": "internal",
            # "ip": "10.1.60.150",
        }
    },
    "hardware_options": {
        "modulation_frequencies": {
            "q0:mw-q0.01": {"lo_freq": 8e9},
            "q0:res-q0.ro": {"lo_freq": 8e9},
        },
    },
    "connectivity": {
        "graph": [
            ["cluster0.module1.complex_output_0", "q0:res"],
            ["cluster0.module1.complex_input_0", "q0:res"],
        ]
    },
}

meas_ctrl = MeasurementControl("meas_ctrl")
instrument_coordinator = InstrumentCoordinator(name="instrument_coordinator")
q0 = BasicTransmonElement("q0")
quantum_device = QuantumDevice(name="quantum_device")
quantum_device.add_element(q0)
quantum_device.instr_measurement_control(meas_ctrl.name)
quantum_device.instr_instrument_coordinator(instrument_coordinator.name)
quantum_device.hardware_config.set(hardware_config)
q0.clock_freqs.readout.set(0)


def two_measurement_sched(sweep_param, qubit: str, repetitions: int = 128) -> Schedule:
    sched = Schedule("two_meas_sched", repetitions=repetitions)
    sched.add(Reset(qubit))
    sched.add(IdlePulse(duration=sweep_param))
    sched.add(Measure(qubit, acq_index=0), label=f"meas_{0}")
    sched.add(Measure(qubit, acq_index=1), label=f"meas_{1}")
    return sched


from qblox_instruments import Cluster
from qblox_instruments.types import ClusterType

cluster = Cluster("cluster0", dummy_cfg={1: ClusterType.CLUSTER_QRM_RF})
ic_cluster = ClusterComponent(cluster)
instrument_coordinator.add_component(ic_cluster)

spec_param = ManualParameter("sweep_param", initial_value=0, unit="s")

schedule_kwargs = {
    "sweep_param": spec_param,
    "qubit": "q0",
}

spec_gettable = ScheduleGettable(
    quantum_device=quantum_device,
    schedule_function=two_measurement_sched,
    schedule_kwargs=schedule_kwargs,
    real_imag=False,
)


params = np.arange(1e-6, 2e-6, 0.1e-6)
meas_ctrl.settables(spec_param)
meas_ctrl.setpoints(params)
meas_ctrl.gettables(spec_gettable)
label = f"Example measurement {quantum_device.name}"
dset = meas_ctrl.run(label)

raises

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[1], line 95
     93 meas_ctrl.gettables(spec_gettable)
     94 label = f"Example measurement {quantum_device.name}"
---> 95 dset = meas_ctrl.run(label)
     96 # spec_gettable.get()

File ~/miniforge3/envs/dev/lib/python3.12/site-packages/quantify_core/measurement/control.py:554, in MeasurementControl.run(self, name, soft_avg, lazy_set, save_data)
    552         if self.verbose():
    553             print("Starting iterative measurement...")
--> 554         self._run_iterative(lazy_set)
    555 except KeyboardInterrupt:
    556     print("\nInterrupt signaled, exiting gracefully...")

File ~/miniforge3/envs/dev/lib/python3.12/site-packages/quantify_core/measurement/control.py:669, in MeasurementControl._run_iterative(self, lazy_set)
    667 self._dataarray_cache = {}
    668 for idx in range(len(self._setpoints[0])):
--> 669     self._iterative_set_and_get(
    670         [spt[idx] for spt in self._setpoints],
    671         self._curr_setpoint_idx(),
    672         lazy_set,
    673     )
    674     self._nr_acquired_values += 1
    675     self._update()

File ~/miniforge3/envs/dev/lib/python3.12/site-packages/quantify_core/measurement/control.py:803, in MeasurementControl._iterative_set_and_get(self, setpoints, idx, lazy_set)
    800     batched = gpar.batched
    801     real_imag = gpar.real_imag
--> 803     new_data = self._process_acquired_data(
    804         new_data_raw, batched, real_imag
    805     )  # can return (N, M)
    806 else:
    807     new_data = new_data_raw

File ~/miniforge3/envs/dev/lib/python3.12/site-packages/quantify_core/measurement/control.py:433, in MeasurementControl._process_acquired_data(cls, acquired_data, batched, real_imag)
    430     vals = acq_channel_data.to_numpy().reshape((-1,))
    432     if not batched and len(vals) != 1:
--> 433         raise ValueError(
    434             f"For iterative mode, only one value is expected for each "
    435             f"acquisition channel. Got {len(vals)} values for acquisition "
    436             f"channel '{acq_channel}' instead."
    437         )
    438     return_data.extend(cls._reshape_data(acq_protocol, vals, real_imag))
    440 logger.debug(f"Returning {len(return_data)} values.")

ValueError: For iterative mode, only one value is expected for each acquisition channel. Got 2 values for acquisition channel '0' instead.
Edited by Robert Sokolewicz