This page was generated from docs/examples/writing_drivers/abstract_instruments.ipynb. Interactive online version: Binder badge.

Abstract Instruments and parameters

Abstract parameters allow us to create abstract instrument types which are guaranteed to have certain parameters present. For instance, this will allow us to create a unified interface for all voltage sources.

Note: An instrument which contains abstract parameters shall be called an ‘Abstract Instrument’

[1]:
from qcodes import Instrument
Logging hadn't been started.
Activating auto-logging. Current session state plus future input saved.
Filename       : /home/runner/.qcodes/logs/command_history.log
Mode           : append
Output logging : True
Raw input log  : False
Timestamping   : True
State          : active
Qcodes Logfile : /home/runner/.qcodes/logs/220701-20468-qcodes.log
[2]:
class BaseVoltageSource(Instrument):
    """
    All abstract parameters *must* be implemented
    before this class can be initialized. This
    allows us to enforce an interface.
    """

    def __init__(self, name: str):
        super().__init__(name)

        self.add_parameter("voltage", unit="V", abstract=True)

        self.add_parameter("current", unit="A", get_cmd=None, set_cmd=None)

We cannot instantiate a Instrument with abstract parameters.

[3]:
try:
    bv = BaseVoltageSource("name")
except NotImplementedError as error:
    print(f"Error: {error}")
Error: <BaseVoltageSource: name> has un-implemented Abstract Parameter and cannot be initialized

Instruments which fail to initialize are not registered:

[4]:
BaseVoltageSource.instances()
[4]:
[]

Units of parameters defined in sub classes must match units defined in the base class

[5]:
class WrongSource2(BaseVoltageSource):
    """
    We implement the voltage paramter with the wrong unit
    """

    def __init__(self, name: str, *args, **kwargs):
        super().__init__(name, *args, **kwargs)

        self.add_parameter("voltage", unit="mV")
[6]:
try:
    WrongSource2("name4")
except ValueError as error:
    print(f"Error: {error}")
Error: The unit of the parameter 'voltage' is 'mV'. This is inconsistent with the unit defined in the base class

Instruments which fail to initialize due to the wrong unit are also not registered:

[7]:
BaseVoltageSource.instances()
[7]:
[]

Working subclass

[8]:
class VoltageSource(BaseVoltageSource):
    """
    We implement the voltage paramter with the correct unit.
    Here we just implement it as a manual parameter but in a
    real instrument we would probably not do that.
    """

    def __init__(self, name: str, *args, **kwargs):
        super().__init__(name, *args, **kwargs)

        self.add_parameter("voltage", unit="V", set_cmd=None, get_cmd=None)
[9]:
vs = VoltageSource("name")
[10]:
vs.voltage(1)
[11]:
vs.voltage()
[11]:
1

This instrument is registered as expected.

[12]:
VoltageSource.instances()
[12]:
[<VoltageSource: name>]