Channels

The channels subpackage encapsulates the concepts that specify the input and output of instruments.

keysight.qcs.channels.Acquisition

Represents an acquisition.

keysight.qcs.channels.Address

Represents the address of a PhysicalChannel, defined by three integers that specify its chassis, slot and channel.

keysight.qcs.channels.ArbitraryEnvelope

Represents an arbitrary envelope specified by linearly interpolating a list of amplitudes.

keysight.qcs.channels.BaseClassifier

A base class for classifiers.

keysight.qcs.channels.BaseLOChannelSettings

Represents the settings of a physical channel that has a local oscillator.

keysight.qcs.channels.BaseWaveform

A base class for waveforms.

keysight.qcs.channels.BasebandAWGChannelSettings

Represents the settings of a baseband AWG channel.

keysight.qcs.channels.ChannelMapper

Represents a map between Channels and PhysicalChannels.

keysight.qcs.channels.ChannelSettings

Represents a physical channel's settings.

keysight.qcs.channels.Channels

A collection of channels to target.

keysight.qcs.channels.Classifier

Classifies results based on the minimum distance to a reference point.

keysight.qcs.channels.ConstantEnvelope

Represents a constant envelope \(E(t) = 1\).

keysight.qcs.channels.DCWaveform

A class for unmodulated waveforms.

keysight.qcs.channels.DataTransaction

A class representing a data transaction.

keysight.qcs.channels.Delay

A HardwareOperation representing a delay.

keysight.qcs.channels.DerivativeEnvelope

Represents a derivative envelope, normalized by the maximum absolute value.

keysight.qcs.channels.DigitizerChannelSettings

Represents the settings of a digitizer channel.

keysight.qcs.channels.DownconverterChannelSettings

Represents the settings of a downconverter channel.

keysight.qcs.channels.Envelope

An abstract base class for envelopes.

keysight.qcs.channels.FdsTransaction

A class representing an FDS Transaction through HVI.

keysight.qcs.channels.GaussianEnvelope

Represents a truncated Gaussian envelope shifted and rescaled to satisfy \(E(0) = E(1) = 0\) and \(E(0.5) = 1\).

keysight.qcs.channels.HardwareOperation

A base class for hardware operations.

keysight.qcs.channels.Hold

A HardwareOperation representing a hold.

keysight.qcs.channels.InstrumentEnum

An enum specifying the supported instrument types.

keysight.qcs.channels.IntegrationFilter

Represents an integration filter for demodulating and integrating time-domain signals.

keysight.qcs.channels.MaskEnvelope

Represents the part of an envelope between a specified start and end time.

keysight.qcs.channels.MinimumDistanceClassifier

Classifies results based on the minimum distance to a reference point.

keysight.qcs.channels.PhaseIncrement

A HardwareOperation representing a phase increment.

keysight.qcs.channels.PhysicalChannel

Represents a channel of an instrument.

keysight.qcs.channels.RFAWGChannelSettings

Represents the settings of an RF AWG channel.

keysight.qcs.channels.RFWaveform

Represents a waveform with target frequency or frequencies.

keysight.qcs.channels.Register

A class for a register with a fixed number of bits.

keysight.qcs.channels.SineEnvelope

Represents a sine envelope \(E(t) = \sin(\pi t)\).

keysight.qcs.channels.TransactionList

A class representing a list of DataTransaction between virtual channels.

Acquisitions

class keysight.qcs.channels.Acquisition(integration_filter: float | Variable[float] | HardwareOperation | Iterable[HardwareOperation] | IntegrationFilter, classifier: MinimumDistanceClassifier | Iterable[MinimumDistanceClassifier] | None = None, name: str | None = None)

Bases: HardwareOperation

Represents an acquisition.

Note

As the M5200 Digitizer returns blocks of 16 samples, the duration of an acquisition with an integration filter should be chosen such that the number of samples is a multiple of 16.

import keysight.qcs as qcs

# initialize a 100ns acquisition
qcs.Acquisition(100e-9)

# initialize a constant 100ns integration filter with an amplitude of 1
waveform = qcs.DCWaveform(100e-9, qcs.ConstantEnvelope(), 1)
integration_filter = qcs.IntegrationFilter(waveform)

# specify a 100ns acquisition with a constant integration filter
qcs.Acquisition(integration_filter)
Acquisition(IntegrationFilter(DCWaveform(duration=Scalar(name=_implicit, value=1e-07, dtype=float, unit=s), envelope={ConstantEnvelope(): Scalar(name=_implicit, value=1.0, dtype=float, unit=none)})))
Parameters:
  • integration_filter – The integration filter or a duration.

  • classifier – The classifiers used to classify integrated acquisitions.

  • name – An optional name for this.

Raises:
  • ValueError – If classifiers are supplied without an integration filter.

  • ValueError – If the number of classifiers does not match the slice width of the integration filters.

render(sample_rate: float, lo_frequency: float = 0.0, sample_offset: float = 0.5) np.ndarray | list[np.ndarray]

Computes the acquisition. The acquisition is rendered at a sideband frequency relative to lo_frequency.

Parameters:
  • sample_rate – The rate at which to sample the acquisition in Hz.

  • lo_frequency – The frequency of the LO in Hz.

  • sample_offset – The offset of each sample in the sample window. The default value of 0.5 generates samples in the middle of the sample window.

property classifier: Classifier | None

The classification to perform after the integration filter is applied.

property duration: Scalar[float]

The duration of the acquisition in seconds.

