iqm-exa-common 26.24.0__tar.gz → 26.26.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/CHANGELOG.rst +16 -0
- {iqm_exa_common-26.24.0/src/iqm_exa_common.egg-info → iqm_exa_common-26.26.0}/PKG-INFO +2 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/requirements/base.in +2 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/requirements/base.txt +2 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/center_span_options.py +1 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/start_stop_base_options.py +5 -9
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/start_stop_options.py +1 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/sweep_values.py +3 -4
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/data/base_model.py +2 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/data/parameter.py +19 -21
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/data/setting_node.py +15 -15
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/helpers/data_helper.py +4 -2
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/helpers/software_version_helper.py +1 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/qcm_data/chad_model.py +3 -2
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/qcm_data/chip_topology.py +7 -7
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/qcm_data/qcm_data_client.py +1 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0/src/iqm_exa_common.egg-info}/PKG-INFO +2 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/iqm_exa_common.egg-info/requires.txt +1 -0
- iqm_exa_common-26.26.0/version.txt +1 -0
- iqm_exa_common-26.24.0/version.txt +0 -1
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/LICENSE.txt +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/MANIFEST.in +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/README.rst +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/API.rst +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/Makefile +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/_static/.gitignore +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/_static/css/custom.css +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/_static/images/favicon.ico +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/_static/images/logo.png +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/_templates/autosummary-class-template.rst +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/_templates/autosummary-module-template.rst +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/changelog.rst +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/conf.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/index.rst +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/license.rst +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/pyproject.toml +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/setup.cfg +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/setup.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/_parameter.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/array.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/datum.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/nd_sweep.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/sequence.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/setting_node.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/exponential_sweep.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/fixed_sweep.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/linear_sweep.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/center_span_base_options.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/constants.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/fixed_options.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/option_converter.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/sweep_options.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/sweep.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/data/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/data/settingnode_v2.html.jinja2 +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/data/value.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/errors/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/errors/exa_error.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/errors/station_control_errors.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/helpers/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/helpers/deprecation.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/helpers/json_helper.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/helpers/numpy_helper.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/helpers/yaml_helper.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/logger/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/logger/logger.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/qcm_data/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/qcm_data/file_adapter.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/qcm_data/immutable_base_model.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/sweep/__init__.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/sweep/database_serialization.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/sweep/util.py +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/iqm_exa_common.egg-info/SOURCES.txt +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/iqm_exa_common.egg-info/dependency_links.txt +0 -0
- {iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/iqm_exa_common.egg-info/top_level.txt +0 -0
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
Changelog
|
|
3
3
|
=========
|
|
4
4
|
|
|
5
|
+
Version 26.26.0 (2025-07-02)
|
|
6
|
+
============================
|
|
7
|
+
|
|
8
|
+
Bug fixes
|
|
9
|
+
---------
|
|
10
|
+
|
|
11
|
+
- Fix type errors raised by mypy.
|
|
12
|
+
|
|
13
|
+
Version 26.25.0 (2025-06-17)
|
|
14
|
+
============================
|
|
15
|
+
|
|
16
|
+
Features
|
|
17
|
+
--------
|
|
18
|
+
|
|
19
|
+
- Add missing jinja2 requirement
|
|
20
|
+
|
|
5
21
|
Version 26.24.0 (2025-06-17)
|
|
6
22
|
============================
|
|
7
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: iqm-exa-common
|
|
3
|
-
Version: 26.
|
|
3
|
+
Version: 26.26.0
|
|
4
4
|
Summary: Framework for control and measurement of superconducting qubits: common library
|
|
5
5
|
Author-email: IQM Finland Oy <info@meetiqm.com>
|
|
6
6
|
License: Apache License
|
|
@@ -221,6 +221,7 @@ Requires-Dist: xarray==2024.10.0
|
|
|
221
221
|
Requires-Dist: requests==2.32.3
|
|
222
222
|
Requires-Dist: ruamel-yaml==0.17.32
|
|
223
223
|
Requires-Dist: ruamel-yaml-clib==0.2.8
|
|
224
|
+
Requires-Dist: jinja2==3.0.3
|
|
224
225
|
|
|
225
226
|
EXA-common
|
|
226
227
|
==========
|
|
@@ -40,7 +40,7 @@ class CenterSpanOptions(SweepOptions):
|
|
|
40
40
|
#: :const:`exa.common.control.sweep.option.constants.DEFAULT_COUNT`.
|
|
41
41
|
count: int | None = None
|
|
42
42
|
#: Size of spacing between values.
|
|
43
|
-
step: int | float | complex = None
|
|
43
|
+
step: int | float | complex | None = None
|
|
44
44
|
#: Order of generated values. Default to ascending
|
|
45
45
|
asc: bool | None = None
|
|
46
46
|
|
|
@@ -35,26 +35,22 @@ class StartStopBaseOptions(SweepOptions):
|
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
37
|
#: The power for the start of the interval.
|
|
38
|
-
start: int | float
|
|
38
|
+
start: int | float
|
|
39
39
|
#: The power for the end of the interval.
|
|
40
|
-
stop: int | float
|
|
40
|
+
stop: int | float
|
|
41
41
|
#: Number of values to generate. Default to
|
|
42
42
|
#: :const:`exa.common.control.sweep.option.constants.DEFAULT_COUNT`.
|
|
43
|
-
count: int
|
|
43
|
+
count: int = DEFAULT_COUNT
|
|
44
44
|
#: Number, that is raised to the power `start` or `stop`. Default to
|
|
45
45
|
#: :const:`exa.common.control.sweep.option.constants.DEFAULT_BASE`.
|
|
46
|
-
base: int
|
|
46
|
+
base: int = DEFAULT_BASE
|
|
47
47
|
|
|
48
48
|
def __post_init__(self):
|
|
49
|
-
if self.count is None:
|
|
50
|
-
object.__setattr__(self, "count", DEFAULT_COUNT)
|
|
51
|
-
if self.base is None:
|
|
52
|
-
object.__setattr__(self, "base", DEFAULT_BASE)
|
|
53
49
|
if self.start == 0 or self.stop == 0:
|
|
54
50
|
raise ValueError("Exponential range sweep start and stop values must not be zero.")
|
|
55
51
|
|
|
56
52
|
@property
|
|
57
|
-
def data(self) -> list[int | float
|
|
53
|
+
def data(self) -> list[int | float]:
|
|
58
54
|
logger.debug(f"EXPONENTS: ({self.start}, {self.stop}) with base {self.base}")
|
|
59
55
|
start = math.pow(self.base, self.start)
|
|
60
56
|
stop = math.pow(self.base, self.stop)
|
|
@@ -65,7 +65,7 @@ class StartStopOptions(SweepOptions):
|
|
|
65
65
|
count = 1 + math.ceil(abs(self.stop - self.start) / float(np.abs(self.step)))
|
|
66
66
|
data = self._generate_by_count(count)
|
|
67
67
|
else:
|
|
68
|
-
data = self._generate_by_count(self.count)
|
|
68
|
+
data = self._generate_by_count(self.count if self.count is not None else DEFAULT_COUNT)
|
|
69
69
|
return data
|
|
70
70
|
|
|
71
71
|
def _generate_by_count(self, count: int) -> SweepValues:
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/sweep_values.py
RENAMED
|
@@ -28,9 +28,8 @@ def validate_sweep_values(sweep_values: Any) -> Any:
|
|
|
28
28
|
if isinstance(sweep_values, np.ndarray):
|
|
29
29
|
sweep_values = sweep_values.tolist()
|
|
30
30
|
for index, value in enumerate(sweep_values):
|
|
31
|
-
if isinstance(value, dict):
|
|
32
|
-
|
|
33
|
-
sweep_values[index] = complex(value["real"], value["imag"])
|
|
31
|
+
if isinstance(value, dict) and "__complex__" in value:
|
|
32
|
+
sweep_values[index] = complex(value["real"], value["imag"])
|
|
34
33
|
return sweep_values
|
|
35
34
|
|
|
36
35
|
|
|
@@ -51,7 +50,7 @@ def serialize_sweep_values(sweep_values: Any) -> Any:
|
|
|
51
50
|
|
|
52
51
|
|
|
53
52
|
SweepValues = Annotated[
|
|
54
|
-
list[Any] | np.ndarray
|
|
53
|
+
list[Any] | np.ndarray,
|
|
55
54
|
PlainValidator(validate_sweep_values),
|
|
56
55
|
PlainSerializer(serialize_sweep_values),
|
|
57
56
|
WithJsonSchema(core_schema.any_schema()),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
1
2
|
from typing import Any, Self
|
|
2
3
|
|
|
3
4
|
import pydantic
|
|
@@ -24,7 +25,7 @@ class BaseModel(pydantic.BaseModel):
|
|
|
24
25
|
frozen=True, # This makes instances of the model potentially hashable if all the attributes are hashable
|
|
25
26
|
)
|
|
26
27
|
|
|
27
|
-
def model_copy(self, *, update:
|
|
28
|
+
def model_copy(self, *, update: Mapping[str, Any] | None = None, deep: bool = True) -> Self:
|
|
28
29
|
"""Returns a copy of the model.
|
|
29
30
|
|
|
30
31
|
Overrides the Pydantic default 'model_copy' to set 'deep=True' by default.
|
|
@@ -116,7 +116,7 @@ class DataType(IntEnum):
|
|
|
116
116
|
else:
|
|
117
117
|
return False
|
|
118
118
|
|
|
119
|
-
def _cast(self, value: str) -> Any: # noqa: PLR0911
|
|
119
|
+
def _cast(self, value: str | None) -> Any: # noqa: PLR0911
|
|
120
120
|
if value is None:
|
|
121
121
|
return None
|
|
122
122
|
elif self in [DataType.FLOAT, DataType.NUMBER]:
|
|
@@ -238,13 +238,12 @@ class Parameter(BaseModel):
|
|
|
238
238
|
raise ValidationError("Parameter 'element_indices' must be one or more ints.")
|
|
239
239
|
object.__setattr__(self, "element_indices", idxs)
|
|
240
240
|
# there may be len(idxs) num of "__" separated indices at the end, remove those to get the parent name
|
|
241
|
-
|
|
241
|
+
seperated_indices = "__".join([str(idx) for idx in idxs])
|
|
242
|
+
parent_name = self.name.replace("__" + seperated_indices, "")
|
|
242
243
|
object.__setattr__(self, "_parent_name", parent_name)
|
|
243
244
|
object.__setattr__(self, "_parent_label", self.label.replace(f" {idxs}", ""))
|
|
244
245
|
object.__setattr__(self, "label", f"{self._parent_label} {idxs}")
|
|
245
|
-
name =
|
|
246
|
-
for index in idxs:
|
|
247
|
-
name += f"__{index}"
|
|
246
|
+
name = parent_name + "__" + seperated_indices
|
|
248
247
|
object.__setattr__(self, "name", name)
|
|
249
248
|
|
|
250
249
|
@property
|
|
@@ -272,7 +271,7 @@ class Parameter(BaseModel):
|
|
|
272
271
|
def build_data_set(
|
|
273
272
|
variables: list[tuple[Parameter, list[Any]]],
|
|
274
273
|
data: tuple[Parameter, SweepValues],
|
|
275
|
-
attributes: dict[str, Any] = None,
|
|
274
|
+
attributes: dict[str, Any] | None = None,
|
|
276
275
|
extra_variables: list[tuple[str, int]] | None = None,
|
|
277
276
|
):
|
|
278
277
|
"""Build an xarray Dataset, where the only DataArray is given by `results` and coordinates are given by
|
|
@@ -289,9 +288,9 @@ class Parameter(BaseModel):
|
|
|
289
288
|
extra_variables: Valueless dimensions and their sizes.
|
|
290
289
|
|
|
291
290
|
"""
|
|
292
|
-
variable_names = []
|
|
293
|
-
variable_sizes = []
|
|
294
|
-
variable_data_arrays = {}
|
|
291
|
+
variable_names: list[str] = []
|
|
292
|
+
variable_sizes: list[int] = []
|
|
293
|
+
variable_data_arrays: dict[str, xr.DataArray] = {}
|
|
295
294
|
for variable in variables:
|
|
296
295
|
variable_names.append(variable[0].name)
|
|
297
296
|
variable_sizes.append(len(variable[1]))
|
|
@@ -326,9 +325,9 @@ class Parameter(BaseModel):
|
|
|
326
325
|
def build_data_array(
|
|
327
326
|
self,
|
|
328
327
|
data: np.ndarray,
|
|
329
|
-
dimensions: list[Hashable] = None,
|
|
330
|
-
coords: dict[Hashable, Any] = None,
|
|
331
|
-
metadata: dict[str, Any] = None,
|
|
328
|
+
dimensions: list[str] | list[Hashable] | None = None,
|
|
329
|
+
coords: dict[Hashable, Any] | None = None,
|
|
330
|
+
metadata: dict[str, Any] | None = None,
|
|
332
331
|
) -> xr.DataArray:
|
|
333
332
|
"""Attach Parameter information to a numerical array.
|
|
334
333
|
|
|
@@ -365,7 +364,7 @@ class Parameter(BaseModel):
|
|
|
365
364
|
da = xr.DataArray(name=self.name, data=data, attrs=attrs, dims=dimensions, coords=coords)
|
|
366
365
|
# copying the coordinate metadata, if present, to the new DataArray coordinates
|
|
367
366
|
if coords:
|
|
368
|
-
for key in [k for k in coords
|
|
367
|
+
for key in [k for k in coords if isinstance(coords[k], xr.DataArray)]:
|
|
369
368
|
da[key].attrs = coords[key].attrs
|
|
370
369
|
return da
|
|
371
370
|
|
|
@@ -474,7 +473,7 @@ class Setting(BaseModel):
|
|
|
474
473
|
return self.parameter.unit
|
|
475
474
|
|
|
476
475
|
@property
|
|
477
|
-
def element_indices(self) ->
|
|
476
|
+
def element_indices(self) -> int | list[int] | None:
|
|
478
477
|
"""Element-wise indices of the parameter in ``self``."""
|
|
479
478
|
return self.parameter.element_indices
|
|
480
479
|
|
|
@@ -483,15 +482,14 @@ class Setting(BaseModel):
|
|
|
483
482
|
return next((setting for setting in values if setting.parameter.name == name), None)
|
|
484
483
|
|
|
485
484
|
@staticmethod
|
|
486
|
-
def remove_by_name(name: str, values: set[Setting]
|
|
487
|
-
if values is None:
|
|
488
|
-
values = set()
|
|
485
|
+
def remove_by_name(name: str, values: set[Setting]) -> set[Setting]:
|
|
489
486
|
removed = copy.deepcopy(values)
|
|
490
|
-
|
|
487
|
+
if setting := Setting.get_by_name(name, values):
|
|
488
|
+
removed.discard(setting)
|
|
491
489
|
return removed
|
|
492
490
|
|
|
493
491
|
@staticmethod
|
|
494
|
-
def replace(settings: Setting | list[Setting], values: set[Setting] = None) -> set[Setting]:
|
|
492
|
+
def replace(settings: Setting | list[Setting], values: set[Setting] | None = None) -> set[Setting]:
|
|
495
493
|
if values is None:
|
|
496
494
|
values = set()
|
|
497
495
|
if not isinstance(settings, list):
|
|
@@ -518,7 +516,7 @@ class Setting(BaseModel):
|
|
|
518
516
|
diff = first.difference(second)
|
|
519
517
|
for s in first.intersection(second):
|
|
520
518
|
a, b = [Setting.get_by_name(s.parameter.name, group) for group in [first, second]]
|
|
521
|
-
if a.value != b.value:
|
|
519
|
+
if a is not None and b is not None and a.value != b.value:
|
|
522
520
|
diff.add(a)
|
|
523
521
|
return diff
|
|
524
522
|
|
|
@@ -555,7 +553,7 @@ class Setting(BaseModel):
|
|
|
555
553
|
def __hash__(self):
|
|
556
554
|
return hash(self.parameter)
|
|
557
555
|
|
|
558
|
-
def __eq__(self, other:
|
|
556
|
+
def __eq__(self, other: Any) -> bool:
|
|
559
557
|
if not (isinstance(other, Setting) and self.parameter == other.parameter):
|
|
560
558
|
return False
|
|
561
559
|
if isinstance(self.value, np.ndarray):
|
|
@@ -224,12 +224,12 @@ from exa.common.qcm_data.chip_topology import sort_components
|
|
|
224
224
|
logger = logging.getLogger(__name__)
|
|
225
225
|
|
|
226
226
|
|
|
227
|
-
def _fix_path_recursive(node: SettingNode
|
|
227
|
+
def _fix_path_recursive(node: SettingNode, path: str) -> SettingNode:
|
|
228
228
|
"""Recursively travel the settings tree and fix the ``path``attribute (also aligns ``name``,
|
|
229
229
|
based on the node type). Deep copies all the child nodes.
|
|
230
230
|
"""
|
|
231
|
-
settings = {}
|
|
232
|
-
subtrees = {}
|
|
231
|
+
settings: dict[str, Setting] = {}
|
|
232
|
+
subtrees: dict[str, SettingNode] = {}
|
|
233
233
|
for key, setting in node.settings.items():
|
|
234
234
|
child_path = f"{path}.{key}"
|
|
235
235
|
update_dict = {"path": child_path}
|
|
@@ -305,8 +305,8 @@ class SettingNode(BaseModel):
|
|
|
305
305
|
generate_paths: bool = True,
|
|
306
306
|
**kwargs,
|
|
307
307
|
):
|
|
308
|
-
settings
|
|
309
|
-
subtrees
|
|
308
|
+
settings = settings or {}
|
|
309
|
+
subtrees = subtrees or {}
|
|
310
310
|
|
|
311
311
|
for key, child in kwargs.items():
|
|
312
312
|
if isinstance(child, Setting):
|
|
@@ -650,7 +650,7 @@ class SettingNode(BaseModel):
|
|
|
650
650
|
append_lines(self, lines, [])
|
|
651
651
|
print("\n", "\n".join(lines))
|
|
652
652
|
|
|
653
|
-
def __eq__(self, other:
|
|
653
|
+
def __eq__(self, other: Any) -> bool:
|
|
654
654
|
return isinstance(other, SettingNode) and (
|
|
655
655
|
(self.name, self.settings, self.subtrees) == (other.name, other.settings, other.subtrees)
|
|
656
656
|
)
|
|
@@ -708,9 +708,12 @@ class SettingNode(BaseModel):
|
|
|
708
708
|
else:
|
|
709
709
|
self.settings[key] = self.settings[key].update(value)
|
|
710
710
|
|
|
711
|
-
def setting_with_path_name(self, setting: Setting) -> Setting:
|
|
711
|
+
def setting_with_path_name(self, setting: Setting) -> Setting | None:
|
|
712
712
|
"""Get a copy of a setting with its name replaced with the path name."""
|
|
713
|
-
|
|
713
|
+
first_item = self.find_by_name(setting.name)
|
|
714
|
+
if isinstance(first_item, Setting):
|
|
715
|
+
return first_item.with_path_name()
|
|
716
|
+
return None
|
|
714
717
|
|
|
715
718
|
def diff(self, other: SettingNode, *, path: str = "") -> list[str]:
|
|
716
719
|
"""Recursive diff between two SettingNodes.
|
|
@@ -888,7 +891,7 @@ class SettingNode(BaseModel):
|
|
|
888
891
|
latest_node[fragment] = SettingNode(name=fragment, align_name=latest_node.align_name)
|
|
889
892
|
latest_node = latest_node[fragment]
|
|
890
893
|
# finally add the nodes
|
|
891
|
-
nodes_to_add = nodes.values() if isinstance(nodes, dict) else nodes
|
|
894
|
+
nodes_to_add: Iterable[Setting | Parameter | SettingNode] = nodes.values() if isinstance(nodes, dict) else nodes
|
|
892
895
|
nodes_keys = list(nodes.keys()) if isinstance(nodes, dict) else []
|
|
893
896
|
for idx, node in enumerate(nodes_to_add):
|
|
894
897
|
key = nodes_keys[idx] if isinstance(nodes, dict) else node.name.split(".")[-1]
|
|
@@ -926,10 +929,7 @@ class SettingNode(BaseModel):
|
|
|
926
929
|
):
|
|
927
930
|
if isinstance(locus, str):
|
|
928
931
|
locus = locus.split("__")
|
|
929
|
-
if gate_settings.symmetric.value
|
|
930
|
-
loci = list(permutations(locus))
|
|
931
|
-
else:
|
|
932
|
-
loci = [tuple(locus)]
|
|
932
|
+
loci = list(permutations(locus)) if gate_settings.symmetric.value else [tuple(locus)]
|
|
933
933
|
for permuted_locus in loci:
|
|
934
934
|
locus_str = "__".join(permuted_locus)
|
|
935
935
|
if locus_str in gate_settings[impl].override_default_for_loci.value:
|
|
@@ -987,7 +987,7 @@ class SettingNode(BaseModel):
|
|
|
987
987
|
The locus node (string) paths corresponding to this gate.
|
|
988
988
|
|
|
989
989
|
"""
|
|
990
|
-
node_paths = []
|
|
990
|
+
node_paths: list[str] = []
|
|
991
991
|
if "gates" not in self.children or gate not in self.gates.children:
|
|
992
992
|
return node_paths
|
|
993
993
|
if implementations is not None:
|
|
@@ -1034,7 +1034,7 @@ class SettingNode(BaseModel):
|
|
|
1034
1034
|
|
|
1035
1035
|
raise ValueError(f"Locus {locus} cannot be found in the gate properties characterization settings.")
|
|
1036
1036
|
|
|
1037
|
-
def _get_symmetric_loci(self, gate: str, implementation: str, locus: str) -> list[str]:
|
|
1037
|
+
def _get_symmetric_loci(self, gate: str, implementation: str, locus: str | Iterable[str]) -> list[str]:
|
|
1038
1038
|
if not isinstance(locus, str):
|
|
1039
1039
|
if self.gate_definitions[gate][implementation].symmetric.value:
|
|
1040
1040
|
str_loci = ["__".join(sort_components(locus))]
|
|
@@ -13,13 +13,15 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
|
|
16
|
+
from collections.abc import Hashable
|
|
17
|
+
|
|
16
18
|
import xarray as xr
|
|
17
19
|
|
|
18
20
|
"""Helper methods for data manipulation.
|
|
19
21
|
"""
|
|
20
22
|
|
|
21
23
|
|
|
22
|
-
def add_data_array(ds: xr.Dataset, da: xr.DataArray, name:
|
|
24
|
+
def add_data_array(ds: xr.Dataset, da: xr.DataArray, name: Hashable | None = None) -> xr.Dataset:
|
|
23
25
|
"""Add data array `da` to dataset `ds`.
|
|
24
26
|
|
|
25
27
|
Unlike the default xarray command, preserves metadata of the dataset.
|
|
@@ -50,7 +52,7 @@ def add_data_array(ds: xr.Dataset, da: xr.DataArray, name: str | None = None) ->
|
|
|
50
52
|
ds[name] = da
|
|
51
53
|
for key in ds.coords:
|
|
52
54
|
if attributes.get(key):
|
|
53
|
-
ds.coords[key].attrs = attributes.get(key)
|
|
55
|
+
ds.coords[key].attrs = attributes.get(key) # type:ignore[assignment]
|
|
54
56
|
for key in ds.data_vars:
|
|
55
57
|
if attributes.get(key):
|
|
56
58
|
ds.data_vars[key].attrs = attributes[key]
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/helpers/software_version_helper.py
RENAMED
|
@@ -30,7 +30,7 @@ def _is_editable(pkg_name: str) -> bool:
|
|
|
30
30
|
``importlib.metadata``, so it might break anytime.
|
|
31
31
|
"""
|
|
32
32
|
dist = distribution(pkg_name)
|
|
33
|
-
return dist.files and dist.files[0].name.startswith("__editable__.")
|
|
33
|
+
return dist.files is not None and dist.files[0].name.startswith("__editable__.")
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def get_all_software_versions(reload_module: bool = False) -> dict[str, str]:
|
|
@@ -17,13 +17,14 @@
|
|
|
17
17
|
from collections.abc import Collection
|
|
18
18
|
from functools import cached_property
|
|
19
19
|
import re
|
|
20
|
+
from typing import Any
|
|
20
21
|
|
|
21
22
|
from pydantic import Field, field_validator
|
|
22
23
|
|
|
23
24
|
from exa.common.qcm_data.immutable_base_model import ImmutableBaseModel
|
|
24
25
|
|
|
25
26
|
|
|
26
|
-
def _natural_sort_key(name: str) -> tuple[int, ...]:
|
|
27
|
+
def _natural_sort_key(name: str) -> tuple[int | str | Any, ...]:
|
|
27
28
|
return tuple(int(item) if item.isdigit() else item.lower() for item in re.split(r"(\d+)", name))
|
|
28
29
|
|
|
29
30
|
|
|
@@ -76,7 +77,7 @@ class Components(ImmutableBaseModel):
|
|
|
76
77
|
|
|
77
78
|
@cached_property
|
|
78
79
|
def all(self) -> dict[str, Component]:
|
|
79
|
-
components: tuple[Qubit
|
|
80
|
+
components: tuple[Qubit | Coupler | ProbeLine | Launcher | ComputationalResonator, ...] = (
|
|
80
81
|
self.qubits + self.couplers + self.probe_lines + self.launchers + self.computational_resonators
|
|
81
82
|
)
|
|
82
83
|
return {component.name: component for component in components}
|
|
@@ -109,7 +109,7 @@ class ChipTopology:
|
|
|
109
109
|
coupler: tuple(sort_components(components)) for coupler, components in couplers.items()
|
|
110
110
|
}
|
|
111
111
|
"""Map from each coupler to all other components it connects to. The values are sorted."""
|
|
112
|
-
component_to_couplers = {}
|
|
112
|
+
component_to_couplers: dict = {}
|
|
113
113
|
for coupler, components in couplers.items():
|
|
114
114
|
for c in components:
|
|
115
115
|
component_to_couplers.setdefault(c, set()).add(coupler)
|
|
@@ -128,7 +128,7 @@ class ChipTopology:
|
|
|
128
128
|
Components without connection to a probe line don't appear.
|
|
129
129
|
"""
|
|
130
130
|
|
|
131
|
-
self._locus_mappings: dict[
|
|
131
|
+
self._locus_mappings: dict[str, dict[Locus, tuple[str, ...]]] = {
|
|
132
132
|
DEFAULT_1QB_MAPPING: {(qubit,): (qubit,) for qubit in self.qubits_sorted},
|
|
133
133
|
DEFAULT_2QB_MAPPING: {
|
|
134
134
|
frozenset(comps): (coupler,)
|
|
@@ -244,7 +244,7 @@ class ChipTopology:
|
|
|
244
244
|
"""Get probelines that are connected to any of the given components."""
|
|
245
245
|
return {self.component_to_probe_line[c] for c in components if c in self.component_to_probe_line}
|
|
246
246
|
|
|
247
|
-
def get_connected_coupler_map(self, components: Collection[str]) ->
|
|
247
|
+
def get_connected_coupler_map(self, components: Collection[str]) -> dict[str, tuple[str, ...]]:
|
|
248
248
|
"""Returns a `ComponentMap`, including only the couplers between components that both are in the given subset.
|
|
249
249
|
|
|
250
250
|
Args:
|
|
@@ -261,7 +261,7 @@ class ChipTopology:
|
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
@staticmethod
|
|
264
|
-
def limit_values(dct: ComponentMap, limit_to: Collection[str]) ->
|
|
264
|
+
def limit_values(dct: ComponentMap, limit_to: Collection[str]) -> dict[str, Collection[str]]:
|
|
265
265
|
"""Prunes the given dictionary (e.g. a coupler-to-qubits map) to a subset of values.
|
|
266
266
|
|
|
267
267
|
Used to prune e.g. :attr:`coupler_to_components` to a subset of relevant elements.
|
|
@@ -313,7 +313,7 @@ class ChipTopology:
|
|
|
313
313
|
self._validate_locus_mapping(mapping)
|
|
314
314
|
self._locus_mappings[name] = mapping
|
|
315
315
|
|
|
316
|
-
def _validate_locus_mapping(self, mapping: dict[
|
|
316
|
+
def _validate_locus_mapping(self, mapping: dict[Locus, tuple[str, ...]]) -> None:
|
|
317
317
|
"""Validate that the components given in mapping are found in self and the mapping is correctly formed."""
|
|
318
318
|
for locus, mapped in mapping.items():
|
|
319
319
|
if not isinstance(locus, tuple) and not isinstance(locus, frozenset):
|
|
@@ -325,7 +325,7 @@ class ChipTopology:
|
|
|
325
325
|
if locus_component not in self.all_components:
|
|
326
326
|
raise ValueError(f"Locus component {locus_component} is not found in this ChipTopology.")
|
|
327
327
|
|
|
328
|
-
def map_locus(self, locus: Locus, name: str | None = None) -> str | tuple[str] | None:
|
|
328
|
+
def map_locus(self, locus: Locus, name: str | None = None) -> str | tuple[str, ...] | None:
|
|
329
329
|
"""Returns the mapped components for the given locus and the given gate.
|
|
330
330
|
|
|
331
331
|
If the locus or the gate is not found from the locus mappings of self, returns None.
|
|
@@ -388,7 +388,7 @@ class ChipTopology:
|
|
|
388
388
|
name = DEFAULT_1QB_MAPPING
|
|
389
389
|
elif default_mapping_dimension == 2:
|
|
390
390
|
name = DEFAULT_2QB_MAPPING
|
|
391
|
-
return
|
|
391
|
+
return list(self._locus_mappings.get(name, {}))
|
|
392
392
|
|
|
393
393
|
def get_common_computational_resonator(self, first_qubit: str, second_qubit: str) -> str:
|
|
394
394
|
"""Convenience method for getting the name of a computational resonator which is connected to both specified
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/qcm_data/qcm_data_client.py
RENAMED
|
@@ -62,7 +62,7 @@ class QCMDataClient:
|
|
|
62
62
|
# Make the cache containers local to the instances so that the reference from cache to the instance
|
|
63
63
|
# gets scraped off with the instance
|
|
64
64
|
# https://rednafi.github.io/reflections/dont-wrap-instance-methods-with-functoolslru_cache-decorator-in-python.html
|
|
65
|
-
self._send_request = cache(self._send_request)
|
|
65
|
+
self._send_request = cache(self._send_request) # type:ignore[method-assign]
|
|
66
66
|
|
|
67
67
|
@property
|
|
68
68
|
def root_url(self) -> str:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: iqm-exa-common
|
|
3
|
-
Version: 26.
|
|
3
|
+
Version: 26.26.0
|
|
4
4
|
Summary: Framework for control and measurement of superconducting qubits: common library
|
|
5
5
|
Author-email: IQM Finland Oy <info@meetiqm.com>
|
|
6
6
|
License: Apache License
|
|
@@ -221,6 +221,7 @@ Requires-Dist: xarray==2024.10.0
|
|
|
221
221
|
Requires-Dist: requests==2.32.3
|
|
222
222
|
Requires-Dist: ruamel-yaml==0.17.32
|
|
223
223
|
Requires-Dist: ruamel-yaml-clib==0.2.8
|
|
224
|
+
Requires-Dist: jinja2==3.0.3
|
|
224
225
|
|
|
225
226
|
EXA-common
|
|
226
227
|
==========
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
26.26.0
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
26.24.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/_templates/autosummary-class-template.rst
RENAMED
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/docs/_templates/autosummary-module-template.rst
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/array.py
RENAMED
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/datum.py
RENAMED
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/nd_sweep.py
RENAMED
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/api/proto_serialization/sequence.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/exponential_sweep.py
RENAMED
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/fixed_sweep.py
RENAMED
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/linear_sweep.py
RENAMED
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/control/sweep/option/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/data/settingnode_v2.html.jinja2
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/errors/station_control_errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/qcm_data/immutable_base_model.py
RENAMED
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/exa/common/sweep/database_serialization.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{iqm_exa_common-26.24.0 → iqm_exa_common-26.26.0}/src/iqm_exa_common.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|