YAML files
The path specified with --db-path
on the beacon server command line
points to the root directory of the configuration database.
Beacon uses plain text files in YAML format (with .yml
extension) to describe the set of objects representing a BLISS system.
The idea is to have a centralized configuration database per beamline.
Info
YAML has been chosen because the standard native types (list, dictionary, numbers, unicode strings…) can be easily mapped to Python equivalents. It handles comments (contrary to JSON) and is optimized for human-readability (contrary to XML).
Beacon goes all over the configuration database directories, and builds an internal representation of the objects that are defined in YAML mapping nodes from the files. Ultimately this structure is flattened and exposed as a Python dictionary with key-value pairs, keys being object names and values being the corresponding configuration information.
YAML items¶
A YAML item is a key-value pair, using key: value
syntax. A YAML mapping
is a set of YAML items:
# example YAML mapping node with 3 nodes
example_key: 1 #float value
example_key2: ['a', 'b', 'c'] # list value
example_key3: a string #string value
Info
An online YAML parser can help finding YAML syntax errors.
Beacon YAML references¶
In a Beacon YAML file, an already defined object can be referenced using the ‘$’ character as a prefix.
$front_blade
refers to the object named front_blade
.
As a real example, here are defined ‘slits’ ie. calculational motors based on
real axes. The references to the real axes are denoted by the $
character.
-
controller:
class: slits
name: secondary_slits
axes:
-
name: $ssf <---------- A reference to existing 'ssf' axis,
tags: real front <---- has got the role of *real front* axis.
-
name: $ssb
tags: real back
-
name: sshg <------------ The (new) virtual axis 'sshg',
tags: hgap <------- is the *horizontal gap* axis.
tolerance: 0.04
Definition of a Beacon object¶
A Beacon object is simply defined by creating a name
item within a YAML mapping:
# example BLISS object
name: my_bliss_object
param1: 42
param2: example string
Warning
name items values must be unique for the whole configuration
Multiple objects can be defined in one file by using the YAML list notation -
to declare a sequence of mappings:
# example of multiple objects
- name: object1
param1: ...
...
- name: object2
param1: ...
...
Note
Files are transparent
- for each mapping defined in the configuration, Beacon is only sensitive
to the presence of a
name
key - multiple files are just a convenient way of grouping related objects within a container
Tree structure¶
Directories¶
Contrary to files, directories play a role in the organization of the configuration database. Beacon’s internal tree structure mirrors the file-system directories.
The following database files:
beamline_configuration/
└── directory_1
└── file_1.yml
# file_1.yml contents:
-
name: object_1
param: 42
-
name: object_2
param: 43
Produce the following internal representation:
>>> from bliss.config.static import get_config
>>> config = get_config() # loads YAML tree from Beacon server,
# and parse it to create a 'config' object
>>> config.pprint()
{ filename: None
directory_1:
[
{ filename: 'directory_1/file_1.yml'
name: object_1
param: 42
},
{ filename: 'directory_1/file_1.yml'
name: object_2
param: 43
}
]
}
>>> config.names_list # get existing names from config
['object_1', 'object_2']
Each YAML mapping is attached to a parent node. In this case, the parent
node of the two mappings defined in file_1.yml
is directory_1
.
__init__.yml
files¶
It is possible to associate mappings to a directory itself by adding a
__init__.yml
file.
This can be used to define global items, with a scope limited to their children:
beamline_configuration/
└── directory_1
└── file_1.yml
└── __init__.yml
# __init__.yml file contents
my_global: hello
>>> config.reload() # since the files changed, reload all config from server
>>> object_1 = config.get("object_1") #indexing by name (flattened dictionary)
>>> object_1.get_inherited("my_global")
hello
root config file¶
Root __init__.yml
is located and can be used to setup “global” configuration info.
It can be used for example to:
- configure the data policy.
- define a global name like the instrument name
See here: to read Root __init__.yml
from a BLISS controller
Configuration behavior¶
Unlike in a SPEC session restart, where all the config was reloaded and parameters taken into account automatically, for performance considerations, in BLISS:
- the config is reloaded:
- on-demand:
config.reload()
- at the (re)start of a session
- on-demand:
- the parameters from config of an object are taken into account:
- at first start of a session
- on demand with
obj.apply_config()
- it is possible to mix both reload and apply with:
obj.apply_config(reload=True)
Changing a configuration parameter, example of the velocity of a BlissAxis.