Download

Download this file as Jupyter notebook: live_plotting.ipynb.

Live Plotting

The QCS is able to display live plots for the IQ data of programs while they are running. Currently the only programs capable of running live plots are one-dimensional and two-dimensional software sweeps. The HclBackend must also be set with hw_demod = True.

In order to enable live plotting, set the live_plotting_config parameter on HclBackend with the channels to visualize.

Live plotting on a program

[2]:
import keysight.qcs as qcs
import numpy as np
[3]:

# Define a channel mapper or load one from file. channel_mapper_exists = False if channel_mapper_exists: mapper = qcs.load("<path/to/channel_mapper.qcs>") else: # generate an empty channel mapper with the correct address mapper = qcs.ChannelMapper("127.0.0.1") readout_pulse_channels = qcs.Channels([0, 1], "readout_pulse", absolute_phase=True) readout_acquisition_channels = qcs.Channels( [0, 1], "readout_acquisition", absolute_phase=True )
[4]:
# Define a program to run
program = qcs.Program()
frequency = qcs.Scalar("frequency", dtype=float)
waveform = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(), 1, frequency)
int_filter = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(), 1, [5.1e9, 5.15e9])
program.add_waveform(waveform, readout_pulse_channels)
program.add_acquisition(int_filter, readout_acquisition_channels)
program.n_shots(50)
frequencies = qcs.Array("frequencies", value=np.linspace(5e9, 5.25e9, 50))
program.sweep(frequencies, frequency)
program.draw()
keysight-logo-svg
Program
Program
Duration 80 ns
Layers 1
Targets 4
Repetitions Sweep with 50 repetitions
Associations
frequency Array(name=frequencies, shape=(50,), dtype=float, unit=none, value=[5 GHz, 5.0051 GHz, 5.0102 GHz, 5.01531 GHz, 5.02041 GHz, 5.02551 GHz, 5.03061 GHz, 5.03571 GHz, 5.04082 GHz, 5.04592 GHz, ... ])
Repeat with 50 repetitions
Layer #0
Layer #0
Duration 80 ns
readout_pulse 0
RFWaveform on ('readout_pulse', 0)

Parameters
Duration 80 ns
Amplitude 1
Frequency Scalar(name=frequency, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
RFWaveform on ('readout_pulse', 1)

Parameters
Duration 80 ns
Amplitude 1
Frequency Scalar(name=frequency, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
readout_acquisition 0
Acquisition on ('readout_acquisition', 0)

Parameters
Duration 80 ns
Integration Filter
RFWaveform

Parameters
Duration 80 ns
Amplitude 1
Frequency [5.1 GHz, 5.15 GHz]
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
Acquisition on ('readout_acquisition', 1)

Parameters
Duration 80 ns
Integration Filter
RFWaveform

Parameters
Duration 80 ns
Amplitude 1
Frequency [5.1 GHz, 5.15 GHz]
Envelope GaussianEnvelope(2.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
[5]:
# Setup live plotting to display the two digitizer channels
backend = qcs.HclBackend(
    channel_mapper=mapper,
    hw_demod=True,
    live_plotting_config=readout_acquisition_channels,
)
[6]:
# Set this to True if connected to hardware
run_on_hw = False

if run_on_hw:
    # Execute the program.
    # While running, live IQ data for the frequency sweep will be shown.
    program_result = qcs.Executor(backend).execute(program)

    # Plot the "static" version of the plot to compare the results
    program_result.plot_iq(channel_subplots=False, plot_type="linear")

Live plotting on an experiment

Live plotting can also be setup to run on experiments. Here we show an example of setting up live plotting to run with a 2D spectroscopy experiment. See Resonator Spectroscopy for more details on setting up this experiment.

[7]:
qubits = qcs.Qudits([0, 1])
calibration_set = qcs.experiments.make_calibration_set(qubits=len(qubits))
[8]:
# Create a resonator spectroscopy experiment with live plotting
# Note that the channels for live plotting match the channels from the calibration set.
backend = qcs.HclBackend(
    channel_mapper=mapper,
    hw_demod=True,
    live_plotting_config=readout_acquisition_channels,
)

res_spectroscopy2D = qcs.experiments.ResonatorSpectroscopy2D(
    backend=backend,
    calibration_set=calibration_set,
    qubits=qubits,
    operation="measurement",
)
[9]:
# Draw the program to view the operations to be performed on hardware
res_spectroscopy2D.draw()
keysight-logo-svg
Program
Program
Duration 105 ns
Layers 1
Targets 4
Repetitions
Layer #0
Layer #0
Duration 105 ns
readout_pulse 0
Delay on ('readout_pulse', 0)

Parameters
Duration ArraySlice(name=readout_pulse_delay, shape=(2,), dtype=float, unit=s, value=[0 s, 0 s])
RFWaveform on ('readout_pulse', 0)

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

Parameters
Duration Scalar(name=_implicit, value=5 ns, dtype=float, unit=s)
1
Delay on ('readout_pulse', 1)

Parameters
Duration ArraySlice(name=readout_pulse_delay, shape=(2,), dtype=float, unit=s, value=[0 s, 0 s])
RFWaveform on ('readout_pulse', 1)

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

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

Parameters
Duration ArraySlice(name=acquisition_delay, shape=(2,), dtype=float, unit=s, value=[5 ns, 5 ns])
Acquisition on ('readout_acquisition', 0)

Parameters
Duration Array(name=_implicit, shape=(2,), dtype=float, unit=s, value=[100 ns, 100 ns])
Integration Filter
RFWaveform

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

Parameters
Duration Scalar(name=_implicit, value=4.96308e-24 s, dtype=float, unit=s)
1
Delay on ('readout_acquisition', 1)

Parameters
Duration ArraySlice(name=acquisition_delay, shape=(2,), dtype=float, unit=s, value=[5 ns, 5 ns])
Acquisition on ('readout_acquisition', 1)

Parameters
Duration Array(name=_implicit, shape=(2,), dtype=float, unit=s, value=[100 ns, 100 ns])
Integration Filter
RFWaveform

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

Parameters
Duration Scalar(name=_implicit, value=4.96308e-24 s, dtype=float, unit=s)

Next, we define the sweep values for both the amplitude and frequency of the readout pulse.

[10]:
# Retrieve the readout frequencies stored in the calibration set for the target qubits
current_freq = res_spectroscopy2D.calibration_set.variables.readout_frequencies[
    [0, 1]
].value

# Set the range for sweeping the readout pulse frequency
start_frequency = current_freq - 200e6
end_frequency = current_freq + 200e6
freq_steps = 9
freq_scan_values = np.linspace(start_frequency, end_frequency, freq_steps)
[11]:
# Set the range for sweeping the readout pulse amplitude (units = V)
start_amplitude = 0.1 if len(qubits) == 1 else [0.1] * len(qubits)
end_amplitude = 1 if len(qubits) == 1 else [1] * len(qubits)
ampl_steps = 10
ampl_scan_values = np.linspace(start_amplitude, end_amplitude, ampl_steps)
[12]:
# Configure the repetitions for this experiment
res_spectroscopy2D.configure_repetitions(
    frequencies=freq_scan_values,
    frequency_name="readout_frequencies",
    amplitudes=ampl_scan_values,
    amplitude_name="readout_pulse_amplitudes",
    n_shots=10,
)

We can now execute the experiment and see the live 2D heatmaps.

[13]:
if run_on_hw:
    res_spectroscopy2D.execute()

Download

Download this file as Jupyter notebook: live_plotting.ipynb.

On this page