Download

Download this file as Jupyter notebook: qubit_iq_distribution.ipynb.

IQ Distribution experiment

This guide shows how to measure the I/Q distribution of both the ground state and excited state of a qubit using a variable amplitude X pulse followed by a measurement.

We can use the pre-defined IQDistributionExperiment and our example calibration set from the experiments library. To start out, we define an empty ChannelMapper to instantiate our experiment for a single qubit.

[2]:
import keysight.qcs as qcs
from keysight.qcs.experiments import IQDistributionExperiment, make_calibration_set

run_on_hw = False

n_qubits = 1
cal_set = make_calibration_set(n_qubits)
qubits = qcs.Qudits(range(n_qubits))

# generate an empty channel mapper
mapper = qcs.ChannelMapper("ip_addr")

iq_experiment = IQDistributionExperiment(mapper, cal_set, qubits)

iq_experiment.draw()
keysight-logo-svg
Program
Program
Duration undefined
Layers 1
Targets 1
Repetitions Repeat with 100 repetitions
Sweep with 2 repetitions
Associations
rx_angles Array(name=scan_values, shape=(2, 1), dtype=float, unit=none)
Layer #0
Layer #0
Duration undefined
qudits 0
RX
ParameterizedGate RX on ('qudits', 0)

Parameters phi_x
Values Array(name=rx_angles, shape=(1,), dtype=float, unit=none)

Matrices
0 1
1 0
Measure on ('qudits', 0)

Parameters
Dim 2

The program consists of a simple RX gate with variable amplitude followed by a measurement. During execution, we set the amplitude of this gate to both zero and one to prepare the ground and excited states.

Compiling this program to the waveform level using the ParameterizedLinkers in the calibration set results in the following program:

[3]:
iq_experiment.compiled_program.draw()
keysight-logo-svg
Program
Program
Duration 130 ns
Layers 1
Targets 3
Repetitions Repeat with 100 repetitions
Sweep with 2 repetitions
Associations
rx_angles Array(name=scan_values, shape=(2, 1), dtype=float, unit=none)
Layer #0
Layer #0
Duration 130 ns
xy_pulse 0
RFWaveform on ('xy_pulse', 0)

Parameters
Duration ScalarRef(name=xy_pulse_durations, value=30 ns, dtype=float, unit=s)
Amplitude ScalarRef(name=_implicit, value=None, dtype=float, unit=none)
Frequency ScalarRef(name=xy_pulse_frequencies, value=5.1 GHz, dtype=float, unit=Hz)
Envelope GaussianEnvelope(2.0)
Instantaneous Phase ScalarRef(name=rx_phase, value=0 rad, dtype=float, unit=rad)
Post-phase ScalarRef(name=rx_post_phase, value=0 rad, dtype=float, unit=rad)
Delay on ('xy_pulse', 0)

Parameters
Duration Max(ScalarRef(name=readout_pulse_duration, value=100 ns, dtype=float, unit=s), ScalarRef(name=acquisition_duration, value=100 ns, dtype=float, unit=s))
readout_pulse 0
Delay on ('readout_pulse', 0)

Parameters
Duration ScalarRef(name=xy_pulse_durations, value=30 ns, dtype=float, unit=s)
RFWaveform on ('readout_pulse', 0)

Parameters
Duration ScalarRef(name=readout_pulse_duration, value=100 ns, dtype=float, unit=s)
Amplitude ScalarRef(name=readout_pulse_amplitudes, value=0.1, dtype=float, unit=none)
Frequency ScalarRef(name=readout_frequencies, value=5.15 GHz, dtype=float, unit=Hz)
Envelope SineEnvelope()
Instantaneous Phase ScalarRef(name=measurement_phase, value=0 rad, dtype=float, unit=rad)
Post-phase ScalarRef(name=measurement_post_phase, value=0 rad, dtype=float, unit=rad)
Delay on ('readout_pulse', 0)

Parameters
Duration Scalar(name=_implicit, value=0 s, dtype=float, unit=s)
readout_acquisition 0
Delay on ('readout_acquisition', 0)

Parameters
Duration ScalarRef(name=xy_pulse_durations, value=30 ns, dtype=float, unit=s)
Acquisition on ('readout_acquisition', 0)

Parameters
Duration ScalarRef(name=acquisition_duration, value=100 ns, dtype=float, unit=s)
Integration Filter
RFWaveform

Parameters
Duration ScalarRef(name=acquisition_duration, value=100 ns, dtype=float, unit=s)
Amplitude ScalarRef(name=measurement_integrator_amplitude, value=1, dtype=float, unit=none)
Frequency ScalarRef(name=readout_frequencies, value=5.15 GHz, dtype=float, unit=Hz)
Envelope ConstantEnvelope()
Instantaneous Phase ScalarRef(name=measurement_integrator_phase, value=0 rad, dtype=float, unit=rad)
Post-phase ScalarRef(name=measurement_integrator_post_phase, value=0 rad, dtype=float, unit=rad)
Classifier Classifier(Array(name=references, shape=(1, 2), dtype=complex, unit=none))
Delay on ('readout_acquisition', 0)

Parameters
Duration Scalar(name=_implicit, value=0 s, dtype=float, unit=s)

The RX pulse has been replaced by an appropriately modulated Gaussian pulse and the measurement waveform and simultaneous acquisition have been added on a separate virtual readout channel.

We can also use the render method to visualize the waveform sequence within this program.

[4]:
iq_experiment.compiled_program.render(
    channel_subplots=False,
    lo_frequency=5e9,
    sweep_index=1,
    sample_rate=5e9,
)

To execute this experiment, we can simply run

