qibolab.instruments.qm package#

Submodules#

qibolab.instruments.qm.acquisition module#

class qibolab.instruments.qm.acquisition.Acquisition(serial: str, average: bool)[source]#

Bases: ABC

QUA variables used for saving of acquisition results.

This class can be instantiated only within a QUA program scope. Each readout pulse is associated with its own set of acquisition variables.

serial: str#

Serial of the readout pulse that generates this acquisition.

average: bool#
abstract assign_element(element)[source]#

Assign acquisition variables to the corresponding QM controlled.

Proposed to do by QM to avoid crashes.

Parameters:

element (str) – Element (from config) that the pulse will be applied on.

abstract measure(operation, element)[source]#

Send measurement pulse and acquire results.

Parameters:
  • operation (str) – Operation (from config) corresponding to the pulse to be played.

  • element (str) – Element (from config) that the pulse will be applied on.

abstract save()[source]#

Save acquired results from variables to streams.

abstract download(*dimensions)[source]#

Save streams to prepare for fetching from host device.

Parameters:

dimensions (int) – Dimensions to use for buffer of data.

abstract fetch()[source]#

Fetch downloaded streams to host device.

class qibolab.instruments.qm.acquisition.RawAcquisition(serial: str, average: bool, adc_stream: qm.qua._dsl._ResultSource = <factory>)[source]#

Bases: Acquisition

QUA variables used for raw waveform acquisition.

adc_stream: qm.qua._dsl._ResultSource#

Stream to collect raw ADC data.

assign_element(element)[source]#

Assign acquisition variables to the corresponding QM controlled.

Proposed to do by QM to avoid crashes.

Parameters:

element (str) – Element (from config) that the pulse will be applied on.

measure(operation, element)[source]#

Send measurement pulse and acquire results.

Parameters:
  • operation (str) – Operation (from config) corresponding to the pulse to be played.

  • element (str) – Element (from config) that the pulse will be applied on.

save()[source]#

Save acquired results from variables to streams.

download(*dimensions)[source]#

Save streams to prepare for fetching from host device.

Parameters:

dimensions (int) – Dimensions to use for buffer of data.

fetch(handles)[source]#

Fetch downloaded streams to host device.

class qibolab.instruments.qm.acquisition.IntegratedAcquisition(serial: str, average: bool, I: qm.qua._dsl._Variable = <factory>, Q: qm.qua._dsl._Variable = <factory>, I_stream: qm.qua._dsl._ResultSource = <factory>, Q_stream: qm.qua._dsl._ResultSource = <factory>)[source]#

Bases: Acquisition

QUA variables used for integrated acquisition.

I: qm.qua._dsl._Variable#
Q: qm.qua._dsl._Variable#

Variables to save the (I, Q) values acquired from a single shot.

I_stream: qm.qua._dsl._ResultSource#
Q_stream: qm.qua._dsl._ResultSource#

Streams to collect the results of all shots.

assign_element(element)[source]#

Assign acquisition variables to the corresponding QM controlled.

Proposed to do by QM to avoid crashes.

Parameters:

element (str) – Element (from config) that the pulse will be applied on.

measure(operation, element)[source]#

Send measurement pulse and acquire results.

Parameters:
  • operation (str) – Operation (from config) corresponding to the pulse to be played.

  • element (str) – Element (from config) that the pulse will be applied on.

save()[source]#

Save acquired results from variables to streams.

download(*dimensions)[source]#

Save streams to prepare for fetching from host device.

Parameters:

dimensions (int) – Dimensions to use for buffer of data.

fetch(handles)[source]#

Fetch downloaded streams to host device.

class qibolab.instruments.qm.acquisition.ShotsAcquisition(serial: str, average: bool, threshold: float, angle: float, I: qm.qua._dsl._Variable = <factory>, Q: qm.qua._dsl._Variable = <factory>, shot: qm.qua._dsl._Variable = <factory>, shots: qm.qua._dsl._ResultSource = <factory>)[source]#

Bases: Acquisition

QUA variables used for shot classification.

Threshold and angle must be given in order to classify shots.

threshold: float#

Threshold to be used for classification of single shots.

angle: float#

Angle in the IQ plane to be used for classification of single shots.

I: qm.qua._dsl._Variable#
Q: qm.qua._dsl._Variable#

Variables to save the (I, Q) values acquired from a single shot.

shot: qm.qua._dsl._Variable#

