Skip to content

Commit

Permalink
Merge pull request #6520 from simonschaal/ADD-Lakeshore-336-input-cur…
Browse files Browse the repository at this point in the history
…ve-query

Add curve header parameters to Lakeshore model 336, make group parameter take callable get_cmd
  • Loading branch information
astafan8 authored Oct 14, 2024
2 parents 3672568 + 5a2e4d8 commit c3f3d07
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 10 deletions.
40 changes: 40 additions & 0 deletions src/qcodes/instrument/sims/lakeshore_model336.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ devices:
setter:
q: "range A,\"{}\""

sensor_curve_number_A:
default: 42
getter:
q: "INCRV? A"
r: "{}"

curve_data_query_for_curve_42:
getter:
q: "CRVHDR? 42"
r: "DT-042,01110042,2,342.0,1"


temperature_B:
default: 100.0
Expand Down Expand Up @@ -96,7 +107,16 @@ devices:
setter:
q: "range A,\"{}\""

sensor_curve_number_B:
default: 41
getter:
q: "INCRV? B"
r: "{}"

curve_data_query_for_curve_41:
getter:
q: "CRVHDR? 41"
r: "DT-041,01110041,2,341.0,1"

temperature_C:
default: 100.0
Expand Down Expand Up @@ -140,7 +160,16 @@ devices:
setter:
q: "range A,\"{}\""

sensor_curve_number_C:
default: 40
getter:
q: "INCRV? C"
r: "{}"

curve_data_query_for_curve_40:
getter:
q: "CRVHDR? 40"
r: "DT-040,01110040,2,340.0,1"

temperature_D:
default: 100.0
Expand Down Expand Up @@ -184,6 +213,17 @@ devices:
setter:
q: "range A,\"{}\""

sensor_curve_number_D:
default: 39
getter:
q: "INCRV? D"
r: "{}"

curve_data_query_for_curve_39:
getter:
q: "CRVHDR? 39"
r: "DT-039,01110039,2,339.0,1"


resources:
GPIB::2::INSTR:
Expand Down
74 changes: 73 additions & 1 deletion src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_336.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import TYPE_CHECKING, ClassVar

import qcodes.validators as vals
from qcodes.parameters import Group, GroupParameter
from qcodes.parameters import Group, GroupParameter, Parameter

from .lakeshore_base import (
LakeshoreBase,
Expand Down Expand Up @@ -203,6 +203,78 @@ def __init__(
get_cmd=f"INTYPE? {self._channel}",
)

# Parameters related to temperature calibration curve (CRVHDR)
self.curve_number: Parameter = self.add_parameter(
"curve_number",
get_cmd=f"INCRV? {self._channel}",
set_cmd=False,
get_parser=int,
label="Temperature calibration curve number",
)
"""
Temperature calibration curve number that is selected now
"""
self.curve_name: GroupParameter = self.add_parameter(
"curve_name",
label="Temperature calibration curve name",
parameter_class=GroupParameter,
)
"""
Temperature calibration curve name
for the current curve as selected by ``curve_number``
"""
self.curve_sn: GroupParameter = self.add_parameter(
"curve_sn",
label="Temperature calibration curve SN",
parameter_class=GroupParameter,
)
"""
Temperature calibration curve SN
for the current curve as selected by ``curve_number``
"""
self.curve_format: GroupParameter = self.add_parameter(
"curve_format",
label="Temperature calibration curve format",
get_parser=int,
val_mapping={"mV/K": 1, "V/K": 2, "Ohms/K": 3, "log Ohms/K": 4},
parameter_class=GroupParameter,
)
"""
Temperature calibration curve format
for the current curve as selected by ``curve_number``
"""
self.curve_limit: GroupParameter = self.add_parameter(
"curve_limit",
get_parser=float,
label="Temperature calibration curve limit value",
parameter_class=GroupParameter,
)
"""
Temperature calibration curve limit value
for the current curve as selected by ``curve_number``
"""
self.curve_coefficient: GroupParameter = self.add_parameter(
"curve_coefficient",
get_parser=int,
label="Temperature calibration curve coefficient",
val_mapping={"negative": 1, "positive": 2},
parameter_class=GroupParameter,
)
"""
Temperature calibration curve coefficient
for the current curve as selected by ``curve_number``
"""
self.curve_parameters_group = Group(
[
self.curve_name,
self.curve_sn,
self.curve_format,
self.curve_limit,
self.curve_coefficient,
],
get_cmd=lambda: f"CRVHDR? {self.curve_number()}",
)


class LakeshoreModel336(LakeshoreBase):
"""
Expand Down
12 changes: 9 additions & 3 deletions src/qcodes/parameters/group_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,10 @@ def __init__(self, name, address, **kwargs):
set_cmd: Format string of the command that is used for setting the
values of the parameters; for example, ``CMD {a}, {b}``.
get_cmd: String of the command that is used for getting the values
of the parameters; for example, ``CMD?``.
of the parameters; for example, ``CMD?``. Can also be a callable
that returns a command string, this is useful for the cases where
the command string is dynamic; for example,
``lambda: f"CMD {get_id_that_specifies_the_command()} ?"``.
separator: A separator that is used when parsing the output of the
``get_cmd`` in order to obtain the values of the parameters; it
is ignored in case a custom ``get_parser`` is used.
Expand All @@ -168,7 +171,7 @@ def __init__(
self,
parameters: Sequence[GroupParameter],
set_cmd: str | None = None,
get_cmd: str | None = None,
get_cmd: str | Callable[[], str] | None = None,
get_parser: Callable[[str], Mapping[str, Any]] | None = None,
separator: str = ",",
single_instrument: bool = True,
Expand Down Expand Up @@ -309,7 +312,10 @@ def update(self) -> None:
f"parameters - {parameter_names} since it "
f"has no `get_cmd` defined."
)
ret = self.get_parser(self.instrument.ask(self._get_cmd))
get_command = (
self._get_cmd if isinstance(self._get_cmd, str) else self._get_cmd()
)
ret = self.get_parser(self.instrument.ask(get_command))
for name, p in list(self.parameters.items()):
p.cache._set_from_raw_value(ret[name])

Expand Down
2 changes: 1 addition & 1 deletion tests/drivers/test_lakeshore.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def ask_raw(self, cmd) -> Any:
self.visa_log.debug(f"Response: {response}")
return response
else:
super().ask_raw(cmd) # type: ignore[misc]
return super().ask_raw(cmd) # type: ignore[misc]


def query(name: str) -> Callable[[Callable[P, T]], Callable[P, T]]:
Expand Down
17 changes: 15 additions & 2 deletions tests/drivers/test_lakeshore_336.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ def __init__(self, *args, **kwargs) -> None:
auto_range_enabled=0, # 'off',
range=0,
compensation_enabled=0, # False,
units=1,
) # 'kelvin')
units=1, # 'kelvin'
)
for i in self.channel_name_command.keys()
}

Expand Down Expand Up @@ -259,6 +259,19 @@ def test_setpoint(lakeshore_336) -> None:
assert h.setpoint() == setpoint


def test_curve_parameters(lakeshore_336) -> None:
# The curve numbers are assigned in the simulation pyvisa sim
# YAML file for each sensor/channel, and properties of the
# curves also include curve number in them to help testing
for ch, curve_number in zip(lakeshore_336.channels, (42, 41, 40, 39)):
assert ch.curve_number() == curve_number
assert ch.curve_name().endswith(str(curve_number))
assert ch.curve_sn().endswith(str(curve_number))
assert ch.curve_format() == "V/K"
assert str(int(ch.curve_limit())).endswith(str(curve_number))
assert ch.curve_coefficient() == "negative"


def test_select_range_limits(lakeshore_336) -> None:
h = lakeshore_336.output_1
ranges = [1, 2, 3]
Expand Down
28 changes: 25 additions & 3 deletions tests/parameter/test_group_parameter.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import re
from datetime import datetime
from typing import Any
from typing import TYPE_CHECKING, Any

import pytest

from qcodes.instrument import Instrument
from qcodes.parameters import Group, GroupParameter

if TYPE_CHECKING:
from collections.abc import Callable


@pytest.fixture(autouse=True)
def close_all_instruments():
Expand All @@ -23,7 +26,7 @@ def __init__(
initial_a: int | None = None,
initial_b: int | None = None,
scale_a: float | None = None,
get_cmd: str | None = "CMD?",
get_cmd: "str | Callable[[], str] | None" = "CMD?",
) -> None:
super().__init__(name)

Expand Down Expand Up @@ -60,7 +63,9 @@ def write(self, cmd: str) -> None:
self._a, self._b = (int(i) for i in result.groups())

def ask(self, cmd: str) -> str:
assert cmd == self._get_cmd
assert self._get_cmd is not None
get_cmd = self._get_cmd if isinstance(self._get_cmd, str) else self._get_cmd()
assert cmd == get_cmd
return ",".join(str(i) for i in [self._a, self._b])


Expand All @@ -85,6 +90,23 @@ def test_sanity() -> None:
assert dummy.b() == 10


def test_get_cmd_being_a_callable_that_returns_a_string_works() -> None:
dummy = Dummy("dummy", get_cmd=lambda: "CMD?")

assert dummy.a() == 0
assert dummy.b() == 0

dummy.a(3)
dummy.b(6)

assert dummy.a() == 3
assert dummy.b() == 6

dummy.b(10)
assert dummy.a() == 3
assert dummy.b() == 10


def test_raise_on_get_set_cmd() -> None:
for arg in ["set_cmd", "get_cmd"]:
kwarg = {arg: ""}
Expand Down

0 comments on commit c3f3d07

Please sign in to comment.