Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding new octave #16

Merged
merged 16 commits into from
Mar 12, 2024
Merged
76 changes: 60 additions & 16 deletions quam/components/channels.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dataclasses import field
from typing import ClassVar, Dict, List, Optional, Tuple, Union

from quam.components.hardware import FrequencyConverter
from quam.components.hardware import BaseFrequencyConverter, Mixer, LocalOscillator
from quam.components.pulses import Pulse, ReadoutPulse
from quam.core import QuamComponent, quam_dataclass
from quam.utils import string_reference as str_ref
Expand Down Expand Up @@ -527,19 +527,19 @@ class IQChannel(Channel):
opx_output_offset_I: float = None
opx_output_offset_Q: float = None

frequency_converter_up: FrequencyConverter
frequency_converter_up: BaseFrequencyConverter

intermediate_frequency: float = 0.0

_default_label: ClassVar[str] = "IQ"

@property
def local_oscillator(self):
return self.frequency_converter_up.local_oscillator
def local_oscillator(self) -> Optional[LocalOscillator]:
return getattr(self.frequency_converter_up, "local_oscillator", None)

@property
def mixer(self):
return self.frequency_converter_up.mixer
def mixer(self) -> Optional[Mixer]:
return getattr(self.frequency_converter_up, "mixer", None)

@property
def rf_frequency(self):
Expand All @@ -565,12 +565,35 @@ def apply_to_config(self, config: dict):
)

element_cfg = config["elements"][self.name]
element_cfg["mixInputs"] = {**opx_outputs}
element_cfg["intermediate_frequency"] = self.intermediate_frequency
if self.mixer is not None:
element_cfg["mixInputs"]["mixer"] = self.mixer.name
if self.local_oscillator is not None:
element_cfg["mixInputs"]["lo_frequency"] = self.local_oscillator.frequency

from quam.components.octave import OctaveUpConverter

if isinstance(self.frequency_converter_up, OctaveUpConverter):
octave = self.frequency_converter_up.octave
if octave is None:
raise ValueError(
f"Error generating config: channel {self.name} has an "
f"OctaveUpConverter (id={self.frequency_converter_up.id}) without "
"an attached Octave"
)
element_cfg["RF_outputs"] = {
"port": (octave.name, self.frequency_converter_up.id)
}
elif str_ref.is_reference(self.frequency_converter_up):
raise ValueError(
f"Error generating config: channel {self.name} could not determine "
f'"frequency_converter_up", it seems to point to a non-existent '
f"reference: {self.frequency_converter_up}"
)
else:
element_cfg["mixInputs"] = {**opx_outputs}
if self.mixer is not None:
element_cfg["mixInputs"]["mixer"] = self.mixer.name
if self.local_oscillator is not None:
element_cfg["mixInputs"][
"lo_frequency"
] = self.local_oscillator.frequency

for I_or_Q in ["I", "Q"]:
controller_name, port = opx_outputs[I_or_Q]
Expand Down Expand Up @@ -631,7 +654,7 @@ class InOutIQChannel(IQChannel):

input_gain: Optional[float] = None

frequency_converter_down: FrequencyConverter = None
frequency_converter_down: BaseFrequencyConverter = None

_default_label: ClassVar[str] = "IQ"

Expand All @@ -648,13 +671,34 @@ def apply_to_config(self, config: dict):

# Note outputs instead of inputs because it's w.r.t. the QPU
element_cfg = config["elements"][self.name]
element_cfg["outputs"] = {
"out1": tuple(self.opx_input_I),
"out2": tuple(self.opx_input_Q),
}
element_cfg["smearing"] = self.smearing
element_cfg["time_of_flight"] = self.time_of_flight

from quam.components.octave import OctaveDownConverter

if isinstance(self.frequency_converter_down, OctaveDownConverter):
octave = self.frequency_converter_down.octave
if octave is None:
raise ValueError(
f"Error generating config: channel {self.name} has an "
f"OctaveDownConverter (id={self.frequency_converter_down.id}) "
"without an attached Octave"
)
element_cfg["RF_inputs"] = {
"port": (octave.name, self.frequency_converter_down.id)
}
elif str_ref.is_reference(self.frequency_converter_down):
raise ValueError(
f"Error generating config: channel {self.name} could not determine "
f'"frequency_converter_down", it seems to point to a non-existent '
f"reference: {self.frequency_converter_down}"
)
else:
element_cfg["outputs"] = {
"out1": tuple(self.opx_input_I),
"out2": tuple(self.opx_input_Q),
}

for I_or_Q in ["I", "Q"]:
controller_name, port = opx_inputs[I_or_Q]
controller_cfg = self._config_add_controller(config, controller_name)
Expand Down
11 changes: 8 additions & 3 deletions quam/components/hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ class LocalOscillator(QuamComponent):
frequency: float = None
power: float = None

def configure(self):
...
def configure(self): ...


@quam_dataclass
Expand Down Expand Up @@ -109,7 +108,13 @@ def IQ_imbalance(g: float, phi: float) -> List[float]:


@quam_dataclass
class FrequencyConverter(QuamComponent):
class BaseFrequencyConverter(QuamComponent):
"""Base class for frequency converters."""
pass


@quam_dataclass
class FrequencyConverter(BaseFrequencyConverter):
local_oscillator: LocalOscillator = None
mixer: Mixer = None
gain: float = None
Expand Down
Loading