Variable for calculating an individual shots.

shots: qm.qua._dsl._ResultSource#

Stream to collect multiple shots.

assign_element(element)[source]#

Assign acquisition variables to the corresponding QM controlled.

Proposed to do by QM to avoid crashes.

Parameters:

element (str) – Element (from config) that the pulse will be applied on.

measure(operation, element)[source]#

Send measurement pulse and acquire results.

Parameters:
  • operation (str) – Operation (from config) corresponding to the pulse to be played.

  • element (str) – Element (from config) that the pulse will be applied on.

save()[source]#

Save acquired results from variables to streams.

download(*dimensions)[source]#

Save streams to prepare for fetching from host device.

Parameters:

dimensions (int) – Dimensions to use for buffer of data.

fetch(handles)[source]#

Fetch downloaded streams to host device.

qibolab.instruments.qm.config module#

qibolab.instruments.qm.config.PortId#

(“con1”, 2).

Type:

Type for port definition, for example

alias of Tuple[str, int]

qibolab.instruments.qm.config.IQPortId#

Type for collections of IQ ports.

alias of Union[Tuple[Tuple[str, int]], Tuple[Tuple[str, int], Tuple[str, int]]]

class qibolab.instruments.qm.config.QMPort(name: Tuple[Tuple[str, int]] | Tuple[Tuple[str, int], Tuple[str, int]], offset: float = 0.0, gain: int = 0, filters: Dict[str, float] | None = None)[source]#

Bases: Port

name: Tuple[Tuple[str, int]] | Tuple[Tuple[str, int], Tuple[str, int]]#

Name of the port that acts as its identifier.

offset: float = 0.0#

DC offset that is applied to this port.

gain: int = 0#

Gain that is applied to this port.

filters: Dict[str, float] | None = None#

Filters to be applied to the channel to reduce the distortions when sending flux pulses.

Useful for two-qubit gates. Quantum Machines (qibolab.instruments.qm.QMOPX) associate filters to channels but this may not be the case in other instruments.

class qibolab.instruments.qm.config.QMConfig(version: int = 1, controllers: dict = <factory>, elements: dict = <factory>, pulses: dict = <factory>, waveforms: dict = <factory>, digital_waveforms: dict = <factory>, integration_weights: dict = <factory>, mixers: dict = <factory>)[source]#

Bases: object

Configuration for communicating with the QuantumMachinesManager.

version: int = 1#
controllers: dict#
elements: dict#
pulses: dict#
waveforms: dict#
digital_waveforms: dict#
integration_weights: dict#
mixers: dict#
register_analog_output_controllers(port: QMPort)[source]#

Register controllers in the config.

Parameters:

ports (QMPort) – Port we are registering. Contains information about the controller and port number and some parameters (offset, gain, filter, etc.).

static iq_imbalance(g, phi)[source]#

Creates the correction matrix for the mixer imbalance caused by the gain and phase imbalances

More information here: https://docs.qualang.io/libs/examples/mixer-calibration/#non-ideal-mixer

Parameters:
  • g (float) – relative gain imbalance between the I & Q ports (unit-less). Set to 0 for no gain imbalance.

  • phi (float) – relative phase imbalance between the I & Q ports (radians). Set to 0 for no phase imbalance.

register_drive_element(qubit, intermediate_frequency=0)[source]#

Register qubit drive elements and controllers in the QM config.

Parameters:
  • qubit (qibolab.platforms.utils.Qubit) – Qubit to add elements for.

  • intermediate_frequency (int) – Intermediate frequency that the OPX will send to this qubit. This frequency will be mixed with the LO connected to the same channel.

register_readout_element(qubit, intermediate_frequency=0, time_of_flight=0, smearing=0)[source]#

Register resonator elements and controllers in the QM config.

Parameters:
  • qubit (qibolab.platforms.utils.Qubit) – Qubit to add elements for.

  • intermediate_frequency (int) – Intermediate frequency that the OPX will send to this qubit. This frequency will be mixed with the LO connected to the same channel.

register_flux_element(qubit, intermediate_frequency=0)[source]#

Register qubit flux elements and controllers in the QM config.

Parameters:
  • qubit (qibolab.platforms.utils.Qubit) – Qubit to add elements for.

  • intermediate_frequency (int) – Intermediate frequency that the OPX will send to this qubit. This frequency will be mixed with the LO connected to the same channel.

