Runcards
Writing python scripts to run experiments can be tedious, especially when you are doing many similar experiments with slight modifications. To aid in experiment building and documentation, the Empyric library allows one to define an experiment in the runcard format. Empyric can then parse the runcard and run the experiment. In addition to providing a convenient way to automate an experiment, the runcard also serves as easy to read documentation of the experiment.
The following is an example that can be found in the “examples” folder (“examples/Henon Map Experiment/henon_runcard_example.yaml”):
# Basic runcard describing an experiment that measures the x and y values of a Henon Map.
# To execute, run select_runcard.py in the examples directory,
# and then select this runcard from the file selection dialog.
Description:
name: Henon Map Experiment
operator: Mike
platform: Test Stand 1
comments: Who is Mike? There is no Test Stand 1
Settings:
follow-up: henon_runcard_example.yaml # experiment repeats ad infinitum
step interval: 0.5
plot interval: 5
save interval: 10
end: 60
# async: True
Instruments:
Henon Mapper:
type: HenonMapper
address: 1
presets:
a: 0
b: 0
postsets:
a: 0
b: 0
Variables:
Knob a:
instrument: Henon Mapper
knob: a
Knob a Setpoint:
parameter: 1.4
Knob b:
instrument: Henon Mapper
knob: b
Coordinate x:
instrument: Henon Mapper
meter: x
Coordinate y:
instrument: Henon Mapper
meter: y
Distance r:
expression: 'sqrt(x^2 + y^2)'
definitions:
x: Coordinate x
y: Coordinate y
Alarms:
r > 1:
condition: 'r > 1'
definitions:
r: Distance r
protocol: hold
Plots:
Henon Map:
x: Coordinate x
y: Coordinate y
xlabel: 'X'
ylabel: 'Y'
style: parametric
configure:
linestyle: None
marker: 'o'
markersize: 3
Y Plot:
x: Time
y: Coordinate y
Routines:
Ramp Knob a:
type: Ramp
knobs: Knob a
targets: Knob a Setpoint
rates: 0.7
start: 3
Ramp Knob b:
type: Timecourse
knobs: Knob b
times: [3, 5]
values: [0.0, 0.3]
The Description section contains the name of the experiment, name of the operator, where the experiment is taking place and any relevant comments for future reference. Technically, this section is optional, but it is good practice to fill it out for future reference.
Description:
name: (Unique name of the experiment; default = 'Experiment')
operator: (Name of person running the experiment)
platform: (Name of experimental apparatus)
comments: (Contextual information for the experiment)
The optional Settings section contains some global settings for the experiment. The follow-up entry allows one to chain experiments; simply give the path name to another experiment runcard here. The step interval defines the minimum time to take between experiment iterations. The save interval specifies how often to save the acquired experimental data. The plot interval sets a minimum time between updates to the plots specified in the Plots section. The end specifies when the experiment should terminate. if end is set to ‘with routines’, the experiment will terminate when the last routine finishes.
Settings: # All settings below are optional
follow-up: (None, 'Repeat', or 'another_experiment_runcard.yaml'; default = None)
step interval: (minimum time between experiment steps; default = 0.1 seconds)
save interval: (minimum time between data saves to file; default = 60 seconds)
plot interval: (minimum time between plotting operations; default = 0.1 seconds)
end: (maximum run time of the experiment; default = infinity)
The Instruments section is where you specify which instruments from Empyric’s collection the experiment will use (see Instruments for the full set of supported instruments). For each specification dictionary, the top level key is the name that you endow upon the instrument. Every instrument must have a unique name. The type is the type of instrument and the address is the properly formatted address of the instrument (something like “COM3” for a serial instrument at port 3 on a Windows machine). It is also possible to alter the instrument presets by assigning values to the corresponding variable names in the presets dictionary, as well as set the postsets in a similar way. Any additional entries are assumed to refer to adapter settings. For example, to change the baud rate of an instrument with a serial adapter to 19200, simply specify `baud rate: 19200.
Instruments:
(Unique Name for an Instrument)
type: (class name of instrument)
address: (address value used by the adapter to locate and connect the instrument)
presets: # optional
(knob name): (setting to apply to knob upon initialization of the instrument)
postsets: # optional
(knob name): (setting to apply to knob upon disconnection of the instrument)
(adapter parameter: value)
The Variables section defines the experiment variables in relation to the instruments. Each variable must have a unique name. The knob and meter type variables must be assigned an instrument as well as the name of the knob or meter of that instrument. The expression type variables are defined by a mathematical expression, using algebraic operations (+, -, *, /, ^) and the common functions (sin, exp, log, sum, etc.) that are built into or in the math module of Python. The symbols in the expression are defined by the definitions entry which maps those symbols to any variables defined above. All variable types can be hidden from view in the ExperimentGUI by setting the (optional) hidden entry to True.
Variables:
(Unique Name for a Knob Variable):
instrument: (Instrument Name)
knob: (instrument knob name)
(Unique Name for a Meter Variable):
instrument: (Instrument Name)
meter: (instrument meter name)
(Unique Name for an Expression Variable):
expression: (python interpretable expression, e.g. 'a + b')
definitions:
a: (Name of Other Variable)
b: (Name of Another Variable)
(character/string in the expression: referenced variable)
(Unique Name for a Parameter Variable):
parameter: (value, e.g. '3.141592653589793')
The optional Alarms section contains alarms which can monitor any of the variables and alert the user of any concerning conditions. Each alarm is defined by the variable(s) that it is monitoring, the condition to watch for and the protocol, which tells the experiment manager what to do when an alarm is triggered. Variables can be called out by their names in the condition, or by using aliases, which are defined in the optional definitions dictionary. Possible protocols include ‘hold’, ‘stop’ and ‘terminate’, each of which calls the corresponding method of the Experiment instance; for ‘hold’ and ‘stop’, the experiment manager resumes the experiment when the alarm is cleared. Another option is setting the protocol to another runcard, in which case the current experiment is terminated and the experiment or process defined in the new runcard is run.
Alarms:
(Name for Alarm):
condition: (python interpretable expression, e.g. 'a > b')
protocol: (action to take if condition evaluates to True)
definitions:
a: (Name of Other Variable)
b: (Name of Another Variable)
(character/string in the condition: referenced variable)
The optional Plots section defines how to present collected data. Each plot specification requires a y entry. If no x entry is given, it assumed that the x-axis will be time. The optional xlabel and ylabel entries specify how to label the corresponding axes. A style can be selected from ‘basic’ (default simple plot), ‘averaged’ (y values at the same x value are averaged together), ‘errorbars’ (same as averaged, but with error bars for the y values at the same x value), and ‘parametric’ (parametric plot with a third parametric variable specified by an optional ‘parameter’ entry; if no parameter is specified, time will be assumed). An optional ‘configure’ entry can be provided, which is just a dictionary of keyword arguments to be given to the Matplotlib.pyplot.plot method used to generate all plots.
Plots:
(Name for a Plot)
x: (Variable on the x-axis) # defaults to 'Time' is unspecified
y: (Variable on the y-axis)
s: (Parametric Variable) # only used for parametric plots
style: (plot style, e.g. 'parametric'). # defaults to 'basic' if unspecified
configure: (any other keyword arguments to pass to Matplotlib for plotting customization)
The optional Routines section defines how the experiment traverses parameter space. A routine (see available routines in Routines) sets its assigned knobs depending on the state of the experiment. In the example above, there are 2 routines, named ‘Ramp Parameter’ a and ‘Ramp Parameter b’, which are both of the Timecourse type. These Timecourse routines set the knob variables ‘Parameter a’ and ‘Parameter b’ to the values specified in the values entry at the times specified in the times entry. It is also possible to combine similar routines into a single routine. For example, the two routines in the above example can be combined into a single Timecourse routine that varies both of these parameters together:
Routines:
(Name of a Set Routine):
type: Set
knobs: (knob or list of knobs this routine controls)
values: (list of fixed values the knobs will be set to)
(Name of a Timecourse Routine):
type: Timecourse
knobs: (knob or list of knobs this routine controls)
times: (list or array of time points when knobs are set)
values: (list or array of values the knobs will be set to at the corresponding times)
(Name of a Sequence Routine):
type: Sequence
knobs: (knob or list of knobs this routine controls)
values: (list or array of values the knobs will be set to sequentially)
(Name of a Minimization or Maximization Routine):
type: ('Minimization' or 'Maximization')
knobs: (knob or list of knobs this routine controls)
meters: (meter or list of meters to be minimized or maximized)
# the sum will be minimized or maximized if a list of meters is given