QuEL-3 deploy check¶
This notebook builds an instrument configuration from the target registry and deploys it through a QuEL-3 controller connected to your quelware server.
Choose system_id = "144Q-LF-Q3" for deployment. QuEL-1 example selections support configuration loading only.
Each InstrumentSpec contains a unit-qualified port ID, alias, role, and minimum/maximum frequency in Hz. An InstrumentConfiguration groups these specifications. Deploy replaces every instrument on each touched port; include all instruments that should remain there.
from pathlib import Path
from qubex.backend.backend_controller import BACKEND_KIND_QUEL3
from qubex.backend.quel3 import InstrumentConfiguration, Quel3BackendController
from qubex.system.config_loader import ConfigLoader
from qubex.system.quel3 import Quel3TargetDeployPlanner
# Example selection
system_id = "144Q-LF-Q3"
supported_system_ids = {"64Q-HF-Q1", "144Q-LF-Q1", "144Q-LF-Q3"}
if system_id not in supported_system_ids:
raise ValueError(f"Unsupported system_id: {system_id}")
candidate_root_dirs = [
Path.cwd(),
Path.cwd() / "docs/examples/system",
Path.cwd().parent,
Path.cwd().parent.parent,
]
example_root = next(
(
path
for path in candidate_root_dirs
if (path / "config").is_dir() and (path / "params").is_dir()
),
None,
)
if example_root is None:
raise FileNotFoundError(
"Could not find `docs/examples/system/{config,params}` from the current working directory."
)
config_dir = example_root / "config"
params_dir = example_root / "params" / system_id
server_host = "localhost"
server_port = 50051
client_mode = "server"
deploy_roles: set[str] | None = None
box_ids: list[str] = []
print(f"example_root: {example_root.resolve()}")
print(f"system_id: {system_id}")
print(f"server: {server_host}:{server_port}")
print(f"client_mode: {client_mode}")
print(f"deploy_roles: {sorted(deploy_roles) if deploy_roles is not None else 'ALL'}")
print(f"config_dir: {config_dir.resolve()}")
print(f"params_dir: {params_dir.resolve()}")
loader = ConfigLoader(
system_id=system_id,
config_dir=config_dir,
params_dir=params_dir,
autoload=False,
)
loader.load()
experiment_system = loader.get_experiment_system()
configured_box_ids = [box.id for box in experiment_system.boxes]
if len(box_ids) == 0:
box_ids = configured_box_ids
is_quel3_backend = loader.backend_kind == BACKEND_KIND_QUEL3
controller = (
Quel3BackendController(
quelware_endpoint=server_host,
quelware_port=server_port,
client_mode=client_mode,
)
if is_quel3_backend
else None
)
readout_targets_by_box: dict[str, list[str]] = {}
for label, target in sorted(experiment_system.gen_targets.items()):
if target.type.value != "READ":
continue
readout_targets_by_box.setdefault(target.channel.port.box_id, []).append(label)
print("backend_kind:", loader.backend_kind)
print("system_id:", loader.system_id)
print("chip_id:", loader.chip_id)
print("boxes in system:", configured_box_ids)
print("boxes to deploy:", box_ids)
print("#gen_targets:", len(experiment_system.gen_targets))
print("deploy enabled:", is_quel3_backend)
if controller is not None:
print("controller client_mode:", controller.client_mode)
print("readout targets by box:")
for box_id, labels in sorted(readout_targets_by_box.items()):
print(f"- {box_id}: {tuple(labels)}")
if "quel3-02-a01" in readout_targets_by_box:
unit_readout_targets = tuple(readout_targets_by_box["quel3-02-a01"])
print(
"quel3-02-a01 readout target check:",
unit_readout_targets == ("RQ000", "RQ001", "RQ002", "RQ003"),
)
else:
unit_readout_targets = ()
print("quel3-02-a01 not present in current example.")
planner = Quel3TargetDeployPlanner()
configuration = InstrumentConfiguration()
unit_labels: list[str] = []
if is_quel3_backend:
all_configuration = planner.build_configuration(
experiment_system=experiment_system,
box_ids=box_ids,
)
configuration = InstrumentConfiguration(
instruments=tuple(
spec
for spec in all_configuration.instruments
if deploy_roles is None or spec.role in deploy_roles
)
)
unit_labels = sorted(
{spec.port_id.split(":", 1)[0] for spec in configuration.instruments}
)
role_counts: dict[str, int] = {}
for spec in configuration.instruments:
role_counts[spec.role] = role_counts.get(spec.role, 0) + 1
print("planned instruments:", len(all_configuration.instruments))
print("selected instruments:", len(configuration.instruments))
print("unit labels:", unit_labels)
print("role counts:", role_counts)
for spec in configuration.instruments:
print(
f"- port_id={spec.port_id}, alias={spec.alias}, role={spec.role}, "
f"range=[{spec.frequency_range_min_hz:.3e}, {spec.frequency_range_max_hz:.3e}]"
)
else:
print("Loaded non-QuEL-3 example set. Instrument configuration preview is skipped.")
The next cells access your hardware. Use a full quelware server endpoint exposing the required APIs.
Hardware-state inspection is an independent diagnostic snapshot. Individual read failures appear as issues, so a snapshot can be partial. It does not populate the execution cache.
if controller is None:
print("Skipping preflight: loaded example is not QuEL-3.")
elif not configuration.instruments:
raise ValueError("No instrument specifications were built.")
else:
controller.connect()
controller.print_hardware_state(unit_labels=unit_labels, view="ports")
if controller is None:
print("Skipping deploy: loaded example is not QuEL-3.")
deployed = {}
else:
deployed = controller.deploy_instruments(configuration=configuration)
print("deployed instrument aliases:", tuple(deployed))
for alias, info in deployed.items():
print(f"- {alias}: resource_id={info.id}, port_id={info.port_id}")
if controller is not None:
cached_configuration = controller.get_instrument_configuration()
print("cached instrument specifications:", len(cached_configuration.instruments))
Inspect and save instrument configuration¶
Explicitly refresh the selected units before exporting their current configuration. Get and save read the controller's cache. YAML contains only the five specification fields; resource IDs and driver configuration remain hardware-acquired runtime data.
Load returns configuration data without hardware access or runtime state changes. Apply a loaded configuration explicitly with controller.deploy_instruments(configuration=loaded).
SystemManager pull updates diagnostic backend-settings snapshots independently of the execution cache.
if controller is not None:
controller.refresh_instrument_cache(unit_labels=unit_labels)
current_configuration = controller.get_instrument_configuration()
configuration_path = example_root / "quel3_instruments.yaml"
saved_path = controller.save_instrument_configuration(configuration_path)
loaded = controller.load_instrument_configuration(saved_path)
assert loaded == current_configuration
print("saved configuration:", saved_path)
print("loaded specifications:", len(loaded.instruments))