Download

Download this file as Jupyter notebook: sweep_examples.ipynb.

Sweeping program variables#

The Running a program on hardware tutorial covers the basic workflow for running experiments on hardware and extracting trace data and I/Q data. Here we expand on that and add sweeps to the programs.

Setting up#

As before, we use two AWG channels and two digitizers.

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

# set the following to True when connected to hardware:
run_on_hw = False

# instantiate channels representing two AWGs and two digitizers
awgs = qcs.Channels(range(2), "readoutawg")
digs = qcs.Channels(range(2), "readoutreceiver")

# load our channel mapper to connect the virtual channels above to physical ones
mapper = qcs.load("../../assets/channel_mapper.qcs")

Single variable sweeps#

We define a program that plays a single RF waveform on our AWG channels and performs an acquisition on the digitizer channels with an IntegrationFilterto perform I/Q demodulation of the trace data.

We are sweeping the frequency of the RF pulse but keep the frequency of the integration filter constant.

[3]:
# define the frequency and amplitude of our RF waveform as QCS variables
frequency = qcs.Scalar("rf", dtype=float)
amplitude = qcs.Scalar("amp", dtype=float, value=1)


def make_program():
    """Creates a simple program with a single RF waveform"""
    program = qcs.Program()
    # define the waveform using this frequency variable & add it to the program
    gauss = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(num_sigma=4), 1, frequency)
    program.add_waveform(gauss, awgs)

    # define an integration filter using the same RF waveform but with fixed frequency
    int_filter = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(num_sigma=4), 1, 4.15e9)
    program.add_acquisition(int_filter, digs)

    # specify the number of shots
    return program.n_shots(10)


program = make_program()

# specify the frequency values to be swept over
frequencies = qcs.Array(
    "frequencies", value=[4.05e9, 4.1e9, 4.15e9, 4.2e9, 4.25e9], dtype=float
)

# add the sweep, targeting the `frequency` variable
program.sweep(frequencies, frequency)

