Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into feat/ports
Browse files Browse the repository at this point in the history
  • Loading branch information
nulinspiratie committed Jul 3, 2024
2 parents 5001015 + 5e55155 commit bed20b3
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 3 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
### Changed
- Allow `QuamBase.get_reference(attr)` to return a reference of one of its attributes

### Fixed
- Fix quam object instantiation error when a parameter type uses pipe operator
- Allow int keys to be serialised / loaded in QuAM using JSONSerialiser


## [0.3.3]
### Added
- Added the following parameters to `IQChannel`: `RF_frequency`, `LO_frequency`, `intermediate_frequency`
Expand Down
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

/// tab | For Windows
- Windows 10 (build 1809 and later), or Windows 11
- Python 3.9 or higher, we recommend Python 3.10 or higher
- 3.8 ≤ Python ≤ 3.11, we recommend Python 3.10 or 3.11
<!-- For Python 3.8 and 3.9, please see additional notes (TODO add note reference) -->
- [Git version control system](https://git-scm.com/), or a Git GUI such as [GitHub Desktop](https://desktop.github.com/) or [GitKraken](https://www.gitkraken.com/)

Expand Down
10 changes: 9 additions & 1 deletion quam/core/quam_instantiation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from __future__ import annotations
import sys
import types
import typing
from typing import TYPE_CHECKING, Dict, Any
from inspect import isclass
Expand All @@ -16,6 +18,12 @@
from quam.core import QuamBase


if sys.version_info < (3, 10):
union_types = (typing.Union,)
else:
union_types = [typing.Union, types.UnionType]


def instantiate_attrs_from_dict(
attr_dict: dict,
required_type: type,
Expand Down Expand Up @@ -224,7 +232,7 @@ def instantiate_attr(
)
if typing.get_origin(expected_type) == dict:
expected_type = dict
elif typing.get_origin(expected_type) == typing.Union:
elif typing.get_origin(expected_type) in union_types:
for union_type in typing.get_args(expected_type):
try:
instantiated_attr = instantiate_attr(
Expand Down
16 changes: 15 additions & 1 deletion quam/serialisation/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def load(

metadata["default_filename"] = path.name
with open(path, "r") as f:
contents = json.load(f)
contents = json.load(f, object_hook=convert_int_keys)
elif path.is_dir():
metadata["default_foldername"] = str(path)
for file in path.iterdir():
Expand All @@ -183,3 +183,17 @@ def load(
metadata["content_mapping"][file.name] = list(file_contents.keys())

return contents, metadata


def convert_int_keys(obj):
"""Convert dictionary keys to integers if possible."""
if not isinstance(obj, dict):
return obj

new_obj = {}
for key, value in obj.items():
if key.isdigit():
key = int(key)
new_obj[key] = value

return new_obj
9 changes: 9 additions & 0 deletions quam/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@ def generate_config_final_actions(qua_config):
Args:
qua_config (dict): The generated qua config.
"""
# Add default dc offset 0V to all analog outputs and inputs if not set
for controller_cfg in qua_config["controllers"].values():
for fem in controller_cfg.get("fems", {}).values():
if fem.get("type") != "LF":
continue
for analog_output in fem.get("analog_outputs", {}).values():
analog_output.setdefault("offset", 0.0)
for analog_input in fem.get("analog_inputs", {}).values():
analog_input.setdefault("offset", 0.0)

if "analog_outputs" in controller_cfg:
for analog_output in controller_cfg["analog_outputs"].values():
analog_output.setdefault("offset", 0.0)
Expand Down
139 changes: 139 additions & 0 deletions tests/config/test_config_final_actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
from quam.utils.config import generate_config_final_actions


def test_config_no_overwrite_existing_offset():
cfg = {
"controllers": {
"con1": {
"analog_outputs": {1: {"offset": 0.5}},
"analog_inputs": {2: {"offset": 0.5}},
},
},
}

generate_config_final_actions(cfg)

assert cfg == {
"controllers": {
"con1": {
"analog_outputs": {1: {"offset": 0.5}},
"analog_inputs": {2: {"offset": 0.5}},
},
},
}


def test_config_default_offset():
cfg = {
"controllers": {
"con1": {
"analog_outputs": {1: {}},
"analog_inputs": {2: {}},
},
},
}

generate_config_final_actions(cfg)

assert cfg == {
"controllers": {
"con1": {
"analog_outputs": {1: {"offset": 0.0}},
"analog_inputs": {2: {"offset": 0.0}},
},
},
}


def test_config_default_offset_LF_FEM():
cfg = {
"controllers": {
"con1": {
"fems": {
2: {
"type": "LF",
"analog_outputs": {1: {}},
"analog_inputs": {2: {}},
},
},
},
},
}

generate_config_final_actions(cfg)

assert cfg == {
"controllers": {
"con1": {
"fems": {
2: {
"type": "LF",
"analog_outputs": {1: {"offset": 0.0}},
"analog_inputs": {2: {"offset": 0.0}},
},
},
},
},
}


def test_config_no_overwrite_existing_offset_LF_FEM():
cfg = {
"controllers": {
"con1": {
"fems": {
2: {
"type": "LF",
"analog_outputs": {1: {"offset": 0.5}},
"analog_inputs": {2: {"offset": 0.5}},
},
},
},
},
}

generate_config_final_actions(cfg)

assert cfg == {
"controllers": {
"con1": {
"fems": {
2: {
"type": "LF",
"analog_outputs": {1: {"offset": 0.5}},
"analog_inputs": {2: {"offset": 0.5}},
},
},
},
},
}


def test_config_default_offset_no_outputs_inputs_entries():
cfg = {"controllers": {"con1": {}}}

generate_config_final_actions(cfg)

assert cfg == {"controllers": {"con1": {}}}


def test_config_default_offset_no_outputs_inputs():
cfg = {
"controllers": {
"con1": {
"analog_outputs": {},
"analog_inputs": {},
}
}
}

generate_config_final_actions(cfg)

assert cfg == {
"controllers": {
"con1": {
"analog_outputs": {},
"analog_inputs": {},
}
}
}
19 changes: 19 additions & 0 deletions tests/instantiation/test_instantiation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import pytest
from typing import List, Literal, Optional, Tuple, Union

from pytest_cov.engine import sys

from quam.core import QuamRoot, QuamComponent, quam_dataclass
from quam.core.quam_classes import QuamDict
from quam.examples.superconducting_qubits.components import Transmon
Expand Down Expand Up @@ -339,6 +341,7 @@ def test_instantiate_dict_referenced():

assert attrs == {"test_attr": "#./reference"}


@quam_dataclass
class TestQuamComponent(QuamComponent):
a: int
Expand All @@ -357,3 +360,19 @@ class TestQuamUnion(QuamComponent):

with pytest.raises(TypeError):
instantiate_quam_class(TestQuamUnion, {"union_val": {"a": "42"}})


@pytest.mark.skipif(sys.version_info < (3, 10), reason="requires python3.10 or higher")
def test_instantiation_pipe_union_type():
@quam_dataclass
class TestQuamUnion(QuamComponent):
union_val: int | TestQuamComponent

obj = instantiate_quam_class(TestQuamUnion, {"union_val": 42})
assert obj.union_val == 42

obj = instantiate_quam_class(TestQuamUnion, {"union_val": {"a": 42}})
assert obj.union_val.a == 42

with pytest.raises(TypeError):
instantiate_quam_class(TestQuamUnion, {"union_val": {"a": "42"}})
26 changes: 26 additions & 0 deletions tests/serialisation/test_json_serialisation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
from typing import Dict
import pytest

from quam.serialisation import JSONSerialiser
Expand Down Expand Up @@ -107,3 +108,28 @@ def test_component_mamping_ignore(tmp_path):
"a": 4,
}
}


@quam_dataclass
class QuAMWithIntDict(QuamRoot):
a: int
d: Dict[int, str]


def test_serialise_int_dict_keys(tmp_path):
quam_root = QuAMWithIntDict(a=1, d={1: "a", 2: "b"})

serialiser = JSONSerialiser()
path = tmp_path / "quam_root.json"
serialiser.save(quam_root, path)

d, _ = serialiser.load(path)

assert d == {
"a": 1,
"d": {
1: "a",
2: "b",
},
"__class__": "test_json_serialisation.QuAMWithIntDict",
}

0 comments on commit bed20b3

Please sign in to comment.