Source code for semi_cr.core.lab.instrument.dummy_d5a

from qcodes.instrument import Instrument
from qcodes.validators import Enum, Numbers

NUM_CHANNELS = 16

# Maps span name → (min_voltage, max_voltage), matching the real D5a driver.
SPAN_RANGES: dict[str, tuple[float, float]] = {
    "4v uni": (0.0, 4.0),
    "4v bi": (-4.0, 4.0),
    "2v bi": (-2.0, 2.0),
}
DEFAULT_SPAN = "4v bi"


[docs] class DummyD5a(Instrument): """ Dummy stand-in for the SPI Rack D5a 16-channel DAC module. Mirrors the interface of QCoDesD5a: channels and spans are accessed as QCoDeS parameters on ``driver`` (which returns self): driver.dac1 … driver.dac16 — voltage parameters (V) driver.span1 … driver.span16 — span parameters ('4v uni', '4v bi', '2v bi') Changing a span updates the corresponding dac validator, matching the behaviour of the real driver. Example: >>> d = DummyD5a("d5a_1") >>> d.driver.dac1(1.5) >>> d.driver.dac1() 1.5 >>> d.driver.span1("2v bi") # restrict channel 1 to ±2 V >>> d.driver.span1() '2v bi' """ def __init__(self, name: str, **kwargs): super().__init__(name, **kwargs) self._voltages = [0.0] * NUM_CHANNELS self._spans: list[str] = [DEFAULT_SPAN] * NUM_CHANNELS for i in range(NUM_CHANNELS): self.add_parameter( f"dac{i + 1}", unit="V", vals=Numbers(*SPAN_RANGES[DEFAULT_SPAN]), get_cmd=lambda i=i: self._voltages[i], set_cmd=lambda v, i=i: self._voltages.__setitem__(i, v), label=f"Channel {i + 1} voltage", ) self.add_parameter( f"span{i + 1}", initial_value=DEFAULT_SPAN, vals=Enum(*SPAN_RANGES.keys()), get_cmd=lambda i=i: self._spans[i], set_cmd=lambda span, i=i: self._set_span(i, span), label=f"Channel {i + 1} span", ) def _set_span(self, channel: int, span: str) -> None: self._spans[channel] = span getattr(self, f"dac{channel + 1}").vals = Numbers(*SPAN_RANGES[span]) @property def driver(self) -> "DummyD5a": """Return self so that d5a.driver.dacN() works identically to QCoDesD5a.""" return self
[docs] def get_idn(self) -> dict: return {"vendor": "Dummy", "model": "D5a", "serial": None, "firmware": None}