diff --git a/src/qcodes/instrument_drivers/CopperMountain/_M5xxx.py b/src/qcodes/instrument_drivers/CopperMountain/_M5xxx.py index 976a859a297a..778918cd2e6f 100644 --- a/src/qcodes/instrument_drivers/CopperMountain/_M5xxx.py +++ b/src/qcodes/instrument_drivers/CopperMountain/_M5xxx.py @@ -7,6 +7,7 @@ from qcodes.parameters import ( ManualParameter, MultiParameter, + MultiParameterKWArgs, Parameter, ParamRawDataType, create_on_off_val_mapping, @@ -637,9 +638,9 @@ def __init__( start: float, stop: float, number_of_points: int, - instrument: CopperMountainM5xxx, + *, expected_measurement_duration: float = 600, - **kwargs: Any, + **kwargs: "Unpack[MultiParameterKWArgs[tuple[NDArray, NDArray], CopperMountainM5xxx]]", ) -> None: """ Linear frequency sweep that returns magnitude and phase for a single @@ -650,40 +651,57 @@ def __init__( start: Start frequency of linear sweep stop: Stop frequency of linear sweep number_of_points: Number of points of linear sweep - instrument: Instrument to which sweep is bound to. expected_measurement_duration: Adjusts instrument timeout (seconds). Defaults to 600 seconds. - **kwargs: Any + **kwargs: Keyword arguments forwarded to MultiParameter. """ self.expected_measurement_duration = expected_measurement_duration - super().__init__( - name, - instrument=instrument, - names=( + instrument = kwargs.get("instrument") + assert instrument is not None + + kw: dict[str, Any] = dict(kwargs) + kw.setdefault( + "names", + ( f"{instrument.short_name}_{name}_magnitude", f"{instrument.short_name}_{name}_phase", ), - labels=( + ) + kw.setdefault( + "labels", + ( f"{instrument.short_name} {name} magnitude", f"{instrument.short_name} {name} phase", ), - units=("dB", "rad"), - setpoint_units=(("Hz",), ("Hz",)), - setpoint_labels=( + ) + kw.setdefault("units", ("dB", "rad")) + kw.setdefault("setpoint_units", (("Hz",), ("Hz",))) + kw.setdefault( + "setpoint_labels", + ( (f"{instrument.short_name} frequency",), (f"{instrument.short_name} frequency",), ), - setpoint_names=( + ) + kw.setdefault( + "setpoint_names", + ( (f"{instrument.short_name}_frequency",), (f"{instrument.short_name}_frequency",), ), - shapes=( + ) + kw.setdefault( + "shapes", + ( (number_of_points,), (number_of_points,), ), - **kwargs, + ) + super().__init__( + name, + **kw, ) self.set_sweep(start, stop, number_of_points) @@ -746,44 +764,46 @@ class PointMagPhase( def __init__( self, name: str, - instrument: CopperMountainM5xxx, + *, expected_measurement_duration: float = 600, - **kwargs: Any, + **kwargs: "Unpack[MultiParameterKWArgs[tuple[np.floating, np.floating], CopperMountainM5xxx]]", ) -> None: """Magnitude and phase measurement of a single point at start frequency. Args: name: Name of point measurement - instrument: Instrument to which parameter is bound to. expected_measurement_duration: Adjusts instrument timeout (seconds). Defaults to 600 seconds. - **kwargs: Any + **kwargs: Keyword arguments forwarded to MultiParameter. """ self.expected_measurement_duration = expected_measurement_duration - super().__init__( - name, - instrument=instrument, - names=( + instrument = kwargs.get("instrument") + assert instrument is not None + + kw: dict[str, Any] = dict(kwargs) + kw.setdefault( + "names", + ( f"{instrument.short_name}_{name}_magnitude", f"{instrument.short_name}_{name}_phase", ), - labels=( + ) + kw.setdefault( + "labels", + ( f"{instrument.short_name} {name} magnitude", f"{instrument.short_name} {name} phase", ), - units=("dB", "rad"), - setpoints=( - (), - (), - ), - shapes=( - (), - (), - ), - **kwargs, + ) + kw.setdefault("units", ("dB", "rad")) + kw.setdefault("setpoints", ((), ())) + kw.setdefault("shapes", ((), ())) + super().__init__( + name, + **kw, ) def get_raw(self) -> tuple[ParamRawDataType, ParamRawDataType]: @@ -844,44 +864,46 @@ class PointIQ(MultiParameter[tuple[np.floating, np.floating], CopperMountainM5xx def __init__( self, name: str, - instrument: CopperMountainM5xxx, + *, expected_measurement_duration: float = 600, - **kwargs: Any, + **kwargs: "Unpack[MultiParameterKWArgs[tuple[np.floating, np.floating], CopperMountainM5xxx]]", ) -> None: """I and Q measurement of a single point at start frequency. Args: name: Name of point measurement - instrument: Instrument to which parameter is bound to. expected_measurement_duration: Adjusts instrument timeout (seconds). Defaults to 600 seconds. - **kwargs: Any + **kwargs: Keyword arguments forwarded to MultiParameter. """ self.expected_measurement_duration = expected_measurement_duration - super().__init__( - name, - instrument=instrument, - names=( + instrument = kwargs.get("instrument") + assert instrument is not None + + kw: dict[str, Any] = dict(kwargs) + kw.setdefault( + "names", + ( f"{instrument.short_name}_{name}_i", f"{instrument.short_name}_{name}_q", ), - labels=( + ) + kw.setdefault( + "labels", + ( f"{instrument.short_name} {name} i", f"{instrument.short_name} {name} q", ), - units=("V", "V"), - setpoints=( - (), - (), - ), - shapes=( - (), - (), - ), - **kwargs, + ) + kw.setdefault("units", ("V", "V")) + kw.setdefault("setpoints", ((), ())) + kw.setdefault("shapes", ((), ())) + super().__init__( + name, + **kw, ) def get_raw(self) -> tuple[ParamRawDataType, ParamRawDataType]: diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py index b678f697058c..76acaaa81ec1 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py @@ -13,6 +13,8 @@ DelegateParameter, MultiParameter, Parameter, + ParameterBaseKWArgs, + ParameterKWArgs, ParamRawDataType, create_on_off_val_mapping, invert_val_mapping, @@ -38,13 +40,19 @@ def __init__( names: "Sequence[str]", shapes: "Sequence[Sequence[int]]", setpoints: "Sequence[Sequence[Any]] | None", - **kwargs: Any, + units: "Sequence[str] | None" = None, + setpoint_units: "Sequence[Sequence[str]] | None" = None, + setpoint_names: "Sequence[Sequence[str]] | None" = None, + **kwargs: "Unpack[ParameterBaseKWArgs]", ): super().__init__( name="data_array_7510", names=names, shapes=shapes, setpoints=setpoints, + units=units, + setpoint_units=setpoint_units, + setpoint_names=setpoint_names, **kwargs, ) for param_name in self.names: @@ -65,10 +73,11 @@ def __init__( start: Parameter, stop: Parameter, n_points: Parameter, - *args: Any, - **kwargs: Any, + *, + name: str, + **kwargs: "Unpack[ParameterKWArgs]", ): - super().__init__(*args, **kwargs) + super().__init__(name, **kwargs) self._start = start self._stop = stop self._n_points = n_points diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py b/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py index 11b7901dc3a4..be44dc036a14 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py @@ -4,13 +4,13 @@ import re from itertools import product -from typing import TYPE_CHECKING, Any, ClassVar +from typing import TYPE_CHECKING, ClassVar from qcodes.instrument import ( VisaInstrument, VisaInstrumentKWArgs, ) -from qcodes.parameters import Parameter, ParamRawDataType +from qcodes.parameters import Parameter, ParameterKWArgs, ParamRawDataType if TYPE_CHECKING: from typing_extensions import Unpack @@ -72,12 +72,12 @@ class S46Parameter(Parameter[ParamRawDataType, "KeithleyS46"]): def __init__( self, name: str, - instrument: "KeithleyS46", + *, channel_number: int, lock: KeithleyS46RelayLock, - **kwargs: Any, + **kwargs: "Unpack[ParameterKWArgs[ParamRawDataType, KeithleyS46]]", ): - super().__init__(name, instrument=instrument, **kwargs) + super().__init__(name, **kwargs) self._lock = lock self._channel_number = channel_number diff --git a/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py b/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py index bf90ee188f3a..2e50b05e7847 100644 --- a/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py +++ b/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py @@ -20,6 +20,7 @@ from qcodes.parameters import ( Parameter, ParameterBase, + ParameterKWArgs, ParameterWithSetpoints, ParamRawDataType, create_on_off_val_mapping, @@ -544,8 +545,8 @@ class Keithley2600MeasurementStatus(StrEnum): class _ParameterWithStatus(Parameter): - def __init__(self, *args: Any, **kwargs: Any): - super().__init__(*args, **kwargs) + def __init__(self, name: str, **kwargs: Unpack[ParameterKWArgs]): + super().__init__(name, **kwargs) self._measurement_status: Keithley2600MeasurementStatus | None = None diff --git a/src/qcodes/instrument_drivers/Keysight/Infiniium.py b/src/qcodes/instrument_drivers/Keysight/Infiniium.py index e411beed9cff..8ad82fcfc7bb 100644 --- a/src/qcodes/instrument_drivers/Keysight/Infiniium.py +++ b/src/qcodes/instrument_drivers/Keysight/Infiniium.py @@ -25,7 +25,9 @@ from qcodes.parameters import ( Parameter, ParameterBase, + ParameterKWArgs, ParameterWithSetpoints, + ParameterWithSetpointsKWArgs, create_on_off_val_mapping, ) from qcodes.utils.deprecate import QCoDeSDeprecationWarning @@ -41,12 +43,20 @@ class DSOTimeAxisParam(Parameter): Time axis parameter for the Infiniium series DSO. """ - def __init__(self, xorigin: float, xincrement: float, points: int, **kwargs: Any): + def __init__( + self, + xorigin: float, + xincrement: float, + points: int, + *, + name: str, + **kwargs: "Unpack[ParameterKWArgs]", + ): """ Initialize time axis. If values are unknown, they can be initialized to zero and filled in later. """ - super().__init__(**kwargs) + super().__init__(name, **kwargs) self.xorigin = xorigin self.xincrement = xincrement @@ -69,12 +79,20 @@ class DSOFrequencyAxisParam(Parameter): Frequency axis parameter for the Infiniium series DSO. """ - def __init__(self, xorigin: float, xincrement: float, points: int, **kwargs: Any): + def __init__( + self, + xorigin: float, + xincrement: float, + points: int, + *, + name: str, + **kwargs: "Unpack[ParameterKWArgs]", + ): """ Initialize frequency axis. If values are unknown, they can be initialized to zero and filled in later. """ - super().__init__(**kwargs) + super().__init__(name, **kwargs) self.xorigin = xorigin self.xincrement = xincrement @@ -113,15 +131,15 @@ class DSOTraceParam( def __init__( self, name: str, - instrument: "KeysightInfiniiumChannel | KeysightInfiniiumFunction", + *, channel: str, - **kwargs: Any, + **kwargs: "Unpack[ParameterWithSetpointsKWArgs[npt.NDArray, KeysightInfiniiumChannel | KeysightInfiniiumFunction]]", ): """ Initialize DSOTraceParam bound to a specific channel. """ self._ch_valid = False - super().__init__(name, instrument=instrument, **kwargs) + super().__init__(name, **kwargs) self._channel = channel # This parameter will be updated prior to being retrieved if # self.root_instrument.auto_digitize is true. diff --git a/src/qcodes/instrument_drivers/Keysight/Keysight_N9030B.py b/src/qcodes/instrument_drivers/Keysight/Keysight_N9030B.py index 4680cf1c17cc..2a26adccaf7a 100644 --- a/src/qcodes/instrument_drivers/Keysight/Keysight_N9030B.py +++ b/src/qcodes/instrument_drivers/Keysight/Keysight_N9030B.py @@ -14,7 +14,9 @@ ) from qcodes.parameters import ( Parameter, + ParameterKWArgs, ParameterWithSetpoints, + ParameterWithSetpointsKWArgs, ParamRawDataType, create_on_off_val_mapping, ) @@ -45,10 +47,11 @@ def __init__( start: Parameter[float, _T], stop: Parameter[float, _T], npts: Parameter[int, _T], - *args: Any, - **kwargs: Any, + *, + name: str, + **kwargs: Unpack[ParameterKWArgs[npt.NDArray[np.float64], _T]], ) -> None: - super().__init__(*args, **kwargs) + super().__init__(name, **kwargs) self._start = start self._stop = stop self._npts = npts @@ -68,11 +71,12 @@ class Trace( def __init__( self, number: int, - *args: Any, + *, + name: str, get_data: Callable[[int], ParameterDataTypeVar], - **kwargs: Any, + **kwargs: Unpack[ParameterWithSetpointsKWArgs[ParameterDataTypeVar, _T]], ) -> None: - super().__init__(*args, **kwargs) + super().__init__(name, **kwargs) # while the parameter classes should ideally be generic in instrument # type it is not generic in the root instrument type self.root_instrument: KeysightN9030B diff --git a/src/qcodes/instrument_drivers/Keysight/N52xx.py b/src/qcodes/instrument_drivers/Keysight/N52xx.py index 66f0e15cf139..51df31c91fcb 100644 --- a/src/qcodes/instrument_drivers/Keysight/N52xx.py +++ b/src/qcodes/instrument_drivers/Keysight/N52xx.py @@ -17,7 +17,9 @@ from qcodes.parameters import ( Parameter, ParameterBase, + ParameterKWArgs, ParameterWithSetpoints, + ParameterWithSetpointsKWArgs, create_on_off_val_mapping, ) from qcodes.validators import Arrays, Bool, Enum, Ints, Numbers @@ -31,15 +33,17 @@ class PNAAxisParameter(Parameter): def __init__( self, + *, + name: str, startparam: Parameter, stopparam: Parameter, pointsparam: Parameter, - **kwargs: Any, + **kwargs: "Unpack[ParameterKWArgs]", ): """ Axis parameter for traces from the PNA """ - super().__init__(**kwargs) + super().__init__(name, **kwargs) self._startparam = startparam self._stopparam = stopparam @@ -79,14 +83,12 @@ class FormattedSweep(ParameterWithSetpoints[npt.NDArray, "KeysightPNATrace"]): def __init__( self, name: str, - instrument: "KeysightPNATrace", + *, sweep_format: str, - label: str, - unit: str, memory: bool = False, - **kwargs: Any, + **kwargs: "Unpack[ParameterWithSetpointsKWArgs[npt.NDArray, KeysightPNATrace]]", ) -> None: - super().__init__(name, instrument=instrument, label=label, unit=unit, **kwargs) + super().__init__(name, **kwargs) self.sweep_format = sweep_format self.memory = memory diff --git a/src/qcodes/instrument_drivers/Keysight/keysight_e4980a.py b/src/qcodes/instrument_drivers/Keysight/keysight_e4980a.py index 76fe3c0383b4..1975040e7650 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysight_e4980a.py +++ b/src/qcodes/instrument_drivers/Keysight/keysight_e4980a.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING from packaging import version from pyvisa.errors import VisaIOError @@ -16,6 +16,7 @@ ManualParameter, MultiParameter, Parameter, + ParameterBaseKWArgs, ParamRawDataType, create_on_off_val_mapping, ) @@ -54,7 +55,11 @@ class KeysightE4980AMeasurementPair(MultiParameter): value: tuple[float, float] = (0.0, 0.0) def __init__( - self, name: str, names: "Sequence[str]", units: "Sequence[str]", **kwargs: Any + self, + name: str, + names: "Sequence[str]", + units: "Sequence[str]", + **kwargs: "Unpack[ParameterBaseKWArgs]", ): super().__init__( name=name, diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py index a14786bcf7fb..0b350fe6952d 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py @@ -4,7 +4,12 @@ from typing import TYPE_CHECKING, Any, Generic, TypedDict, cast from qcodes.instrument import VisaInstrument, VisaInstrumentKWArgs -from qcodes.parameters import MultiParameter, Parameter, create_on_off_val_mapping +from qcodes.parameters import ( + MultiParameter, + MultiParameterKWArgs, + Parameter, + create_on_off_val_mapping, +) from qcodes.parameters.parameter_base import ParameterDataTypeVar from . import constants @@ -512,18 +517,22 @@ class IVSweepMeasurement( """ - def __init__(self, name: str, instrument: KeysightB1500, **kwargs: Any): + def __init__( + self, + name: str, + **kwargs: "Unpack[MultiParameterKWArgs[ParameterDataTypeVar, KeysightB1500]]", + ): + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("names", tuple(["param1", "param2"])) + kw.setdefault("units", tuple(["A", "A"])) + kw.setdefault("labels", tuple(["Param1 Current", "Param2 Current"])) + kw.setdefault("shapes", ((1,),) * 2) + kw.setdefault("setpoint_names", (("Voltage",),) * 2) + kw.setdefault("setpoint_labels", (("Voltage",),) * 2) + kw.setdefault("setpoint_units", (("V",),) * 2) super().__init__( name, - names=tuple(["param1", "param2"]), - units=tuple(["A", "A"]), - labels=tuple(["Param1 Current", "Param2 Current"]), - shapes=((1,),) * 2, - setpoint_names=(("Voltage",),) * 2, - setpoint_labels=(("Voltage",),) * 2, - setpoint_units=(("V",),) * 2, - instrument=instrument, - **kwargs, + **kw, ) self.param1 = _FMTResponse(None, None, None, None) diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_sampling_measurement.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_sampling_measurement.py index dbe422d06d28..a6f4100c820c 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_sampling_measurement.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_sampling_measurement.py @@ -1,10 +1,10 @@ import warnings -from typing import TYPE_CHECKING, Any, cast +from typing import TYPE_CHECKING, cast import numpy import numpy.typing as npt -from qcodes.parameters import ParameterWithSetpoints +from qcodes.parameters import ParameterWithSetpoints, ParameterWithSetpointsKWArgs from . import constants from .KeysightB1500_module import ( @@ -16,11 +16,13 @@ from .message_builder import MessageBuilder if TYPE_CHECKING: + from typing_extensions import Unpack + from .KeysightB1500_base import ( KeysightB1500, ) from .KeysightB1517A import ( - KeysightB1517A, # noqa: F401 # used in generic argument below + KeysightB1517A, # used in generic argument below ) @@ -37,7 +39,11 @@ class SamplingMeasurement( # the measured measurement-time and the calculated measurement # (from the user input). Check :get_raw: method to find its usage. - def __init__(self, name: str, **kwargs: Any): + def __init__( + self, + name: str, + **kwargs: "Unpack[ParameterWithSetpointsKWArgs[npt.NDArray[numpy.float64], KeysightB1517A]]", + ): super().__init__(name, **kwargs) self.data = _FMTResponse(None, None, None, None) diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1517A.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1517A.py index 774d7380ab94..2fda09c947c5 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1517A.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1517A.py @@ -8,7 +8,13 @@ import qcodes.validators as vals from qcodes.instrument import InstrumentBaseKWArgs, InstrumentChannel -from qcodes.parameters import Group, GroupParameter, Parameter, ParamRawDataType +from qcodes.parameters import ( + Group, + GroupParameter, + Parameter, + ParameterKWArgs, + ParamRawDataType, +) from qcodes.parameters.parameter_base import ParameterDataTypeVar from qcodes.utils.deprecate import QCoDeSDeprecationWarning @@ -713,8 +719,12 @@ class IVSweeper(KeysightB1500IVSweeper): class _ParameterWithStatus( Parameter[ParameterDataTypeVar, "KeysightB1517A"], Generic[ParameterDataTypeVar] ): - def __init__(self, *args: Any, **kwargs: Any): - super().__init__(*args, **kwargs) + def __init__( + self, + name: str, + **kwargs: Unpack[ParameterKWArgs[ParameterDataTypeVar, "KeysightB1517A"]], + ): + super().__init__(name, **kwargs) self._measurement_status: MeasurementStatus | None = None diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py index 686766e40e3c..341124ab79b3 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py @@ -7,7 +7,13 @@ import qcodes.validators as vals from qcodes.instrument import InstrumentBaseKWArgs, InstrumentChannel -from qcodes.parameters import Group, GroupParameter, MultiParameter, Parameter +from qcodes.parameters import ( + Group, + GroupParameter, + MultiParameter, + MultiParameterKWArgs, + Parameter, +) from qcodes.utils.deprecate import QCoDeSDeprecationWarning from . import constants @@ -1179,18 +1185,22 @@ class KeysightB1500CVSweepMeasurement( """ - def __init__(self, name: str, instrument: KeysightB1520A, **kwargs: Any): + def __init__( + self, + name: str, + **kwargs: "Unpack[MultiParameterKWArgs[tuple[tuple[float, ...], tuple[float, ...]], KeysightB1520A]]", + ): + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("names", ("", "")) + kw.setdefault("units", ("", "")) + kw.setdefault("labels", ("", "")) + kw.setdefault("shapes", ((1,),) * 2) + kw.setdefault("setpoint_names", (("Voltage",),) * 2) + kw.setdefault("setpoint_labels", (("Voltage",),) * 2) + kw.setdefault("setpoint_units", (("V",),) * 2) super().__init__( name, - names=("", ""), - units=("", ""), - labels=("", ""), - shapes=((1,),) * 2, - setpoint_names=(("Voltage",),) * 2, - setpoint_labels=(("Voltage",),) * 2, - setpoint_units=(("V",),) * 2, - instrument=instrument, - **kwargs, + **kw, ) self.update_name_label_unit_from_impedance_model() diff --git a/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py b/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py index 17d7156139c5..46b83f58b82f 100644 --- a/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py +++ b/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py @@ -2,7 +2,7 @@ from bisect import bisect_left from contextlib import ExitStack from functools import partial -from typing import TYPE_CHECKING, Any, Literal, TypeAlias, get_args +from typing import TYPE_CHECKING, Literal, TypeAlias, get_args import numpy as np import numpy.typing as npt @@ -18,7 +18,11 @@ from qcodes.instrument_drivers.Keysight.private.error_handling import ( KeysightErrorQueueMixin, ) -from qcodes.parameters import Parameter, ParameterWithSetpoints +from qcodes.parameters import ( + Parameter, + ParameterWithSetpoints, + ParameterWithSetpointsKWArgs, +) from qcodes.utils import ( convert_legacy_version_to_supported_version, ) @@ -502,8 +506,12 @@ class TimeTrace(ParameterWithSetpoints[npt.NDArray[np.float64], "Keysight344xxA" intervals """ - def __init__(self, name: str, instrument: "Keysight344xxA", **kwargs: Any): - super().__init__(name=name, instrument=instrument, **kwargs) + def __init__( + self, + name: str, + **kwargs: "Unpack[ParameterWithSetpointsKWArgs[npt.NDArray[np.float64], Keysight344xxA]]", + ): + super().__init__(name=name, **kwargs) # the extra time needed to avoid timeouts during acquisition self._acquire_timeout_fudge_factor = 1.25 diff --git a/src/qcodes/instrument_drivers/QDev/QDac_channels.py b/src/qcodes/instrument_drivers/QDev/QDac_channels.py index 7d0a8fd0dd4f..f84e8e643fdd 100644 --- a/src/qcodes/instrument_drivers/QDev/QDac_channels.py +++ b/src/qcodes/instrument_drivers/QDev/QDac_channels.py @@ -17,7 +17,11 @@ VisaInstrument, VisaInstrumentKWArgs, ) -from qcodes.parameters import MultiChannelInstrumentParameter, ParamRawDataType +from qcodes.parameters import ( + MultiChannelInstrumentParameter, + ParameterBaseKWArgs, + ParamRawDataType, +) if TYPE_CHECKING: from collections.abc import Sequence @@ -182,7 +186,7 @@ def __init__( self, channels: "Sequence[InstrumentChannel]", param_name: str, - **kwargs: Any, + **kwargs: "Unpack[ParameterBaseKWArgs]", ): super().__init__(channels=channels, param_name=param_name, **kwargs) diff --git a/src/qcodes/instrument_drivers/mock_instruments/__init__.py b/src/qcodes/instrument_drivers/mock_instruments/__init__.py index 4bf8a9b914cb..9583378ecd51 100644 --- a/src/qcodes/instrument_drivers/mock_instruments/__init__.py +++ b/src/qcodes/instrument_drivers/mock_instruments/__init__.py @@ -17,9 +17,13 @@ ) from qcodes.parameters import ( ArrayParameter, + ArrayParameterKWArgs, MultiParameter, + MultiParameterKWArgs, Parameter, + ParameterKWArgs, ParameterWithSetpoints, + ParameterWithSetpointsKWArgs, ParamRawDataType, ) from qcodes.validators import Arrays, ComplexNumbers, Numbers, OnOff, Strings @@ -258,7 +262,7 @@ def __init__(self, name: str = "dummy", **kwargs: Unpack[InstrumentBaseKWArgs]): class DmmExponentialParameter(Parameter): - def __init__(self, name: str, **kwargs: Any): + def __init__(self, name: str, **kwargs: Unpack[ParameterKWArgs]): super().__init__(name, **kwargs) self._rng = np.random.default_rng() self._ed = self._exponential_decay(5, 0.2) @@ -289,7 +293,7 @@ def _exponential_decay(self, a: float, b: float) -> Generator[float, float, None class DmmGaussParameter(Parameter): - def __init__(self, name: str, **kwargs: Any): + def __init__(self, name: str, **kwargs: Unpack[ParameterKWArgs]): super().__init__(name, **kwargs) self.x0 = 0.1 self.y0 = 0.2 @@ -660,34 +664,33 @@ class MultiSetPointParam(MultiParameter): def __init__( self, - instrument: InstrumentBase | None = None, name: str = "multi_setpoint_param", - **kwargs: Any, + **kwargs: Unpack[MultiParameterKWArgs], ): - shapes = ((5,), (5,)) - names = ("multi_setpoint_param_this", "multi_setpoint_param_that") - labels = ("this label", "that label") - units = ("this unit", "that unit") sp_base = tuple(np.linspace(5, 9, 5)) - setpoints = ((sp_base,), (sp_base,)) - setpoint_names = ( - ("multi_setpoint_param_this_setpoint",), - ("multi_setpoint_param_this_setpoint",), + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shapes", ((5,), (5,))) + kw.setdefault( + "names", + ("multi_setpoint_param_this", "multi_setpoint_param_that"), + ) + kw.setdefault("labels", ("this label", "that label")) + kw.setdefault("units", ("this unit", "that unit")) + kw.setdefault("setpoints", ((sp_base,), (sp_base,))) + kw.setdefault( + "setpoint_names", + ( + ("multi_setpoint_param_this_setpoint",), + ("multi_setpoint_param_this_setpoint",), + ), + ) + kw.setdefault("setpoint_labels", (("this setpoint",), ("this setpoint",))) + kw.setdefault( + "setpoint_units", (("this setpointunit",), ("this setpointunit",)) ) - setpoint_labels = (("this setpoint",), ("this setpoint",)) - setpoint_units = (("this setpointunit",), ("this setpointunit",)) super().__init__( name, - names=names, - shapes=shapes, - instrument=instrument, - labels=labels, - units=units, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, + **kw, ) def get_raw(self) -> ParamRawDataType: @@ -703,48 +706,48 @@ class Multi2DSetPointParam(MultiParameter): def __init__( self, - instrument: InstrumentBase | None = None, name: str = "multi_2d_setpoint_param", - **kwargs: Any, + **kwargs: Unpack[MultiParameterKWArgs], ): - shapes = ((5, 3), (5, 3)) - names = ("this", "that") - labels = ("this label", "that label") - units = ("this unit", "that unit") sp_base_1 = tuple(np.linspace(5, 9, 5).flatten().tolist()) sp_base_2 = tuple(np.linspace(9, 11, 3).flatten().tolist()) array_setpoints = setpoint_generator(sp_base_1, sp_base_2) - setpoints = (array_setpoints, array_setpoints) - setpoint_names = ( + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shapes", ((5, 3), (5, 3))) + kw.setdefault("names", ("this", "that")) + kw.setdefault("labels", ("this label", "that label")) + kw.setdefault("units", ("this unit", "that unit")) + kw.setdefault("setpoints", (array_setpoints, array_setpoints)) + kw.setdefault( + "setpoint_names", ( - "multi_2d_setpoint_param_this_setpoint", - "multi_2d_setpoint_param_that_setpoint", + ( + "multi_2d_setpoint_param_this_setpoint", + "multi_2d_setpoint_param_that_setpoint", + ), + ( + "multi_2d_setpoint_param_this_setpoint", + "multi_2d_setpoint_param_that_setpoint", + ), ), + ) + kw.setdefault( + "setpoint_labels", ( - "multi_2d_setpoint_param_this_setpoint", - "multi_2d_setpoint_param_that_setpoint", + ("this setpoint", "that setpoint"), + ("this setpoint", "that setpoint"), ), ) - setpoint_labels = ( - ("this setpoint", "that setpoint"), - ("this setpoint", "that setpoint"), - ) - setpoint_units = ( - ("this setpointunit", "that setpointunit"), - ("this setpointunit", "that setpointunit"), + kw.setdefault( + "setpoint_units", + ( + ("this setpointunit", "that setpointunit"), + ("this setpointunit", "that setpointunit"), + ), ) super().__init__( name, - names=names, - shapes=shapes, - instrument=instrument, - labels=labels, - units=units, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, + **kw, ) def get_raw(self) -> ParamRawDataType: @@ -760,51 +763,51 @@ class Multi2DSetPointParam2Sizes(MultiParameter): def __init__( self, - instrument: InstrumentBase | None = None, name: str = "multi_2d_setpoint_param", - **kwargs: Any, + **kwargs: Unpack[MultiParameterKWArgs], ): - shapes = ((5, 3), (2, 7)) - names = ("this_5_3", "this_2_7") - labels = ("this label", "that label") - units = ("this unit", "that unit") sp_base_1_1 = tuple(np.linspace(5, 9, 5).flatten().tolist()) sp_base_2_1 = tuple(np.linspace(9, 11, 3).flatten().tolist()) array_setpoints_1 = setpoint_generator(sp_base_1_1, sp_base_2_1) sp_base_1_2 = tuple(np.linspace(5, 9, 2).flatten().tolist()) sp_base_2_2 = tuple(np.linspace(9, 11, 7).flatten().tolist()) array_setpoints_2 = setpoint_generator(sp_base_1_2, sp_base_2_2) - setpoints = (array_setpoints_1, array_setpoints_2) - setpoint_names = ( + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shapes", ((5, 3), (2, 7))) + kw.setdefault("names", ("this_5_3", "this_2_7")) + kw.setdefault("labels", ("this label", "that label")) + kw.setdefault("units", ("this unit", "that unit")) + kw.setdefault("setpoints", (array_setpoints_1, array_setpoints_2)) + kw.setdefault( + "setpoint_names", ( - "multi_2d_setpoint_param_this_setpoint_1", - "multi_2d_setpoint_param_that_setpoint_1", + ( + "multi_2d_setpoint_param_this_setpoint_1", + "multi_2d_setpoint_param_that_setpoint_1", + ), + ( + "multi_2d_setpoint_param_this_setpoint_2", + "multi_2d_setpoint_param_that_setpoint_2", + ), ), + ) + kw.setdefault( + "setpoint_labels", ( - "multi_2d_setpoint_param_this_setpoint_2", - "multi_2d_setpoint_param_that_setpoint_2", + ("this setpoint 1", "that setpoint 1"), + ("this setpoint 2", "that setpoint 2"), ), ) - setpoint_labels = ( - ("this setpoint 1", "that setpoint 1"), - ("this setpoint 2", "that setpoint 2"), - ) - setpoint_units = ( - ("this setpointunit", "that setpointunit"), - ("this setpointunit", "that setpointunit"), + kw.setdefault( + "setpoint_units", + ( + ("this setpointunit", "that setpointunit"), + ("this setpointunit", "that setpointunit"), + ), ) super().__init__( name, - names=names, - shapes=shapes, - instrument=instrument, - labels=labels, - units=units, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, + **kw, ) def get_raw(self) -> ParamRawDataType: @@ -820,24 +823,18 @@ class MultiScalarParam(MultiParameter): def __init__( self, - instrument: InstrumentBase | None = None, name: str = "multiscalarparameter", - **kwargs: Any, + **kwargs: Unpack[MultiParameterKWArgs], ): - shapes = ((), ()) - names = ("thisparam", "thatparam") - labels = ("thisparam label", "thatparam label") - units = ("thisparam unit", "thatparam unit") - setpoints = ((), ()) + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shapes", ((), ())) + kw.setdefault("names", ("thisparam", "thatparam")) + kw.setdefault("labels", ("thisparam label", "thatparam label")) + kw.setdefault("units", ("thisparam unit", "thatparam unit")) + kw.setdefault("setpoints", ((), ())) super().__init__( name, - names=names, - shapes=shapes, - instrument=instrument, - labels=labels, - units=units, - setpoints=setpoints, - **kwargs, + **kw, ) def get_raw(self) -> ParamRawDataType: @@ -853,29 +850,21 @@ class ArraySetPointParam(ArrayParameter): def __init__( self, - instrument: InstrumentBase | None = None, name: str = "array_setpoint_param", - **kwargs: Any, + **kwargs: Unpack[ArrayParameterKWArgs], ): - shape = (5,) - label = "this label" - unit = "this unit" sp_base = tuple(np.linspace(5, 9, 5)) - setpoints = (sp_base,) - setpoint_names = ("array_setpoint_param_this_setpoint",) - setpoint_labels = ("this setpoint",) - setpoint_units = ("this setpointunit",) + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shape", (5,)) + kw.setdefault("label", "this label") + kw.setdefault("unit", "this unit") + kw.setdefault("setpoints", (sp_base,)) + kw.setdefault("setpoint_names", ("array_setpoint_param_this_setpoint",)) + kw.setdefault("setpoint_labels", ("this setpoint",)) + kw.setdefault("setpoint_units", ("this setpointunit",)) super().__init__( name, - shape=shape, - instrument=instrument, - label=label, - unit=unit, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, + **kw, ) def get_raw(self) -> ParamRawDataType: @@ -890,29 +879,21 @@ class ComplexArraySetPointParam(ArrayParameter): def __init__( self, - instrument: InstrumentBase | None = None, name: str = "testparameter", - **kwargs: Any, + **kwargs: Unpack[ArrayParameterKWArgs], ): - shape = (5,) - label = "this label" - unit = "this unit" sp_base = tuple(np.linspace(5, 9, 5)) - setpoints = (sp_base,) - setpoint_names = ("this_setpoint",) - setpoint_labels = ("this setpoint",) - setpoint_units = ("this setpointunit",) + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shape", (5,)) + kw.setdefault("label", "this label") + kw.setdefault("unit", "this unit") + kw.setdefault("setpoints", (sp_base,)) + kw.setdefault("setpoint_names", ("this_setpoint",)) + kw.setdefault("setpoint_labels", ("this setpoint",)) + kw.setdefault("setpoint_units", ("this setpointunit",)) super().__init__( name, - shape=shape, - instrument=instrument, - label=label, - unit=unit, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, + **kw, ) def get_raw(self) -> ParamRawDataType: @@ -931,10 +912,11 @@ def __init__( startparam: Parameter, stopparam: Parameter, numpointsparam: Parameter, - *args: Any, - **kwargs: Any, + *, + name: str, + **kwargs: Unpack[ParameterKWArgs], ): - super().__init__(*args, **kwargs) + super().__init__(name, **kwargs) self._startparam = startparam self._stopparam = stopparam self._numpointsparam = numpointsparam @@ -951,8 +933,8 @@ class DummyParameterWithSetpoints1D(ParameterWithSetpoints): `dummy_n_points` parameter in the instrument. """ - def __init__(self, *args: Any, **kwargs: Any): - super().__init__(*args, **kwargs) + def __init__(self, *, name: str, **kwargs: Unpack[ParameterWithSetpointsKWArgs]): + super().__init__(name, **kwargs) self._rng = np.random.default_rng() def get_raw(self) -> ParamRawDataType: @@ -967,8 +949,8 @@ class DummyParameterWithSetpoints2D(ParameterWithSetpoints): `dummy_n_points` and `dummy_n_points_2` parameters in the instrument. """ - def __init__(self, *args: Any, **kwargs: Any): - super().__init__(*args, **kwargs) + def __init__(self, *, name: str, **kwargs: Unpack[ParameterWithSetpointsKWArgs]): + super().__init__(name, **kwargs) self._rng = np.random.default_rng() def get_raw(self) -> ParamRawDataType: @@ -984,8 +966,8 @@ class DummyParameterWithSetpointsComplex(ParameterWithSetpoints): `dummy_n_points` parameter in the instrument. Returns Complex values """ - def __init__(self, *args: Any, **kwargs: Any): - super().__init__(*args, **kwargs) + def __init__(self, *, name: str, **kwargs: Unpack[ParameterWithSetpointsKWArgs]): + super().__init__(name, **kwargs) self._rng = np.random.default_rng() def get_raw(self) -> ParamRawDataType: diff --git a/src/qcodes/instrument_drivers/rohde_schwarz/RTO1000.py b/src/qcodes/instrument_drivers/rohde_schwarz/RTO1000.py index 94ad53118d20..a843596a27d0 100644 --- a/src/qcodes/instrument_drivers/rohde_schwarz/RTO1000.py +++ b/src/qcodes/instrument_drivers/rohde_schwarz/RTO1000.py @@ -19,7 +19,12 @@ VisaInstrument, VisaInstrumentKWArgs, ) -from qcodes.parameters import ArrayParameter, Parameter, create_on_off_val_mapping +from qcodes.parameters import ( + ArrayParameter, + ArrayParameterKWArgs, + Parameter, + create_on_off_val_mapping, +) if TYPE_CHECKING: from typing_extensions import Unpack @@ -31,30 +36,30 @@ class ScopeTrace(ArrayParameter[npt.NDArray, "RohdeSchwarzRTO1000ScopeChannel"]) def __init__( self, name: str, - instrument: "RohdeSchwarzRTO1000ScopeChannel", + *, channum: int, - **kwargs: Any, + **kwargs: "Unpack[ArrayParameterKWArgs[npt.NDArray, RohdeSchwarzRTO1000ScopeChannel]]", ) -> None: """ The ScopeTrace parameter is attached to a channel of the oscilloscope. For now, we only support reading out the entire trace. """ + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("snapshot_value", False) + kw.setdefault("shape", (1,)) + kw.setdefault("label", "Voltage") # TODO: Is this sometimes dbm? + kw.setdefault("unit", "V") + kw.setdefault("setpoint_names", ("Time",)) + kw.setdefault("setpoint_labels", ("Time",)) + kw.setdefault("setpoint_units", ("s",)) + kw.setdefault("docstring", "Holds scope trace") super().__init__( name=name, - shape=(1,), - label="Voltage", # TODO: Is this sometimes dbm? - unit="V", - setpoint_names=("Time",), - setpoint_labels=("Time",), - setpoint_units=("s",), - docstring="Holds scope trace", - snapshot_value=False, - instrument=instrument, - **kwargs, + **kw, ) - self.channel = instrument + self.channel = self.instrument self.channum = channum self._trace_ready = False diff --git a/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py b/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py index f8fad7c1f034..4454a42dffb1 100644 --- a/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py +++ b/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py @@ -15,8 +15,10 @@ ) from qcodes.parameters import ( ArrayParameter, + ArrayParameterKWArgs, ManualParameter, MultiParameter, + MultiParameterKWArgs, Parameter, create_on_off_val_mapping, ) @@ -45,28 +47,32 @@ class FixedFrequencyTraceIQ( def __init__( self, name: str, - instrument: "RohdeSchwarzZNBChannel", + *, npts: int, bandwidth: int, - **kwargs: Any, + **kwargs: "Unpack[MultiParameterKWArgs[Any, RohdeSchwarzZNBChannel]]", ) -> None: - super().__init__( - name, - instrument=instrument, - names=("I", "Q"), - labels=(f"{instrument.short_name} I", f"{instrument.short_name} Q"), - units=("", ""), - setpoint_names=( + instrument = kwargs.get("instrument") + assert instrument is not None + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("names", ("I", "Q")) + kw.setdefault( + "labels", (f"{instrument.short_name} I", f"{instrument.short_name} Q") + ) + kw.setdefault("units", ("", "")) + kw.setdefault( + "setpoint_names", + ( (f"{instrument.short_name}_frequency",), (f"{instrument.short_name}_frequency",), ), - setpoint_units=(("s",), ("s",)), - setpoint_labels=(("time",), ("time",)), - shapes=( - (npts,), - (npts,), - ), - **kwargs, + ) + kw.setdefault("setpoint_units", (("s",), ("s",))) + kw.setdefault("setpoint_labels", (("time",), ("time",))) + kw.setdefault("shapes", ((npts,), (npts,))) + super().__init__( + name, + **kw, ) self.set_cw_sweep(npts, bandwidth) @@ -124,23 +130,23 @@ class FixedFrequencyPointIQ( """ def __init__( - self, name: str, instrument: "RohdeSchwarzZNBChannel", **kwargs: Any + self, + name: str, + **kwargs: "Unpack[MultiParameterKWArgs[Any, RohdeSchwarzZNBChannel]]", ) -> None: + instrument = kwargs.get("instrument") + assert instrument is not None + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("names", ("I", "Q")) + kw.setdefault( + "labels", (f"{instrument.short_name} I", f"{instrument.short_name} Q") + ) + kw.setdefault("units", ("", "")) + kw.setdefault("setpoints", ((), ())) + kw.setdefault("shapes", ((), ())) super().__init__( name, - instrument=instrument, - names=("I", "Q"), - labels=(f"{instrument.short_name} I", f"{instrument.short_name} Q"), - units=("", ""), - setpoints=( - (), - (), - ), - shapes=( - (), - (), - ), - **kwargs, + **kw, ) def get_raw(self) -> tuple[float, float]: @@ -174,26 +180,27 @@ class FixedFrequencyPointMagPhase( """ def __init__( - self, name: str, instrument: "RohdeSchwarzZNBChannel", **kwargs: Any + self, + name: str, + **kwargs: "Unpack[MultiParameterKWArgs[Any, RohdeSchwarzZNBChannel]]", ) -> None: - super().__init__( - name, - instrument=instrument, - names=("magnitude", "phase"), - labels=( + instrument = kwargs.get("instrument") + assert instrument is not None + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("names", ("magnitude", "phase")) + kw.setdefault( + "labels", + ( f"{instrument.short_name} magnitude", f"{instrument.short_name} phase", ), - units=("", "rad"), - setpoints=( - (), - (), - ), - shapes=( - (), - (), - ), - **kwargs, + ) + kw.setdefault("units", ("", "rad")) + kw.setdefault("setpoints", ((), ())) + kw.setdefault("shapes", ((), ())) + super().__init__( + name, + **kw, ) def get_raw(self) -> tuple[float, float]: @@ -221,36 +228,50 @@ class FrequencySweepMagPhase( def __init__( self, name: str, - instrument: "RohdeSchwarzZNBChannel", + *, start: float, stop: float, npts: int, channel: int, - **kwargs: Any, + **kwargs: "Unpack[MultiParameterKWArgs[Any, RohdeSchwarzZNBChannel]]", ) -> None: - super().__init__( - name, - instrument=instrument, - names=("magnitude", "phase"), - labels=( + instrument = kwargs.get("instrument") + assert instrument is not None + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("names", ("magnitude", "phase")) + kw.setdefault( + "labels", + ( f"{instrument.short_name} magnitude", f"{instrument.short_name} phase", ), - units=("", "rad"), - setpoint_units=(("Hz",), ("Hz",)), - setpoint_labels=( + ) + kw.setdefault("units", ("", "rad")) + kw.setdefault("setpoint_units", (("Hz",), ("Hz",))) + kw.setdefault( + "setpoint_labels", + ( (f"{instrument.short_name} frequency",), (f"{instrument.short_name} frequency",), ), - setpoint_names=( + ) + kw.setdefault( + "setpoint_names", + ( (f"{instrument.short_name}_frequency",), (f"{instrument.short_name}_frequency",), ), - shapes=( + ) + kw.setdefault( + "shapes", + ( (npts,), (npts,), ), - **kwargs, + ) + super().__init__( + name, + **kw, ) self.set_sweep(start, stop, npts) self._channel = channel @@ -281,36 +302,44 @@ class FrequencySweepDBPhase( def __init__( self, name: str, - instrument: "RohdeSchwarzZNBChannel", + *, start: float, stop: float, npts: int, channel: int, - **kwargs: Any, + **kwargs: "Unpack[MultiParameterKWArgs[Any, RohdeSchwarzZNBChannel]]", ) -> None: - super().__init__( - name, - instrument=instrument, - names=("magnitude", "phase"), - labels=( + instrument = kwargs.get("instrument") + assert instrument is not None + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("names", ("magnitude", "phase")) + kw.setdefault( + "labels", + ( f"{instrument.short_name} magnitude", f"{instrument.short_name} phase", ), - units=("dB", "rad"), - setpoint_units=(("Hz",), ("Hz",)), - setpoint_labels=( + ) + kw.setdefault("units", ("dB", "rad")) + kw.setdefault("setpoint_units", (("Hz",), ("Hz",))) + kw.setdefault( + "setpoint_labels", + ( (f"{instrument.short_name} frequency",), (f"{instrument.short_name} frequency",), ), - setpoint_names=( + ) + kw.setdefault( + "setpoint_names", + ( (f"{instrument.short_name}_frequency",), (f"{instrument.short_name}_frequency",), ), - shapes=( - (npts,), - (npts,), - ), - **kwargs, + ) + kw.setdefault("shapes", ((npts,), (npts,))) + super().__init__( + name, + **kw, ) self.set_sweep(start, stop, npts) self._channel = channel @@ -355,23 +384,25 @@ class FrequencySweep( def __init__( self, name: str, - instrument: "RohdeSchwarzZNBChannel", + *, start: float, stop: float, npts: int, channel: int, - **kwargs: Any, + **kwargs: "Unpack[ArrayParameterKWArgs[Any, RohdeSchwarzZNBChannel]]", ) -> None: + instrument = kwargs.get("instrument") + assert instrument is not None + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shape", (npts,)) + kw.setdefault("unit", "dB") + kw.setdefault("label", f"{instrument.short_name} magnitude") + kw.setdefault("setpoint_units", ("Hz",)) + kw.setdefault("setpoint_labels", (f"{instrument.short_name} frequency",)) + kw.setdefault("setpoint_names", (f"{instrument.short_name}_frequency",)) super().__init__( name, - shape=(npts,), - instrument=instrument, - unit="dB", - label=f"{instrument.short_name} magnitude", - setpoint_units=("Hz",), - setpoint_labels=(f"{instrument.short_name} frequency",), - setpoint_names=(f"{instrument.short_name}_frequency",), - **kwargs, + **kw, ) self.set_sweep(start, stop, npts) self._channel = channel diff --git a/src/qcodes/instrument_drivers/signal_hound/SignalHound_USB_SA124B.py b/src/qcodes/instrument_drivers/signal_hound/SignalHound_USB_SA124B.py index 4f8c728b9048..79d5a6190a79 100644 --- a/src/qcodes/instrument_drivers/signal_hound/SignalHound_USB_SA124B.py +++ b/src/qcodes/instrument_drivers/signal_hound/SignalHound_USB_SA124B.py @@ -9,7 +9,13 @@ import qcodes.validators as vals from qcodes.instrument import Instrument, InstrumentBaseKWArgs -from qcodes.parameters import ArrayParameter, Parameter, ParameterWithSetpoints +from qcodes.parameters import ( + ArrayParameter, + ArrayParameterKWArgs, + Parameter, + ParameterKWArgs, + ParameterWithSetpoints, +) if TYPE_CHECKING: from typing_extensions import Unpack @@ -27,8 +33,12 @@ class TraceParameter(Parameter): I.e. calling set/get will not communicate with the instrument. """ - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) + def __init__( + self, + name: str, + **kwargs: "Unpack[ParameterKWArgs]", + ) -> None: + super().__init__(name, **kwargs) def set_raw(self, value: Any) -> None: if not isinstance(self.instrument, SignalHoundUSBSA124B): @@ -87,8 +97,12 @@ class SweepTraceParameter(TraceParameter): addition to the functionality of `TraceParameter` """ - def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, **kwargs) + def __init__( + self, + name: str, + **kwargs: "Unpack[ParameterKWArgs]", + ) -> None: + super().__init__(name, **kwargs) def set_raw(self, value: Any) -> None: if not isinstance(self.instrument, SignalHoundUSBSA124B): @@ -120,22 +134,22 @@ class FrequencySweep(ArrayParameter): def __init__( self, name: str, - instrument: "SignalHoundUSBSA124B", + *, sweep_len: int, start_freq: float, stepsize: float, - **kwargs: Any, + **kwargs: "Unpack[ArrayParameterKWArgs]", ) -> None: + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shape", (sweep_len,)) + kw.setdefault("unit", "dBm") + kw.setdefault("label", "Magnitude") + kw.setdefault("setpoint_units", ("Hz",)) + kw.setdefault("setpoint_labels", ("Frequency",)) + kw.setdefault("setpoint_names", ("frequency",)) super().__init__( name, - shape=(sweep_len,), - instrument=instrument, - unit="dBm", - label="Magnitude", - setpoint_units=("Hz",), - setpoint_labels=("Frequency",), - setpoint_names=("frequency",), - **kwargs, + **kw, ) self.set_sweep(sweep_len, start_freq, stepsize) diff --git a/src/qcodes/instrument_drivers/stanford_research/SR830.py b/src/qcodes/instrument_drivers/stanford_research/SR830.py index 6ce5413f602f..23f48e1261fa 100644 --- a/src/qcodes/instrument_drivers/stanford_research/SR830.py +++ b/src/qcodes/instrument_drivers/stanford_research/SR830.py @@ -2,7 +2,7 @@ import time from functools import partial -from typing import TYPE_CHECKING, Any, ClassVar +from typing import TYPE_CHECKING, ClassVar import numpy as np @@ -10,7 +10,9 @@ from qcodes.parameters import ( ArrayParameter, Parameter, + ParameterKWArgs, ParameterWithSetpoints, + ParameterWithSetpointsKWArgs, ParamRawDataType, ) from qcodes.validators import Arrays, ComplexNumbers, Enum, Ints, Numbers, Strings @@ -26,7 +28,9 @@ class ChannelTrace(ParameterWithSetpoints): Parameter class for the two channel buffers """ - def __init__(self, name: str, channel: int, **kwargs: Any) -> None: + def __init__( + self, name: str, channel: int, **kwargs: Unpack[ParameterWithSetpointsKWArgs] + ) -> None: """ Args: name: The name of the parameter @@ -1001,10 +1005,11 @@ class GeneratedSetPoints(Parameter): def __init__( self, sweep_array: Iterable[float | int] = np.linspace(0, 1, 10), - *args: Any, - **kwargs: Any, + *, + name: str, + **kwargs: Unpack[ParameterKWArgs], ) -> None: - super().__init__(*args, **kwargs) + super().__init__(name, **kwargs) self.sweep_array = sweep_array self.update_units_if_constant_sample_rate() diff --git a/src/qcodes/instrument_drivers/stanford_research/SR86x.py b/src/qcodes/instrument_drivers/stanford_research/SR86x.py index a206d0f5da9c..16366da67034 100644 --- a/src/qcodes/instrument_drivers/stanford_research/SR86x.py +++ b/src/qcodes/instrument_drivers/stanford_research/SR86x.py @@ -14,7 +14,7 @@ VisaInstrument, VisaInstrumentKWArgs, ) -from qcodes.parameters import ArrayParameter +from qcodes.parameters import ArrayParameter, ArrayParameterKWArgs from qcodes.validators import ComplexNumbers, Enum, Ints, Numbers if TYPE_CHECKING: @@ -38,21 +38,24 @@ class SR86xBufferReadout(ArrayParameter): """ - def __init__(self, name: str, instrument: SR86x, **kwargs: Any) -> None: + def __init__(self, name: str, **kwargs: Unpack[ArrayParameterKWArgs]) -> None: unit = "deg" if name in ["X", "Y", "R"]: unit = "V" + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shape", (1,)) # dummy initial shape + kw.setdefault("unit", unit) + kw.setdefault("setpoint_names", ("Time",)) + kw.setdefault("setpoint_labels", ("Time",)) + kw.setdefault("setpoint_units", ("s",)) + kw.setdefault( + "docstring", + "Holds an acquired (part of the) data buffer of one channel.", + ) super().__init__( name, - shape=(1,), # dummy initial shape - unit=unit, - setpoint_names=("Time",), - setpoint_labels=("Time",), - setpoint_units=("s",), - instrument=instrument, - docstring="Holds an acquired (part of the) data buffer of one channel.", - **kwargs, + **kw, ) self._capture_data: npt.NDArray | None = None diff --git a/src/qcodes/instrument_drivers/tektronix/TPS2012.py b/src/qcodes/instrument_drivers/tektronix/TPS2012.py index 3b373dc3d1d6..9f69e6e466be 100644 --- a/src/qcodes/instrument_drivers/tektronix/TPS2012.py +++ b/src/qcodes/instrument_drivers/tektronix/TPS2012.py @@ -16,7 +16,12 @@ VisaInstrument, VisaInstrumentKWArgs, ) -from qcodes.parameters import ArrayParameter, Parameter, ParamRawDataType +from qcodes.parameters import ( + ArrayParameter, + ArrayParameterKWArgs, + Parameter, + ParamRawDataType, +) if TYPE_CHECKING: from qcodes.instrument.channel import ChannelTuple @@ -50,21 +55,21 @@ class ScopeArray(ArrayParameter): def __init__( self, name: str, - instrument: "TektronixTPS2012Channel", + *, channel: int, - **kwargs: Any, + **kwargs: Unpack[ArrayParameterKWArgs], ): + kw: dict[str, Any] = dict(kwargs) + kw.setdefault("shape", (2500,)) + kw.setdefault("label", "Voltage") + kw.setdefault("unit", "V ") + kw.setdefault("setpoint_names", ("Time",)) + kw.setdefault("setpoint_labels", ("Time",)) + kw.setdefault("setpoint_units", ("s",)) + kw.setdefault("docstring", "holds an array from scope") super().__init__( name=name, - shape=(2500,), - label="Voltage", - unit="V ", - setpoint_names=("Time",), - setpoint_labels=("Time",), - setpoint_units=("s",), - docstring="holds an array from scope", - instrument=instrument, - **kwargs, + **kw, ) self.channel = channel diff --git a/src/qcodes/parameters/__init__.py b/src/qcodes/parameters/__init__.py index 4ff68a69fac7..2aa8816f7fef 100644 --- a/src/qcodes/parameters/__init__.py +++ b/src/qcodes/parameters/__init__.py @@ -69,14 +69,14 @@ """ from ._paramspec import ParamSpecBase, ParamSpecBaseDict -from .array_parameter import ArrayParameter +from .array_parameter import ArrayParameter, ArrayParameterKWArgs from .combined_parameter import CombinedParameter, combine from .delegate_parameter import DelegateParameter from .function import Function from .group_parameter import Group, GroupParameter from .grouped_parameter import DelegateGroup, DelegateGroupParameter, GroupedParameter from .multi_channel_instrument_parameter import MultiChannelInstrumentParameter -from .multi_parameter import MultiParameter +from .multi_parameter import MultiParameter, MultiParameterKWArgs from .parameter import ManualParameter, Parameter, ParameterKWArgs from .parameter_base import ( ParamDataType, @@ -86,7 +86,11 @@ ParamRawDataType, invert_val_mapping, ) -from .parameter_with_setpoints import ParameterWithSetpoints, expand_setpoints_helper +from .parameter_with_setpoints import ( + ParameterWithSetpoints, + ParameterWithSetpointsKWArgs, + expand_setpoints_helper, +) from .scaled_paramter import ScaledParameter from .specialized_parameters import ElapsedTimeParameter, InstrumentRefParameter from .sweep_values import SweepFixedValues, SweepValues @@ -94,6 +98,7 @@ __all__ = [ "ArrayParameter", + "ArrayParameterKWArgs", "CombinedParameter", "DelegateGroup", "DelegateGroupParameter", @@ -107,6 +112,7 @@ "ManualParameter", "MultiChannelInstrumentParameter", "MultiParameter", + "MultiParameterKWArgs", "ParamDataType", "ParamRawDataType", "ParamSpecBase", @@ -117,6 +123,7 @@ "ParameterKWArgs", "ParameterSet", "ParameterWithSetpoints", + "ParameterWithSetpointsKWArgs", "ScaledParameter", "SweepFixedValues", "SweepValues", diff --git a/src/qcodes/parameters/array_parameter.py b/src/qcodes/parameters/array_parameter.py index 8d4782cf1b12..27679ae7d6db 100644 --- a/src/qcodes/parameters/array_parameter.py +++ b/src/qcodes/parameters/array_parameter.py @@ -2,7 +2,7 @@ import collections.abc import os -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Generic import numpy as np @@ -12,7 +12,8 @@ has_loop = True except ImportError: has_loop = False -from typing import Generic + +from typing import NotRequired, TypedDict from .parameter_base import ( InstrumentTypeVar_co, @@ -23,10 +24,12 @@ from .sequence_helpers import is_sequence_of if TYPE_CHECKING: - from collections.abc import Sequence + from collections.abc import Callable, Iterable, Mapping, Sequence from typing_extensions import Unpack + from qcodes.validators import Validator + try: from qcodes_loop.data.data_array import DataArray @@ -47,6 +50,166 @@ ) +class ArrayParameterKWArgs( + TypedDict, + Generic[ParameterDataTypeVar, InstrumentTypeVar_co], +): + """ + This TypedDict defines the type of the kwargs that can be passed to + the ``ArrayParameter`` class. + + A subclass of ``ArrayParameter`` should take + ``**kwargs: Unpack[ArrayParameterKWArgs]`` as input and forward this to + the super class to ensure that it can accept all the arguments + defined here. + """ + + # Members from ParameterBaseKWArgs are redeclared here + # so that Sphinx can discover and document them. + instrument: NotRequired[InstrumentTypeVar_co] + """ + The instrument this parameter belongs to, if any. + """ + snapshot_get: NotRequired[bool] + """ + False prevents any update to the parameter during a snapshot, + even if the snapshot was called with ``update=True``. + Default True. + """ + metadata: NotRequired[Mapping[Any, Any] | None] + """ + Additional static metadata to add to this + parameter's JSON snapshot. + """ + step: NotRequired[float | None] + """ + Max increment of parameter value. + Larger changes are broken into multiple steps this size. + When combined with delays, this acts as a ramp. + """ + scale: NotRequired[float | Iterable[float] | None] + """ + Scale to multiply value with before performing set. + The internally multiplied value is stored in + ``cache.raw_value``. Can account for a voltage divider. + """ + offset: NotRequired[float | Iterable[float] | None] + """ + Compensate for a parameter specific offset. + get value = raw value - offset. + set value = argument + offset. + """ + inter_delay: NotRequired[float] + """ + Minimum time (in seconds) between successive sets. + If the previous set was less than this, it will wait until the + condition is met. Can be set to 0 to go maximum speed with + no errors. + """ + post_delay: NotRequired[float] + """ + Time (in seconds) to wait after the *start* of each set, + whether part of a sweep or not. Can be set to 0 to go maximum + speed with no errors. + """ + val_mapping: NotRequired[Mapping[Any, Any] | None] + """ + A bidirectional map of data/readable values to instrument codes, + expressed as a dict: ``{data_val: instrument_code}``. + """ + get_parser: NotRequired[Callable[..., Any] | None] + """ + Function to transform the response from get to the final + output value. See also ``val_mapping``. + """ + set_parser: NotRequired[Callable[..., Any] | None] + """ + Function to transform the input set value to an encoded + value sent to the instrument. See also ``val_mapping``. + """ + snapshot_value: NotRequired[bool] + """ + False prevents parameter value to be stored in the snapshot. + Useful if the value is large. Default True. + """ + snapshot_exclude: NotRequired[bool] + """ + True prevents parameter to be included in the snapshot. + Useful if there are many of the same parameter which are + clogging up the snapshot. Default False. + """ + max_val_age: NotRequired[float | None] + """ + The max time (in seconds) to trust a saved value obtained + from ``cache.get`` (or ``get_latest``). If this parameter has not + been set or measured more recently than this, perform an + additional measurement. + """ + vals: NotRequired[Validator[Any] | None] + """ + A Validator object for this parameter. + """ + abstract: NotRequired[bool | None] + """ + Specifies if this parameter is abstract or not. Default is False. + If the parameter is 'abstract', it *must* be overridden by a + non-abstract parameter before the instrument containing this + parameter can be instantiated. + """ + bind_to_instrument: NotRequired[bool] + """ + Should the parameter be registered as a delegate attribute + on the instrument passed via the instrument argument. + """ + register_name: NotRequired[str | None] + """ + Specifies if the parameter should be registered in datasets + using a different name than the parameter's ``full_name``. + """ + on_set_callback: NotRequired[ + Callable[[ParameterBase, ParameterDataTypeVar], None] | None + ] + """ + Callback called when the parameter value is set. + """ + # Members specific to ArrayParameterKWArgs + shape: NotRequired[Sequence[int]] + """ + The shape (as used in numpy arrays) of the array to expect. + Scalars should be denoted by (), 1D arrays as (n,), + 2D arrays as (n, m), etc. + """ + label: NotRequired[str | None] + """ + Normally used as the axis label when this parameter is graphed, + along with ``unit``. + """ + unit: NotRequired[str | None] + """ + The unit of measure. Use ``''`` for unitless. + """ + setpoints: NotRequired[Sequence[Any] | None] + """ + The setpoints for each dimension of the returned array. + """ + setpoint_names: NotRequired[Sequence[str] | None] + """ + One identifier (like ``name``) per setpoint array. + """ + setpoint_labels: NotRequired[Sequence[str] | None] + """ + One label (like ``labels``) per setpoint array. + """ + setpoint_units: NotRequired[Sequence[str] | None] + """ + One unit (like ``v``) per setpoint array. + """ + docstring: NotRequired[str | None] + """ + Documentation string for the ``__doc__`` field of the object. + """ + + class ArrayParameter( ParameterBase[ParameterDataTypeVar, InstrumentTypeVar_co], Generic[ParameterDataTypeVar, InstrumentTypeVar_co], diff --git a/src/qcodes/parameters/multi_parameter.py b/src/qcodes/parameters/multi_parameter.py index b8f2139502bf..3b51a9a30c6f 100644 --- a/src/qcodes/parameters/multi_parameter.py +++ b/src/qcodes/parameters/multi_parameter.py @@ -2,7 +2,7 @@ import os from collections.abc import Iterator, Sequence -from typing import TYPE_CHECKING, Any, Generic +from typing import TYPE_CHECKING, Any, Generic, NotRequired, TypedDict import numpy as np @@ -15,8 +15,12 @@ from .sequence_helpers import is_sequence_of if TYPE_CHECKING: + from collections.abc import Callable, Iterable, Mapping + from typing_extensions import Unpack + from qcodes.validators import Validator + try: from qcodes_loop.data.data_array import DataArray @@ -55,6 +59,170 @@ def _is_nested_sequence_or_none( return True +class MultiParameterKWArgs( + TypedDict, + Generic[ParameterDataTypeVar, InstrumentTypeVar_co], +): + """ + This TypedDict defines the type of the kwargs that can be passed to + the ``MultiParameter`` class. + + A subclass of ``MultiParameter`` should take + ``**kwargs: Unpack[MultiParameterKWArgs]`` as input and forward this to + the super class to ensure that it can accept all the arguments + defined here. + """ + + # Members from ParameterBaseKWArgs are redeclared here + # so that Sphinx can discover and document them. + instrument: NotRequired[InstrumentTypeVar_co] + """ + The instrument this parameter belongs to, if any. + """ + snapshot_get: NotRequired[bool] + """ + False prevents any update to the parameter during a snapshot, + even if the snapshot was called with ``update=True``. + Default True. + """ + metadata: NotRequired[Mapping[Any, Any] | None] + """ + Additional static metadata to add to this + parameter's JSON snapshot. + """ + step: NotRequired[float | None] + """ + Max increment of parameter value. + Larger changes are broken into multiple steps this size. + When combined with delays, this acts as a ramp. + """ + scale: NotRequired[float | Iterable[float] | None] + """ + Scale to multiply value with before performing set. + The internally multiplied value is stored in + ``cache.raw_value``. Can account for a voltage divider. + """ + offset: NotRequired[float | Iterable[float] | None] + """ + Compensate for a parameter specific offset. + get value = raw value - offset. + set value = argument + offset. + """ + inter_delay: NotRequired[float] + """ + Minimum time (in seconds) between successive sets. + If the previous set was less than this, it will wait until the + condition is met. Can be set to 0 to go maximum speed with + no errors. + """ + post_delay: NotRequired[float] + """ + Time (in seconds) to wait after the *start* of each set, + whether part of a sweep or not. Can be set to 0 to go maximum + speed with no errors. + """ + val_mapping: NotRequired[Mapping[Any, Any] | None] + """ + A bidirectional map of data/readable values to instrument codes, + expressed as a dict: ``{data_val: instrument_code}``. + """ + get_parser: NotRequired[Callable[..., Any] | None] + """ + Function to transform the response from get to the final + output value. See also ``val_mapping``. + """ + set_parser: NotRequired[Callable[..., Any] | None] + """ + Function to transform the input set value to an encoded + value sent to the instrument. See also ``val_mapping``. + """ + snapshot_value: NotRequired[bool] + """ + False prevents parameter value to be stored in the snapshot. + Useful if the value is large. Default True. + """ + snapshot_exclude: NotRequired[bool] + """ + True prevents parameter to be included in the snapshot. + Useful if there are many of the same parameter which are + clogging up the snapshot. Default False. + """ + max_val_age: NotRequired[float | None] + """ + The max time (in seconds) to trust a saved value obtained + from ``cache.get`` (or ``get_latest``). If this parameter has not + been set or measured more recently than this, perform an + additional measurement. + """ + vals: NotRequired[Validator[Any] | None] + """ + A Validator object for this parameter. + """ + abstract: NotRequired[bool | None] + """ + Specifies if this parameter is abstract or not. Default is False. + If the parameter is 'abstract', it *must* be overridden by a + non-abstract parameter before the instrument containing this + parameter can be instantiated. + """ + bind_to_instrument: NotRequired[bool] + """ + Should the parameter be registered as a delegate attribute + on the instrument passed via the instrument argument. + """ + register_name: NotRequired[str | None] + """ + Specifies if the parameter should be registered in datasets + using a different name than the parameter's ``full_name``. + """ + on_set_callback: NotRequired[ + Callable[[ParameterBase, ParameterDataTypeVar], None] | None + ] + """ + Callback called when the parameter value is set. + """ + # Members specific to MultiParameterKWArgs + names: NotRequired[Sequence[str]] + """ + A name for each item returned by a ``.get`` call. + """ + shapes: NotRequired[Sequence[Sequence[int]]] + """ + The shape (as used in numpy arrays) of each item. + """ + labels: NotRequired[Sequence[str] | None] + """ + A label for each item. Normally used as the axis label + when a component is graphed, along with the matching entry + from ``units``. + """ + units: NotRequired[Sequence[str] | None] + """ + A unit of measure for each item. Use ``''`` or ``None`` + for unitless values. + """ + setpoints: NotRequired[Sequence[Sequence[Any]] | None] + """ + The setpoints for each returned array. + """ + setpoint_names: NotRequired[Sequence[Sequence[str]] | None] + """ + One identifier (like ``name``) per setpoint array. + """ + setpoint_labels: NotRequired[Sequence[Sequence[str]] | None] + """ + One label (like ``labels``) per setpoint array. + """ + setpoint_units: NotRequired[Sequence[Sequence[str]] | None] + """ + One unit (like ``V``) per setpoint array. + """ + docstring: NotRequired[str | None] + """ + Documentation string for the ``__doc__`` field of the object. + """ + + class MultiParameter( ParameterBase[ParameterDataTypeVar, InstrumentTypeVar_co], Generic[ParameterDataTypeVar, InstrumentTypeVar_co], diff --git a/src/qcodes/parameters/parameter_with_setpoints.py b/src/qcodes/parameters/parameter_with_setpoints.py index 5207089c5f1e..3a233b38245c 100644 --- a/src/qcodes/parameters/parameter_with_setpoints.py +++ b/src/qcodes/parameters/parameter_with_setpoints.py @@ -1,7 +1,7 @@ from __future__ import annotations import logging -from typing import TYPE_CHECKING, Generic +from typing import TYPE_CHECKING, Any, Generic, Literal, NotRequired, TypedDict import numpy as np @@ -18,16 +18,186 @@ from qcodes.validators import Arrays if TYPE_CHECKING: - from collections.abc import Callable, Sequence + from collections.abc import Callable, Iterable, Mapping, Sequence from typing_extensions import Unpack from qcodes.dataset.data_set_protocol import ValuesType - from qcodes.parameters.parameter_base import ParamDataType, ParameterBase + from qcodes.parameters.parameter_base import ParamDataType + from qcodes.validators import Validator LOG = logging.getLogger(__name__) +class ParameterWithSetpointsKWArgs( + TypedDict, + Generic[ParameterDataTypeVar, InstrumentTypeVar_co], +): + """ + This TypedDict defines the type of the kwargs that can be passed to + the ``ParameterWithSetpoints`` class. + + A subclass of ``ParameterWithSetpoints`` should take + ``**kwargs: Unpack[ParameterWithSetpointsKWArgs]`` as input and forward + this to the super class to ensure that it can accept all the arguments + defined here. + """ + + # Members from ParameterBaseKWArgs are redeclared here + # so that Sphinx can discover and document them. + instrument: NotRequired[InstrumentTypeVar_co] + """ + The instrument this parameter belongs to, if any. + """ + snapshot_get: NotRequired[bool] + """ + False prevents any update to the parameter during a snapshot, + even if the snapshot was called with ``update=True``. + Default True. + """ + metadata: NotRequired[Mapping[Any, Any] | None] + """ + Additional static metadata to add to this + parameter's JSON snapshot. + """ + step: NotRequired[float | None] + """ + Max increment of parameter value. + Larger changes are broken into multiple steps this size. + When combined with delays, this acts as a ramp. + """ + scale: NotRequired[float | Iterable[float] | None] + """ + Scale to multiply value with before performing set. + The internally multiplied value is stored in + ``cache.raw_value``. Can account for a voltage divider. + """ + offset: NotRequired[float | Iterable[float] | None] + """ + Compensate for a parameter specific offset. + get value = raw value - offset. + set value = argument + offset. + """ + inter_delay: NotRequired[float] + """ + Minimum time (in seconds) between successive sets. + If the previous set was less than this, it will wait until the + condition is met. Can be set to 0 to go maximum speed with + no errors. + """ + post_delay: NotRequired[float] + """ + Time (in seconds) to wait after the *start* of each set, + whether part of a sweep or not. Can be set to 0 to go maximum + speed with no errors. + """ + val_mapping: NotRequired[Mapping[Any, Any] | None] + """ + A bidirectional map of data/readable values to instrument codes, + expressed as a dict: ``{data_val: instrument_code}``. + """ + get_parser: NotRequired[Callable[..., Any] | None] + """ + Function to transform the response from get to the final + output value. See also ``val_mapping``. + """ + set_parser: NotRequired[Callable[..., Any] | None] + """ + Function to transform the input set value to an encoded + value sent to the instrument. See also ``val_mapping``. + """ + snapshot_value: NotRequired[bool] + """ + False prevents parameter value to be stored in the snapshot. + Useful if the value is large. Default True. + """ + snapshot_exclude: NotRequired[bool] + """ + True prevents parameter to be included in the snapshot. + Useful if there are many of the same parameter which are + clogging up the snapshot. Default False. + """ + max_val_age: NotRequired[float | None] + """ + The max time (in seconds) to trust a saved value obtained + from ``cache.get`` (or ``get_latest``). If this parameter has not + been set or measured more recently than this, perform an + additional measurement. + """ + vals: NotRequired[Validator[Any] | None] + """ + A Validator object for this parameter. + """ + abstract: NotRequired[bool | None] + """ + Specifies if this parameter is abstract or not. Default is False. + If the parameter is 'abstract', it *must* be overridden by a + non-abstract parameter before the instrument containing this + parameter can be instantiated. + """ + bind_to_instrument: NotRequired[bool] + """ + Should the parameter be registered as a delegate attribute + on the instrument passed via the instrument argument. + """ + register_name: NotRequired[str | None] + """ + Specifies if the parameter should be registered in datasets + using a different name than the parameter's ``full_name``. + """ + on_set_callback: NotRequired[ + Callable[[ParameterBase, ParameterDataTypeVar], None] | None + ] + """ + Callback called when the parameter value is set. + """ + # Members from ParameterKWArgs are redeclared here + # so that Sphinx can discover and document them. + label: NotRequired[str | None] + """ + Normally used as the axis label when this parameter is graphed, + along with ``unit``. + """ + unit: NotRequired[str | None] + """ + The unit of measure. Use ``''`` for unitless. + """ + get_cmd: NotRequired[str | Callable[..., Any] | Literal[False] | None] + """ + A command to issue to the instrument to retrieve the value of this + parameter. Can be a callable with zero args, a VISA command string, + ``None`` to use ``get_raw``, or ``False`` to disable getting. + """ + set_cmd: NotRequired[str | Callable[..., Any] | Literal[False] | None] + """ + A command to issue to the instrument to set the value of this + parameter. Can be a callable with one arg, a VISA command string, + ``None`` to use ``set_raw``, or ``False`` to disable setting. + Default ``False``. + """ + initial_value: NotRequired[ParameterDataTypeVar | None] + """ + Value to set the parameter to at the end of its initialization. + Cannot be passed together with ``initial_cache_value`` argument. + """ + docstring: NotRequired[str | None] + """ + Documentation string for the ``__doc__`` field of the object. + """ + initial_cache_value: NotRequired[ParameterDataTypeVar | None] + """ + Value to set the cache of the parameter to at the end of its + initialization. Cannot be passed together with ``initial_value`` + argument. + """ + # Members specific to ParameterWithSetpointsKWArgs + setpoints: NotRequired[Sequence[ParameterBase] | None] + """ + A list of other parameters that describe the values, names + and units of the setpoint axes for this parameter. + """ + + class ParameterWithSetpoints( Parameter[ParameterDataTypeVar, InstrumentTypeVar_co], Generic[ParameterDataTypeVar, InstrumentTypeVar_co],