Repository: QCoDeS/Qcodes
Pull request #5563 (2023-11-29 19:00:22)

Add pyvisa sim yaml file for RohdeSchwarz SGS100A
Adds a pyvisa sim yaml file for the RohdeSchwarz SGS100A driver.

Basic unit tests to validate each supported parameter has been included.


Patch:
diff --git a/src/qcodes/instrument/sims/RSSGS100A.yaml b/src/qcodes/instrument/sims/RSSGS100A.yaml
new file mode 100644
index 000000000..8b35ed6bf
--- /dev/null
+++ b/src/qcodes/instrument/sims/RSSGS100A.yaml
@@ -0,0 +1,174 @@
+# SIMULATED INSTRUMENT FOR Rohde&Schwarz SGS100A
+spec: "1.0"
+devices:
+  SGS100A:
+    eom:
+      GPIB INSTR:
+        q: "\n"
+        r: "\n"
+    error: ERROR
+    dialogues:
+      - q: "*IDN?"
+        r: "QCoDeS, SGS100A_simulated, simulated, 0.0.1"
+
+    properties:
+
+      state:
+        default: 0
+        getter:
+          q: "OUTPut:MASTer:STATe?"
+          r: "{}"
+        setter:
+          q: "OUTPut:MASTer:STATe {}"
+
+      frequency:
+        default: 1e6
+        getter:
+          q: "SOUR:FREQ?"
+          r: "{}"
+        setter:
+          q: "SOUR:FREQ {:.2f}"
+
+      phase:
+        default: 0
+        getter:
+          q: "SOUR:PHAS?"
+          r: "{}"
+        setter:
+          q: "SOUR:PHAS {:.2f}"
+
+      power:
+        default: 0
+        getter:
+          q: "SOUR:POW?"
+          r: "{}"
+        setter:
+          q: "SOUR:POW {:.2f}"
+
+      status:
+        default: 0
+        getter:
+          q: ":OUTP:STAT?"
+          r: "{}"
+        setter:
+          q: ":OUTP:STAT {}"
+
+      IQ_state:
+        default: 0
+        getter:
+          q: ":IQ:STAT?"
+          r: "{}"
+        setter:
+          q: ":IQ:STAT {}"
+
+      pulsemod_state:
+        default: 0
+        getter:
+          q: ":SOUR:PULM:STAT?"
+          r: "{}"
+        setter:
+          q: ":SOUR:PULM:STAT {}"
+
+      pulsemod_source:
+        default: "INT"
+        getter:
+          q: "SOUR:PULM:SOUR?"
+          r: "{}"
+        setter:
+          q: "SOUR:PULM:SOUR {}"
+
+      ref_osc_source:
+        default: "INT"
+        getter:
+          q: "SOUR:ROSC:SOUR?"
+          r: "{}"
+        setter:
+          q: "SOUR:ROSC:SOUR {}"
+
+      # Define LO source INT/EXT (Only with K-90 option)
+      LO_source:
+        default : "INT"
+        getter:
+          q: "SOUR:LOSC:SOUR?"
+          r: "{}"
+        setter:
+          q: "SOUR:LOSC:SOUR {}"
+
+      # Define output at REF/LO Output (Only with K-90 option)
+      ref_LO_out:
+        default: "OFF"
+        getter:
+          q: "CONN:REFL:OUTP?"
+          r: "{}"
+        setter:
+          q: "CONN:REFL:OUTP {}"
+
+      # Frequency mw_source outputs when used as a reference
+      ref_osc_output_freq:
+        default: "1000MHz"
+        getter:
+          q: "SOUR:ROSC:OUTP:FREQ?"
+          r: "{}"
+        setter:
+          q: "SOUR:ROSC:OUTP:FREQ {}"
+
+      ref_osc_external_freq:
+        default: "1000MHz"
+        getter:
+          q: "SOUR:ROSC:EXT:FREQ?"
+          r: "{}"
+        setter:
+          q: "SOUR:ROSC:EXT:FREQ {}"
+
+      # IQ impairments
+      IQ_impairments:
+        default: 0
+        getter:
+          q: ":SOUR:IQ:IMP:STAT?"
+          r: "{}"
+        setter:
+          q: ":SOUR:IQ:IMP:STAT {}"
+
+      I_offset:
+        default: 0
+        getter:
+          q: "SOUR:IQ:IMP:LEAK:I?"
+          r: "{}"
+        setter:
+          q: "SOUR:IQ:IMP:LEAK:I {:.2f}"
+
+      Q_offset:
+        default: 0
+        getter:
+          q: "SOUR:IQ:IMP:LEAK:Q?"
+          r: "{}"
+        setter:
+          q: "SOUR:IQ:IMP:LEAK:Q {:.2f}"
+
+      IQ_gain_imbalance:
+        default: 0
+        getter:
+          q: "SOUR:IQ:IMP:IQR?"
+          r: "{}"
+        setter:
+          q: "SOUR:IQ:IMP:IQR {:.2f}"
+
+      IQ_angle:
+        default: 0
+        getter:
+          q: "SOUR:IQ:IMP:QUAD?"
+          r: "{}"
+        setter:
+          q: "SOUR:IQ:IMP:QUAD {:.2f}"
+
+resources:
+  GPIB::1::INSTR:
+    device: SGS100A
+  GPIB::2::INSTR:
+    device: SGS100A
+  GPIB::3::INSTR:
+    device: SGS100A
+  GPIB::4::INSTR:
+    device: SGS100A
+  GPIB::5::INSTR:
+    device: SGS100A