property integration_filter: IntegrationFilter | None

The integration filter used to integrate the raw results.

property rf_frequencies: set[float]

The RF frequencies in the integration filters of this acquisition.

class keysight.qcs.channels.BaseClassifier

A base class for classifiers.

Parameters:

references – The map from reference points to the classified output.

property references: Array[complex]

Returns the map from reference points to the classified output.

classify(result: complex) int

Classify a result into distinct outcomes.

Parameters:

result – Is the result to classify.

class keysight.qcs.channels.Classifier(references: list[complex] | Array[complex], register: Register | None = None)

Classifies results based on the minimum distance to a reference point.

Parameters:
  • references – The reference points.

  • register – The register to which the classified results are to be written. A register is required if the classified data is used in subsequent conditional operations.

property register: Register | None

The register to which the classified results are to be written.

property slice_width: int | None

The number of classifiers in this, or None if there is a single classifier.

class keysight.qcs.channels.MinimumDistanceClassifier(references: list[complex] | Array[complex])

Classifies results based on the minimum distance to a reference point.

Parameters:

references – The reference points.

class keysight.qcs.channels.IntegrationFilter(*waveforms: HardwareOperation)

Bases: CsWrapper

Represents an integration filter for demodulating and integrating time-domain signals.

The signal provided to the integrate() is demodulated to a single complex number using the formula

\[z = 2 * V^\dagger U / n\]

where \(V\) is the rendered integration filter and n is the number of points of both \(U\) and \(V\).

import keysight.qcs as qcs
import numpy as np

# initialize a filter from a single waveform
duration = 120e-9
waveform = qcs.DCWaveform(duration, qcs.ConstantEnvelope(), 1)
integration_filter = qcs.IntegrationFilter(waveform)

# initialize a set of data
sample_rate = 4.8e9
n_samples = round(duration * sample_rate)
data = np.ones(n_samples)

# obtain the result by integrating
result = integration_filter.integrate(data, sample_rate)
assert (result == [2]).all()

# specify a sliceable filter with a sliceable waveform
frequencies = qcs.Array("frequencies", value=[0, 10e6, 20e6])
waveform = qcs.RFWaveform(duration, qcs.ConstantEnvelope(), 1, frequencies)
filter_slc = qcs.IntegrationFilter(waveform)

# integrate the data with each of the slices
result_slc = filter_slc.integrate(data, sample_rate)
assert np.allclose(result_slc, [2 + 0j, 0.25 - 0.18j, 0.08 - 0.23j], atol=2)
Parameters:

waveforms – One or more HardwareOperations used to perform demodulation.

property duration: Variable[float]

Returns the total filter duration in seconds.

property rf_frequencies: set[float]

Returns all the RF frequencies in this filter.

Raises:

ValueError – If any RF frequency has not been set.

property slice_width: int | None

The dimension of the sliceable axis, or None if this filter does not contain sliceable HardwareOperations.

property waveforms: tuple[keysight.qcs.channels.waveforms.HardwareOperation, ...]

Series of HardwareOperations used to perform demodulation.

broadcast(prefix: str, length: int) IntegrationFilter

Returns a new integration filter where any scalars have been broadcast to arrays.

Parameters:
  • prefix – The prefix to use when broadcasting variables.

  • length – The length of the resulting arrays.

integrate(signal: ndarray, sample_rate: float, downconversion_frequency: float = 0.0, sample_offset: float = 0.5, truncate: bool = False) ndarray

Returns the integrated time-domain data. If the filter is sliceable, the first axis is the slice axis.

Parameters:
  • signal – The data to process. If multi-dimensional, the last axis is interpreted as time.

  • sample_rate – Sample rate of the signal.

  • downconversion_frequency – The frequency the filter is rendered with. See render().

  • sample_offset – The offset of each sample in the sample window. The default value of 0.5 generates samples in the middle of the sample window.

  • truncate – Whether to truncate samples from either the signal or the filter before integrating.

Raises:

ValueError – If the number of samples of signal and the rendered filter is different when truncate is False.

render(sample_rate: float, lo_frequency: float = 0.0, sample_offset: float = 0.5) np.ndarray | list[np.ndarray]

Computes the filter. The filter is rendered at a sideband frequency relative to lo_frequency.

Parameters:
  • sample_rate – The rate at which to sample the filter in Hz.

  • lo_frequency – The frequency of the LO in Hz.

  • sample_offset – The offset of each sample in the sample window. The default value of 0.5 generates samples in the middle of the sample window.

Data Transactions

class keysight.qcs.channels.DataTransaction(source: TargetedOperation)

A class representing a data transaction.

Parameters:

source – The operation that will populate the register for this transaction.

property destinations: list[keysight.qcs.operations.targeted_operation.TargetedOperation]

The destination for the data.

property register: Register

The register for this transaction.

property source: TargetedOperation

The source of the data.

class keysight.qcs.channels.FdsTransaction(source: Address, destination: Address)

A class representing an FDS Transaction through HVI.

Parameters:
  • source – The source module address.

  • destination – The destination module address.

property destination: Address

The destination module address.

property source: Address

The source module address.

class keysight.qcs.channels.TransactionList

A class representing a list of DataTransaction between virtual channels.

property unmapped_transactions: list[keysight.qcs.channels.data_transaction.DataTransaction]

A list of DataTransaction between virtual channels.

property mapped_transactions: list[keysight.qcs.channels.data_transaction.DataTransaction]

