Jinja2 Templating#
The YAML files used to define labs, devices, experiments, and tasks support Jinja2 templating. This allows easier authoring of complex YAML files by enabling the use of variables, loops, conditionals, macros, and more. Jinja2 templates are evaluated with Python, so some expressions are the same as in Python.
Note
Jinja2 templates are evaluated during loading of the YAML file, not during runtime.
Jinja is useful for defining templates. For example, an experiment template can be defined with placeholders and variables that when specified lead to different variations of the experiment. This is particularly useful for altering the task sequence of an experiment while loading it.
Note
Experiment templating is useful if EOS dynamic parameters and references do not suffice.
Below are some useful Jinja2 features:
Variables#
Jinja2 allows setting and reading variables in the YAML file.
In the example below, the variable max_volume
is set to 300 and used to define the capacity of two beakers:
lab.yml
{% set max_volume = 300 %}
...
resource_types:
beaker:
meta:
capacity: {{ max_volume }}
resources:
{% for name in ["c_a", "c_b"] %}
{{ name }}:
type: beaker
{% endfor %}
Arithmetic#
You can perform arithmetic within Jinja2 expressions. In the example below, the volumes of cyan, magenta, and yellow colorants are calculated based on a total color volume:
task.yml
{% set total_color_volume = 100 %}
...
parameters:
cyan_volume: {{ total_color_volume * 0.6 }}
magenta_volume: {{ total_color_volume * 0.3 }}
yellow_volume: {{ total_color_volume * 0.1 }}
Conditionals#
You can use if statements to include or exclude content based on conditions.
In the example below, the task “mix_colors” is only included if the variable mix_colors
is set to True
:
experiment.yml
tasks:
{% if mix_colors %}
- name: mix_colors
type: Mix Colors
desc: Mix the colors in the container
# ... rest of the task definition
{% endif %}
Loops#
Jinja2 allows you to use loops to generate repetitive content. In the example below, a loop is used to generate container IDs with a common prefix and a letter (e.g., c_a, c_b, c_c, etc.):
lab.yml
resource_types:
beaker:
meta:
capacity: 300
resources:
{% for letter in ['a', 'b', 'c', 'd', 'e', 'f', 'g'] %}
c_{{ letter }}:
type: beaker
{% endfor %}
Macros#
Jinja2 macros allow you to define reusable blocks of content.
In the example below, the create_containers
macro is used to easily create containers with a prefix and a number
(e.g., c_0, c_1, c_2, etc.):
lab.yml
{% macro create_resources(res_type, capacity, id_prefix, count) -%}
resource_types:
{{ res_type }}:
meta:
capacity: {{ capacity }}
resources:
{%- for i in range(count) %}
{{ id_prefix }}{{ i }}:
type: {{ res_type }}
{%- endfor %}
{%- endmacro %}
{{ create_resources('beaker', 300, 'c_', 5) }}