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:

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

SPEC vs BLISS

When restarting a SPEC session, 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
  • 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)

configuration behavior

Changing a configuration parameter, example of the velocity of a BlissAxis.

Changing a configuration parameter

Saving parameters

Example to save the velocity of an axis into YAML configuration file:

DEMO [1]: m1.config.set("velocity", 9)
DEMO [2]: m1.config.save()