register_element(qubit, pulse, time_of_flight=0, smearing=0)[source]#
register_pulse(qubit, pulse)[source]#

Registers pulse, waveforms and integration weights in QM config.

Parameters:
  • qubit (qibolab.platforms.utils.Qubit) – Qubit that the pulse acts on.

  • pulse (qibolab.pulses.Pulse) – Pulse object to register.

Returns:

Name of the element this pulse will be played on.

Elements are a part of the QM config and are generated during instantiation of the Qubit objects. They are named as “drive0”, “drive1”, “flux0”, “readout0”, …

Return type:

element (str)

register_waveform(pulse, mode='i')[source]#

Registers waveforms in QM config.

QM supports two kinds of waveforms, examples:

“zero_wf”: {“type”: “constant”, “sample”: 0.0} “x90_wf”: {“type”: “arbitrary”, “samples”: x90_wf.tolist()}

Parameters:
  • pulse (qibolab.pulses.Pulse) – Pulse object to read the waveform from.

  • mode (str) – “i” or “q” specifying which channel the waveform will be played.

Returns:

String with a serialization of the waveform.

Used as key to identify the waveform in the config.

Return type:

serial (str)

register_integration_weights(qubit, readout_len)[source]#

Registers integration weights in QM config.

Parameters:
  • qubit (qibolab.platforms.quantum_machines.Qubit) – Qubit object that the integration weights will be used for.

  • readout_len (int) – Duration of the readout pulse in ns.

qibolab.instruments.qm.driver module#

class qibolab.instruments.qm.driver.QMOPX(name: str, address: str, manager: qm.QuantumMachinesManager.QuantumMachinesManager | None = None, config: ~qibolab.instruments.qm.config.QMConfig = <factory>, is_connected: bool = False, time_of_flight: int = 0, smearing: int = 0, _ports: ~typing.Dict[~typing.Tuple[~typing.Tuple[str, int]] | ~typing.Tuple[~typing.Tuple[str, int], ~typing.Tuple[str, int]], ~qibolab.instruments.qm.config.QMPort] = <factory>, script_file_name: str | None = 'qua_script.txt')[source]#

Bases: Controller

Instrument object for controlling Quantum Machines (QM) OPX controllers.

Playing pulses on QM controllers requires a config dictionary and a program written in QUA language. The config file is generated in parts in the following places in the register_* methods. The controllers, elements and pulses are all registered after a pulse sequence is given, so that the config contains only elements related to the participating qubits. The QUA program for executing an arbitrary qibolab PulseSequence is written in play and play_pulses and executed in execute_program.

Parameters:
  • name (str) – Name of the instrument instance.

  • address (str) – IP address and port for connecting to the OPX instruments.

PortType#

alias of QMPort

name: str#
address: str#
manager: qm.QuantumMachinesManager.QuantumMachinesManager | None = None#

Manager object used for controlling the QM OPXs.

config: QMConfig#

Configuration dictionary required for pulse execution on the OPXs.

is_connected: bool = False#

Boolean that shows whether we are connected to the QM manager.

time_of_flight: int = 0#

Time of flight used for hardware signal integration.

smearing: int = 0#

Smearing used for hardware signal integration.

script_file_name: str | None = 'qua_script.txt'#

Name of the file that the QUA program will dumped in that after every execution. If None the program will not be dumped.

connect()[source]#

Connect to the QM manager.

setup()[source]#

Deprecated method.

start()[source]#

Turn on the physical instrument.

stop()[source]#

Close all running Quantum Machines.

disconnect()[source]#

Disconnect from QM manager.

execute_program(program)[source]#

Executes an arbitrary program written in QUA language.

Parameters:

program – QUA program.

Returns:

TODO

static fetch_results(result, ro_pulses)[source]#

Fetches results from an executed experiment.

Defined as @staticmethod because it is overwritten in qibolab.instruments.qm.simulator.QMSim.

play(qubits, sequence, options)[source]#

Play a pulse sequence and retrieve feedback.

Returns:

(Dict[ResultType]) mapping the serial of the readout pulses used to the acquired qibolab.result.ExecutionResults object.

sweep(qubits, sequence, options, *sweepers)[source]#

Play a pulse sequence while sweeping one or more parameters.

Returns:

(dict) mapping the serial of the readout pulses used to the acquired qibolab.result.ExecutionResults object.

play_sequences(qubits, sequence, options)[source]#

