boulder-opal-scale-up-sdk 1.0.0__py3-none-any.whl → 1.0.2__py3-none-any.whl
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.
- boulder_opal_scale_up_sdk-1.0.2.dist-info/LICENSE +805 -0
- {boulder_opal_scale_up_sdk-1.0.0.dist-info → boulder_opal_scale_up_sdk-1.0.2.dist-info}/METADATA +17 -7
- boulder_opal_scale_up_sdk-1.0.2.dist-info/RECORD +60 -0
- boulderopalscaleupsdk/agent/worker.py +22 -11
- boulderopalscaleupsdk/common/dtypes.py +81 -114
- boulderopalscaleupsdk/device/__init__.py +5 -1
- boulderopalscaleupsdk/device/config_loader.py +15 -10
- boulderopalscaleupsdk/device/controller/__init__.py +17 -14
- boulderopalscaleupsdk/device/controller/base.py +12 -3
- boulderopalscaleupsdk/device/controller/qblox.py +43 -17
- boulderopalscaleupsdk/device/controller/quantum_machines.py +60 -59
- boulderopalscaleupsdk/device/controller/resolver.py +117 -0
- boulderopalscaleupsdk/device/defcal.py +62 -0
- boulderopalscaleupsdk/device/device.py +8 -2
- boulderopalscaleupsdk/device/processor/__init__.py +9 -1
- boulderopalscaleupsdk/device/processor/common.py +129 -20
- boulderopalscaleupsdk/device/processor/superconducting_processor.py +61 -15
- boulderopalscaleupsdk/experiments/__init__.py +8 -0
- boulderopalscaleupsdk/experiments/chi01_scan.py +56 -0
- boulderopalscaleupsdk/experiments/common.py +8 -4
- boulderopalscaleupsdk/experiments/power_rabi.py +3 -3
- boulderopalscaleupsdk/experiments/ramsey.py +15 -8
- boulderopalscaleupsdk/experiments/readout_classifier_calibration.py +24 -0
- boulderopalscaleupsdk/experiments/resonator_spectroscopy.py +3 -3
- boulderopalscaleupsdk/experiments/resonator_spectroscopy_by_bias.py +10 -10
- boulderopalscaleupsdk/experiments/resonator_spectroscopy_by_power.py +3 -3
- boulderopalscaleupsdk/experiments/transmon_anharmonicity.py +68 -0
- boulderopalscaleupsdk/experiments/transmon_spectroscopy.py +69 -0
- boulderopalscaleupsdk/grpc_interceptors/auth.py +5 -2
- boulderopalscaleupsdk/plotting/__init__.py +20 -2
- boulderopalscaleupsdk/plotting/dtypes.py +81 -117
- boulderopalscaleupsdk/protobuf/v1/agent_pb2.py +17 -17
- boulderopalscaleupsdk/protobuf/v1/agent_pb2.pyi +8 -6
- boulderopalscaleupsdk/protobuf/v1/agent_pb2_grpc.py +13 -13
- boulderopalscaleupsdk/protobuf/v1/device_pb2.py +43 -25
- boulderopalscaleupsdk/protobuf/v1/device_pb2.pyi +50 -8
- boulderopalscaleupsdk/protobuf/v1/device_pb2_grpc.py +116 -14
- boulderopalscaleupsdk/routines/__init__.py +1 -4
- boulderopalscaleupsdk/routines/resonator_mapping.py +8 -2
- boulderopalscaleupsdk/stubs/__init__.py +12 -0
- boulderopalscaleupsdk/stubs/dtypes.py +47 -0
- boulderopalscaleupsdk/stubs/maps.py +9 -0
- boulderopalscaleupsdk/third_party/quantum_machines/__init__.py +32 -0
- boulderopalscaleupsdk/third_party/quantum_machines/config.py +30 -9
- boulder_opal_scale_up_sdk-1.0.0.dist-info/RECORD +0 -50
- {boulder_opal_scale_up_sdk-1.0.0.dist-info → boulder_opal_scale_up_sdk-1.0.2.dist-info}/WHEEL +0 -0
@@ -12,12 +12,19 @@
|
|
12
12
|
# License for the specific language.
|
13
13
|
|
14
14
|
from collections.abc import Callable
|
15
|
-
from datetime import
|
16
|
-
from
|
15
|
+
from datetime import UTC, datetime
|
16
|
+
from types import EllipsisType
|
17
|
+
from typing import Annotated, Any, Generic, Literal, Self, TypeVar
|
17
18
|
|
18
|
-
from pydantic import
|
19
|
+
from pydantic import BeforeValidator, ConfigDict, TypeAdapter
|
20
|
+
from pydantic.dataclasses import dataclass
|
19
21
|
|
20
|
-
from boulderopalscaleupsdk.common.dtypes import
|
22
|
+
from boulderopalscaleupsdk.common.dtypes import (
|
23
|
+
Duration,
|
24
|
+
DurationNsLike,
|
25
|
+
Frequency,
|
26
|
+
ISO8601DatetimeUTCLike,
|
27
|
+
)
|
21
28
|
from boulderopalscaleupsdk.common.typeclasses import Combine
|
22
29
|
|
23
30
|
T = TypeVar("T")
|
@@ -25,8 +32,20 @@ T2 = TypeVar("T2")
|
|
25
32
|
CalibrationStatusT = Literal["approximate", "bad", "good", "stale", "unmeasured"]
|
26
33
|
|
27
34
|
|
28
|
-
|
29
|
-
|
35
|
+
@dataclass
|
36
|
+
class CalibrationThresholds:
|
37
|
+
good: float
|
38
|
+
approximate: float
|
39
|
+
|
40
|
+
def __post_init__(self):
|
41
|
+
if self.good <= 0 or self.approximate < self.good:
|
42
|
+
raise ValueError(
|
43
|
+
f"Invalid thresholds: good: {self.good}, approximate: {self.approximate}",
|
44
|
+
)
|
45
|
+
|
46
|
+
|
47
|
+
@dataclass
|
48
|
+
class ComponentParameter(Generic[T]):
|
30
49
|
value: T
|
31
50
|
err_minus: T | None = None
|
32
51
|
err_plus: T | None = None
|
@@ -40,7 +59,7 @@ class ComponentParameter(BaseModel, Generic[T]):
|
|
40
59
|
cls,
|
41
60
|
value: Any,
|
42
61
|
target_type: type[float | int | Duration],
|
43
|
-
) ->
|
62
|
+
) -> Self:
|
44
63
|
"""
|
45
64
|
Create a ComponentParameter instance from a value, ensuring it matches the target type.
|
46
65
|
|
@@ -64,7 +83,7 @@ class ComponentParameter(BaseModel, Generic[T]):
|
|
64
83
|
match value:
|
65
84
|
case value if isinstance(value, cls):
|
66
85
|
if not isinstance(value.value, target_type):
|
67
|
-
raise TypeError("
|
86
|
+
raise TypeError("Invalid value type.")
|
68
87
|
return value
|
69
88
|
case _ if target_type in [float, int]:
|
70
89
|
return cls(**value)
|
@@ -73,7 +92,7 @@ class ComponentParameter(BaseModel, Generic[T]):
|
|
73
92
|
duration_ns = TypeAdapter(DurationNsLike).validate_python(value_copy.pop("value"))
|
74
93
|
return cls(value=duration_ns, **value_copy) # type: ignore[arg-type]
|
75
94
|
case _:
|
76
|
-
|
95
|
+
raise TypeError("Invalid component value type.")
|
77
96
|
|
78
97
|
@staticmethod
|
79
98
|
def combine(
|
@@ -94,7 +113,7 @@ class ComponentParameter(BaseModel, Generic[T]):
|
|
94
113
|
other.err_plus,
|
95
114
|
),
|
96
115
|
calibration_status=other.calibration_status,
|
97
|
-
updated_at=datetime.now(tz=
|
116
|
+
updated_at=datetime.now(tz=UTC),
|
98
117
|
)
|
99
118
|
|
100
119
|
return Combine[ComponentParameter[T]].create(_combine)
|
@@ -116,23 +135,113 @@ class ComponentParameter(BaseModel, Generic[T]):
|
|
116
135
|
self.calibration_status = combined.calibration_status
|
117
136
|
self.updated_at = combined.updated_at
|
118
137
|
|
138
|
+
def update(
|
139
|
+
self,
|
140
|
+
*,
|
141
|
+
value: T | EllipsisType = ...,
|
142
|
+
err_minus: T | None | EllipsisType = ...,
|
143
|
+
err_plus: T | None | EllipsisType = ...,
|
144
|
+
calibration_status: CalibrationStatusT | EllipsisType = ...,
|
145
|
+
) -> None:
|
146
|
+
if not isinstance(value, EllipsisType):
|
147
|
+
self.value = value
|
148
|
+
if not isinstance(err_minus, EllipsisType):
|
149
|
+
self.err_minus = err_minus
|
150
|
+
if not isinstance(err_plus, EllipsisType):
|
151
|
+
self.err_plus = err_plus
|
152
|
+
if not isinstance(calibration_status, EllipsisType):
|
153
|
+
self.calibration_status = calibration_status
|
154
|
+
self.updated_at = datetime.now(UTC)
|
155
|
+
|
156
|
+
def simple_update(
|
157
|
+
self,
|
158
|
+
*,
|
159
|
+
value: T | EllipsisType = ...,
|
160
|
+
std: T | None | EllipsisType = ...,
|
161
|
+
calibration_thresholds: CalibrationThresholds | EllipsisType = ...,
|
162
|
+
to_float: Callable[[T], float],
|
163
|
+
from_float: Callable[[float], T],
|
164
|
+
) -> None:
|
165
|
+
if not isinstance(value, EllipsisType):
|
166
|
+
self.value = value
|
167
|
+
if not isinstance(std, EllipsisType):
|
168
|
+
if std is None:
|
169
|
+
self.err_minus = None
|
170
|
+
self.err_plus = None
|
171
|
+
else:
|
172
|
+
self.err_minus = from_float(to_float(std) / 2.0)
|
173
|
+
self.err_plus = from_float(to_float(std) / 2.0)
|
174
|
+
if (
|
175
|
+
not isinstance(calibration_thresholds, EllipsisType)
|
176
|
+
and self.err_minus is not None
|
177
|
+
and self.err_plus is not None
|
178
|
+
):
|
179
|
+
self.calibration_status = _get_calibration_status_from_thresholds(
|
180
|
+
value=to_float(self.value),
|
181
|
+
confidence_interval=to_float(self.err_plus) - to_float(self.err_minus),
|
182
|
+
calibration_thresholds=calibration_thresholds,
|
183
|
+
)
|
184
|
+
self.updated_at = datetime.now(UTC)
|
185
|
+
|
186
|
+
|
187
|
+
def update_parameter(
|
188
|
+
parameter: ComponentParameter[T],
|
189
|
+
*,
|
190
|
+
value: T | EllipsisType = ...,
|
191
|
+
std: T | None | EllipsisType = ...,
|
192
|
+
calibration_thresholds: CalibrationThresholds | EllipsisType = ...,
|
193
|
+
) -> None:
|
194
|
+
"""
|
195
|
+
Update a ComponentParameter.
|
119
196
|
|
120
|
-
|
197
|
+
Parameters
|
198
|
+
----------
|
199
|
+
parameter : ComponentParameter[T]
|
200
|
+
The parameter to update.
|
201
|
+
value : T | EllipsisType, optional
|
202
|
+
The parameter value. If not provided, the value is left unchanged.
|
203
|
+
std : T | None | EllipsisType, optional
|
204
|
+
The standard deviation to set the parameter errors.
|
205
|
+
If None, the errors are cleared.
|
206
|
+
If not provided, the error is left unchanged.
|
207
|
+
calibration_thresholds : CalibrationThresholds
|
208
|
+
The thresholds to update the calibration status.
|
209
|
+
If not provided, the status is left unchanged.
|
210
|
+
If the parameter errors are not set, the status is left unchanged.
|
211
|
+
"""
|
212
|
+
|
213
|
+
# Use type of value to determine generic T.
|
214
|
+
match parameter.value:
|
215
|
+
case float():
|
216
|
+
parameter.simple_update(
|
217
|
+
value=value,
|
218
|
+
std=std,
|
219
|
+
calibration_thresholds=calibration_thresholds,
|
220
|
+
to_float=float, # type: ignore[arg-type]
|
221
|
+
from_float=float, # type: ignore[arg-type]
|
222
|
+
)
|
223
|
+
case Frequency():
|
224
|
+
parameter.simple_update(
|
225
|
+
value=value,
|
226
|
+
std=std,
|
227
|
+
calibration_thresholds=calibration_thresholds,
|
228
|
+
to_float=Frequency.to_float_hz, # type: ignore[arg-type]
|
229
|
+
from_float=Frequency.from_float_hz, # type: ignore[arg-type]
|
230
|
+
)
|
231
|
+
case _:
|
232
|
+
raise TypeError(f"Unsupported type in update: {type(parameter.value)}.")
|
233
|
+
|
234
|
+
|
235
|
+
def _get_calibration_status_from_thresholds(
|
121
236
|
value: float,
|
122
237
|
confidence_interval: float,
|
123
|
-
|
124
|
-
approximate_threshold: float,
|
238
|
+
calibration_thresholds: CalibrationThresholds,
|
125
239
|
) -> CalibrationStatusT:
|
126
|
-
if good_threshold <= 0 or approximate_threshold <= 0 or good_threshold >= approximate_threshold:
|
127
|
-
raise ValueError(
|
128
|
-
f"Invalid thresholds: good: {good_threshold}, approximate: {approximate_threshold}",
|
129
|
-
)
|
130
|
-
|
131
240
|
relative_uncertainty = abs(confidence_interval / value)
|
132
241
|
|
133
|
-
if relative_uncertainty <
|
242
|
+
if relative_uncertainty < calibration_thresholds.good:
|
134
243
|
return "good"
|
135
|
-
if relative_uncertainty <
|
244
|
+
if relative_uncertainty < calibration_thresholds.approximate:
|
136
245
|
return "approximate"
|
137
246
|
return "bad"
|
138
247
|
|
@@ -14,7 +14,7 @@
|
|
14
14
|
from copy import deepcopy
|
15
15
|
from typing import Annotated, Any, Literal, Union, get_args, get_origin
|
16
16
|
|
17
|
-
from pydantic import BaseModel, Field
|
17
|
+
from pydantic import BaseModel, Field, TypeAdapter
|
18
18
|
|
19
19
|
from boulderopalscaleupsdk.common.dtypes import (
|
20
20
|
Duration,
|
@@ -81,9 +81,9 @@ class Transmon(Component[Literal["tunable"]]):
|
|
81
81
|
)
|
82
82
|
|
83
83
|
|
84
|
-
class Resonator(Component[Literal["
|
84
|
+
class Resonator(Component[Literal["readout"]]):
|
85
85
|
dtype: Literal["resonator"] = "resonator"
|
86
|
-
traits: list[Literal["
|
86
|
+
traits: list[Literal["readout"]] = Field(default=["readout"])
|
87
87
|
|
88
88
|
frequency_high: FloatComponentParameter | None = Field(
|
89
89
|
default=None,
|
@@ -109,6 +109,33 @@ class Resonator(Component[Literal["dispersive"]]):
|
|
109
109
|
default=ComponentParameter(value=0.0),
|
110
110
|
json_schema_extra={"display": {"label": "vp_high", "unit": "V", "scale": 1}},
|
111
111
|
)
|
112
|
+
purcell_coupling: FloatComponentParameter = Field(
|
113
|
+
default=ComponentParameter(value=0.0),
|
114
|
+
json_schema_extra={"display": {"label": "purcell_coupling", "unit": "MHz", "scale": 1e-6}},
|
115
|
+
)
|
116
|
+
purcell_frequency: FloatComponentParameter = Field(
|
117
|
+
default=ComponentParameter(value=0.0),
|
118
|
+
json_schema_extra={"display": {"label": "purcell_frequency", "unit": "MHz", "scale": 1e-6}},
|
119
|
+
)
|
120
|
+
|
121
|
+
|
122
|
+
class Coupler(Component[Literal["tunable"]]):
|
123
|
+
dtype: Literal["coupler"] = "coupler"
|
124
|
+
traits: list[Literal["tunable"]] = Field(default=["tunable"])
|
125
|
+
|
126
|
+
# Tunable coupler parameters
|
127
|
+
dc_bias: FloatComponentParameter = Field(
|
128
|
+
default=ComponentParameter(value=0.0),
|
129
|
+
json_schema_extra={"display": {"label": "dc_bias", "unit": "V", "scale": 1}},
|
130
|
+
)
|
131
|
+
fmax_bias: FloatComponentParameter = Field(
|
132
|
+
default=ComponentParameter(value=0.0),
|
133
|
+
json_schema_extra={"display": {"label": "fmax_bias", "unit": "V", "scale": 1}},
|
134
|
+
)
|
135
|
+
bias_period: FloatComponentParameter = Field(
|
136
|
+
default=ComponentParameter(value=0.0),
|
137
|
+
json_schema_extra={"display": {"label": "bias_period", "unit": "V", "scale": 1}},
|
138
|
+
)
|
112
139
|
|
113
140
|
|
114
141
|
class Port(Component[Literal["drive", "readout", "flux"]]):
|
@@ -128,7 +155,7 @@ class Feedline(Component[Literal["feedline"]]):
|
|
128
155
|
traits: list = Field(default=[])
|
129
156
|
|
130
157
|
|
131
|
-
SuperconductingComponentType = Transmon | Resonator | Port | Feedline | Filter
|
158
|
+
SuperconductingComponentType = Transmon | Resonator | Port | Feedline | Filter | Coupler
|
132
159
|
|
133
160
|
|
134
161
|
class Edge(BaseModel):
|
@@ -143,14 +170,14 @@ class TemplateParam(BaseModel):
|
|
143
170
|
|
144
171
|
|
145
172
|
class ProcessorTemplate(BaseModel):
|
146
|
-
elements: dict[str, Transmon | Resonator | Port | Feedline | Filter]
|
173
|
+
elements: dict[str, Transmon | Resonator | Port | Feedline | Filter | Coupler]
|
147
174
|
edges: list[Edge]
|
148
175
|
|
149
176
|
|
150
177
|
class SuperconductingProcessorTemplate(BaseModel):
|
151
178
|
build: list[TemplateParam]
|
152
179
|
templates: dict[str, ProcessorTemplate]
|
153
|
-
device_parameters: dict[str, Transmon | Resonator | Port | Feedline | Filter] = Field(
|
180
|
+
device_parameters: dict[str, Transmon | Resonator | Port | Feedline | Filter | Coupler] = Field(
|
154
181
|
default={},
|
155
182
|
)
|
156
183
|
|
@@ -221,13 +248,32 @@ class SuperconductingProcessor(Processor):
|
|
221
248
|
raise KeyError(f"Component with ID '{component_id}' does not exist.")
|
222
249
|
|
223
250
|
component = self.nodes[component_id]
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
251
|
+
updated_component = deepcopy(component)
|
252
|
+
|
253
|
+
for k, v in params.items():
|
254
|
+
component_param = getattr(updated_component, k)
|
255
|
+
if not isinstance(component_param, ComponentParameter):
|
256
|
+
raise ValueError(f"Invalid or unexpected parameter for {type(component)}.") # noqa: TRY004
|
257
|
+
|
258
|
+
if k in ["dtype", "traits"]:
|
259
|
+
raise ValueError("Invalid attempt to modify component type or traits.")
|
260
|
+
|
261
|
+
if v is None:
|
262
|
+
continue
|
263
|
+
|
264
|
+
match v:
|
265
|
+
case ComponentParameter():
|
266
|
+
setattr(updated_component, k, v)
|
267
|
+
case _:
|
268
|
+
component_param.update(
|
269
|
+
value=v,
|
270
|
+
err_minus=None,
|
271
|
+
err_plus=None,
|
272
|
+
calibration_status="unmeasured",
|
273
|
+
)
|
274
|
+
setattr(updated_component, k, component_param)
|
275
|
+
|
276
|
+
self.nodes[component_id] = type(component).model_validate(updated_component.model_dump())
|
231
277
|
|
232
278
|
def get_component(self, component_id: str) -> SuperconductingComponentType:
|
233
279
|
"""
|
@@ -279,13 +325,13 @@ def _coerce_component_params(
|
|
279
325
|
continue
|
280
326
|
|
281
327
|
try:
|
282
|
-
dumped = value.
|
328
|
+
dumped = TypeAdapter(type(value)).dump_python(value)
|
283
329
|
coerced = expected_type(**dumped)
|
284
330
|
setattr(component, field_name, coerced)
|
285
331
|
except Exception as e:
|
286
332
|
raise ValueError(
|
287
333
|
f"Failed to coerce field '{field_name}' of type "
|
288
|
-
"'{expected_type}' with value '{value}': {e}",
|
334
|
+
"'{expected_type}' with value '{value}': {e}.",
|
289
335
|
) from e
|
290
336
|
|
291
337
|
return component
|
@@ -15,6 +15,7 @@
|
|
15
15
|
|
16
16
|
__all__ = [
|
17
17
|
"CWSIterable",
|
18
|
+
"Chi01Scan",
|
18
19
|
"ConstantWaveform",
|
19
20
|
"Experiment",
|
20
21
|
"GaussianWaveform",
|
@@ -23,11 +24,15 @@ __all__ = [
|
|
23
24
|
"PowerRabi",
|
24
25
|
"Ramsey",
|
25
26
|
"RangeIterable",
|
27
|
+
"ReadoutClassifierCalibration",
|
26
28
|
"ResonatorSpectroscopy",
|
27
29
|
"ResonatorSpectroscopyByBias",
|
28
30
|
"ResonatorSpectroscopyByPower",
|
31
|
+
"TransmonAnharmonicity",
|
32
|
+
"TransmonSpectroscopy",
|
29
33
|
]
|
30
34
|
|
35
|
+
from .chi01_scan import Chi01Scan
|
31
36
|
from .common import (
|
32
37
|
ConstantWaveform,
|
33
38
|
CWSIterable,
|
@@ -39,6 +44,9 @@ from .common import (
|
|
39
44
|
)
|
40
45
|
from .power_rabi import PowerRabi
|
41
46
|
from .ramsey import Ramsey
|
47
|
+
from .readout_classifier_calibration import ReadoutClassifierCalibration
|
42
48
|
from .resonator_spectroscopy import ResonatorSpectroscopy
|
43
49
|
from .resonator_spectroscopy_by_bias import ResonatorSpectroscopyByBias
|
44
50
|
from .resonator_spectroscopy_by_power import ResonatorSpectroscopyByPower
|
51
|
+
from .transmon_anharmonicity import TransmonAnharmonicity
|
52
|
+
from .transmon_spectroscopy import TransmonSpectroscopy
|
@@ -0,0 +1,56 @@
|
|
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
|
+
from pydantic import PrivateAttr
|
15
|
+
|
16
|
+
from boulderopalscaleupsdk.experiments.common import (
|
17
|
+
CWSIterable,
|
18
|
+
Experiment,
|
19
|
+
HypIterable,
|
20
|
+
LinspaceIterable,
|
21
|
+
RangeIterable,
|
22
|
+
)
|
23
|
+
|
24
|
+
DEFAULT_RECYCLE_DELAY_NS = 10_000
|
25
|
+
DEFAULT_SHOT_COUNT = 100
|
26
|
+
|
27
|
+
|
28
|
+
class Chi01Scan(Experiment):
|
29
|
+
"""
|
30
|
+
Parameters for running an experiment to find the dispersive shift for a transmon
|
31
|
+
resonator pair.
|
32
|
+
|
33
|
+
Attributes
|
34
|
+
----------
|
35
|
+
transmon : str
|
36
|
+
The reference for the transmon to target in the experiment.
|
37
|
+
frequencies : list[int] or LinspaceIterable or RangeIterable or CWSIterable
|
38
|
+
or HypIterable or None, optional
|
39
|
+
The frequencies at which to scan.
|
40
|
+
If None, frequencies around the readout frequency will be used.
|
41
|
+
recycle_delay_ns : int, optional
|
42
|
+
The delay time between consecutive shots of the experiment, in nanoseconds.
|
43
|
+
Defaults to 10000 ns.
|
44
|
+
shot_count : int, optional
|
45
|
+
The number of shots to be taken in the experiment.
|
46
|
+
Defaults to 100.
|
47
|
+
"""
|
48
|
+
|
49
|
+
_experiment_name: str = PrivateAttr("chi01_scan")
|
50
|
+
|
51
|
+
transmon: str
|
52
|
+
frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
|
53
|
+
None
|
54
|
+
)
|
55
|
+
recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
|
56
|
+
shot_count: int = DEFAULT_SHOT_COUNT
|
@@ -26,7 +26,11 @@ class Experiment(BaseModel):
|
|
26
26
|
return self._experiment_name
|
27
27
|
|
28
28
|
|
29
|
-
class
|
29
|
+
class _RangeIterable(BaseModel):
|
30
|
+
model_config = ConfigDict(extra="forbid")
|
31
|
+
|
32
|
+
|
33
|
+
class LinspaceIterable(_RangeIterable):
|
30
34
|
"""A linear space of float values."""
|
31
35
|
|
32
36
|
dtype: Literal["linspace"] = "linspace"
|
@@ -39,7 +43,7 @@ class LinspaceIterable(BaseModel):
|
|
39
43
|
count: int = Field(default=101)
|
40
44
|
|
41
45
|
|
42
|
-
class RangeIterable(
|
46
|
+
class RangeIterable(_RangeIterable):
|
43
47
|
"""A range of values with a specified step."""
|
44
48
|
|
45
49
|
dtype: Literal["range"] = "range"
|
@@ -52,7 +56,7 @@ class RangeIterable(BaseModel):
|
|
52
56
|
step: float
|
53
57
|
|
54
58
|
|
55
|
-
class CWSIterable(
|
59
|
+
class CWSIterable(_RangeIterable):
|
56
60
|
"""A range of linearly spaced values in center ± width/2."""
|
57
61
|
|
58
62
|
dtype: Literal["cws"] = "cws"
|
@@ -65,7 +69,7 @@ class CWSIterable(BaseModel):
|
|
65
69
|
step: float
|
66
70
|
|
67
71
|
|
68
|
-
class HypIterable(
|
72
|
+
class HypIterable(_RangeIterable):
|
69
73
|
"""
|
70
74
|
A hyperbolic iterable of values in center ± width/2,
|
71
75
|
with points more concentrated around the center.
|
@@ -32,8 +32,8 @@ class PowerRabi(Experiment):
|
|
32
32
|
|
33
33
|
Parameters
|
34
34
|
----------
|
35
|
-
|
36
|
-
The
|
35
|
+
transmon : str
|
36
|
+
The reference for the transmon to target in the experiment.
|
37
37
|
scales : list[float] or LinspaceIterable or RangeIterable
|
38
38
|
or CWSIterable or HypIterable or None, optional
|
39
39
|
The scaling factors for the drive pulse amplitude. If None, a default scan will be used.
|
@@ -51,7 +51,7 @@ class PowerRabi(Experiment):
|
|
51
51
|
|
52
52
|
_experiment_name: str = PrivateAttr("power_rabi")
|
53
53
|
|
54
|
-
|
54
|
+
transmon: str
|
55
55
|
scales: list[float] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = None
|
56
56
|
drive_waveform: GaussianWaveform
|
57
57
|
measure_waveform: ConstantWaveform
|
@@ -17,6 +17,7 @@ from .common import Experiment
|
|
17
17
|
|
18
18
|
DEFAULT_RECYCLE_DELAY_NS = 10_000
|
19
19
|
DEFAULT_SHOT_COUNT = 400
|
20
|
+
DEFAULT_DURATION_NS = 2_000
|
20
21
|
|
21
22
|
|
22
23
|
class Ramsey(Experiment):
|
@@ -25,18 +26,22 @@ class Ramsey(Experiment):
|
|
25
26
|
|
26
27
|
Parameters
|
27
28
|
----------
|
28
|
-
|
29
|
-
The
|
29
|
+
transmon : str
|
30
|
+
The reference for the transmon to target in the experiment.
|
30
31
|
max_delay_ns : int
|
31
32
|
The maximum delay time, in nanoseconds.
|
32
33
|
min_delay_ns : int
|
33
34
|
The minimum delay time, in nanoseconds.
|
34
35
|
delay_step_ns : int
|
35
36
|
The step for generating the list of delays, in nanoseconds.
|
36
|
-
|
37
|
-
The difference between the drive signal frequency and the qubit frequency,
|
38
|
-
|
39
|
-
|
37
|
+
virtual_detuning : float
|
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
|
+
recycle_delay_ns : int, optional
|
40
45
|
The delay time between consecutive shots of the experiment, in nanoseconds.
|
41
46
|
Defaults to 10000 ns.
|
42
47
|
shot_count : int, optional
|
@@ -46,10 +51,12 @@ class Ramsey(Experiment):
|
|
46
51
|
|
47
52
|
_experiment_name: str = PrivateAttr("ramsey")
|
48
53
|
|
49
|
-
|
54
|
+
transmon: str
|
50
55
|
max_delay_ns: int
|
51
56
|
min_delay_ns: int
|
52
57
|
delay_step_ns: int
|
53
|
-
|
58
|
+
virtual_detuning: float
|
59
|
+
readout_amplitude: float
|
60
|
+
duration_ns: int = DEFAULT_DURATION_NS
|
54
61
|
recycle_delay_ns: int = DEFAULT_RECYCLE_DELAY_NS
|
55
62
|
shot_count: int = DEFAULT_SHOT_COUNT
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from pydantic import PrivateAttr
|
2
|
+
|
3
|
+
from boulderopalscaleupsdk.experiments.common import Experiment
|
4
|
+
|
5
|
+
|
6
|
+
class ReadoutClassifierCalibration(Experiment):
|
7
|
+
"""
|
8
|
+
Parameters for running calibration of readout classifier for a transmon.
|
9
|
+
|
10
|
+
Parameters
|
11
|
+
----------
|
12
|
+
transmon : str
|
13
|
+
The reference for the transmon to target in the experiment.
|
14
|
+
recycle_delay_ns : int
|
15
|
+
The delay time between consecutive shots of the experiment, in nanoseconds.
|
16
|
+
shot_count : int, optional
|
17
|
+
The number of shots to be taken in the experiment.
|
18
|
+
Defaults to 5000.
|
19
|
+
"""
|
20
|
+
|
21
|
+
_experiment_name: str = PrivateAttr("readout_classifier_calibration")
|
22
|
+
transmon: str
|
23
|
+
recycle_delay_ns: int
|
24
|
+
shot_count: int = 5000
|
@@ -32,8 +32,8 @@ class ResonatorSpectroscopy(Experiment):
|
|
32
32
|
|
33
33
|
Parameters
|
34
34
|
----------
|
35
|
-
|
36
|
-
The
|
35
|
+
resonator : str
|
36
|
+
The reference for the resonator to target in the experiment.
|
37
37
|
frequencies : list[int] or LinspaceIterable or RangeIterable or CWSIterable
|
38
38
|
or HypIterable or None, optional
|
39
39
|
The frequencies at which to scan.
|
@@ -54,7 +54,7 @@ class ResonatorSpectroscopy(Experiment):
|
|
54
54
|
|
55
55
|
_experiment_name: str = PrivateAttr("resonator_spectroscopy")
|
56
56
|
|
57
|
-
|
57
|
+
resonator: str
|
58
58
|
frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
|
59
59
|
None
|
60
60
|
)
|
@@ -33,12 +33,12 @@ class ResonatorSpectroscopyByBias(Experiment):
|
|
33
33
|
|
34
34
|
Parameters
|
35
35
|
----------
|
36
|
-
|
37
|
-
The
|
38
|
-
|
39
|
-
The
|
40
|
-
If None, defaults to the
|
41
|
-
frequencies : list[
|
36
|
+
resonator : str
|
37
|
+
The reference for the resonator to target in the experiment.
|
38
|
+
bias_transmons : list[str] or None, optional
|
39
|
+
The transmons to bias.
|
40
|
+
If None, it defaults to transmon coupled to the resonator.
|
41
|
+
frequencies : list[int] or LinspaceIterable or RangeIterable or CWSIterable
|
42
42
|
or HypIterable or None, optional
|
43
43
|
The frequencies at which to scan.
|
44
44
|
If None, frequencies around the readout frequency will be used.
|
@@ -49,10 +49,10 @@ class ResonatorSpectroscopyByBias(Experiment):
|
|
49
49
|
readout_amplitude : float, optional
|
50
50
|
The amplitude of the readout pulse.
|
51
51
|
Defaults to None.
|
52
|
-
duration_ns :
|
52
|
+
duration_ns : int, optional
|
53
53
|
The duration of the pulse, in nanoseconds.
|
54
54
|
Defaults to 2000 ns.
|
55
|
-
recycle_delay_ns :
|
55
|
+
recycle_delay_ns : int, optional
|
56
56
|
The delay time between consecutive shots of the experiment, in nanoseconds.
|
57
57
|
Defaults to 10000 ns.
|
58
58
|
shot_count : int, optional
|
@@ -62,8 +62,8 @@ class ResonatorSpectroscopyByBias(Experiment):
|
|
62
62
|
|
63
63
|
_experiment_name: str = PrivateAttr("resonator_spectroscopy_by_bias")
|
64
64
|
|
65
|
-
|
66
|
-
|
65
|
+
resonator: str
|
66
|
+
bias_transmons: list[str] | None = None
|
67
67
|
frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
|
68
68
|
None
|
69
69
|
)
|
@@ -32,8 +32,8 @@ class ResonatorSpectroscopyByPower(Experiment):
|
|
32
32
|
|
33
33
|
Parameters
|
34
34
|
----------
|
35
|
-
|
36
|
-
The
|
35
|
+
resonator : str
|
36
|
+
The reference for the resonator to target in the experiment.
|
37
37
|
frequencies : list[int] or LinspaceIterable or RangeIterable or CWSIterable
|
38
38
|
or HypIterable or None, optional
|
39
39
|
The frequencies at which to scan.
|
@@ -54,7 +54,7 @@ class ResonatorSpectroscopyByPower(Experiment):
|
|
54
54
|
|
55
55
|
_experiment_name: str = PrivateAttr("resonator_spectroscopy_by_power")
|
56
56
|
|
57
|
-
|
57
|
+
resonator: str
|
58
58
|
frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
|
59
59
|
None
|
60
60
|
)
|