# Generated by the protocol buffer compiler.  DO NOT EDIT!
# sources: qm/grpc/quantum_simulator/v1/physical_system.proto
# plugin: python-betterproto
from dataclasses import dataclass
from typing import Dict, List

import betterproto


@dataclass
class InputPort(betterproto.Message):
    """Input port of the quantum system (output port of OPX)"""

    # name of the controller
    controller: str = betterproto.string_field(1)
    # id
    id: int = betterproto.uint32_field(2)


@dataclass
class OutputPort(betterproto.Message):
    """Output port of the quantum system (input port of OPX)"""

    # name of the controller
    controller: str = betterproto.string_field(1)
    # id
    id: int = betterproto.uint32_field(2)


@dataclass
class TransmonProperties(betterproto.Message):
    """A class that holds the physical properties of a transmon."""

    # frequency of the qubit in Hz
    frequency: float = betterproto.double_field(1)
    # anharmonicity of the qubit in Hz
    anharmonicity: float = betterproto.double_field(2)
    # T1 time in ns
    t1: float = betterproto.double_field(3)
    # T2 time in ns
    t2: float = betterproto.double_field(4)
    n_levels: int = betterproto.uint32_field(5)
    n_order: int = betterproto.uint32_field(6)


@dataclass
class IQMixerIn(betterproto.Message):
    """IQMixer for up conversion"""

    # output port of the OPX
    i: "InputPort" = betterproto.message_field(1)
    # output port of the OPX
    q: "InputPort" = betterproto.message_field(2)
    # frequency of the local oscillator in Hz
    lo_frequency: float = betterproto.double_field(3)


@dataclass
class IQMixerOut(betterproto.Message):
    """IQMixer for down conversion"""

    # input port of the OPX
    i: "OutputPort" = betterproto.message_field(1)
    # input port of the OPX
    q: "OutputPort" = betterproto.message_field(2)
    # frequency of the local oscillator in Hz
    lo_frequency: float = betterproto.double_field(3)


@dataclass
class AnalogFrontend(betterproto.Message):
    """
    A class to describe analog frontend (currently just a constant
    multiplicative factor)
    """

    # a constant factor to account for losses or amplification of the signal
    amp_factor: float = betterproto.double_field(1)


@dataclass
class FluxLine(betterproto.Message):
    """
    A class to describe flux line and how it is connected to the OPX. The
    frequency of the qubit follows is tuned as: amp*(flux voltage - offset)^2
    """

    # output port of the OPX driving the flux line
    port: "InputPort" = betterproto.message_field(1)
    # amplitude in units of GHz/V^2
    amp_factor: float = betterproto.double_field(2)
    # offset voltage at which the bias is zero
    offset: float = betterproto.double_field(3)


@dataclass
class FixedFrequencyTransmon(betterproto.Message):
    pass


@dataclass
class TunableFrequencyTransmon(betterproto.Message):
    """A class to describe tunable frequency transmon"""

    # flux line controlling the transmon frequency
    flux_line: "FluxLine" = betterproto.message_field(1)


@dataclass
class Transmon(betterproto.Message):
    """
    Transmon contains the physical properties of the transmonand the
    information about how it is connected to the IQ Mixer and OPX
    """

    # physical properties of the transmon
    properties: "TransmonProperties" = betterproto.message_field(1)
    # IQ mixer used to drive the qubit
    i_q_mixer: "IQMixerIn" = betterproto.message_field(2)
    # analog frontend
    analog_frontend: "AnalogFrontend" = betterproto.message_field(3)
    # fixed frequency qubit
    fixed_frequency_transmon: "FixedFrequencyTransmon" = betterproto.message_field(
        4, group="type"
    )
    # tunable frequency qubit
    tunable_frequency_transmon: "TunableFrequencyTransmon" = betterproto.message_field(
        5, group="type"
    )


@dataclass
class DriveResonator(betterproto.Message):
    pass


@dataclass
class ReadoutResonator(betterproto.Message):
    """
    A class with the information about how the back reflected from the
    resonator is fed to the OPX.
    """

    i_q_mixer: "IQMixerOut" = betterproto.message_field(1)


@dataclass
class ResonatorProperties(betterproto.Message):
    # resonator frequency in Hz
    frequency: float = betterproto.double_field(1)
    # resonator loss rate in Hz
    lossrate: float = betterproto.double_field(2)
    # number of n_levels
    n_levels: int = betterproto.uint32_field(3)


@dataclass
class Resonator(betterproto.Message):
    """
    A class to describe the physical properties of readout resonator and how it
    is connected to the OPX
    """

    properties: "ResonatorProperties" = betterproto.message_field(1)
    # IQMixer to upconvert the drive
    i_q_mixer: "IQMixerIn" = betterproto.message_field(2)
    # analog frontend
    analog_frontend: "AnalogFrontend" = betterproto.message_field(3)
    # drive resonator
    drive_resonator: "DriveResonator" = betterproto.message_field(4, group="type")
    # readout resonator
    readout_resonator: "ReadoutResonator" = betterproto.message_field(5, group="type")


@dataclass
class CapacitiveCoupler(betterproto.Message):
    """A class for describing capacitive coupling between two qubits"""

    # output port of the OPX driving the coupler
    g: "InputPort" = betterproto.message_field(1)
    # amplitude factor in units of GHz/V
    amp_factor: float = betterproto.double_field(2)


