boulder-opal-scale-up-sdk 1.0.1__tar.gz → 1.0.3__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.
Files changed (64) hide show
  1. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/PKG-INFO +1 -1
  2. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/agent/worker.py +10 -5
  3. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/common/dtypes.py +15 -3
  4. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/common/typeclasses.py +22 -0
  5. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/__init__.py +1 -2
  6. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/common.py +0 -3
  7. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/config_loader.py +5 -2
  8. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/defcal.py +1 -0
  9. boulder_opal_scale_up_sdk-1.0.3/boulderopalscaleupsdk/device/device.py +25 -0
  10. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/processor/common.py +36 -14
  11. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/processor/superconducting_processor.py +19 -20
  12. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/__init__.py +6 -2
  13. boulder_opal_scale_up_sdk-1.0.1/boulderopalscaleupsdk/experiments/transmon_resonator_chi_scan.py → boulder_opal_scale_up_sdk-1.0.3/boulderopalscaleupsdk/experiments/chi01_scan.py +8 -3
  14. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/common.py +15 -0
  15. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/power_rabi.py +4 -3
  16. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/ramsey.py +7 -10
  17. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/readout_classifier_calibration.py +5 -1
  18. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/resonator_spectroscopy.py +5 -8
  19. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/resonator_spectroscopy_by_bias.py +6 -9
  20. boulder_opal_scale_up_sdk-1.0.3/boulderopalscaleupsdk/experiments/t1.py +54 -0
  21. boulder_opal_scale_up_sdk-1.0.3/boulderopalscaleupsdk/experiments/t2.py +48 -0
  22. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/transmon_anharmonicity.py +21 -17
  23. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/transmon_spectroscopy.py +8 -13
  24. boulder_opal_scale_up_sdk-1.0.3/boulderopalscaleupsdk/protobuf/v1/device_pb2.py +89 -0
  25. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/device_pb2.pyi +10 -2
  26. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/task_pb2.py +16 -16
  27. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/task_pb2.pyi +4 -2
  28. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/pyproject.toml +1 -1
  29. boulder_opal_scale_up_sdk-1.0.1/boulderopalscaleupsdk/device/device.py +0 -41
  30. boulder_opal_scale_up_sdk-1.0.1/boulderopalscaleupsdk/protobuf/v1/device_pb2.py +0 -89
  31. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/LICENSE +0 -0
  32. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/README.md +0 -0
  33. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/__init__.py +0 -0
  34. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/agent/__init__.py +0 -0
  35. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/common/__init__.py +0 -0
  36. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/__init__.py +0 -0
  37. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/base.py +0 -0
  38. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/qblox.py +0 -0
  39. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/quantum_machines.py +0 -0
  40. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/controller/resolver.py +0 -0
  41. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/device/processor/__init__.py +0 -0
  42. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/experiments/resonator_spectroscopy_by_power.py +0 -0
  43. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/grpc_interceptors/__init__.py +0 -0
  44. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/grpc_interceptors/auth.py +0 -0
  45. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/plotting/__init__.py +0 -0
  46. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/plotting/dtypes.py +0 -0
  47. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/agent_pb2.py +0 -0
  48. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/agent_pb2.pyi +0 -0
  49. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/agent_pb2_grpc.py +0 -0
  50. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/device_pb2_grpc.py +0 -0
  51. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/protobuf/v1/task_pb2_grpc.py +0 -0
  52. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/py.typed +0 -0
  53. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/routines/__init__.py +0 -0
  54. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/routines/common.py +0 -0
  55. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/routines/resonator_mapping.py +0 -0
  56. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/stubs/__init__.py +0 -0
  57. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/stubs/dtypes.py +0 -0
  58. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/stubs/maps.py +0 -0
  59. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/third_party/__init__.py +0 -0
  60. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/third_party/quantum_machines/__init__.py +0 -0
  61. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/third_party/quantum_machines/config.py +0 -0
  62. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/third_party/quantum_machines/constants.py +0 -0
  63. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/utils/__init__.py +0 -0
  64. {boulder_opal_scale_up_sdk-1.0.1 → boulder_opal_scale_up_sdk-1.0.3}/boulderopalscaleupsdk/utils/serial_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: boulder-opal-scale-up-sdk
