Configuration Options
When working with measurement modules (hardware/logic/GUI) you may want to give the user the opportunity to statically configure certain aspects of the measurement module.
options property for each measurement
module.A measurement module constant that is automatically initialized from the qudi configuration is called a “configuration option” or “config option”.
⚠ WARNING:
Config options are initialized only ONCE during instantiation of a measurement module and NOT every time the module is activated.So it is good practice to keep config option data members constant during runtime.
Usage
In order to simplify and automate the process of initializing these data
members and prevent each measurement module to implement their own
solution, qudi provides the meta object
qudi.core.configoption.ConfigOption.
When implementing a measurement module
(hardware/logic/GUI) you can simply instantiate ConfigOption 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.configoption import ConfigOption
from qudi.core.module import LogicBase
class MyExampleLogic(LogicBase):
""" Module description goes here """
_my_config_option = ConfigOption(name='my_config_option',
default='Not configured',
missing='warn')
...
def print_my_config_option(self):
print(self._my_config_option)
...
The corresponding module section in the config file would look like:
global:
...
gui:
...
hardware:
...
logic:
example_logic_identifier_name:
module.Class: my_example_logic.MyExampleLogic
options:
my_config_option: 'I am a string from the qudi configuration'
connect:
...
...
name
Please note here that the variable name in the measurement module
definition is _my_config_option, while the name given in the config
file is my_config_option (without underscore). This is possible
because of the optional name argument of ConfigOption. This
argument specifies the field name of the config option in the qudi
configuration and can be any YAML-compatible string as long as it is
unique within a measurement module.
default
default value for the
config option. If you specify a default value, this config option is
considered optional, i.e. if you do not provide the config option via
qudi configuration, it will be initialized to this default value
instead.default argument) will
cause the measurement module to raise an exception during
initialization if the corresponding field is not specified in the qudi
configuration.missing
missing argument can be used to define the behaviour
in case the config option is missing from the configuration and has a
default value. Ignored for non-optional config options.value |
effect |
|---|---|
|
Silently use the default value. |
|
Use default value but also logs an info message about the missing config option. |
|
Use default value but also logs a warning about the missing config option. |
|
Fail to initialize the module with an exception. Same as for non-optional config options. |
checker
checker argument of ConfigOption.True) or not.constructor
Since config options must be provided via YAML format you are limited in what data types can be configured. The qudi YAML loader currently supports any native Python builtin type and numpy arrays.
constructor function to the ConfigOption meta object.constructor argument to
ConfigOption or you can register a callable member of your
measurement module as such via decorator, e.g.:from qudi.core.configoption import ConfigOption
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_config_option = ConfigOption(name='my_config_option')
_my_other_config_option = ConfigOption(name='my_other_config_option',
constructor=lambda yaml_data: FancyDataType(*yaml_data))
...
@_my_config_option.constructor
def my_config_option_constructor(self, yaml_data):
return FancyDataType(*yaml_data)
...
Since the constructor function is usually static (as the example
above also shows), you could combine that with the @staticmethod
decorator. But this is not necessary and just good style.