program.draw()
Program
Sweep Details:
Repetitions Sweep with 5 repetitions
Associations
rf Array(name=frequencies, shape=(5,), dtype=float, unit=none, value=[4.05 GHz, 4.1 GHz, 4.15 GHz, 4.2 GHz, 4.25 GHz])
(SW)Sweep_rf
Sweep Details:
Repetitions Repeat with 10 repetitions
(HW)Repeat(10)
keysight-logo-svg
Program Body
Program
Duration 80 ns
Layers 1
Targets 4
Layer #0
Layer #0
Duration 80 ns
readoutawg 0
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency Scalar(name=rf, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency Scalar(name=rf, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
readoutreceiver 0
Acquisition on ('readoutreceiver', 0)

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

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency 4.15 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
Acquisition on ('readoutreceiver', 1)

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

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency 4.15 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad

We can inspect the sweep settings on the program visualization by hovering over the table header. Alternatively, we can retrieve them through the repetitions attribute:

[4]:
print(program.repetitions.items)
[Sweep(rf=Array(name=frequencies, shape=(5,), dtype=float, unit=none)), Repeat(10)]

Next, we execute the program on hardware.

[5]:
if run_on_hw:
    # initialize the backend pass
    backend = qcs.HclBackend(channel_mapper=mapper)
    # the executor returns the program populated with results
    program = qcs.Executor(backend).execute(program)
    # (optional) export the data to an HDF5 file
    program.to_hdf5("program2.hdf5")

# we are loading a previously run program here for this example
program = qcs.load("program2.hdf5")

The results will now consist of five traces for each sweep point and for each channel.

[6]:
program.plot_trace()

We can retrieve the I/Q data by calling the get_iq_pandas() method, which returns a dataframe that has the sweep values in its column header.

[7]:
program.get_iq_pandas(stack_channels=True)
[7]:
(rf, 4.05 GHz) ... (rf, 4.25 GHz)
0 1 2 3 4 5 6 7 8 9 ... 0 1 2 3 4 5 6 7 8 9
(((readoutreceiver_0))) 0.002351-0.002617j 0.001562-0.003162j 0.001999-0.003444j 0.002334-0.002812j 0.001619-0.003178j 0.001974-0.003325j 0.002244-0.002614j 0.001584-0.003135j 0.001894-0.003386j 0.002325-0.002754j ... -0.000353-0.000242j -0.000056+0.000357j 0.000290-0.000252j -0.000126-0.000030j 0.000081+0.000200j 0.000281-0.000253j -0.000226-0.000165j 0.000205+0.000234j 0.000370-0.000073j -0.000272-0.000114j
(((readoutreceiver_1))) -0.003926-0.002629j -0.002427-0.001740j -0.002129-0.000508j -0.003600-0.001572j -0.002188-0.001321j -0.001880-0.000612j -0.004357-0.002121j -0.002159-0.002206j -0.002250-0.000615j -0.004123-0.002111j ... 0.000047-0.000634j -0.000227+0.000729j 0.000404+0.000285j -0.000619-0.000269j -0.000079+0.000723j 0.000246+0.000136j -0.000124-0.000674j -0.000112+0.000165j 0.000463-0.000247j -0.000024-0.000089j
(((readoutreceiver_2))) 0.004186-0.001393j 0.004653-0.001658j 0.004354-0.000896j 0.004046-0.001135j 0.004784-0.001412j 0.004066-0.000832j 0.003935-0.001297j 0.004887-0.001311j 0.004025-0.000916j 0.004254-0.001515j ... 0.000401-0.000258j -0.000200-0.000369j -0.000081+0.000279j 0.000265-0.000322j -0.000437-0.000284j -0.000292+0.000412j 0.000202-0.000232j -0.000108-0.000409j 0.000152+0.000226j 0.000329-0.000201j
(((readoutreceiver_3))) 0.003129+0.001425j 0.003441+0.001442j 0.002865+0.002030j 0.003196+0.001574j 0.003758+0.001457j 0.003232+0.002031j 0.002919+0.001560j 0.003477+0.001332j 0.002991+0.002071j 0.003148+0.001320j ... -0.000067+0.000023j -0.000269-0.000081j -0.000009+0.000215j 0.000104+0.000032j -0.000207+0.000012j 0.000041+0.000437j 0.000226-0.000166j -0.000123-0.000006j 0.000186+0.000372j 0.000137-0.000029j

4 rows × 50 columns

We can extract data for a sweep and repeat using the following

[8]:
df = program.get_iq_pandas(stack_channels=True)
channel0_rf_4_05_data = df["(rf, 4.05 GHz)"]["0"][digs[0]]
channel0_rf_4_05_data
[8]:
(0.0023512427568418183-0.0026169676054433096j)

This is the data for channel (labels=[0], name=readoutreceiver), 4.05 GHz frequency and 0th repeat.

Also, using the results class we can get the data directly as a numpy array:

[9]:
program.results.get_iq()[digs[0]]
[9]:
array([[ 2.35124276e-03-2.61696761e-03j,  1.56245443e-03-3.16220147e-03j,
         1.99869235e-03-3.44414807e-03j,  2.33420904e-03-2.81241797e-03j,
         1.61864528e-03-3.17826601e-03j,  1.97415616e-03-3.32476444e-03j,
         2.24370314e-03-2.61436829e-03j,  1.58411493e-03-3.13454107e-03j,
         1.89427713e-03-3.38570377e-03j,  2.32488827e-03-2.75443529e-03j],
       [ 9.03837221e-03-1.31979863e-02j, -1.60448812e-02-1.15120579e-03j,
         6.88682387e-03+1.43951763e-02j,  9.14083963e-03-1.32208673e-02j,
        -1.60652258e-02-1.13517492e-03j,  6.92790761e-03+1.45518245e-02j,
         9.04989827e-03-1.29691433e-02j, -1.59535191e-02-1.09506675e-03j,
         7.00933728e-03+1.45844746e-02j,  9.11382591e-03-1.31389008e-02j],
       [-9.69921596e-02+1.41306446e-01j, -9.68726013e-02+1.41300715e-01j,
        -9.66008497e-02+1.41492925e-01j, -9.66862182e-02+1.41401766e-01j,
        -9.67742680e-02+1.41309223e-01j, -9.70541093e-02+1.41359629e-01j,
        -9.68253698e-02+1.41451627e-01j, -9.64496395e-02+1.41546603e-01j,
        -9.70479037e-02+1.41218335e-01j, -9.67055504e-02+1.41535448e-01j],
       [ 6.32470779e-03-9.17958610e-03j,  4.52432357e-03+1.00455726e-02j,
        -1.11222287e-02-1.06291578e-03j,  6.35371604e-03-9.03682141e-03j,
         4.56529070e-03+1.01961803e-02j, -1.09632058e-02-1.02351663e-03j,
         6.24255967e-03-9.00895436e-03j,  4.78976786e-03+1.02531960e-02j,
        -1.10242711e-02-1.02314139e-03j,  6.49037177e-03-8.99366121e-03j],
       [-3.52554585e-04-2.42393203e-04j, -5.56220660e-05+3.56588658e-04j,
         2.89539537e-04-2.52136938e-04j, -1.25781980e-04-2.96531565e-05j,
         8.11054827e-05+2.00224330e-04j,  2.81490092e-04-2.52850340e-04j,
        -2.25801394e-04-1.64635471e-04j,  2.04950458e-04+2.34214862e-04j,
         3.69634580e-04-7.28241968e-05j, -2.71968595e-04-1.13773288e-04j]])

We can extract data for a sweep, repeat, acquisition using the following:

[10]:
xarray_data = program.get_iq_array()
xarray_data
[10]:
<xarray.DataArray (channel: 4, rf: 5, shot: 10)> Size: 3kB
array([[[ 2.35124276e-03-2.61696761e-03j,
          1.56245443e-03-3.16220147e-03j,
          1.99869235e-03-3.44414807e-03j,
          2.33420904e-03-2.81241797e-03j,
          1.61864528e-03-3.17826601e-03j,
          1.97415616e-03-3.32476444e-03j,
          2.24370314e-03-2.61436829e-03j,
          1.58411493e-03-3.13454107e-03j,
          1.89427713e-03-3.38570377e-03j,
          2.32488827e-03-2.75443529e-03j],
        [ 9.03837221e-03-1.31979863e-02j,
         -1.60448812e-02-1.15120579e-03j,
          6.88682387e-03+1.43951763e-02j,
          9.14083963e-03-1.32208673e-02j,
         -1.60652258e-02-1.13517492e-03j,
          6.92790761e-03+1.45518245e-02j,
          9.04989827e-03-1.29691433e-02j,
         -1.59535191e-02-1.09506675e-03j,
          7.00933728e-03+1.45844746e-02j,
          9.11382591e-03-1.31389008e-02j],
...
        [ 6.18884111e-04+1.08999988e-02j,
         -9.91955269e-03-4.80722289e-03j,
          9.01942783e-03-6.14082153e-03j,
          7.96975201e-04+1.08534687e-02j,
         -9.74559262e-03-4.74106531e-03j,
          8.86968264e-03-6.14256811e-03j,
          8.93213455e-04+1.07568410e-02j,
         -1.00829324e-02-5.00753895e-03j,
          8.94359127e-03-6.09020717e-03j,
          7.95272045e-04+1.09735093e-02j],
        [-6.69431427e-05+2.27261535e-05j,
         -2.69320267e-04-8.14274398e-05j,
         -8.75962302e-06+2.15030159e-04j,
          1.03785371e-04+3.24787986e-05j,
         -2.06820091e-04+1.24558417e-05j,
          4.06028909e-05+4.36860893e-04j,
          2.26074919e-04-1.65653841e-04j,
         -1.22591191e-04-5.58106242e-06j,
          1.86249393e-04+3.71819284e-04j,
          1.36530683e-04-2.85289959e-05j]]])
Coordinates:
  * channel  (channel) <U17 272B 'readoutreceiver_0' ... 'readoutreceiver_3'
  * rf       (rf) float64 40B 4.05e+09 4.1e+09 4.15e+09 4.2e+09 4.25e+09
  * shot     (shot) int64 80B 0 1 2 3 4 5 6 7 8 9

get_iq_array() returns a xarray. From this xarray we can easily retrieve data for a specific channel, sweep index, repeat and acquisition index.

[11]:
xarray_data.sel(channel="readoutreceiver_0", rf=4.05e9, shot=0).values
[11]:
array(0.00235124-0.00261697j)

xarray_data is an xarray which has the following

  • values: a numpy.ndarray or numpy-like array holding the arrays values

  • dims: dimension names for each axis (e.g. ‘channel’ or ‘qudit’, ‘rf’, ‘amp’,

    ‘repeats_1’, ‘acq_index’, ‘shot’)

  • coords: a dict-like container of arrays (coordinates) that label

    each point (e.g., 1-dimensional arrays of numbers, datetime objects or strings)

    • channel =[‘readoutreceiver_0’, ‘readoutreceiver_1’]

    • rf =[4.05e+09, 4.1e+09, 4.15e+09, 4.2e+09, 4.25e+09]

    • repeats_1 = [0,1,2,3,4,5,6,7,8,9] (when there are 10 repeats)

Also, the values can be accessed using the indices like

[12]:
xarray_data[0][0][0].values
[12]:
array(0.00235124-0.00261697j)

We can access nearest neighbor (inexact) lookups by use of the method ‘nearest’. Tolerance limits the maximum distance for valid matches with an inexact lookup.

[13]:
print(xarray_data.sel(rf=[4.065e09, 4.09e09], method="nearest", tolerance=0.2e09))
<xarray.DataArray (channel: 4, rf: 2, shot: 10)> Size: 1kB
array([[[ 0.00235124-0.00261697j,  0.00156245-0.0031622j ,
          0.00199869-0.00344415j,  0.00233421-0.00281242j,
          0.00161865-0.00317827j,  0.00197416-0.00332476j,
          0.0022437 -0.00261437j,  0.00158411-0.00313454j,
          0.00189428-0.0033857j ,  0.00232489-0.00275444j],
        [ 0.00903837-0.01319799j, -0.01604488-0.00115121j,
          0.00688682+0.01439518j,  0.00914084-0.01322087j,
         -0.01606523-0.00113517j,  0.00692791+0.01455182j,
          0.0090499 -0.01296914j, -0.01595352-0.00109507j,
          0.00700934+0.01458447j,  0.00911383-0.0131389j ]],

       [[-0.00392558-0.0026286j , -0.00242739-0.00173962j,
         -0.00212863-0.00050826j, -0.00360018-0.00157223j,
         -0.00218814-0.00132137j, -0.00187957-0.00061227j,
         -0.00435733-0.00212076j, -0.00215927-0.00220587j,
         -0.0022505 -0.00061475j, -0.0041227 -0.00211136j],
        [ 0.01551049+0.00978542j,  0.00037847-0.01875842j,
         -0.01700963+0.0088894j ,  0.01596848+0.01012468j,
          0.00089933-0.01888905j, -0.01698407+0.00882589j,
          0.0156424 +0.00987043j,  0.0006453 -0.01922j   ,
...
          0.00435363-0.00089584j,  0.00404613-0.00113493j,
          0.00478383-0.00141224j,  0.00406552-0.00083206j,
          0.00393484-0.00129733j,  0.00488691-0.00131106j,
          0.0040251 -0.00091627j,  0.0042536 -0.00151533j],
        [ 0.00430716+0.01652637j,  0.01252134-0.01179884j,
         -0.01653907-0.00504542j,  0.00413787+0.01678267j,
          0.01264508-0.0117718j , -0.01657059-0.00466112j,
          0.00435433+0.01677603j,  0.01225165-0.01196148j,
         -0.01696162-0.0050442j ,  0.00405041+0.01652359j]],

       [[ 0.00312935+0.00142462j,  0.00344088+0.00144212j,
          0.00286484+0.00203009j,  0.00319639+0.00157438j,
          0.00375806+0.00145745j,  0.00323223+0.00203136j,
          0.00291922+0.00156037j,  0.00347749+0.00133224j,
          0.00299148+0.00207069j,  0.00314841+0.00131987j],
        [-0.0012235 +0.01580019j,  0.01455134-0.00685866j,
         -0.01334378-0.00923721j, -0.00132292+0.0157757j ,
          0.01439666-0.00690648j, -0.0130688 -0.00933187j,
         -0.00100963+0.01572335j,  0.01445168-0.00686767j,
         -0.01335825-0.00910171j, -0.00137836+0.01620398j]]])
Coordinates:
  * channel  (channel) <U17 272B 'readoutreceiver_0' ... 'readoutreceiver_3'
  * rf       (rf) float64 16B 4.05e+09 4.1e+09
  * shot     (shot) int64 80B 0 1 2 3 4 5 6 7 8 9

We can access slices of data from an xarray very similar to numpy arrays.

[14]:
xarray_data[
    :,
].values
[14]:
array([[[ 2.35124276e-03-2.61696761e-03j,
          1.56245443e-03-3.16220147e-03j,
          1.99869235e-03-3.44414807e-03j,
          2.33420904e-03-2.81241797e-03j,
          1.61864528e-03-3.17826601e-03j,
          1.97415616e-03-3.32476444e-03j,
          2.24370314e-03-2.61436829e-03j,
          1.58411493e-03-3.13454107e-03j,
          1.89427713e-03-3.38570377e-03j,
          2.32488827e-03-2.75443529e-03j],
        [ 9.03837221e-03-1.31979863e-02j,
         -1.60448812e-02-1.15120579e-03j,
          6.88682387e-03+1.43951763e-02j,
          9.14083963e-03-1.32208673e-02j,
         -1.60652258e-02-1.13517492e-03j,
          6.92790761e-03+1.45518245e-02j,
          9.04989827e-03-1.29691433e-02j,
         -1.59535191e-02-1.09506675e-03j,
          7.00933728e-03+1.45844746e-02j,
          9.11382591e-03-1.31389008e-02j],
        [-9.69921596e-02+1.41306446e-01j,
         -9.68726013e-02+1.41300715e-01j,
         -9.66008497e-02+1.41492925e-01j,
         -9.66862182e-02+1.41401766e-01j,
         -9.67742680e-02+1.41309223e-01j,
         -9.70541093e-02+1.41359629e-01j,
         -9.68253698e-02+1.41451627e-01j,
         -9.64496395e-02+1.41546603e-01j,
         -9.70479037e-02+1.41218335e-01j,
         -9.67055504e-02+1.41535448e-01j],
        [ 6.32470779e-03-9.17958610e-03j,
          4.52432357e-03+1.00455726e-02j,
         -1.11222287e-02-1.06291578e-03j,
          6.35371604e-03-9.03682141e-03j,
          4.56529070e-03+1.01961803e-02j,
         -1.09632058e-02-1.02351663e-03j,
          6.24255967e-03-9.00895436e-03j,
          4.78976786e-03+1.02531960e-02j,
         -1.10242711e-02-1.02314139e-03j,
          6.49037177e-03-8.99366121e-03j],
        [-3.52554585e-04-2.42393203e-04j,
         -5.56220660e-05+3.56588658e-04j,
          2.89539537e-04-2.52136938e-04j,
         -1.25781980e-04-2.96531565e-05j,
          8.11054827e-05+2.00224330e-04j,
          2.81490092e-04-2.52850340e-04j,
         -2.25801394e-04-1.64635471e-04j,
          2.04950458e-04+2.34214862e-04j,
          3.69634580e-04-7.28241968e-05j,
         -2.71968595e-04-1.13773288e-04j]],

       [[-3.92558399e-03-2.62860430e-03j,
         -2.42738665e-03-1.73961819e-03j,
         -2.12862718e-03-5.08264336e-04j,
         -3.60017707e-03-1.57223093e-03j,
         -2.18814062e-03-1.32136715e-03j,
         -1.87956514e-03-6.12269807e-04j,
         -4.35733292e-03-2.12075747e-03j,
         -2.15927450e-03-2.20587362e-03j,
         -2.25049827e-03-6.14747506e-04j,
         -4.12270044e-03-2.11136407e-03j],
        [ 1.55104949e-02+9.78541860e-03j,
          3.78473956e-04-1.87584164e-02j,
         -1.70096318e-02+8.88940297e-03j,
          1.59684760e-02+1.01246835e-02j,
          8.99326704e-04-1.88890527e-02j,
         -1.69840734e-02+8.82588846e-03j,
          1.56424040e-02+9.87043307e-03j,
          6.45298621e-04-1.92200044e-02j,
         -1.71202296e-02+8.86297946e-03j,
          1.63284801e-02+9.97949118e-03j],
        [-1.54206529e-01-1.02826987e-01j,
         -1.54882074e-01-1.02843797e-01j,
         -1.54888912e-01-1.02752130e-01j,
         -1.55075433e-01-1.03027644e-01j,
         -1.55410754e-01-1.02964869e-01j,
         -1.54603278e-01-1.02750512e-01j,
         -1.55302378e-01-1.03075006e-01j,
         -1.54821862e-01-1.02938643e-01j,
         -1.54960410e-01-1.02681469e-01j,
         -1.54694729e-01-1.03219082e-01j],
        [ 1.04770207e-02+6.49278778e-03j,
         -1.12004231e-02+5.39313180e-03j,
          7.29321651e-04-1.28012138e-02j,
          1.03136901e-02+6.76332358e-03j,
         -1.13988448e-02+5.84638916e-03j,
          1.01970685e-03-1.24624537e-02j,
          1.04219269e-02+6.91859364e-03j,
         -1.13310609e-02+5.53322242e-03j,
          1.11232307e-03-1.23870055e-02j,
          1.03212291e-02+6.68549727e-03j],
        [ 4.73511142e-05-6.34045795e-04j,
         -2.26675478e-04+7.29044046e-04j,
          4.04301218e-04+2.85271423e-04j,
         -6.18736680e-04-2.69337879e-04j,
         -7.88689509e-05+7.23141781e-04j,
          2.45589072e-04+1.35684919e-04j,
         -1.23637888e-04-6.74234501e-04j,
         -1.12373907e-04+1.64976119e-04j,
          4.62654895e-04-2.46942687e-04j,
         -2.36615256e-05-8.94280965e-05j]],

       [[ 4.18615982e-03-1.39250096e-03j,
          4.65261845e-03-1.65810412e-03j,
          4.35363215e-03-8.95842933e-04j,
          4.04612761e-03-1.13493386e-03j,
          4.78383311e-03-1.41223546e-03j,
          4.06552217e-03-8.32059307e-04j,
          3.93483791e-03-1.29733081e-03j,
          4.88690721e-03-1.31106310e-03j,
          4.02510068e-03-9.16274844e-04j,
          4.25360496e-03-1.51533416e-03j],
        [ 4.30715993e-03+1.65263684e-02j,
          1.25213370e-02-1.17988353e-02j,
         -1.65390720e-02-5.04541904e-03j,
          4.13786827e-03+1.67826654e-02j,
          1.26450848e-02-1.17718020e-02j,
         -1.65705879e-02-4.66112092e-03j,
          4.35432824e-03+1.67760316e-02j,
          1.22516528e-02-1.19614758e-02j,
         -1.69616214e-02-5.04419818e-03j,
          4.05040914e-03+1.65235854e-02j],
        [-3.37301622e-02-1.68960619e-01j,
         -3.38840340e-02-1.69209703e-01j,
         -3.41415362e-02-1.68727856e-01j,
         -3.39195836e-02-1.69182512e-01j,
         -3.40168252e-02-1.69037410e-01j,
         -3.41649507e-02-1.69261792e-01j,
         -3.41573793e-02-1.69088767e-01j,
         -3.40179481e-02-1.69062567e-01j,
         -3.38470123e-02-1.69119431e-01j,
         -3.39878030e-02-1.69093576e-01j],
        [ 1.57830395e-03+1.03938395e-02j,
         -1.00525537e-02-3.86989347e-03j,
          8.60672862e-03-6.82185040e-03j,
          1.71348962e-03+1.06882811e-02j,
         -1.01513825e-02-3.86233316e-03j,
          8.15640266e-03-6.58853160e-03j,
          1.51150511e-03+1.05534255e-02j,
         -9.96975602e-03-3.95865294e-03j,
          8.39752041e-03-6.52944550e-03j,
          1.43181278e-03+1.04496855e-02j],
        [ 4.01375883e-04-2.57530817e-04j,
         -1.99688618e-04-3.69448313e-04j,
         -8.09030719e-05+2.78525762e-04j,
          2.65387435e-04-3.21906955e-04j,
         -4.36508422e-04-2.84005337e-04j,
         -2.91778332e-04+4.11607532e-04j,
          2.02230212e-04-2.32224319e-04j,
         -1.08296899e-04-4.08593160e-04j,
          1.51789271e-04+2.26080193e-04j,
          3.29437029e-04-2.00660153e-04j]],

       [[ 3.12935366e-03+1.42462088e-03j,
          3.44088079e-03+1.44211956e-03j,
          2.86483959e-03+2.03009391e-03j,
          3.19639468e-03+1.57438011e-03j,
          3.75805807e-03+1.45745139e-03j,
          3.23223375e-03+2.03136439e-03j,
          2.91921695e-03+1.56036850e-03j,
          3.47748625e-03+1.33223563e-03j,
          2.99147989e-03+2.07068699e-03j,
          3.14840647e-03+1.31987164e-03j],
        [-1.22349642e-03+1.58001881e-02j,
          1.45513388e-02-6.85866093e-03j,
         -1.33437751e-02-9.23721301e-03j,
         -1.32291651e-03+1.57757011e-02j,
          1.43966595e-02-6.90647832e-03j,
         -1.30687995e-02-9.33186517e-03j,
         -1.00962622e-03+1.57233509e-02j,
          1.44516843e-02-6.86766628e-03j,
         -1.33582527e-02-9.10170620e-03j,
         -1.37835684e-03+1.62039818e-02j],
        [ 2.15241206e-03-1.64045816e-01j,
          2.19188080e-03-1.64126110e-01j,
          2.19566497e-03-1.64130555e-01j,
          2.38861035e-03-1.63908325e-01j,
          2.29176289e-03-1.64127773e-01j,
          2.21819364e-03-1.64133209e-01j,
          2.23172691e-03-1.63879739e-01j,
          2.30067213e-03-1.64056183e-01j,
          2.35677589e-03-1.64225281e-01j,
          2.17544744e-03-1.64058950e-01j],
        [ 6.18884111e-04+1.08999988e-02j,
         -9.91955269e-03-4.80722289e-03j,
          9.01942783e-03-6.14082153e-03j,
          7.96975201e-04+1.08534687e-02j,
         -9.74559262e-03-4.74106531e-03j,
          8.86968264e-03-6.14256811e-03j,
          8.93213455e-04+1.07568410e-02j,
         -1.00829324e-02-5.00753895e-03j,
          8.94359127e-03-6.09020717e-03j,
          7.95272045e-04+1.09735093e-02j],
        [-6.69431427e-05+2.27261535e-05j,
         -2.69320267e-04-8.14274398e-05j,
         -8.75962302e-06+2.15030159e-04j,
          1.03785371e-04+3.24787986e-05j,
         -2.06820091e-04+1.24558417e-05j,
          4.06028909e-05+4.36860893e-04j,
          2.26074919e-04-1.65653841e-04j,
         -1.22591191e-04-5.58106242e-06j,
          1.86249393e-04+3.71819284e-04j,
          1.36530683e-04-2.85289959e-05j]]])
[15]:
xarray_data[:, [0, -1]].values
[15]:
array([[[ 2.35124276e-03-2.61696761e-03j,
          1.56245443e-03-3.16220147e-03j,
          1.99869235e-03-3.44414807e-03j,
          2.33420904e-03-2.81241797e-03j,
          1.61864528e-03-3.17826601e-03j,
          1.97415616e-03-3.32476444e-03j,
          2.24370314e-03-2.61436829e-03j,
          1.58411493e-03-3.13454107e-03j,
          1.89427713e-03-3.38570377e-03j,
          2.32488827e-03-2.75443529e-03j],
        [-3.52554585e-04-2.42393203e-04j,
         -5.56220660e-05+3.56588658e-04j,
          2.89539537e-04-2.52136938e-04j,
         -1.25781980e-04-2.96531565e-05j,
          8.11054827e-05+2.00224330e-04j,
          2.81490092e-04-2.52850340e-04j,
         -2.25801394e-04-1.64635471e-04j,
          2.04950458e-04+2.34214862e-04j,
          3.69634580e-04-7.28241968e-05j,
         -2.71968595e-04-1.13773288e-04j]],

       [[-3.92558399e-03-2.62860430e-03j,
         -2.42738665e-03-1.73961819e-03j,
         -2.12862718e-03-5.08264336e-04j,
         -3.60017707e-03-1.57223093e-03j,
         -2.18814062e-03-1.32136715e-03j,
         -1.87956514e-03-6.12269807e-04j,
         -4.35733292e-03-2.12075747e-03j,
         -2.15927450e-03-2.20587362e-03j,
         -2.25049827e-03-6.14747506e-04j,
         -4.12270044e-03-2.11136407e-03j],
        [ 4.73511142e-05-6.34045795e-04j,
         -2.26675478e-04+7.29044046e-04j,
          4.04301218e-04+2.85271423e-04j,
         -6.18736680e-04-2.69337879e-04j,
         -7.88689509e-05+7.23141781e-04j,
          2.45589072e-04+1.35684919e-04j,
         -1.23637888e-04-6.74234501e-04j,
         -1.12373907e-04+1.64976119e-04j,
          4.62654895e-04-2.46942687e-04j,
         -2.36615256e-05-8.94280965e-05j]],

       [[ 4.18615982e-03-1.39250096e-03j,
          4.65261845e-03-1.65810412e-03j,
          4.35363215e-03-8.95842933e-04j,
          4.04612761e-03-1.13493386e-03j,
          4.78383311e-03-1.41223546e-03j,
          4.06552217e-03-8.32059307e-04j,
          3.93483791e-03-1.29733081e-03j,
          4.88690721e-03-1.31106310e-03j,
          4.02510068e-03-9.16274844e-04j,
          4.25360496e-03-1.51533416e-03j],
        [ 4.01375883e-04-2.57530817e-04j,
         -1.99688618e-04-3.69448313e-04j,
         -8.09030719e-05+2.78525762e-04j,
          2.65387435e-04-3.21906955e-04j,
         -4.36508422e-04-2.84005337e-04j,
         -2.91778332e-04+4.11607532e-04j,
          2.02230212e-04-2.32224319e-04j,
         -1.08296899e-04-4.08593160e-04j,
          1.51789271e-04+2.26080193e-04j,
          3.29437029e-04-2.00660153e-04j]],

       [[ 3.12935366e-03+1.42462088e-03j,
          3.44088079e-03+1.44211956e-03j,
          2.86483959e-03+2.03009391e-03j,
          3.19639468e-03+1.57438011e-03j,
          3.75805807e-03+1.45745139e-03j,
          3.23223375e-03+2.03136439e-03j,
          2.91921695e-03+1.56036850e-03j,
          3.47748625e-03+1.33223563e-03j,
          2.99147989e-03+2.07068699e-03j,
          3.14840647e-03+1.31987164e-03j],
        [-6.69431427e-05+2.27261535e-05j,
         -2.69320267e-04-8.14274398e-05j,
         -8.75962302e-06+2.15030159e-04j,
          1.03785371e-04+3.24787986e-05j,
         -2.06820091e-04+1.24558417e-05j,
          4.06028909e-05+4.36860893e-04j,
          2.26074919e-04-1.65653841e-04j,
         -1.22591191e-04-5.58106242e-06j,
          1.86249393e-04+3.71819284e-04j,
          1.36530683e-04-2.85289959e-05j]]])

Since this program sweeps the frequency of the RF waveform but keeps the frequency in the integration filter constant, we expect a peak in I/Q magnitude at the center frequency, which can be visually confirmed by plotting the data:

[16]:
program.plot_iq(channel_subplots=False)

In typical applications, we typically have larger sweep ranges and storing all the trace data and performing the I/Q demodulation in software adds timing overhead. Instead, we can perform the demodulation on hardware, and only I/Q data will be stored.

[17]:
new_frequencies = qcs.Array(
    "rfs", value=np.linspace(4.05e9, 4.25e9, num=20), dtype=float
)

program = make_program()
program.sweep(new_frequencies, frequency)

if run_on_hw:
    # initialize the backend pass
    # setting fpga_postprocessing=True enables hardware demodulation of trace data
    backend = qcs.HclBackend(channel_mapper=mapper, fpga_postprocessing=True)
    # the executor returns the program populated with results
    program = qcs.Executor(backend).execute(program)
    # (optional) export the data to an HDF5 file
    program.to_hdf5("program3.hdf5")

# we are loading a previously run program here for this example
program = qcs.load("program3.hdf5")

program.plot_iq(channel_subplots=False)

We can retrieve the classified data by calling the get_classified_pandas() method, which returns a dataframe that has the sweep values in its column header.

[18]:
program.get_classified_pandas()

xarray_data = program.get_classified_array()
xarray_data
[18]:
<xarray.DataArray (channel: 4, rf: 20, shot: 10)> Size: 6kB
array([[[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [1, 0, 0, 1, 0, 1, 1, 0, 1, 0],
        [1, 0, 1, 0, 1, 1, 0, 1, 0, 1],
        [0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
        [1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
        [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 1, 0, 0, 1, 0, 1, 0, 0, 1],
        [1, 1, 1, 1, 0, 0, 0, 1, 1, 1],
        [1, 1, 0, 1, 1, 0, 1, 1, 0, 0],
        [0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
        [0, 0, 0, 1, 1, 0, 0, 1, 1, 0],
        [1, 0, 0, 1, 0, 0, 1, 0, 0, 1],
        [0, 1, 1, 1, 1, 0, 0, 0, 1, 1],
        [0, 1, 0, 1, 0, 0, 1, 0, 1, 0],
        [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
        [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
        [1, 1, 0, 1, 0, 1, 0, 1, 1, 0],
        [0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
        [1, 0, 1, 1, 0, 1, 1, 0, 1, 1]],
...
       [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [1, 1, 0, 1, 0, 0, 1, 0, 1, 1],
        [0, 1, 0, 1, 1, 0, 1, 0, 1, 0],
        [1, 1, 1, 1, 1, 0, 0, 0, 0, 0],
        [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
        [0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
        [1, 0, 1, 0, 0, 1, 0, 1, 0, 0],
        [1, 0, 0, 0, 1, 1, 1, 1, 0, 0],
        [0, 1, 1, 0, 0, 1, 0, 0, 1, 0],
        [1, 1, 0, 0, 1, 1, 1, 0, 0, 1],
        [1, 1, 0, 0, 1, 1, 1, 0, 0, 1],
        [0, 1, 1, 0, 0, 1, 0, 0, 1, 0],
        [1, 0, 0, 0, 1, 1, 1, 1, 0, 0],
        [1, 0, 1, 0, 0, 1, 0, 1, 0, 0],
        [0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
        [1, 0, 0, 1, 0, 1, 0, 1, 0, 1],
        [1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 1, 0, 1, 1, 0, 1, 0, 1, 0],
        [1, 1, 1, 1, 0, 0, 0, 0, 1, 1],
        [1, 1, 0, 1, 1, 0, 1, 0, 0, 1]]])
Coordinates:
  * channel  (channel) <U17 272B 'readoutreceiver_0' ... 'readoutreceiver_3'
  * rf       (rf) float64 160B 4.05e+09 4.061e+09 ... 4.239e+09 4.25e+09
  * shot     (shot) int64 80B 0 1 2 3 4 5 6 7 8 9

get_classified_array() returns a xarray. From this xarray we can easily retrieve data for a specific channel, sweep index, repeat and acquisition index.

[19]:

print(xarray_data.sel(channel="readoutreceiver_0", rf=4.05e9))
<xarray.DataArray (shot: 10)> Size: 80B
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
Coordinates:
    channel  <U17 68B 'readoutreceiver_0'
    rf       float64 8B 4.05e+09
  * shot     (shot) int64 80B 0 1 2 3 4 5 6 7 8 9

xarray_data is an xarray which has the following

  • values: a numpy.ndarray or numpy-like array holding the array�s values

  • dims: dimension names for each axis (e.g. ‘channel’, ‘rf’, ‘amp’,

    ‘repeats_1’, ‘acq_index’, ‘shot’)

  • coords: a dict-like container of arrays (coordinates) that label

    each point (e.g., 1-dimensional arrays of numbers, datetime objects or strings)

    • channel=[‘readoutreceiver_0’, ‘readoutreceiver_1’]

    • rf =[4.05e+09, 4.1e+09, 4.15e+09, 4.2e+09, 4.25e+09]

    • repeats_1 = [0,1,2,3,4,5,6,7,8,9] (when there are 10 repeats)

Also, the values can be accessed using the indices like

[20]:
xarray_data[0][0][0].values
[20]:
array(1)

Plot classified data gives the count of occurrences of 1’s and 0’s:

[21]:
program.plot_classified(channel_subplots=False)
/home/kpclocal/jenkins/workspace/qcs_release_2025B/.venv3.10/lib/python3.10/site-packages/keysight/qcs/programs/program.py:1172: UserWarning:

get_classified() is deprecated and will be removed in a future version. Use get_classified_array() instead.

[22]:
program = qcs.load("program4.hdf5")

Plot classified data as a 2d heat-map:

[23]:
program.plot_classified(avg=True, plot_type="2d")
/home/kpclocal/jenkins/workspace/qcs_release_2025B/.venv3.10/lib/python3.10/site-packages/keysight/qcs/programs/program.py:1172: UserWarning:

get_classified() is deprecated and will be removed in a future version. Use get_classified_array() instead.

Note

It is possible to perform variable sweeps both on hardware and software. To enable hardware sweeping, the program’s sweep() method needs to be called before the n_shots() method. This will execute both the sweep and the repetitions on hardware. Any other sweeps defined after those will be performed in software.

Nested sweeps#

Sweeps can be nested by calling the sweep() method multiple times. For example, we can sweep the frequency and amplitude in our program from above:

[24]:
program = make_program()

# specify the frequency values to be swept over
frequencies = qcs.Array(
    "frequencies", value=[4.05e9, 4.1e9, 4.15e9, 4.2e9, 4.25e9], dtype=float
)

# specify the amplitude values to be swept over
amplitudes = qcs.Array("amplitude", value=[0.2, 0.4, 0.6, 0.8, 1], dtype=float)

program.sweep(frequencies, frequency)
program.sweep(amplitudes, amplitude)

print(program.repetitions.items)
[Sweep(amp=Array(name=amplitude, shape=(5,), dtype=float, unit=none)), Sweep(rf=Array(name=frequencies, shape=(5,), dtype=float, unit=none)), Repeat(10)]

We execute this program as before and load in the results:

[25]:
if run_on_hw:
    program = qcs.Executor(qcs.HclBackend(mapper, fpga_postprocessing=True)).apply(
        program
    )
    program.to_hdf5("program4.hdf5")

program = qcs.load("program4.hdf5")

program.get_iq_pandas(avg=True, stack_channels=True)
[25]:
(amp, 0.2) (amp, 0.4) ... (amp, 0.8) (amp, 1)
(rf, 4.05 GHz) (rf, 4.1 GHz) (rf, 4.15 GHz) (rf, 4.2 GHz) (rf, 4.25 GHz) (rf, 4.05 GHz) (rf, 4.1 GHz) (rf, 4.15 GHz) (rf, 4.2 GHz) (rf, 4.25 GHz) ... (rf, 4.05 GHz) (rf, 4.1 GHz) (rf, 4.15 GHz) (rf, 4.2 GHz) (rf, 4.25 GHz) (rf, 4.05 GHz) (rf, 4.1 GHz) (rf, 4.15 GHz) (rf, 4.2 GHz) (rf, 4.25 GHz)
(((readoutreceiver_0))) 0.000054-0.000024j 0.000311-0.000175j -0.021990+0.030870j 0.000031-0.000342j -0.000002+0.000011j 0.000237-0.000276j 0.000504-0.000323j -0.043212+0.060772j 0.000108-0.000541j -0.000025+0.000005j ... 0.001422-0.001562j 0.000976-0.000823j -0.082690+0.117219j 0.000405-0.000960j -0.000032+0.000049j 0.001917-0.003032j 0.000923-0.001317j -0.096898+0.141482j 0.000648-0.000950j 0.000026-0.000017j
(((readoutreceiver_1))) -0.000020-0.000008j 0.000115+0.000262j -0.032923-0.023555j 0.000313+0.000043j -0.000088-0.000052j -0.000390-0.000342j 0.000282+0.000497j -0.065213-0.046224j 0.000726-0.000080j -0.000004-0.000047j ... -0.002221-0.001783j 0.000929+0.001123j -0.127204-0.087077j 0.001139+0.000442j -0.000023+0.000028j -0.002824-0.001579j 0.001513+0.001036j -0.154821-0.102813j 0.001006+0.000709j -0.000158-0.000085j
(((readoutreceiver_2))) 0.000079-0.000031j -0.000095+0.000329j -0.006091-0.037335j 0.000239+0.000210j 0.000004+0.000044j 0.000433-0.000006j -0.000154+0.000612j -0.012199-0.073485j 0.000407+0.000504j -0.000023-0.000051j ... 0.002674-0.000274j 0.000008+0.001391j -0.025622-0.140898j 0.000384+0.001028j 0.000035+0.000039j 0.004332-0.001243j 0.000439+0.001622j -0.033850-0.169222j 0.000125+0.001070j 0.000024-0.000145j
(((readoutreceiver_3))) 0.000059-0.000005j -0.000145+0.000291j 0.001644-0.035483j 0.000079+0.000276j -0.000008+0.000001j 0.000318+0.000171j -0.000201+0.000450j 0.002980-0.070049j 0.000227+0.000548j -0.000059+0.000004j ... 0.001766+0.001234j -0.000320+0.001185j 0.003630-0.134825j 0.000308+0.000933j 0.000031-0.000048j 0.003222+0.001599j -0.000203+0.001572j 0.002406-0.164136j 0.000017+0.001130j -0.000004+0.000070j

4 rows × 25 columns

We can see that the dataframe now has an additional column index for the second sweep. When plotting the I/Q data, we can easily switch between sweep axes by specifying the plot_axis argument. The default, plot_axis=0 will plot the data over the first sweep (zeroth index of the dataframe columns). Note that this can also be used to plot the I/Q data as a function of shots, when the method is called with avg=False.

[26]:
# plot over amplitude for each frequency
program.plot_iq(channel_subplots=False)
[27]:
# plot over frequency for each amplitude
program.plot_iq(channel_subplots=False, plot_axis=1)

Simultaneous sweeps#

Sweeps can also be performed simultaneously by passing the sweep values and targets as lists:

[28]:
program = make_program()

# specify the frequency values to be swept over
frequencies = qcs.Array(
    "frequencies", value=[4.05e9, 4.1e9, 4.15e9, 4.2e9, 4.25e9], dtype=float
)

# specify the amplitude values to be swept over
amplitudes = qcs.Array("amplitude", value=[0.2, 0.4, 0.6, 0.8, 1], dtype=float)

program.sweep([frequencies, amplitudes], [frequency, amplitude])
Program
Sweep Details:
Repetitions Sweep with 5 repetitions
Associations
rf Array(name=frequencies, shape=(5,), dtype=float, unit=none, value=[4.05 GHz, 4.1 GHz, 4.15 GHz, 4.2 GHz, 4.25 GHz])
amp Array(name=amplitude, shape=(5,), dtype=float, unit=none, value=[0.2, 0.4, 0.6, 0.8, 1])
(SW)Sweep_rf_amp
Sweep Details:
Repetitions Repeat with 10 repetitions
(HW)Repeat(10)
keysight-logo-svg
Program Body
Program
Duration 80 ns
Layers 1
Targets 4
Layer #0
Layer #0
Duration 80 ns
readoutawg 0
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency Scalar(name=rf, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency Scalar(name=rf, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
readoutreceiver 0
Acquisition on ('readoutreceiver', 0)

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

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency 4.15 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
Acquisition on ('readoutreceiver', 1)

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

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency 4.15 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
[28]:
Program([Layer(Channels(labels=[0, 1], name=readoutawg, absolute_phase=False)=[RFWaveform(duration=Scalar(name=_implicit, value=8e-08, dtype=float, unit=s), envelope={GaussianEnvelope(4.0): Scalar(name=_implicit, value=1.0, dtype=float, unit=none)}, rf_frequency=Scalar(name=rf, value=None, dtype=float, unit=Hz), instantaneous_phase={GaussianEnvelope(4.0): Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)}, post_phase=Scalar(name=_implicit, value=0.0, dtype=float, unit=rad))], Channels(labels=[0, 1], name=readoutreceiver, absolute_phase=False)=[Acquisition(IntegrationFilter(RFWaveform(duration=Scalar(name=_implicit, value=8e-08, dtype=float, unit=s), envelope={GaussianEnvelope(4.0): Scalar(name=_implicit, value=1.0, dtype=float, unit=none)}, rf_frequency=Scalar(name=_implicit, value=4150000000.0, dtype=float, unit=Hz), instantaneous_phase={GaussianEnvelope(4.0): Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)}, post_phase=Scalar(name=_implicit, value=0.0, dtype=float, unit=rad))))])])

We execute this program as before and load in the results:

[29]:
if run_on_hw:
    program = qcs.Executor(qcs.HclBackend(mapper, fpga_postprocessing=True)).apply(
        program
    )
    program.to_hdf5("program5.hdf5")

program = qcs.load("program5.hdf5")

program.get_iq_pandas(avg=True, stack_channels=True)
[29]:
(rf, 4.05 GHz), (amp, 0.2) (rf, 4.1 GHz), (amp, 0.4) (rf, 4.15 GHz), (amp, 0.6) (rf, 4.2 GHz), (amp, 0.8) (rf, 4.25 GHz), (amp, 1)
(((readoutreceiver_0))) 0.000012-0.000053j 0.000591-0.000309j -0.062908+0.089234j 0.000409-0.000950j -0.000002-0.000024j
(((readoutreceiver_1))) 0.000023+0.000026j 0.000343+0.000561j -0.096364-0.067022j 0.000932+0.000280j -0.000066-0.000098j
(((readoutreceiver_2))) 0.000061-0.000079j -0.000158+0.000644j -0.018962-0.107608j 0.000361+0.000904j -0.000002-0.000001j
(((readoutreceiver_3))) 0.000015+0.000015j -0.000241+0.000522j 0.003421-0.102856j 0.000300+0.000922j 0.000002+0.000000j
[30]:
# plot the results
program.plot_iq(channel_subplots=False)

Hardware Sweeps#

So far, all examples shown were constructed as a Software sweep. This means that after each point in the sweep, the hardware stops and waits for the software to compile the next steps and load all the information into the FPGAs. For large sweeps or for nested sweeps, this can be a slow process.

Hardware Sweep provides a way to preload every step of the sweep into the hardware, so it can execute the whole sweep without interruptions.

To enable this, we only need to change the order of the sweeps: The repetitions (n_shots()) needs to be placed after the sweeps like in the example below.

[31]:
frequency = qcs.Scalar("rf", dtype=float)

"""Creates a simple program with a single RF waveform"""
program = qcs.Program()
# define the waveform using this frequency variable & add it to the program
gauss = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(num_sigma=4), 1, frequency)
program.add_waveform(gauss, awgs)

# define an integration filter using the same RF waveform but with fixed frequency
int_filter = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(num_sigma=4), 1, 4.15e9)
program.add_acquisition(int_filter, digs)

# specify the frequency values to be swept over
frequencies = qcs.Array(
    "frequencies", value=[4.05e9, 4.1e9, 4.15e9, 4.2e9, 4.25e9], dtype=float
)

# add the sweep, targeting the `frequency` variable
program.sweep(frequencies, frequency)

# specify the number of shots
program.n_shots(10)

program.draw()
Program
Sweep Details:
Repetitions Repeat with 10 repetitions
(HW)Repeat(10)
Sweep Details:
Repetitions Sweep with 5 repetitions
Associations
rf Array(name=frequencies, shape=(5,), dtype=float, unit=none, value=[4.05 GHz, 4.1 GHz, 4.15 GHz, 4.2 GHz, 4.25 GHz])
(HW)Sweep_rf
keysight-logo-svg
Program Body
Program
Duration 80 ns
Layers 1
Targets 4
Layer #0
Layer #0
Duration 80 ns
readoutawg 0
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency Scalar(name=rf, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency Scalar(name=rf, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
readoutreceiver 0
Acquisition on ('readoutreceiver', 0)

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

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency 4.15 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
Acquisition on ('readoutreceiver', 1)

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

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude 1
Frequency 4.15 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad

This constructs the program to have the sweep of frequencies as the inner-loop, and then the repeat (i.e. n_shots) as the outer loop. Both the sweep and the repeat are executed as a hardware loop, so the entire program is executed without interruption.

It is possible to perform multi-dimensional sweeps. More than one sweep can be executed as a software sweep or a hardware sweep.

The innermost Repeat on a program’s repetition structure serves as the boundary between hardware and software sweeps. To check which operations will be performed in hardware-time, the repetitions property of the program can be inspected

[32]:
program.repetitions.hw_items
[32]:
[Repeat(10),
 Sweep(rf=Array(name=frequencies, shape=(5,), dtype=float, unit=none))]

Limitations#

Sweepable parameters#

Sweepable Parameters#

Instrument

Operation

Software sweep variables

Hardware sweep variables

M5300AWG and M5301AWG

RFWaveform

Support for sweeping amplitude, frequency, instantaneous_phase, post_phase, and duration

Support for sweeping amplitude, frequency, instantaneous_phase, and post_phase The duration variable is only supported for the hold duration on flat-top waveforms.

M5300AWG and M5301AWG

DCWaveform

Support for sweeping amplitude and duration

Support for sweeping amplitude. The duration variable is only supported for the hold duration on flat-top waveforms

M5200Digitizer

Acquisition

Support for sweeping all waveform variables on the Acquisition’s IntegrationFilter. Support for sweeping the Acquisition’s Classifier reference points. Support for changing the acquisition duration is not supported when fpga_postprocessing==False

Support for sweeping amplitude and frequency of the Acquisition’s IntegrationFilter.

M5300AWG, M5301AWG, and M5200Digitizer

Delay

Support for sweeping duration

Support for sweeping duration

M5300AWG

RFAWGChannelSettings

Support for sweeping delay and lo_frequency

No support

M5301AWG

BasebandAWGChannelSettings

Support for sweeping delay and offset

No support

M5200AWG

DigitizerChannelSettings

Support for sweeping delay and range

No support

M5201AWG

DownconverterChannelSettings

Support for sweeping lo_frequency

No support

Other limitations per sweep type#

Limitation

Software sweep mode

Hardware sweep mode

Supported channel settings

Both absolute_phase=True and absolute_phase=False

Most parameters can only be swept on channels where absolute_phase=False. The only exceptions are Delay duration, amplitude, and frequency, which can be swept regardless of the channel’s absolute phase setting.

Demodulation mode

Both fpga_postprocessing=False and fpga_postprocessing=True

Only fpga_postprocessing=True

Maximum number of parameter swept on a single waveform.

No limit

Three parameters

Maximum number of nested sweeping dimensions.

No limit

Eight dimensions

Sweep length limitation

No limit

The sum of all sweep lengths must be less than 24,576 points (more details below)

Minimum value for a delay duration sweep

0 ns

13.333 ns

Note

Sweeping parameters of a IntegrationFilter is currently incompatible with ConditionalOperation and qubit reset.

Note

Sweeping parameters of a IntegrationFilter is currently incompatible with invoking get_classified_pandas() or get_classified_array() for classified state retrieval. Users may still manually classify data from demodulated IQ traces, but cannot use the get_classified() methods in this context.

Hardware sweep size limitations#

During compilation, each swept variable is translated into a separate array stored in FPGA memory. Each instrument channel supports up to eight FPGA arrays. All eight arrays share the same memory space that can hold 24,576 sweep points.

When designing an experiment, it can be complicated to determine if all the sweeps fit inside the hardware due to multiple optimization steps. This section will go over some common scenarios. This won’t be an exhaustive list.

Example 1: Simple 1D sweep

In the following example, amplitude will use one FPGA array that contains 10,000 data points. The total number of points is 10,000 which is less than the 24,576 maximum.

[33]:
amplitude = qcs.Scalar("amp", dtype=float)

program = qcs.Program()

# define the waveform using this frequency variable & add it to the program
gauss = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(num_sigma=4), amplitude, 4e9)
program.add_waveform(gauss, awgs)

# define the values for the sweep
amplitudes = qcs.Array("amplitudes", value=np.linspace(0.1, 0.2, 10000), dtype=float)

# sweep the program
program.sweep(amplitudes, amplitude)
program.n_shots(10)
Program
Sweep Details:
Repetitions Repeat with 10 repetitions
(HW)Repeat(10)
Sweep Details:
Repetitions Sweep with 10000 repetitions
Associations
amp Array(name=amplitudes, shape=(10000,), dtype=float, unit=none, value=[0.1, 0.1, 0.1, 0.1, 0.1, 0.1001, 0.1001, 0.1001, 0.1001, 0.1001, ... ])
(HW)Sweep_amp
keysight-logo-svg
Program Body
Program
Duration 80 ns
Layers 1
Targets 2
Layer #0
Layer #0
Duration 80 ns
readoutawg 0
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
[33]:
Program([Layer([RFWaveform(duration=Scalar(name=_implicit, value=8e-08, dtype=float, unit=s), envelope={GaussianEnvelope(4.0): Scalar(name=amp, value=None, dtype=float, unit=none)}, rf_frequency=Scalar(name=_implicit, value=4000000000.0, dtype=float, unit=Hz), instantaneous_phase={GaussianEnvelope(4.0): Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)}, post_phase=Scalar(name=_implicit, value=0.0, dtype=float, unit=rad))])])

Example 2: 2D Hardware Sweep

In the following example, amplitude and frequency will each take one FPGA array and each will use 10,000 data points. The total number of points is 20,000 which is less than the 24,576 maximum.

[34]:
frequency = qcs.Scalar("rf", dtype=float)
amplitude = qcs.Scalar("amp", dtype=float)

program = qcs.Program()

# define the waveform using this frequency variable & add it to the program
gauss = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(num_sigma=4), amplitude, frequency)
program.add_waveform(gauss, awgs)

# define the values for each sweep
frequencies = qcs.Array(
    "frequencies", value=np.linspace(4e9, 4.1e9, 10000), dtype=float
)
amplitudes = qcs.Array("amplitudes", value=np.linspace(0.1, 0.2, 10000), dtype=float)

# sweep the program
program.sweep(frequencies, frequency)
program.sweep(amplitudes, amplitude)
program.n_shots(10)
Program
Sweep Details:
Repetitions Repeat with 10 repetitions
(HW)Repeat(10)
Sweep Details:
Repetitions Sweep with 10000 repetitions
Associations
amp Array(name=amplitudes, shape=(10000,), dtype=float, unit=none, value=[0.1, 0.1, 0.1, 0.1, 0.1, 0.1001, 0.1001, 0.1001, 0.1001, 0.1001, ... ])
(HW)Sweep_amp
Sweep Details:
Repetitions Sweep with 10000 repetitions
Associations
rf Array(name=frequencies, shape=(10000,), dtype=float, unit=none, value=[4 GHz, 4.00001 GHz, 4.00002 GHz, 4.00003 GHz, 4.00004 GHz, 4.00005 GHz, 4.00006 GHz, 4.00007 GHz, 4.00008 GHz, 4.00009 GHz, ... ])
(HW)Sweep_rf
keysight-logo-svg
Program Body
Program
Duration 80 ns
Layers 1
Targets 2
Layer #0
Layer #0
Duration 80 ns
readoutawg 0
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency Scalar(name=rf, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency Scalar(name=rf, value=None, dtype=float, unit=Hz)
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
[34]:
Program([Layer([RFWaveform(duration=Scalar(name=_implicit, value=8e-08, dtype=float, unit=s), envelope={GaussianEnvelope(4.0): Scalar(name=amp, value=None, dtype=float, unit=none)}, rf_frequency=Scalar(name=rf, value=None, dtype=float, unit=Hz), instantaneous_phase={GaussianEnvelope(4.0): Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)}, post_phase=Scalar(name=_implicit, value=0.0, dtype=float, unit=rad))])])

Example 3: 1D Sweep with Array reuse

In the following example, the program plays three identical waveforms, all of which use the same sweep values. The amplitudes values for the waveforms will be reused. This results in one FPGA array with 10,000 sweep points. If the FPGA array was not reused, the sweep points would have exceeded the 24,576 maximum. Note: FPGA array reuse is only possible if there is at least 13.333ns delay between each waveform.

[35]:
amplitude1 = qcs.Scalar("amp", dtype=float)

program = qcs.Program()

# define the waveform using this frequency variable & add it to the program
gauss = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(num_sigma=4), amplitude, 4e9)
program.add_waveform(gauss, awgs)
program.add_waveform(gauss, awgs, pre_delay=20e-9)
program.add_waveform(gauss, awgs, pre_delay=20e-9)
# define the values for the sweep
amplitudes = qcs.Array("amplitudes", value=np.linspace(0.1, 0.2, 10000), dtype=float)

# sweep the program
program.sweep(amplitudes, amplitude)
program.n_shots(10)
Program
Sweep Details:
Repetitions Repeat with 10 repetitions
(HW)Repeat(10)
Sweep Details:
Repetitions Sweep with 10000 repetitions
Associations
amp Array(name=amplitudes, shape=(10000,), dtype=float, unit=none, value=[0.1, 0.1, 0.1, 0.1, 0.1, 0.1001, 0.1001, 0.1001, 0.1001, 0.1001, ... ])
(HW)Sweep_amp
keysight-logo-svg
Program Body
Program
Duration 280 ns
Layers 1
Targets 2
Layer #0
Layer #0
Duration 280 ns
readoutawg 0
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
Delay on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=20 ns, dtype=float, unit=s)
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
Delay on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=20 ns, dtype=float, unit=s)
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
Delay on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=20 ns, dtype=float, unit=s)
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
Delay on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=20 ns, dtype=float, unit=s)
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
[35]:
Program([Layer([RFWaveform(duration=Scalar(name=_implicit, value=8e-08, dtype=float, unit=s), envelope={GaussianEnvelope(4.0): Scalar(name=amp, value=None, dtype=float, unit=none)}, rf_frequency=Scalar(name=_implicit, value=4000000000.0, dtype=float, unit=Hz), instantaneous_phase={GaussianEnvelope(4.0): Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)}, post_phase=Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)), Delay(Scalar(name=_implicit, value=2e-08, dtype=float, unit=s)), RFWaveform(duration=Scalar(name=_implicit, value=8e-08, dtype=float, unit=s), envelope={GaussianEnvelope(4.0): Scalar(name=amp, value=None, dtype=float, unit=none)}, rf_frequency=Scalar(name=_implicit, value=4000000000.0, dtype=float, unit=Hz), instantaneous_phase={GaussianEnvelope(4.0): Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)}, post_phase=Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)), Delay(Scalar(name=_implicit, value=2e-08, dtype=float, unit=s)), RFWaveform(duration=Scalar(name=_implicit, value=8e-08, dtype=float, unit=s), envelope={GaussianEnvelope(4.0): Scalar(name=amp, value=None, dtype=float, unit=none)}, rf_frequency=Scalar(name=_implicit, value=4000000000.0, dtype=float, unit=Hz), instantaneous_phase={GaussianEnvelope(4.0): Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)}, post_phase=Scalar(name=_implicit, value=0.0, dtype=float, unit=rad))])])

