# Repository: https://gitlab.com/quantify-os/quantify-scheduler
# Licensed according to the LICENCE file on the main branch
"""Python dataclasses for quantify-scheduler json-schemas."""
from dataclasses import dataclass, field
from enum import Enum, unique
from typing import List, Optional, Union
from dataclasses_json import DataClassJsonMixin
from quantify_scheduler import enums
from quantify_scheduler.backends.types import common
@unique
[docs]class DeviceType(str, Enum):
"""Enum of device types."""
@dataclass
[docs]class Output(DataClassJsonMixin):
"""
The definition class for zhinst channel properties.
This class maps to the zhinst backend JSON "channel"
properties defined in the hardware mapping.
Parameters
----------
port :
The port resource.
clock :
The Clock resource.
clock_frequency:
The frequency for the clock resource
(AKA RF/signal frequency).
mode :
The output mode type.
modulation :
The modulation settings.
local_oscillator :
The LocalOscillator name.
gain1 :
The output1 IQ modulation gain.
Accepted value between -1 and + 1. (default = 1.0)
gain2 :
The output2 IQ modulation gain.
Accepted value between -1 and + 1. (default = 1.0)
trigger :
The ZI Instrument input trigger. (default = None)
Setting this will declare the device secondary
markers :
The ZI Instrument output triggers. (default = [])
mixer_corrections :
The output mixer corrections.
"""
[docs] mode: enums.SignalModeType
[docs] modulation: common.Modulation
[docs] clock_frequency: Optional[float] = None
[docs] trigger: Optional[int] = None
[docs] markers: List[Union[str, int]] = field(default_factory=lambda: [])
[docs] mixer_corrections: Optional[common.MixerCorrections] = None
@dataclass
[docs]class Device(DataClassJsonMixin):
"""
The device definition class for zhinst devices.
This class maps to the zhinst backend JSON "devices"
properties defined in the hardware mapping.
Parameters
----------
name :
The QCodes Instrument name.
type :
The instrument model type.
For example: 'UHFQA', 'HDAWG4', 'HDAWG8'
ref :
The reference source type.
channels :
The list of channels. (auto generated)
channel_0 :
The first physical channel properties.
channel_1 :
The second physical channel properties.
channel_2 :
The third physical channel properties.
channel_3 :
The fourth physical channel properties.
channelgrouping :
The HDAWG channelgrouping property. (default = 0) corresponding to a single
sequencer controlling a pair (2) awg outputs.
clock_select :
The clock rate divisor which will be used to get
the instruments clock rate from the lookup dictionary in
quantify_scheduler.backends.zhinst_backend.DEVICE_CLOCK_RATES.
For information see zhinst User manuals, section /DEV..../AWGS/n/TIME
Examples: base sampling rate (1.8 GHz) divided by 2^clock_select. (default = 0)
mode :
The Instruments operation mode.
(default = enums.InstrumentOperationMode.OPERATING)
device_type :
The Zurich Instruments hardware type. (default = DeviceType.NONE)
This field is automatically populated.
sample_rate :
The Instruments sampling clock rate.
This field is automatically populated.
n_channels :
The number of physical channels of this ZI Instrument.
This field is automatically populated.
"""
[docs] ref: enums.ReferenceSourceType
[docs] channels: List[Output] = field(init=False)
[docs] channel_1: Optional[Output] = None
[docs] channel_2: Optional[Output] = None
[docs] channel_3: Optional[Output] = None
[docs] clock_select: Optional[int] = 0
[docs] channelgrouping: int = 0
[docs] mode: enums.InstrumentOperationMode = enums.InstrumentOperationMode.OPERATING
[docs] device_type: DeviceType = DeviceType.NONE
[docs] sample_rate: Optional[int] = field(init=False)
[docs] n_channels: int = field(init=False)
def __post_init__(self):
"""Initializes fields after initializing object."""
self.channels = [self.channel_0]
if self.channel_1 is not None:
self.channels.append(self.channel_1)
if self.channel_2 is not None:
self.channels.append(self.channel_2)
if self.channel_3 is not None:
self.channels.append(self.channel_3)
if self.type[-1].isdigit():
digit = int(self.type[-1])
self.n_channels = digit
device_type = self.type[: len(self.type) - 1]
self.device_type = DeviceType(device_type)
else:
self.device_type = DeviceType(self.type)
self.n_channels = 1
@dataclass
[docs]class CommandTableHeader(DataClassJsonMixin):
"""
The CommandTable header definition.
"""
@dataclass
[docs]class CommandTableEntryValue(DataClassJsonMixin):
"""
A CommandTable entry definition with a value.
"""
@dataclass
@dataclass
[docs]class CommandTableEntry(DataClassJsonMixin):
"""
The definition of a single CommandTable entry.
"""
[docs] waveform: "CommandTableWaveform"
@dataclass
[docs]class CommandTable(DataClassJsonMixin):
"""
The CommandTable definition for ZI HDAWG.
"""
[docs] header: "CommandTableHeader" = field(init=False)
[docs] table: List["CommandTableEntry"]
def __post_init__(self):
"""Initializes fields after initializing object."""
self.header = CommandTableHeader()
@unique
[docs]class QasIntegrationMode(Enum):
"""
Operation mode of all weighted integration units.
NORMAL: Normal mode. The integration weights are given
by the user-programmed filter memory.
SPECTROSCOPY: Spectroscopy mode. The integration weights
are generated by a digital oscillator. This mode offers
enhanced frequency resolution.
"""
@unique
[docs]class QasResultMode(Enum):
"""UHFQA QAS result mode."""
@unique
[docs]class QasResultSource(Enum):
"""UHFQA QAS result source."""
[docs] CROSSTALK_CORRELATION = 4
[docs] THRESHOLD_CORRELATION = 5
@dataclass
[docs]class InstrumentInfo:
"""Instrument information record type."""
[docs] num_samples_per_clock: int # number of samples per clock cycle (sequencer_rate)
[docs] granularity: int # waveforms need to be a multiple of this many samples.
[docs] mode: enums.InstrumentOperationMode = enums.InstrumentOperationMode.OPERATING
[docs] sequencer_rate: float = field(init=False)
def __post_init__(self):
"""Initializes fields after initializing object."""
self.sequencer_rate = self.num_samples_per_clock / self.sample_rate
@dataclass(frozen=True)
[docs]class Instruction:
"""Sequence base instruction record type."""
@staticmethod
[docs] def default():
"""
Returns a default Instruction instance.
Returns
-------
Instruction :
"""
return Instruction("None", 0, 0, 0)
@dataclass(frozen=True)
[docs]class Acquisition(Instruction):
"""
This instruction indicates that an acquisition is to be triggered in the UHFQA.
If a waveform_id is specified, this waveform will be used as the integration weight.
"""
def __repr__(self):
return (
f"Acquisition(waveform_id: {self.waveform_id}"
f"|abs_time: {self.abs_time * 1e9} ns"
f"|dt: {self.duration * 1e9} ns"
f"|c0: {self.clock_cycle_start}"
)
@dataclass(frozen=True)
[docs]class Wave(Instruction):
"""
This instruction indicates that a waveform should be played.
"""
def __repr__(self):
return (
f"Wave(waveform_id: {self.waveform_id}"
f"|abs_time: {self.abs_time * 1e9} ns"
f"|dt: {self.duration * 1e9} ns"
f"|c0: {self.clock_cycle_start}"
)