zhinst_backend ============== .. py:module:: quantify_scheduler.backends.zhinst_backend .. autoapi-nested-parse:: Backend for Zurich Instruments. Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: quantify_scheduler.backends.zhinst_backend.ZIAcquisitionConfig quantify_scheduler.backends.zhinst_backend.ZIDeviceConfig quantify_scheduler.backends.zhinst_backend.ZIHardwareCompilationConfig Functions ~~~~~~~~~ .. autoapisummary:: quantify_scheduler.backends.zhinst_backend.ensure_no_operations_overlap quantify_scheduler.backends.zhinst_backend._extract_port_clock_channelmapping quantify_scheduler.backends.zhinst_backend._determine_clock_sample_start quantify_scheduler.backends.zhinst_backend._determine_clock_start quantify_scheduler.backends.zhinst_backend._determine_sample_start quantify_scheduler.backends.zhinst_backend._add_channel_information quantify_scheduler.backends.zhinst_backend._apply_latency_corrections quantify_scheduler.backends.zhinst_backend._determine_measurement_fixpoint_correction quantify_scheduler.backends.zhinst_backend._apply_measurement_fixpoint_correction quantify_scheduler.backends.zhinst_backend._add_clock_sample_starts quantify_scheduler.backends.zhinst_backend._add_waveform_ids quantify_scheduler.backends.zhinst_backend._parse_local_oscillators quantify_scheduler.backends.zhinst_backend._parse_devices quantify_scheduler.backends.zhinst_backend._validate_schedule quantify_scheduler.backends.zhinst_backend.apply_waveform_corrections quantify_scheduler.backends.zhinst_backend._get_instruction_list quantify_scheduler.backends.zhinst_backend._generate_legacy_hardware_config quantify_scheduler.backends.zhinst_backend._generate_new_style_hardware_compilation_config quantify_scheduler.backends.zhinst_backend.flatten_schedule quantify_scheduler.backends.zhinst_backend._get_operations_by_repr quantify_scheduler.backends.zhinst_backend.compile_backend quantify_scheduler.backends.zhinst_backend._add_lo_config quantify_scheduler.backends.zhinst_backend._add_wave_nodes quantify_scheduler.backends.zhinst_backend._compile_for_hdawg quantify_scheduler.backends.zhinst_backend._assemble_hdawg_sequence quantify_scheduler.backends.zhinst_backend._compile_for_uhfqa quantify_scheduler.backends.zhinst_backend._assemble_uhfqa_sequence quantify_scheduler.backends.zhinst_backend.construct_waveform_table Attributes ~~~~~~~~~~ .. autoapisummary:: quantify_scheduler.backends.zhinst_backend.logger quantify_scheduler.backends.zhinst_backend.handler quantify_scheduler.backends.zhinst_backend.formatter quantify_scheduler.backends.zhinst_backend.SUPPORTED_DEVICE_TYPES quantify_scheduler.backends.zhinst_backend.SUPPORTED_ACQ_PROTOCOLS quantify_scheduler.backends.zhinst_backend.WAVEFORM_GRANULARITY quantify_scheduler.backends.zhinst_backend.HDAWG_DEVICE_TYPE_CHANNEL_GROUPS quantify_scheduler.backends.zhinst_backend.DEVICE_SAMPLING_RATES quantify_scheduler.backends.zhinst_backend.CLOCK_SAMPLE_FACTOR quantify_scheduler.backends.zhinst_backend.NUM_UHFQA_READOUT_CHANNELS quantify_scheduler.backends.zhinst_backend.MAX_QAS_INTEGRATION_LENGTH .. py:data:: logger .. py:data:: handler .. py:data:: formatter .. py:data:: SUPPORTED_DEVICE_TYPES :type: list[str] :value: ['HDAWG', 'UHFQA'] .. py:data:: SUPPORTED_ACQ_PROTOCOLS .. py:data:: WAVEFORM_GRANULARITY :type: dict[quantify_scheduler.backends.types.zhinst.DeviceType, int] .. py:data:: HDAWG_DEVICE_TYPE_CHANNEL_GROUPS :type: dict[str, dict[int, int]] .. py:data:: DEVICE_SAMPLING_RATES :type: dict[quantify_scheduler.backends.types.zhinst.DeviceType, dict[int, int]] .. py:data:: CLOCK_SAMPLE_FACTOR :value: 8 .. py:data:: NUM_UHFQA_READOUT_CHANNELS :value: 10 .. py:data:: MAX_QAS_INTEGRATION_LENGTH :value: 4096 .. py:function:: ensure_no_operations_overlap(timing_table: pandas.DataFrame) -> None Iterates over all hardware_channels in a schedule to determine if any of the pulses have overlap. :param timing_table: a timing table containing the absolute time and duration as well as the hardware channels on which these pulses are to be applied. :raises ValueError: If there is overlap between operations. .. py:function:: _extract_port_clock_channelmapping(hardware_cfg: dict[str, Any]) -> dict[str, str] Take the hardware configuration file and return a dictionary that maps port-clock pairs to instrument output channels. e.g.: {'q0:mw-q0.01': 'ic_hdawg0.channel_0', 'q0:res-q0.ro': 'ic_uhfqa0.channel_0'} .. py:function:: _determine_clock_sample_start(hardware_channel: str, abs_time: float, operation_name: str = '') -> tuple[int, float] depending on the output channel, select the right clock cycle time and sample rate from the channel descriptor for ZI channels. the sample is returned as a float to preserve information of incorrect rounding to full samples if present. .. py:function:: _determine_clock_start(hardware_channel: str, abs_time: float, operation_name: str) -> float .. py:function:: _determine_sample_start(hardware_channel: str, abs_time: float, operation_name: str) -> float .. py:function:: _add_channel_information(timing_table: pandas.DataFrame, port_clock_channelmapping: dict) -> pandas.DataFrame | None .. py:function:: _apply_latency_corrections(timing_table: pandas.DataFrame, latency_dict: dict) -> pandas.DataFrame Changes the "abs_time" of a timing table depending on the specified latency corrections for each port-clock combination as specified in the latency dict. The corrections are added to the abs_time elements fulfilling the specific port-clock combination. .. py:function:: _determine_measurement_fixpoint_correction(measurement_start_sample: int, common_frequency: float = 600000000.0) -> tuple[float, int] Calculates by how much time to shift all operations to ensure a measurement starts at sample 0. :param measurement_start_sample: the sample at which the measurement starts :param common_frequency: The shift needs to be such that it occurs at a multiple of the common frequency. A larger common frequency results in a smaller time correction. This largest common frequency is the common frequency of the HDAWG and UHFQA and is 600 MHz. :returns: The time correction to be applied in seconds. The correction in the number of samples. :rtype: Tuple[float, int] .. py:function:: _apply_measurement_fixpoint_correction(timing_table: pandas.DataFrame, common_frequency: float = 600000000.0) -> pandas.DataFrame Updates the abs_time of all operations based on the measurement fixpoint correction. The abs_time is applied to all operations between two acquisitions. After that the samples and clocks are re-calculated to reflect this change in time. :param timing_table: A timing table that has the samples already determined. :param common_frequency: The shift needs to be such that it occurs at a multiple of the common frequency. A larger common frequency results in a smaller time correction. This largest common frequency is the common frequency of the HDAWG and UHFQA and is 600 MHz. .. py:function:: _add_clock_sample_starts(timing_table: pandas.DataFrame) -> pandas.DataFrame Adds the sequence clock cycle start and sampling start of each operation for each channel. .. py:function:: _add_waveform_ids(timing_table: pandas.DataFrame) -> pandas.DataFrame Multiple (numerical) waveforms might be needed to represent a single operation. This waveform_id consists of a concatenation of the waveform_op_id with the sample_start and modulation phase added to it. .. py:function:: _parse_local_oscillators(data: dict[str, Any]) -> dict[str, quantify_scheduler.backends.types.zhinst.LocalOscillator] Returns the LocalOscillator domain models parsed from the data dictionary. :param data: The hardware map "local_oscillators" entry. :returns: A dictionary of unique LocalOscillator instances. :raises RuntimeError: If duplicate LocalOscillators have been found. .. py:function:: _parse_devices(data: dict[str, Any]) -> list[quantify_scheduler.backends.types.zhinst.Device] .. py:function:: _validate_schedule(schedule: quantify_scheduler.schedules.schedule.Schedule) -> None Validates the CompiledSchedule required values for creating the backend. :param schedule: :raises ValueError: The validation error. .. py:function:: apply_waveform_corrections(output: quantify_scheduler.backends.types.zhinst.Output, waveform: numpy.ndarray, start_and_duration_in_seconds: tuple[float, float], instrument_info: quantify_scheduler.backends.types.zhinst.InstrumentInfo, is_pulse: bool) -> tuple[int, int, numpy.ndarray] Add waveform corrections such as modulation, changing the waveform starting time by shifting it and resizing it based on the Instruments granularity. :param output: :param waveform: :param start_and_duration_in_seconds: :param instrument_info: :param is_pulse: True if it is a pulse to be up converted, False if it is an integration weight. .. py:function:: _get_instruction_list(output_timing_table: pandas.DataFrame) -> list[quantify_scheduler.backends.types.zhinst.Instruction] Iterates over a timing table for a specific output for which clock_cycle_start and waveform_id have been determined to return a list of all instructions to be played on a Zurich Instruments device. .. py:class:: ZIAcquisitionConfig Zurich Instruments acquisition configuration. :param bin_mode: .. py:attribute:: n_acquisitions :type: int The number of distinct acquisitions in this experiment. .. py:attribute:: resolvers :type: dict[int, Callable] Resolvers used to retrieve the results from the right UHFQA nodes. See also :mod:`~quantify_scheduler.backends.zhinst.resolvers` .. py:attribute:: bin_mode :type: quantify_scheduler.enums.BinMode The bin mode of the acquisitions. .. py:attribute:: acq_protocols :type: dict[int, SUPPORTED_ACQ_PROTOCOLS] Acquisition protocols for each acquisition channel. .. py:class:: ZIDeviceConfig Zurich Instruments device configuration. .. py:attribute:: name :type: str The name of the schedule the config is for. .. py:attribute:: settings_builder :type: quantify_scheduler.backends.zhinst.settings.ZISettingsBuilder The builder to configure the ZI settings. The builder typically includes DAQ and AWG settings. .. py:attribute:: acq_config :type: ZIAcquisitionConfig | None Acquisition config for the schedule. The acquisition config contains the number of acquisitions and a dictionary of resolvers used to retrieve the results from the right UHFQA nodes. Note that this part of the config is not needed during prepare, but only during the retrieve acquisitions step. .. py:function:: _generate_legacy_hardware_config(schedule: quantify_scheduler.schedules.schedule.Schedule, compilation_config: quantify_scheduler.backends.graph_compilation.CompilationConfig) -> dict Extract the old-style Zhinst hardware config from the CompilationConfig. Only the port-clok combinations that are used in the schedule are included in the old-style hardware config. :param schedule: Schedule from which the port-clock combinations are extracted. :type schedule: Schedule :param config: CompilationConfig from which hardware config is extracted. :type config: CompilationConfig :returns: **hardware_config** -- Zhinst hardware configuration. :rtype: dict :raises KeyError: If the CompilationConfig.connectivity does not contain a hardware config. :raises KeyError: If the 'frequency_param' is not specified for in a LO config. :raises ValueError: If a value is specified in both the hardware options and the hardware config. :raises RuntimeError: If no external local oscillator is found in the generated zhinst hardware configuration. .. py:function:: _generate_new_style_hardware_compilation_config(old_style_config: dict) -> dict Generate a new-style ZIHardwareCompilationConfig from an old-style hardware config. :param old_style_config: Old-style hardware config. :returns: New-style hardware compilation config dictionary. :rtype: dict .. py:function:: flatten_schedule(schedule: quantify_scheduler.schedules.schedule.Schedule, config: quantify_scheduler.backends.graph_compilation.CompilationConfig | None = None) -> quantify_scheduler.schedules.schedule.Schedule Recursively flatten subschedules based on the absolute timing. :param schedule: schedule to be flattened :type schedule: Schedule :param config: Compilation config for :class:`~quantify_scheduler.backends.graph_compilation.QuantifyCompiler`, which is currently not only used to detect if the function is called directly. by default None :type config: CompilationConfig | None, optional :returns: Equivalent schedule without subschedules :rtype: Schedule .. py:function:: _get_operations_by_repr(schedule: quantify_scheduler.schedules.schedule.Schedule) -> dict[str, quantify_scheduler.operations.operation.Operation] .. py:function:: compile_backend(schedule: quantify_scheduler.schedules.schedule.Schedule, config: quantify_scheduler.backends.graph_compilation.CompilationConfig | dict[str, Any] | None = None, *, hardware_cfg: dict[str, Any] | None = None) -> quantify_scheduler.schedules.schedule.CompiledSchedule Compiles zhinst hardware instructions for a schedule. This method generates sequencer programs, waveforms and configurations required for the instruments defined in the hardware configuration. :param schedule: The schedule to be compiled. :param config: Compilation config for :class:`~quantify_scheduler.backends.graph_compilation.QuantifyCompiler`. :param hardware_cfg: (deprecated) The hardware configuration of the setup. Pass a full compilation config instead using ``config`` argument. :returns: A collection containing the compiled backend configuration for each device. :raises NotImplementedError: Thrown when using unsupported ZI Instruments. :raises ValueError: When both ``config`` and ``hardware_cfg`` are supplied. .. py:class:: ZIHardwareCompilationConfig(/, **data: Any) Bases: :py:obj:`quantify_scheduler.backends.types.common.HardwareCompilationConfig` Datastructure containing the information needed to compile to the Zurich Instruments backend. This information is structured in the same way as in the generic :class:`~quantify_scheduler.backends.types.common.HardwareCompilationConfig`, but contains fields for hardware-specific settings. .. py:attribute:: config_type :type: Type[ZIHardwareCompilationConfig] A reference to the ``HardwareCompilationConfig`` DataStructure for the Zurich Instruments backend. .. py:attribute:: hardware_description :type: Dict[str, Union[quantify_scheduler.backends.types.zhinst.ZIHardwareDescription, quantify_scheduler.backends.types.common.HardwareDescription]] Description of the instruments in the physical setup. .. py:attribute:: hardware_options :type: quantify_scheduler.backends.types.zhinst.ZIHardwareOptions Options that are used in compiling the instructions for the hardware, such as :class:`~quantify_scheduler.backends.types.common.LatencyCorrection` or :class:`~quantify_scheduler.backends.types.zhinst.OutputGain`. .. py:attribute:: compilation_passes :type: List[quantify_scheduler.backends.graph_compilation.SimpleNodeConfig] The list of compilation nodes that should be called in succession to compile a schedule to instructions for the Zurich Instruments hardware. .. py:method:: from_old_style_hardware_config(data: Any) -> Any :classmethod: Convert old style hardware config dict to new style before validation. .. py:function:: _add_lo_config(channel: quantify_scheduler.backends.types.zhinst.Output, local_oscillators: dict[str, quantify_scheduler.backends.types.zhinst.LocalOscillator], resources: dict[str, quantify_scheduler.resources.Resource], device_configs: dict[str, ZIDeviceConfig | float]) -> None Adds configuration for a local oscillator required for a specific output channel to the device configs. .. py:function:: _add_wave_nodes(device_type: quantify_scheduler.backends.types.zhinst.DeviceType, awg_index: int, wf_id_mapping: dict[str, int], numerical_wf_dict: dict[str, numpy.ndarray], settings_builder: quantify_scheduler.backends.zhinst.settings.ZISettingsBuilder) -> quantify_scheduler.backends.zhinst.settings.ZISettingsBuilder .. py:function:: _compile_for_hdawg(device: quantify_scheduler.backends.types.zhinst.Device, timing_table: pandas.DataFrame, numerical_wf_dict: dict[str, numpy.ndarray], repetitions: int) -> quantify_scheduler.backends.zhinst.settings.ZISettingsBuilder :param device: :param timing_table: :param numerical_wf_dict: :param repetitions: :raises ValueError: .. py:function:: _assemble_hdawg_sequence(instructions: list[quantify_scheduler.backends.types.zhinst.Instruction], wf_id_mapping: dict[str, int], numerical_wf_dict: dict[str, numpy.ndarray], repetitions: int, schedule_duration: float, markers: str | int | None = None, trigger: int = None) -> tuple[str, str] .. py:function:: _compile_for_uhfqa(device: quantify_scheduler.backends.types.zhinst.Device, timing_table: pandas.DataFrame, numerical_wf_dict: dict[str, numpy.ndarray], repetitions: int, operations: dict[str, quantify_scheduler.operations.operation.Operation], bin_mode: quantify_scheduler.enums.BinMode) -> tuple[quantify_scheduler.backends.zhinst.settings.ZISettingsBuilder, ZIAcquisitionConfig] Initialize programming the UHFQA ZI Instrument. Creates a sequence program and converts schedule pulses to waveforms for the UHFQA. :param device: :param timing_table: :param numerical_wf_dict: :param repetitions: :param operations: .. py:function:: _assemble_uhfqa_sequence(instructions: list[quantify_scheduler.backends.types.zhinst.Instruction], wf_id_mapping: dict[str, int], repetitions: int, device_name: str, trigger: int = 2) -> str .. py:function:: construct_waveform_table(timing_table: pandas.DataFrame, operations_dict: dict[str, quantify_scheduler.operations.operation.Operation], device_dict: dict[str, quantify_scheduler.backends.types.zhinst.Device]) -> dict[str, numpy.ndarray] Iterates over all unique waveforms in a timing_table dataframe to calculate the numerical waveforms. :param timing_table: A timing table for which the waveform_id has been determined :param operations_dict: The Operations contained in a Schedule. :param device_dict: A dictionary containing the :class:`~.backends.types.zhinst.Device` objects describing the devicesin the hardware configuration. :returns: numerical_waveform dict, a dictionary containing the complex valued waveforms that will be uploaded to the control hardware.