A list of FdsTransactions between source addresses.

class keysight.qcs.channels.Register(name: str, num_outcomes: int, dim: int | None = None)

A class for a register with a fixed number of bits.

Parameters:
  • name – The name of this register.

  • num_outcomes – The number of outcomes to be stored in this register.

  • dim – The number of outcomes to be stored in each group of bits.

property dim: int

The number of outcomes stored in each group of bits in this register.

property name: str

The name of this register.

property num_bits: int

The number of bits in this register.

property num_outcomes: int

The number of outcomes in this register.

binary_representations(num_ops: int) list[str]

Returns the binary representations of the bit strings needed to choose from a specified number of operations.

Parameters:

num_ops – The number of operations to choose from.

num_outcomes_per_decision(num_ops: int) int

Returns the number of outcomes needed to choose from a specified number of operations.

Parameters:

num_ops – The number of operations to choose from.

num_decisions(num_ops: int) int

Gets the number of independent decisions that can be made for a specified number of operations from this register.

Parameters:

num_ops – The number of operations to choose from in each decision.

Instrument Channels

class keysight.qcs.channels.Address(chassis: int, slot: int, channel: int, host_controller: int = 1)

Represents the address of a PhysicalChannel, defined by three integers that specify its chassis, slot and channel.

Parameters:
  • chassis – An integer specifying a chassis number.

  • slot – An integer specifying a slot number.

  • channel – An integer specifying a channel number.

  • host_controller – An integer specifying a host controller ID.

property chassis: int

The chassis number.

property host_controller: int

The host controller index.

property channel: int

The channel number.

property slot: int

The slot number.

class keysight.qcs.channels.Channels(labels: int | Iterable[int], name: str | None = None, absolute_phase: bool = False)

Bases: Targets

A collection of channels to target.

Channels are destinations for channel-level operations. Channels that are grouped together can be used as a target for a common operation. Individual channels are identified by an integer label and the name of the collection.

import keysight.qcs as qcs

# five channels each used for single-qubit xy control
xy_channels = qcs.Channels(range(5), "xy_channels")

# slice into a subset of the channels
assert xy_channels[0:2] == qcs.Channels(range(2), "xy_channels")
Parameters:
  • labels – An iterable of channel labels, or an integer representing a single label.

  • name – The name of this channel collection.

  • absolute_phase – Whether RFWaveforms played on the channels in this collection are rendered with a relative or an absolute phase.

Raises:

ValueError – If the name contains symbols other than letters, numbers and underscores.

property absolute_phase: bool

Whether RFWaveforms played on the channels in this collection are rendered with a relative or an absolute phase.

class keysight.qcs.channels.ChannelMapper(ip_address: str | None = None)

Bases: CsWrapper

Represents a map between Channels and PhysicalChannels.

import keysight.qcs as qcs

# two channels each used for single-qubit xy control
xy_channels = qcs.Channels(range(2), "xy_channels")

# the associated physical channel addresses
address1 = qcs.Address(1, 2, 3)
address2 = qcs.Address(1, 2, 4)
instrument_type = qcs.InstrumentEnum.M5300AWG

# the channel mapper
chan_map = qcs.ChannelMapper()

# add the configurations
chan_map.add_channel_mapping(xy_channels, [address1, address2], instrument_type)

# get the physical channel associated with the first channel
(phys_chan1,) = chan_map.get_physical_channels(xy_channels[0])
assert phys_chan1.address == address1
assert phys_chan1.instrument == instrument_type
assert phys_chan1.settings.setting_names == ["delay", "lo_frequency"]
Parameters:

ip_address – An IP address used for remote job submission.

property channels: list[keysight.qcs.channels.channels.Channels]

The Channels in this channel mapper.

property ip_address: str | None

The IP address of this channel mapper.

property physical_channels: list[keysight.qcs.channels.physical_channels.PhysicalChannel]

The PhysicalChannels in this channel mapper.

add_channel_mapping(channels: Channels, addresses: Address | tuple[int, int, int] | list[Address | tuple[int, int, int]], instrument_types: InstrumentEnum | Iterable[InstrumentEnum]) None

Adds a channel configuration to map labels in Channels to Addresss.

Parameters:
  • channels – The channels to map from.

  • addresses – The physical channel addresses to map to.

  • instrument_types – The type of instrument present at address.

Raises:
  • ValueError – If the number of physical channels does not match the number of labels.

  • ValueError – If the attributes of channels does not match those specified in the channel map.

add_downconverters(dig_addresses: Address | tuple[int, int, int] | list[Address | tuple[int, int, int]], downcon_addresses: Address | tuple[int, int, int] | list[Address | tuple[int, int, int]]) None

Maps digitizer channel addresses to upstream downconverter channel addresses.

import keysight.qcs as qcs

ch_map = qcs.ChannelMapper()

# link two digitizer channels in slot 3 with two downconverter channels in
# slot 4.
ch_map.add_downconverters(
    [qcs.Address(1, 3, 1), qcs.Address(1, 3, 2)],
    [qcs.Address(1, 4, 1), qcs.Address(1, 4, 2)],
)

assert ch_map.get_downconverter(
    qcs.Address(1, 3, 1)
).address == qcs.Address(1, 4, 1)
Parameters:
  • dig_addresses – The digitizer addresses to assign downconverters to.

  • downcon_addresses – The downconverter addresses to assign.

Raises:

ValueError – If the number of digitizer and downconverter addresses do not match.