Example 4: 1D Simultaneous Sweep

In the following example, the program plays two waveforms, each with its own set of amplitudes being swept. The amplitudes will be compiled into one interleaved array with a total of 20,000 data points

[36]:
amplitude1 = qcs.Scalar("amp1", dtype=float)
amplitude2 = qcs.Scalar("amp2", dtype=float)

program = qcs.Program()

# define the waveform using this frequency variable & add it to the program
gauss1 = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(num_sigma=4), amplitude1, 4e9)
gauss2 = qcs.RFWaveform(80e-9, qcs.GaussianEnvelope(num_sigma=4), amplitude2, 4e9)
program.add_waveform(gauss1, awgs)
program.add_waveform(gauss2, awgs)

# define the values for the sweep
amplitudes1 = qcs.Array("amplitudes1", value=np.linspace(0.1, 0.2, 10000), dtype=float)
amplitudes2 = qcs.Array("amplitudes2", value=np.linspace(0.3, 0.4, 10000), dtype=float)

# sweep the program
program.sweep([amplitudes1, amplitudes2], [amplitude1, amplitude2])
program.n_shots(10)
Program
Sweep Details:
Repetitions Repeat with 10 repetitions
(HW)Repeat(10)
Sweep Details:
Repetitions Sweep with 10000 repetitions
Associations
amp1 Array(name=amplitudes1, shape=(10000,), dtype=float, unit=none, value=[0.1, 0.1, 0.1, 0.1, 0.1, 0.1001, 0.1001, 0.1001, 0.1001, 0.1001, ... ])
amp2 Array(name=amplitudes2, shape=(10000,), dtype=float, unit=none, value=[0.3, 0.3, 0.3, 0.3, 0.3, 0.3001, 0.3001, 0.3001, 0.3001, 0.3001, ... ])
(HW)Sweep_amp1_amp2
keysight-logo-svg
Program Body
Program
Duration 160 ns
Layers 1
Targets 2
Layer #0
Layer #0
Duration 160 ns
readoutawg 0
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp1, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
RFWaveform on ('readoutawg', 0)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp2, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
1
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp1, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
RFWaveform on ('readoutawg', 1)

