Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions quam_builder/architecture/superconducting/qpu/base_quam.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from dataclasses import field
from typing import List, Dict, ClassVar, Optional, Union
from typing import List, Dict, ClassVar, Optional, Type, Union, cast

from qm import QuantumMachinesManager, QuantumMachine
from qm.octave import QmOctaveConfig
Expand All @@ -14,6 +14,7 @@

from quam_builder.architecture.superconducting.qubit_pair import AnyTransmonPair
from quam_builder.architecture.superconducting.qubit import AnyTransmon
from quam_builder.tools import load_class_from_string

from qualang_tools.results.data_handler import DataHandler

Expand Down Expand Up @@ -89,14 +90,30 @@ def connect(self) -> QuantumMachinesManager:
Returns:
QuantumMachinesManager: The opened Quantum Machine Manager.
"""
settings = dict(
host=self.network["host"],
cluster_name=self.network["cluster_name"],
octave=self.get_octave_config(),
)
if "port" in self.network:
settings["port"] = self.network["port"]
self.qmm = QuantumMachinesManager(**settings)

if self.network.get("cloud", False):
if "qmm_settings" not in self.network:
raise ValueError(
"machine.network.qmm_settings is required for cloud connection"
)
if "qmm_class" not in self.network:
raise ValueError(
"machine.network.qmm_class is required for cloud connection"
)

qmm_cls = load_class_from_string(self.network["qmm_class"])
qmm_cls = cast(Type[QuantumMachinesManager], qmm_cls)
qmm_settings = self.network["qmm_settings"]
else:
qmm_cls = QuantumMachinesManager
qmm_settings = dict(
host=self.network["host"],
cluster_name=self.network["cluster_name"],
octave=self.get_octave_config(),
)
if "port" in self.network:
qmm_settings["port"] = self.network["port"]
self.qmm = qmm_cls(**qmm_settings)
return self.qmm

def calibrate_octave_ports(self, QM: QuantumMachine) -> None:
Expand Down
10 changes: 9 additions & 1 deletion quam_builder/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,15 @@
get_output_power_iq_channel,
get_output_power_mw_channel,
)
from quam_builder.tools.import_utils import (
load_class_from_string,
)

__all__ = [
*power_tools.__all__,
"calculate_voltage_scaling_factor",
"set_output_power_mw_channel",
"set_output_power_iq_channel",
"get_output_power_iq_channel",
"get_output_power_mw_channel",
"load_class_from_string",
]
37 changes: 37 additions & 0 deletions quam_builder/tools/import_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Utilities for dynamic class loading and imports."""

import importlib
from typing import Type, TypeVar

__all__ = ["load_class_from_string"]

T = TypeVar("T")


def load_class_from_string(class_path: str) -> Type[T]:
"""Load a class dynamically from a string path.

Args:
class_path: Full path to the class in the format 'module.ClassName'.

Returns:
The class type.

Raises:
ValueError: If the class_path format is invalid.
ImportError: If the module or class cannot be imported.

Example:
>>> MyClass = load_class_from_string("my_module.MyClass")
>>> instance = MyClass()
"""
if "." not in class_path:
raise ValueError(
"class_path should be a full path in the format 'module.ClassName'"
)
module_path, class_name = class_path.rsplit(".", 1)
try:
module = importlib.import_module(module_path)
return getattr(module, class_name)
except (ModuleNotFoundError, AttributeError) as e:
raise ImportError(f"Could not import class '{class_path}': {e}")