get_downconverter(channel: PhysicalChannel | Address | tuple[int, int, int]) PhysicalChannel | None

Returns the upstream downconverter physical channel of a digitizer channel. Returns None if no downconverter is connected to the given channel.

Parameters:

channel – The digitizer channel or address.

get_physical_channel(address: Address | tuple[int, int, int]) PhysicalChannel

Returns the PhysicalChannel for an address.

Raises:

ValueError – If the address is not defined in this channel mapper.

get_physical_channels(channels: Channels) list[keysight.qcs.channels.physical_channels.PhysicalChannel]

Returns PhysicalChannels for each label in channels.

Parameters:

channels – The channels to get the physical channels of.

get_virtual_channels(address: Address | tuple[int, int, int]) Iterable[Channels]

Returns the Channelss for the given address.

Parameters:

address – The address to get the virtual channels of.

constrain_lo_frequencies(addresses: Address | tuple[int, int, int] | list[Address | tuple[int, int, int]], min_freq: float, max_freq: float) float

Sets the LO frequency setting of a group of channels.

This method first constrains the LO frequency setting of the given channels. It then updates the setting values to a suitable LO frequency based on a given RF frequency range.

When a downconverter is not present in the list of addresses (i.e., only RF AWGs), this sets the LO frequency to the midpoint of the highest and lowest RF frequency provided. This uses both sidebands of the RF AWG.

When a downconverter is present in the list of addresses, this chooses the LO frequency such that the minimum IF frequency is above the minimum sideband frequency of 20 MHz. This is to account for the fact that the M5201A Downconverter has a high-pass filter on its IF output ports, and hence does not pass small IF frequencies. Additionally, this avoids the problem of spectral folding, wherein the upper and lower sidebands are indistinguishable after downconversion.

import keysight.qcs as qcs

# initialize virtual channels
xy_awg = qcs.Channels(range(1), "xy_awgs")
readout_awg = qcs.Channels(range(1), "readout_awgs")
digs = qcs.Channels(range(1), "digs")

# map virtual channels to physical addresses
mapper = qcs.ChannelMapper()
mapper.add_channel_mapping(xy_awg, [(1, 1, 1)], qcs.InstrumentEnum.M5300AWG)
mapper.add_channel_mapping(
    readout_awg, [(1, 2, 1)], qcs.InstrumentEnum.M5300AWG
)
mapper.add_channel_mapping(
    digs, [(1, 4, 1)], qcs.InstrumentEnum.M5200Digitizer
)
mapper.add_downconverters([(1, 4, 1)], [(1, 3, 1)])

# set the LO frequency for the awg in slot 1
xy_lo = mapper.constrain_lo_frequencies([(1, 1, 1)], 6e9, 6.6e9)
assert xy_lo == 6.3e9

# set the LO frequency for the awg and downconverter used for readouts
readout_lo = mapper.constrain_lo_frequencies(
    [(1, 2, 1), (1, 3, 1)], 6.4e9, 6.9e9
)
assert readout_lo == 6.38e9
Parameters:
  • addresses – The physical channel addresses to set to the same LO frequency.

  • min_freq – The minimum RF frequency played through a channel.

  • max_freq – The maximum RF frequency played through a channel.

Raises:
  • ValueError – If a specified channel does not have an LO frequency setting.

  • ValueError – If the range of frequencies is larger than the bandwidth of the M5300 AWG and M5201 downconverter.

set_delays(addresses: Address | tuple[int, int, int] | list[Address | tuple[int, int, int]], delays: float | list[float] | Scalar[float] | list[Scalar[float]]) None

Sets the delay setting of a group of channels.

Parameters:
  • addresses – The physical channel addresses to set.

  • delays – The delays to set these channels to. All addresses are set to the same delay if provided with only a single delay.

Raises:

ValueError – If the number of delays given does not match the number of addresses when provided with more than one delay.

set_lo_frequencies(addresses: Address | tuple[int, int, int] | list[Address | tuple[int, int, int]], lo_frequency: float) None

Sets the LO frequency setting of a group of channels to a given value.

Parameters:
  • addresses – The physical channel addresses to set to the given LO frequency.

  • lo_frequency – The LO frequency to set these channels to.

Raises:

ValueError – If a specified channel does not have an LO frequency setting.

class keysight.qcs.channels.PhysicalChannel(address: Address | tuple[int, int, int], instrument: InstrumentEnum | str)

Bases: CsWrapper

Represents a channel of an instrument.

Note

This class should not be constructed directly, and should instead be constructed through ChannelMapper.

Parameters:
  • address – The address of this channel.

  • instrument – The instrument type of this channel.

property address: Address

The address of this channel.

property bandwidth: float

The bandwidth of the channel in Hz.

property instrument: InstrumentEnum

The instrument type of this channel.

property sample_rate: float | None

The sample rate of the channel in Hz, or None for analog channels.

property settings: ChannelSettings

The settings of this channel.

property yield_variables: Generator[Variable]

Yield the variables of this channel.

Instrument Channel Settings

class keysight.qcs.channels.ChannelSettings

Bases: CsWrapper

Represents a physical channel’s settings.

Parameters:

name – The name of this collection of settings.

property delay: Scalar[float]

The physical channel delay.

The units are in seconds and the default value is 0.0.

property name: str

The name of this collection of settings.

abstract property setting_names: list[str]

The setting names.

property yield_variables: Generator[Scalar]

Yield the variables in this setting.

constrain(setting_name: str, source: Scalar[float]) None

