Source code for zhinst.utils.shfsg
"""Zurich Instruments LabOne Python API Utility functions for SHFSG."""
import time
import typing as t
from zhinst.utils import convert_awg_waveform, wait_for_state_change
from zhinst.ziPython import AwgModule, ziDAQServer, compile_seqc
SHFSG_MAX_SIGNAL_GENERATOR_WAVEFORM_LENGTH = 98304
SHFSG_SAMPLING_FREQUENCY = 2e9
[docs]def load_sequencer_program(
daq: ziDAQServer,
device_id: str,
channel_index: int,
sequencer_program: str,
*,
awg_module: AwgModule = None,
timeout: float = 10,
) -> None:
"""Compiles and loads a program to a specified AWG core.
Args:
daq: Instance of a Zurich Instruments API session connected to a Data
Server. The device with identifier device_id is assumed to already
be connected to this instance.
device_id: SHFSG device identifier, e.g. `dev12004` or 'shf-dev12004'.
channel_index: Index specifying which sequencer to upload - there
is one sequencer per channel.
sequencer_program: Sequencer program to be uploaded.
awg_module: The standalone AWG compiler is used instead. .. deprecated:: 22.08
timeout: maximum time to wait for the compilation in seconds.
(default = 10)
"""
# start by resetting the sequencer
daq.syncSetInt(
f"/{device_id}/sgchannels/{channel_index}/awg/reset",
1,
)
wait_for_state_change(
daq,
f"/{device_id}/sgchannels/{channel_index}/awg/ready",
0,
timeout=timeout,
)
device_type = daq.getString(f"/{device_id}/features/devtype")
device_options = daq.getString(f"/{device_id}/features/options")
elf, _ = compile_seqc(
sequencer_program, device_type, device_options, channel_index, sequencer="sg"
)
daq.setVector(f"/{device_id}/sgchannels/{channel_index}/awg/elf/data", elf)
# wait until the device becomes ready after program upload
wait_for_state_change(
daq,
f"/{device_id}/sgchannels/{channel_index}/awg/ready",
1,
timeout=timeout,
)
[docs]def enable_sequencer(
daq: ziDAQServer,
device_id: str,
channel_index: int,
*,
single: t.Union[bool, int] = True,
) -> None:
"""Starts the sequencer of a specific channel.
Args:
daq: Instance of a Zurich Instruments API session connected to a Data
Server. The device with identifier device_id is assumed to already
be connected to this instance.
device_id: SHFSG device identifier, e.g. `dev12004` or 'shf-dev12004'.
channel_index: Index specifying which sequencer to enable - there
is one sequencer per channel.
single: Flag if the sequencer should run in single mode.
"""
sequencer_path = f"/{device_id}/sgchannels/{channel_index}/awg/"
daq.setInt(
sequencer_path + "single",
int(single),
)
daq.syncSetInt(sequencer_path + "enable", 1)
hundred_milliseconds = 0.1
time.sleep(hundred_milliseconds)
[docs]def upload_commandtable(
daq: ziDAQServer,
device_id: str,
channel_index: int,
command_table: str,
) -> None:
"""Uploads a command table in the form of a string to the appropriate channel.
Args:
daq: Instance of a Zurich Instruments API session connected to a Data
Server. The device with identifier device_id is assumed to already
be connected to this instance.
device_id: SHFSG device identifier, e.g. `dev12004` or 'shf-dev12004'.
channel_index: Index specifying which channel to upload the command
table to.
command_table: The command table to be uploaded.
"""
# upload command table
daq.setVector(
f"/{device_id}/sgchannels/{channel_index}/awg/commandtable/data",
command_table,
)
[docs]def write_to_waveform_memory(
daq: ziDAQServer,
device_id: str,
channel_index: int,
waveforms: dict,
) -> None:
"""Writes waveforms to the waveform memory of a specified sequencer.
Args:
daq: Instance of a Zurich Instruments API session connected to a Data
Server. The device with identifier device_id is assumed to already
be connected to this instance.
device_id: SHFSG device identifier, e.g. `dev12004` or 'shf-dev12004'.
channel_index: Index specifying which sequencer the waveforms below are
written to - there is one generator per channel.
waveforms (dict): Dictionary of waveforms, the key specifies the
waveform index to which to write the waveforms.
"""
waveforms_path = f"/{device_id}/sgchannels/{channel_index}/awg/waveform/waves/"
settings = []
for slot, waveform in waveforms.items():
wave_raw = convert_awg_waveform(waveform)
settings.append((waveforms_path + f"{slot}", wave_raw))
daq.set(settings)
[docs]def configure_marker_and_trigger(
daq: ziDAQServer,
device_id: str,
channel_index: int,
*,
trigger_in_source: str,
trigger_in_slope: str,
marker_out_source: str,
) -> None:
"""Configures the trigger inputs and marker outputs of a specified AWG core.
Args:
daq: Instance of a Zurich Instruments API session connected to a Data
Server. The device with identifier device_id is assumed to already
be connected to this instance.
device_id: SHFSG device identifier, e.g. `dev12004` or 'shf-dev12004'
channel_index: Index of the used SG channel.
trigger_in_source: Alias for the trigger input used by the
sequencer. For a list of available values use:
daq.help(f"/{dev_id}/sgchannels/{channel_index}/awg/auxtriggers/0/channel")
trigger_in_slope: Alias for the slope of the input trigger used
by sequencer. For a list of available values use
daq.help(f"/{dev_id}/sgchannels/{channel_index}/awg/auxtriggers/0/slope")
marker_out_source: Alias for the marker output source used by the
sequencer. For a list of available values use
daq.help(f"/{dev_id}/sgchannels/{channel_index}/marker/source")
"""
# Trigger input
settings = []
settings.append(
(
f"/{device_id}/sgchannels/{channel_index}/awg/auxtriggers/0/channel",
trigger_in_source,
)
)
settings.append(
(
f"/{device_id}/sgchannels/{channel_index}/awg/auxtriggers/0/slope",
trigger_in_slope,
)
)
# Marker output
settings.append(
(
f"/{device_id}/sgchannels/{channel_index}/marker/source",
marker_out_source,
)
)
daq.set(settings)
[docs]def configure_channel(
daq: ziDAQServer,
device_id: str,
channel_index: int,
*,
enable: int,
output_range: int,
center_frequency: float,
rflf_path: int,
) -> None:
"""Configures the RF input and output of a specified channel.
Args:
daq: Instance of a Zurich Instruments API session connected to a Data
Server. The device with identifier device_id is assumed to already
be connected to this instance.
device_id: SHFSG device identifier, e.g. `dev12004` or 'shf-dev12004'.
channel_index: Index of the used SG channel.
enable: Whether or not to enable the channel.
output_range: Maximal range of the signal output power in dbM.
center_frequency: Center Frequency before modulation.
rflf_path: Switch between RF and LF paths.
"""
path = f"/{device_id}/sgchannels/{channel_index}/"
settings = []
settings.append((path + "output/range", output_range))
settings.append((path + "output/rflfpath", rflf_path))
if rflf_path == 1:
synth = daq.getInt(path + "synthesizer")
settings.append(
(f"/{device_id}/synthesizers/{synth}/centerfreq", center_frequency)
)
elif rflf_path == 0:
settings.append((path + "digitalmixer/centerfreq", center_frequency))
settings.append((path + "output/on", enable))
daq.set(settings)
[docs]def configure_pulse_modulation(
daq: ziDAQServer,
device_id: str,
channel_index: int,
*,
enable: int,
osc_index: int = 0,
osc_frequency: float = 100e6,
phase: float = 0.0,
global_amp: float = 0.5,
gains: tuple = (1.0, -1.0, 1.0, 1.0),
sine_generator_index: int = 0,
) -> None:
"""Configure the pulse modulation.
Configures the sine generator to digitally modulate the AWG output, for
generating single sideband AWG signals.
Args:
daq: Instance of a Zurich Instruments API session connected to a Data
Server. The device with identifier device_id is assumed to already
be connected to this instance.
device_id: SHFSG device identifier, e.g. `dev12004` or 'shf-dev12004'
channel_index: Index of the used SG channel.
enable: Enables modulation.
osc_index: Selects which oscillator to use.
osc_frequency: Oscillator frequency used to modulate the AWG
outputs. (default = 100e6)
phase: Sets the oscillator phase. (default = 0.0)
global_amp: Global scale factor for the AWG outputs. (default = 0.5)
gains: Sets the four amplitudes used for single sideband
generation. default values correspond to upper sideband with a
positive oscillator frequency. (default = (1.0, -1.0, 1.0, 1.0))
sine_generator_index: Selects which sine generator to use on a given
channel.
"""
path = f"/{device_id}/sgchannels/{channel_index}/"
settings = []
settings.append((path + f"sines/{sine_generator_index}/oscselect", osc_index))
settings.append((path + f"sines/{sine_generator_index}/phaseshift", phase))
settings.append((path + f"oscs/{osc_index}/freq", osc_frequency))
settings.append((path + "awg/modulation/enable", enable))
settings.append((path + "awg/outputamplitude", global_amp))
settings.append((path + "awg/outputs/0/gains/0", gains[0]))
settings.append((path + "awg/outputs/0/gains/1", gains[1]))
settings.append((path + "awg/outputs/1/gains/0", gains[2]))
settings.append((path + "awg/outputs/1/gains/1", gains[3]))
daq.set(settings)
[docs]def configure_sine_generation(
daq: ziDAQServer,
device_id: str,
channel_index: int,
*,
enable: int,
osc_index: int = 0,
osc_frequency: float = 100e6,
phase: float = 0.0,
gains: tuple = (0.0, 1.0, 1.0, 0.0),
sine_generator_index: int = 0,
) -> None:
"""Configures the sine generator output of a specified channel.
Configures the sine generator output of a specified channel for generating
continuous wave signals without the AWG.
Args:
daq: Instance of a Zurich Instruments API session connected to a Data
Server. The device with identifier device_id is assumed to already
be connected to this instance.
device_id: SHFSG device identifier, e.g. `dev12004` or 'shf-dev12004'.
channel_index: Index of the used SG channel.
enable: Enables the sine generator output.
osc_index: Selects which oscillator to use.
osc_frequency: Oscillator frequency used by the sine generator.
(default = 100e6)
phase: Sets the oscillator phase. (default = 0.0)
gains: Sets the four amplitudes used for single sideband.
generation. default values correspond to upper sideband with a
positive oscillator frequency. gains are set in this order:
I/sin, I/cos, Q/sin, Q/cos
(default = (0.0, 1.0, 1.0, 0.0))
sine_generator_index: Selects which sine generator to use on a given
channel.
"""
path = f"/{device_id}/sgchannels/{channel_index}/sines/{sine_generator_index}/"
settings = []
settings.append((path + "i/enable", enable))
settings.append((path + "q/enable", enable))
settings.append((path + "i/sin/amplitude", gains[0]))
settings.append((path + "i/cos/amplitude", gains[1]))
settings.append((path + "q/sin/amplitude", gains[2]))
settings.append((path + "q/cos/amplitude", gains[3]))
settings.append((path + "oscselect", osc_index))
settings.append(
(
f"/{device_id}/sgchannels/{channel_index}/oscs/{osc_index}/freq",
osc_frequency,
)
)
settings.append((path + "phaseshift", phase))
daq.set(settings)