boulder-opal-scale-up-sdk 1.0.4__tar.gz → 1.0.5__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.
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/PKG-INFO +1 -1
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/agent/worker.py +23 -4
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/common/dtypes.py +20 -1
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/controller/qblox.py +94 -26
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/device.py +5 -1
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/processor/superconducting_processor.py +23 -3
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/__init__.py +8 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/chi01_scan.py +9 -7
- boulder_opal_scale_up_sdk-1.0.5/boulderopalscaleupsdk/experiments/drag_leakage_calibration.py +66 -0
- boulder_opal_scale_up_sdk-1.0.5/boulderopalscaleupsdk/experiments/fine_amplitude_calibration.py +54 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/power_rabi.py +10 -7
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/power_rabi_ef.py +10 -9
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/ramsey.py +9 -7
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/readout_classifier_calibration.py +9 -3
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/resonator_spectroscopy.py +9 -7
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/resonator_spectroscopy_by_bias.py +11 -8
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/resonator_spectroscopy_by_power.py +10 -9
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/t1.py +8 -6
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/t2.py +12 -10
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/t2_echo.py +12 -10
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/transmon_anharmonicity.py +13 -10
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/transmon_spectroscopy.py +10 -8
- boulder_opal_scale_up_sdk-1.0.5/boulderopalscaleupsdk/experiments/voltage_bias_fine_tune.py +58 -0
- boulder_opal_scale_up_sdk-1.0.5/boulderopalscaleupsdk/experiments/zz_ramsey.py +59 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/plotting/dtypes.py +5 -3
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/protobuf/v1/agent_pb2.py +9 -3
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/protobuf/v1/agent_pb2.pyi +14 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/protobuf/v1/agent_pb2_grpc.py +34 -0
- boulder_opal_scale_up_sdk-1.0.5/boulderopalscaleupsdk/protobuf/v1/device_pb2.py +89 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/protobuf/v1/device_pb2.pyi +4 -2
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/routines/__init__.py +10 -1
- boulder_opal_scale_up_sdk-1.0.4/boulderopalscaleupsdk/routines/transmon_retuning.py → boulder_opal_scale_up_sdk-1.0.5/boulderopalscaleupsdk/routines/one_qubit_calibration.py +10 -5
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/routines/resonator_mapping.py +1 -1
- boulder_opal_scale_up_sdk-1.0.5/boulderopalscaleupsdk/routines/transmon_coherence.py +34 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/routines/transmon_discovery.py +5 -9
- boulder_opal_scale_up_sdk-1.0.5/boulderopalscaleupsdk/routines/transmon_retuning.py +41 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/pyproject.toml +2 -4
- boulder_opal_scale_up_sdk-1.0.4/boulderopalscaleupsdk/protobuf/v1/device_pb2.py +0 -89
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/LICENSE +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/README.md +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/agent/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/common/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/common/typeclasses.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/common.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/config_loader.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/controller/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/controller/base.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/controller/quantum_machines.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/controller/resolver.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/defcal.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/processor/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/device/processor/common.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/common.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/experiments/waveforms.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/grpc_interceptors/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/grpc_interceptors/auth.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/plotting/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/protobuf/v1/device_pb2_grpc.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/protobuf/v1/task_pb2.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/protobuf/v1/task_pb2.pyi +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/protobuf/v1/task_pb2_grpc.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/py.typed +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/routines/common.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/stubs/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/stubs/dtypes.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/stubs/maps.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/third_party/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/third_party/quantum_machines/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/third_party/quantum_machines/config.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/third_party/quantum_machines/constants.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/boulderopalscaleupsdk/utils/__init__.py +0 -0
- {boulder_opal_scale_up_sdk-1.0.4 → boulder_opal_scale_up_sdk-1.0.5}/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.
|
3
|
+
Version: 1.0.5
|
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
|
@@ -54,11 +54,13 @@ class TaskHandler(Protocol):
|
|
54
54
|
self,
|
55
55
|
request: agent_pb2.RunProgramRequest
|
56
56
|
| agent_pb2.RunQuantumMachinesMixerCalibrationRequest
|
57
|
-
| agent_pb2.DisplayResultsRequest
|
57
|
+
| agent_pb2.DisplayResultsRequest
|
58
|
+
| agent_pb2.AskRequest,
|
58
59
|
) -> (
|
59
60
|
agent_pb2.RunProgramResponse
|
60
61
|
| agent_pb2.RunQuantumMachinesMixerCalibrationResponse
|
61
62
|
| agent_pb2.DisplayResultsResponse
|
63
|
+
| agent_pb2.AskResponse
|
62
64
|
| task_pb2.TaskErrorDetail
|
63
65
|
): ...
|
64
66
|
|
@@ -67,9 +69,8 @@ class TaskHandler(Protocol):
|
|
67
69
|
task: task_pb2.Task,
|
68
70
|
) -> any_pb2.Any | task_pb2.TaskErrorDetail:
|
69
71
|
request = (
|
70
|
-
_as_run_program_request(
|
71
|
-
|
72
|
-
)
|
72
|
+
_as_run_program_request(task.data)
|
73
|
+
or _as_ask_request(task.data)
|
73
74
|
or _as_run_qua_calibration_request(task.data)
|
74
75
|
or _as_display_results_request(task.data)
|
75
76
|
)
|
@@ -78,6 +79,7 @@ class TaskHandler(Protocol):
|
|
78
79
|
agent_pb2.RunProgramRequest()
|
79
80
|
| agent_pb2.RunQuantumMachinesMixerCalibrationRequest()
|
80
81
|
| agent_pb2.DisplayResultsRequest()
|
82
|
+
| agent_pb2.AskRequest()
|
81
83
|
):
|
82
84
|
return _as_any_message(await self.handle(request))
|
83
85
|
case None:
|
@@ -104,6 +106,17 @@ def _as_run_program_request(
|
|
104
106
|
return request
|
105
107
|
|
106
108
|
|
109
|
+
def _as_ask_request(
|
110
|
+
task_result: any_pb2.Any,
|
111
|
+
) -> agent_pb2.AskRequest | None:
|
112
|
+
request = agent_pb2.AskRequest()
|
113
|
+
unpacked: bool = task_result.Unpack(request) # type: ignore[reportUnknownMemberType]
|
114
|
+
if not unpacked:
|
115
|
+
return None
|
116
|
+
|
117
|
+
return request
|
118
|
+
|
119
|
+
|
107
120
|
def _as_run_qua_calibration_request(
|
108
121
|
task_result: any_pb2.Any,
|
109
122
|
) -> agent_pb2.RunQuantumMachinesMixerCalibrationRequest | None:
|
@@ -158,16 +171,22 @@ class Agent:
|
|
158
171
|
Create a gRPC channel.
|
159
172
|
"""
|
160
173
|
host = url.split(":")[0]
|
174
|
+
options = [
|
175
|
+
("grpc.max_send_message_length", 1024 * 1024 * 50), # 50MB
|
176
|
+
("grpc.max_receive_message_length", 1024 * 1024 * 50), # 50MB
|
177
|
+
]
|
161
178
|
if host in ["localhost", "127.0.0.1", "0.0.0.0", "::"]:
|
162
179
|
channel = grpc.insecure_channel(
|
163
180
|
url,
|
164
181
|
interceptors=interceptors,
|
182
|
+
options=options,
|
165
183
|
)
|
166
184
|
else:
|
167
185
|
channel = grpc.secure_channel(
|
168
186
|
url,
|
169
187
|
credentials=ssl_channel_credentials(),
|
170
188
|
interceptors=interceptors,
|
189
|
+
options=options,
|
171
190
|
)
|
172
191
|
return channel
|
173
192
|
|
@@ -325,7 +325,26 @@ class JobSummary(BaseModel):
|
|
325
325
|
created_at: ISO8601DatetimeUTCLike
|
326
326
|
|
327
327
|
def __str__(self):
|
328
|
-
return f
|
328
|
+
return f'JobSummary(name="{self.name}", id="{self.id}")'
|
329
|
+
|
330
|
+
|
331
|
+
class JobDataEntry(BaseModel):
|
332
|
+
message: str
|
333
|
+
created_at: ISO8601DatetimeUTCLike
|
334
|
+
dt: str
|
335
|
+
elapsed_time: str
|
336
|
+
|
337
|
+
class Config:
|
338
|
+
extra = "allow"
|
339
|
+
|
340
|
+
|
341
|
+
class JobData(BaseModel):
|
342
|
+
id: str
|
343
|
+
name: str
|
344
|
+
session_id: str
|
345
|
+
created_at: ISO8601DatetimeUTCLike
|
346
|
+
device_name: str
|
347
|
+
data: list[JobDataEntry]
|
329
348
|
|
330
349
|
|
331
350
|
DEFAULT_JOB_HISTORY_PAGE = 1
|
@@ -257,18 +257,18 @@ ChannelType = RealChannel | ComplexChannel
|
|
257
257
|
# ==================================================================================================
|
258
258
|
# Controller information
|
259
259
|
# ==================================================================================================
|
260
|
-
class
|
260
|
+
class PortConnection(BaseModel): # pragma: no cover
|
261
261
|
"""
|
262
|
-
The connections involved for a
|
262
|
+
The connections involved for a QPU port.
|
263
263
|
|
264
264
|
Attributes
|
265
265
|
----------
|
266
266
|
ch_out: ChannelType
|
267
|
-
The output channel that will signal towards the
|
268
|
-
ch_in: ChannelType, optional
|
269
|
-
The input channel from which signals will be acquired from the
|
270
|
-
not all modules support acquisitions. If an input channel is specified, it must be
|
271
|
-
on the same module as the output channel.
|
267
|
+
The output channel that will signal towards the QPU port
|
268
|
+
ch_in: ChannelType or None, optional
|
269
|
+
The input channel from which signals will be acquired from the QPU port. This is optional,
|
270
|
+
as not all modules support acquisitions. If an input channel is specified, it must be
|
271
|
+
located on the same module as the output channel.
|
272
272
|
|
273
273
|
Notes
|
274
274
|
-----
|
@@ -276,20 +276,21 @@ class ElementConnection(BaseModel): # pragma: no cover
|
|
276
276
|
direction is outwards from the control stack. The following diagram depicts a simple setup with
|
277
277
|
the arrows indicating a control channel.
|
278
278
|
|
279
|
-
┌────────┐
|
280
|
-
│ │─── out ──►│
|
281
|
-
│ QBLOX │
|
282
|
-
│ Stack │
|
283
|
-
│ │─── out ──►│
|
284
|
-
│ │◄── in ────│
|
285
|
-
└────────┘
|
279
|
+
┌────────┐ ┌───────────────┐
|
280
|
+
│ │─── out ──►│ Port: p_xy1 │
|
281
|
+
│ QBLOX │ └───────────────┘
|
282
|
+
│ Stack │ ┌───────────────┐
|
283
|
+
│ │─── out ──►│ Port: p_flrr0 │
|
284
|
+
│ │◄── in ────│ │
|
285
|
+
└────────┘ └───────────────┘
|
286
|
+
QPU fridge
|
286
287
|
"""
|
287
288
|
|
288
289
|
ch_out: ChannelType
|
289
290
|
ch_in: ChannelType | None = None
|
290
291
|
|
291
292
|
@model_validator(mode="after")
|
292
|
-
def validate_channels(self) -> "
|
293
|
+
def validate_channels(self) -> "PortConnection":
|
293
294
|
if self.ch_in is not None and self.ch_in.module != self.ch_out.module:
|
294
295
|
raise ValueError("I/O channels for an element must be on the same module.")
|
295
296
|
return self
|
@@ -309,38 +310,102 @@ class QBLOXControllerInfo(BaseModel): # pragma: no cover
|
|
309
310
|
The type of controller, which is always `ControllerType.QBLOX` for this class.
|
310
311
|
modules: dict[ModuleAddrType, ModuleType]
|
311
312
|
The modules connected to the QBLOX stack.
|
312
|
-
|
313
|
-
The
|
313
|
+
port_config: dict[str, PortConnection]
|
314
|
+
The dictionary of ports with their types and addresses.
|
314
315
|
"""
|
315
316
|
|
316
317
|
controller_type: Literal[ControllerType.QBLOX] = ControllerType.QBLOX
|
317
318
|
modules: dict[ModuleAddrType, ModuleType]
|
318
|
-
|
319
|
+
port_config: dict[str, PortConnection]
|
319
320
|
|
320
321
|
|
321
322
|
# ==================================================================================================
|
322
323
|
# Instrument management
|
323
324
|
# ==================================================================================================
|
324
325
|
class SequencerParams(BaseModel):
|
325
|
-
nco_freq: float | None = Field(default=None
|
326
|
+
nco_freq: float | None = Field(default=None)
|
326
327
|
gain_awg_path0: float | None = Field(default=None, ge=-1.0, le=1.0)
|
327
328
|
offset_awg_path0: float | None = Field(default=None, ge=-1.0, le=1.0)
|
328
329
|
gain_awg_path1: float | None = Field(default=None, ge=-1.0, le=1.0)
|
329
330
|
offset_awg_path1: float | None = Field(default=None, ge=-1.0, le=1.0)
|
330
331
|
marker_ovr_en: bool | None = Field(default=None)
|
331
|
-
marker_ovr_value: int | None = Field(default=None)
|
332
|
+
marker_ovr_value: int | None = Field(default=None, ge=0, le=15)
|
332
333
|
mod_en_awg: bool | None = Field(default=None)
|
333
334
|
demod_en_acq: bool | None = Field(default=None)
|
334
335
|
sync_en: bool | None = Field(default=None)
|
335
336
|
nco_prop_delay_comp_en: bool | None = Field(default=True)
|
336
|
-
integration_length_acq: int | None = Field(default=None)
|
337
|
+
integration_length_acq: int | None = Field(default=None, ge=4, le=16777212, multiple_of=4)
|
337
338
|
|
338
339
|
|
339
|
-
class
|
340
|
-
|
341
|
-
|
340
|
+
class QcmParams(BaseModel):
|
341
|
+
out0_offset: float | None = Field(default=None, ge=-2.5, le=2.5)
|
342
|
+
out1_offset: float | None = Field(default=None, ge=-2.5, le=2.5)
|
343
|
+
out2_offset: float | None = Field(default=None, ge=-2.5, le=2.5)
|
344
|
+
out3_offset: float | None = Field(default=None, ge=-2.5, le=2.5)
|
345
|
+
|
346
|
+
def update(self, other: Self) -> None:
|
347
|
+
if self == other:
|
348
|
+
return # Nothing to do
|
349
|
+
|
350
|
+
self.out0_offset = pick_only_one_or_raise(self.out0_offset, other.out0_offset)
|
351
|
+
self.out1_offset = pick_only_one_or_raise(self.out1_offset, other.out1_offset)
|
352
|
+
self.out2_offset = pick_only_one_or_raise(self.out2_offset, other.out2_offset)
|
353
|
+
self.out3_offset = pick_only_one_or_raise(self.out3_offset, other.out3_offset)
|
354
|
+
|
355
|
+
|
356
|
+
class QcmRfParams(BaseModel):
|
357
|
+
out0_att: int | None = Field(default=None, ge=0, le=60, multiple_of=2)
|
358
|
+
out1_att: int | None = Field(default=None, ge=0, le=60, multiple_of=2)
|
359
|
+
|
342
360
|
out0_lo_freq: float | None = Field(default=None, gt=0)
|
343
361
|
out0_lo_en: bool | None = Field(default=None)
|
362
|
+
out1_lo_freq: float | None = Field(default=None, gt=0)
|
363
|
+
out1_lo_en: bool | None = Field(default=None)
|
364
|
+
|
365
|
+
def update(self, other: Self) -> None:
|
366
|
+
if self == other:
|
367
|
+
return # Nothing to do
|
368
|
+
|
369
|
+
self.out0_att = pick_only_one_or_raise(self.out0_att, other.out0_att)
|
370
|
+
self.out1_att = pick_only_one_or_raise(self.out1_att, other.out1_att)
|
371
|
+
self.out0_lo_freq = pick_only_one_or_raise(self.out0_lo_freq, other.out0_lo_freq)
|
372
|
+
self.out0_lo_en = pick_only_one_or_raise(self.out0_lo_en, other.out0_lo_en)
|
373
|
+
self.out1_lo_freq = pick_only_one_or_raise(self.out1_lo_freq, other.out1_lo_freq)
|
374
|
+
self.out1_lo_en = pick_only_one_or_raise(self.out1_lo_en, other.out1_lo_en)
|
375
|
+
|
376
|
+
|
377
|
+
class QrmRfParams(BaseModel):
|
378
|
+
out0_att: int | None = Field(default=None, ge=0, le=60, multiple_of=2)
|
379
|
+
|
380
|
+
out0_in0_lo_freq: float | None = Field(default=None, gt=0)
|
381
|
+
out0_in0_lo_en: bool | None = Field(default=None)
|
382
|
+
|
383
|
+
def update(self, other: Self) -> None:
|
384
|
+
if self == other:
|
385
|
+
return # Nothing to do
|
386
|
+
|
387
|
+
self.out0_att = pick_only_one_or_raise(self.out0_att, other.out0_att)
|
388
|
+
self.out0_in0_lo_freq = pick_only_one_or_raise(
|
389
|
+
self.out0_in0_lo_freq,
|
390
|
+
other.out0_in0_lo_freq,
|
391
|
+
)
|
392
|
+
self.out0_in0_lo_en = pick_only_one_or_raise(self.out0_in0_lo_en, other.out0_in0_lo_en)
|
393
|
+
|
394
|
+
|
395
|
+
ModuleParams = QcmParams | QcmRfParams | QrmRfParams
|
396
|
+
|
397
|
+
|
398
|
+
T0 = TypeVar("T0")
|
399
|
+
|
400
|
+
|
401
|
+
def pick_only_one_or_raise(a: T0 | None, b: T0 | None) -> T0 | None:
|
402
|
+
if a == b:
|
403
|
+
return a
|
404
|
+
if a is None:
|
405
|
+
return b
|
406
|
+
if b is None:
|
407
|
+
return a
|
408
|
+
raise ValueError(f"Cannot resolve conflict between given parameters {a} and {b}!")
|
344
409
|
|
345
410
|
|
346
411
|
# ==================================================================================================
|
@@ -414,7 +479,7 @@ class PreparedSequenceProgram(BaseModel): # pragma: no cover
|
|
414
479
|
|
415
480
|
|
416
481
|
class PreparedModule(BaseModel):
|
417
|
-
params: ModuleParams
|
482
|
+
params: ModuleParams
|
418
483
|
|
419
484
|
|
420
485
|
class PreparedProgram(BaseModel):
|
@@ -661,7 +726,10 @@ class BitStrideArrayEncoding:
|
|
661
726
|
encoded_shape = tuple(
|
662
727
|
BitStrideArrayEncoding._round_power2_32bit(dim) for dim in desired_shape
|
663
728
|
)
|
664
|
-
|
729
|
+
# Right-most (most nested) dimension takes least significant bits!
|
730
|
+
exponents = tuple(int(math.log2(dim)) for dim in encoded_shape)
|
731
|
+
n_bits = sum(exponents)
|
732
|
+
bit_stride = tuple(n_bits - sum(exponents[: idx + 1]) for idx in range(len(exponents)))
|
665
733
|
return cls(
|
666
734
|
desired_shape=desired_shape,
|
667
735
|
encoded_shape=encoded_shape,
|
@@ -29,6 +29,9 @@ class EmptyDefCalData:
|
|
29
29
|
message: str
|
30
30
|
|
31
31
|
|
32
|
+
DeviceName = str
|
33
|
+
|
34
|
+
|
32
35
|
@dataclass
|
33
36
|
class DeviceData:
|
34
37
|
# TODO: retire DeviceInfo the next SDK release
|
@@ -58,6 +61,7 @@ class DeviceSummary(BaseModel):
|
|
58
61
|
provider: str
|
59
62
|
updated_at: ISO8601DatetimeUTCLike
|
60
63
|
created_at: ISO8601DatetimeUTCLike
|
64
|
+
copied_from: DeviceName | None = None
|
61
65
|
|
62
66
|
def __str__(self):
|
63
|
-
return f
|
67
|
+
return f'DeviceSummary(name="{self.name}", id="{self.id}")'
|
@@ -161,7 +161,27 @@ class Feedline(Component[Literal["feedline"]]):
|
|
161
161
|
traits: list = Field(default=[])
|
162
162
|
|
163
163
|
|
164
|
-
|
164
|
+
class TWPA(Component[Literal["twpa"]]):
|
165
|
+
dtype: Literal["twpa"] = "twpa"
|
166
|
+
traits: list = Field(default=[])
|
167
|
+
|
168
|
+
impedance: FloatComponentParameter = Field(
|
169
|
+
default=ComponentParameter(value=0.0),
|
170
|
+
json_schema_extra={"display": {"label": "impedance", "unit": "Ohm", "scale": 1}},
|
171
|
+
)
|
172
|
+
|
173
|
+
# Tunable TWPA parameters
|
174
|
+
pump_power: FloatComponentParameter = Field(
|
175
|
+
default=ComponentParameter(value=0.0),
|
176
|
+
json_schema_extra={"display": {"label": "pump_power", "unit": "dBm", "scale": 1}},
|
177
|
+
)
|
178
|
+
pump_freq: FloatComponentParameter = Field(
|
179
|
+
default=ComponentParameter(value=(0.0)),
|
180
|
+
json_schema_extra={"display": {"label": "pump_freq", "unit": "MHz", "scale": 1e-6}},
|
181
|
+
)
|
182
|
+
|
183
|
+
|
184
|
+
SuperconductingComponentType = Transmon | Resonator | Port | Feedline | Filter | Coupler | TWPA
|
165
185
|
|
166
186
|
|
167
187
|
class Edge(BaseModel):
|
@@ -176,14 +196,14 @@ class TemplateParam(BaseModel):
|
|
176
196
|
|
177
197
|
|
178
198
|
class ProcessorTemplate(BaseModel):
|
179
|
-
elements: dict[str,
|
199
|
+
elements: dict[str, SuperconductingComponentType]
|
180
200
|
edges: list[Edge]
|
181
201
|
|
182
202
|
|
183
203
|
class SuperconductingProcessorTemplate(BaseModel):
|
184
204
|
build: list[TemplateParam]
|
185
205
|
templates: dict[str, ProcessorTemplate]
|
186
|
-
device_parameters: dict[str,
|
206
|
+
device_parameters: dict[str, SuperconductingComponentType] = Field(
|
187
207
|
default={},
|
188
208
|
)
|
189
209
|
|
@@ -20,7 +20,9 @@ __all__ = [
|
|
20
20
|
"Chi01Scan",
|
21
21
|
"ConstantWaveform",
|
22
22
|
"DragCosineWaveform",
|
23
|
+
"DragLeakageCalibration",
|
23
24
|
"Experiment",
|
25
|
+
"FineAmplitudeCalibration",
|
24
26
|
"GaussianWaveform",
|
25
27
|
"HypIterable",
|
26
28
|
"LinspaceIterable",
|
@@ -36,7 +38,9 @@ __all__ = [
|
|
36
38
|
"T2Echo",
|
37
39
|
"TransmonAnharmonicity",
|
38
40
|
"TransmonSpectroscopy",
|
41
|
+
"VoltageBiasFineTune",
|
39
42
|
"Waveform",
|
43
|
+
"ZZRamsey",
|
40
44
|
"update_amplitude",
|
41
45
|
]
|
42
46
|
|
@@ -49,6 +53,8 @@ from .common import (
|
|
49
53
|
LogspaceIterable,
|
50
54
|
RangeIterable,
|
51
55
|
)
|
56
|
+
from .drag_leakage_calibration import DragLeakageCalibration
|
57
|
+
from .fine_amplitude_calibration import FineAmplitudeCalibration
|
52
58
|
from .power_rabi import PowerRabi
|
53
59
|
from .power_rabi_ef import PowerRabiEF
|
54
60
|
from .ramsey import Ramsey
|
@@ -61,6 +67,7 @@ from .t2 import T2
|
|
61
67
|
from .t2_echo import T2Echo
|
62
68
|
from .transmon_anharmonicity import TransmonAnharmonicity
|
63
69
|
from .transmon_spectroscopy import TransmonSpectroscopy
|
70
|
+
from .voltage_bias_fine_tune import VoltageBiasFineTune
|
64
71
|
from .waveforms import (
|
65
72
|
ConstantWaveform,
|
66
73
|
DragCosineWaveform,
|
@@ -68,3 +75,4 @@ from .waveforms import (
|
|
68
75
|
Waveform,
|
69
76
|
update_amplitude,
|
70
77
|
)
|
78
|
+
from .zz_ramsey import ZZRamsey
|
@@ -11,6 +11,8 @@
|
|
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
|
+
from typing import Literal
|
15
|
+
|
14
16
|
from pydantic import PrivateAttr
|
15
17
|
|
16
18
|
from .common import (
|
@@ -22,9 +24,6 @@ from .common import (
|
|
22
24
|
)
|
23
25
|
from .waveforms import ConstantWaveform
|
24
26
|
|
25
|
-
DEFAULT_RECYCLE_DELAY_NS = 10_000
|
26
|
-
DEFAULT_SHOT_COUNT = 100
|
27
|
-
|
28
27
|
|
29
28
|
class Chi01Scan(Experiment):
|
30
29
|
"""
|
@@ -35,12 +34,12 @@ class Chi01Scan(Experiment):
|
|
35
34
|
----------
|
36
35
|
transmon : str
|
37
36
|
The reference for the transmon to target.
|
38
|
-
frequencies : list[int] or LinspaceIterable or RangeIterable or CWSIterable
|
37
|
+
frequencies : list[int] or LinspaceIterable or RangeIterable or CWSIterable \
|
39
38
|
or HypIterable or None, optional
|
40
39
|
The frequencies at which to scan, in Hz.
|
41
40
|
Defaults to a scan around the readout frequency.
|
42
41
|
recycle_delay_ns : int, optional
|
43
|
-
The delay between consecutive shots, in nanoseconds. Defaults to
|
42
|
+
The delay between consecutive shots, in nanoseconds. Defaults to 200,000 ns.
|
44
43
|
shot_count : int, optional
|
45
44
|
The number of shots to take. Defaults to 100.
|
46
45
|
measure_waveform : ConstantWaveform or None, optional
|
@@ -48,6 +47,8 @@ class Chi01Scan(Experiment):
|
|
48
47
|
Defaults to the measurement defcal.
|
49
48
|
run_mixer_calibration: bool
|
50
49
|
Whether to run mixer calibrations before running a program. Defaults to False.
|
50
|
+
update : "auto" or "off" or "prompt", optional
|
51
|
+
How the device should be updated after an experiment run. Defaults to auto.
|
51
52
|
"""
|
52
53
|
|
53
54
|
_experiment_name: str = PrivateAttr("chi01_scan")
|
@@ -56,7 +57,8 @@ class Chi01Scan(Experiment):
|
|
56
57
|
frequencies: list[int] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = (
|
57
58
|
None
|
58
59
|
)
|
59
|
-
recycle_delay_ns: int =
|
60
|
-
shot_count: int =
|
60
|
+
recycle_delay_ns: int = 200_000
|
61
|
+
shot_count: int = 100
|
61
62
|
measure_waveform: ConstantWaveform | None = None
|
62
63
|
run_mixer_calibration: bool = False
|
64
|
+
update: Literal["auto", "off", "prompt"] = "auto"
|
@@ -0,0 +1,66 @@
|
|
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 typing import Literal
|
15
|
+
|
16
|
+
from pydantic import PrivateAttr, field_validator
|
17
|
+
|
18
|
+
from .common import CWSIterable, Experiment
|
19
|
+
|
20
|
+
|
21
|
+
class DragLeakageCalibration(Experiment):
|
22
|
+
"""
|
23
|
+
Parameters for running a DRAG leakage calibration experiment for
|
24
|
+
a specified gate on a transmon.
|
25
|
+
|
26
|
+
Attributes
|
27
|
+
----------
|
28
|
+
transmon : str
|
29
|
+
The reference for the transmon to target.
|
30
|
+
recycle_delay_ns : int
|
31
|
+
The delay between consecutive shots, in nanoseconds. Defaults to 10,000 ns.
|
32
|
+
shot_count : int, optional
|
33
|
+
The number of shots to take. Defaults to 1,000.
|
34
|
+
alphas: list[float] or CWSIterable
|
35
|
+
List of values to sweep for DRAG parameter alpha.
|
36
|
+
repetitions : list[int]
|
37
|
+
List of repetition counts for the calibration experiment.
|
38
|
+
gate : "sx" or "x"
|
39
|
+
The gate to calibrate.
|
40
|
+
anharmonicity : float or None, optional
|
41
|
+
The anharmonicity of the transmon, in Hz.
|
42
|
+
Defaults to None, in which case the anharmonicity of the transmon will be used.
|
43
|
+
drag_guess : float
|
44
|
+
Initial guess for the DRAG parameter.
|
45
|
+
update : "auto" or "off" or "prompt", optional
|
46
|
+
How the device should be updated after an experiment run. Defaults to auto.
|
47
|
+
"""
|
48
|
+
|
49
|
+
_experiment_name: str = PrivateAttr("drag_leakage_calibration")
|
50
|
+
|
51
|
+
transmon: str
|
52
|
+
recycle_delay_ns: int = 10_000
|
53
|
+
shot_count: int = 1_000
|
54
|
+
alphas: list[float] | CWSIterable
|
55
|
+
repetitions: list[int]
|
56
|
+
gate: Literal["x", "sx"]
|
57
|
+
anharmonicity: float | None = None
|
58
|
+
drag_guess: float
|
59
|
+
update: Literal["auto", "off", "prompt"] = "auto"
|
60
|
+
|
61
|
+
@field_validator("alphas")
|
62
|
+
@classmethod
|
63
|
+
def validate_alphas(cls, value: list[float] | CWSIterable):
|
64
|
+
if isinstance(value, CWSIterable) and value.center is None:
|
65
|
+
raise TypeError("The center of alphas must not be None.")
|
66
|
+
return value
|
boulder_opal_scale_up_sdk-1.0.5/boulderopalscaleupsdk/experiments/fine_amplitude_calibration.py
ADDED
@@ -0,0 +1,54 @@
|
|
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 typing import Literal
|
15
|
+
|
16
|
+
from pydantic import Field, PrivateAttr
|
17
|
+
|
18
|
+
from .common import Experiment
|
19
|
+
from .waveforms import ConstantWaveform
|
20
|
+
|
21
|
+
|
22
|
+
class FineAmplitudeCalibration(Experiment):
|
23
|
+
"""
|
24
|
+
Parameters for running a fine amplitude calibration experiment for
|
25
|
+
a specified gate on a transmon.
|
26
|
+
|
27
|
+
Attributes
|
28
|
+
----------
|
29
|
+
transmon : str
|
30
|
+
The reference for the transmon to target.
|
31
|
+
gate : Literal["sx", "x"]
|
32
|
+
The gate to be calibrated.
|
33
|
+
repetitions : list[int]
|
34
|
+
List of repetition counts for the calibration experiment.
|
35
|
+
recycle_delay_ns : int
|
36
|
+
The delay between consecutive shots, in nanoseconds. Defaults to 10,000 ns.
|
37
|
+
shot_count : int, optional
|
38
|
+
The number of shots to take. Defaults to 1000.
|
39
|
+
measure_waveform : ConstantWaveform or None, optional
|
40
|
+
The waveform to use for the measurement pulse.
|
41
|
+
Defaults to the measurement defcal.
|
42
|
+
update : "auto" or "off" or "prompt", optional
|
43
|
+
How the device should be updated after an experiment run. Defaults to auto.
|
44
|
+
"""
|
45
|
+
|
46
|
+
_experiment_name: str = PrivateAttr("fine_amplitude_calibration")
|
47
|
+
|
48
|
+
transmon: str
|
49
|
+
gate: Literal["sx", "x"]
|
50
|
+
repetitions: list[int] = Field(default=list(range(0, 100, 4)))
|
51
|
+
recycle_delay_ns: int = 10_000
|
52
|
+
shot_count: int = 1000
|
53
|
+
measure_waveform: ConstantWaveform | None = None
|
54
|
+
update: Literal["auto", "off", "prompt"] = "auto"
|
@@ -11,6 +11,8 @@
|
|
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
|
+
from typing import Literal
|
15
|
+
|
14
16
|
from pydantic import PrivateAttr
|
15
17
|
|
16
18
|
from .common import (
|
@@ -22,25 +24,23 @@ from .common import (
|
|
22
24
|
)
|
23
25
|
from .waveforms import ConstantWaveform, Waveform
|
24
26
|
|
25
|
-
DEFAULT_SHOT_COUNT = 400
|
26
|
-
|
27
27
|
|
28
28
|
class PowerRabi(Experiment):
|
29
29
|
"""
|
30
30
|
Parameters for running a Power Rabi experiment.
|
31
31
|
|
32
|
-
|
32
|
+
Attributes
|
33
33
|
----------
|
34
34
|
transmon : str
|
35
35
|
The reference for the transmon to target.
|
36
|
-
scales : list[float] or LinspaceIterable or RangeIterable
|
36
|
+
scales : list[float] or LinspaceIterable or RangeIterable \
|
37
37
|
or CWSIterable or HypIterable or None, optional
|
38
38
|
The scaling factors for the drive pulse amplitude.
|
39
39
|
If None, a default scan will be used.
|
40
40
|
drive_waveform : Waveform
|
41
41
|
The waveform to use for the drive pulse.
|
42
42
|
recycle_delay_ns : int
|
43
|
-
The delay between consecutive shots, in nanoseconds.
|
43
|
+
The delay between consecutive shots, in nanoseconds. Defaults to 200,000 ns.
|
44
44
|
shot_count : int, optional
|
45
45
|
The number of shots to take. Defaults to 400.
|
46
46
|
pulse_vp : float, optional
|
@@ -50,6 +50,8 @@ class PowerRabi(Experiment):
|
|
50
50
|
Defaults to the measurement defcal.
|
51
51
|
run_mixer_calibration: bool
|
52
52
|
Whether to run mixer calibrations before running a program. Defaults to False.
|
53
|
+
update : "auto" or "off" or "prompt", optional
|
54
|
+
How the device should be updated after an experiment run. Defaults to auto.
|
53
55
|
"""
|
54
56
|
|
55
57
|
_experiment_name: str = PrivateAttr("power_rabi")
|
@@ -57,8 +59,9 @@ class PowerRabi(Experiment):
|
|
57
59
|
transmon: str
|
58
60
|
scales: list[float] | LinspaceIterable | RangeIterable | CWSIterable | HypIterable | None = None
|
59
61
|
drive_waveform: Waveform
|
60
|
-
recycle_delay_ns: int
|
61
|
-
shot_count: int =
|
62
|
+
recycle_delay_ns: int = 200_000
|
63
|
+
shot_count: int = 400
|
62
64
|
pulse_vp: float | None = None
|
63
65
|
measure_waveform: ConstantWaveform | None = None
|
64
66
|
run_mixer_calibration: bool = False
|
67
|
+
update: Literal["auto", "off", "prompt"] = "auto"
|