Constrains the value of a channel setting to that of another Scalar.

import keysight.qcs as qcs

settings = qcs.BasebandAWGChannelSettings("1x2x1")
source = qcs.Scalar("other_scalar", value=0.1, dtype=float)
settings.constrain("offset", source)
assert settings.offset == source
assert settings.offset.value == 0.1

source.value = 0.2
assert settings.offset.value == 0.2

This can also be used to tie settings together between channels:

settings_downconverter = qcs.DownconverterChannelSettings("1x2x1")
settings_awg = qcs.RFAWGChannelSettings("1x3x1")

settings_awg.constrain("lo_frequency", settings_downconverter.lo_frequency)
settings_downconverter.lo_frequency.value = 8e9
assert settings_awg.lo_frequency.value == 8e9
Parameters:
  • setting_name – The name of the setting to constrain in snake_case.

  • source – The unique name of this settings collection.

Raises:

ValueError – If setting_name is not a valid setting name.

get_default_value(setting_name: str) float | None

Returns the default value of a setting.

import keysight.qcs as qcs

settings = qcs.BasebandAWGChannelSettings("1x2x1")
assert settings.get_default_value("offset") == 0.0
Parameters:

setting_name – The name of the setting.

Raises:

ValueError – If setting_name is not a valid setting name.

reset(setting_name: str)

Restores a channel setting to its default state.

import keysight.qcs as qcs

settings = qcs.BasebandAWGChannelSettings("1x2x1")
settings.offset.value = 0.4
settings.reset("offset")
assert settings.offset.value == settings.get_default_value("offset")

This method can be used to remove settings constraints.

import keysight.qcs as qcs

settings = qcs.BasebandAWGChannelSettings("1x2x1")
source = qcs.Scalar("other_scalar", value=0.1, dtype=float)
settings.constrain("offset", source)
assert settings.offset.value == 0.1
settings.reset("offset")
assert settings.offset.value == settings.get_default_value("offset")
Parameters:

setting_name – The name of the setting to reset in snake_case.

Raises:

ValueError – If setting_name is not a valid setting name.

class keysight.qcs.channels.BasebandAWGChannelSettings(name)

Bases: ChannelSettings

Represents the settings of a baseband AWG channel.

import keysight.qcs as qcs

settings = qcs.BasebandAWGChannelSettings("1x2x1")
assert settings.offset.value == 0.0
Parameters:

name – The unique name of this settings collection.

property offset: Scalar[float]

The DC offset voltage as a fraction of the max output voltage.

The default value is 0 and the limits are [-1, 1].

property setting_names: list[str]

The setting names.

class keysight.qcs.channels.BaseLOChannelSettings

Bases: ChannelSettings

Represents the settings of a physical channel that has a local oscillator.

Parameters:

name – The unique name of this settings collection.

property lo_frequency: Scalar[float]

The local oscillator frequency.

The setting units are Hz and the limits are [0, 18e9]. The setting defaults to a value of None, meaning that it must be set before executing. See constrain_lo_frequencies() for an automated way of setting this value.

property setting_names: list[str]

The setting names.

class keysight.qcs.channels.DigitizerChannelSettings(name)

Bases: ChannelSettings

Represents the settings of a digitizer channel.

import keysight.qcs as qcs

settings = qcs.DigitizerChannelSettings("1x3x1")
assert settings.range.value == 0.9
Parameters:

name – The unique name of this settings collection.

property range: Scalar[float]

The range of this digitizer channel.

The units are in Volts. This defaults to a value of 0.9 and its limits are [0.045, 1.7].

property setting_names: list[str]

The setting names.

class keysight.qcs.channels.DownconverterChannelSettings(name: str)

Bases: BaseLOChannelSettings

Represents the settings of a downconverter channel.

import keysight.qcs as qcs

settings = qcs.DownconverterChannelSettings("1x4x1")
assert settings.lo_frequency.value is None
Parameters:

name – The unique name of this settings collection.

class keysight.qcs.channels.RFAWGChannelSettings(name: str)

Bases: BaseLOChannelSettings

Represents the settings of an RF AWG channel.

import keysight.qcs as qcs

setings = qcs.RFAWGChannelSettings("1x5x1")
assert settings.lo_frequency.value is None
Parameters:

name – The unique name of this settings collection.

Supported Instruments

Constants

qcs.SAMPLE_RATES = {<InstrumentEnum.M3202AWG: 0>: 1000000000.0, <InstrumentEnum.M5300AWG: 1>: 2400000000.0, <InstrumentEnum.M5301AWG: 2>: 2400000000.0, <InstrumentEnum.M5200Digitizer: 3>: 4800000000.0}
class keysight.qcs.channels.InstrumentEnum

An enum specifying the supported instrument types.

The names (values) are: M3202AWG (0) M5300AWG (1) M5301AWG (2) M5200Digitizer (3) M5201Downconverter (4)

from_string() str

Construct a <class ‘Keysight.Qcs.SharedTypes.Channels.InstrumentEnum’> from a string.

Waveforms

class keysight.qcs.channels.ArbitraryEnvelope(times: Iterable[float], amplitudes: Iterable[complex])

Bases: Envelope

Represents an arbitrary envelope specified by linearly interpolating a list of amplitudes.

Upon construction, the times are renormalized to the unit interval [0, 1] and the sampled values are normalized to the unit disc.

import keysight.qcs as qcs
import numpy as np

