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

Fix/Add all MW channel properties #72

Merged
merged 11 commits into from
Sep 4, 2024
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
### Added
- Added `DragCosinePulse`.
- Added support for sticky channels through the `StickyChannelAddon` (see documentation)
- Added `Channel.thread`, which defaults to None

### Changed
- Added ports for different hardware. As a consequence we now also support the LF-FEM and MW-FEM
- `Channel` is now an abstract base class.
- Moved `intermediate_frequency` to `Channel` from `SingleChannel/IQChannel`.
The default is `None`. A consequence of this is that `SingleChannel` no longer adds
`intermediate_frequency` to the config if it's not set.


## [0.3.4]
Expand Down
315 changes: 194 additions & 121 deletions quam/components/channels.py

Large diffs are not rendered by default.

13 changes: 7 additions & 6 deletions quam/components/pulses.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,11 @@ def _config_add_waveforms(self, config):

Raises:
ValueError: If the waveform type (single or IQ) does not match the parent
channel type (SingleChannel, IQChannel, InOutIQChannel).
channel type (SingleChannel, IQChannel, InOutIQChannel, MWChannel,
InOutMWChannel).
"""

from quam.components.channels import SingleChannel, IQChannel
from quam.components.channels import SingleChannel, IQChannel, MWChannel

pulse_config = config["pulses"][self.pulse_name]

Expand All @@ -199,7 +200,7 @@ def _config_add_waveforms(self, config):
wf_type = "constant"
if isinstance(waveform, complex):
waveforms = {"I": waveform.real, "Q": waveform.imag}
elif isinstance(self.channel, IQChannel):
elif isinstance(self.channel, (IQChannel, MWChannel)):
waveforms = {"I": waveform, "Q": 0.0}
else:
waveforms = {"single": waveform}
Expand All @@ -208,7 +209,7 @@ def _config_add_waveforms(self, config):
wf_type = "arbitrary"
if np.iscomplexobj(waveform):
waveforms = {"I": list(waveform.real), "Q": list(waveform.imag)}
elif isinstance(self.channel, IQChannel):
elif isinstance(self.channel, (IQChannel, MWChannel)):
waveforms = {"I": waveform, "Q": np.zeros_like(waveform)}
else:
waveforms = {"single": list(waveform)}
Expand All @@ -218,10 +219,10 @@ def _config_add_waveforms(self, config):
# Add check that waveform type (single or IQ) matches parent
if "single" in waveforms and not isinstance(self.channel, SingleChannel):
raise ValueError(
"Waveform type 'single' not allowed for IQChannel"
"Waveform type 'single' not allowed for (IQChannel, MWChannel)"
f" '{self.channel.name}'"
)
elif "I" in waveforms and not isinstance(self.channel, IQChannel):
elif "I" in waveforms and not isinstance(self.channel, (IQChannel, MWChannel)):
raise ValueError(
"Waveform type 'IQ' not allowed for SingleChannel"
f" '{self.channel.name}'"
Expand Down
4 changes: 1 addition & 3 deletions tests/components/channels/test_IQ_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def test_IQ_channel_inferred_RF_frequency():
frequency_converter_up=None,
)

assert channel.intermediate_frequency == 0.0
assert channel.intermediate_frequency is None
assert channel.LO_frequency == "#./frequency_converter_up/LO_frequency"
assert channel.RF_frequency == "#./inferred_RF_frequency"
with pytest.raises(AttributeError):
Expand Down Expand Up @@ -112,7 +112,6 @@ def test_generate_config(qua_config):

assert qua_config["elements"] == {
"out_channel": {
"intermediate_frequency": 0.0,
"mixInputs": {
"I": ("con1", 1),
"Q": ("con1", 2),
Expand Down Expand Up @@ -145,7 +144,6 @@ def test_generate_config_ports(qua_config):

assert qua_config["elements"] == {
"out_channel": {
"intermediate_frequency": 0.0,
"mixInputs": {
"I": ("con1", 1),
"Q": ("con1", 2),
Expand Down
1 change: 1 addition & 0 deletions tests/components/channels/test_in_IQ_out_single_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def test_in_single_channel_attr_annotations():
"opx_input_offset_I",
"opx_input_offset_Q",
"frequency_converter_down",
"thread",
}


Expand Down
2 changes: 2 additions & 0 deletions tests/components/channels/test_in_single_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ def test_in_single_channel_attr_annotations():
attr_annotations = get_dataclass_attr_annotations(InSingleChannel)
assert set(attr_annotations["required"]) == {"opx_input"}
assert set(attr_annotations["optional"]) == {
"intermediate_frequency",
"operations",
"sticky",
"id",
"digital_outputs",
"opx_input_offset",
"time_of_flight",
"smearing",
"thread",
}


Expand Down
4 changes: 2 additions & 2 deletions tests/components/channels/test_in_single_out_IQ_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def test_in_single_channel_attr_annotations():
"opx_input_offset",
"time_of_flight",
"smearing",
"thread"
}


Expand Down Expand Up @@ -85,7 +86,7 @@ def test_generate_config(qua_config):
"analog_inputs": {
1: {"gain_db": 0, "shareable": False},
},
"analog_outputs": {
"analog_outputs": {
1: {"delay": 0, "shareable": False},
2: {"delay": 0, "shareable": False},
},
Expand All @@ -94,7 +95,6 @@ def test_generate_config(qua_config):

assert qua_config["elements"] == {
"in_out_channel": {
"intermediate_frequency": 0.0,
"mixInputs": {
"I": ("con1", 1),
"Q": ("con1", 2),
Expand Down
2 changes: 0 additions & 2 deletions tests/components/test_octave.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,6 @@ def test_channel_add_RF_outputs(octave, qua_config):

expected_cfg_elements = {
"ch": {
"intermediate_frequency": 0.0,
"RF_inputs": {"port": ("octave1", 2)},
"operations": {},
}
Expand Down Expand Up @@ -308,7 +307,6 @@ def test_channel_add_RF_inputs(octave, qua_config):

expected_cfg_elements = {
"ch": {
"intermediate_frequency": 0.0,
"RF_inputs": {"port": ("octave1", 3)},
"RF_outputs": {"port": ("octave1", 4)},
"operations": {},
Expand Down