quantify_scheduler.backends.qblox.helpers

Helper functions for Qblox backend.

Module Contents

Classes

Frequencies

Functions

find_inner_dicts_containing_key(→ List[dict])

Generates a list of the first dictionaries encountered that contain a certain key,

find_all_port_clock_combinations(→ List[Tuple[str, str]])

Generates a list with all port and clock combinations found in a dictionary with

generate_waveform_data(→ numpy.ndarray)

Generates an array using the parameters specified in data_dict.

generate_waveform_names_from_uuid(→ Tuple[str, str])

Generates names for the I and Q parts of the complex waveform based on a unique

generate_uuid_from_wf_data(→ str)

Creates a unique identifier from the waveform data, using a hash. Identical arrays

add_to_wf_dict_if_unique(→ Tuple[Dict[str, Any], str, int])

Adds a waveform to the waveform dictionary if it is not yet in there and returns the

output_name_to_outputs(→ Optional[Union[Tuple[int], ...)

Finds the output path index associated with the output names specified in the

input_name_to_inputs(→ Union[Tuple[int], Tuple[int, int]])

Finds the input path index associated with the input names specified in the

io_mode_from_ios(→ Literal[complex, real, imag])

Takes the specified outputs to use and extracts a "sequencer mode" from it.

generate_waveform_dict(→ Dict[str, dict])

Takes a dictionary with complex waveforms and generates a new dictionary with

to_grid_time(→ int)

Takes a float value representing a time in seconds as used by the schedule, and

is_multiple_of_grid_time(→ bool)

Takes a time in seconds and converts it to the ns grid time that the Qblox hardware

get_nco_phase_arguments(→ int)

Converts a phase in degrees to the int arguments the NCO phase instructions expect.

get_nco_set_frequency_arguments(→ int)

Converts a frequency in Hz to the int argument the NCO set_freq instruction expects.

determine_clock_lo_interm_freqs(→ Frequencies)

generate_port_clock_to_device_map(→ Dict[Tuple[str, ...)

Generates a mapping that specifies which port-clock combinations belong to which

assign_pulse_and_acq_info_to_devices(schedule, ...)

Traverses the schedule and generates OpInfo objects for every pulse and

convert_hw_config_to_portclock_configs_spec(...)

Converts possibly old hardware configs to the new format introduced by

calc_from_units_volt(→ Optional[float])

Helper method to calculate the offset from mV or V.

extract_acquisition_metadata_from_acquisitions(...)

Variant of

single_scope_mode_acquisition_raise(sequencer_0, ...)

Raises an error stating that only one scope mode acquisition can be used per module.

find_inner_dicts_containing_key(d: dict, key: Any) List[dict][source]

Generates a list of the first dictionaries encountered that contain a certain key, in a complicated dictionary with nested dictionaries or Iterables.

This is achieved by recursively traversing the nested structures until the key is found, which is then appended to a list.

Parameters:
  • d – The dictionary to traverse.

  • key – The key to search for.

Returns:

A list containing all the inner dictionaries containing the specified key.

find_all_port_clock_combinations(d: dict) List[Tuple[str, str]][source]

Generates a list with all port and clock combinations found in a dictionary with nested structures. Traversing the dictionary is done using the find_inner_dicts_containing_key function.

Parameters:

d – The dictionary to traverse.

Returns:

A list containing tuples representing the port and clock combinations found in the dictionary.

generate_waveform_data(data_dict: dict, sampling_rate: float) numpy.ndarray[source]

Generates an array using the parameters specified in data_dict.

Parameters:
  • data_dict – The dictionary that contains the values needed to parameterize the waveform. data_dict[‘wf_func’] is then called to calculate the values.

  • sampling_rate – The sampling rate used to generate the time axis values.

Returns:

The (possibly complex) values of the generated waveform. The number of values is determined by rounding to the nearest integer.

generate_waveform_names_from_uuid(uuid: Any) Tuple[str, str][source]

Generates names for the I and Q parts of the complex waveform based on a unique identifier for the pulse/acquisition.

Parameters:

uuid – A unique identifier for a pulse/acquisition.

Returns:

  • uuid_I – Name for the I waveform.

  • uuid_Q – Name for the Q waveform.

generate_uuid_from_wf_data(wf_data: numpy.ndarray, decimals: int = 12) str[source]

Creates a unique identifier from the waveform data, using a hash. Identical arrays yield identical strings within the same process.

Parameters:
  • wf_data – The data to generate the unique id for.

  • decimals – The number of decimal places to consider.

Returns:

A unique identifier.

add_to_wf_dict_if_unique(wf_dict: Dict[str, Any], waveform: numpy.ndarray) Tuple[Dict[str, Any], str, int][source]

Adds a waveform to the waveform dictionary if it is not yet in there and returns the uuid and index. If it is already present it simply returns the uuid and index.

Parameters:
  • wf_dict – The waveform dict in the format expected by the sequencer.

  • waveform – The waveform to add.

Returns:

  • Dict[str, Any] – The (updated) wf_dict.

  • str – The uuid of the waveform.

  • int – The index.

output_name_to_outputs(name: str) Optional[Union[Tuple[int], Tuple[int, int]]][source]

Finds the output path index associated with the output names specified in the config.

For the baseband modules, these indices correspond directly to a physical output ( e.g. index 0 corresponds to output 1 etc.).

For the RF modules, index 0 and 2 correspond to path0 of output 1 and output 2 respectively, and 1 and 3 to path1 of those outputs.

Parameters:

name – name of the output channel. e.g. ‘complex_output_0’.

Returns:

A tuple containing the indices of the physical (real) outputs.

input_name_to_inputs(name: str) Union[Tuple[int], Tuple[int, int]][source]

Finds the input path index associated with the input names specified in the config.

For the baseband modules, these indices correspond directly to a physical input ( e.g. index 0 corresponds to input 1 etc.).

For the RF modules, index 0 corresponds to path0 of input 1 and path 1 of input 1.

Parameters:

name – name of the input channel. e.g. ‘real_input_0’.

Returns:

A tuple containing the indices of the physical (real) inputs.

io_mode_from_ios(io: Union[Tuple[int], Tuple[int, int]]) Literal[complex, real, imag][source]

Takes the specified outputs to use and extracts a “sequencer mode” from it.

Modes:

  • "real": only path0 is used

  • "imag": only path1 is used

  • "complex": both path0 and path1 paths are used.

Parameters:

io – The io the sequencer is supposed to use. Note that the outputs start from 0, but the labels on the front panel start counting from 1. So the mapping differs n-1.

Returns:

The mode

Raises:

RuntimeError – The amount of ios is more than 2, which is impossible for one sequencer.

generate_waveform_dict(waveforms_complex: Dict[str, numpy.ndarray]) Dict[str, dict][source]

Takes a dictionary with complex waveforms and generates a new dictionary with real valued waveforms with a unique index, as required by the hardware.

Parameters:

waveforms_complex – Dictionary containing the complex waveforms. Keys correspond to a unique identifier, value is the complex waveform.

Returns:

A dictionary with as key the unique name for that waveform, as value another dictionary containing the real-valued data (list) as well as a unique index. Note that the index of the Q waveform is always the index of the I waveform +1.

Return type:

dict[str, dict]

Examples

import numpy as np
from quantify_scheduler.backends.qblox.helpers import generate_waveform_dict

complex_waveforms = {12345: np.array([1, 2])}
generate_waveform_dict(complex_waveforms)

# {'12345_I': {'data': [1, 2], 'index': 0},
# '12345_Q': {'data': [0, 0], 'index': 1}}
{'12345_I': {'data': [1, 2], 'index': 0},
 '12345_Q': {'data': [0, 0], 'index': 1}}
to_grid_time(time: float, grid_time_ns: int = constants.GRID_TIME) int[source]

Takes a float value representing a time in seconds as used by the schedule, and returns the integer valued time in nanoseconds that the sequencer uses.

Parameters:
  • time – The time to convert.

  • grid_time_ns – The grid time to use in ns.

Returns:

The integer valued nanosecond time.

is_multiple_of_grid_time(time: float, grid_time_ns: int = constants.GRID_TIME) bool[source]

Takes a time in seconds and converts it to the ns grid time that the Qblox hardware expects.

Parameters:
  • time – A time in seconds.

  • grid_time_ns – A grid time in ns.

Returns:

If it the time is a multiple of the grid time.

get_nco_phase_arguments(phase_deg: float) int[source]

Converts a phase in degrees to the int arguments the NCO phase instructions expect. We take phase_deg modulo 360 to account for negative phase and phase larger than 360.

Parameters:

phase_deg – The phase in degrees

Returns:

The int corresponding to the phase argument.

get_nco_set_frequency_arguments(frequency_hz: float) int[source]

Converts a frequency in Hz to the int argument the NCO set_freq instruction expects.

Parameters:

frequency_hz – The frequency in Hz.

Returns:

The frequency expressed in steps for the NCO set_freq instruction.

Raises:

ValueError – If the frequency_hz is out of range.

class Frequencies[source]
clock: Optional[float][source]
LO: Optional[float][source]
IF: Optional[float][source]
determine_clock_lo_interm_freqs(clock_freq: float, lo_freq: Union[float, None], interm_freq: Union[float, None], downconverter_freq: Optional[float] = None, mix_lo: bool = True) Frequencies[source]

Warning

Using downconverter_freq requires custom Qblox hardware, do not use otherwise.

From known frequency for the local oscillator or known intermodulation frequency, determine any missing frequency, after optionally applying downconverter_freq to the clock frequency.

If mix_lo is True, the following relation is obeyed: \(f_{RF} = f_{LO} + f_{IF}\).

If mix_lo is False, \(f_{RF} = f_{LO}\) is upheld.

Parameters:
  • clock_freq (float) – Frequency of the clock.

  • lo_freq (Union[float, None]) – Frequency of the local oscillator (LO).

  • interm_freq (Union[float, None]) – Intermodulation frequency (IF), the frequency of the numerically controlled oscillator (NCO).

  • downconverter_freq (Optional[float]) – Frequency for downconverting the clock frequency, using: \(f_\mathrm{out} = f_\mathrm{downconverter} - f_\mathrm{in}\).

  • mix_lo (bool) – Flag indicating whether IQ mixing is enabled with the LO.

Returns:

Frequencies object containing the determined LO and IF frequencies and the optionally downconverted clock frequency.

Warns:

ValueWarning – In case downconverter_freq is set equal to 0, warns to unset via null/None instead.

Raises:
  • ValueError – In case downconverter_freq is less than 0.

  • ValueError – In case downconverter_freq is less than clock_freq.

generate_port_clock_to_device_map(hardware_cfg: Dict[str, Any]) Dict[Tuple[str, str], str][source]

Generates a mapping that specifies which port-clock combinations belong to which device.

Note

The same device may contain multiple port-clock combinations, but each port-clock combination may only occur once.

Parameters:

hardware_cfg – The hardware config dictionary.

Returns:

A dictionary with as key a tuple representing a port-clock combination, and as value the name of the device. Note that multiple port-clocks may point to the same device.

assign_pulse_and_acq_info_to_devices(schedule: quantify_scheduler.Schedule, device_compilers: Dict[str, Any], hardware_cfg: Dict[str, Any])[source]

Traverses the schedule and generates OpInfo objects for every pulse and acquisition, and assigns it to the correct InstrumentCompiler.

Parameters:
  • schedule – The schedule to extract the pulse and acquisition info from.

  • device_compilers – Dictionary containing InstrumentCompilers as values and their names as keys.

  • hardware_cfg – The hardware config dictionary.

Raises:
  • RuntimeError – This exception is raised then the function encountered an operation that has no pulse or acquisition info assigned to it.

  • KeyError – This exception is raised when attempting to assign a pulse with a port-clock combination that is not defined in the hardware configuration.

  • KeyError – This exception is raised when attempting to assign an acquisition with a port-clock combination that is not defined in the hardware configuration.

convert_hw_config_to_portclock_configs_spec(hw_config: Dict[str, Any]) Dict[str, Any][source]

Converts possibly old hardware configs to the new format introduced by the new dynamic sequencer allocation feature.

Manual assignment between sequencers and port-clock combinations under each output is removed, and instead only a list of port-clock configurations is specified, under the new "portclock_configs" key.

Furthermore, we scan for "latency_correction" defined at sequencer or portclock_configs level and store under "port:clock" under toplevel "latency_corrections" key.

Parameters:

hw_config – The hardware config to be upgraded to the new specification.

Returns:

A hardware config compatible with the specification required by the new dynamic sequencer allocation feature.

calc_from_units_volt(voltage_range, name: str, param_name: str, cfg: Dict[str, Any]) Optional[float][source]

Helper method to calculate the offset from mV or V. Then compares to given voltage range, and throws a ValueError if out of bounds.

Parameters:
  • voltage_range – The range of the voltage levels of the device used.

  • name – The name of the device used.

  • param_name – The name of the current parameter the method is used for.

  • cfg – The hardware config of the device used.

Returns:

The normalized offsets.

Raises:

RuntimeError – When a unit range is given that is not supported, or a value is given that falls outside the allowed range.

extract_acquisition_metadata_from_acquisitions(acquisitions: List[quantify_scheduler.backends.types.qblox.OpInfo], repetitions: int) quantify_scheduler.schedules.schedule.AcquisitionMetadata[source]

Variant of extract_acquisition_metadata_from_acquisition_protocols() for use with the Qblox backend.

single_scope_mode_acquisition_raise(sequencer_0, sequencer_1, module_name)[source]

Raises an error stating that only one scope mode acquisition can be used per module.

Parameters:
  • sequencer_0 – First sequencer which attempts to use the scope mode acquisition.

  • sequencer_1 – Second sequencer which attempts to use the scope mode acquisition.

  • module_name – Name of the module.

Raises:

ValueError – Always raises the error message.