Status Variables
When working with measurement modules (hardware/logic/GUI) you may want to preserve some variable values across consecutive runs of qudi.
We call measurement module instance variables that are automatically dumped/loaded upon deactivation/activation a “status variable”.
Base class will take care of dumping all status
variables upon deactivation of the module. This will happen
automatically at the end of on_deactivate and does NOT need to be
triggered explicitly in the on_deactivate method definition.on_deactivate raises an exception.⚠ WARNING:
Status variables will NOT be automatically saved if the measurement modules are not deactivated properly (i.e. by the module manager).This can happen for example if the user is just killing the qudi process instead of shutting it down as intended (e.g. by pressing the “stop” button in the PyCharm IDE).If this happens, the next startup of the modules will load the status variables from the last graceful deactivation.
on_activate is run,
status variables are read from disk and initialized in the module
instance. This means that on_activate can already use these
variables.on_activate.The status variables are stored in YAML format in one file per module
using the qudi utilities in qudi.util.yaml. They are stored in an OS
dependent qudi “AppData” directory.
Usage
In order to simplify the process of dumping/loading these variables
to/from disk and prevent each measurement module to implement their own
solution, qudi provides the meta object
qudi.core.statusvariable.StatusVar.
When implementing a measurement module
(hardware/logic/GUI) you can simply instantiate StatusVar class
variables. These meta objects will be transformed into regular variable
members of your measurement module instances and can be used like any
normal instance variable in Python:
from qudi.core.statusvariable import StatusVar
from qudi.core.module import LogicBase
class MyExampleLogic(LogicBase):
""" Module description goes here """
_my_status_variable = StatusVar(name='my_storage_name', default=42,)
...
def increment_my_variable(self):
self._my_status_variable += 1
...
constructor & representer
If your status variables should be of any other type, you need to
provide conversion functions to the StatusVar meta object: - The
constructor is a callable that accepts a simplified variable from
the YAML loader and returns the data as custom data type to initialize
the status variable with. - The representer is a callable that
accepts the custom status variable data and returns a simplified data
representation that is digestible by the YAML dumper.
You can provide constructor and representer callables as
arguments to StatusVar or you can register a callable member of your
module as such via decorators, e.g.:
from qudi.core.statusvariable import StatusVar
from qudi.core.module import LogicBase
class FancyDataType:
def __init__(self, a, b):
self.a = a
self.b = b
class MyExampleLogic(LogicBase):
""" Module description goes here """
_my_status_variable = StatusVar(default=FancyDataType(42, 3.1415))
_my_other_status_variable = StatusVar(
default=FancyDataType(1, 2),
constructor=lambda yaml_data: FancyDataType(*yaml_data),
representer=lambda data: [data.a, data.b]
)
...
@_my_status_variable.constructor
def my_status_variable_constructor(self, yaml_data):
return FancyDataType(*yaml_data)
@_my_status_variable.representer
def my_status_variable_constructor(self, data):
return [data.a, data.b]
...
Since these conversion functions are usually static (as the example
above also shows), you could also combine that with the
@staticmethod decorator. But this is not necessary and just good
style.
name
name argument for StatusVar. The name
given here is used by the YAML dumper as field name for the variable
data. So the name argument can be used to store the status
variable under a different (e.g. better readable) name in the app
status file that is created.