Source code for qcodes.parameters.grouped_parameter

from __future__ import annotations

import logging
from collections import OrderedDict, namedtuple
from typing import TYPE_CHECKING, Any

from .delegate_parameter import DelegateParameter
from .group_parameter import Group, GroupParameter
from .parameter_base import ParamDataType, ParameterBase, ParamRawDataType

if TYPE_CHECKING:
    from collections.abc import Callable, Iterable, Mapping, Sequence

    from qcodes.instrument.base import InstrumentBase

    from .parameter import Parameter


_log = logging.getLogger(__name__)


[docs] class DelegateGroupParameter(DelegateParameter, GroupParameter): def __init__( self, name: str, source: Parameter | None, instrument: InstrumentBase | None = None, initial_value: float | str | None = None, **kwargs: Any, ) -> None: super().__init__( name=name, source=source, instrument=instrument, initial_value=initial_value, **kwargs, )
[docs] class DelegateGroup(Group): """The DelegateGroup combines :class:`.DelegateParameter` s that are to be gotten or set using one :class:`.GroupedParameter`. Each :class:`.DelegateParameter` maps to one source parameter that is individually set or gotten on an instrument. These parameters can originate from the same or different instruments. The class :class:`.DelegateGroup` is used within the :class:`GroupedParameter` class in order to get and set the :class:`.DelegateParameter` s either via their default get and set methods or via a custom get or set method. The value to be set can be passed to the set method either via a dictionary, where the keys are the names of the :class:`.DelegateParameter` s contained in the :class:`DelegateGroup`, or a single value, if a custom setter is defined or if the group only contains a single :class:`.DelegateParameter`. The value returned by the get method is passed through a formatter. By default, the formatter returns the :class:`.DelegateParameter` values in a namedtuple, where the keys are the names of the :class:`.DelegateParameter` s. In the special case where the :class:`.DelegateGroup` only contains one :class:`.DelegateParameter`, the formatter simply returns the individual value. Optionally, the formatter can be customized and specified via the constructor. The formatter takes as input the values of the :class:`.DelegateParameter` s as positional arguments in the order at which the :class:`.DelegateParameter` s are specified. Args: name: Name of the DelegateGroup parameters: DelegateParameters to group together parameter_names: Optional names of parameters, defaults to the parameter `name` attributes setter: Optional function to call for setting the grouped parameters, should take one argument `value`. Defaults to set_parameters(), which sets each parameter using its .set() method. getter: Optional function to call for getting the grouped parameters. Defaults to .get_parameters(), which runs the get() method for each parameter. formatter: Optional formatter for value returned by get_parameters(), defaults to a namedtuple with the parameter names as keys. """ def __init__( self, name: str, parameters: Sequence[DelegateGroupParameter], parameter_names: Iterable[str] | None = None, setter: Callable[..., Any] | None = None, getter: Callable[..., Any] | None = None, formatter: Callable[..., Any] | None = None, **kwargs: Any, ): super().__init__(parameters=parameters, single_instrument=False, **kwargs) self.name = name self._parameter_names = parameter_names or [_e.name for _e in parameters] self._set_fn = setter self._get_fn = getter self._params = parameters self._parameters = OrderedDict(zip(self._parameter_names, parameters)) if formatter is None and len(parameters) == 1: self._formatter = lambda result: result elif formatter is None: self._formatter = self._namedtuple else: self._formatter = formatter def _namedtuple(self, *args: Any, **kwargs: Any) -> tuple[Any, ...]: return namedtuple(self.name, self._parameter_names)(*args, **kwargs)
[docs] def set(self, value: ParamDataType | Mapping[str, ParamDataType]) -> None: if self._set_fn is not None: self._set_fn(value) else: if not isinstance(value, dict): value = {name: value for name in self._parameter_names} self.set_parameters(value)
[docs] def get(self) -> Any: if self._get_fn is not None: return self._get_fn() else: return self.get_parameters()
[docs] def get_parameters(self) -> Any: return self._formatter(*(_p.get() for _p in self.parameters.values()))
def _set_from_dict(self, calling_dict: Mapping[str, ParamRawDataType]) -> None: for name, p in list(self.parameters.items()): p.set(calling_dict[name]) @property def source_parameters(self) -> tuple[Parameter | None, ...]: """Get source parameters of each DelegateParameter""" return tuple(p.source for p in self._params)
[docs] class GroupedParameter(ParameterBase): """ The GroupedParameter wraps one or more :class:`.DelegateParameter` s, such that those parameters can be accessed as if they were one parameter. The :class:`GroupedParameter` uses a :class:`DelegateGroup` to keep track of the :class:`.DelegateParameter` s. Mainly, this class is a thin wrapper around the :class:`DelegateGroup`, and mainly exists in order to allow for it to be used as a :class:`ParameterBase`. This class can be seen as the opposite of a :class:`GroupParameter`, which is a class to create parameters that are set with a single get and set string command on *the same* instrument but need to be accessed separately. In contrast, the :class:`GroupedParameter` allows grouped access to parameters that are normally separate, and can be associated with *different* instruments. Args: name: Grouped parameter name. group: Group that contains the target parameter(s). unit: The unit of measure. Use ``''`` for unitless. label: Optional label, defaults to parameter name. default set method(s). """ def __init__( self, name: str, group: DelegateGroup, unit: str | None = None, label: str | None = None, **kwargs: Any, ): super().__init__(name, **kwargs) self.label = name if label is None else label self.unit = unit if unit is not None else "" self._group = group @property def group(self) -> DelegateGroup: """ The group that contains the target parameters. """ return self._group @property def parameters(self) -> dict[str, GroupParameter]: """Get delegate parameters wrapped by this GroupedParameter""" return self.group.parameters @property def source_parameters(self) -> tuple[Parameter | None, ...]: """Get source parameters of each DelegateParameter""" return self.group.source_parameters
[docs] def get_raw(self) -> ParamDataType | Mapping[str, ParamDataType]: """Get parameter raw value""" return self.group.get_parameters()
[docs] def set_raw(self, value: ParamDataType | Mapping[str, ParamDataType]) -> None: """Set parameter raw value Args: value: Parameter value to set Returns: float: Returns the parameter value """ self.group.set(value)
def __repr__(self) -> str: output = f"GroupedParameter(name={self.name}" if self.source_parameters: source_parameters = ", ".join(str(_) for _ in self.source_parameters) output += f", source_parameters=({source_parameters})" output += ")" return output