@dataclass
class TransmonTransmonCoupling(betterproto.Message):
    """Transmon-transmon coupling"""

    # name of the capacitive coupler
    capacitive_coupler: str = betterproto.string_field(1)
    # name of the qubit 1
    qb1: str = betterproto.string_field(2)
    # name of the qubit 2
    qb2: str = betterproto.string_field(3)


@dataclass
class TransmonResonatorCoupling(betterproto.Message):
    """
    Transmon-resonator coupling describes the connectivity between a qubit and
    a resonator
    """

    # name of the qubit
    transmon: str = betterproto.string_field(1)
    # name of the resonator
    resonator: str = betterproto.string_field(2)
    # strength of the coupling in GHz
    g: float = betterproto.double_field(3)
    # coupling type
    is_dispersive: bool = betterproto.bool_field(4)


@dataclass
class SCChip(betterproto.Message):
    """
    A class to describe a superconducting chip layout consisting of fixed/flux
    tunable transmons, capacitive couplers and readout resonators.
    """

    # a dictionary of Transmons
    transmons: Dict[str, "Transmon"] = betterproto.map_field(
        1, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE
    )
    # a dictionary of resonators
    resonators: Dict[str, "Resonator"] = betterproto.map_field(
        2, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE
    )
    # a dictionary of capacitive couplers
    capacitive_couplers: Dict[str, "CapacitiveCoupler"] = betterproto.map_field(
        3, betterproto.TYPE_STRING, betterproto.TYPE_MESSAGE
    )
    # a list containing all the qubit-qubit couplings in the chip
    transmon_transmon_coupling: List[
        "TransmonTransmonCoupling"
    ] = betterproto.message_field(4)
    # a list containing the qubit-resonator couplings and their respective
    # strengths
    transmon_resonator_coupling: List[
        "TransmonResonatorCoupling"
    ] = betterproto.message_field(5)


@dataclass
class Offset(betterproto.Message):
    port: "InputPort" = betterproto.message_field(1)
    value: float = betterproto.double_field(2)


@dataclass
class Waveform(betterproto.Message):
    constant_waveform: "ConstantWaveform" = betterproto.message_field(1, group="type")
    arbitrary_waveform: "ArbitraryWaveform" = betterproto.message_field(2, group="type")


@dataclass
class ConstantWaveform(betterproto.Message):
    sample: float = betterproto.double_field(1)


@dataclass
class ArbitraryWaveform(betterproto.Message):
    samples: List[float] = betterproto.double_field(1)


@dataclass
class Error(betterproto.Message):
    type: str = betterproto.string_field(1)
    stack: str = betterproto.string_field(2)


@dataclass
class ColdAtomDevice(betterproto.Message):
    v: float = betterproto.double_field(1)
    qubit: str = betterproto.string_field(2)
    frequency_01: float = betterproto.double_field(3)
    frequency_1r: float = betterproto.double_field(4)
    positions: List["Coordinate"] = betterproto.message_field(5)
    t1: float = betterproto.double_field(6)
    t2: float = betterproto.double_field(7)


@dataclass
class Coordinate(betterproto.Message):
    x: float = betterproto.double_field(1)
    y: float = betterproto.double_field(2)


@dataclass
class ColdAtomSetup(betterproto.Message):
    device: "ColdAtomDevice" = betterproto.message_field(1)
    global_raman_beam: "GlobalRamanBeam" = betterproto.message_field(2)
    global_rydberg_beam: "GlobalRydbergBeam" = betterproto.message_field(3)
    local_raman_detuning: "ACStarkShifter" = betterproto.message_field(4)
    local_rydberg_detuning: "ACStarkShifter" = betterproto.message_field(5)


@dataclass
class BeamSteerer(betterproto.Message):
    a_o_d_x: str = betterproto.string_field(1)
    a_o_d_y: str = betterproto.string_field(2)
    reference_position: "Coordinate" = betterproto.message_field(3)
    eta_x: float = betterproto.double_field(4)
    eta_y: float = betterproto.double_field(5)


@dataclass
class ACStarkShifter(betterproto.Message):
    a_o_m: str = betterproto.string_field(1)
    delta: float = betterproto.double_field(2)
    eta_x: List[float] = betterproto.double_field(3)
    beam_steerer: "BeamSteerer" = betterproto.message_field(4)


@dataclass
class GlobalRamanBeam(betterproto.Message):
    intensity_modulator: str = betterproto.string_field(1)
    frequency: float = betterproto.double_field(2)
    scale_factor: float = betterproto.double_field(3)
    lo_frequency: float = betterproto.double_field(4)


@dataclass
class GlobalRydbergBeam(betterproto.Message):
    a_o_m1: str = betterproto.string_field(1)
    a_o_m2: str = betterproto.string_field(2)
    frequency1: float = betterproto.double_field(3)
    frequency2: float = betterproto.double_field(4)
    scale_factor1: float = betterproto.double_field(5)
    scale_factor2: float = betterproto.double_field(6)


@dataclass
class PhysicalConfig(betterproto.Message):
    chip: "SCChip" = betterproto.message_field(1, group="type")
    cold_atom_setup: "ColdAtomSetup" = betterproto.message_field(2, group="type")
