From e7e16c12427ea8764e332e744dfdce3f0dfa2543 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Sat, 4 Nov 2023 08:11:18 +0100 Subject: [PATCH] update test refs to use public mock instruments --- .../dist/tests/station/example.station.yaml | 4 +- .../mock_instruments/__init__.py | 1139 ++++++++++++++++ src/qcodes/tests/dataset/conftest.py | 4 +- src/qcodes/tests/dataset/dond/test_do0d.py | 4 +- src/qcodes/tests/dataset/dond/test_do1d.py | 6 +- src/qcodes/tests/dataset/dond/test_do2d.py | 4 +- src/qcodes/tests/dataset/dond/test_doNd.py | 6 +- .../data_001_testsweep_15_42_57/snapshot.json | 24 +- .../data_002_2D_test_15_43_14/snapshot.json | 28 +- .../dataset/test_database_extract_runs.py | 2 +- src/qcodes/tests/dataset/test_detect_shape.py | 4 +- src/qcodes/tests/dataset/test_plotting.py | 2 +- src/qcodes/tests/dataset/test_snapshot.py | 2 +- src/qcodes/tests/delegate/conftest.py | 2 +- src/qcodes/tests/delegate/data/chip.yml | 4 +- src/qcodes/tests/delegate/data/chip_typo.yml | 2 +- .../delegate/test_delegate_instrument.py | 2 +- src/qcodes/tests/delegate/test_device.py | 2 +- src/qcodes/tests/instrument_mocks.py | 1151 +---------------- src/qcodes/tests/parameter/conftest.py | 2 +- src/qcodes/tests/parameter/test_function.py | 2 +- .../test_instrument_ref_parameter.py | 2 +- .../tests/parameter/test_parameter_cache.py | 2 +- .../test_parameter_context_manager.py | 2 +- .../parameter/test_parameter_registration.py | 2 +- .../tests/parameter/test_scaled_parameter.py | 2 +- .../tests/parameter/test_val_mapping.py | 2 +- src/qcodes/tests/test_channels.py | 10 +- src/qcodes/tests/test_instrument.py | 19 +- src/qcodes/tests/test_monitor.py | 5 +- src/qcodes/tests/test_snapshot.py | 2 +- src/qcodes/tests/test_station.py | 125 +- src/qcodes/tests/test_threading.py | 3 +- 33 files changed, 1327 insertions(+), 1245 deletions(-) create mode 100644 src/qcodes/instrument_drivers/mock_instruments/__init__.py diff --git a/src/qcodes/dist/tests/station/example.station.yaml b/src/qcodes/dist/tests/station/example.station.yaml index c6d13b85123..fe62495bc91 100644 --- a/src/qcodes/dist/tests/station/example.station.yaml +++ b/src/qcodes/dist/tests/station/example.station.yaml @@ -48,12 +48,12 @@ instruments: add_parameters: Bx: {source: ch01.fine_volt, label: Bx, unit: T, scale: 28, limits: [-1, 1], monitor: true} mock_dac: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument enable_forced_reconnect: true init: gates: {"ch1", "ch2"} add_parameters: Bx: {source: ch1, label: Bx, unit: T, scale: 28, limits: [-1, 1], monitor: true} mock_dac2: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument enable_forced_reconnect: true diff --git a/src/qcodes/instrument_drivers/mock_instruments/__init__.py b/src/qcodes/instrument_drivers/mock_instruments/__init__.py new file mode 100644 index 00000000000..89e1a3761f4 --- /dev/null +++ b/src/qcodes/instrument_drivers/mock_instruments/__init__.py @@ -0,0 +1,1139 @@ +from __future__ import annotations + +import logging +import time +from collections.abc import Generator, Sequence +from functools import partial +from typing import Any + +import numpy as np + +from qcodes.instrument import ChannelList, Instrument, InstrumentBase, InstrumentChannel +from qcodes.parameters import ( + ArrayParameter, + MultiParameter, + Parameter, + ParameterWithSetpoints, + ParamRawDataType, +) +from qcodes.validators import Arrays, ComplexNumbers, Numbers, OnOff, Strings +from qcodes.validators import Sequence as ValidatorSequence + +log = logging.getLogger(__name__) + + +class DummyBase(Instrument): + def get_idn(self) -> dict[str, str | None]: + return { + "vendor": "QCoDeS", + "model": str(self.__class__), + "seral": "NA", + "firmware": "NA", + } + + +class MockParabola(DummyBase): + """ + Holds dummy parameters which are get and set able as well as provides + some basic functions that depends on these parameters for testing + purposes. + + This instrument is intended to be simpler than the mock model in that it + does not emulate communications. + + It has 3 main parameters (x, y, z) in order to allow for testing of 3D + sweeps. The function (parabola with optional noise) is chosen to allow + testing of numerical optimizations. + """ + + def __init__(self, name: str, **kw: Any): + super().__init__(name, **kw) + + # Instrument parameters + for parname in ['x', 'y', 'z']: + self.add_parameter(parname, unit='a.u.', + parameter_class=Parameter, + vals=Numbers(), initial_value=0, + get_cmd=None, set_cmd=None) + + self.add_parameter('noise', unit='a.u.', + label='white noise amplitude', + parameter_class=Parameter, + vals=Numbers(), initial_value=0, + get_cmd=None, set_cmd=None) + + self.add_parameter('parabola', unit='a.u.', + get_cmd=self._measure_parabola) + self.add_parameter('skewed_parabola', unit='a.u.', + get_cmd=self._measure_skewed_parabola) + + def _measure_parabola(self) -> float: + return (self.x.get()**2 + self.y.get()**2 + self.z.get()**2 + + self.noise.get()*np.random.rand(1)) + + def _measure_skewed_parabola(self) -> float: + """ + Adds an -x term to add a corelation between the parameters. + """ + return ((self.x.get()**2 + self.y.get()**2 + + self.z.get()**2)*(1 + abs(self.y.get()-self.x.get())) + + self.noise.get()*np.random.rand(1)) + + +class MockMetaParabola(InstrumentBase): + """ + Test for a meta instrument, has a tunable gain knob + + Unlike a MockParabola, a MockMetaParabola does not have a connection, or + access to ask_raw/write_raw, i.e. it would not be connected to a real instrument. + + It is also not tracked in the global _all_instruments list, but is still + snapshottable in a station. + """ + + def __init__(self, name: str, mock_parabola_inst: MockParabola, **kw: Any): + """ + Create a new MockMetaParabola, connected to an existing MockParabola instance. + """ + super().__init__(name, **kw) + self.mock_parabola_inst = mock_parabola_inst + + # Instrument parameters + for parname in ['x', 'y', 'z']: + self.parameters[parname] = getattr(mock_parabola_inst, parname) + self.add_parameter('gain', parameter_class=Parameter, + initial_value=1, + get_cmd=None, set_cmd=None) + + self.add_parameter('parabola', unit='a.u.', + get_cmd=self._get_parabola) + self.add_parameter('skewed_parabola', unit='a.u.', + get_cmd=self._get_skew_parabola) + + def _get_parabola(self) -> float: + val = self.mock_parabola_inst.parabola.get() + return val*self.gain.get() + + def _get_skew_parabola(self) -> float: + val = self.mock_parabola_inst.skewed_parabola.get() + return val*self.gain.get() + + +class DummyInstrument(DummyBase): + def __init__( + self, + name: str = "dummy", + gates: Sequence[str] = ("dac1", "dac2", "dac3"), + **kwargs: Any, + ): + """ + Create a dummy instrument that can be used for testing + + Args: + name: name for the instrument + gates: list of names that is used to create parameters for + the instrument + """ + super().__init__(name, **kwargs) + + # make gates + for _, g in enumerate(gates): + self.add_parameter( + g, + parameter_class=Parameter, + initial_value=0, + label=f"Gate {g}", + unit="V", + vals=Numbers(-800, 400), + get_cmd=None, + set_cmd=None, + ) + + +class DummyFailingInstrument(DummyBase): + def __init__(self, name: str = "dummy", fail: bool = True, **kwargs: Any): + + """ + Create a dummy instrument that fails on initialization + that can be used for testing + + Args: + name: name for the instrument + fail: if true, instrument will throw a runtime error on creation. + """ + super().__init__(name, **kwargs) + + if fail: + raise RuntimeError("Failed to create instrument") + + +class DummyAttrInstrument(DummyBase): + def __init__(self, name: str = "dummy", **kwargs: Any): + + """ + Create a dummy instrument that can be used for testing. + This instrument has its parameters declared as attributes + and does not use add_parameter. + """ + super().__init__(name, **kwargs) + + self.ch1 = Parameter( + "ch1", + instrument=self, + initial_value=0, + label="Gate ch1", + unit="V", + vals=Numbers(-800, 400), + get_cmd=None, + set_cmd=None, + ) + + self.ch2 = Parameter( + "ch2", + instrument=self, + initial_value=0, + label="Gate ch2", + unit="V", + vals=Numbers(-800, 400), + get_cmd=None, + set_cmd=None, + ) + + +class DmmExponentialParameter(Parameter): + def __init__(self, name: str, **kwargs: Any): + super().__init__(name, **kwargs) + self._ed = self._exponential_decay(5, 0.2) + next(self._ed) + + def get_raw(self) -> ParamRawDataType: + """ + This method is automatically wrapped to + provide a ``get`` method on the parameter instance. + """ + assert isinstance(self.root_instrument, DummyInstrumentWithMeasurement) + dac = self.root_instrument._setter_instr + val = self._ed.send(dac.ch1.cache.get()) + if self.root_instrument is not None: + mylogger = self.root_instrument.log + else: + mylogger = log + mylogger.debug("Getting raw value of parameter: %s as %s", self.full_name, val) + return val + + @staticmethod + def _exponential_decay(a: float, b: float) -> Generator[float, float, None]: + """ + Yields a*exp(-b*x) where x is put in + """ + x = 0.0 + while True: + x = yield a * np.exp(-b * x) + 0.02 * a * np.random.randn() + + +class DmmGaussParameter(Parameter): + def __init__(self, name: str, **kwargs: Any): + super().__init__(name, **kwargs) + self.x0 = 0.1 + self.y0 = 0.2 + self.sigma = 0.25 + self.noise: float = 0.0005 + self._gauss = self._gauss_model() + next(self._gauss) + + def get_raw(self) -> ParamRawDataType: + """ + This method is automatically wrapped to + provide a ``get`` method on the parameter instance. + """ + assert isinstance(self.root_instrument, DummyInstrumentWithMeasurement) + dac = self.root_instrument._setter_instr + val = self._gauss.send((dac.ch1.cache.get(), dac.ch2.cache.get())) + if self.root_instrument is not None: + mylogger = self.root_instrument.log + else: + mylogger = log + mylogger.debug("Getting raw value of parameter: %s as %s", self.full_name, val) + return val + + def _gauss_model(self) -> Generator[float, tuple[float, float], None]: + """ + Returns a generator sampling a gaussian. The gaussian is + normalised such that its maximal value is simply 1 + """ + + def gauss_2d(x: float, y: float) -> np.floating: + return np.exp( + -((self.x0 - x) ** 2 + (self.y0 - y) ** 2) / 2 / self.sigma**2 + ) * np.exp(2 * self.sigma**2) + + x = 0.0 + y = 0.0 + while True: + noise = np.random.randn() * self.noise + (x, y) = yield float(gauss_2d(x, y) + noise) + + +class DummyInstrumentWithMeasurement(DummyBase): + def __init__(self, name: str, setter_instr: DummyInstrument, **kwargs: Any): + super().__init__(name=name, **kwargs) + self._setter_instr = setter_instr + self.add_parameter('v1', + parameter_class=DmmExponentialParameter, + initial_value=0, + label='Gate v1', + unit="V", + vals=Numbers(-800, 400), + get_cmd=None, set_cmd=None) + self.add_parameter('v2', + parameter_class=DmmGaussParameter, + initial_value=0, + label='Gate v2', + unit="V", + vals=Numbers(-800, 400), + get_cmd=None, set_cmd=None) + + +class DummyChannel(InstrumentChannel): + """ + A single dummy channel implementation + """ + + def __init__(self, parent: Instrument, name: str, channel: str, **kwargs: Any): + super().__init__(parent, name, **kwargs) + + self._channel = channel + + # Add the various channel parameters + self.add_parameter('temperature', + parameter_class=Parameter, + initial_value=0, + label=f"Temperature_{channel}", + unit='K', + vals=Numbers(0, 300), + get_cmd=None, set_cmd=None) + + self.add_parameter(name='dummy_multi_parameter', + parameter_class=MultiSetPointParam) + + self.add_parameter(name='dummy_scalar_multi_parameter', + parameter_class=MultiScalarParam) + + self.add_parameter(name='dummy_2d_multi_parameter', + parameter_class=Multi2DSetPointParam) + + self.add_parameter(name='dummy_2d_multi_parameter_2', + parameter_class=Multi2DSetPointParam2Sizes) + + self.add_parameter(name='dummy_array_parameter', + parameter_class=ArraySetPointParam) + + self.add_parameter(name='dummy_complex_array_parameter', + parameter_class=ComplexArraySetPointParam) + + self.add_parameter('dummy_start', + initial_value=0, + unit='some unit', + label='f start', + vals=Numbers(0, 1e3), + get_cmd=None, + set_cmd=None) + + self.add_parameter( + "dummy_stop", + initial_value=100, + unit="some unit", + label="f stop", + vals=Numbers(1, 1e3), + get_cmd=None, + set_cmd=None, + ) + + self.add_parameter( + "dummy_n_points", + initial_value=101, + unit="", + vals=Numbers(1, 1e3), + get_cmd=None, + set_cmd=None, + ) + + self.add_parameter('dummy_start_2', + initial_value=0, + unit='some unit', + label='f start', + vals=Numbers(0, 1e3), + get_cmd=None, + set_cmd=None) + + self.add_parameter( + "dummy_stop_2", + initial_value=100, + unit="some unit", + label="f stop", + vals=Numbers(1, 1e3), + get_cmd=None, + set_cmd=None, + ) + + self.add_parameter( + "dummy_n_points_2", + initial_value=101, + unit="", + vals=Numbers(1, 1e3), + get_cmd=None, + set_cmd=None, + ) + + self.add_parameter('dummy_sp_axis', + unit='some unit', + label='Dummy sp axis', + parameter_class=GeneratedSetPoints, + startparam=self.dummy_start, + stopparam=self.dummy_stop, + numpointsparam=self.dummy_n_points, + vals=Arrays(shape=(self.dummy_n_points,))) + + self.add_parameter('dummy_sp_axis_2', + unit='some unit', + label='Dummy sp axis', + parameter_class=GeneratedSetPoints, + startparam=self.dummy_start_2, + stopparam=self.dummy_stop_2, + numpointsparam=self.dummy_n_points_2, + vals=Arrays(shape=(self.dummy_n_points_2,))) + + self.add_parameter(name='dummy_parameter_with_setpoints', + label='Dummy Parameter with Setpoints', + unit='some other unit', + setpoints=(self.dummy_sp_axis,), + vals=Arrays(shape=(self.dummy_n_points,)), + parameter_class=DummyParameterWithSetpoints1D) + + self.add_parameter(name='dummy_parameter_with_setpoints_2d', + label='Dummy Parameter with Setpoints', + unit='some other unit', + setpoints=(self.dummy_sp_axis,self.dummy_sp_axis_2), + vals=Arrays(shape=(self.dummy_n_points,self.dummy_n_points_2)), + parameter_class=DummyParameterWithSetpoints2D) + + self.add_parameter(name='dummy_text', + label='Dummy text', + unit='text unit', + initial_value='thisisastring', + set_cmd=None, + vals=Strings()) + + self.add_parameter(name='dummy_complex', + label='Dummy complex', + unit='complex unit', + initial_value=1+1j, + set_cmd=None, + vals=ComplexNumbers()) + + self.add_parameter(name='dummy_parameter_with_setpoints_complex', + label='Dummy Parameter with Setpoints complex', + unit='some other unit', + setpoints=(self.dummy_sp_axis,), + vals=Arrays(shape=(self.dummy_n_points,), + valid_types=(np.complexfloating,)), + parameter_class=DummyParameterWithSetpointsComplex) + + self.add_function(name='log_my_name', + call_cmd=partial(log.debug, f'{name}')) + + def turn_on(self) -> None: + pass + + +class DummyChannelInstrument(Instrument): + """ + Dummy instrument with channels + """ + + def __init__( + self, name: str, channel_names: Sequence[str] | None = None, **kwargs: Any + ): + super().__init__(name, **kwargs) + + channels = ChannelList(self, "TempSensors", DummyChannel, snapshotable=False) + + if channel_names is None: + channel_ids: Sequence[str] = ("A", "B", "C", "D", "E", "F") + channel_names = tuple(f"Chan{chan_name}" for chan_name in channel_ids) + else: + channel_ids = channel_names + for chan_name, chan_id in zip(channel_names, channel_ids): + channel = DummyChannel(self, chan_name, chan_id) + channels.append(channel) + self.add_submodule(chan_id, channel) + self.add_submodule("channels", channels.to_channel_tuple()) + + +class MultiGetter(MultiParameter): + """ + Test parameters with complicated return values + instantiate with kwargs:: + + MultiGetter(name1=return_val1, name2=return_val2) + + to set the names and (constant) return values of the + pieces returned. Each return_val can be any array-like + object + eg:: + + MultiGetter(one=1, onetwo=(1, 2)) + + """ + + def __init__(self, **kwargs: Any): + names = tuple(sorted(kwargs.keys())) + self._return = tuple(kwargs[k] for k in names) + shapes = tuple(np.shape(v) for v in self._return) + super().__init__(name='multigetter', names=names, shapes=shapes) + + def get_raw(self) -> ParamRawDataType: + return self._return + + +class MultiSetPointParam(MultiParameter): + """ + Multiparameter which only purpose it to test that units, setpoints + and so on are copied correctly to the individual arrays in the datarray. + """ + + def __init__( + self, + instrument: InstrumentBase | None = None, + name: str = "multi_setpoint_param", + **kwargs: Any, + ): + 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",), + ) + setpoint_labels = (("this setpoint",), ("this setpoint",)) + setpoint_units = (("this setpointunit",), ("this setpointunit",)) + super().__init__( + name, + names, + shapes, + instrument=instrument, + labels=labels, + units=units, + setpoints=setpoints, + setpoint_labels=setpoint_labels, + setpoint_names=setpoint_names, + setpoint_units=setpoint_units, + **kwargs, + ) + + def get_raw(self) -> ParamRawDataType: + items = (np.zeros(5), np.ones(5)) + return items + + +class Multi2DSetPointParam(MultiParameter): + """ + Multiparameter which only purpose it to test that units, setpoints + and so on are copied correctly to the individual arrays in the datarray. + """ + + def __init__( + self, + instrument: InstrumentBase | None = None, + name: str = "multi_2d_setpoint_param", + **kwargs: Any, + ): + 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)) + sp_base_2 = tuple(np.linspace(9, 11, 3)) + array_setpoints = setpoint_generator(sp_base_1, sp_base_2) + setpoints = (array_setpoints, array_setpoints) + 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", + ), + ) + setpoint_labels = ( + ("this setpoint", "that setpoint"), + ("this setpoint", "that setpoint"), + ) + setpoint_units = ( + ("this setpointunit", "that setpointunit"), + ("this setpointunit", "that setpointunit"), + ) + super().__init__( + name, + names, + shapes, + instrument=instrument, + labels=labels, + units=units, + setpoints=setpoints, + setpoint_labels=setpoint_labels, + setpoint_names=setpoint_names, + setpoint_units=setpoint_units, + **kwargs, + ) + + def get_raw(self) -> ParamRawDataType: + items = (np.zeros((5, 3)), np.ones((5, 3))) + return items + + + +class Multi2DSetPointParam2Sizes(MultiParameter): + """ + Multiparameter for testing containing individual parameters with different + shapes. + """ + + def __init__( + self, + instrument: InstrumentBase | None = None, + name: str = "multi_2d_setpoint_param", + **kwargs: Any, + ): + 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)) + sp_base_2_1 = tuple(np.linspace(9, 11, 3)) + array_setpoints_1 = setpoint_generator(sp_base_1_1, sp_base_2_1) + sp_base_1_2 = tuple(np.linspace(5, 9, 2)) + sp_base_2_2 = tuple(np.linspace(9, 11, 7)) + array_setpoints_2 = setpoint_generator(sp_base_1_2, sp_base_2_2) + setpoints = (array_setpoints_1, array_setpoints_2) + setpoint_names = ( + ( + "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", + ), + ) + setpoint_labels = ( + ("this setpoint 1", "that setpoint 1"), + ("this setpoint 2", "that setpoint 2"), + ) + setpoint_units = ( + ("this setpointunit", "that setpointunit"), + ("this setpointunit", "that setpointunit"), + ) + super().__init__( + name, + names, + shapes, + instrument=instrument, + labels=labels, + units=units, + setpoints=setpoints, + setpoint_labels=setpoint_labels, + setpoint_names=setpoint_names, + setpoint_units=setpoint_units, + **kwargs, + ) + + def get_raw(self) -> ParamRawDataType: + items = (np.zeros((5, 3)), np.ones((2, 7))) + return items + + +class MultiScalarParam(MultiParameter): + """ + Multiparameter whos elements are scalars i.e. similar to + Parameter with no setpoints etc. + """ + + def __init__( + self, + instrument: InstrumentBase | None = None, + name: str = "multiscalarparameter", + **kwargs: Any, + ): + shapes = ((), ()) + names = ('thisparam', 'thatparam') + labels = ('thisparam label', 'thatparam label') + units = ('thisparam unit', 'thatparam unit') + setpoints = ((), ()) + super().__init__( + name, + names, + shapes, + instrument=instrument, + labels=labels, + units=units, + setpoints=setpoints, + **kwargs, + ) + + def get_raw(self) -> ParamRawDataType: + items = (0, 1) + return items + + +class ArraySetPointParam(ArrayParameter): + """ + Arrayparameter which only purpose it to test that units, setpoints + and so on are copied correctly to the individual arrays in the datarray. + """ + + def __init__( + self, + instrument: InstrumentBase | None = None, + name: str = "array_setpoint_param", + **kwargs: Any, + ): + 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",) + super().__init__( + name, + shape, + instrument, + label=label, + unit=unit, + setpoints=setpoints, + setpoint_labels=setpoint_labels, + setpoint_names=setpoint_names, + setpoint_units=setpoint_units, + **kwargs, + ) + + def get_raw(self) -> ParamRawDataType: + item = np.ones(5) + 1 + return item + + +class ComplexArraySetPointParam(ArrayParameter): + """ + Arrayparameter that returns complex numbers + """ + + def __init__( + self, + instrument: InstrumentBase | None = None, + name: str = "testparameter", + **kwargs: Any, + ): + 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",) + super().__init__( + name, + shape, + instrument, + label=label, + unit=unit, + setpoints=setpoints, + setpoint_labels=setpoint_labels, + setpoint_names=setpoint_names, + setpoint_units=setpoint_units, + **kwargs, + ) + + def get_raw(self) -> ParamRawDataType: + item = np.arange(5) - 1j*np.arange(5) + return item + + +class GeneratedSetPoints(Parameter): + """ + A parameter that generates a setpoint array from start, stop and num points + parameters. + """ + + def __init__( + self, + startparam: Parameter, + stopparam: Parameter, + numpointsparam: Parameter, + *args: Any, + **kwargs: Any, + ): + super().__init__(*args, **kwargs) + self._startparam = startparam + self._stopparam = stopparam + self._numpointsparam = numpointsparam + + def get_raw(self) -> ParamRawDataType: + return np.linspace(self._startparam(), self._stopparam(), + self._numpointsparam()) + + +class DummyParameterWithSetpoints1D(ParameterWithSetpoints): + """ + Dummy parameter that returns data with a shape based on the + `dummy_n_points` parameter in the instrument. + """ + + def get_raw(self) -> ParamRawDataType: + assert isinstance(self.instrument, DummyChannel) + npoints = self.instrument.dummy_n_points() + return np.random.rand(npoints) + + +class DummyParameterWithSetpoints2D(ParameterWithSetpoints): + """ + Dummy parameter that returns data with a shape based on the + `dummy_n_points` and `dummy_n_points_2` parameters in the instrument. + """ + + def get_raw(self) -> ParamRawDataType: + assert isinstance(self.instrument, DummyChannel) + npoints = self.instrument.dummy_n_points() + npoints_2 = self.instrument.dummy_n_points_2() + return np.random.rand(npoints, npoints_2) + + + +class DummyParameterWithSetpointsComplex(ParameterWithSetpoints): + """ + Dummy parameter that returns data with a shape based on the + `dummy_n_points` parameter in the instrument. Returns Complex values + """ + + def get_raw(self) -> ParamRawDataType: + assert isinstance(self.instrument, DummyChannel) + npoints = self.instrument.dummy_n_points() + return np.random.rand(npoints) + 1j*np.random.rand(npoints) + + +def setpoint_generator( + *sp_bases: Sequence[float] | np.ndarray, +) -> tuple[np.ndarray | Sequence[float], ...]: + """ + Helper function to generate setpoints in the format that ArrayParameter + (and MultiParameter) expects + + Args: + *sp_bases: + + Returns: + + """ + setpoints: list[np.ndarray | Sequence[float]] = [] + for i, sp_base in enumerate(sp_bases): + if i == 0: + setpoints.append(sp_base) + else: + repeats = [len(sp) for sp in sp_bases[:i]] + repeats.append(1) + setpoints.append(np.tile(sp_base, repeats)) + + return tuple(setpoints) + + +class SnapShotTestInstrument(DummyBase): + """ + A highly specialized dummy instrument for testing the snapshot. Used by + test_snapshot.py + + Args: + name: name for the instrument + params: parameter names. The instrument will have these as parameters + params_to_skip: parameters to skip updating in the snapshot. Must be + a subset of params + """ + + def __init__(self, name: str, params: Sequence[str] = ('v1', 'v2', 'v3'), + params_to_skip: Sequence[str] = ('v2')): + + super().__init__(name) + + if not(set(params_to_skip).issubset(params)): + raise ValueError('Invalid input; params_to_skip must be a subset ' + 'of params') + + self._params_to_skip = params_to_skip + self._params = params + + # dict to keep track of how many time 'get' has been called on each + # parameter. Useful for testing params_to_skip_update in the snapshot + self._get_calls = {p: 0 for p in params} + + for p_name in params: + + self.add_parameter(p_name, label=f'{name} Label', unit='V', + set_cmd=None, + get_cmd=partial(self._getter, p_name)) + + def _getter(self, name: str) -> ParamRawDataType: + val = self.parameters[name].cache.get(get_if_invalid=False) + self._get_calls[name] += 1 + return val + + def snapshot_base( + self, + update: bool | None = True, + params_to_skip_update: Sequence[str] | None = None, + ) -> dict[Any, Any]: + if params_to_skip_update is None: + params_to_skip_update = self._params_to_skip + snap = super().snapshot_base( + update=update, params_to_skip_update=params_to_skip_update) + return snap + + +class MockField(DummyBase): + + def __init__( + self, + name: str, + vals: Numbers = Numbers(min_value=-1.0, max_value=1.0), + **kwargs: Any, + ): + """Mock instrument for emulating a magnetic field axis + + Args: + name (str): Instrument name + vals (Numbers, optional): Soft limits. Defaults to Numbers(min_value=-1., max_value=1.). + """ + super().__init__(name=name, **kwargs) + self._field = 0.0 + self.add_parameter("field", + parameter_class=Parameter, + initial_value=0.0, + unit='T', + vals=vals, + get_cmd=self.get_field, set_cmd=self.set_field) + self.add_parameter("ramp_rate", + parameter_class=Parameter, + initial_value=0.1, + unit='T/min', + get_cmd=None, set_cmd=None) + self._ramp_start_time: float | None = None + self._wait_time: float | None = None + self._fr = self._field_ramp() + next(self._fr) + + def get_field(self) -> float: + """ + This method is automatically wrapped to + provide a ``get`` method on the parameter instance. + """ + if self._ramp_start_time: + _time_since_start = time.time() - self._ramp_start_time + val = self._fr.send(_time_since_start) + self._field = val + return self._field + + def set_field(self, value: float, block: bool = True) -> None | float: + if self._field == value: + return value + + wait_time = 60. * np.abs(self._field - value) / self.ramp_rate() + self._wait_time = wait_time + self._sign = np.sign(value - self._field) + self._start_field = self._field + self._target_field = value + self._ramp_start_time = time.time() + + if block: + time.sleep(wait_time) + self._field = value + return value + else: + return None + + def _field_ramp_fcn(self, _time: float) -> float: + if self._wait_time is None: + return self._field + elif _time <= 0.0: + return self._start_field + elif _time >= self._wait_time: + return self._target_field + dfield = self.ramp_rate() * _time / 60.0 + return self._start_field + self._sign * dfield + + def _field_ramp(self) -> Generator[float, float, None]: + """ + Yields field for a given point in time + """ + time = 0.0 + while True: + time = yield float(self._field_ramp_fcn(time)) + + +class MockLockin(DummyBase): + def __init__(self, name: str, **kwargs: Any): + super().__init__(name=name, **kwargs) + self.add_parameter("X", + parameter_class=Parameter, + initial_value=1e-3, + unit='V', + get_cmd=None, set_cmd=None) + self.add_parameter("Y", + parameter_class=Parameter, + initial_value=1e-5, + unit='V', + get_cmd=None, set_cmd=None) + self.add_parameter("frequency", + parameter_class=Parameter, + initial_value=125., + unit='Hz', + get_cmd=None, set_cmd=None) + self.add_parameter("amplitude", + parameter_class=Parameter, + initial_value=0., + unit='V', + get_cmd=None, set_cmd=None) + self.add_parameter("phase", + parameter_class=Parameter, + initial_value=0., + unit='deg', + get_cmd=None, set_cmd=None) + self.add_parameter("time_constant", + parameter_class=Parameter, + initial_value=1.e-3, + unit='s', + get_cmd=None, set_cmd=None) + + +class MockDACChannel(InstrumentChannel): + """ + A single dummy channel implementation + """ + + def __init__(self, parent: InstrumentBase, name: str, num: str): + super().__init__(parent, name) + + self._num = num + self.add_parameter('voltage', + parameter_class=Parameter, + initial_value=0., + label=f"Voltage_{name}", + unit='V', + vals=Numbers(-2., 2.), + get_cmd=None, set_cmd=None) + self.add_parameter('dac_output', + parameter_class=Parameter, + initial_value="off", + vals=OnOff(), + get_cmd=None, set_cmd=None) + self.add_parameter('smc', + parameter_class=Parameter, + initial_value="off", + vals=OnOff(), + get_cmd=None, set_cmd=None) + self.add_parameter('bus', + parameter_class=Parameter, + initial_value="off", + vals=OnOff(), + get_cmd=None, set_cmd=None) + self.add_parameter('gnd', + parameter_class=Parameter, + initial_value="off", + vals=OnOff(), + get_cmd=None, set_cmd=None) + + def channel_number(self) -> str: + return self._num + + +class MockDAC(DummyBase): + def __init__(self, name: str = "mdac", num_channels: int = 10, **kwargs: Any): + + """ + Create a dummy instrument that can be used for testing + + Args: + name: name for the instrument + gates: list of names that is used to create parameters for + the instrument + """ + super().__init__(name, **kwargs) + + # make gates + channels = ChannelList(self, "channels", MockDACChannel) + for n in range(num_channels): + num = str(n + 1).zfill(2) + chan_name = f"ch{num}" + channel = MockDACChannel(parent=self, name=chan_name, num=num) + channels.append(channel) + self.add_submodule(chan_name, channel) + self.add_submodule("channels", channels.to_channel_tuple()) + + +class MockCustomChannel(InstrumentChannel): + def __init__( + self, + parent: InstrumentBase, + name: str, + channel: str | InstrumentChannel, + current_valid_range: Sequence[float] | None = None, + ) -> None: + """ + A custom instrument channel emulating an existing channel. + + It adds a parameter not found in the original channel, the + current_valid_range. + Args: + parent: Instrument to which the original channel belongs to, + usually a dac. + name: Name of channel. + channel: The original instrument channel. + current_valid_range: Voltage range the channel is expected to show + interesting features. It's just an example of an additional + parameter a regular instrument channel does not have. + """ + if isinstance(channel, str): + _, channel_name = channel.split(".") + instr_channel = getattr(parent, channel_name) + self._dac_channel = instr_channel + elif isinstance(channel, InstrumentChannel): + self._dac_channel = channel + else: + raise ValueError('Unknown input type for "channel".') + + super().__init__(parent, name) + + if current_valid_range is None: + current_valid_range = [] + super().add_parameter( + name="current_valid_range", + label=f"{name} valid voltage range", + initial_value=current_valid_range, + vals=ValidatorSequence(Numbers(), length=2), + get_cmd=None, + set_cmd=None, + ) + + self.add_parameter( + "voltage", + parameter_class=Parameter, + initial_value=0.0, + label=f"Voltage_{name}", + unit="V", + vals=Numbers(-2.0, 2.0), + get_cmd=None, + set_cmd=None, + ) diff --git a/src/qcodes/tests/dataset/conftest.py b/src/qcodes/tests/dataset/conftest.py index 897977e6c46..9057aa9bc65 100644 --- a/src/qcodes/tests/dataset/conftest.py +++ b/src/qcodes/tests/dataset/conftest.py @@ -17,8 +17,7 @@ from qcodes.dataset.descriptions.param_spec import ParamSpec, ParamSpecBase from qcodes.dataset.measurements import Measurement from qcodes.dataset.sqlite.database import connect -from qcodes.parameters import ArrayParameter, Parameter, ParameterWithSetpoints -from qcodes.tests.instrument_mocks import ( +from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, DummyChannelInstrument, DummyInstrument, @@ -26,6 +25,7 @@ Multi2DSetPointParam2Sizes, setpoint_generator, ) +from qcodes.parameters import ArrayParameter, Parameter, ParameterWithSetpoints from qcodes.validators import Arrays, ComplexNumbers, Numbers diff --git a/src/qcodes/tests/dataset/dond/test_do0d.py b/src/qcodes/tests/dataset/dond/test_do0d.py index 16837333afe..1096050f5ac 100644 --- a/src/qcodes/tests/dataset/dond/test_do0d.py +++ b/src/qcodes/tests/dataset/dond/test_do0d.py @@ -8,13 +8,13 @@ from qcodes import config, validators from qcodes.dataset import do0d, new_experiment from qcodes.dataset.data_set import DataSet -from qcodes.tests.dataset.conftest import ArrayshapedParam -from qcodes.tests.instrument_mocks import ( +from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, ) +from qcodes.tests.dataset.conftest import ArrayshapedParam @pytest.mark.usefixtures("plot_close", "experiment") diff --git a/src/qcodes/tests/dataset/dond/test_do1d.py b/src/qcodes/tests/dataset/dond/test_do1d.py index 21efcfa2b5d..88efe8557da 100644 --- a/src/qcodes/tests/dataset/dond/test_do1d.py +++ b/src/qcodes/tests/dataset/dond/test_do1d.py @@ -12,14 +12,14 @@ from qcodes import config, validators from qcodes.dataset import do1d, new_experiment from qcodes.dataset.data_set import DataSet -from qcodes.parameters import Parameter -from qcodes.tests.dataset.conftest import ArrayshapedParam -from qcodes.tests.instrument_mocks import ( +from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, ) +from qcodes.parameters import Parameter +from qcodes.tests.dataset.conftest import ArrayshapedParam @pytest.mark.usefixtures("plot_close", "experiment") diff --git a/src/qcodes/tests/dataset/dond/test_do2d.py b/src/qcodes/tests/dataset/dond/test_do2d.py index 7b6432e2f76..722a989b4f7 100644 --- a/src/qcodes/tests/dataset/dond/test_do2d.py +++ b/src/qcodes/tests/dataset/dond/test_do2d.py @@ -12,13 +12,13 @@ from qcodes import config from qcodes.dataset import do2d, new_experiment from qcodes.dataset.data_set import DataSet -from qcodes.parameters import Parameter -from qcodes.tests.instrument_mocks import ( +from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, ) +from qcodes.parameters import Parameter @pytest.mark.usefixtures("plot_close", "experiment") diff --git a/src/qcodes/tests/dataset/dond/test_doNd.py b/src/qcodes/tests/dataset/dond/test_doNd.py index 5fa60d2f5a4..b7aae98623f 100644 --- a/src/qcodes/tests/dataset/dond/test_doNd.py +++ b/src/qcodes/tests/dataset/dond/test_doNd.py @@ -26,14 +26,14 @@ ) from qcodes.dataset.data_set import DataSet from qcodes.dataset.dond.do_nd import _Sweeper -from qcodes.parameters import ManualParameter, Parameter, ParameterBase -from qcodes.tests.dataset.conftest import ArrayshapedParam -from qcodes.tests.instrument_mocks import ( +from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, ) +from qcodes.parameters import ManualParameter, Parameter, ParameterBase +from qcodes.tests.dataset.conftest import ArrayshapedParam from qcodes.validators import Ints diff --git a/src/qcodes/tests/dataset/fixtures/data_2018_01_17/data_001_testsweep_15_42_57/snapshot.json b/src/qcodes/tests/dataset/fixtures/data_2018_01_17/data_001_testsweep_15_42_57/snapshot.json index 2854afa4ce2..7de44914386 100644 --- a/src/qcodes/tests/dataset/fixtures/data_2018_01_17/data_001_testsweep_15_42_57/snapshot.json +++ b/src/qcodes/tests/dataset/fixtures/data_2018_01_17/data_001_testsweep_15_42_57/snapshot.json @@ -4,7 +4,7 @@ "dac": { "functions": {}, "submodules": {}, - "__class__": "qcodes.tests.instrument_mocks.DummyInstrument", + "__class__": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "parameters": { "IDN": { "value": { @@ -26,7 +26,7 @@ "label": "IDN", "name": "IDN", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "" @@ -41,7 +41,7 @@ "label": "Gate ch1", "name": "ch1", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V" @@ -56,7 +56,7 @@ "label": "Gate ch2", "name": "ch2", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V" @@ -70,7 +70,7 @@ "label": "Verbose Channel", "name": "verbose_channel", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V" @@ -81,7 +81,7 @@ "dmm": { "functions": {}, "submodules": {}, - "__class__": "qcodes.tests.instrument_mocks.DummyInstrument", + "__class__": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "parameters": { "IDN": { "value": { @@ -103,7 +103,7 @@ "label": "IDN", "name": "IDN", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dmm", "post_delay": 0, "unit": "" @@ -118,7 +118,7 @@ "label": "Gate voltage", "name": "voltage", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dmm", "post_delay": 0, "unit": "V" @@ -144,7 +144,7 @@ "label": "Gate ch1", "name": "ch1", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V" @@ -170,7 +170,7 @@ "label": "Gate voltage", "name": "voltage", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dmm", "post_delay": 0, "unit": "V" @@ -192,7 +192,7 @@ "label": "Gate ch1", "name": "ch1", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V", @@ -211,7 +211,7 @@ "label": "Gate voltage", "name": "voltage", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dmm", "post_delay": 0, "unit": "V", diff --git a/src/qcodes/tests/dataset/fixtures/data_2018_01_17/data_002_2D_test_15_43_14/snapshot.json b/src/qcodes/tests/dataset/fixtures/data_2018_01_17/data_002_2D_test_15_43_14/snapshot.json index 91d982dd71f..ed7775ab9a0 100644 --- a/src/qcodes/tests/dataset/fixtures/data_2018_01_17/data_002_2D_test_15_43_14/snapshot.json +++ b/src/qcodes/tests/dataset/fixtures/data_2018_01_17/data_002_2D_test_15_43_14/snapshot.json @@ -4,7 +4,7 @@ "dac": { "functions": {}, "submodules": {}, - "__class__": "qcodes.tests.instrument_mocks.DummyInstrument", + "__class__": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "parameters": { "IDN": { "value": { @@ -26,7 +26,7 @@ "label": "IDN", "name": "IDN", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "" @@ -41,7 +41,7 @@ "label": "Gate ch1", "name": "ch1", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V" @@ -56,7 +56,7 @@ "label": "Gate ch2", "name": "ch2", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V" @@ -70,7 +70,7 @@ "label": "Verbose Channel", "name": "verbose_channel", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V" @@ -81,7 +81,7 @@ "dmm": { "functions": {}, "submodules": {}, - "__class__": "qcodes.tests.instrument_mocks.DummyInstrument", + "__class__": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "parameters": { "IDN": { "value": { @@ -103,7 +103,7 @@ "label": "IDN", "name": "IDN", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dmm", "post_delay": 0, "unit": "" @@ -118,7 +118,7 @@ "label": "Gate voltage", "name": "voltage", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dmm", "post_delay": 0, "unit": "V" @@ -144,7 +144,7 @@ "label": "Gate ch1", "name": "ch1", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V" @@ -173,7 +173,7 @@ "label": "Gate ch2", "name": "ch2", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V" @@ -199,7 +199,7 @@ "label": "Gate voltage", "name": "voltage", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dmm", "post_delay": 0, "unit": "V" @@ -224,7 +224,7 @@ "label": "Gate ch1", "name": "ch1", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V", @@ -243,7 +243,7 @@ "label": "Gate ch2", "name": "ch2", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dac", "post_delay": 0, "unit": "V", @@ -265,7 +265,7 @@ "label": "Gate voltage", "name": "voltage", "inter_delay": 0, - "instrument": "qcodes.tests.instrument_mocks.DummyInstrument", + "instrument": "qcodes.instrument_drivers.mock_instruments.DummyInstrument", "instrument_name": "dmm", "post_delay": 0, "unit": "V", diff --git a/src/qcodes/tests/dataset/test_database_extract_runs.py b/src/qcodes/tests/dataset/test_database_extract_runs.py index e2cbd46dea9..a3d863ef148 100644 --- a/src/qcodes/tests/dataset/test_database_extract_runs.py +++ b/src/qcodes/tests/dataset/test_database_extract_runs.py @@ -33,9 +33,9 @@ from qcodes.dataset.sqlite.connection import path_to_dbfile from qcodes.dataset.sqlite.database import get_db_version_and_newest_available_version from qcodes.dataset.sqlite.queries import get_experiments +from qcodes.instrument_drivers.mock_instruments import DummyInstrument from qcodes.station import Station from qcodes.tests.common import error_caused_by, skip_if_no_fixtures -from qcodes.tests.instrument_mocks import DummyInstrument @contextmanager diff --git a/src/qcodes/tests/dataset/test_detect_shape.py b/src/qcodes/tests/dataset/test_detect_shape.py index 26e29bd691d..a538caf9ae6 100644 --- a/src/qcodes/tests/dataset/test_detect_shape.py +++ b/src/qcodes/tests/dataset/test_detect_shape.py @@ -4,13 +4,13 @@ from hypothesis import HealthCheck, given, settings from qcodes.dataset.descriptions.detect_shapes import detect_shape_of_measurement -from qcodes.parameters import Parameter -from qcodes.tests.instrument_mocks import ( +from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, ) +from qcodes.parameters import Parameter from qcodes.validators import Arrays from .conftest import ArrayshapedParam diff --git a/src/qcodes/tests/dataset/test_plotting.py b/src/qcodes/tests/dataset/test_plotting.py index 5a7c8b652f0..abe442e3e1a 100644 --- a/src/qcodes/tests/dataset/test_plotting.py +++ b/src/qcodes/tests/dataset/test_plotting.py @@ -16,8 +16,8 @@ plot_by_id, plot_dataset, ) +from qcodes.instrument_drivers.mock_instruments import DummyInstrument from qcodes.plotting.axis_labels import _ENGINEERING_PREFIXES, _UNITS_FOR_RESCALING -from qcodes.tests.instrument_mocks import DummyInstrument class TerminateLoopException(Exception): diff --git a/src/qcodes/tests/dataset/test_snapshot.py b/src/qcodes/tests/dataset/test_snapshot.py index 6c6ed35736c..28248203d32 100644 --- a/src/qcodes/tests/dataset/test_snapshot.py +++ b/src/qcodes/tests/dataset/test_snapshot.py @@ -4,9 +4,9 @@ import pytest from qcodes.dataset.measurements import Measurement +from qcodes.instrument_drivers.mock_instruments import DummyInstrument from qcodes.parameters import ManualParameter from qcodes.station import Station -from qcodes.tests.instrument_mocks import DummyInstrument @pytest.fixture # scope is "function" per default diff --git a/src/qcodes/tests/delegate/conftest.py b/src/qcodes/tests/delegate/conftest.py index a53087afff6..f232bf46a18 100644 --- a/src/qcodes/tests/delegate/conftest.py +++ b/src/qcodes/tests/delegate/conftest.py @@ -3,8 +3,8 @@ import pytest +from qcodes.instrument_drivers.mock_instruments import MockDAC, MockField, MockLockin from qcodes.station import Station -from qcodes.tests.instrument_mocks import MockDAC, MockField, MockLockin PARENT_DIR = pathlib.Path(__file__).parent.absolute() diff --git a/src/qcodes/tests/delegate/data/chip.yml b/src/qcodes/tests/delegate/data/chip.yml index 924f96c0137..20dac4f2e04 100644 --- a/src/qcodes/tests/delegate/data/chip.yml +++ b/src/qcodes/tests/delegate/data/chip.yml @@ -28,11 +28,11 @@ instruments: channels: gate_1: channel: dac.ch01 - type: qcodes.tests.instrument_mocks.MockCustomChannel + type: qcodes.instrument_drivers.mock_instruments.MockCustomChannel current_valid_range: [-0.5, 0] fast_gate: channel: dac.ch02 - type: qcodes.tests.instrument_mocks.DummyChannel + type: qcodes.instrument_drivers.mock_instruments.DummyChannel set_initial_values_on_load: true initial_values: diff --git a/src/qcodes/tests/delegate/data/chip_typo.yml b/src/qcodes/tests/delegate/data/chip_typo.yml index ee49d1fe767..61cf81c48bc 100644 --- a/src/qcodes/tests/delegate/data/chip_typo.yml +++ b/src/qcodes/tests/delegate/data/chip_typo.yml @@ -25,7 +25,7 @@ instruments: parameters: readout: lockin.phase channels: - type: qcodes.tests.instrument_mocks.MockCustomChannel + type: qcodes.instrument_drivers.mock_instruments.MockCustomChannel gate_1: channel: dac.ch01 current_valid_range: [-0.5, 0] diff --git a/src/qcodes/tests/delegate/test_delegate_instrument.py b/src/qcodes/tests/delegate/test_delegate_instrument.py index 36dcd9a0057..5c6563371ed 100644 --- a/src/qcodes/tests/delegate/test_delegate_instrument.py +++ b/src/qcodes/tests/delegate/test_delegate_instrument.py @@ -2,7 +2,7 @@ from numpy.testing import assert_almost_equal -from qcodes.tests.instrument_mocks import MockField +from qcodes.instrument_drivers.mock_instruments import MockField def test_mock_dac(dac) -> None: diff --git a/src/qcodes/tests/delegate/test_device.py b/src/qcodes/tests/delegate/test_device.py index 478f65a6fb5..2a1cf99f43a 100644 --- a/src/qcodes/tests/delegate/test_device.py +++ b/src/qcodes/tests/delegate/test_device.py @@ -4,7 +4,7 @@ import pytest from qcodes.dataset import Measurement -from qcodes.tests.instrument_mocks import DummyChannel, MockCustomChannel +from qcodes.instrument_drivers.mock_instruments import DummyChannel, MockCustomChannel def test_device(station, chip_config, dac, lockin) -> None: diff --git a/src/qcodes/tests/instrument_mocks.py b/src/qcodes/tests/instrument_mocks.py index 89e1a3761f4..679da7ec127 100644 --- a/src/qcodes/tests/instrument_mocks.py +++ b/src/qcodes/tests/instrument_mocks.py @@ -1,3 +1,6 @@ +# ruff: noqa: F401 +# left for backwards compatibility will be deprecated and removed +# along with the rest of qcodes.tests from __future__ import annotations import logging @@ -9,6 +12,35 @@ import numpy as np from qcodes.instrument import ChannelList, Instrument, InstrumentBase, InstrumentChannel +from qcodes.instrument_drivers.mock_instruments import ( + ArraySetPointParam, + ComplexArraySetPointParam, + DmmExponentialParameter, + DmmGaussParameter, + DummyBase, + DummyChannel, + DummyChannelInstrument, + DummyFailingInstrument, + DummyInstrument, + DummyInstrumentWithMeasurement, + DummyParameterWithSetpoints1D, + DummyParameterWithSetpoints2D, + DummyParameterWithSetpointsComplex, + GeneratedSetPoints, + MockCustomChannel, + MockDAC, + MockDACChannel, + MockField, + MockLockin, + MockMetaParabola, + MockParabola, + Multi2DSetPointParam, + Multi2DSetPointParam2Sizes, + MultiScalarParam, + MultiSetPointParam, + SnapShotTestInstrument, + setpoint_generator, +) from qcodes.parameters import ( ArrayParameter, MultiParameter, @@ -18,1122 +50,3 @@ ) from qcodes.validators import Arrays, ComplexNumbers, Numbers, OnOff, Strings from qcodes.validators import Sequence as ValidatorSequence - -log = logging.getLogger(__name__) - - -class DummyBase(Instrument): - def get_idn(self) -> dict[str, str | None]: - return { - "vendor": "QCoDeS", - "model": str(self.__class__), - "seral": "NA", - "firmware": "NA", - } - - -class MockParabola(DummyBase): - """ - Holds dummy parameters which are get and set able as well as provides - some basic functions that depends on these parameters for testing - purposes. - - This instrument is intended to be simpler than the mock model in that it - does not emulate communications. - - It has 3 main parameters (x, y, z) in order to allow for testing of 3D - sweeps. The function (parabola with optional noise) is chosen to allow - testing of numerical optimizations. - """ - - def __init__(self, name: str, **kw: Any): - super().__init__(name, **kw) - - # Instrument parameters - for parname in ['x', 'y', 'z']: - self.add_parameter(parname, unit='a.u.', - parameter_class=Parameter, - vals=Numbers(), initial_value=0, - get_cmd=None, set_cmd=None) - - self.add_parameter('noise', unit='a.u.', - label='white noise amplitude', - parameter_class=Parameter, - vals=Numbers(), initial_value=0, - get_cmd=None, set_cmd=None) - - self.add_parameter('parabola', unit='a.u.', - get_cmd=self._measure_parabola) - self.add_parameter('skewed_parabola', unit='a.u.', - get_cmd=self._measure_skewed_parabola) - - def _measure_parabola(self) -> float: - return (self.x.get()**2 + self.y.get()**2 + self.z.get()**2 + - self.noise.get()*np.random.rand(1)) - - def _measure_skewed_parabola(self) -> float: - """ - Adds an -x term to add a corelation between the parameters. - """ - return ((self.x.get()**2 + self.y.get()**2 + - self.z.get()**2)*(1 + abs(self.y.get()-self.x.get())) + - self.noise.get()*np.random.rand(1)) - - -class MockMetaParabola(InstrumentBase): - """ - Test for a meta instrument, has a tunable gain knob - - Unlike a MockParabola, a MockMetaParabola does not have a connection, or - access to ask_raw/write_raw, i.e. it would not be connected to a real instrument. - - It is also not tracked in the global _all_instruments list, but is still - snapshottable in a station. - """ - - def __init__(self, name: str, mock_parabola_inst: MockParabola, **kw: Any): - """ - Create a new MockMetaParabola, connected to an existing MockParabola instance. - """ - super().__init__(name, **kw) - self.mock_parabola_inst = mock_parabola_inst - - # Instrument parameters - for parname in ['x', 'y', 'z']: - self.parameters[parname] = getattr(mock_parabola_inst, parname) - self.add_parameter('gain', parameter_class=Parameter, - initial_value=1, - get_cmd=None, set_cmd=None) - - self.add_parameter('parabola', unit='a.u.', - get_cmd=self._get_parabola) - self.add_parameter('skewed_parabola', unit='a.u.', - get_cmd=self._get_skew_parabola) - - def _get_parabola(self) -> float: - val = self.mock_parabola_inst.parabola.get() - return val*self.gain.get() - - def _get_skew_parabola(self) -> float: - val = self.mock_parabola_inst.skewed_parabola.get() - return val*self.gain.get() - - -class DummyInstrument(DummyBase): - def __init__( - self, - name: str = "dummy", - gates: Sequence[str] = ("dac1", "dac2", "dac3"), - **kwargs: Any, - ): - """ - Create a dummy instrument that can be used for testing - - Args: - name: name for the instrument - gates: list of names that is used to create parameters for - the instrument - """ - super().__init__(name, **kwargs) - - # make gates - for _, g in enumerate(gates): - self.add_parameter( - g, - parameter_class=Parameter, - initial_value=0, - label=f"Gate {g}", - unit="V", - vals=Numbers(-800, 400), - get_cmd=None, - set_cmd=None, - ) - - -class DummyFailingInstrument(DummyBase): - def __init__(self, name: str = "dummy", fail: bool = True, **kwargs: Any): - - """ - Create a dummy instrument that fails on initialization - that can be used for testing - - Args: - name: name for the instrument - fail: if true, instrument will throw a runtime error on creation. - """ - super().__init__(name, **kwargs) - - if fail: - raise RuntimeError("Failed to create instrument") - - -class DummyAttrInstrument(DummyBase): - def __init__(self, name: str = "dummy", **kwargs: Any): - - """ - Create a dummy instrument that can be used for testing. - This instrument has its parameters declared as attributes - and does not use add_parameter. - """ - super().__init__(name, **kwargs) - - self.ch1 = Parameter( - "ch1", - instrument=self, - initial_value=0, - label="Gate ch1", - unit="V", - vals=Numbers(-800, 400), - get_cmd=None, - set_cmd=None, - ) - - self.ch2 = Parameter( - "ch2", - instrument=self, - initial_value=0, - label="Gate ch2", - unit="V", - vals=Numbers(-800, 400), - get_cmd=None, - set_cmd=None, - ) - - -class DmmExponentialParameter(Parameter): - def __init__(self, name: str, **kwargs: Any): - super().__init__(name, **kwargs) - self._ed = self._exponential_decay(5, 0.2) - next(self._ed) - - def get_raw(self) -> ParamRawDataType: - """ - This method is automatically wrapped to - provide a ``get`` method on the parameter instance. - """ - assert isinstance(self.root_instrument, DummyInstrumentWithMeasurement) - dac = self.root_instrument._setter_instr - val = self._ed.send(dac.ch1.cache.get()) - if self.root_instrument is not None: - mylogger = self.root_instrument.log - else: - mylogger = log - mylogger.debug("Getting raw value of parameter: %s as %s", self.full_name, val) - return val - - @staticmethod - def _exponential_decay(a: float, b: float) -> Generator[float, float, None]: - """ - Yields a*exp(-b*x) where x is put in - """ - x = 0.0 - while True: - x = yield a * np.exp(-b * x) + 0.02 * a * np.random.randn() - - -class DmmGaussParameter(Parameter): - def __init__(self, name: str, **kwargs: Any): - super().__init__(name, **kwargs) - self.x0 = 0.1 - self.y0 = 0.2 - self.sigma = 0.25 - self.noise: float = 0.0005 - self._gauss = self._gauss_model() - next(self._gauss) - - def get_raw(self) -> ParamRawDataType: - """ - This method is automatically wrapped to - provide a ``get`` method on the parameter instance. - """ - assert isinstance(self.root_instrument, DummyInstrumentWithMeasurement) - dac = self.root_instrument._setter_instr - val = self._gauss.send((dac.ch1.cache.get(), dac.ch2.cache.get())) - if self.root_instrument is not None: - mylogger = self.root_instrument.log - else: - mylogger = log - mylogger.debug("Getting raw value of parameter: %s as %s", self.full_name, val) - return val - - def _gauss_model(self) -> Generator[float, tuple[float, float], None]: - """ - Returns a generator sampling a gaussian. The gaussian is - normalised such that its maximal value is simply 1 - """ - - def gauss_2d(x: float, y: float) -> np.floating: - return np.exp( - -((self.x0 - x) ** 2 + (self.y0 - y) ** 2) / 2 / self.sigma**2 - ) * np.exp(2 * self.sigma**2) - - x = 0.0 - y = 0.0 - while True: - noise = np.random.randn() * self.noise - (x, y) = yield float(gauss_2d(x, y) + noise) - - -class DummyInstrumentWithMeasurement(DummyBase): - def __init__(self, name: str, setter_instr: DummyInstrument, **kwargs: Any): - super().__init__(name=name, **kwargs) - self._setter_instr = setter_instr - self.add_parameter('v1', - parameter_class=DmmExponentialParameter, - initial_value=0, - label='Gate v1', - unit="V", - vals=Numbers(-800, 400), - get_cmd=None, set_cmd=None) - self.add_parameter('v2', - parameter_class=DmmGaussParameter, - initial_value=0, - label='Gate v2', - unit="V", - vals=Numbers(-800, 400), - get_cmd=None, set_cmd=None) - - -class DummyChannel(InstrumentChannel): - """ - A single dummy channel implementation - """ - - def __init__(self, parent: Instrument, name: str, channel: str, **kwargs: Any): - super().__init__(parent, name, **kwargs) - - self._channel = channel - - # Add the various channel parameters - self.add_parameter('temperature', - parameter_class=Parameter, - initial_value=0, - label=f"Temperature_{channel}", - unit='K', - vals=Numbers(0, 300), - get_cmd=None, set_cmd=None) - - self.add_parameter(name='dummy_multi_parameter', - parameter_class=MultiSetPointParam) - - self.add_parameter(name='dummy_scalar_multi_parameter', - parameter_class=MultiScalarParam) - - self.add_parameter(name='dummy_2d_multi_parameter', - parameter_class=Multi2DSetPointParam) - - self.add_parameter(name='dummy_2d_multi_parameter_2', - parameter_class=Multi2DSetPointParam2Sizes) - - self.add_parameter(name='dummy_array_parameter', - parameter_class=ArraySetPointParam) - - self.add_parameter(name='dummy_complex_array_parameter', - parameter_class=ComplexArraySetPointParam) - - self.add_parameter('dummy_start', - initial_value=0, - unit='some unit', - label='f start', - vals=Numbers(0, 1e3), - get_cmd=None, - set_cmd=None) - - self.add_parameter( - "dummy_stop", - initial_value=100, - unit="some unit", - label="f stop", - vals=Numbers(1, 1e3), - get_cmd=None, - set_cmd=None, - ) - - self.add_parameter( - "dummy_n_points", - initial_value=101, - unit="", - vals=Numbers(1, 1e3), - get_cmd=None, - set_cmd=None, - ) - - self.add_parameter('dummy_start_2', - initial_value=0, - unit='some unit', - label='f start', - vals=Numbers(0, 1e3), - get_cmd=None, - set_cmd=None) - - self.add_parameter( - "dummy_stop_2", - initial_value=100, - unit="some unit", - label="f stop", - vals=Numbers(1, 1e3), - get_cmd=None, - set_cmd=None, - ) - - self.add_parameter( - "dummy_n_points_2", - initial_value=101, - unit="", - vals=Numbers(1, 1e3), - get_cmd=None, - set_cmd=None, - ) - - self.add_parameter('dummy_sp_axis', - unit='some unit', - label='Dummy sp axis', - parameter_class=GeneratedSetPoints, - startparam=self.dummy_start, - stopparam=self.dummy_stop, - numpointsparam=self.dummy_n_points, - vals=Arrays(shape=(self.dummy_n_points,))) - - self.add_parameter('dummy_sp_axis_2', - unit='some unit', - label='Dummy sp axis', - parameter_class=GeneratedSetPoints, - startparam=self.dummy_start_2, - stopparam=self.dummy_stop_2, - numpointsparam=self.dummy_n_points_2, - vals=Arrays(shape=(self.dummy_n_points_2,))) - - self.add_parameter(name='dummy_parameter_with_setpoints', - label='Dummy Parameter with Setpoints', - unit='some other unit', - setpoints=(self.dummy_sp_axis,), - vals=Arrays(shape=(self.dummy_n_points,)), - parameter_class=DummyParameterWithSetpoints1D) - - self.add_parameter(name='dummy_parameter_with_setpoints_2d', - label='Dummy Parameter with Setpoints', - unit='some other unit', - setpoints=(self.dummy_sp_axis,self.dummy_sp_axis_2), - vals=Arrays(shape=(self.dummy_n_points,self.dummy_n_points_2)), - parameter_class=DummyParameterWithSetpoints2D) - - self.add_parameter(name='dummy_text', - label='Dummy text', - unit='text unit', - initial_value='thisisastring', - set_cmd=None, - vals=Strings()) - - self.add_parameter(name='dummy_complex', - label='Dummy complex', - unit='complex unit', - initial_value=1+1j, - set_cmd=None, - vals=ComplexNumbers()) - - self.add_parameter(name='dummy_parameter_with_setpoints_complex', - label='Dummy Parameter with Setpoints complex', - unit='some other unit', - setpoints=(self.dummy_sp_axis,), - vals=Arrays(shape=(self.dummy_n_points,), - valid_types=(np.complexfloating,)), - parameter_class=DummyParameterWithSetpointsComplex) - - self.add_function(name='log_my_name', - call_cmd=partial(log.debug, f'{name}')) - - def turn_on(self) -> None: - pass - - -class DummyChannelInstrument(Instrument): - """ - Dummy instrument with channels - """ - - def __init__( - self, name: str, channel_names: Sequence[str] | None = None, **kwargs: Any - ): - super().__init__(name, **kwargs) - - channels = ChannelList(self, "TempSensors", DummyChannel, snapshotable=False) - - if channel_names is None: - channel_ids: Sequence[str] = ("A", "B", "C", "D", "E", "F") - channel_names = tuple(f"Chan{chan_name}" for chan_name in channel_ids) - else: - channel_ids = channel_names - for chan_name, chan_id in zip(channel_names, channel_ids): - channel = DummyChannel(self, chan_name, chan_id) - channels.append(channel) - self.add_submodule(chan_id, channel) - self.add_submodule("channels", channels.to_channel_tuple()) - - -class MultiGetter(MultiParameter): - """ - Test parameters with complicated return values - instantiate with kwargs:: - - MultiGetter(name1=return_val1, name2=return_val2) - - to set the names and (constant) return values of the - pieces returned. Each return_val can be any array-like - object - eg:: - - MultiGetter(one=1, onetwo=(1, 2)) - - """ - - def __init__(self, **kwargs: Any): - names = tuple(sorted(kwargs.keys())) - self._return = tuple(kwargs[k] for k in names) - shapes = tuple(np.shape(v) for v in self._return) - super().__init__(name='multigetter', names=names, shapes=shapes) - - def get_raw(self) -> ParamRawDataType: - return self._return - - -class MultiSetPointParam(MultiParameter): - """ - Multiparameter which only purpose it to test that units, setpoints - and so on are copied correctly to the individual arrays in the datarray. - """ - - def __init__( - self, - instrument: InstrumentBase | None = None, - name: str = "multi_setpoint_param", - **kwargs: Any, - ): - 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",), - ) - setpoint_labels = (("this setpoint",), ("this setpoint",)) - setpoint_units = (("this setpointunit",), ("this setpointunit",)) - super().__init__( - name, - names, - shapes, - instrument=instrument, - labels=labels, - units=units, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, - ) - - def get_raw(self) -> ParamRawDataType: - items = (np.zeros(5), np.ones(5)) - return items - - -class Multi2DSetPointParam(MultiParameter): - """ - Multiparameter which only purpose it to test that units, setpoints - and so on are copied correctly to the individual arrays in the datarray. - """ - - def __init__( - self, - instrument: InstrumentBase | None = None, - name: str = "multi_2d_setpoint_param", - **kwargs: Any, - ): - 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)) - sp_base_2 = tuple(np.linspace(9, 11, 3)) - array_setpoints = setpoint_generator(sp_base_1, sp_base_2) - setpoints = (array_setpoints, array_setpoints) - 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", - ), - ) - setpoint_labels = ( - ("this setpoint", "that setpoint"), - ("this setpoint", "that setpoint"), - ) - setpoint_units = ( - ("this setpointunit", "that setpointunit"), - ("this setpointunit", "that setpointunit"), - ) - super().__init__( - name, - names, - shapes, - instrument=instrument, - labels=labels, - units=units, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, - ) - - def get_raw(self) -> ParamRawDataType: - items = (np.zeros((5, 3)), np.ones((5, 3))) - return items - - - -class Multi2DSetPointParam2Sizes(MultiParameter): - """ - Multiparameter for testing containing individual parameters with different - shapes. - """ - - def __init__( - self, - instrument: InstrumentBase | None = None, - name: str = "multi_2d_setpoint_param", - **kwargs: Any, - ): - 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)) - sp_base_2_1 = tuple(np.linspace(9, 11, 3)) - array_setpoints_1 = setpoint_generator(sp_base_1_1, sp_base_2_1) - sp_base_1_2 = tuple(np.linspace(5, 9, 2)) - sp_base_2_2 = tuple(np.linspace(9, 11, 7)) - array_setpoints_2 = setpoint_generator(sp_base_1_2, sp_base_2_2) - setpoints = (array_setpoints_1, array_setpoints_2) - setpoint_names = ( - ( - "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", - ), - ) - setpoint_labels = ( - ("this setpoint 1", "that setpoint 1"), - ("this setpoint 2", "that setpoint 2"), - ) - setpoint_units = ( - ("this setpointunit", "that setpointunit"), - ("this setpointunit", "that setpointunit"), - ) - super().__init__( - name, - names, - shapes, - instrument=instrument, - labels=labels, - units=units, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, - ) - - def get_raw(self) -> ParamRawDataType: - items = (np.zeros((5, 3)), np.ones((2, 7))) - return items - - -class MultiScalarParam(MultiParameter): - """ - Multiparameter whos elements are scalars i.e. similar to - Parameter with no setpoints etc. - """ - - def __init__( - self, - instrument: InstrumentBase | None = None, - name: str = "multiscalarparameter", - **kwargs: Any, - ): - shapes = ((), ()) - names = ('thisparam', 'thatparam') - labels = ('thisparam label', 'thatparam label') - units = ('thisparam unit', 'thatparam unit') - setpoints = ((), ()) - super().__init__( - name, - names, - shapes, - instrument=instrument, - labels=labels, - units=units, - setpoints=setpoints, - **kwargs, - ) - - def get_raw(self) -> ParamRawDataType: - items = (0, 1) - return items - - -class ArraySetPointParam(ArrayParameter): - """ - Arrayparameter which only purpose it to test that units, setpoints - and so on are copied correctly to the individual arrays in the datarray. - """ - - def __init__( - self, - instrument: InstrumentBase | None = None, - name: str = "array_setpoint_param", - **kwargs: Any, - ): - 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",) - super().__init__( - name, - shape, - instrument, - label=label, - unit=unit, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, - ) - - def get_raw(self) -> ParamRawDataType: - item = np.ones(5) + 1 - return item - - -class ComplexArraySetPointParam(ArrayParameter): - """ - Arrayparameter that returns complex numbers - """ - - def __init__( - self, - instrument: InstrumentBase | None = None, - name: str = "testparameter", - **kwargs: Any, - ): - 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",) - super().__init__( - name, - shape, - instrument, - label=label, - unit=unit, - setpoints=setpoints, - setpoint_labels=setpoint_labels, - setpoint_names=setpoint_names, - setpoint_units=setpoint_units, - **kwargs, - ) - - def get_raw(self) -> ParamRawDataType: - item = np.arange(5) - 1j*np.arange(5) - return item - - -class GeneratedSetPoints(Parameter): - """ - A parameter that generates a setpoint array from start, stop and num points - parameters. - """ - - def __init__( - self, - startparam: Parameter, - stopparam: Parameter, - numpointsparam: Parameter, - *args: Any, - **kwargs: Any, - ): - super().__init__(*args, **kwargs) - self._startparam = startparam - self._stopparam = stopparam - self._numpointsparam = numpointsparam - - def get_raw(self) -> ParamRawDataType: - return np.linspace(self._startparam(), self._stopparam(), - self._numpointsparam()) - - -class DummyParameterWithSetpoints1D(ParameterWithSetpoints): - """ - Dummy parameter that returns data with a shape based on the - `dummy_n_points` parameter in the instrument. - """ - - def get_raw(self) -> ParamRawDataType: - assert isinstance(self.instrument, DummyChannel) - npoints = self.instrument.dummy_n_points() - return np.random.rand(npoints) - - -class DummyParameterWithSetpoints2D(ParameterWithSetpoints): - """ - Dummy parameter that returns data with a shape based on the - `dummy_n_points` and `dummy_n_points_2` parameters in the instrument. - """ - - def get_raw(self) -> ParamRawDataType: - assert isinstance(self.instrument, DummyChannel) - npoints = self.instrument.dummy_n_points() - npoints_2 = self.instrument.dummy_n_points_2() - return np.random.rand(npoints, npoints_2) - - - -class DummyParameterWithSetpointsComplex(ParameterWithSetpoints): - """ - Dummy parameter that returns data with a shape based on the - `dummy_n_points` parameter in the instrument. Returns Complex values - """ - - def get_raw(self) -> ParamRawDataType: - assert isinstance(self.instrument, DummyChannel) - npoints = self.instrument.dummy_n_points() - return np.random.rand(npoints) + 1j*np.random.rand(npoints) - - -def setpoint_generator( - *sp_bases: Sequence[float] | np.ndarray, -) -> tuple[np.ndarray | Sequence[float], ...]: - """ - Helper function to generate setpoints in the format that ArrayParameter - (and MultiParameter) expects - - Args: - *sp_bases: - - Returns: - - """ - setpoints: list[np.ndarray | Sequence[float]] = [] - for i, sp_base in enumerate(sp_bases): - if i == 0: - setpoints.append(sp_base) - else: - repeats = [len(sp) for sp in sp_bases[:i]] - repeats.append(1) - setpoints.append(np.tile(sp_base, repeats)) - - return tuple(setpoints) - - -class SnapShotTestInstrument(DummyBase): - """ - A highly specialized dummy instrument for testing the snapshot. Used by - test_snapshot.py - - Args: - name: name for the instrument - params: parameter names. The instrument will have these as parameters - params_to_skip: parameters to skip updating in the snapshot. Must be - a subset of params - """ - - def __init__(self, name: str, params: Sequence[str] = ('v1', 'v2', 'v3'), - params_to_skip: Sequence[str] = ('v2')): - - super().__init__(name) - - if not(set(params_to_skip).issubset(params)): - raise ValueError('Invalid input; params_to_skip must be a subset ' - 'of params') - - self._params_to_skip = params_to_skip - self._params = params - - # dict to keep track of how many time 'get' has been called on each - # parameter. Useful for testing params_to_skip_update in the snapshot - self._get_calls = {p: 0 for p in params} - - for p_name in params: - - self.add_parameter(p_name, label=f'{name} Label', unit='V', - set_cmd=None, - get_cmd=partial(self._getter, p_name)) - - def _getter(self, name: str) -> ParamRawDataType: - val = self.parameters[name].cache.get(get_if_invalid=False) - self._get_calls[name] += 1 - return val - - def snapshot_base( - self, - update: bool | None = True, - params_to_skip_update: Sequence[str] | None = None, - ) -> dict[Any, Any]: - if params_to_skip_update is None: - params_to_skip_update = self._params_to_skip - snap = super().snapshot_base( - update=update, params_to_skip_update=params_to_skip_update) - return snap - - -class MockField(DummyBase): - - def __init__( - self, - name: str, - vals: Numbers = Numbers(min_value=-1.0, max_value=1.0), - **kwargs: Any, - ): - """Mock instrument for emulating a magnetic field axis - - Args: - name (str): Instrument name - vals (Numbers, optional): Soft limits. Defaults to Numbers(min_value=-1., max_value=1.). - """ - super().__init__(name=name, **kwargs) - self._field = 0.0 - self.add_parameter("field", - parameter_class=Parameter, - initial_value=0.0, - unit='T', - vals=vals, - get_cmd=self.get_field, set_cmd=self.set_field) - self.add_parameter("ramp_rate", - parameter_class=Parameter, - initial_value=0.1, - unit='T/min', - get_cmd=None, set_cmd=None) - self._ramp_start_time: float | None = None - self._wait_time: float | None = None - self._fr = self._field_ramp() - next(self._fr) - - def get_field(self) -> float: - """ - This method is automatically wrapped to - provide a ``get`` method on the parameter instance. - """ - if self._ramp_start_time: - _time_since_start = time.time() - self._ramp_start_time - val = self._fr.send(_time_since_start) - self._field = val - return self._field - - def set_field(self, value: float, block: bool = True) -> None | float: - if self._field == value: - return value - - wait_time = 60. * np.abs(self._field - value) / self.ramp_rate() - self._wait_time = wait_time - self._sign = np.sign(value - self._field) - self._start_field = self._field - self._target_field = value - self._ramp_start_time = time.time() - - if block: - time.sleep(wait_time) - self._field = value - return value - else: - return None - - def _field_ramp_fcn(self, _time: float) -> float: - if self._wait_time is None: - return self._field - elif _time <= 0.0: - return self._start_field - elif _time >= self._wait_time: - return self._target_field - dfield = self.ramp_rate() * _time / 60.0 - return self._start_field + self._sign * dfield - - def _field_ramp(self) -> Generator[float, float, None]: - """ - Yields field for a given point in time - """ - time = 0.0 - while True: - time = yield float(self._field_ramp_fcn(time)) - - -class MockLockin(DummyBase): - def __init__(self, name: str, **kwargs: Any): - super().__init__(name=name, **kwargs) - self.add_parameter("X", - parameter_class=Parameter, - initial_value=1e-3, - unit='V', - get_cmd=None, set_cmd=None) - self.add_parameter("Y", - parameter_class=Parameter, - initial_value=1e-5, - unit='V', - get_cmd=None, set_cmd=None) - self.add_parameter("frequency", - parameter_class=Parameter, - initial_value=125., - unit='Hz', - get_cmd=None, set_cmd=None) - self.add_parameter("amplitude", - parameter_class=Parameter, - initial_value=0., - unit='V', - get_cmd=None, set_cmd=None) - self.add_parameter("phase", - parameter_class=Parameter, - initial_value=0., - unit='deg', - get_cmd=None, set_cmd=None) - self.add_parameter("time_constant", - parameter_class=Parameter, - initial_value=1.e-3, - unit='s', - get_cmd=None, set_cmd=None) - - -class MockDACChannel(InstrumentChannel): - """ - A single dummy channel implementation - """ - - def __init__(self, parent: InstrumentBase, name: str, num: str): - super().__init__(parent, name) - - self._num = num - self.add_parameter('voltage', - parameter_class=Parameter, - initial_value=0., - label=f"Voltage_{name}", - unit='V', - vals=Numbers(-2., 2.), - get_cmd=None, set_cmd=None) - self.add_parameter('dac_output', - parameter_class=Parameter, - initial_value="off", - vals=OnOff(), - get_cmd=None, set_cmd=None) - self.add_parameter('smc', - parameter_class=Parameter, - initial_value="off", - vals=OnOff(), - get_cmd=None, set_cmd=None) - self.add_parameter('bus', - parameter_class=Parameter, - initial_value="off", - vals=OnOff(), - get_cmd=None, set_cmd=None) - self.add_parameter('gnd', - parameter_class=Parameter, - initial_value="off", - vals=OnOff(), - get_cmd=None, set_cmd=None) - - def channel_number(self) -> str: - return self._num - - -class MockDAC(DummyBase): - def __init__(self, name: str = "mdac", num_channels: int = 10, **kwargs: Any): - - """ - Create a dummy instrument that can be used for testing - - Args: - name: name for the instrument - gates: list of names that is used to create parameters for - the instrument - """ - super().__init__(name, **kwargs) - - # make gates - channels = ChannelList(self, "channels", MockDACChannel) - for n in range(num_channels): - num = str(n + 1).zfill(2) - chan_name = f"ch{num}" - channel = MockDACChannel(parent=self, name=chan_name, num=num) - channels.append(channel) - self.add_submodule(chan_name, channel) - self.add_submodule("channels", channels.to_channel_tuple()) - - -class MockCustomChannel(InstrumentChannel): - def __init__( - self, - parent: InstrumentBase, - name: str, - channel: str | InstrumentChannel, - current_valid_range: Sequence[float] | None = None, - ) -> None: - """ - A custom instrument channel emulating an existing channel. - - It adds a parameter not found in the original channel, the - current_valid_range. - Args: - parent: Instrument to which the original channel belongs to, - usually a dac. - name: Name of channel. - channel: The original instrument channel. - current_valid_range: Voltage range the channel is expected to show - interesting features. It's just an example of an additional - parameter a regular instrument channel does not have. - """ - if isinstance(channel, str): - _, channel_name = channel.split(".") - instr_channel = getattr(parent, channel_name) - self._dac_channel = instr_channel - elif isinstance(channel, InstrumentChannel): - self._dac_channel = channel - else: - raise ValueError('Unknown input type for "channel".') - - super().__init__(parent, name) - - if current_valid_range is None: - current_valid_range = [] - super().add_parameter( - name="current_valid_range", - label=f"{name} valid voltage range", - initial_value=current_valid_range, - vals=ValidatorSequence(Numbers(), length=2), - get_cmd=None, - set_cmd=None, - ) - - self.add_parameter( - "voltage", - parameter_class=Parameter, - initial_value=0.0, - label=f"Voltage_{name}", - unit="V", - vals=Numbers(-2.0, 2.0), - get_cmd=None, - set_cmd=None, - ) diff --git a/src/qcodes/tests/parameter/conftest.py b/src/qcodes/tests/parameter/conftest.py index 77268018632..59ceb6d8324 100644 --- a/src/qcodes/tests/parameter/conftest.py +++ b/src/qcodes/tests/parameter/conftest.py @@ -8,8 +8,8 @@ import qcodes.validators as vals from qcodes.instrument import InstrumentBase +from qcodes.instrument_drivers.mock_instruments import DummyChannelInstrument from qcodes.parameters import ParamDataType, Parameter, ParamRawDataType -from qcodes.tests.instrument_mocks import DummyChannelInstrument T = TypeVar("T") diff --git a/src/qcodes/tests/parameter/test_function.py b/src/qcodes/tests/parameter/test_function.py index d4fe39edc8d..882a1c45b78 100644 --- a/src/qcodes/tests/parameter/test_function.py +++ b/src/qcodes/tests/parameter/test_function.py @@ -2,7 +2,7 @@ import pytest -from qcodes.tests.instrument_mocks import DummyChannelInstrument +from qcodes.instrument_drivers.mock_instruments import DummyChannelInstrument @pytest.fixture(name="channel_instr") diff --git a/src/qcodes/tests/parameter/test_instrument_ref_parameter.py b/src/qcodes/tests/parameter/test_instrument_ref_parameter.py index e75d6234315..4f37e7a9fc6 100644 --- a/src/qcodes/tests/parameter/test_instrument_ref_parameter.py +++ b/src/qcodes/tests/parameter/test_instrument_ref_parameter.py @@ -2,8 +2,8 @@ import pytest +from qcodes.instrument_drivers.mock_instruments import DummyInstrument from qcodes.parameters import InstrumentRefParameter -from qcodes.tests.instrument_mocks import DummyInstrument @pytest.fixture(name="instrument_a") diff --git a/src/qcodes/tests/parameter/test_parameter_cache.py b/src/qcodes/tests/parameter/test_parameter_cache.py index f708575874d..918fa2793c9 100644 --- a/src/qcodes/tests/parameter/test_parameter_cache.py +++ b/src/qcodes/tests/parameter/test_parameter_cache.py @@ -7,8 +7,8 @@ import pytest import qcodes.validators as vals +from qcodes.instrument_drivers.mock_instruments import DummyChannelInstrument from qcodes.parameters import Parameter, ParameterBase -from qcodes.tests.instrument_mocks import DummyChannelInstrument from .conftest import NOT_PASSED, BetterGettableParam, SettableParam diff --git a/src/qcodes/tests/parameter/test_parameter_context_manager.py b/src/qcodes/tests/parameter/test_parameter_context_manager.py index 073d27f2a5b..7c876166811 100644 --- a/src/qcodes/tests/parameter/test_parameter_context_manager.py +++ b/src/qcodes/tests/parameter/test_parameter_context_manager.py @@ -4,8 +4,8 @@ import pytest import qcodes.validators as vals +from qcodes.instrument_drivers.mock_instruments import DummyInstrument from qcodes.parameters import Parameter, ParamRawDataType -from qcodes.tests.instrument_mocks import DummyInstrument class DummyTrackingInstrument(DummyInstrument): diff --git a/src/qcodes/tests/parameter/test_parameter_registration.py b/src/qcodes/tests/parameter/test_parameter_registration.py index 94c4bc08f7f..7f08242a004 100644 --- a/src/qcodes/tests/parameter/test_parameter_registration.py +++ b/src/qcodes/tests/parameter/test_parameter_registration.py @@ -4,8 +4,8 @@ import pytest from qcodes.instrument import InstrumentBase +from qcodes.instrument_drivers.mock_instruments import DummyAttrInstrument from qcodes.parameters import Parameter -from qcodes.tests.instrument_mocks import DummyAttrInstrument from qcodes.utils import QCoDeSDeprecationWarning diff --git a/src/qcodes/tests/parameter/test_scaled_parameter.py b/src/qcodes/tests/parameter/test_scaled_parameter.py index 108223f629f..72815432a62 100644 --- a/src/qcodes/tests/parameter/test_scaled_parameter.py +++ b/src/qcodes/tests/parameter/test_scaled_parameter.py @@ -2,8 +2,8 @@ import pytest +from qcodes.instrument_drivers.mock_instruments import DummyInstrument from qcodes.parameters import ManualParameter, ScaledParameter -from qcodes.tests.instrument_mocks import DummyInstrument @pytest.fixture(name="instrument") diff --git a/src/qcodes/tests/parameter/test_val_mapping.py b/src/qcodes/tests/parameter/test_val_mapping.py index 6a11d14c970..ab43f155df1 100644 --- a/src/qcodes/tests/parameter/test_val_mapping.py +++ b/src/qcodes/tests/parameter/test_val_mapping.py @@ -3,8 +3,8 @@ import pytest import qcodes.validators as vals +from qcodes.instrument_drivers.mock_instruments import DummyInstrument from qcodes.parameters import Parameter, create_on_off_val_mapping -from qcodes.tests.instrument_mocks import DummyInstrument from .conftest import ParameterMemory diff --git a/src/qcodes/tests/test_channels.py b/src/qcodes/tests/test_channels.py index 8ae5b0d8843..f6b629d5d35 100644 --- a/src/qcodes/tests/test_channels.py +++ b/src/qcodes/tests/test_channels.py @@ -9,7 +9,10 @@ from pytest import LogCaptureFixture from qcodes.instrument import ChannelList, ChannelTuple, Instrument, InstrumentChannel -from qcodes.tests.instrument_mocks import DummyChannel, DummyChannelInstrument +from qcodes.instrument_drivers.mock_instruments import ( + DummyChannel, + DummyChannelInstrument, +) @pytest.fixture(scope='function', name='dci') @@ -72,8 +75,9 @@ def test_channels_call_function(dci, caplog: LogCaptureFixture) -> None: Test that dci.channels.some_function() calls some_function on each of the channels """ - with caplog.at_level(logging.DEBUG, - logger='qcodes.tests.instrument_mocks'): + with caplog.at_level( + logging.DEBUG, logger="qcodes.instrument_drivers.mock_instruments" + ): caplog.clear() dci.channels.log_my_name() mssgs = [rec.message for rec in caplog.records] diff --git a/src/qcodes/tests/test_instrument.py b/src/qcodes/tests/test_instrument.py index d3c88a888de..f326110ef4a 100644 --- a/src/qcodes/tests/test_instrument.py +++ b/src/qcodes/tests/test_instrument.py @@ -15,16 +15,15 @@ from pytest import FixtureRequest from qcodes.instrument import Instrument, InstrumentBase, find_or_create_instrument -from qcodes.metadatable import Metadatable -from qcodes.parameters import Function, Parameter - -from .instrument_mocks import ( +from qcodes.instrument_drivers.mock_instruments import ( DummyChannelInstrument, DummyFailingInstrument, DummyInstrument, MockMetaParabola, MockParabola, ) +from qcodes.metadatable import Metadatable +from qcodes.parameters import Function, Parameter @pytest.fixture(name="testdummy", scope="function") @@ -342,11 +341,13 @@ class GammyInstrument(Instrument): some_other_attr = 25 # Find an instrument with the same name but of different class - error_msg = ("Instrument instr is but " - "" - ".GammyInstrument'> was requested") + error_msg = ( + "Instrument instr is but " + "" + ".GammyInstrument'> was requested" + ) with pytest.raises(TypeError, match=error_msg): _ = find_or_create_instrument( diff --git a/src/qcodes/tests/test_monitor.py b/src/qcodes/tests/test_monitor.py index 8838e8f7210..2d1abd06724 100644 --- a/src/qcodes/tests/test_monitor.py +++ b/src/qcodes/tests/test_monitor.py @@ -11,9 +11,12 @@ import websockets from pytest import FixtureRequest +from qcodes.instrument_drivers.mock_instruments import ( + DummyChannelInstrument, + DummyInstrument, +) from qcodes.monitor import monitor from qcodes.parameters import Parameter -from qcodes.tests.instrument_mocks import DummyChannelInstrument, DummyInstrument monitor.WEBSOCKET_PORT = random.randint(50000, 60000) diff --git a/src/qcodes/tests/test_snapshot.py b/src/qcodes/tests/test_snapshot.py index 9a39e06ed2e..91c9cd908ab 100644 --- a/src/qcodes/tests/test_snapshot.py +++ b/src/qcodes/tests/test_snapshot.py @@ -5,7 +5,7 @@ import pytest from pytest import FixtureRequest -from qcodes.tests.instrument_mocks import SnapShotTestInstrument +from qcodes.instrument_drivers.mock_instruments import SnapShotTestInstrument @pytest.mark.parametrize( diff --git a/src/qcodes/tests/test_station.py b/src/qcodes/tests/test_station.py index b87218650be..d77aba48564 100644 --- a/src/qcodes/tests/test_station.py +++ b/src/qcodes/tests/test_station.py @@ -13,10 +13,13 @@ import qcodes from qcodes import validators from qcodes.instrument import Instrument +from qcodes.instrument_drivers.mock_instruments import ( + DummyChannelInstrument, + DummyInstrument, +) from qcodes.monitor import Monitor from qcodes.parameters import DelegateParameter, Parameter from qcodes.station import SCHEMA_PATH, Station, ValidationWarning, update_config_schema -from qcodes.tests.instrument_mocks import DummyChannelInstrument, DummyInstrument from qcodes.utils import NumpyJSONEncoder, QCoDeSDeprecationWarning, get_qcodes_path from qcodes.utils.deprecate import deprecation_message @@ -282,7 +285,7 @@ def _make_example_station_config(): init: visalib: '{sims_path}lakeshore_model336.yaml@sim' mock_dac: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument enable_forced_reconnect: true init: gates: {{"ch1", "ch2"}} @@ -290,7 +293,7 @@ def _make_example_station_config(): ch1: monitor: true mock_dac2: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument """ with config_file_context(test_config) as filename: yield filename @@ -410,18 +413,21 @@ def simple_mock_station(): """ instruments: mock: - type: qcodes.tests.instrument_mocks.DummyInstrument - """) + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument + """ + ) def test_simple_mock_config(simple_mock_station) -> None: st = simple_mock_station assert station_config_has_been_loaded(st) - assert hasattr(st, 'load_mock') - mock_snapshot = st.snapshot()['config']['instruments']['mock'] - assert (mock_snapshot['type'] == - "qcodes.tests.instrument_mocks.DummyInstrument") - assert 'mock' in st.config['instruments'] + assert hasattr(st, "load_mock") + mock_snapshot = st.snapshot()["config"]["instruments"]["mock"] + assert ( + mock_snapshot["type"] + == "qcodes.instrument_drivers.mock_instruments.DummyInstrument" + ) + assert "mock" in st.config["instruments"] def test_simple_mock_load_mock(simple_mock_station) -> None: @@ -445,7 +451,7 @@ def get_instrument_config(enable_forced_reconnect: Optional[bool]) -> str: return f""" instruments: mock: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument {f'enable_forced_reconnect: {enable_forced_reconnect}' if enable_forced_reconnect is not None else ''} init: @@ -489,16 +495,18 @@ def assert_on_reconnect(*, use_user_cfg: Optional[bool], def test_revive_instance() -> None: - st = station_from_config_str(""" + st = station_from_config_str( + """ instruments: mock: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument enable_forced_reconnect: true init: gates: {"ch1"} - """) - mock = st.load_instrument('mock') - mock2 = st.load_instrument('mock') + """ + ) + mock = st.load_instrument("mock") + mock2 = st.load_instrument("mock") assert mock is not mock2 assert mock is not st.mock assert mock2 is st.mock @@ -513,7 +521,7 @@ def test_init_parameters() -> None: """ instruments: mock: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument enable_forced_reconnect: true init: gates: {"ch1", "ch2"} @@ -556,10 +564,11 @@ def test_name_specified_in_init_in_yaml_is_used() -> None: """ instruments: mock: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument init: name: dummy - """) + """ + ) mock = st.load_instrument('mock') assert isinstance(mock, DummyInstrument) @@ -588,10 +597,11 @@ def test_able_to_load_instrument_with_name_argument_not_being_the_first() -> Non def test_setup_alias_parameters() -> None: - st = station_from_config_str(""" + st = station_from_config_str( + """ instruments: mock: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument enable_forced_reconnect: true init: gates: {"ch1"} @@ -605,9 +615,10 @@ def test_setup_alias_parameters() -> None: alias: gate_a initial_value: 9 - """) - mock = st.load_instrument('mock') - p = getattr(mock, 'gate_a') + """ + ) + mock = st.load_instrument("mock") + p = getattr(mock, "gate_a") assert isinstance(p, Parameter) assert p.unit == 'mV' assert p.label == 'main gate' @@ -625,10 +636,11 @@ def test_setup_alias_parameters() -> None: def test_setup_delegate_parameters() -> None: - st = station_from_config_str(""" + st = station_from_config_str( + """ instruments: mock: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument enable_forced_reconnect: true init: gates: {"ch1"} @@ -649,9 +661,10 @@ def test_setup_delegate_parameters() -> None: limits: [-6.0 , 6.] initial_value: 2 - """) - mock = st.load_instrument('mock') - p = getattr(mock, 'gate_a') + """ + ) + mock = st.load_instrument("mock") + p = getattr(mock, "gate_a") assert isinstance(p, DelegateParameter) assert p.unit == 'mV' assert p.label == 'main gate' @@ -677,10 +690,11 @@ def test_setup_delegate_parameters() -> None: def test_channel_instrument() -> None: """Test that parameters from instrument's submodule also get configured correctly""" - st = station_from_config_str(""" + st = station_from_config_str( + """ instruments: mock: - type: qcodes.tests.instrument_mocks.DummyChannelInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyChannelInstrument enable_forced_reconnect: true parameters: A.temperature: @@ -690,23 +704,26 @@ def test_channel_instrument() -> None: source: A.temperature A.voltage: source: A.temperature - """) - mock = st.load_instrument('mock') - assert mock.A.temperature.unit == 'mK' - assert mock.T.unit == 'mK' + """ + ) + mock = st.load_instrument("mock") + assert mock.A.temperature.unit == "mK" + assert mock.T.unit == "mK" assert mock.A.voltage.source is mock.A.temperature def test_setting_channel_parameter() -> None: - st = station_from_config_str(""" + st = station_from_config_str( + """ instruments: mock: - type: qcodes.tests.instrument_mocks.DummyChannelInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyChannelInstrument parameters: channels.temperature: initial_value: 10 - """) - mock = st.load_instrument('mock') + """ + ) + mock = st.load_instrument("mock") assert mock.channels.temperature() == (10,) * 6 @@ -742,12 +759,14 @@ def test_monitor_not_loaded_if_specified(example_station_config) -> None: def test_deprecated_driver_keyword() -> None: - st = station_from_config_str(""" + st = station_from_config_str( + """ instruments: mock: - driver: qcodes.tests.instrument_mocks + driver: qcodes.instrument_drivers.mock_instruments type: DummyChannelInstrument - """) + """ + ) message = deprecation_message( 'use of the "driver"-keyword in the station configuration file', alternative='the "type"-keyword instead, prepending the driver value to it', @@ -757,16 +776,18 @@ def test_deprecated_driver_keyword() -> None: def test_deprecated_limits_keyword_as_string() -> None: - st = station_from_config_str(""" + st = station_from_config_str( + """ instruments: mock: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument init: gates: {"ch1"} parameters: ch1: limits: -10, 10 - """) + """ + ) message = deprecation_message( "use of a comma separated string for the limits keyword", alternative=r'an array like "\[lower_lim, upper_lim\]"', @@ -777,13 +798,15 @@ def test_deprecated_limits_keyword_as_string() -> None: def test_config_validation_failure() -> None: with pytest.raises(ValidationWarning): - station_from_config_str(""" + station_from_config_str( + """ instruments: mock: - driver: qcodes.tests.instrument_mocks.DummyInstrument + driver: qcodes.instrument_drivers.mock_instruments.DummyInstrument invalid_keyword: more_errors: 42 - """) + """ + ) def test_config_validation_failure_on_file() -> None: @@ -791,7 +814,7 @@ def test_config_validation_failure_on_file() -> None: test_config = """ instruments: mock: - driver: qcodes.tests.instrument_mocks.DummyInstrument + driver: qcodes.instrument_drivers.mock_instruments.DummyInstrument invalid_keyword: more_errors: 42 """ @@ -885,7 +908,7 @@ def test_station_config_created_with_multiple_config_files() -> None: test_config1 = """ instruments: mock_dac1: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument enable_forced_reconnect: true init: gates: {{"ch1", "ch2"}} @@ -896,7 +919,7 @@ def test_station_config_created_with_multiple_config_files() -> None: test_config2 = """ instruments: mock_dac2: - type: qcodes.tests.instrument_mocks.DummyInstrument + type: qcodes.instrument_drivers.mock_instruments.DummyInstrument """ with config_files_context( test_config1, test_config2 diff --git a/src/qcodes/tests/test_threading.py b/src/qcodes/tests/test_threading.py index 694996b17d9..337bedd47bf 100644 --- a/src/qcodes/tests/test_threading.py +++ b/src/qcodes/tests/test_threading.py @@ -9,10 +9,9 @@ import pytest from qcodes.dataset.threading import ThreadPoolParamsCaller, call_params_threaded +from qcodes.instrument_drivers.mock_instruments import DummyInstrument from qcodes.parameters import Parameter, ParamRawDataType -from .instrument_mocks import DummyInstrument - class ParameterWithThreadKnowledge(Parameter): def __init__(self, *args: Any, **kwargs: Any) -> None: