From cb2c9424e95dd0ddb22e4921b117c93c5b007de1 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 23 May 2024 20:37:54 +0200 Subject: [PATCH 01/10] Don't document inherited members for Keithley --- docs/drivers_api/Keithley.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/drivers_api/Keithley.rst b/docs/drivers_api/Keithley.rst index e7b566739d8..0c84e7bc449 100644 --- a/docs/drivers_api/Keithley.rst +++ b/docs/drivers_api/Keithley.rst @@ -5,3 +5,4 @@ Keithley Drivers .. automodule:: qcodes.instrument_drivers.Keithley :autosummary: + :no-inherited-members: From f454f3709366751152caa8753e00b6afd6a8a48c Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 23 May 2024 20:39:44 +0200 Subject: [PATCH 02/10] Add Keithley baseclass to public api --- src/qcodes/instrument_drivers/Keithley/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/qcodes/instrument_drivers/Keithley/__init__.py b/src/qcodes/instrument_drivers/Keithley/__init__.py index db239ebfacb..b41bf9e9cb1 100644 --- a/src/qcodes/instrument_drivers/Keithley/__init__.py +++ b/src/qcodes/instrument_drivers/Keithley/__init__.py @@ -1,6 +1,6 @@ from typing import Union -from ._Keithley_2600 import Keithley2600MeasurementStatus +from ._Keithley_2600 import Keithley2600, Keithley2600MeasurementStatus from .Keithley_2000 import Keithley2000 from .Keithley_2400 import Keithley2400 from .Keithley_2450 import ( @@ -50,7 +50,7 @@ Keithley2636B, ] """ -All Keithley 26xx SMUs supported by QCoDeS. +Type alias for all Keithley 26xx SMUs supported by QCoDeS. """ __all__ = [ @@ -61,6 +61,7 @@ "Keithley2450Sense", "Keithley2450Source", "Keithley2600MeasurementStatus", + "Keithley2600", "Keithley26xx", "Keithley2601B", "Keithley2602A", From 8fafb77853692e7795e7c9c71f7d14eb48d1b923 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 23 May 2024 20:40:11 +0200 Subject: [PATCH 03/10] Document that base class should not be instantiated --- src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py b/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py index b5785bc6e5a..81ab1d088f5 100644 --- a/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py +++ b/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py @@ -786,9 +786,9 @@ def _set_measurerange_i(self, val: float) -> None: class Keithley2600(VisaInstrument): """ - This is the qcodes driver for the Keithley 2600 Source-Meter series, - tested with Keithley 2614B - + This is the base class for all qcodes driver for the Keithley 2600 Source-Meter series. + This class should not be instantiated directly. Rather one of the subclasses for a + specific instrument should be used. """ default_terminator = "\n" From bf61711c095f2068effe463c7fa213221536af27 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 23 May 2024 20:43:28 +0200 Subject: [PATCH 04/10] Refactor Keithley driver --- .../Keithley/Keithley_2000.py | 49 +++++--- .../Keithley/Keithley_2400.py | 38 ++++-- .../Keithley/Keithley_2450.py | 92 +++++++++----- .../Keithley/Keithley_3706A.py | 28 ++++- .../Keithley/Keithley_6500.py | 38 ++++-- .../Keithley/Keithley_7510.py | 117 ++++++++++++------ .../Keithley/Keithley_s46.py | 3 +- .../Keithley/_Keithley_2600.py | 74 +++++++---- 8 files changed, 302 insertions(+), 137 deletions(-) diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py index 5c09c3c07fb..be0fd03fcd2 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py @@ -7,6 +7,8 @@ if TYPE_CHECKING: from typing_extensions import Unpack + from qcodes.parameters import Parameter + def _parse_output_string(s: str) -> str: """Parses and cleans string outputs of the Keithley""" @@ -66,67 +68,75 @@ def __init__( "frequency": '"FREQ"', } - self.add_parameter( + self.mode: Parameter = self.add_parameter( "mode", get_cmd="SENS:FUNC?", set_cmd="SENS:FUNC {}", val_mapping=self._mode_map, ) + """Parameter mode""" # Mode specific parameters - self.add_parameter( + self.nplc: Parameter = self.add_parameter( "nplc", get_cmd=partial(self._get_mode_param, "NPLC", float), set_cmd=partial(self._set_mode_param, "NPLC"), vals=Numbers(min_value=0.01, max_value=10), ) + """Parameter nplc""" # TODO: validator, this one is more difficult since different modes # require different validation ranges - self.add_parameter( + self.range: Parameter = self.add_parameter( "range", get_cmd=partial(self._get_mode_param, "RANG", float), set_cmd=partial(self._set_mode_param, "RANG"), vals=Numbers(), ) + """Parameter range""" - self.add_parameter( + self.auto_range_enabled: Parameter = self.add_parameter( "auto_range_enabled", get_cmd=partial(self._get_mode_param, "RANG:AUTO", _parse_output_bool), set_cmd=partial(self._set_mode_param, "RANG:AUTO"), vals=Bool(), ) + """Parameter auto_range_enabled""" - self.add_parameter( + self.digits: Parameter = self.add_parameter( "digits", get_cmd=partial(self._get_mode_param, "DIG", int), set_cmd=partial(self._set_mode_param, "DIG"), vals=Ints(min_value=4, max_value=7), ) + """Parameter digits""" - self.add_parameter( + self.averaging_type: Parameter = self.add_parameter( "averaging_type", get_cmd=partial(self._get_mode_param, "AVER:TCON", _parse_output_string), set_cmd=partial(self._set_mode_param, "AVER:TCON"), vals=Enum("moving", "repeat"), ) + """Parameter averaging_type""" - self.add_parameter( + self.averaging_count: Parameter = self.add_parameter( "averaging_count", get_cmd=partial(self._get_mode_param, "AVER:COUN", int), set_cmd=partial(self._set_mode_param, "AVER:COUN"), vals=Ints(min_value=1, max_value=100), ) + """Parameter averaging_count""" - self.add_parameter( + self.averaging_enabled: Parameter = self.add_parameter( "averaging_enabled", get_cmd=partial(self._get_mode_param, "AVER:STAT", _parse_output_bool), set_cmd=partial(self._set_mode_param, "AVER:STAT"), vals=Bool(), ) + """Parameter averaging_enabled""" # Global parameters - self.add_parameter( + self.display_enabled: Parameter = self.add_parameter( "display_enabled", get_cmd="DISP:ENAB?", get_parser=_parse_output_bool, @@ -134,8 +144,9 @@ def __init__( set_parser=int, vals=Bool(), ) + """Parameter display_enabled""" - self.add_parameter( + self.trigger_continuous: Parameter = self.add_parameter( "trigger_continuous", get_cmd="INIT:CONT?", get_parser=_parse_output_bool, @@ -143,8 +154,9 @@ def __init__( set_parser=int, vals=Bool(), ) + """Parameter trigger_continuous""" - self.add_parameter( + self.trigger_count: Parameter = self.add_parameter( "trigger_count", get_cmd="TRIG:COUN?", get_parser=int, @@ -154,8 +166,9 @@ def __init__( Enum("inf", "default", "minimum", "maximum"), ), ) + """Parameter trigger_count""" - self.add_parameter( + self.trigger_delay: Parameter = self.add_parameter( "trigger_delay", get_cmd="TRIG:DEL?", get_parser=float, @@ -163,8 +176,9 @@ def __init__( unit="s", vals=Numbers(min_value=0, max_value=999999.999), ) + """Parameter trigger_delay""" - self.add_parameter( + self.trigger_source: Parameter = self.add_parameter( "trigger_source", get_cmd="TRIG:SOUR?", set_cmd="TRIG:SOUR {}", @@ -176,8 +190,9 @@ def __init__( "external": "EXT", }, ) + """Parameter trigger_source""" - self.add_parameter( + self.trigger_timer: Parameter = self.add_parameter( "trigger_timer", get_cmd="TRIG:TIM?", get_parser=float, @@ -185,8 +200,12 @@ def __init__( unit="s", vals=Numbers(min_value=0.001, max_value=999999.999), ) + """Parameter trigger_timer""" - self.add_parameter("amplitude", unit="arb.unit", get_cmd=self._read_next_value) + self.amplitude: Parameter = self.add_parameter( + "amplitude", unit="arb.unit", get_cmd=self._read_next_value + ) + """Parameter amplitude""" self.add_function("reset", call_cmd="*RST") diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2400.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2400.py index 5d2fe8325ae..a1be6ff2bac 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2400.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2400.py @@ -7,6 +7,8 @@ if TYPE_CHECKING: from typing_extensions import Unpack + from qcodes.parameters import Parameter + class Keithley2400(VisaInstrument): """ @@ -23,39 +25,43 @@ def __init__( ): super().__init__(name, address, **kwargs) - self.add_parameter( + self.rangev: Parameter = self.add_parameter( "rangev", get_cmd="SENS:VOLT:RANG?", get_parser=float, set_cmd="SOUR:VOLT:RANG {:f}", label="Voltage range", ) + """Parameter rangev""" - self.add_parameter( + self.rangei: Parameter = self.add_parameter( "rangei", get_cmd="SENS:CURR:RANG?", get_parser=float, set_cmd="SOUR:CURR:RANG {:f}", label="Current range", ) + """Parameter rangei""" - self.add_parameter( + self.compliancev: Parameter = self.add_parameter( "compliancev", get_cmd="SENS:VOLT:PROT?", get_parser=float, set_cmd="SENS:VOLT:PROT {:f}", label="Voltage Compliance", ) + """Parameter compliancev""" - self.add_parameter( + self.compliancei: Parameter = self.add_parameter( "compliancei", get_cmd="SENS:CURR:PROT?", get_parser=float, set_cmd="SENS:CURR:PROT {:f}", label="Current Compliance", ) + """Parameter compliancei""" - self.add_parameter( + self.volt: Parameter = self.add_parameter( "volt", get_cmd=self._get_read_output_protected, get_parser=self._volt_parser, @@ -69,8 +75,9 @@ def __init__( "Note that it is an error to read voltage with " "output off", ) + """Sets voltage in 'VOLT' mode. Get returns measured voltage if sensing 'VOLT' otherwise it returns setpoint value. Note that it is an error to read voltage with output off""" - self.add_parameter( + self.curr: Parameter = self.add_parameter( "curr", get_cmd=self._get_read_output_protected, get_parser=self._curr_parser, @@ -84,47 +91,53 @@ def __init__( "Note that it is an error to read current with " "output off", ) + """Sets current in 'CURR' mode. Get returns measured current if sensing 'CURR' otherwise it returns setpoint value. Note that it is an error to read current with output off""" - self.add_parameter( + self.mode: Parameter = self.add_parameter( "mode", vals=Enum("VOLT", "CURR"), get_cmd=":SOUR:FUNC?", set_cmd=self._set_mode_and_sense, label="Mode", ) + """Parameter mode""" - self.add_parameter( + self.sense: Parameter = self.add_parameter( "sense", vals=Strings(), get_cmd=":SENS:FUNC?", set_cmd=':SENS:FUNC "{:s}"', label="Sense mode", ) + """Parameter sense""" - self.add_parameter( + self.output: Parameter = self.add_parameter( "output", set_cmd=":OUTP:STAT {}", get_cmd=":OUTP:STAT?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), ) + """Parameter output""" - self.add_parameter( + self.nplcv: Parameter = self.add_parameter( "nplcv", get_cmd="SENS:VOLT:NPLC?", get_parser=float, set_cmd="SENS:VOLT:NPLC {:f}", label="Voltage integration time", ) + """Parameter nplcv""" - self.add_parameter( + self.nplci: Parameter = self.add_parameter( "nplci", get_cmd="SENS:CURR:NPLC?", get_parser=float, set_cmd="SENS:CURR:NPLC {:f}", label="Current integration time", ) + """Parameter nplci""" - self.add_parameter( + self.resistance: Parameter = self.add_parameter( "resistance", get_cmd=self._get_read_output_protected, get_parser=self._resistance_parser, @@ -134,6 +147,7 @@ def __init__( "Note that it is an error to read current " "and voltage with output off", ) + """Measure resistance from current and voltage Note that it is an error to read current and voltage with output off""" self.write(":TRIG:COUN 1;:FORM:ELEM VOLT,CURR") # This line sends 2 commands to the instrument: diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py index 4d3bdf12585..36b39c1f804 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py @@ -5,6 +5,7 @@ from qcodes.instrument import InstrumentChannel, VisaInstrument, VisaInstrumentKWArgs from qcodes.parameters import ( + Parameter, ParameterWithSetpoints, create_on_off_val_mapping, invert_val_mapping, @@ -94,22 +95,24 @@ def __init__( f"{self.buffer_name} size to {self._size}." ) - self.add_parameter( + self.size: Parameter = self.add_parameter( "size", get_cmd=f":TRACe:POINts? '{self.buffer_name}'", set_cmd=f":TRACe:POINts {{}}, '{self.buffer_name}'", get_parser=int, docstring="The number of readings a buffer can store.", ) + """The number of readings a buffer can store.""" - self.add_parameter( + self.number_of_readings: Parameter = self.add_parameter( "number_of_readings", get_cmd=f":TRACe:ACTual? '{self.buffer_name}'", get_parser=int, docstring="To get the number of readings in the reading buffer.", ) + """To get the number of readings in the reading buffer.""" - self.add_parameter( + self.elements: Parameter = self.add_parameter( "elements", get_cmd=None, get_parser=self.from_scpi_to_name, @@ -118,6 +121,7 @@ def __init__( vals=Lists(Enum(*list(self.buffer_elements.keys()))), docstring="List of buffer elements to read.", ) + """List of buffer elements to read.""" def from_name_to_scpi(self, element_names: list[str]) -> list[str]: return [self.buffer_elements[element] for element in element_names] @@ -240,14 +244,15 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N self.function = self.parent.sense_function - self.add_parameter( + self.four_wire_measurement: Parameter = self.add_parameter( "four_wire_measurement", set_cmd=f":SENSe:{self._proper_function}:RSENse {{}}", get_cmd=f":SENSe:{self._proper_function}:RSENse?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), ) + """Parameter four_wire_measurement""" - self.add_parameter( + self.range: Parameter = self.add_parameter( "range", set_cmd=f":SENSe:{self._proper_function}:RANGe {{}}", get_cmd=f":SENSe:{self._proper_function}:RANGe?", @@ -255,13 +260,15 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N get_parser=float, unit=unit, ) + """Parameter range""" - self.add_parameter( + self.auto_range: Parameter = self.add_parameter( "auto_range", set_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO {{}}", get_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), ) + """Parameter auto_range""" self.add_parameter( self._proper_function, @@ -271,7 +278,7 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N snapshot_value=False, ) - self.add_parameter( + self.sweep: ParameterWithSetpointsCustomized = self.add_parameter( "sweep", label=self._proper_function, get_cmd=self._measure_sweep, @@ -279,25 +286,31 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N vals=Arrays(shape=(self.parent.npts,)), parameter_class=ParameterWithSetpointsCustomized, ) + """Parameter sweep""" - self.add_parameter( + self.nplc: Parameter = self.add_parameter( "nplc", get_cmd=f":SENSe:{self._proper_function}:NPLCycles?", set_cmd=f":SENSe:{self._proper_function}:NPLCycles {{}}", vals=Numbers(0.001, 10), ) + """Parameter nplc""" - self.add_parameter("user_number", get_cmd=None, set_cmd=None, vals=Ints(1, 5)) + self.user_number: Parameter = self.add_parameter( + "user_number", get_cmd=None, set_cmd=None, vals=Ints(1, 5) + ) + """Parameter user_number""" - self.add_parameter( + self.user_delay: Parameter = self.add_parameter( "user_delay", get_cmd=self._get_user_delay, set_cmd=self._set_user_delay, get_parser=float, vals=Numbers(0, 1e4), ) + """Parameter user_delay""" - self.add_parameter( + self.auto_zero_enabled: Parameter = self.add_parameter( "auto_zero_enabled", get_cmd=f":SENSe:{self._proper_function}:AZERo?", set_cmd=f":SENSe:{self._proper_function}:AZERo {{}}", @@ -306,14 +319,16 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N "the internal reference measurements (autozero) of the" "instrument.", ) + """This command enables or disables automatic updates tothe internal reference measurements (autozero) of theinstrument.""" - self.add_parameter( + self.count: Parameter = self.add_parameter( "count", get_cmd=":SENSe:COUNt?", set_cmd=":SENSe:COUNt {}", docstring="The number of measurements to make when a measurement " "is requested.", ) + """The number of measurements to make when a measurement is requested.""" def _measure(self) -> Union[float, str]: if not self.parent.output_enabled(): @@ -391,7 +406,7 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N self.function = self.parent.source_function self._sweep_arguments: Optional[_SweepDict] = None - self.add_parameter( + self.range: Parameter = self.add_parameter( "range", set_cmd=f":SOUR:{self._proper_function}:RANGe {{}}", get_cmd=f":SOUR:{self._proper_function}:RANGe?", @@ -399,28 +414,32 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N get_parser=float, unit=unit, ) + """Parameter range""" - self.add_parameter( + self.auto_range: Parameter = self.add_parameter( "auto_range", set_cmd=f":SOURce:{self._proper_function}:RANGe:AUTO {{}}", get_cmd=f":SOURce:{self._proper_function}:RANGe:AUTO?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), ) + """Parameter auto_range""" limit_cmd = {"current": "VLIM", "voltage": "ILIM"}[self._proper_function] - self.add_parameter( + self.limit: Parameter = self.add_parameter( "limit", set_cmd=f"SOUR:{self._proper_function}:{limit_cmd} {{}}", get_cmd=f"SOUR:{self._proper_function}:{limit_cmd}?", get_parser=float, unit=unit, ) + """Parameter limit""" - self.add_parameter( + self.limit_tripped: Parameter = self.add_parameter( "limit_tripped", get_cmd=f":SOUR:{self._proper_function}:{limit_cmd}:TRIPped?", val_mapping={True: 1, False: 0}, ) + """Parameter limit_tripped""" self.add_parameter( self._proper_function, @@ -431,38 +450,45 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N snapshot_value=False, ) - self.add_parameter( + self.sweep_axis: Parameter = self.add_parameter( "sweep_axis", label=self._proper_function, get_cmd=self.get_sweep_axis, vals=Arrays(shape=(self.parent.npts,)), unit=unit, ) + """Parameter sweep_axis""" - self.add_parameter( + self.delay: Parameter = self.add_parameter( "delay", get_cmd=f":SOURce:{self._proper_function}:DELay?", set_cmd=f":SOURce:{self._proper_function}:DELay {{}}", vals=Numbers(0, 1e4), ) + """Parameter delay""" - self.add_parameter("user_number", get_cmd=None, set_cmd=None, vals=Ints(1, 5)) + self.user_number: Parameter = self.add_parameter( + "user_number", get_cmd=None, set_cmd=None, vals=Ints(1, 5) + ) + """Parameter user_number""" - self.add_parameter( + self.user_delay: Parameter = self.add_parameter( "user_delay", get_cmd=self._get_user_delay, set_cmd=self._set_user_delay, vals=Numbers(0, 1e4), ) + """Parameter user_delay""" - self.add_parameter( + self.auto_delay: Parameter = self.add_parameter( "auto_delay", get_cmd=f":SOURce:{self._proper_function}:DELay:AUTO?", set_cmd=f":SOURce:{self._proper_function}:DELay:AUTO {{}}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), ) + """Parameter auto_delay""" - self.add_parameter( + self.read_back_enabled: Parameter = self.add_parameter( "read_back_enabled", get_cmd=f":SOURce:{self._proper_function}:READ:BACK?", set_cmd=f":SOURce:{self._proper_function}:READ:BACK {{}}", @@ -471,8 +497,9 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N "measured source value or the configured source value " "when making a measurement.", ) + """This command determines if the instrument records the measured source value or the configured source value when making a measurement.""" - self.add_parameter( + self.block_during_ramp: Parameter = self.add_parameter( "block_during_ramp", initial_value=False, get_cmd=None, @@ -482,6 +509,7 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N "execution of subsequent code. This parameter allows _proper_function" "to either block or not.", ) + """Setting the source output level alone cannot block the execution of subsequent code. This parameter allows _proper_functionto either block or not.""" def _set_proper_function(self, value: float) -> None: self.write(f"SOUR:{self._proper_function} {value}") @@ -581,7 +609,7 @@ def __init__( ) return - self.add_parameter( + self.source_function: Parameter = self.add_parameter( "source_function", set_cmd=self._set_source_function, get_cmd=":SOUR:FUNC?", @@ -590,8 +618,9 @@ def __init__( for key, value in Keithley2450Source.function_modes.items() }, ) + """Parameter source_function""" - self.add_parameter( + self.sense_function: Parameter = self.add_parameter( "sense_function", set_cmd=self._set_sense_function, get_cmd=":SENS:FUNC?", @@ -600,35 +629,40 @@ def __init__( for key, value in Keithley2450Sense.function_modes.items() }, ) + """Parameter sense_function""" - self.add_parameter( + self.terminals: Parameter = self.add_parameter( "terminals", set_cmd="ROUTe:TERMinals {}", get_cmd="ROUTe:TERMinals?", vals=Enum("rear", "front"), ) + """Parameter terminals""" - self.add_parameter( + self.output_enabled: Parameter = self.add_parameter( "output_enabled", set_cmd=":OUTP {}", get_cmd=":OUTP?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), ) + """Parameter output_enabled""" - self.add_parameter( + self.line_frequency: Parameter = self.add_parameter( "line_frequency", get_cmd=":SYSTem:LFRequency?", unit="Hz", docstring="returns the power line frequency setting that is used " "for NPLC calculations", ) + """returns the power line frequency setting that is used for NPLC calculations""" - self.add_parameter( + self.buffer_name: Parameter = self.add_parameter( "buffer_name", get_cmd=None, set_cmd=None, docstring="name of the reading buffer in using", ) + """name of the reading buffer in using""" # Make a source module for every source function ('current' and 'voltage') for proper_source_function in Keithley2450Source.function_modes: diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py b/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py index 41b1637d50b..2e1f092be86 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py @@ -5,7 +5,7 @@ import qcodes.validators as vals from qcodes.instrument import VisaInstrument, VisaInstrumentKWArgs -from qcodes.parameters import create_on_off_val_mapping +from qcodes.parameters import Parameter, create_on_off_val_mapping if TYPE_CHECKING: from typing_extensions import Unpack @@ -41,7 +41,7 @@ def __init__( """ super().__init__(name, address, **kwargs) - self.add_parameter( + self.channel_connect_rule: Parameter = self.add_parameter( "channel_connect_rule", get_cmd=self._get_channel_connect_rule, set_cmd=self._set_channel_connect_rule, @@ -65,16 +65,32 @@ def __init__( ), vals=vals.Enum("BREAK_BEFORE_MAKE", "MAKE_BEFORE_BREAK", "OFF"), ) + """Controls the connection rule for closing +and opening channels when using +`exclusive_close` and `exclusive_slot_close` +parameters. - self.add_parameter( +If it is set to break before make, +it is ensured that all channels open +before any channels close. + +If it is set to make before break, it is +ensured that all channels close before any +channels open. + +If it is off, channels open and close +simultaneously.""" + + self.gpib_enabled: Parameter = self.add_parameter( "gpib_enabled", get_cmd=self._get_gpib_status, set_cmd=self._set_gpib_status, docstring="Enables or disables GPIB connection.", val_mapping=create_on_off_val_mapping(on_val="true", off_val="false"), ) + """Enables or disables GPIB connection.""" - self.add_parameter( + self.gpib_address: Parameter = self.add_parameter( "gpib_address", get_cmd=self._get_gpib_address, get_parser=int, @@ -82,14 +98,16 @@ def __init__( docstring="Sets and gets the GPIB address.", vals=vals.Ints(1, 30), ) + """Sets and gets the GPIB address.""" - self.add_parameter( + self.lan_enabled: Parameter = self.add_parameter( "lan_enabled", get_cmd=self._get_lan_status, set_cmd=self._set_lan_status, docstring="Enables or disables LAN connection.", val_mapping=create_on_off_val_mapping(on_val="true", off_val="false"), ) + """Enables or disables LAN connection.""" self.connect_message() diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py b/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py index b8e01328cad..2314ae66a98 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py @@ -7,6 +7,8 @@ if TYPE_CHECKING: from typing_extensions import Unpack + from qcodes.parameters import Parameter + T = TypeVar("T") @@ -92,67 +94,75 @@ def __init__( "frequency": "FREQ", } - self.add_parameter( + self.mode: Parameter = self.add_parameter( "mode", get_cmd="SENS:FUNC?", set_cmd="SENS:FUNC '{}'", val_mapping=self._mode_map, ) + """Parameter mode""" - self.add_parameter( + self.nplc: Parameter = self.add_parameter( "nplc", get_cmd=partial(self._get_mode_param, "NPLC", float), set_cmd=partial(self._set_mode_param, "NPLC"), vals=Numbers(min_value=0.01, max_value=10), ) + """Parameter nplc""" # TODO: validator, this one is more difficult since different modes # require different validation ranges. - self.add_parameter( + self.range: Parameter = self.add_parameter( "range", get_cmd=partial(self._get_mode_param, "RANG", float), set_cmd=partial(self._set_mode_param, "RANG"), vals=Numbers(), ) + """Parameter range""" - self.add_parameter( + self.auto_range_enabled: Parameter = self.add_parameter( "auto_range_enabled", get_cmd=partial(self._get_mode_param, "RANG:AUTO", _parse_output_bool), set_cmd=partial(self._set_mode_param, "RANG:AUTO"), vals=Bool(), ) + """Parameter auto_range_enabled""" - self.add_parameter( + self.digits: Parameter = self.add_parameter( "digits", get_cmd="DISP:VOLT:DC:DIG?", get_parser=int, set_cmd="DISP:VOLT:DC:DIG? {}", vals=Ints(min_value=4, max_value=7), ) + """Parameter digits""" - self.add_parameter( + self.averaging_type: Parameter = self.add_parameter( "averaging_type", get_cmd=partial(self._get_mode_param, "AVER:TCON", _parse_output_string), set_cmd=partial(self._set_mode_param, "AVER:TCON"), vals=Enum("moving", "repeat"), ) + """Parameter averaging_type""" - self.add_parameter( + self.averaging_count: Parameter = self.add_parameter( "averaging_count", get_cmd=partial(self._get_mode_param, "AVER:COUN", int), set_cmd=partial(self._set_mode_param, "AVER:COUN"), vals=Ints(min_value=1, max_value=100), ) + """Parameter averaging_count""" - self.add_parameter( + self.averaging_enabled: Parameter = self.add_parameter( "averaging_enabled", get_cmd=partial(self._get_mode_param, "AVER:STAT", _parse_output_bool), set_cmd=partial(self._set_mode_param, "AVER:STAT"), vals=Bool(), ) + """Parameter averaging_enabled""" # Global parameters - self.add_parameter( + self.display_backlight: Parameter = self.add_parameter( "display_backlight", docstring="Control the brightness of the display " "backligt. Off turns the display off and" @@ -169,8 +179,9 @@ def __init__( "Blackout": "BLACkout", }, ) + """Control the brightness of the display backligt. Off turns the display off andBlackout also turns off indicators and key lights on the device.""" - self.add_parameter( + self.trigger_count: Parameter = self.add_parameter( "trigger_count", get_parser=int, get_cmd="ROUT:SCAN:COUN:SCAN?", @@ -180,6 +191,7 @@ def __init__( Enum("inf", "default", "minimum", "maximum"), ), ) + """Parameter trigger_count""" for trigger in range(1, 5): self.add_parameter( @@ -214,7 +226,7 @@ def __init__( # Control interval between scans; the default value from the instrument is 0, # hence 0 is included in the validator's range of this parameter. - self.add_parameter( + self.trigger_timer: Parameter = self.add_parameter( "trigger_timer", get_parser=float, get_cmd="ROUT:SCAN:INT?", @@ -222,10 +234,12 @@ def __init__( unit="s", vals=Numbers(min_value=0, max_value=999999.999), ) + """Parameter trigger_timer""" - self.add_parameter( + self.amplitude: Parameter = self.add_parameter( "amplitude", get_cmd=self._read_next_value, set_cmd=False, unit="a.u." ) + """Parameter amplitude""" if reset_device: self.reset() diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py index a1941aa2b32..aa6ef25b0c6 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py @@ -129,52 +129,58 @@ def __init__( f"{self.short_name} size to {self._size}." ) - self.add_parameter( + self.size: Parameter = self.add_parameter( "size", get_cmd=f":TRACe:POINts? '{self.short_name}'", set_cmd=f":TRACe:POINts {{}}, '{self.short_name}'", get_parser=int, docstring="The number of readings a buffer can store.", ) + """The number of readings a buffer can store.""" - self.add_parameter( + self.number_of_readings: Parameter = self.add_parameter( "number_of_readings", get_cmd=f":TRACe:ACTual? '{self.short_name}'", get_parser=int, docstring="Get the number of readings in the reading buffer.", ) + """Get the number of readings in the reading buffer.""" - self.add_parameter( + self.last_index: Parameter = self.add_parameter( "last_index", get_cmd=f":TRACe:ACTual:END? '{self.short_name}'", get_parser=int, docstring="Get the last index of readings in the reading buffer.", ) + """Get the last index of readings in the reading buffer.""" - self.add_parameter( + self.first_index: Parameter = self.add_parameter( "first_index", get_cmd=f":TRACe:ACTual:STARt? '{self.short_name}'", get_parser=int, docstring="Get the starting index of readings in the reading buffer.", ) + """Get the starting index of readings in the reading buffer.""" - self.add_parameter( + self.data_start: Parameter = self.add_parameter( "data_start", initial_value=1, get_cmd=None, set_cmd=None, docstring="First index of the data to be returned.", ) + """First index of the data to be returned.""" - self.add_parameter( + self.data_end: Parameter = self.add_parameter( "data_end", initial_value=1, get_cmd=None, set_cmd=None, docstring="Last index of the data to be returned.", ) + """Last index of the data to be returned.""" - self.add_parameter( + self.elements: Parameter = self.add_parameter( "elements", get_cmd=None, get_parser=self._from_scpi_to_name, @@ -183,26 +189,30 @@ def __init__( vals=Lists(Enum(*list(self.buffer_elements.keys()))), docstring="List of buffer elements to read.", ) + """List of buffer elements to read.""" - self.add_parameter( + self.setpoints_start: DelegateParameter = self.add_parameter( "setpoints_start", label="start value for the setpoints", source=None, parameter_class=DelegateParameter, ) + """Parameter setpoints_start""" - self.add_parameter( + self.setpoints_stop: DelegateParameter = self.add_parameter( "setpoints_stop", label="stop value for the setpoints", source=None, parameter_class=DelegateParameter, ) + """Parameter setpoints_stop""" - self.add_parameter( + self.n_pts: Parameter = self.add_parameter( "n_pts", label="total n for the setpoints", get_cmd=self._get_n_pts ) + """Parameter n_pts""" - self.add_parameter( + self.setpoints: GeneratedSetPoints = self.add_parameter( "setpoints", parameter_class=GeneratedSetPoints, start=self.setpoints_start, @@ -210,8 +220,9 @@ def __init__( n_points=self.n_pts, vals=Arrays(shape=(self.n_pts.get_latest,)), ) + """Parameter setpoints""" - self.add_parameter( + self.t_start: Parameter = self.add_parameter( "t_start", label="start time", unit="s", @@ -220,8 +231,9 @@ def __init__( set_cmd=None, set_parser=float, ) + """Parameter t_start""" - self.add_parameter( + self.t_stop: Parameter = self.add_parameter( "t_stop", label="stop time", unit="s", @@ -230,8 +242,9 @@ def __init__( set_cmd=None, set_parser=float, ) + """Parameter t_stop""" - self.add_parameter( + self.fill_mode: Parameter = self.add_parameter( "fill_mode", get_cmd=f":TRACe:FILL:MODE? '{self.short_name}'", set_cmd=f":TRACe:FILL:MODE {{}}, '{self.short_name}'", @@ -239,6 +252,7 @@ def __init__( docstring="if a reading buffer is filled continuously or is filled" " once and stops", ) + """if a reading buffer is filled continuously or is filled once and stops""" def _from_name_to_scpi(self, element_names: list[str]) -> list[str]: return [self.buffer_elements[element] for element in element_names] @@ -476,7 +490,7 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N "return the last reading.", ) - self.add_parameter( + self.auto_range: Parameter = self.add_parameter( "auto_range", get_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO?", set_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO {{}}", @@ -484,8 +498,9 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Determine if the measurement range is set manually or " "automatically for the selected measure function.", ) + """Determine if the measurement range is set manually or automatically for the selected measure function.""" - self.add_parameter( + self.range: Parameter = self.add_parameter( "range", get_cmd=f":SENSe:{self._proper_function}:RANGe?", set_cmd=f":SENSe:{self._proper_function}:RANGe {{}}", @@ -494,8 +509,9 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N unit=unit, docstring="Determine the positive full-scale measure range.", ) + """Determine the positive full-scale measure range.""" - self.add_parameter( + self.nplc: Parameter = self.add_parameter( "nplc", get_cmd=f":SENSe:{self._proper_function}:NPLCycles?", set_cmd=f":SENSe:{self._proper_function}:NPLCycles {{}}", @@ -504,8 +520,9 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Set the time that the input signal is measured for the " "selected function.(NPLC = number of power line cycles)", ) + """Set the time that the input signal is measured for the selected function.(NPLC = number of power line cycles)""" - self.add_parameter( + self.auto_delay: Parameter = self.add_parameter( "auto_delay", get_cmd=f":SENSe:{self._proper_function}:DELay:AUTO?", set_cmd=f":SENSe:{self._proper_function}:DELay:AUTO {{}}", @@ -513,16 +530,18 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Enable or disable the automatic delay that occurs " "before each measurement.", ) + """Enable or disable the automatic delay that occurs before each measurement.""" - self.add_parameter( + self.user_number: Parameter = self.add_parameter( "user_number", get_cmd=None, set_cmd=None, vals=Ints(1, 5), docstring="Set the user number for user-defined delay.", ) + """Set the user number for user-defined delay.""" - self.add_parameter( + self.user_delay: Parameter = self.add_parameter( "user_delay", get_cmd=self._get_user_delay, set_cmd=self._set_user_delay, @@ -531,8 +550,9 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Set a user-defined delay that you can use in the " "trigger model.", ) + """Set a user-defined delay that you can use in the trigger model.""" - self.add_parameter( + self.auto_zero: Parameter = self.add_parameter( "auto_zero", get_cmd=f":SENSe:{self._proper_function}:AZERo?", set_cmd=f":SENSe:{self._proper_function}:AZERo {{}}", @@ -540,15 +560,17 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Enable or disable automatic updates to the internal " "reference measurements (autozero) of the instrument.", ) + """Enable or disable automatic updates to the internal reference measurements (autozero) of the instrument.""" - self.add_parameter( + self.auto_zero_once: Parameter = self.add_parameter( "auto_zero_once", set_cmd=":SENSe:AZERo:ONCE", docstring="Cause the instrument to refresh the reference and " "zero measurements once", ) + """Cause the instrument to refresh the reference and zero measurements once""" - self.add_parameter( + self.average: Parameter = self.add_parameter( "average", get_cmd=f":SENSe:{self._proper_function}:AVERage?", set_cmd=f":SENSe:{self._proper_function}:AVERage {{}}", @@ -556,8 +578,9 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Enable or disable the averaging filter for measurements " "of the selected function.", ) + """Enable or disable the averaging filter for measurements of the selected function.""" - self.add_parameter( + self.average_count: Parameter = self.add_parameter( "average_count", get_cmd=f":SENSe:{self._proper_function}:AVERage:COUNt?", set_cmd=f":SENSe:{self._proper_function}:AVERage:COUNt {{}}", @@ -565,8 +588,9 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Set the number of measurements that are averaged when " "filtering is enabled.", ) + """Set the number of measurements that are averaged when filtering is enabled.""" - self.add_parameter( + self.average_type: Parameter = self.add_parameter( "average_type", get_cmd=f":SENSe:{self._proper_function}:AVERage:TCONtrol?", set_cmd=f":SENSe:{self._proper_function}:AVERage:TCONtrol {{}}", @@ -575,6 +599,7 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N "selected measure function when the measurement filter " "is enabled.", ) + """Set the type of averaging filter that is used for the selected measure function when the measurement filter is enabled.""" def _get_user_delay(self) -> str: get_cmd = f":SENSe:{self._proper_function}:DELay:USER{self.user_number()}?" @@ -634,7 +659,7 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N "return the last reading.", ) - self.add_parameter( + self.range: Parameter = self.add_parameter( "range", get_cmd=f":SENSe:DIGitize:{self._proper_function}:RANGe?", set_cmd=f":SENSe:DIGitize:{self._proper_function}:RANGe {{}}", @@ -643,8 +668,9 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N unit=unit, docstring="Determine the positive full-scale measure range.", ) + """Determine the positive full-scale measure range.""" - self.add_parameter( + self.input_impedance: Parameter = self.add_parameter( "input_impedance", get_cmd=":SENSe:DIGitize:VOLTage:INPutimpedance?", set_cmd=":SENSe:DIGitize:VOLTage:INPutimpedance {}", @@ -652,8 +678,9 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Determine when the 10 MΩ input divider is enabled. " "'MOHM10' means 10 MΩ for all ranges.", ) + """Determine when the 10 MΩ input divider is enabled. 'MOHM10' means 10 MΩ for all ranges.""" - self.add_parameter( + self.acq_rate: Parameter = self.add_parameter( "acq_rate", get_cmd=f":SENSe:DIGitize:{self._proper_function}:SRATE?", set_cmd=f":SENSe:DIGitize:{self._proper_function}:SRATE {{}}", @@ -661,16 +688,18 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Define the precise acquisition rate at which the " "digitizing measurements are made.", ) + """Define the precise acquisition rate at which the digitizing measurements are made.""" - self.add_parameter( + self.aperture: Parameter = self.add_parameter( "aperture", get_cmd=f":SENSe:DIGitize:{self._proper_function}:APERture?", set_cmd=f":SENSe:DIGitize:{self._proper_function}:APERture {{}}", unit="us", docstring="Determine the aperture setting.", ) + """Determine the aperture setting.""" - self.add_parameter( + self.count: Parameter = self.add_parameter( "count", get_cmd="SENSe:DIGitize:COUNt?", set_cmd="SENSe:DIGitize:COUNt {}", @@ -678,6 +707,7 @@ def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> N docstring="Set the number of measurements to digitize when a " "measurement is requested", ) + """Set the number of measurements to digitize when a measurement is requested""" def _measure(self) -> Union[float, str]: buffer_name = self.parent.buffer_name() @@ -707,7 +737,7 @@ def __init__( """ super().__init__(name, address, **kwargs) - self.add_parameter( + self.sense_function: Parameter = self.add_parameter( "sense_function", set_cmd=":SENSe:FUNCtion {}", get_cmd=":SENSe:FUNCtion?", @@ -717,8 +747,9 @@ def __init__( }, docstring="Add sense functions listed in the function modes.", ) + """Add sense functions listed in the function modes.""" - self.add_parameter( + self.digi_sense_function: Parameter = self.add_parameter( "digi_sense_function", set_cmd=":DIGitize:FUNCtion {}", get_cmd=":DIGitize:FUNCtion?", @@ -728,27 +759,31 @@ def __init__( }, docstring="Make readings using the active digitize function.", ) + """Make readings using the active digitize function.""" - self.add_parameter( + self.buffer_name: Parameter = self.add_parameter( "buffer_name", get_cmd=None, set_cmd=None, docstring="Name of the reading buffer in use.", ) + """Name of the reading buffer in use.""" - self.add_parameter( + self.trigger_block_list: Parameter = self.add_parameter( "trigger_block_list", get_cmd=":TRIGger:BLOCk:LIST?", docstring="Return the settings for all trigger model blocks.", ) + """Return the settings for all trigger model blocks.""" - self.add_parameter( + self.trigger_in_ext_clear: Parameter = self.add_parameter( "trigger_in_ext_clear", set_cmd=":TRIGger:EXTernal:IN:CLEar", docstring="Clear the trigger event on the external in line.", ) + """Clear the trigger event on the external in line.""" - self.add_parameter( + self.trigger_in_ext_edge: Parameter = self.add_parameter( "trigger_in_ext_edge", get_cmd=":TRIGger:EXTernal:IN:EDGE?", set_cmd=":TRIGger:EXTernal:IN:EDGE {}", @@ -756,14 +791,16 @@ def __init__( docstring="Type of edge that is detected as an input on the " "external trigger in line", ) + """Type of edge that is detected as an input on the external trigger in line""" - self.add_parameter( + self.overrun_status: Parameter = self.add_parameter( "overrun_status", get_cmd=":TRIGger:EXTernal:IN:OVERrun?", docstring="Return the event detector overrun status.", ) + """Return the event detector overrun status.""" - self.add_parameter( + self.digitize_trigger: Parameter = self.add_parameter( "digitize_trigger", get_cmd=":TRIGger:DIGitize:STIMulus?", set_cmd=":TRIGger:DIGitize:STIMulus {}", @@ -771,13 +808,15 @@ def __init__( docstring="Set the instrument to digitize a measurement the next " "time it detects the specified trigger event.", ) + """Set the instrument to digitize a measurement the next time it detects the specified trigger event.""" - self.add_parameter( + self.system_errors: Parameter = self.add_parameter( "system_errors", get_cmd=":SYSTem:ERRor?", docstring="Return the oldest unread error message from the event " "log and removes it from the log.", ) + """Return the oldest unread error message from the event log and removes it from the log.""" for proper_sense_function in Keithley7510Sense.function_modes: self.add_submodule( diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py b/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py index 5a90801082f..ae619423864 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py @@ -153,11 +153,12 @@ def __init__( ): super().__init__(name, address, **kwargs) try: - self.add_parameter( + self.closed_channels: Parameter = self.add_parameter( "closed_channels", get_cmd=":CLOS?", get_parser=self._get_closed_channels_parser, ) + """Parameter closed_channels""" self._available_channels: list[str] = [] diff --git a/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py b/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py index 81ab1d088f5..06f4c1562d9 100644 --- a/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py +++ b/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py @@ -374,23 +374,25 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: vlimit_minmax = self.parent._vlimit_minmax ilimit_minmax = self.parent._ilimit_minmax - self.add_parameter( + self.volt: _MeasurementVoltageParameter = self.add_parameter( "volt", parameter_class=_MeasurementVoltageParameter, label="Voltage", unit="V", snapshot_get=False, ) + """Parameter volt""" - self.add_parameter( + self.curr: _MeasurementCurrentParameter = self.add_parameter( "curr", parameter_class=_MeasurementCurrentParameter, label="Current", unit="A", snapshot_get=False, ) + """Parameter curr""" - self.add_parameter( + self.res: Parameter = self.add_parameter( "res", get_cmd=f"{channel}.measure.r()", get_parser=float, @@ -398,8 +400,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: label="Resistance", unit="Ohm", ) + """Parameter res""" - self.add_parameter( + self.mode: Parameter = self.add_parameter( "mode", get_cmd=f"{channel}.source.func", get_parser=float, @@ -408,16 +411,18 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: docstring="Selects the output source type. " "Can be either voltage or current.", ) + """Selects the output source type. Can be either voltage or current.""" - self.add_parameter( + self.output: Parameter = self.add_parameter( "output", get_cmd=f"{channel}.source.output", get_parser=float, set_cmd=f"{channel}.source.output={{:d}}", val_mapping=create_on_off_val_mapping(on_val=1, off_val=0), ) + """Parameter output""" - self.add_parameter( + self.linefreq: Parameter = self.add_parameter( "linefreq", label="Line frequency", get_cmd="localnode.linefreq", @@ -425,8 +430,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: set_cmd=False, unit="Hz", ) + """Parameter linefreq""" - self.add_parameter( + self.nplc: Parameter = self.add_parameter( "nplc", label="Number of power line cycles", set_cmd=f"{channel}.measure.nplc={{}}", @@ -435,9 +441,10 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: docstring="Number of power line cycles, used to perform measurements", vals=vals.Numbers(0.001, 25), ) + """Number of power line cycles, used to perform measurements""" # volt range # needs get after set (WilliamHPNielsen): why? - self.add_parameter( + self.sourcerange_v: Parameter = self.add_parameter( "sourcerange_v", label="voltage source range", get_cmd=f"{channel}.source.rangev", @@ -449,8 +456,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: "of the source.", vals=vals.Enum(*vranges[self.model]), ) + """The range used when sourcing voltage This affects the range and the precision of the source.""" - self.add_parameter( + self.source_autorange_v_enabled: Parameter = self.add_parameter( "source_autorange_v_enabled", label="voltage source autorange", get_cmd=f"{channel}.source.autorangev", @@ -459,8 +467,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: docstring="Set autorange on/off for source voltage.", val_mapping=create_on_off_val_mapping(on_val=1, off_val=0), ) + """Set autorange on/off for source voltage.""" - self.add_parameter( + self.measurerange_v: Parameter = self.add_parameter( "measurerange_v", label="voltage measure range", get_cmd=f"{channel}.measure.rangev", @@ -475,8 +484,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: "set `sourcerange_v` instead", vals=vals.Enum(*vranges[self.model]), ) + """The range to perform voltage measurements in. This affects the range and the precision of the measurement. Note that if you both measure and source current this will have no effect, set `sourcerange_v` instead""" - self.add_parameter( + self.measure_autorange_v_enabled: Parameter = self.add_parameter( "measure_autorange_v_enabled", label="voltage measure autorange", get_cmd=f"{channel}.measure.autorangev", @@ -485,9 +495,10 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: docstring="Set autorange on/off for measure voltage.", val_mapping=create_on_off_val_mapping(on_val=1, off_val=0), ) + """Set autorange on/off for measure voltage.""" # current range # needs get after set - self.add_parameter( + self.sourcerange_i: Parameter = self.add_parameter( "sourcerange_i", label="current source range", get_cmd=f"{channel}.source.rangei", @@ -499,8 +510,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: "precision of the source.", vals=vals.Enum(*iranges[self.model]), ) + """The range used when sourcing current This affects the range and the precision of the source.""" - self.add_parameter( + self.source_autorange_i_enabled: Parameter = self.add_parameter( "source_autorange_i_enabled", label="current source autorange", get_cmd=f"{channel}.source.autorangei", @@ -509,8 +521,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: docstring="Set autorange on/off for source current.", val_mapping=create_on_off_val_mapping(on_val=1, off_val=0), ) + """Set autorange on/off for source current.""" - self.add_parameter( + self.measurerange_i: Parameter = self.add_parameter( "measurerange_i", label="current measure range", get_cmd=f"{channel}.measure.rangei", @@ -525,8 +538,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: "`sourcerange_i` instead", vals=vals.Enum(*iranges[self.model]), ) + """The range to perform current measurements in. This affects the range and the precision of the measurement. Note that if you both measure and source current this will have no effect, set `sourcerange_i` instead""" - self.add_parameter( + self.measure_autorange_i_enabled: Parameter = self.add_parameter( "measure_autorange_i_enabled", label="current autorange", get_cmd=f"{channel}.measure.autorangei", @@ -535,8 +549,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: docstring="Set autorange on/off for measure current.", val_mapping=create_on_off_val_mapping(on_val=1, off_val=0), ) + """Set autorange on/off for measure current.""" # Compliance limit - self.add_parameter( + self.limitv: Parameter = self.add_parameter( "limitv", get_cmd=f"{channel}.source.limitv", get_parser=float, @@ -549,8 +564,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: ), unit="V", ) + """Voltage limit e.g. the maximum voltage allowed in current mode. If exceeded the current will be clipped.""" # Compliance limit - self.add_parameter( + self.limiti: Parameter = self.add_parameter( "limiti", get_cmd=f"{channel}.source.limiti", get_parser=float, @@ -563,18 +579,23 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: ), unit="A", ) + """Current limit e.g. the maximum current allowed in voltage mode. If exceeded the voltage will be clipped.""" - self.add_parameter("fastsweep", parameter_class=LuaSweepParameter) + self.fastsweep: LuaSweepParameter = self.add_parameter( + "fastsweep", parameter_class=LuaSweepParameter + ) + """Parameter fastsweep""" - self.add_parameter( + self.timetrace_npts: Parameter = self.add_parameter( "timetrace_npts", initial_value=500, label="Number of points", get_cmd=None, set_cmd=None, ) + """Parameter timetrace_npts""" - self.add_parameter( + self.timetrace_dt: Parameter = self.add_parameter( "timetrace_dt", initial_value=1e-3, label="Time resolution", @@ -582,8 +603,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: get_cmd=None, set_cmd=None, ) + """Parameter timetrace_dt""" - self.add_parameter( + self.time_axis: TimeAxis = self.add_parameter( name="time_axis", label="Time", unit="s", @@ -591,21 +613,24 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: vals=vals.Arrays(shape=(self.timetrace_npts,)), parameter_class=TimeAxis, ) + """Parameter time_axis""" - self.add_parameter( + self.timetrace: TimeTrace = self.add_parameter( "timetrace", vals=vals.Arrays(shape=(self.timetrace_npts,)), setpoints=(self.time_axis,), parameter_class=TimeTrace, ) + """Parameter timetrace""" - self.add_parameter( + self.timetrace_mode: Parameter = self.add_parameter( "timetrace_mode", initial_value="current", get_cmd=None, set_cmd=self.timetrace._set_mode, vals=vals.Enum("current", "voltage"), ) + """Parameter timetrace_mode""" self.channel = channel @@ -923,9 +948,10 @@ def __init__( self.channels.append(channel) # display - self.add_parameter( + self.display_settext: Parameter = self.add_parameter( "display_settext", set_cmd=self._display_settext, vals=vals.Strings() ) + """Parameter display_settext""" self.connect_message() From fc287d2c9d335d46c0f715f56be7cf0e61b6a854 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 23 May 2024 20:57:25 +0200 Subject: [PATCH 05/10] add channel to public interface --- src/qcodes/instrument_drivers/Keithley/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/qcodes/instrument_drivers/Keithley/__init__.py b/src/qcodes/instrument_drivers/Keithley/__init__.py index b41bf9e9cb1..5957889e3fe 100644 --- a/src/qcodes/instrument_drivers/Keithley/__init__.py +++ b/src/qcodes/instrument_drivers/Keithley/__init__.py @@ -1,6 +1,10 @@ from typing import Union -from ._Keithley_2600 import Keithley2600, Keithley2600MeasurementStatus +from ._Keithley_2600 import ( + Keithley2600, + Keithley2600Channel, + Keithley2600MeasurementStatus, +) from .Keithley_2000 import Keithley2000 from .Keithley_2400 import Keithley2400 from .Keithley_2450 import ( @@ -63,6 +67,7 @@ "Keithley2600MeasurementStatus", "Keithley2600", "Keithley26xx", + "Keithley2600Channel", "Keithley2601B", "Keithley2602A", "Keithley2602B", From bbea473e9473a2fb1335092215619a66642771c2 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 23 May 2024 20:58:04 +0200 Subject: [PATCH 06/10] Improve docstrings --- .../Keithley/Keithley_6500.py | 9 ++-- .../Keithley/Keithley_7510.py | 51 ++++++++++--------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py b/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py index 2314ae66a98..e43e10d03b3 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py @@ -59,11 +59,12 @@ def __init__( reset_device: bool = False, **kwargs: "Unpack[VisaInstrumentKWArgs]", ): - """Driver for the Keithley 6500 multimeter. Based on the Keithley 2000 driver, - commands have been adapted for the Keithley 6500. This driver does not contain - all commands available, but only the ones most commonly used. + """ + Driver for the Keithley 6500 multimeter. Based on the Keithley 2000 driver, + commands have been adapted for the Keithley 6500. This driver does not contain + all commands available, but only the ones most commonly used. - Status: beta-version. + Status: beta-version. Args: name: The name used internally by QCoDeS in the DataSet. diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py index aa6ef25b0c6..f31021a03e8 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py @@ -417,27 +417,6 @@ class _FunctionMode(TypedDict): class Keithley7510Sense(InstrumentChannel): - """ - The sense module of the Keithley 7510 DMM, based on the sense module of - Keithley 2450 SMU. - - Args: - parent - name - proper_function: This can be one of modes listed in the dictionary - "function_modes", e.g., "current", "voltage", or "resistance". - "voltage"/"current" is for DC voltage/current. - "Avoltage"/"Acurrent" is for AC voltage/current. - "resistance" is for two-wire measurement of resistance. - "Fresistance" is for Four-wire measurement of resistance. - - All parameters and methods in this submodule should only be - accessible to the user if - self.parent.sense_function.get() == self._proper_function. We - ensure this through the 'sense' property on the main driver class - which returns the proper submodule for any given function mode. - """ - function_modes: ClassVar[dict[str, _FunctionMode]] = { "voltage": { "name": '"VOLT:DC"', @@ -471,9 +450,35 @@ class Keithley7510Sense(InstrumentChannel): }, } - def __init__(self, parent: VisaInstrument, name: str, proper_function: str) -> None: + def __init__( + self, + parent: VisaInstrument, + name: str, + proper_function: str, + **kwargs: "Unpack[VisaInstrumentKWArgs]", + ) -> None: + """ + The sense module of the Keithley 7510 DMM, based on the sense module of + Keithley 2450 SMU. - super().__init__(parent, name) + All parameters and methods in this submodule should only be + accessible to the user if + self.parent.sense_function.get() == self._proper_function. We + ensure this through the 'sense' property on the main driver class + which returns the proper submodule for any given function mode. + + Args: + parent: Parent instrument. + name: Name of the channel. + proper_function: This can be one of modes listed in the dictionary + "function_modes", e.g., "current", "voltage", or "resistance". + "voltage"/"current" is for DC voltage/current. + "Avoltage"/"Acurrent" is for AC voltage/current. + "resistance" is for two-wire measurement of resistance. + "Fresistance" is for Four-wire measurement of resistance. + **kwargs: Forwarded to base class. + """ + super().__init__(parent, name, **kwargs) self._proper_function = proper_function range_vals = self.function_modes[self._proper_function]["range_vals"] From 6d43cb880cae25dcb5a53189fbc3daa301737d95 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 May 2024 06:53:00 +0200 Subject: [PATCH 07/10] fix type checking --- src/qcodes/instrument_drivers/Keithley/Keithley_2450.py | 4 +++- src/qcodes/instrument_drivers/Keithley/Keithley_7510.py | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py index 36b39c1f804..eaadc143053 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py @@ -698,6 +698,7 @@ def _set_sense_function(self, value: str) -> None: self.write( f":SENS:FUNC {value}", ) + assert self.sense_function.inverse_val_mapping is not None sense_function = self.sense_function.inverse_val_mapping[value] sense = self.submodules[f"_sense_{sense_function}"] if not isinstance(sense, Keithley2450Sense): @@ -728,8 +729,9 @@ def _set_source_function(self, value: str) -> None: ) self.write(f":SOUR:FUNC {value}") + assert self.source_function.inverse_val_mapping is not None source_function = self.source_function.inverse_val_mapping[value] - source = self.submodules[f"_source_{source_function}"] + source = cast(Keithley2450Source, self.submodules[f"_source_{source_function}"]) self.sense.sweep.setpoints = (source.sweep_axis,) if not isinstance(source, Keithley2450Source): raise RuntimeError( diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py index f31021a03e8..17aef17051e 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py @@ -3,6 +3,7 @@ import numpy as np from qcodes.instrument import ( + InstrumentBaseKWArgs, InstrumentChannel, VisaInstrument, VisaInstrumentKWArgs, @@ -455,7 +456,7 @@ def __init__( parent: VisaInstrument, name: str, proper_function: str, - **kwargs: "Unpack[VisaInstrumentKWArgs]", + **kwargs: "Unpack[InstrumentBaseKWArgs]", ) -> None: """ The sense module of the Keithley 7510 DMM, based on the sense module of From 5e6a02d277433a43227549b445d70f45d8916cae Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 May 2024 08:53:34 +0200 Subject: [PATCH 08/10] Reformat docstrings --- .../Keithley/Keithley_3706A.py | 22 +++++++++---------- .../Keithley/_Keithley_2600.py | 9 ++++++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py b/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py index 2e1f092be86..98afd7115db 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py @@ -65,21 +65,19 @@ def __init__( ), vals=vals.Enum("BREAK_BEFORE_MAKE", "MAKE_BEFORE_BREAK", "OFF"), ) - """Controls the connection rule for closing -and opening channels when using -`exclusive_close` and `exclusive_slot_close` -parameters. + """ + Controls the connection rule for closing and opening channels when using + `exclusive_close` and `exclusive_slot_close` + parameters. -If it is set to break before make, -it is ensured that all channels open -before any channels close. + If it is set to break before make, it is ensured that all channels open + before any channels close. -If it is set to make before break, it is -ensured that all channels close before any -channels open. + If it is set to make before break, it is ensured that all channels close + before any channels open. -If it is off, channels open and close -simultaneously.""" + If it is off, channels open and close simultaneously. + """ self.gpib_enabled: Parameter = self.add_parameter( "gpib_enabled", diff --git a/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py b/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py index 06f4c1562d9..d92f06a0398 100644 --- a/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py +++ b/src/qcodes/instrument_drivers/Keithley/_Keithley_2600.py @@ -484,7 +484,10 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: "set `sourcerange_v` instead", vals=vals.Enum(*vranges[self.model]), ) - """The range to perform voltage measurements in. This affects the range and the precision of the measurement. Note that if you both measure and source current this will have no effect, set `sourcerange_v` instead""" + """ + The range to perform voltage measurements in. This affects the range and the precision of the measurement. + Note that if you both measure and source current this will have no effect, set `sourcerange_v` instead + """ self.measure_autorange_v_enabled: Parameter = self.add_parameter( "measure_autorange_v_enabled", @@ -538,7 +541,9 @@ def __init__(self, parent: Instrument, name: str, channel: str) -> None: "`sourcerange_i` instead", vals=vals.Enum(*iranges[self.model]), ) - """The range to perform current measurements in. This affects the range and the precision of the measurement. Note that if you both measure and source current this will have no effect, set `sourcerange_i` instead""" + """ + The range to perform current measurements in. This affects the range and the precision of the measurement. + Note that if you both measure and source current this will have no effect, set `sourcerange_i` instead""" self.measure_autorange_i_enabled: Parameter = self.add_parameter( "measure_autorange_i_enabled", From 3c21546e744af84f3a32ebc039c58100f6379bc0 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 May 2024 08:58:07 +0200 Subject: [PATCH 09/10] Add changelog for 6115 --- docs/changes/newsfragments/6115.improved_driver | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/changes/newsfragments/6115.improved_driver diff --git a/docs/changes/newsfragments/6115.improved_driver b/docs/changes/newsfragments/6115.improved_driver new file mode 100644 index 00000000000..3b94746ce0c --- /dev/null +++ b/docs/changes/newsfragments/6115.improved_driver @@ -0,0 +1,6 @@ +The Keithley 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. From 00934db997b19476fbccb8404ae99af7ab621189 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 May 2024 15:53:40 +0200 Subject: [PATCH 10/10] Fixes from review --- src/qcodes/instrument_drivers/Keithley/Keithley_2400.py | 4 ++-- src/qcodes/instrument_drivers/Keithley/Keithley_2450.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2400.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2400.py index a1be6ff2bac..8dd162b4907 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2400.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2400.py @@ -143,11 +143,11 @@ def __init__( get_parser=self._resistance_parser, label="Resistance", unit="Ohm", - docstring="Measure resistance from current and voltage " + docstring="Measure resistance from current and voltage. " "Note that it is an error to read current " "and voltage with output off", ) - """Measure resistance from current and voltage Note that it is an error to read current and voltage with output off""" + """Measure resistance from current and voltage. Note that it is an error to read current and voltage with output off""" self.write(":TRIG:COUN 1;:FORM:ELEM VOLT,CURR") # This line sends 2 commands to the instrument: diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py index eaadc143053..2154fa6cb9d 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py @@ -315,11 +315,11 @@ def __init__(self, parent: "Keithley2450", name: str, proper_function: str) -> N get_cmd=f":SENSe:{self._proper_function}:AZERo?", set_cmd=f":SENSe:{self._proper_function}:AZERo {{}}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), - docstring="This command enables or disables automatic updates to" - "the internal reference measurements (autozero) of the" + docstring="This command enables or disables automatic updates to " + "the internal reference measurements (autozero) of the " "instrument.", ) - """This command enables or disables automatic updates tothe internal reference measurements (autozero) of theinstrument.""" + """This command enables or disables automatic updates to the internal reference measurements (autozero) of the instrument.""" self.count: Parameter = self.add_parameter( "count",