Parameters
Duration Scalar(name=_implicit, value=80 ns, dtype=float, unit=s)
Amplitude Scalar(name=amp2, value=None, dtype=float, unit=none)
Frequency 4 GHz
Envelope GaussianEnvelope(4.0)
Instantaneous Phase 0 rad
Post-phase 0 rad
[36]:
Program([Layer([RFWaveform(duration=Scalar(name=_implicit, value=8e-08, dtype=float, unit=s), envelope={GaussianEnvelope(4.0): Scalar(name=amp1, value=None, dtype=float, unit=none)}, rf_frequency=Scalar(name=_implicit, value=4000000000.0, dtype=float, unit=Hz), instantaneous_phase={GaussianEnvelope(4.0): Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)}, post_phase=Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)), RFWaveform(duration=Scalar(name=_implicit, value=8e-08, dtype=float, unit=s), envelope={GaussianEnvelope(4.0): Scalar(name=amp2, value=None, dtype=float, unit=none)}, rf_frequency=Scalar(name=_implicit, value=4000000000.0, dtype=float, unit=Hz), instantaneous_phase={GaussianEnvelope(4.0): Scalar(name=_implicit, value=0.0, dtype=float, unit=rad)}, post_phase=Scalar(name=_implicit, value=0.0, dtype=float, unit=rad))])])

Download

Download this file as Jupyter notebook: sweep_examples.ipynb.