[5]:
if run_on_hw:
    iq_experiment.execute()
else:
    # load in a previously executed version of this experiment
    iq_experiment = qcs.load("IQDistribution.qcs")

For the purposes of this demonstration, we added a second “ancilla” qubit to the IQ distribution program and connected the physical output channels for our qubit to the digizer associated with the ancilla to allow us to capture the full pulse sequence.

[6]:
iq_experiment.draw()
keysight-logo-svg
Program
Program
Duration undefined
Layers 1
Targets 2
Repetitions Sweep with 2 repetitions
Associations
rx_angles Array(name=scan_values, shape=(2, 1), dtype=float, unit=none)
Repeat with 1 repetitions
Layer #0
Layer #0
Duration undefined
qudits 0
RX
ParameterizedGate RX on ('qudits', 0)

Parameters phi_x
Values Array(name=rx_angles, shape=(1,), dtype=float, unit=none)

Matrices
0 1
1 0
Measure on ('qudits', 0)

Parameters
Dim 2
ancilla 1
Measure on ('ancilla', 1)

Parameters
Dim 2
[7]:
iq_experiment.compiled_program.draw()
keysight-logo-svg
Program
Program
Duration 130 ns
Layers 1
Targets 4
Repetitions Sweep with 2 repetitions
Associations
rx_angles Array(name=scan_values, shape=(2, 1), dtype=float, unit=none)
Repeat with 1 repetitions
Layer #0
Layer #0
Duration 130 ns
xy_pulse 0
RFWaveform on ('xy_pulse', 0)

Parameters
Duration ScalarRef(name=xy_pulse_durations, value=30 ns, dtype=float, unit=s)
Amplitude ScalarRef(name=_implicit, value=None, dtype=float, unit=none)
Frequency ScalarRef(name=xy_pulse_frequencies, value=5.1 GHz, dtype=float, unit=Hz)
Envelope GaussianEnvelope(2.0)
Instantaneous Phase ScalarRef(name=rx_phase, value=0 rad, dtype=float, unit=rad)
Post-phase ScalarRef(name=rx_post_phase, value=0 rad, dtype=float, unit=rad)
Delay on ('xy_pulse', 0)

Parameters
Duration Max(ScalarRef(name=readout_pulse_duration, value=100 ns, dtype=float, unit=s), ScalarRef(name=acquisition_duration, value=100 ns, dtype=float, unit=s))
readout_pulse 0
Delay on ('readout_pulse', 0)

Parameters
Duration ScalarRef(name=xy_pulse_durations, value=30 ns, dtype=float, unit=s)
RFWaveform on ('readout_pulse', 0)

Parameters
Duration ScalarRef(name=readout_pulse_duration, value=100 ns, dtype=float, unit=s)
Amplitude ScalarRef(name=readout_pulse_amplitudes, value=0.1, dtype=float, unit=none)
Frequency ScalarRef(name=readout_frequencies, value=5.15 GHz, dtype=float, unit=Hz)
Envelope SineEnvelope()
Instantaneous Phase ScalarRef(name=measurement_phase, value=0 rad, dtype=float, unit=rad)
Post-phase ScalarRef(name=measurement_post_phase, value=0 rad, dtype=float, unit=rad)
Delay on ('readout_pulse', 0)

Parameters
Duration Scalar(name=_implicit, value=0 s, dtype=float, unit=s)
readout_acquisition 0
Delay on ('readout_acquisition', 0)

Parameters
Duration ScalarRef(name=xy_pulse_durations, value=30 ns, dtype=float, unit=s)
Acquisition on ('readout_acquisition', 0)

Parameters
Duration ScalarRef(name=acquisition_duration, value=100 ns, dtype=float, unit=s)
Integration Filter
RFWaveform

Parameters
Duration ScalarRef(name=acquisition_duration, value=100 ns, dtype=float, unit=s)
Amplitude ScalarRef(name=measurement_integrator_amplitude, value=1, dtype=float, unit=none)
Frequency ScalarRef(name=readout_frequencies, value=5.15 GHz, dtype=float, unit=Hz)
Envelope ConstantEnvelope()
Instantaneous Phase ScalarRef(name=measurement_integrator_phase, value=0 rad, dtype=float, unit=rad)
Post-phase ScalarRef(name=measurement_integrator_post_phase, value=0 rad, dtype=float, unit=rad)
Classifier Classifier(Array(name=references, shape=(1, 2), dtype=complex, unit=none))
Delay on ('readout_acquisition', 0)

Parameters
Duration Scalar(name=_implicit, value=0 s, dtype=float, unit=s)
1
Acquisition on ('readout_acquisition', 1)

Parameters
Duration Scalar(name=_implicit, value=40 ns, dtype=float, unit=s)
Integration Filter
DCWaveform

Parameters
Duration Scalar(name=_implicit, value=40 ns, dtype=float, unit=s)
Amplitude 1
Frequency 0 Hz
Envelope ConstantEnvelope()
Instantaneous Phase 0
Post-phase 0

The ancilla qubit is mapped to the digitizer channel 1 and has a single acquisition that spans the duration of the control pulse.

[8]:
iq_experiment.plot_trace()

Here we can see the control pulse with amplitudes zero or one, followed by the readout pulse. Note that our local oscillator (LO) frequency was set to 5 GHz in this example.

And to look at the IQ distribution, we can plot the IQ data as a scatter plot. This data was taken with a simple constant integration filter.

[9]:
iq_experiment.plot_iq(channels=qcs.Qudits(1, "ancilla"), plot_type="scatter")

Download

Download this file as Jupyter notebook: qubit_iq_distribution.ipynb.

On this page