Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor drivers Minicircuits - R&S #6160

Merged
merged 19 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/changes/newsfragments/6160.improved_driver
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
The Minicircuits, Oxford, QDev, QuantumDesign, Rigol and Rohde & Schwarz drivers shipping with QCoDeS
have been updated to ensure all Parameters are set as static
attributes that are documented and can be type checked. The docs for the same drivers have been
updated to not document inherited members. This makes the documentation significantly more readable
as it focuses on specific members for a given instrument. The documentation now also links superclasses.
Please consult these for inherited members.
1 change: 1 addition & 0 deletions docs/drivers_api/Minicircuits.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ MiniCircuits Drivers

.. automodule:: qcodes.instrument_drivers.Minicircuits
:autosummary:
:no-inherited-members:
1 change: 1 addition & 0 deletions docs/drivers_api/Oxford.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Oxford Instruments Drivers

.. automodule:: qcodes.instrument_drivers.oxford
:autosummary:
:no-inherited-members:
1 change: 1 addition & 0 deletions docs/drivers_api/QDev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ QDev Drivers

.. automodule:: qcodes.instrument_drivers.QDev
:autosummary:
:no-inherited-members:
1 change: 1 addition & 0 deletions docs/drivers_api/QuantumDesign.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Quantum Design Drivers

.. automodule:: qcodes.instrument_drivers.QuantumDesign
:autosummary:
:no-inherited-members:
1 change: 1 addition & 0 deletions docs/drivers_api/Rigol.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Rigol Drivers

.. automodule:: qcodes.instrument_drivers.rigol
:autosummary:
:no-inherited-members:
1 change: 1 addition & 0 deletions docs/drivers_api/RohdeSchwarz.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Rohde & Schwarz Drivers

.. automodule:: qcodes.instrument_drivers.rohde_schwarz
:autosummary:
:no-inherited-members:
36 changes: 32 additions & 4 deletions src/qcodes/instrument_drivers/Minicircuits/Base_SPDT.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@
import warnings
from typing import TYPE_CHECKING, Any

from typing_extensions import deprecated

from qcodes.instrument import (
ChannelList,
Instrument,
InstrumentBaseKWArgs,
InstrumentChannel,
)
from qcodes.utils import QCoDeSDeprecationWarning
from qcodes.validators import Ints

if TYPE_CHECKING:
from typing_extensions import Unpack

from qcodes.parameters import Parameter

log = logging.getLogger(__name__)


class SwitchChannelBase(InstrumentChannel):
class MiniCircuitsSPDTSwitchChannelBase(InstrumentChannel):
def __init__(
self,
parent: Instrument,
Expand All @@ -28,6 +33,9 @@
**kwargs: Unpack[InstrumentBaseKWArgs],
):
"""
Base class for MiniCircuits SPDT Switch channels.
Should not be instantiated directly.

Args:
parent: The instrument the channel is a part of
name: the name of the channel
Expand All @@ -40,12 +48,13 @@
_chanlist = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
self.channel_number = _chanlist.index(channel_letter)

self.add_parameter(
self.switch: Parameter = self.add_parameter(

Check warning on line 51 in src/qcodes/instrument_drivers/Minicircuits/Base_SPDT.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/Base_SPDT.py#L51

Added line #L51 was not covered by tests
'switch',
label=f'switch {self.channel_letter}',
set_cmd=self._set_switch,
get_cmd=self._get_switch,
vals=Ints(1, 2))
"""Parameter switch"""

Check warning on line 57 in src/qcodes/instrument_drivers/Minicircuits/Base_SPDT.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/Base_SPDT.py#L57

Added line #L57 was not covered by tests

def __call__(self, *args: int) -> int | None:
if len(args) == 1:
Expand All @@ -63,10 +72,21 @@
def _get_switch(self) -> int:
raise NotImplementedError()

@deprecated(
"Deprecated alias, use MiniCircuitsSPDTSwitchChannelBase.",
category=QCoDeSDeprecationWarning,
)
class SwitchChannelBase(MiniCircuitsSPDTSwitchChannelBase):
pass


class SPDT_Base(Instrument):
class MiniCircuitsSPDTBase(Instrument):
"""
Base class for MiniCircuits SPDT Switch instruments.
Should not be instantiated directly.
"""

CHANNEL_CLASS: type[SwitchChannelBase]
CHANNEL_CLASS: type[MiniCircuitsSPDTSwitchChannelBase]

def add_channels(self) -> None:
channels = ChannelList(
Expand Down Expand Up @@ -136,3 +156,11 @@
f" the model '{model}', it might not be supported"
)
return int(channels)


@deprecated(
"Deprecated alias, use MiniCircuitsSPDTBase.",
category=QCoDeSDeprecationWarning,
)
class SPDT_Base(MiniCircuitsSPDTBase):
pass
124 changes: 122 additions & 2 deletions src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import time
from typing import TYPE_CHECKING, Optional

from typing_extensions import deprecated

from qcodes.utils import QCoDeSDeprecationWarning

try:
from pywinusb import hid # pyright: ignore[reportMissingModuleSource]

Expand All @@ -23,6 +27,10 @@
from qcodes.instrument import InstrumentBaseKWArgs


@deprecated(
"USBHIDMixin is deprecated. This is unused in QCoDeS",
category=QCoDeSDeprecationWarning,
)
class USBHIDMixin(Instrument):

# The following class attributes should be set by subclasses
Expand Down Expand Up @@ -164,7 +172,22 @@
return [dev.instance_id for dev in devs]


class MiniCircuitsHIDMixin(USBHIDMixin):
class MiniCircuitsHIDMixin(Instrument):
# The following class attributes should be set by subclasses
vendor_id = 0x0000
product_id = 0x0000

@staticmethod
def _check_hid_import() -> None:
if os.name != "nt":
raise ImportError("This driver only works on Windows.")

Check warning on line 183 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L182-L183

Added lines #L182 - L183 were not covered by tests

if imported_hid is False:
raise ImportError(

Check warning on line 186 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L185-L186

Added lines #L185 - L186 were not covered by tests
"pywinusb is not installed. Please install it by typing "
"'pip install pywinusb' in a qcodes environment terminal"
)

def __init__(
self,
name: str,
Expand All @@ -188,13 +211,110 @@
timeout: Specify a timeout for this instrument in seconds
**kwargs: Forwarded to base class.
"""
self._check_hid_import()