Test patch:
diff --git a/tests/drivers/test_RS_SGS100A.py b/tests/drivers/test_RS_SGS100A.py
new file mode 100644
index 000000000..0200dae26
--- /dev/null
+++ b/tests/drivers/test_RS_SGS100A.py
@@ -0,0 +1,80 @@
+from collections.abc import Sequence
+from typing import Any
+
+import numpy as np
+import pytest
+
+from qcodes.instrument_drivers.rohde_schwarz.SGS100A import RohdeSchwarz_SGS100A
+
+
+@pytest.fixture(scope='function', name="sg")
+def _make_sg():
+    """
+    Create a RohdeSchwarz SGS100A instrument
+    """
+    driver = RohdeSchwarz_SGS100A(
+        "sgs100a", address="GPIB::1::INSTR", pyvisa_sim_file="RSSGS100A.yaml"
+    )
+    yield driver
+    driver.close()
+
+def verify_property(sg, param_name, vals : Sequence[Any]):
+    param = getattr(sg, param_name)
+    for val in vals:
+        param(val)
+        new_val = param()
+        if isinstance(new_val, float):
+            assert np.isclose(new_val, val)
+        else:
+            assert new_val == val
+
+def test_frequency(sg) -> None:
+    verify_property(sg, "frequency", [1e6, 2e6, 3e9, 20e9])
+
+def test_phase(sg) -> None:
+    verify_property(sg, "phase", [0, 45, 90, 180, 270, 359, 360])
+
+def test_power(sg) -> None:
+    verify_property(sg, "power", [-120, -50, 0, 10, 25])
+
+def test_status(sg) -> None:
+    verify_property(sg, "status", [True, False])
+
+def test_IQ_state(sg) -> None:
+    verify_property(sg, "IQ_state", [True, False])
+
+def test_pulsemod_state(sg) -> None:
+    verify_property(sg, "pulsemod_state", [True, False])
+
+def test_pulsemod_source(sg) -> None:
+    verify_property(sg, "pulsemod_source", ["INT", "EXT"])
+
+def test_ref_osc_source(sg) -> None:
+    verify_property(sg, "ref_osc_source", ["INT", "EXT"])
+
+def test_LO_source(sg) -> None:
+    verify_property(sg, "LO_source", ["INT", "EXT"])
+
+def test_ref_LO_out(sg) -> None:
+    verify_property(sg, "ref_LO_out", ["REF", "LO", "OFF"])
+
+def test_ref_osc_output_freq(sg) -> None:
+    verify_property(sg, "ref_osc_output_freq", ["10MHz", "100MHz", "1000MHz"])
+
+def test_ref_osc_external_freq(sg) -> None:
+    verify_property(sg, "ref_osc_external_freq", ["10MHz", "100MHz", "1000MHz"])
+
+def test_IQ_impairments(sg) -> None:
+    verify_property(sg, "IQ_impairments", [True, False])
+
+def test_I_offset(sg) -> None:
+    verify_property(sg, "I_offset", [-10, 0, 10])
+
+def test_Q_offset(sg) -> None:
+    verify_property(sg, "Q_offset", [-10, 0, 10])
+
+def test_IQ_gain_imbalance(sg) -> None:
+    verify_property(sg, "IQ_gain_imbalance", [-1, 0, 1])
+
+def test_IQ_angle(sg) -> None:
+    verify_property(sg, "IQ_angle", [-8, -4, 0, 4, 8])