egse.setup
Setup¶
This module defines the Setup, which contains the complete configuration information for a test.
The Setup class contains all configuration items that are specific for a test or observation and is normally (during nominal operation/testing) loaded automatically from the configuration manager. The Setup includes type and identification of hardware that is used, calibration files, software versions, reference frames and coordinate systems that link positions of alignment equipment, conversion functions for temperature sensors, etc.
The configuration information that is in the Setup can be navigated in two different ways. First, the Setup is a dictionary, so all information can be accessed by keys as in the following example.
>>> setup = Setup({"gse": {"hexapod": {"ID": 42, "calibration": [0,1,2,3,4,5]}}})
>>> setup["gse"]["hexapod"]["ID"]
42
Second, each of the keys is also available as an attribute of the Setup and that make it possible to navigate the Setup with dot-notation:
>>> id = setup.gse.hexapod.ID
In the above example you can see how to navigate from the setup to a device like the PUNA Hexapod.
The Hexapod device is connected to the control server and accepts commands as usual. If you want to
know which keys you can use to navigate the Setup, use the keys()
method.
>>> setup.gse.hexapod.keys()
dict_keys(['ID', 'calibration'])
>>> setup.gse.hexapod.calibration
[0, 1, 2, 3, 4, 5]
To get a full printout of the Setup, you can use the pretty_str()
method. Be careful, because
this can print out a lot of information when a full Setup is loaded.
>>> print(setup)
Setup
└── gse
└── hexapod
├── ID: 42
└── calibration: [0, 1, 2, 3, 4, 5]
Special Values¶
Some of the information in the Setup is interpreted in a special way, i.e. some values are processed before returning. Examples are the device classes and calibration/data files. The following values are treated special if they start with:
class//
: instantiate the class and return the objectfactory//
: instantiates a factory and executes itscreate()
methodcsv//
: load the CSV file and return a numpy arrayyaml//
: load the YAML file and return a dictionarypandas//
: load a CSV file into a pandas Dataframeint-enum//
: dynamically create the enumeration and return the Enum object
Device Classes¶
Most of the hardware components in the Setup will have a device
key that defines the class for
the device controller. The device
keys have a value that starts with class//
and it will
return the device object. As an example, the following defines the Hexapod device:
>>> setup = Setup(
... {
... "gse": {
... "hexapod": {"ID": 42, "device": "class//egse.hexapod.symetrie.puna.PunaSimulator"}
... }
... }
... )
>>> setup.gse.hexapod.device.is_homing_done()
False
>>> setup.gse.hexapod.device.info()
'Info about the PunaSimulator...'
In the above example you see that we can call the is_homing_done()
and info()
methodes
directly on the device by navigating the Setup. It would however be better (more performant) to
put the device object in a variable and work with that variable:
>>> hexapod = setup.gse.hexapod.device
>>> hexapod.homing()
>>> hexapod.is_homing_done()
True
>>> hexapod.get_user_positions()
If you need, for some reason, to have access to the actual raw value of the hexapod device key,
use the get_raw_value()
method:
>>> setup.gse.hexapod.get_raw_value("device")
<egse.hexapod.symetrie.puna.PunaSimulator object at ...
Data Files¶
Some information is too large to add to the Setup as such and should be loaded from a data file. Examples are calibration files, flat-fields, temperature conversion curves, etc.
The Setup will automatically load the file when you access a key that contains a value that
starts with csv//
or yaml//
.
>>> setup = Setup({
... "instrument": {"coeff": "csv//cal_coeff_1234.csv"}
... })
>>> setup.instrument.coeff[0, 4]
5.0
Note: the resource location is always relative to the path defined by the PROJECT_CONF_DATA_LOCATION environment variable.
The Setup inherits from a NavigableDict (aka navdict) which is also defined in this module.
Classes:
Name | Description |
---|---|
Setup |
The Setup class represents a version of the configuration of the test facility, the |
SetupError |
A setup-specific error. |
Functions:
Name | Description |
---|---|
get_setup |
Retrieve the currently active Setup from the configuration manager. |
list_setups |
This is a function to be used for interactive use, it will print to the terminal (stdout) a |
load_last_setup_id |
Returns the ID of the last Setup that was used by the configuration manager. |
load_setup |
This function loads the Setup corresponding with the given |
save_last_setup_id |
Makes the given Setup ID persistent, so it can be restored upon the next startup. |
submit_setup |
Submit the given Setup to the Configuration Manager. |
Attributes:
Name | Type | Description |
---|---|---|
navdict |
Shortcut for NavigableDict and more Pythonic. |
NavigableDict
¶
NavigableDict(head=None, label=None)
Bases: dict
A NavigableDict is a dictionary where all keys in the original dictionary are also accessible
as attributes to the class instance. So, if the original dictionary (setup) has a key
"site_id" which is accessible as setup['site_id']
, it will also be accessible as
setup.site_id
.
Examples:
>>> setup = NavigableDict({'site_id': 'KU Leuven', 'version': "0.1.0"})
>>> assert setup['site_id'] == setup.site_id
>>> assert setup['version'] == setup.version
Note
We always want all keys to be accessible as attributes, or none. That means all
keys of the original dictionary shall be of type str
.
label (str): a label or name that is used when printing the navdict
Methods:
Name | Description |
---|---|
add |
Set a value for the given key. |
get_private_attribute |
Returns the value of the given private attribute. |
get_raw_value |
Returns the raw value of the given key. |
has_private_attribute |
Check if the given key is defined as a private attribute. |
pretty_str |
Returns a pretty string representation of the dictionary. |
set_private_attribute |
Sets a private attribute for this object. |
add
¶
add(key, value)
Set a value for the given key.
If the value is a dictionary, it will be converted into a NavigableDict and the keys will become available as attributes provided that all the keys are strings.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key
|
str
|
the name of the key / attribute to access the value |
required |
value
|
Any
|
the value to assign to the key |
required |
get_private_attribute
¶
get_private_attribute(key)
Returns the value of the given private attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key
|
str
|
the name of the private attribute (must start with an underscore character). |
required |
Returns:
Type | Description |
---|---|
Any
|
the value of the private attribute given in |
Note
Because of the implementation, this private attribute can also be accessed as a 'normal' attribute of the object. This use is however discouraged as it will make your code less understandable. Use the methods to access these 'private' attributes.
get_raw_value
¶
get_raw_value(key)
Returns the raw value of the given key.
Some keys have special values that are interpreted by the AtributeDict class. An example is a value that starts with 'class//'. When you access these values, they are first converted from their raw value into their expected value, e.g. the instantiated object in the above example. This method allows you to access the raw value before conversion.
has_private_attribute
¶
has_private_attribute(key)
Check if the given key is defined as a private attribute.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key
|
str
|
the name of a private attribute (must start with an underscore) |
required |
pretty_str
¶
pretty_str(indent=0)
Returns a pretty string representation of the dictionary.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
indent
|
int
|
number of indentations (of four spaces) |
0
|
Note
The indent argument is intended for the recursive call of this function.
set_private_attribute
¶
set_private_attribute(key, value)
Sets a private attribute for this object.
The name in key will be accessible as an attribute for this object, but the key will not be added to the dictionary and not be returned by methods like keys().
The idea behind this private attribute is to have the possibility to add status information or identifiers to this classes object that can be used by save() or load() methods.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key
|
str
|
the name of the private attribute (must start with an underscore character). |
required |
value
|
the value for this private attribute |
required |
Examples:
>>> setup = NavigableDict({'a': 1, 'b': 2, 'c': 3})
>>> setup.set_private_attribute("_loaded_from_dict", True)
>>> assert "c" in setup
>>> assert "_loaded_from_dict" not in setup
>>> assert setup.get_private_attribute("_loaded_from_dict") == True
Setup
¶
Setup(nav_dict=None, label=None)
Bases: NavigableDict
The Setup class represents a version of the configuration of the test facility, the test setup and the Camera Under Test (CUT).
Methods:
Name | Description |
---|---|
find_devices |
Returns a dictionary with the devices that are included in the setup. The keys |
from_dict |
Create a Setup from a given dictionary. |
from_yaml_file |
Loads a Setup from the given YAML file. |
from_yaml_string |
Loads a Setup from the given YAML string. |
get_filename |
Returns the filename for this Setup or None when no filename could be determined. |
get_id |
Returns the Setup ID (as a string) or None when no setup id could be identified. |
to_yaml_file |
Saves a NavigableDict to a YAML file. |
walk |
Walk through the given dictionary, in a recursive way, appending the leaf with |
find_devices
staticmethod
¶
find_devices(node, devices=None)
Returns a dictionary with the devices that are included in the setup. The keys in the dictionary are taken from the "device_name" entries in the setup file. The corresponding values in the dictionary are taken from the "device" entries in the setup file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
node
|
NavigableDict
|
Dictionary in which to look for the devices (and their names). |
required |
devices
|
dict
|
Dictionary in which to include the devices in the setup. |
None
|
Returns:
Type | Description |
---|---|
dict
|
Dictionary with the devices that are included in the setup. |
from_dict
staticmethod
¶
from_dict(my_dict)
Create a Setup from a given dictionary.
Remember that all keys in the given dictionary shall be of type 'str' in order to be accessible as attributes.
Examples:
>>> setup = Setup.from_dict({"ID": "my-setup-001", "version": "0.1.0"})
>>> assert setup["ID"] == setup.ID == "my-setup-001"
from_yaml_file
cached
staticmethod
¶
from_yaml_file(filename=None, add_local_settings=True)
Loads a Setup from the given YAML file.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
filename
|
str
|
the path of the YAML file to be loaded |
None
|
add_local_settings
|
bool
|
if local settings shall be loaded and override the settings from the YAML file. |
True
|
Returns:
Type | Description |
---|---|
a Setup that was loaded from the given location. |
from_yaml_string
staticmethod
¶
from_yaml_string(yaml_content=None)
Loads a Setup from the given YAML string.
This method is mainly used for easy creation of Setups from strings during unit tests.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
yaml_content
|
str
|
a string containing YAML |
None
|
Returns:
Type | Description |
---|---|
a Setup that was loaded from the content of the given string. |
get_filename
¶
get_filename()
Returns the filename for this Setup or None when no filename could be determined.
to_yaml_file
¶
to_yaml_file(filename=None)
Saves a NavigableDict to a YAML file.
When no filename is provided, this method will look for a 'private' attribute
_filename
and use that to save the data.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
filename
|
str | Path
|
the path of the YAML file where to save the data |
None
|
Note
This method will overwrite the original or given YAML file and therefore you might lose proper formatting and/or comments.
walk
staticmethod
¶
walk(node, key_of_interest, leaf_list)
Walk through the given dictionary, in a recursive way, appending the leaf with the given keyword to the given list.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
node
|
dict
|
Dictionary in which to look for leaves with the given keyword. |
required |
key_of_interest
|
Key to look for in the leaves of the given dictionary. |
required | |
leaf_list
|
List to which to add the leaves with the given keyword. |
required |
Returns:
Type | Description |
---|---|
list
|
Given list with the leaves (with the given keyword) in the given dictionary appended to it. |
SetupError
¶
Bases: Exception
A setup-specific error.
disentangle_filename
¶
disentangle_filename(filename)
Returns the site_id and setup_id (as a tuple) that is extracted from the Setups filename.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
filename
|
str
|
the filename or fully qualified file path as a string. |
required |
Returns:
Type | Description |
---|---|
tuple
|
A tuple (site_id, setup_id). |
get_last_setup_id_file_path
¶
get_last_setup_id_file_path(site_id=None)
Return the fully expanded file path of the file containing the last loaded Setup in the configuration manager. The default location for this file is the data storage location.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
site_id
|
str
|
The SITE identifier (overrides the SITE_ID environment variable) |
None
|
get_path_of_setup_file
¶
get_path_of_setup_file(setup_id, site_id)
Returns the Path to the last Setup file for the given site_id. The last Setup file is the file with the largest setup_id number.
This function needs the environment variable
Parameters:
Name | Type | Description | Default |
---|---|---|---|
setup_id
|
int
|
the identifier for the requested Setup |
required |
site_id
|
str
|
the test house name, one of CSL, SRON, IAS, INTA |
required |
Returns:
Type | Description |
---|---|
Path
|
The full path to the requested Setup file. |
Raises:
Type | Description |
---|---|
LookupError
|
when the environment variable is not set. |
NotADirectoryError
|
when either the repository folder or the Setups folder doesn't exist. |
FileNotFoundError
|
when no Setup file can be found for the given arguments. |
get_setup
¶
get_setup(setup_id=None)
Retrieve the currently active Setup from the configuration manager.
When a setup_id is provided, that setup will be returned, but not loaded in the configuration manager. This function does NOT change the configuration manager.
This function is for interactive use and consults the configuration manager server. Don't use
this within the test script, but use the GlobalState.setup
property instead.
list_setups
¶
list_setups(**attr)
This is a function to be used for interactive use, it will print to the terminal (stdout) a list of Setups known at the Configuration Manager. This list is sorted with the most recent ( highest) value last.
The list can be restricted with key:value pairs (keyword arguments). This search mechanism allows us to find all Setups that adhere to the key:value pairs, e.g. to find all Setups for CSL at position 2, use:
>>> list_setups(site_id="CSL", position=2)
To have a nested keyword search (i.e. search by gse.hexapod.ID
) then pass in
gse__hexapod__ID
as the keyword argument. Replace the '.' notation with double underscores
'__'.
>>> list_setups(gse__hexapod__ID=4)
load_last_setup_id
¶
load_last_setup_id(site_id=None)
Returns the ID of the last Setup that was used by the configuration manager. The file shall only contain the Setup ID which must be an integer on the first line of the file. If no such ID can be found, the Setup ID = 0 will be returned.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
site_id
|
str
|
The SITE identifier |
None
|
load_setup
¶
load_setup(setup_id=None, site_id=None, from_disk=False)
This function loads the Setup corresponding with the given setup_id
.
Loading a Setup means:
- that this Setup will also be loaded and activated in the configuration manager,
- that this Setup will be available from the
GlobalState.setup
When no setup_id is provided, the current Setup is loaded from the configuration manager.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
setup_id
|
int
|
the identifier for the Setup |
None
|
site_id
|
str
|
the name of the test house |
None
|
from_disk
|
bool
|
True if the Setup needs to be loaded from disk |
False
|
Returns:
Type | Description |
---|---|
Setup
|
The requested Setup or None when the Setup could not be loaded from the configuration manager. |
save_last_setup_id
¶
save_last_setup_id(setup_id, site_id=None)
Makes the given Setup ID persistent, so it can be restored upon the next startup.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
setup_id
|
int | str
|
The Setup identifier to be saved |
required |
site_id
|
str
|
The SITE identifier |
None
|
submit_setup
¶
submit_setup(setup, description)
Submit the given Setup to the Configuration Manager.
When you submit a Setup, the Configuration Manager will save this Setup with the
next (new) setup id and make this Setup the current Setup in the Configuration manager
unless you have explicitly set replace=False
in which case the current Setup will
not be replaced with the new Setup.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
setup
|
Setup
|
a (new) Setup to submit to the configuration manager |
required |
description
|
str
|
one-liner to help identifying the Setup afterwards |
required |
Returns:
Type | Description |
---|---|
str | None
|
The Setup ID of the newly created Setup or None. |