Check warning on line 214 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L214

Added line #L214 was not covered by tests

# USB interrupt code for sending SCPI commands
self._sending_scpi_cmds_code = 1
self._usb_endpoint = 0
self._end_of_message = b"\x00"
self.packet_size = 64

super().__init__(name, instance_id, timeout, **kwargs)
devs = hid.HidDeviceFilter( # pyright: ignore[reportPossiblyUnboundVariable]

Check warning on line 222 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L222

Added line #L222 was not covered by tests
product_id=self.product_id,
vendor_id=self.vendor_id,
instance_id=instance_id,
).get_devices()

if len(devs) == 0:
raise RuntimeError("No instruments found!")
elif len(devs) > 1:
raise RuntimeError(

Check warning on line 231 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L228-L231

Added lines #L228 - L231 were not covered by tests
"Multiple HID devices detected! Please supply a instance id"
)

self._device = devs[0]
self._device.open()

Check warning on line 236 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L235-L236

Added lines #L235 - L236 were not covered by tests

self._data_buffer: Optional[bytes] = None
self._device.set_raw_data_handler(self._handler)

Check warning on line 239 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L238-L239

Added lines #L238 - L239 were not covered by tests

self._timeout = timeout
self._tries_per_second = 5

Check warning on line 242 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L241-L242

Added lines #L241 - L242 were not covered by tests

super().__init__(name, **kwargs)

Check warning on line 244 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L244

Added line #L244 was not covered by tests

def _handler(self, data: bytes) -> None:
self._data_buffer = data

Check warning on line 247 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L247

Added line #L247 was not covered by tests

def _get_data_buffer(self) -> Optional[bytes]:
data = self._data_buffer
self._data_buffer = None
return data

Check warning on line 252 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L250-L252

Added lines #L250 - L252 were not covered by tests

def write_raw(self, cmd: str) -> None:
"""
Send a string command to the human interface device

The given command is processed by `_pack_string` method to return a
byte sequence that is going to be actually sent to the device.
Subclasses must implement `_pack_string` method.

Args:
cmd: a command to send in a form of a string
"""
data = self._pack_string(cmd)

Check warning on line 265 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L265

Added line #L265 was not covered by tests

result = self._device.send_output_report(data)
if not result:
raise RuntimeError(f"Communication with device failed for command {cmd}")

Check warning on line 269 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L267-L269

Added lines #L267 - L269 were not covered by tests

def ask_raw(self, cmd: str) -> str:
"""
Send a string command to the human interface device and wait for a reply

The given command is processed by `_pack_string` method to return a
byte sequence that is going to be actually sent to the device.
Subclasses must implement `_pack_string` method.

The byte sequence of the reply is processed by `_unpack_string`
method, and the resulting string is returned. Subclasses must
implement `_unpack_string` method.

Args:
cmd: a command to send in a form of a string
"""
self.write_raw(cmd)

Check warning on line 286 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L286

Added line #L286 was not covered by tests

number_of_tries = int(self._tries_per_second * self._timeout)

Check warning on line 288 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L288

Added line #L288 was not covered by tests

response = None
for _ in range(number_of_tries):
time.sleep(1 / self._tries_per_second)
response = self._get_data_buffer()
if response is not None:
break

Check warning on line 295 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L290-L295

Added lines #L290 - L295 were not covered by tests

if response is None:
raise TimeoutError(f"Timed out for command {cmd}")