3
- Version: 1.0.1
3
+ Version: 1.0.3
4
4
  Summary: Q-CTRL Boulder Opal Scale Up Python SDK
5
5
  License: https://q-ctrl.com/terms
6
6
  Keywords: black opal,boulder opal,fire opal,nisq,open controls,q control,q ctrl,q-control,q-ctrl,qcontrol,qctrl,quantum,quantum algorithms,quantum circuits,quantum coding,quantum coding software,quantum computing,quantum control,quantum control software,quantum control theory,quantum engineering,quantum error correction,quantum firmware,quantum fundamentals,quantum sensing,qubit,qudit
@@ -27,7 +27,7 @@ from grpc import aio as grpc
27
27
  from grpc import ssl_channel_credentials
28
28
  from pydantic_settings import BaseSettings, SettingsConfigDict
29
29
 
30
- from boulderopalscaleupsdk.common.dtypes import GrpcMetadata
30
+ from boulderopalscaleupsdk.common.dtypes import GrpcMetadata, JobId
31
31
  from boulderopalscaleupsdk.protobuf.v1 import agent_pb2, task_pb2, task_pb2_grpc
32
32
 
33
33
  LOG = logging.getLogger(__name__)
@@ -178,7 +178,7 @@ class Agent:
178
178
  device_name: str,
179
179
  routine: str,
180
180
  data: Struct | None,
181
- ) -> str:
181
+ ) -> JobId | None:
182
182
  if not self._channel:
183
183
  raise RuntimeError("Cannot start session: agent is shutdown.")
184
184
  _data = any_pb2.Any()
@@ -196,16 +196,18 @@ class Agent:
196
196
  metadata=metadata,
197
197
  )
198
198
  self._state = response.target_state
199
- await self._resume(response, metadata)
199
+ job_id: JobId | None = await self._resume(response, metadata)
200
200
  await self.shutdown()
201
- return response.session_id
201
+
202
+ return job_id
202
203
 
203
204
  async def _resume(
204
205
  self,
205
206
  response: task_pb2.AgentTasksResponse,
206
207
  metadata: GrpcMetadata,
207
- ) -> None:
208
+ ) -> JobId | None:
208
209
  tasks = response.tasks
210
+ job_id = None
209
211
  while self._state not in [
210
212
  task_pb2.AGENT_STATE_SHUTDOWN_MANAGER_INITIATED,
211
213
  task_pb2.AGENT_STATE_SHUTDOWN_FAULT,
@@ -243,6 +245,9 @@ class Agent:
243
245
 
244
246
  tasks = _resp.tasks
245
247
  self._state = _resp.target_state
248
+ job_id = _resp.job_id
249
+
250
+ return job_id or response.job_id
246
251
 
247
252
  async def shutdown(
248
253
  self,
@@ -13,6 +13,7 @@
13
13
 
14
14
  from __future__ import annotations
15
15
 
16
+ import enum
16
17
  from typing import overload
17
18
 
18
19
  __all__ = [
@@ -23,7 +24,6 @@ __all__ = [
23
24
 
24
25
  from datetime import datetime, timedelta
25
26
  from decimal import Decimal
26
- from enum import Enum
27
27
  from typing import Annotated, Any, Literal, Self
28
28
 
29
29
  import numpy as np
@@ -33,11 +33,13 @@ from pydantic.dataclasses import dataclass
33
33
 
34
34
  GrpcMetadata = list[tuple[str, str | bytes]]
35
35
 
36
+ JobId = str
37
+
36
38
 
37
39
  class BaseType: ...
38
40
 
39
41
 
40
- class FrequencyUnit(str, Enum):
42
+ class FrequencyUnit(str, enum.Enum):
41
43
  Hz = "Hz"
42
44
 
43
45
 
@@ -115,7 +117,7 @@ class Frequency:
115
117
  return self.__mul__(lhs)
116
118
 
117
119
 
118
- class TimeUnit(str, Enum):
120
+ class TimeUnit(str, enum.Enum):
119
121
  S = "s"
120
122
  MS = "ms"
121
123
  US = "us"
@@ -308,3 +310,13 @@ ISO8601DatetimeUTCLike = Annotated[
308
310
  BeforeValidator(_validate_iso_datetime),
309
311
  PlainSerializer(_serialize_datetime),
310
312
  ]
313
+
314
+
315
+ class JobHistorySortOrder(enum.Enum):
316
+ CREATED_AT_DESC = 1
317
+ CREATED_AT_ASC = 2
318
+
319
+
320
+ DEFAULT_JOB_HISTORY_PAGE = 1
321
+ DEFAULT_JOB_HISTORY_PAGE_SIZE = 10
322
+ DEFAULT_JOB_HISTORY_SORT_ORDER = JobHistorySortOrder.CREATED_AT_DESC
@@ -83,3 +83,25 @@ class Combine(Protocol[T]):
83
83
  return destination
84
84
 
85
85
  return Combine.create(_combine)
86
+
87
+
88
+ class Eq(Protocol[T]):
89
+ @abstractmethod
90
+ def eq(self, first: T, second: T) -> bool: ...
91
+
92
+ def eq_option(self, first: T | None, second: T | None) -> bool:
93
+ match first, second:
94
+ case None, None:
95
+ return True
96
+ case _ if first is not None and second is not None:
97
+ return self.eq(first, second)
98
+ case _:
99
+ return False
100
+
101
+ @classmethod
102
+ def create(cls, eq_fn: Callable[[T, T], bool]) -> "Eq[T]":
103
+ class _Eq(Eq):
104
+ def eq(self, first: T, second: T) -> bool:
105
+ return eq_fn(first, second)
106
+
107
+ return _Eq()
@@ -11,10 +11,9 @@
11
11
  # distributed under the License is distributed on an "AS IS" BASIS. See the
12
12
  # License for the specific language.
13
13
 
14
- __all__ = ["Device", "InvalidDevice", "InvalidDeviceComponent"]
14
+ __all__ = ["InvalidDevice", "InvalidDeviceComponent"]
15
15
 
16
16
  from boulderopalscaleupsdk.device.device import (
17
- Device,
18
17
  InvalidDevice,
19
18
  InvalidDeviceComponent,
20
19
  )
@@ -23,9 +23,6 @@ ExtraType = JsonDict | Callable[[JsonDict], None] | None
23
23
  ComponentRef = str
24
24
 
25
25
 
26
- class Processor(BaseModel): ...
27
-
28
-
29
26
  class Component(BaseModel, Generic[TraitT]):
30
27
  traits: list[TraitT]
31
28
 
@@ -52,9 +52,12 @@ class DeviceConfigLoader:
52
52
  layout_file = device_config_data.pop("layout_file", None)
53
53
  if layout_file is None:
54
54
  raise ValueError("Layout file is missing from device configuration data.")
55
- self._validate_file_is_filename(layout_file)
56
55
 
57
- layout_path = self.config_path.parent / layout_file
56
+ layout_path = Path(layout_file)
57
+ if not layout_path.is_absolute():
58
+ self._validate_file_is_filename(layout_path.name)
59
+ layout_path = self.config_path.parent / layout_file
60
+
58
61
  device_layout_data = self._load_yaml_file(layout_path)
59
62
 
60
63
  processed_device_config = {**device_config_data, **device_layout_data}
@@ -59,3 +59,4 @@ DataKeyLike = Annotated[
59
59
  class DefCalData:
60
60
  body: str
61
61
  status: Literal["calibrated", "uncalibrated"]
62
+ scope: Literal["public", "internal"]
@@ -0,0 +1,25 @@
1
+ # Copyright 2025 Q-CTRL. All rights reserved.
2
+ #
3
+ # Licensed under the Q-CTRL Terms of service (the "License"). Unauthorized
4
+ # copying or use of this file, via any medium, is strictly prohibited.
5
+ # Proprietary and confidential. You may not use this file except in compliance
6
+ # with the License. You may obtain a copy of the License at
7
+ #
8
+ # https://q-ctrl.com/terms
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS. See the
12
+ # License for the specific language.
13
+
14
+
15
+ from pydantic.dataclasses import dataclass
16
+
17
+
18
+ @dataclass
19
+ class InvalidDevice:
20
+ message: str
21
+
22
+
23
+ @dataclass
24
+ class InvalidDeviceComponent:
25
+ message: str
@@ -25,7 +25,7 @@ from boulderopalscaleupsdk.common.dtypes import (
25
25
  Frequency,
26
26
  ISO8601DatetimeUTCLike,
27
27
  )
28
- from boulderopalscaleupsdk.common.typeclasses import Combine
28
+ from boulderopalscaleupsdk.common.typeclasses import Combine, Eq
29
29
 
30
30
  T = TypeVar("T")
31
31
  T2 = TypeVar("T2")
@@ -97,23 +97,40 @@ class ComponentParameter(Generic[T]):
97
97
  @staticmethod
98
98
  def combine(
99
99
  combine_instance: Combine[T],
100
+ eq_instance: Eq[T],
100
101
  ) -> "Combine[ComponentParameter[T]]":
101
102
  def _combine(
102
103
  first: ComponentParameter[T],
103
104
  other: ComponentParameter[Any],
104
105
  ) -> ComponentParameter[T]:
106
+ _value = combine_instance.combine(first.value, other.value)
107
+ _err_minus = combine_instance.combine_option(
108
+ first.err_minus,
109
+ other.err_minus,
110
+ )
111
+ _err_plus = combine_instance.combine_option(
112
+ first.err_plus,
113
+ other.err_plus,
114
+ )
115
+ _calibration_status = other.calibration_status
116
+
117
+ _updated_at: ISO8601DatetimeUTCLike | None
118
+ if (
119
+ not eq_instance.eq(_value, first.value)
120
+ or not eq_instance.eq_option(_err_minus, first.err_minus)
121
+ or not eq_instance.eq_option(_err_plus, first.err_plus)
122
+ or _calibration_status != first.calibration_status
123
+ ):
124
+ _updated_at = datetime.now(tz=UTC)
125
+ else:
126
+ _updated_at = first.updated_at
127
+
105
128
  return ComponentParameter(
106
- value=combine_instance.combine(first.value, other.value),
107
- err_minus=combine_instance.combine_option(
108
- first.err_minus,
109
- other.err_minus,
110
- ),
111
- err_plus=combine_instance.combine_option(
112
- first.err_plus,
113
- other.err_plus,
114
- ),
115
- calibration_status=other.calibration_status,
116
- updated_at=datetime.now(tz=UTC),
129
+ value=_value,
130
+ err_minus=_err_minus,
131
+ err_plus=_err_plus,
132
+ calibration_status=_calibration_status,
133
+ updated_at=_updated_at,
117
134
  )
118
135
 
119
136
  return Combine[ComponentParameter[T]].create(_combine)
@@ -127,8 +144,13 @@ class ComponentParameter(Generic[T]):
127
144
  updated_at=self.updated_at,
128
145
  )
129
146
 
130
- def merge_with(self, other: "ComponentParameter[T]", combine_value: "Combine[T]"):
131
- combined = ComponentParameter[T].combine(combine_value).combine(self, other)
147
+ def merge_with(
148
+ self,
149
+ other: "ComponentParameter[T]",
150
+ combine_value: "Combine[T]",
151
+ eq_value: Eq[T],
152
+ ):
153
+ combined = ComponentParameter[T].combine(combine_value, eq_value).combine(self, other)
132
154
  self.value = combined.value
133
155
  self.err_minus = combined.err_minus
134
156
  self.err_plus = combined.err_plus
@@ -23,7 +23,6 @@ from boulderopalscaleupsdk.common.dtypes import (
23
23
  from boulderopalscaleupsdk.device.common import (
24
24
  Component,
25
25
  ComponentRef,
26
- Processor,
27
26
  )
28
27
  from boulderopalscaleupsdk.device.processor import (
29
28
  ComponentParameter,
@@ -37,12 +36,12 @@ class Transmon(Component[Literal["tunable"]]):
37
36
  dtype: Literal["transmon"] = "transmon"
38
37
  traits: list[Literal["tunable"]] = Field(default=["tunable"])
39
38
 
40
- freq_01: FloatComponentParameter | None = Field(
41
- default=None,
39
+ freq_01: FloatComponentParameter = Field(
40
+ default=ComponentParameter(value=(0.0)),
42
41
  json_schema_extra={"display": {"label": "freq_01", "unit": "MHz", "scale": 1e-6}},
43
42
  )
44
- anharm: FloatComponentParameter | None = Field(
45
- default=None,
43
+ anharm: FloatComponentParameter = Field(
44
+ default=ComponentParameter(value=0.0),
46
45
  json_schema_extra={"display": {"label": "anharm", "unit": "MHz", "scale": 1e-6}},
47
46
  )
48
47
  t1: DurationComponentParameter = Field(
@@ -71,9 +70,9 @@ class Transmon(Component[Literal["tunable"]]):
71
70
  default=ComponentParameter(value=0.0),
72
71
  json_schema_extra={"display": {"label": "dc_bias", "unit": "V", "scale": 1}},
73
72
  )
74
- fmax_bias: FloatComponentParameter = Field(
73
+ bias_offset: FloatComponentParameter = Field(
75
74
  default=ComponentParameter(value=0.0),
76
- json_schema_extra={"display": {"label": "fmax_bias", "unit": "V", "scale": 1}},
75
+ json_schema_extra={"display": {"label": "bias_offset", "unit": "V", "scale": 1}},
77
76
  )
78
77
  bias_period: FloatComponentParameter = Field(
79
78
  default=ComponentParameter(value=0.0),
@@ -81,24 +80,24 @@ class Transmon(Component[Literal["tunable"]]):
81
80
  )
82
81
 
83
82
 
84
- class Resonator(Component[Literal["dispersive"]]):
83
+ class Resonator(Component[Literal["readout"]]):
85
84
  dtype: Literal["resonator"] = "resonator"
86
- traits: list[Literal["dispersive"]] = Field(default=["dispersive"])
85
+ traits: list[Literal["readout"]] = Field(default=["readout"])
87
86
 
88
- frequency_high: FloatComponentParameter | None = Field(
89
- default=None,
87
+ frequency_high: FloatComponentParameter = Field(
88
+ default=ComponentParameter(value=0.0),
90
89
  json_schema_extra={"display": {"label": "frequency_high", "unit": "MHz", "scale": 1e-6}},
91
90
  )
92
- frequency_low: FloatComponentParameter | None = Field(
93
- default=None,
91
+ frequency_low: FloatComponentParameter = Field(
92
+ default=ComponentParameter(value=0.0),
94
93
  json_schema_extra={"display": {"label": "frequency_low", "unit": "MHz", "scale": 1e-6}},
95
94
  )
96
- kappa_low: FloatComponentParameter | None = Field(
97
- default=None,
95
+ kappa_low: FloatComponentParameter = Field(
96
+ default=ComponentParameter(value=0.0),
98
97
  json_schema_extra={"display": {"label": "kappa_low", "unit": "MHz", "scale": 1e-6}},
99
98
  )
100
- kappa_high: FloatComponentParameter | None = Field(
101
- default=None,
99
+ kappa_high: FloatComponentParameter = Field(
100
+ default=ComponentParameter(value=0.0),
102
101
  json_schema_extra={"display": {"label": "kappa_high", "unit": "MHz", "scale": 1e-6}},
103
102
  )
104
103
  vp_low: FloatComponentParameter = Field(
@@ -128,9 +127,9 @@ class Coupler(Component[Literal["tunable"]]):
128
127
  default=ComponentParameter(value=0.0),
129
128
  json_schema_extra={"display": {"label": "dc_bias", "unit": "V", "scale": 1}},
130
129
  )
131
- fmax_bias: FloatComponentParameter = Field(
130
+ bias_offset: FloatComponentParameter = Field(
132
131
  default=ComponentParameter(value=0.0),
133
- json_schema_extra={"display": {"label": "fmax_bias", "unit": "V", "scale": 1}},
132
+ json_schema_extra={"display": {"label": "bias_offset", "unit": "V", "scale": 1}},
134
133
  )
135
134
  bias_period: FloatComponentParameter = Field(
136
135
  default=ComponentParameter(value=0.0),
@@ -182,7 +181,7 @@ class SuperconductingProcessorTemplate(BaseModel):
182
181
  )
183
182
 
184
183
 
185
- class SuperconductingProcessor(Processor):
184
+ class SuperconductingProcessor(BaseModel):
186
185
  nodes: dict[ComponentRef, SuperconductingComponentType]
187
186
  edges: list[Edge]
188
187
 
@@ -14,7 +14,10 @@
14
14
  """Experiment library."""
15
15
 
16
16
  __all__ = [
17
+ "T1",
18
+ "T2",
17
19
  "CWSIterable",
20
+ "Chi01Scan",
18
21
  "ConstantWaveform",
19
22
  "Experiment",
20
23
  "GaussianWaveform",
@@ -28,10 +31,10 @@ __all__ = [
28
31
  "ResonatorSpectroscopyByBias",
29
32
  "ResonatorSpectroscopyByPower",
30
33
  "TransmonAnharmonicity",
31
- "TransmonResonatorChiScan",
32
34
  "TransmonSpectroscopy",
33
35
  ]
34
36
 
37
+ from .chi01_scan import Chi01Scan
35
38
  from .common import (
36
39
  ConstantWaveform,
37
40
  CWSIterable,
@@ -47,6 +50,7 @@ from .readout_classifier_calibration import ReadoutClassifierCalibration
47
50
  from .resonator_spectroscopy import ResonatorSpectroscopy
48
51
  from .resonator_spectroscopy_by_bias import ResonatorSpectroscopyByBias
49
52
  from .resonator_spectroscopy_by_power import ResonatorSpectroscopyByPower
53
+ from .t1 import T1
54
+ from .t2 import T2
50
55
  from .transmon_anharmonicity import TransmonAnharmonicity
51
- from .transmon_resonator_chi_scan import TransmonResonatorChiScan
52
56
  from .transmon_spectroscopy import TransmonSpectroscopy
@@ -13,7 +13,8 @@
13
13
 
14
14
  from pydantic import PrivateAttr
15
15
 
16
- from boulderopalscaleupsdk.experiments.common import (
16
+ from .common import (
17
+ ConstantWaveform,
17
18
  CWSIterable,
18
19
  Experiment,
19
20
  HypIterable,
@@ -25,7 +26,7 @@ DEFAULT_RECYCLE_DELAY_NS = 10_000
25
26
  DEFAULT_SHOT_COUNT = 100
26
27
 
27
28
 
28
- class TransmonResonatorChiScan(Experiment):
29
+ class Chi01Scan(Experiment):
29
30
  """
30
31
  Parameters for running an experiment to find the dispersive shift for a transmon
31
32
  resonator pair.
@@ -44,9 +45,12 @@ class TransmonResonatorChiScan(Experiment):
44
45
  shot_count : int, optional
45
46
  The number of shots to be taken in the experiment.
46
47
  Defaults to 100.
48
+ measure_waveform : ConstantWaveform or None, optional
49
+ The waveform to use for the measurement pulse.
50
+ If not provided, the measurement defcal will be used.
47
51
  """
48
52
 
49
- _experiment_name: str = PrivateAttr("transmon_resonator_chi_scan")
53
+ _experiment_name: str = PrivateAttr("chi01_scan")
50
54
 
51
55
  transmon: str
52
56
  frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
@@ -54,3 +58,4 @@ class TransmonResonatorChiScan(Experiment):
54
58
  )
55
59
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
56
60
  shot_count: int = DEFAULT_SHOT_COUNT
61
+ measure_waveform: ConstantWaveform | None = None
@@ -56,6 +56,21 @@ class RangeIterable(_RangeIterable):
56
56
  step: float
57
57
 
58
58
 
59
+ class LogspaceIterable(_RangeIterable):
60
+ """A range of values spaced evenly on a log scale."""
61
+
62
+ dtype: Literal["logspace"] = "logspace"
63
+
64
+ # The starting value.
65
+ start: float
66
+ # The final value.
67
+ stop: float
68
+ # The number of values. Defaults to 101.
69
+ count: int = Field(default=101)
70
+ # Base of the logarithm
71
+ base: int = Field(default=10)
72
+
73
+
59
74
  class CWSIterable(_RangeIterable):
60
75
  """A range of linearly spaced values in center ± width/2."""
61
76
 
@@ -39,14 +39,15 @@ class PowerRabi(Experiment):
39
39
  The scaling factors for the drive pulse amplitude. If None, a default scan will be used.
40
40
  drive_waveform : GaussianWaveform
41
41
  The waveform to use for the drive pulse.
42
- measure_waveform : ConstantWaveform
43
- The waveform to use for the measurement pulse.
44
42
  recycle_delay_ns : int
45
43
  The delay time between consecutive shots of the experiment, in nanoseconds.
46
44
  shot_count : int, optional
47
45
  The number of shots to be taken in the experiment. Defaults to 400.
48
46
  pulse_vp : float, optional
49
47
  The voltage per pulse. If None, a default value will be used.
48
+ measure_waveform : ConstantWaveform or None, optional
49
+ The waveform to use for the measurement pulse.
50
+ If not provided, the measurement defcal will be used.
50
51
  """
51
52
 
52
53
  _experiment_name: str = PrivateAttr("power_rabi")
@@ -54,7 +55,7 @@ class PowerRabi(Experiment):
54
55
  transmon: str
55
56
  scales: list[float] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = None
56
57
  drive_waveform: GaussianWaveform
57
- measure_waveform: ConstantWaveform
58
58
  recycle_delay_ns: int
59
59
  shot_count: int = DEFAULT_SHOT_COUNT
60
60
  pulse_vp: float | None = None
61
+ measure_waveform: ConstantWaveform | None = None
@@ -13,7 +13,7 @@
13
13
 
14
14
  from pydantic import PrivateAttr
15
15
 
16
- from .common import Experiment
16
+ from .common import ConstantWaveform, Experiment
17
17
 
18
18
  DEFAULT_RECYCLE_DELAY_NS = 10_000
19
19
  DEFAULT_SHOT_COUNT = 400
@@ -34,19 +34,17 @@ class Ramsey(Experiment):
34
34
  The minimum delay time, in nanoseconds.
35
35
  delay_step_ns : int
36
36
  The step for generating the list of delays, in nanoseconds.
37
- detuning : float
37
+ virtual_detuning : float
38
38
  The difference between the drive signal frequency and the qubit frequency, in Hz.
39
- readout_amplitude : float
40
- The amplitude of the readout pulse.
41
- duration_ns : int, optional
42
- The duration of the pulse, in nanoseconds.
43
- Defaults to 2000 ns.
44
39
  recycle_delay_ns : int, optional
45
40
  The delay time between consecutive shots of the experiment, in nanoseconds.
46
41
  Defaults to 10000 ns.
47
42
  shot_count : int, optional
48
43
  The number of shots to be taken in the experiment.
49
44
  Defaults to 400.
45
+ measure_waveform : ConstantWaveform or None, optional
46
+ The waveform to use for the measurement pulse.
47
+ If not provided, the measurement defcal will be used.
50
48
  """
51
49
 
52
50
  _experiment_name: str = PrivateAttr("ramsey")
@@ -55,8 +53,7 @@ class Ramsey(Experiment):
55
53
  max_delay_ns: int
56
54
  min_delay_ns: int
57
55
  delay_step_ns: int
58
- detuning: float
59
- readout_amplitude: float
60
- duration_ns: int = DEFAULT_DURATION_NS
56
+ virtual_detuning: float
61
57
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
62
58
  shot_count: int = DEFAULT_SHOT_COUNT
59
+ measure_waveform: ConstantWaveform | None = None
@@ -1,6 +1,6 @@
1
1
  from pydantic import PrivateAttr
2
2
 
3
- from boulderopalscaleupsdk.experiments.common import Experiment
3
+ from .common import ConstantWaveform, Experiment
4
4
 
5
5
 
6
6
  class ReadoutClassifierCalibration(Experiment):
@@ -16,9 +16,13 @@ class ReadoutClassifierCalibration(Experiment):
16
16
  shot_count : int, optional
17
17
  The number of shots to be taken in the experiment.
18
18
  Defaults to 5000.
19
+ measure_waveform : ConstantWaveform or None, optional
20
+ The waveform to use for the measurement pulse.
21
+ If not provided, the measurement defcal will be used.
19
22
  """
20
23
 
21
24
  _experiment_name: str = PrivateAttr("readout_classifier_calibration")
22
25
  transmon: str
23
26
  recycle_delay_ns: int
24
27
  shot_count: int = 5000
28
+ measure_waveform: ConstantWaveform | None = None
@@ -14,6 +14,7 @@
14
14
  from pydantic import PrivateAttr
15
15
 
16
16
  from .common import (
17
+ ConstantWaveform,
17
18
  CWSIterable,
18
19
  Experiment,
19
20
  HypIterable,
@@ -38,18 +39,15 @@ class ResonatorSpectroscopy(Experiment):
38
39
  or HypIterable or None, optional
39
40
  The frequencies at which to scan.
40
41
  If None, frequencies around the readout frequency will be used.
41
- readout_amplitude : float, optional
42
- The amplitude of the readout pulse.
43
- If None, a default amplitude will be used.
44
- duration_ns : int, optional
45
- The duration of the readout pulse, in nanoseconds.
46
- Defaults to 2000 ns.
47
42
  recycle_delay_ns :int, optional
48
43
  The delay time between consecutive shots of the experiment, in nanoseconds.
49
44
  Defaults to 1000 ns.
50
45
  shot_count : int, optional
51
46
  The number of shots to be taken in the experiment.
52
47
  Defaults to 100.
48
+ measure_waveform : ConstantWaveform or None, optional
49
+ The waveform to use for the measurement pulse.
50
+ If not provided, the measurement defcal will be used.
53
51
  """
54
52
 
55
53
  _experiment_name: str = PrivateAttr("resonator_spectroscopy")
@@ -58,7 +56,6 @@ class ResonatorSpectroscopy(Experiment):
58
56
  frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
59
57
  None
60
58
  )
61
- readout_amplitude: float | None = None
62
- duration_ns: int = DEFAULT_DURATION_NS
63
59
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
64
60
  shot_count: int = DEFAULT_SHOT_COUNT
61
+ measure_waveform: ConstantWaveform | None = None
@@ -14,6 +14,7 @@
14
14
  from pydantic import PrivateAttr
15
15
 
16
16
  from .common import (
17
+ ConstantWaveform,
17
18
  CWSIterable,
18
19
  Experiment,
19
20
  HypIterable,
@@ -36,7 +37,7 @@ class ResonatorSpectroscopyByBias(Experiment):
36
37
  resonator : str
37
38
  The reference for the resonator to target in the experiment.
38
39
  bias_transmons : list[str] or None, optional
39
- The transmons to bias.
40
+ The references for the transmons to bias.
40
41
  If None, it defaults to transmon coupled to the resonator.
41
42
  frequencies : list[int] or LinspaceIterable or RangeIterable or CWSIterable
42
43
  or HypIterable or None, optional
@@ -46,18 +47,15 @@ class ResonatorSpectroscopyByBias(Experiment):
46
47
  or HypIterable, optional
47
48
  The biases at which to scan.
48
49
  If None, defaults to 21 points between -0.49 and 0.49.
49
- readout_amplitude : float, optional
50
- The amplitude of the readout pulse.
51
- Defaults to None.
52
- duration_ns : int, optional
53
- The duration of the pulse, in nanoseconds.
54
- Defaults to 2000 ns.
55
50
  recycle_delay_ns : int, optional
56
51
  The delay time between consecutive shots of the experiment, in nanoseconds.
57
52
  Defaults to 10000 ns.
58
53
  shot_count : int, optional
59
54
  The number of shots to be taken in the experiment.
60
55
  Defaults to 100.
56
+ measure_waveform : ConstantWaveform or None, optional
57
+ The waveform to use for the measurement pulse.
58
+ If not provided, the measurement defcal will be used.
61
59
  """
62
60
 
63
61
  _experiment_name: str = PrivateAttr("resonator_spectroscopy_by_bias")
@@ -70,7 +68,6 @@ class ResonatorSpectroscopyByBias(Experiment):
70
68
  biases: list[float] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable = (
71
69
  DEFAULT_BIASES
72
70
  )
73
- readout_amplitude: float | None = None
74
- duration_ns: int = DEFAULT_DURATION_NS
75
71
  recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
76
72
  shot_count: int = DEFAULT_SHOT_COUNT
73
+ measure_waveform: ConstantWaveform | None = None