# initialize an ArbitraryEnvelope
pulse = qcs.ArbitraryEnvelope(np.linspace(0, 1, 5), np.linspace(0, 1, 5))
Parameters:
  • times – The time (in seconds) corresponding to each of the amplitudes.

  • amplitudes – The amplitudes of the envelope.

Raises:

ValueError – If any sampled time is negative or there is no positive sampled time.

property sampled_amplitudes: ndarray

The normalized sampled amplitudes.

property sampled_times: ndarray

The normalized times at which the amplitudes were sampled.

static sample(fn: Callable[[float], complex], n_samples: int) ArbitraryEnvelope

Returns an instance of this class with amplitudes sampled n_samples times from fn on the interval [0, duration].

Parameters:
  • fn – The function to sample from.

  • n_samples – The number of samples.

class keysight.qcs.channels.BaseWaveform

Bases: HardwareOperation

A base class for waveforms.

Parameters:

duration – The duration of the waveform in seconds.

property amplitudes: list[Variable[float]]

The amplitudes of the envelopes.

property envelopes: dict[Envelope, Variable[float]]

The dictionary from envelopes to corresponding amplitudes.

For envelopes \(E_i(t)\) with amplitudes \(\alpha_i\), the envelope of the waveform is given by the linear combination

\[E(t) = \sum_i \alpha_i E_i(t).\]
render(sample_rate: float, lo_frequency: float = 0.0, sample_offset: float = 0.5) np.ndarray | list[np.ndarray]

Render the waveform as it would appear at the input of a specified channel before mixing with a local oscillator (LO) at a specific frequency.

Parameters:
  • sample_rate – The rate at which to sample the envelope in Hz.

  • lo_frequency – The frequency of the LO in Hz.

  • sample_offset – The offset of each sample in the sample window. The default value of 0.5 generates samples in the middle of the sample window.

to_flattop(hold_duration: float | Iterable[float] | Variable[float], fraction: float = 0.5) list[HardwareOperation]

Returns a sequence of three operations where a sample at a specified fraction is held for a specified time.

Parameters:
  • hold_duration – How long to hold the sample for.

  • fraction – The fraction of the duration specifying the sample to hold.

Raises:

ValueError – If fraction is not in [0.0, 1.0].

class keysight.qcs.channels.ConstantEnvelope

Bases: Envelope

Represents a constant envelope \(E(t) = 1\).

import keysight.qcs as qcs

# initialize a ConstantEnvelope
pulse = qcs.ConstantEnvelope()
class keysight.qcs.channels.DCWaveform(duration: float | Iterable[float] | Variable[float], envelope: Envelope, amplitude: float | Variable[float], name: str | None = None)

Bases: BaseWaveform

A class for unmodulated waveforms.

Parameters:
  • duration – The duration of the waveform.

  • envelope – The shape of the waveform.

  • amplitude – The amplitude of the waveform relative to the range of the signal generator.

  • name – An optional name for this.

class keysight.qcs.channels.Delay(duration: float | Iterable[float] | Variable[float], name: str | None = None)

Bases: HardwareOperation

A HardwareOperation representing a delay.

When a delay is present in a series of waveforms, the next RF waveform is modulated by the phase accumulated during the delay, which depends on the frequency of the next RF waveform. This ensures that channels can track phase evolution.

The value of the phase is exp(1j * sampled_delay * int_freq) where sampled_delay is the exact duration of the delay accounting for finite sampling effects (that is, the output of delay.sampled_duration(sample_rate)) and int_freq is the output of waveform.intermediate_frequency(lo_frequency).

Parameters:
  • duration – The duration of the delay in seconds.

  • name – An optional name for this.

render(sample_rate: float, lo_frequency: float = 0.0, start: float = 0.0) ndarray

Renders the delay as it would appear at the input of a specified channel before mixing with a local oscillator (LO) at a specific frequency.

Parameters:
  • sample_rate – The rate at which to sample the operation in Hz.

  • lo_frequency – The frequency of the LO in Hz.

  • start – The start time in seconds.

class keysight.qcs.channels.DerivativeEnvelope(base_envelope: Envelope)

Bases: Envelope

Represents a derivative envelope, normalized by the maximum absolute value.

The derivative is evaluated using a central finite difference with a step size of 1% of the sample period, unless the sample offset is too close to an edge, in which case it falls back to the appropriate forward or backward finite difference.

import keysight.qcs as qcs

# initialize a single derivative envelope
base_env = qcs.SineEnvelope()
pulse = qcs.DerivativeEnvelope(base_env)
Parameters:

base_envelope – The base envelope.

property base: Envelope

The envelope to differentiate.

class keysight.qcs.channels.Envelope

Bases: CsWrapper

An abstract base class for envelopes.

render(n_samples: int = 64, sample_offset: float = 0.5) ndarray

Render the envelope.

By default, envelopes are normalized to the unit interval and this method will return \(64\) samples.

import keysight.qcs as qcs