Check warning on line 298 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L297-L298

Added lines #L297 - L298 were not covered by tests

return self._unpack_string(response)

Check warning on line 300 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L300

Added line #L300 was not covered by tests

def close(self) -> None:
self._device.close()

Check warning on line 303 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L303

Added line #L303 was not covered by tests

@classmethod
def enumerate_devices(cls) -> list[str]:
"""
This method returns the 'instance_id's of all connected devices for
with the given product and vendor IDs.
"""
cls._check_hid_import()

Check warning on line 311 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L311

Added line #L311 was not covered by tests

devs = hid.HidDeviceFilter( # pyright: ignore[reportPossiblyUnboundVariable]

Check warning on line 313 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L313

Added line #L313 was not covered by tests
porduct_id=cls.product_id, vendor_id=cls.vendor_id
).get_devices()

return [dev.instance_id for dev in devs]

Check warning on line 317 in src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/USBHIDMixin.py#L317

Added line #L317 was not covered by tests

def _pack_string(self, cmd: str) -> bytes:
"""
Expand Down
11 changes: 10 additions & 1 deletion src/qcodes/instrument_drivers/Minicircuits/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
from ._minicircuits_rc_sp4t import MiniCircuitsRCSP4T, MiniCircuitsRCSP4TChannel
from ._minicircuits_rc_spdt import MiniCircuitsRCSPDT, MiniCircuitsRCSPDTChannel
from ._minicircuits_rudat_13g_90 import MiniCircuitsRudat13G90Usb
from ._minicircuits_rudat_13g_90 import (
MiniCircuitsRudat13G90Base,
MiniCircuitsRudat13G90Usb,
)
from ._minicircuits_usb_spdt import (
MiniCircuitsUsbSPDT,
MiniCircuitsUsbSPDTSwitchChannel,
)
from .Base_SPDT import MiniCircuitsSPDTBase, MiniCircuitsSPDTSwitchChannelBase
from .USBHIDMixin import MiniCircuitsHIDMixin

__all__ = [
"MiniCircuitsRCSP4T",
"MiniCircuitsRCSP4TChannel",
"MiniCircuitsRCSPDT",
"MiniCircuitsRCSPDTChannel",
"MiniCircuitsRudat13G90Usb",
"MiniCircuitsRudat13G90Base",
"MiniCircuitsHIDMixin",
"MiniCircuitsUsbSPDT",
"MiniCircuitsSPDTBase",
"MiniCircuitsUsbSPDTSwitchChannel",
"MiniCircuitsSPDTSwitchChannelBase",
]
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
if TYPE_CHECKING:
from typing_extensions import Unpack

from qcodes.parameters import Parameter


class MiniCircuitsRCSP4TChannel(InstrumentChannel):
def __init__(
Expand All @@ -34,13 +36,14 @@
chanlist = ["a", "b"]
self.channel_number = chanlist.index(channel_letter)

self.add_parameter(
self.switch: Parameter = self.add_parameter(

Check warning on line 39 in src/qcodes/instrument_drivers/Minicircuits/_minicircuits_rc_sp4t.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/_minicircuits_rc_sp4t.py#L39

Added line #L39 was not covered by tests
"switch",
label="switch",
set_cmd=self._set_switch,
get_cmd=self._get_switch,
vals=vals.Ints(0, 4),
)
"""Parameter switch"""

Check warning on line 46 in src/qcodes/instrument_drivers/Minicircuits/_minicircuits_rc_sp4t.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/_minicircuits_rc_sp4t.py#L46

Added line #L46 was not covered by tests

def _set_switch(self, switch: int) -> None:
if len(self._parent.channels) > 1:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
if TYPE_CHECKING:
from typing_extensions import Unpack

from qcodes.parameters import Parameter


class MiniCircuitsRCSPDTChannel(InstrumentChannel):
def __init__(
Expand All @@ -33,13 +35,14 @@
_chanlist = ["a", "b", "c", "d", "e", "f", "g", "h"]
self.channel_number = _chanlist.index(channel_letter)

self.add_parameter(
self.switch: Parameter = self.add_parameter(

Check warning on line 38 in src/qcodes/instrument_drivers/Minicircuits/_minicircuits_rc_spdt.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/_minicircuits_rc_spdt.py#L38

Added line #L38 was not covered by tests
"switch",
label="switch",
set_cmd=self._set_switch,
get_cmd=self._get_switch,
vals=vals.Ints(1, 2),
)
"""Parameter switch"""

Check warning on line 45 in src/qcodes/instrument_drivers/Minicircuits/_minicircuits_rc_spdt.py

View check run for this annotation

Codecov / codecov/patch

src/qcodes/instrument_drivers/Minicircuits/_minicircuits_rc_spdt.py#L45

Added line #L45 was not covered by tests

def _set_switch(self, switch: int) -> None:
self.write(f"SET{self.channel_letter}={switch-1}")
Expand Down
Loading
Loading