Download
Download this file as Jupyter notebook: simulated_experiment.ipynb.
Loading Simulated Experiment data
This section explains how to load simulated experiment data using the mock_data parameter. The mock_data parameter allows you to test and analyze experiments without requiring actual hardware execution.
The mock_data parameter should be structured as follows:
Keys: Instances of Channels representing the channels used in the experiment.
Values: Iterables containing the simulated data for each channel.
Example usage:
mock_data = {
channel_1: [trace_data_1, trace_data_2, ...],
channel_2: [trace_data_1, trace_data_2, ...],
qubit_1: [trace_data_1, trace_data_2, ...],
...
}
[2]:
import keysight.qcs as qcs
from keysight.qcs.experiments import Experiment, make_calibration_set
import numpy as np
Before creating the Experiment
with mock_data, we need a
ChannelMapper
and Program
object to tell the
Experiment
class for what data structure to expect for
mock_data.
Creating a dummy ChannelMapper
ChannelMapper
is required to configure the number of channels
available for acquisition, and how many number of channel-data to expect in mock_data.
The dimension of the accepted program is [n_shots, sweep_a, sweep_b, …, n_points]
n_shots: Number of program repetitions
sweep_a, sweep_b, …: Sweep variables
n_points: number of accepted points by the
IntegrationFilter
to covert trace data into IQ data.
[3]:
n_channels = 2
n_qubits = 2
n_points = 240 # points accepted by the integration filter
qubits = qcs.Qudits(range(n_qubits))
channels = qcs.Channels(range(n_channels), "xy_channels", absolute_phase=False)
mapper = qcs.ChannelMapper("dummy")
# assigning dummy physical addresses to the channels
for i in range(n_channels):
mapper.add_channel_mapping(
channels=channels[i],
addresses=qcs.Address(1, 1, i + 1),
instrument_types=qcs.InstrumentEnum.M5300AWG,
)
Loading a simple Sweep Program and Data
The Program
class gives information what dimension of data to expect
from mock_data. The program can be a simple non-iterating program, a normal sweep,
a nested sweep, or a zipped sweep. The data shape is determined by the structure of
program.repetitions.items.
Here, we will load data for a simple amplitude sweep program.
[4]:
n_shots = 7
num_amps = 13 # number of amplitude points to sweep on
program = qcs.Program()
amplitude = qcs.Scalar("amplitude", dtype=float)
phase = qcs.Scalar("phase", dtype=float)
amps = qcs.Array("amps", value=np.linspace(0, 0.8, num_amps), dtype=float)
waveform = qcs.RFWaveform(
duration=20e-9,
envelope=qcs.GaussianEnvelope(),
amplitude=amplitude,
rf_frequency=5.1e9,
)
program.add_waveform(waveform, channels)
int_filter = qcs.RFWaveform(10e-8, qcs.ConstantEnvelope(), 1, 5.15e9)
program.add_acquisition(int_filter, channels)
program.sweep(amps, amplitude).n_shots(n_shots)
# The shape of the accepted data must account for these dimensions
for i in program.repetitions.items:
print(i)
Repeat(7)
Sweep(amplitude=Array(name=amps, shape=(13,), dtype=float, unit=none))
Defining mock data and loading into the Experiment:
[5]:
hw_demod = False
# acceptable data shape
shape = [n_shots, num_amps, n_points]
# generate mock trace data
mock_data = dict()
for chan in channels:
mock_data[chan] = np.random.random(shape)
# load the mock_data using the mock_data parameter in the Experiment class
backend = qcs.HclBackend(mapper, hw_demod=hw_demod)
exp = Experiment(backend, make_calibration_set(2), qubits, program, mock_data=mock_data)
exp.get_iq() # or exp.get_trace()
[5]:
(((Channels(labels=[0], name=xy_channels, absolute_phase=False)))) | ... | (((Channels(labels=[1], name=xy_channels, absolute_phase=False)))) | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | ... | 6 | |||||||||||||||||||
(amplitude, 0) | (amplitude, 0.0667) | (amplitude, 0.1333) | (amplitude, 0.2) | (amplitude, 0.2667) | (amplitude, 0.3333) | (amplitude, 0.4) | (amplitude, 0.4667) | (amplitude, 0.5333) | (amplitude, 0.6) | ... | (amplitude, 0.2) | (amplitude, 0.2667) | (amplitude, 0.3333) | (amplitude, 0.4) | (amplitude, 0.4667) | (amplitude, 0.5333) | (amplitude, 0.6) | (amplitude, 0.6667) | (amplitude, 0.7333) | (amplitude, 0.8) | |
0 | 0.031249-0.026000j | -0.031621-0.012998j | -0.011636-0.015886j | 0.004438-0.019826j | 0.023532+0.034597j | -0.019214+0.049735j | -0.006032-0.034850j | 0.026803+0.008326j | 0.002084+0.007049j | 0.000282-0.017490j | ... | 0.004098+0.004213j | -0.006963-0.041617j | -0.017787+0.002688j | 0.025167+0.012283j | 0.029283+0.059102j | -0.039216+0.030935j | -0.024009-0.028680j | 0.018269+0.040368j | -0.020776+0.012157j | -0.007685-0.010754j |
1 rows × 182 columns
Nested Sweeps with mock_data
Moving on to more complicated sweeps, we just have to that the shape of program.repetitions.items and our data matches.
[6]:
n_shots = 7
num_a = 13 # number of points to sweep on
num_b = 17 # number of points to sweep on
qubits = qcs.Qudits(range(n_qubits))
channels = qcs.Channels(range(n_channels), "xy_channels", absolute_phase=False)
program = qcs.Program()
amplitude = qcs.Scalar("amplitude", dtype=float)
phase = qcs.Scalar("phase", dtype=float)
amps = qcs.Array("amps", value=np.linspace(0, 0.8, num_a), dtype=float)
phases = qcs.Array("phases", value=np.linspace(0, np.pi, num_b), dtype=float)
waveform = qcs.RFWaveform(
duration=20e-9,
envelope=qcs.GaussianEnvelope(),
amplitude=amplitude,
rf_frequency=5.1e9,
instantaneous_phase=phase,
)
program.add_waveform(waveform, channels)
int_filter = qcs.RFWaveform(10e-8, qcs.ConstantEnvelope(), 1, 5.15e9)
program.add_acquisition(int_filter, channels)
program.sweep(amps, amplitude).sweep(phases, phase).n_shots(n_shots)
for i in program.repetitions.items:
print(i)
Repeat(7)
Sweep(phase=Array(name=phases, shape=(17,), dtype=float, unit=none))
Sweep(amplitude=Array(name=amps, shape=(13,), dtype=float, unit=none))
Defining and loading mock_data
[7]:
hw_demod = False
shape = [n_shots, num_a, num_b, n_points]
mock_data = dict()
for chan in channels:
mock_data[chan] = np.random.random(shape)
backend = qcs.HclBackend(mapper, hw_demod=hw_demod)
exp = Experiment(backend, make_calibration_set(2), qubits, program, mock_data=mock_data)
exp.get_iq() # OR exp.get_trace()
[7]:
(((Channels(labels=[0], name=xy_channels, absolute_phase=False)))) | ... | (((Channels(labels=[1], name=xy_channels, absolute_phase=False)))) | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | ... | 6 | |||||||||||||||||||
(phase, 0 rad) | ... | (phase, 3.1415926536 rad) | |||||||||||||||||||
(amplitude, 0) | (amplitude, 0.0667) | (amplitude, 0.1333) | (amplitude, 0.2) | (amplitude, 0.2667) | (amplitude, 0.3333) | (amplitude, 0.4) | (amplitude, 0.4667) | (amplitude, 0.5333) | (amplitude, 0.6) | ... | (amplitude, 0.2) | (amplitude, 0.2667) | (amplitude, 0.3333) | (amplitude, 0.4) | (amplitude, 0.4667) | (amplitude, 0.5333) | (amplitude, 0.6) | (amplitude, 0.6667) | (amplitude, 0.7333) | (amplitude, 0.8) | |
0 | -0.019448+0.013503j | -0.002012-0.028937j | -0.021066+0.015633j | 0.007827+0.058362j | 0.090904+0.036831j | -0.004793-0.021340j | 0.037485+0.056948j | 0.014964+0.028572j | -0.023797+0.026929j | -0.044831+0.006169j | ... | 0.012186+0.042002j | 0.011547-0.022397j | 0.025953+0.012802j | -0.045448-0.013421j | -0.052819-0.031184j | -0.005990+0.024468j | 0.037878-0.016779j | 0.017988-0.010031j | -0.089399-0.027104j | -0.025709-0.016623j |
1 rows × 3094 columns
Zipped Sweeps with mock_data
Zipped sweeps have special structure in program.repetitions.items
[8]:
num_a = 13
# program
qubits = qcs.Qudits(range(n_channels))
channels = qcs.Channels(range(n_channels), "xy_channels", absolute_phase=False)
program = qcs.Program()
amplitude = qcs.Scalar("amplitude", dtype=float)
phase = qcs.Scalar("phase", dtype=float)
amps = qcs.Array("amps", value=np.linspace(0, 0.8, num_a), dtype=float)
phases = qcs.Array("phases", value=np.linspace(0, np.pi, num_a), dtype=float)
waveform = qcs.RFWaveform(
duration=20e-9,
envelope=qcs.GaussianEnvelope(),
amplitude=amplitude,
rf_frequency=5.1e9,
instantaneous_phase=phase,
)
program.add_waveform(waveform, channels)
int_filter = qcs.RFWaveform(10e-8, qcs.ConstantEnvelope(), 1, 5.15e9)
program.add_acquisition(int_filter, channels)
program.sweep((amps, phases), (amplitude, phase)).n_shots(n_shots)
for i in program.repetitions.items:
print(i)
Repeat(7)
Sweep(amplitude=Array(name=amps, shape=(13,), dtype=float, unit=none), phase=Array(name=phases, shape=(13,), dtype=float, unit=none))
Defining and loading mock_data
[9]:
# mock_data
shape = [n_shots, num_a, n_points]
mock_data = dict()
for chan in channels:
mock_data[chan] = np.random.random(shape)
# test for each mock_data
backend = qcs.HclBackend(mapper, hw_demod=hw_demod)
exp = Experiment(backend, make_calibration_set(2), qubits, program, mock_data=mock_data)
exp.get_iq() # OR exp.get_trace()
[9]:
(((Channels(labels=[0], name=xy_channels, absolute_phase=False)))) | ... | (((Channels(labels=[1], name=xy_channels, absolute_phase=False)))) | |||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | ... | 6 | |||||||||||||||||||
(amplitude, 0), (phase, 0 rad) | (amplitude, 0.0667), (phase, 261.8 mrad) | (amplitude, 0.1333), (phase, 523.6 mrad) | (amplitude, 0.2), (phase, 785.4 mrad) | (amplitude, 0.2667), (phase, 1.0471975512 rad) | (amplitude, 0.3333), (phase, 1.308996939 rad) | (amplitude, 0.4), (phase, 1.5707963268 rad) | (amplitude, 0.4667), (phase, 1.8325957146 rad) | (amplitude, 0.5333), (phase, 2.0943951024 rad) | (amplitude, 0.6), (phase, 2.3561944902 rad) | ... | (amplitude, 0.2), (phase, 785.4 mrad) | (amplitude, 0.2667), (phase, 1.0471975512 rad) | (amplitude, 0.3333), (phase, 1.308996939 rad) | (amplitude, 0.4), (phase, 1.5707963268 rad) | (amplitude, 0.4667), (phase, 1.8325957146 rad) | (amplitude, 0.5333), (phase, 2.0943951024 rad) | (amplitude, 0.6), (phase, 2.3561944902 rad) | (amplitude, 0.6667), (phase, 2.617993878 rad) | (amplitude, 0.7333), (phase, 2.8797932658 rad) | (amplitude, 0.8), (phase, 3.1415926536 rad) | |
0 | -0.010586-0.003072j | 0.002063-0.035717j | -0.026939-0.029382j | 0.013823+0.022923j | -0.026898-0.002183j | 0.018640-0.039584j | -0.002380+0.035292j | -0.010906+0.019501j | 0.021480+0.010561j | 0.016323-0.012088j | ... | 0.030539+0.008261j | 0.027897-0.048971j | 0.020939+0.028002j | -0.004342+0.002680j | -0.008071-0.035649j | 0.005053-0.000899j | -0.038410-0.023571j | 0.006008+0.012163j | 0.035101-0.045239j | -0.014720+0.011348j |
1 rows × 182 columns
Example for a Qubit level program
For qubit level program, the user need to additionally take care of the calibration set and the application of LinkerPass to the program, as shown below:
[10]:
# channel mapper
n_channels = 2
n_qubits = 2
n_points = 240 # points accepted by the integration filter
mapper = qcs.ChannelMapper("dummy")
# channel_acq required for qubit-type mock_data
# our default function qcs.experiments.make_calibration_set` creates channels with
# name="readout_acquisition", and supporting linkers for it.
channels_acq = qcs.Channels(
range(n_channels), "readout_acquisition", absolute_phase=True
)
# assigning dummy physical addresses to the channels
for i in range(n_channels):
mapper.add_channel_mapping(
channels=channels_acq[i],
addresses=qcs.Address(2, 1, i + 1),
instrument_types=qcs.InstrumentEnum.M5300AWG,
)
Defining the program and other components:
[11]:
n_shots = 7
num_amps = 13 # number of amplitude points to sweep on
hw_demod = False
qubits = qcs.Qudits(range(n_channels))
channels_acq = qcs.Channels(
range(n_channels), "readout_acquisition", absolute_phase=True
)
program = qcs.Program()
program.add_measurement(qubits)
program.n_shots(n_shots)
# Additional steps: Defining the calibration set and applying LinkerPass
cal_set = make_calibration_set(n_channels)
program = qcs.LinkerPass(*cal_set.linkers.values()).apply(program)
# mock_data for qubits
mock_data = dict()
for qub in qubits:
mock_data[qub] = np.random.random((n_shots, n_points))
backend = qcs.HclBackend(mapper, hw_demod=hw_demod)
exp = Experiment(backend, make_calibration_set(2), qubits, program, mock_data=mock_data)
exp.get_iq()
[11]:
(((Qudits(labels=[0], name=qudits, dim=2)))) | (((Qudits(labels=[1], name=qudits, dim=2)))) | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | |
0 | -0.029511+0.003492j | 0.000815-0.028222j | -0.015486-0.010311j | -0.052808+0.017443j | 0.017927+0.033257j | 0.007270-0.001728j | 0.002164+0.004423j | -0.030739-0.010229j | 0.028088+0.035851j | 0.021961-0.000595j | 0.032344-0.029078j | -0.001332-0.001276j | -0.002384+0.003196j | -0.008209-0.009716j |
Download
Download this file as Jupyter notebook: simulated_experiment.ipynb.