Calibration Set#

The purpose of the Calibration Set is to define all the experiment variables and gate definitions relevant to a set of experiments. The information contained in the Calibration Set falls into two categories: calibration parameters and linkers.

from __future__ import annotations

import numpy as np
import keysight.qcs as qcs

from keysight.qcs.channels import(
    Channels,
    ConstantEnvelope,
    GaussianEnvelope,
    PhaseIncrement,
    RFWaveform,
    SineEnvelope,
)
from keysight.qcs.programs import CalibrationSet
from keysight.qcs.quantum import GATES, PAULIS, ParameterizedGate, Qudits
from keysight.qcs.variables import Array

__all__ = ["calibration__set"]

###############################################################################################
#
# Configuration parameter
#
###############################################################################################

# define the qubits and matching virtual channels
n_qubits = 2
n_channels = 2
qubits = Qudits(range(n_qubits))
control_channels = Channels(qubits.labels, "xy_channels")
readout_channels = Channels(qubits.labels, "readout_channels", absolute_phase=True)
digitizer_channels = Channels(qubits.labels, "acquire_channels", absolute_phase=True)

# initialize the calibration set
calibration_set = CalibrationSet()

First we need to initialize physical and quantum channels and initialize the calibration_set object.

single_qubit_amplitudes = Array(
    "single_qubit_amplitudes", dtype=float, value=[0.5] * n_qubits
)
"""
The amplitudes for each single-qubit X gate or Pi pulse.
"""

Next we should add calibration parameters which should be used in experiments. This is done with Array objects.

##########################################################################################################
#
# Add the X gate
#
##########################################################################################################

x_pulse = RFWaveform(
    single_qubit_durations,
    GaussianEnvelope(),
    single_qubit_amplitudes,
    control_frequencies,
)
drag_waveform = x_pulse.drag(single_qubit_drag_coefficients)

calibration_set.add_sq_gate("x", GATES.x, drag_waveform, qubits, control_channels)

We should also create linkers which define quantum gates in terms of physical waveforms. This example is part of a longer list of linkers which can be used in experiment programs.

#########################################################################################################
#
# Add the measurement
#
#########################################################################################################

# define the readout drive pulse and integration filter

readout_pulse = RFWaveform(readout_durations, ConstantEnvelope(), readout_amplitudes, readout_frequencies, readout_phases)

integration_filter = RFWaveform(
    acquisition_durations, ConstantEnvelope(), 1, readout_frequencies
)


# define program for measurement

replacement_program = qcs.Program()

replacement_program.add_waveform(readout_oulse, readout_channels, pre_delay=readout_delays)

classifiers = [qcs.MinimumdistanceClassifier(classification_refs[qb]) for qb in range(n_qubits)]

replacement_program.add_acquisition(
    integration_filter,
    digitizer_channels,
    classifiers,
    pre_delay=readout_delays + acquisition+delays
)

measure = qcs.Measure()

meas_linker = qcs.ParameterizedLinker(measure, qubits, replacement_program)

calibration_set.add_linker("measurement", meas_linker)

qcs.save(calibration_set, "calibration_set.qcs")
print("Done - Cal file generated successfully")

Just as with the Channel Mapper, the end of our Calibration Set script will generate a file in the .qcs format with all the information needed to run a set of experiments.