Play pulses sequences by unrolling and retrieve feedback.

Returns:

(Dict[List[ResultType]) mapping the serial of the readout pulses used to a list of the acquired qibolab.result.ExecutionResults object.

qibolab.instruments.qm.sequence module#

qibolab.instruments.qm.sequence.DurationsType#

Type of values that can be accepted in a duration sweeper.

alias of Union[List[int], ndarray[Any, dtype[int]]]

class qibolab.instruments.qm.sequence.QMPulse(pulse: ~qibolab.pulses.Pulse, element: str | None = None, operation: str | None = None, relative_phase: float | None = None, wait_time: int = 0, wait_time_variable: qm.qua._dsl._Variable | None = None, swept_duration: qm.qua._dsl._Variable | None = None, acquisition: ~qibolab.instruments.qm.acquisition.Acquisition | None = None, next_: ~typing.Set[~qibolab.instruments.qm.sequence.QMPulse] = <factory>, elements_to_align: ~typing.Set[str] = <factory>)[source]#

Bases: object

Wrapper around qibolab.pulses.Pulse for easier translation to QUA program.

These pulses are defined when qibolab.instruments.qm.QMOPX.play() is called and hold attributes for the element and operation that corresponds to each pulse, as defined in the QM config.

pulse: Pulse#

qibolab.pulses.Pulse implemting the current pulse.

element: str | None = None#

Element that the pulse will be played on, as defined in the QM config.

operation: str | None = None#

Name of the operation that is implementing the pulse in the QM config.

relative_phase: float | None = None#

Relative phase of the pulse normalized to follow QM convention. May be overwritten when sweeping phase.

wait_time: int = 0#

Time (in clock cycles) to wait before playing this pulse. Calculated and assigned by qibolab.instruments.qm.Sequence.add().

wait_time_variable: qm.qua._dsl._Variable | None = None#

Time (in clock cycles) to wait before playing this pulse when we are sweeping start.

swept_duration: qm.qua._dsl._Variable | None = None#

Pulse duration when sweeping it.

acquisition: Acquisition | None = None#

Data class containing the variables required for data acquisition for the instrument.

next_: Set[QMPulse]#

Pulses that will be played after the current pulse. These pulses need to be re-aligned if we are sweeping the start or duration.

elements_to_align: Set[str]#
property duration#

Duration of the pulse as defined in the qibolab.pulses.PulseSequence.

Remains constant even when we are sweeping the duration of this pulse.

property wait_cycles#

Instrument clock cycles (1 cycle = 4ns) to wait before playing the pulse.

This property will be used in the QUA wait command, so that it is compatible with and without start sweepers.

play()[source]#

Play the pulse.

Relevant only in the context of a QUA program.

declare_output(options, threshold=None, angle=None)[source]#
class qibolab.instruments.qm.sequence.BakedPulse(pulse: ~qibolab.pulses.Pulse, element: str | None = None, operation: str | None = None, relative_phase: float | None = None, wait_time: int = 0, wait_time_variable: qm.qua._dsl._Variable | None = None, swept_duration: qm.qua._dsl._Variable | None = None, acquisition: ~qibolab.instruments.qm.acquisition.Acquisition | None = None, next_: ~typing.Set[~qibolab.instruments.qm.sequence.QMPulse] = <factory>, elements_to_align: ~typing.Set[str] = <factory>, segments: ~typing.List[~qualang_tools.bakery.bakery.Baking] = <factory>, amplitude: float | None = None, durations: ~typing.List[int] | ~numpy.ndarray[~typing.Any, ~numpy.dtype[int]] | None = None)[source]#

Bases: QMPulse

Baking allows 1ns resolution in the pulse waveforms.

segments: List[Baking]#

Baked segments implementing the pulse.

amplitude: float | None = None#

Amplitude of the baked pulse. Relevant only when sweeping amplitude.

durations: List[int] | ndarray[Any, dtype[int]] | None = None#
property duration#

Duration of the pulse as defined in the qibolab.pulses.PulseSequence.

Remains constant even when we are sweeping the duration of this pulse.

static calculate_waveform(original_waveform, t)[source]#
bake(config: QMConfig, durations: List[int] | ndarray[Any, dtype[int]])[source]#
property amplitude_array#
play()[source]#

Play the pulse.

Relevant only in the context of a QUA program.

qibolab.instruments.qm.sequence.find_duration_sweeper_pulses(sweepers)[source]#

Find all pulses that require baking because we are sweeping their duration.

class qibolab.instruments.qm.sequence.Sequence(qmpulses: ~typing.List[~qibolab.instruments.qm.sequence.QMPulse] = <factory>, ro_pulses: ~typing.List[~qibolab.instruments.qm.sequence.QMPulse] = <factory>, pulse_to_qmpulse: ~typing.Dict[~qibolab.pulses.Pulse, ~qibolab.instruments.qm.sequence.QMPulse] = <factory>, clock: ~typing.Dict[str, int] = <factory>, pulse_finish: ~typing.Dict[int, ~typing.List[~qibolab.instruments.qm.sequence.QMPulse]] = <factory>)[source]#

Bases: object

Pulse sequence containing QM specific pulses (qmpulse). Defined in qibolab.instruments.qm.QMOPX.play(). Holds attributes for the element and operation that corresponds to each pulse, as defined in the QM config.

qmpulses: List[QMPulse]#

List of qibolab.instruments.qm.QMPulse objects corresponding to the original pulses.

ro_pulses: List[QMPulse]#

List of readout pulses used for registering outputs.

pulse_to_qmpulse: Dict[Pulse, QMPulse]#

Map from qibolab pulses to QMPulses (useful when sweeping).

clock: Dict[str, int]#

Dictionary used to keep track of times of each element, in order to calculate wait times.

pulse_finish: Dict[int, List[QMPulse]]#

Map to find all pulses that finish at a given time (useful for _find_previous).

classmethod create(qubits, sequence, sweepers, config, time_of_flight, smearing)[source]#

Translates a qibolab.pulses.PulseSequence to a qibolab.instruments.qm.sequence.Sequence.

Parameters:
Returns:

(qibolab.instruments.qm.Sequence) containing the pulses from given pulse sequence.

add(qmpulse: QMPulse)[source]#
shift()[source]#

Shift all pulses that come after a BakedPulse a bit to avoid overlapping pulses.

play(relaxation_time=0)[source]#

Part of QUA program that plays an arbitrary pulse sequence.

Should be used inside a program() context.

qibolab.instruments.qm.simulator module#

class qibolab.instruments.qm.simulator.QMSim(name: str, address: str, manager: qm.QuantumMachinesManager.QuantumMachinesManager | None = None, config: ~qibolab.instruments.qm.config.QMConfig = <factory>, is_connected: bool = False, time_of_flight: int = 0, smearing: int = 0, _ports: ~typing.Dict[~typing.Tuple[~typing.Tuple[str, int]] | ~typing.Tuple[~typing.Tuple[str, int], ~typing.Tuple[str, int]], ~qibolab.instruments.qm.config.QMPort] = <factory>, script_file_name: str | None = 'qua_script.txt', simulation_duration: int = 1000, cloud: bool = False)[source]#

Bases: QMOPX

Instrument for using the Quantum Machines (QM) OPX simulator.

Parameters:
  • address (str) – Address and port of the simulator.

  • simulation_duration (int) – Duration for the simulation in ns.

  • cloud (bool) – If True the QM cloud simulator is used which does not require access to physical instruments. This assumes that a proper cloud address has been given. If False the simulator built-in the instruments is used. This requires connection to instruments. Default is False.

simulation_duration: int = 1000#
cloud: bool = False#
connect()[source]#

Connect to the QM manager.

static fetch_results(result, ro_pulses)[source]#

Fetches results from an executed experiment.

Defined as @staticmethod because it is overwritten in qibolab.instruments.qm.simulator.QMSim.

execute_program(program)[source]#

Executes an arbitrary program written in QUA language.

Parameters:

program – QUA program.

Returns:

TODO

qibolab.instruments.qm.sweepers module#

qibolab.instruments.qm.sweepers.maximum_sweep_value(values, value0)[source]#

Calculates maximum value that is reached during a sweep.

Useful to check whether a sweep exceeds the range of allowed values. Note that both the array of values we sweep and the center value can be negative, so we need to make sure that the maximum absolute value is within range.

Parameters:
  • values (np.ndarray) – Array of values we will sweep over.

  • value0 (float, int) – Center value of the sweep.

qibolab.instruments.qm.sweepers.sweep(sweepers, qubits, qmsequence, relaxation_time, config)[source]#

Public sweep function that is called by the driver.