Source code for qcodes.instrument_drivers.Keysight.keysight_34980a

import logging
import re
import warnings
from functools import wraps
from typing import TYPE_CHECKING, TypeVar

from typing_extensions import ParamSpec

from qcodes import validators as vals
from qcodes.instrument import VisaInstrument, VisaInstrumentKWArgs

from .keysight_34934a import Keysight34934A
from .keysight_34980a_submodules import Keysight34980ASwitchMatrixSubModule

    from import Callable
    from typing import Concatenate

    from typing_extensions import Unpack

KEYSIGHT_MODELS = {'34934A': Keysight34934A}

S = TypeVar("S", bound="Keysight34980A")
P = ParamSpec("P")
T = TypeVar('T')

def post_execution_status_poll(
    func: "Callable[Concatenate[S, P], T]",
) -> "Callable[Concatenate[S, P], T]":
    Generates a decorator that clears the instrument's status registers
    before executing the actual call and reads the status register after the
    function call to determine whether an error occurs.

        func: function to wrap
    def wrapper(self: S, *args: P.args, **kwargs: P.kwargs) -> T:
        retval = func(self, *args, **kwargs)

        stb = self.get_status()
        if stb:
            warnings.warn(f"Instrument status byte indicates an error occurred "
                          f"(value of STB was: {stb})! Use `get_error` method "
                          f"to poll error message.",
        return retval

    return wrapper

[docs] class Keysight34980A(VisaInstrument): """ QCodes driver for 34980A switch/measure unit """ default_terminator = "\n" def __init__( self, name: str, address: str, **kwargs: "Unpack[VisaInstrumentKWArgs]" ): """ Create an instance of the instrument. Args: name: Name of the instrument instance address: Visa-resolvable instrument address. **kwargs: kwargs are forwarded to base class. """ super().__init__(name, address, **kwargs) self._total_slot = 8 self._system_slots_info_dict: dict[int, dict[str, str]] | None = None self.module = dict.fromkeys(self.system_slots_info.keys()) self.scan_slots() self.connect_message()
[docs] def get_status(self) -> int: """ Queries status register Returns: 0 if there is no error """ msg = super().ask('*ESR?') nums = list(map(int, re.findall(r'\d+', msg))) return nums[0]
[docs] def get_error(self) -> str: """ Queries error queue Returns: error message, or '+0,"No error"' if there is no error """ msg = super().ask(':SYST:ERR?') return msg
[docs] def clear_status(self) -> None: """ Clears status register and error queue of the instrument. """ super().write('*CLS')
[docs] def reset(self) -> None: """ Performs an instrument reset. Does not reset error queue! """ super().write('*RST')
[docs] @post_execution_status_poll def ask(self, cmd: str) -> str: return super().ask(cmd)
[docs] @post_execution_status_poll def write(self, cmd: str) -> None: return super().write(cmd)
[docs] def scan_slots(self) -> None: """ Scan the occupied slots and make an object for each switch matrix module installed """ for slot in self.system_slots_info.keys(): model_string = self.system_slots_info[slot]['model'] for model in KEYSIGHT_MODELS: if model in model_string: sub_module_name = f'slot_{slot}_{model}' sub_module = KEYSIGHT_MODELS[model](self, sub_module_name, slot) self.module[slot] = sub_module self.add_submodule(sub_module_name, sub_module) break if self.module[slot] is None: sub_module_name = f"slot_{slot}_{model_string}_no_driver" sub_module_no_driver = Keysight34980ASwitchMatrixSubModule( self, sub_module_name, slot ) self.module[slot] = sub_module_no_driver self.add_submodule(sub_module_name, sub_module_no_driver) logging.warning(f'can not find driver for {model_string}' f'in slot {slot}')
@property def system_slots_info(self) -> dict[int, dict[str, str]]: if self._system_slots_info_dict is None: self._system_slots_info_dict = self._system_slots_info() return self._system_slots_info_dict def _system_slots_info(self) -> dict[int, dict[str, str]]: """ the command SYST:CTYP? returns the following: Agilent Technologies,<Model Number>,<Serial Number>,<Firmware Rev> where <Model Number> is '0' if there is no module connected to the given slot Returns: a dictionary, with slot numbers as the keys, and vendor/model/ serial/firmware dictionaries as the values """ slots_dict = {} keys = ['vendor', 'model', 'serial', 'firmware'] for i in range(1, self._total_slot+1): identity = self.ask(f'SYST:CTYP? {i}').strip('"').split(',') if identity[1] != '0': slots_dict[i] = dict(zip(keys, identity)) return slots_dict
[docs] def disconnect_all(self, slot: int | None = None) -> None: """ to open/disconnect all connections on select module Args: slot: slot number, between 1 and 8 (self._total_slot), default value is None, which means all slots """ cmd = 'ROUT:OPEN:ALL' if slot is None: self.write(cmd) else: vals.Ints(min_value=1, max_value=self._total_slot).validate(slot) self.write(f'ROUT:OPEN:ALL {slot}')