envelope = qcs.GaussianEnvelope(4)
envelope.render()
array([9.44711312e-05+0.j, 3.62458897e-04+0.j, 7.79880111e-04+0.j,
       1.41928233e-03+0.j, 2.38240131e-03+0.j, 3.80884406e-03+0.j,
       5.88593499e-03+0.j, 8.85922081e-03+0.j, 1.30427741e-02+0.j,
       1.88280253e-02+0.j, 2.66894332e-02+0.j, 3.71849332e-02+0.j,
       5.09488792e-02+0.j, 6.86752013e-02+0.j, 9.10888496e-02+0.j,
       1.18904354e-01+0.j, 1.52771524e-01+0.j, 1.93209934e-01+0.j,
       2.40535702e-01+0.j, 2.94786083e-01+0.j, 3.55649096e-01+0.j,
       4.22406682e-01+0.j, 4.93900196e-01+0.j, 5.68526310e-01+0.j,
       6.44269391e-01+0.j, 7.18773229e-01+0.j, 7.89450938e-01+0.j,
       8.53627259e-01+0.j, 9.08703130e-01+0.j, 9.52328808e-01+0.j,
       9.82569622e-01+0.j, 9.98048126e-01+0.j, 9.98048126e-01+0.j,
       9.82569622e-01+0.j, 9.52328808e-01+0.j, 9.08703130e-01+0.j,
       8.53627259e-01+0.j, 7.89450938e-01+0.j, 7.18773229e-01+0.j,
       6.44269391e-01+0.j, 5.68526310e-01+0.j, 4.93900196e-01+0.j,
       4.22406682e-01+0.j, 3.55649096e-01+0.j, 2.94786083e-01+0.j,
       2.40535702e-01+0.j, 1.93209934e-01+0.j, 1.52771524e-01+0.j,
       1.18904354e-01+0.j, 9.10888496e-02+0.j, 6.86752013e-02+0.j,
       5.09488792e-02+0.j, 3.71849332e-02+0.j, 2.66894332e-02+0.j,
       1.88280253e-02+0.j, 1.30427741e-02+0.j, 8.85922081e-03+0.j,
       5.88593499e-03+0.j, 3.80884406e-03+0.j, 2.38240131e-03+0.j,
       1.41928233e-03+0.j, 7.79880111e-04+0.j, 3.62458897e-04+0.j,
       9.44711312e-05+0.j])

With a given duration and sample_rate, the envelope is rendered as it appears on an instrument.

import keysight.qcs as qcs

duration = qcs.Scalar("duration", value=30e-9, dtype=float)
sample_rate = 1e9
qcs.GaussianEnvelope(4).render(n_samples=duration.value * sample_rate)
array([2.31385801e-04+0.j, 1.19875019e-03+0.j, 3.53164225e-03+0.j,
       8.74255799e-03+0.j, 1.95121777e-02+0.j, 4.00794614e-02+0.j,
       7.63107690e-02+0.j, 1.35045123e-01+0.j, 2.22374001e-01+0.j,
       3.40887090e-01+0.j, 4.86580023e-01+0.j, 6.46786686e-01+0.j,
       8.00670535e-01+0.j, 9.23090546e-01+0.j, 9.91147531e-01+0.j,
       9.91147531e-01+0.j, 9.23090546e-01+0.j, 8.00670535e-01+0.j,
       6.46786686e-01+0.j, 4.86580023e-01+0.j, 3.40887090e-01+0.j,
       2.22374001e-01+0.j, 1.35045123e-01+0.j, 7.63107690e-02+0.j,
       4.00794614e-02+0.j, 1.95121777e-02+0.j, 8.74255799e-03+0.j,
       3.53164225e-03+0.j, 1.19875019e-03+0.j, 2.31385801e-04+0.j])
Parameters:
  • n_samples – The number of samples to render.

  • sample_offset – The offset of each sample in the sample window. The default value of 0.5 generates samples in the middle of the sample window.

class keysight.qcs.channels.GaussianEnvelope(num_sigma: float = 2)

Bases: Envelope

Represents a truncated Gaussian envelope shifted and rescaled to satisfy \(E(0) = E(1) = 0\) and \(E(0.5) = 1\).

The envelope \(E(t)\) at time \(t\) is

\[E(t) = (1 + \alpha)\exp\left(-(2 * t - 1)^2 n_\sigma^2 / 2 \right) - \alpha\:,\]

where \(n_\sigma\) is the number of standard deviations included in the envelope and \(\alpha\) is the scale factor.

import keysight.qcs as qcs

# initialize a GaussianEnvelope with three standard deviations
pulse = qcs.GaussianEnvelope(3)
Parameters:

num_sigma – The number of standard deviations to include in the envelope.

Raises:

ValueError – If num_sigma is less than 2.

property alpha: float

The scale factor used to ensure that \(E(0) = E(1) = 0\) and \(E(0.5) = 1\).

Specifically, \(\alpha = 1 / (\exp\left(n_\sigma^2 / 2\right) - 1)\).

property num_sigma: float

The number of standard deviations included in the envelope.

class keysight.qcs.channels.HardwareOperation

Bases: BaseOperation

A base class for hardware operations.

Parameters:

duration – The duration of the operation in seconds.

property duration: Variable[float]

The duration in seconds.

n_samples(sample_rate: float) int

The number of samples in this operation when sampled at a specific rate.

Parameters:

sample_rate – The sample rate in Hz.

sampled_duration(sample_rate: float) float

The duration of the operation in seconds when sampled at a specified rate.

Parameters:

sample_rate – The rate at which to sample the operation in Hz.

class keysight.qcs.channels.Hold(duration: float | Iterable[float] | Variable[float], name: str | None = None)

Bases: HardwareOperation

A HardwareOperation representing a hold.

When a hold is present in a series of waveforms, the value of the last sample will be held as a constant waveform and modulated based on the previous waveform.

Parameters:
  • duration – The duration of the hold in seconds.

  • name – An optional name for this.

make_waveform(amplitude: complex, frequency: float | None) BaseWaveform

Makes a waveform equivalent to this based on the last sample value and the frequency of the last waveform.

Parameters:
  • value – The value of the sample immediately before this.

  • frequency – The frequency of the previous waveform.

class keysight.qcs.channels.MaskEnvelope(base_envelope: Envelope, start: float, end: float)

Bases: Envelope

Represents the part of an envelope between a specified start and end time.

import keysight.qcs as qcs

# initialize a single Mask envelope for the first half of a sine envelope
base_env = qcs.SineEnvelope()
pulse = qcs.MaskEnvelope(base_env, 0, 0.5)
Parameters:
  • base_envelope – The base envelope.

  • start – The start of the mask as a fraction of the unit interval.

  • end – The end of the mask as a fraction of the unit interval.

Raises:
  • ValueError – If start or end is outside [0.0, 1.0].

  • ValueError – If end is less than start.

property base: Envelope

The envelope to mask.

property end: float

The end of the mask as a fraction of the unit interval.

property start: float

The start of the mask as a fraction of the unit interval.

class keysight.qcs.channels.PhaseIncrement(phase: float | Variable[float], name: str | None = None)

Bases: HardwareOperation

A HardwareOperation representing a phase increment. This operation always has duration \(0\).

When a phase increment is present in a series of waveforms, the phase of the next RFWaveform will be incremented.

Parameters:
  • phase – The phase to increment the next RF waveform by in radians.

  • name – An optional name for this.

property phase: Variable[float]

The phase in radians.

class keysight.qcs.channels.RFWaveform(duration: float | Iterable[float] | Scalar[float], envelope: Envelope, amplitude: float | Variable[float], rf_frequency: float | Variable[float], instantaneous_phase: float | Variable[float] = 0.0, post_phase: float | Variable[float] = 0.0, name: str | None = None)

Bases: BaseWaveform

Represents a waveform with target frequency or frequencies.

The signal \(V(t)\) at time \(t\) after modulating an envelope \(E(t)\) by a frequency \(f\) and a phase \(\phi\) is

\[V(t) = E(t) \exp(2 \pi j f t + \phi).\]
import keysight.qcs as qcs

# initialize a 100ns base envelope
base = qcs.ConstantEnvelope()

# initialize an RFWaveform with an amplitude of 0.3 and a frequency of 5 GHz
pulse1 = qcs.RFWaveform(100e-9, base, 0.3, 5e9)

# initialize a sliceable RFWaveform with different frequencies
rf = qcs.Array("rf", value=[5e9, 6e9])
pulse2 = qcs.RFWaveform(100e-9, base, 0.3, rf)

Note

If rf_frequency and instantaneous_phase are given as floats, they are converted to a scalar. Otherwise, if they are given as scalar or array, they are stored as provided.

Parameters:
  • duration – The duration of the waveform.

  • envelope – The envelope of the waveform before modulation.

  • amplitude – The amplitude of the waveform relative to the range of the signal generator.

  • rf_frequency – The RF frequency of the output pulse in Hz.

  • instantaneous_phase – The amount (in radians) by which the phase of this waveform is shifted, relative to the rotating frame set by rf_frequency.

  • post_phase – The amount (in radians) by which the phase of all subsequent RF waveforms are shifted relative to the rotating frame.

  • name – An optional name for this.

Raises:

ValueError – If rf_frequency`, ``instantaneous_phase, and post_phase have invalid (not one-dimensional) or inconsistent shapes.

property instantaneous_phase: dict[Envelope, Variable[float]]

The amount (in radians) by which the phase of each envelope is shifted.

property post_phase: Variable[float]

The amount (in radians) by which the phases of all subsequent RF waveforms are shifted.

property rf_frequency: Variable[float]

The RF frequency.

drag(coeff: float | Iterable[float] | Variable[float]) RFWaveform

Returns a new waveform with a Derivative Removal by Adiabatic Gate (DRAG) envelope that uses the envelope of this as the base.

For a base envelope \(E(t)\) and a DRAG coefficient \(b\), the corresponding DRAG envelope is given by

\[DRAG(E(t), b) = E(t) + ibE'(t),\]

where \(E'(t)\) is the derivative of \(E(t)\) with respect to time.

Parameters:

coeff – The coefficient \(b\) of the imaginary part.

intermediate_frequency(lo_frequency: float) float

The intermediate frequency in radians per second for a specified LO frequency.

Parameters:

lo_frequency – The LO frequency in Hz.

Raises:

ValueError – If the RF frequency has not been set.

phase_update(sample_rate: float, lo_frequency: float = 0.0) complex

The complex phasor by which subsequent RF waveforms should be multiplied due to phase accumulation during this Waveform and the specified post_phase().

Parameters:
  • sample_rate – The rate at which to sample the envelope in Hz.

  • lo_frequency – The LO frequency in Hz.

phase_per_fractional_sample(sample_rate: float, lo_frequency: float = 0.0, fraction: float = 1) complex

The complex phasor specifying the phase accumulated during a fraction of a sample period.

Parameters:
  • sample_rate – The rate at which to sample the envelope in Hz.

  • lo_frequency – The LO frequency in Hz.

  • fraction – The fraction of a sample period to compute the phase accumulation for.

class keysight.qcs.channels.SineEnvelope

Bases: Envelope

Represents a sine envelope \(E(t) = \sin(\pi t)\).

import keysight.qcs as qcs

# initialize a SineEnvelope
pulse = qcs.SineEnvelope()
On this page