Function plugins
Defines a plugin architecture so that new functions can be defined at runtime
and made available to the FunctionFactoryBase
used in the GUI to list available functions, and for analysis.
ceed.function.register_all_functions() is called by the GUI and it
registers any plugin functions with the
ceed.function.FunctionFactoryBase used by the GUI for managing
functions. ceed.function.register_all_functions() internally calls
get_plugin_functions() to get all the functions exported by all the
Python plugin module files in the ceed/function/plugin directory and
registers them with the ceed.function.FunctionFactoryBase.
Additionally, if the user provides a package name in the
external_function_plugin_package configuration
variable, the GUI will similarly import and register the plugins in
that package with ceed.function.register_external_functions().
The package must however be a proper python package that can be imported.
E.g. if external_function_plugin_package
is my_ceed_plugin.func, Ceed will try something roughly like
from my_ceed_plugin.func import get_ceed_functions.
Files in ceed/function/plugin that want to define new function or function
distribution classes should define a function in the file called
get_ceed_functions or get_ceed_distributions, respectively, that
returns a list of functions or function distributions that will be
automatically registered with the function factory
FunctionFactoryBase or
param_noise_factory, respectively,
using register() or
register_class().
To write a plugin, familiarize yourself with
FuncBase, it’s properties, and relevant methods that
need to be overridden. CeedFunc is the actual class
to inherit from. Some relevant methods are
get_gui_props(),
get_state(),
get_noise_supported_parameters(),
get_prop_pretty_name(),
init_func_tree(),
init_func(),
init_loop_iteration(),
get_relative_time(), and
resample_parameters().
__call__() is how the function is called. It
takes the time in global time so it should convert it to function local time
with get_relative_time() and then return the
function value.
See the ceed/function/plugin/__init__.py file and
get_ceed_functions() and get_ceed_distributions() for an example
plugin.
- ceed.function.plugin.get_plugin_functions(function_factory: ceed.function.FunctionFactoryBase, base_package: str, root: Union[str, pathlib.Path]) Tuple[List[Type[ceed.function.FuncType]], List[Type[ceed.function.param_noise.NoiseType]], List[Tuple[Tuple[str], bytes]]]
 Imports all the
.pyfiles in the given directory and sub-directories for the named package that don’t start with a underscore (except for__init__.pyof course, which is imported). For each imported module, it calls itsget_ceed_functionsandget_ceed_distributionsfunction (if they are defined in the module) which should return a list (that can be empty) of all the function and function distribution classes, respectively, exported by the module.It then returns all these exported functions, distributions, and all the file contents in the folder.
Ceed will automatically import all the plugins under
ceed/function/plugin.- Parameters
 function_factory – The
FunctionFactoryBaseinstance with which the returned plugin functions will be registered.base_package – The package name from which the plugins will be imported. E.g. to import the plugins in
ceed/function/plugin,base_packageisceed.function.pluginbecause that’s the package containing name for theplugindirectory. Then, they are imported asceed.function.pluginandceed.function.plugin.xyz, if the plugin directory also contains axyz.pyplugin file.root – The full directory path that contains the plugins. E.g. for
ceed.function.pluginit isceed/function/plugin.
- Returns
 A tuple with three values containing: a list of function classes exported by all the modules, a list of distribution classes exported by all the modules, and a list containing all the python files contents encountered in the directory.
The python files contents are returned so that Ceed can store it in the data files in case the plugins are changed between experimental runs.
See
get_ceed_functions(),get_ceed_distributions(), andregister_all_functions()for an example how it’s used.
- class ceed.function.plugin.ConstFunc(name='Const', description='y(t) = a', **kwargs)
 Bases:
ceed.function.CeedFuncDefines a function which returns a constant value.
The function is defined as
y(t) = a.- a
 The amplitude value of the function.
- get_gui_props()
 Called internally by the GUI to get the properties of the function that should be displayed to the user to be customized.
- Returns
 A dict that contains all properties that should be displayed. The values of the property is as follows:
If it’s the string int, float, str or it’s the python type int, float, or str then the GUI will show a editable property for this type.
If it’s None, we look at the value of the property in the instance and display accordingly (e.g. if it’s a str type property, a string property is displayed to the user).
Note
The default value determines the type. So if the default value is
0, the type will be int and a user won’t be able to enter a float. Use e.g.0.0in the latter case.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_gui_props() {'A': None, 'duration': None, 'f': None, 'loop': None, 'name': None, 't_offset': None, 'th0': None}
- get_state(*largs, **kwargs)
 Returns a dict representation of the function so that it can be reconstructed later with
apply_state().- Params
 - recurse: bool
 When the function has children functions, e.g. a
FuncGroup, if True all the children functions’ states will also be returned, otherwise, only this function’s state is returned. See the example.- expand_ref: bool
 If True, if any sub-functions (or this function itself) are
CeedFuncRefinstances, they will be expanded to contain the state of the actual underlying function. Otherwise, it is returned as being a function reference.
- Returns
 A dict with all the configuration data.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_state() {'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0} >>> Group = function_factory.get('FuncGroup') >>> g = Group() >>> g <ceed.function.FuncGroup at 0x4f85800> >>> g.add_func(cos) >>> g.get_state(recurse=True) {'cls': 'FuncGroup', 'funcs': [{'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0}], 'loop': 1, 'name': 'Group'} >>> g.get_state(recurse=False) {'cls': 'FuncGroup', 'loop': 1, 'name': 'Group'}
- get_noise_supported_parameters()
 Returns the set of property names of this function that supports randomness and may have an
ceed.function.param_noise.NoiseBaseinstance associated with it.
- class ceed.function.plugin.LinearFunc(**kwargs)
 Bases:
ceed.function.CeedFuncDefines a linearly increasing function.
The function is defined as
y(t_in) = mt + b, wheret = (t_in - t_start + t_offset).- m
 The line’s slope.
- b
 The line’s zero intercept.
- get_gui_props()
 Called internally by the GUI to get the properties of the function that should be displayed to the user to be customized.
- Returns
 A dict that contains all properties that should be displayed. The values of the property is as follows:
If it’s the string int, float, str or it’s the python type int, float, or str then the GUI will show a editable property for this type.
If it’s None, we look at the value of the property in the instance and display accordingly (e.g. if it’s a str type property, a string property is displayed to the user).
Note
The default value determines the type. So if the default value is
0, the type will be int and a user won’t be able to enter a float. Use e.g.0.0in the latter case.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_gui_props() {'A': None, 'duration': None, 'f': None, 'loop': None, 'name': None, 't_offset': None, 'th0': None}
- get_state(*largs, **kwargs)
 Returns a dict representation of the function so that it can be reconstructed later with
apply_state().- Params
 - recurse: bool
 When the function has children functions, e.g. a
FuncGroup, if True all the children functions’ states will also be returned, otherwise, only this function’s state is returned. See the example.- expand_ref: bool
 If True, if any sub-functions (or this function itself) are
CeedFuncRefinstances, they will be expanded to contain the state of the actual underlying function. Otherwise, it is returned as being a function reference.
- Returns
 A dict with all the configuration data.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_state() {'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0} >>> Group = function_factory.get('FuncGroup') >>> g = Group() >>> g <ceed.function.FuncGroup at 0x4f85800> >>> g.add_func(cos) >>> g.get_state(recurse=True) {'cls': 'FuncGroup', 'funcs': [{'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0}], 'loop': 1, 'name': 'Group'} >>> g.get_state(recurse=False) {'cls': 'FuncGroup', 'loop': 1, 'name': 'Group'}
- get_noise_supported_parameters()
 Returns the set of property names of this function that supports randomness and may have an
ceed.function.param_noise.NoiseBaseinstance associated with it.
- class ceed.function.plugin.ExponentialFunc(**kwargs)
 Bases:
ceed.function.CeedFuncDefines a double exponential function.
The function is defined as
y(t_in) = Ae^-t/tau1 + Be^-t/tau2, wheret = (t_in - t_start + t_offset).- A
 The amplitude of the first exponential.
- B
 The amplitude of the second exponential.
- tau1
 The time constant of the first exponential.
- tau2
 The time constant of the second exponential.
- get_gui_props()
 Called internally by the GUI to get the properties of the function that should be displayed to the user to be customized.
- Returns
 A dict that contains all properties that should be displayed. The values of the property is as follows:
If it’s the string int, float, str or it’s the python type int, float, or str then the GUI will show a editable property for this type.
If it’s None, we look at the value of the property in the instance and display accordingly (e.g. if it’s a str type property, a string property is displayed to the user).
Note
The default value determines the type. So if the default value is
0, the type will be int and a user won’t be able to enter a float. Use e.g.0.0in the latter case.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_gui_props() {'A': None, 'duration': None, 'f': None, 'loop': None, 'name': None, 't_offset': None, 'th0': None}
- get_state(*largs, **kwargs)
 Returns a dict representation of the function so that it can be reconstructed later with
apply_state().- Params
 - recurse: bool
 When the function has children functions, e.g. a
FuncGroup, if True all the children functions’ states will also be returned, otherwise, only this function’s state is returned. See the example.- expand_ref: bool
 If True, if any sub-functions (or this function itself) are
CeedFuncRefinstances, they will be expanded to contain the state of the actual underlying function. Otherwise, it is returned as being a function reference.
- Returns
 A dict with all the configuration data.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_state() {'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0} >>> Group = function_factory.get('FuncGroup') >>> g = Group() >>> g <ceed.function.FuncGroup at 0x4f85800> >>> g.add_func(cos) >>> g.get_state(recurse=True) {'cls': 'FuncGroup', 'funcs': [{'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0}], 'loop': 1, 'name': 'Group'} >>> g.get_state(recurse=False) {'cls': 'FuncGroup', 'loop': 1, 'name': 'Group'}
- get_noise_supported_parameters()
 Returns the set of property names of this function that supports randomness and may have an
ceed.function.param_noise.NoiseBaseinstance associated with it.
- class ceed.function.plugin.CosFunc(**kwargs)
 Bases:
ceed.function.CeedFuncDefines a cosine function.
The function is defined as
y(t_in) = Acos(2pi*f*t + th0*pi/180) + b, wheret = (t_in - t_start + t_offset).- f
 The function’s frequency in Hz.
- A
 The function’s amplitude.
- th0
 The function’s angle offset in degrees.
- b
 The function’s y offset.
- get_gui_props()
 Called internally by the GUI to get the properties of the function that should be displayed to the user to be customized.
- Returns
 A dict that contains all properties that should be displayed. The values of the property is as follows:
If it’s the string int, float, str or it’s the python type int, float, or str then the GUI will show a editable property for this type.
If it’s None, we look at the value of the property in the instance and display accordingly (e.g. if it’s a str type property, a string property is displayed to the user).
Note
The default value determines the type. So if the default value is
0, the type will be int and a user won’t be able to enter a float. Use e.g.0.0in the latter case.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_gui_props() {'A': None, 'duration': None, 'f': None, 'loop': None, 'name': None, 't_offset': None, 'th0': None}
- get_state(*largs, **kwargs)
 Returns a dict representation of the function so that it can be reconstructed later with
apply_state().- Params
 - recurse: bool
 When the function has children functions, e.g. a
FuncGroup, if True all the children functions’ states will also be returned, otherwise, only this function’s state is returned. See the example.- expand_ref: bool
 If True, if any sub-functions (or this function itself) are
CeedFuncRefinstances, they will be expanded to contain the state of the actual underlying function. Otherwise, it is returned as being a function reference.
- Returns
 A dict with all the configuration data.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_state() {'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0} >>> Group = function_factory.get('FuncGroup') >>> g = Group() >>> g <ceed.function.FuncGroup at 0x4f85800> >>> g.add_func(cos) >>> g.get_state(recurse=True) {'cls': 'FuncGroup', 'funcs': [{'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0}], 'loop': 1, 'name': 'Group'} >>> g.get_state(recurse=False) {'cls': 'FuncGroup', 'loop': 1, 'name': 'Group'}
- get_noise_supported_parameters()
 Returns the set of property names of this function that supports randomness and may have an
ceed.function.param_noise.NoiseBaseinstance associated with it.
- class ceed.function.plugin.CSVFunc(**kwargs)
 Bases:
ceed.function.CeedFuncDefines a function whose frames are read from a csv file.
There’s only one column of data with no header row. Each row in the column is the value of the function for one frame. The total duration of the function is the number of frames divided by the frame rate. I.e. each row corresponds to a frame, but the depending on the fps in Ceed it can be at different times.
Values are forced to the
[0, 1]range.The function is defined as
y(t) = row(t * fps).- csv_path: str
 The full path to the CSV file.
- get_gui_elements()
 Returns widget instances that should be displayed to the user along with this function’s editable properties of
get_gui_props().These widgets are displayed along with other config parameters for the function and can be used for custom config options. This is called by the Ceed GUI when the settings are first displayed to the user.
- Returns
 It should return a dict of the name of each setting mapped to the widget controlling the setting. It will be displayed in two columns: the name followed by the widget on the same row.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_gui_elements() {}
- get_state(*largs, **kwargs)
 Returns a dict representation of the function so that it can be reconstructed later with
apply_state().- Params
 - recurse: bool
 When the function has children functions, e.g. a
FuncGroup, if True all the children functions’ states will also be returned, otherwise, only this function’s state is returned. See the example.- expand_ref: bool
 If True, if any sub-functions (or this function itself) are
CeedFuncRefinstances, they will be expanded to contain the state of the actual underlying function. Otherwise, it is returned as being a function reference.
- Returns
 A dict with all the configuration data.
E.g.:
>>> Cos = function_factory.get('CosFunc') >>> cos = Cos() >>> cos.get_state() {'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0} >>> Group = function_factory.get('FuncGroup') >>> g = Group() >>> g <ceed.function.FuncGroup at 0x4f85800> >>> g.add_func(cos) >>> g.get_state(recurse=True) {'cls': 'FuncGroup', 'funcs': [{'A': 1.0, 'cls': 'CosFunc', 'duration': 0, 'f': 1.0, 'loop': 1, 'name': 'Cos', 't_offset': 0, 'th0': 0.0}], 'loop': 1, 'name': 'Group'} >>> g.get_state(recurse=False) {'cls': 'FuncGroup', 'loop': 1, 'name': 'Group'}
- init_func_tree(*args, **kwargs) None
 Initializes the function as part of the function tree so it is ready to be called to get the function values as part of the tree. It is called once for each function of the entire function tree.
- Parameters
 root – The root of the function tree. If None, it’s self.
For example, for the following function structure:
GroupFunc: name: 'root' loop: 5 GroupFunc: name: 'child_a' loop: 3 ConstFunc: name: 'child' loop: 4
when the experiment is ready, after
resample_parameters()and the stage is ready to run, ceed will callinit_func_tree()once forroot,child_a, andchildin that order. Therootparameter passed will be therootfunction.Then, it will call
init_func()forroot,child_a, andchild1, 5, and 15 times, respectively. Once for each time the function is started.Finally, it will call
init_loop_iteration()forroot,child_a, andchild4, 10, and 45 times, respectively. Once for each loop iteration of the function, except the first.
- init_func(*args, **kwargs) None
 Initializes the function so it is ready to be called to get the function values. See also
init_func_tree()andinit_loop_iteration(). If overriding,supermust be called.- Parameters
 t_start – The time in seconds in global time.
t_startwill be set to this value. All subsequent calls to the function with a time value will be relative to this given time.
- init_loop_iteration(*args, **kwargs) None
 Initializes the function at the beginning of each loop.
It’s called internally at the start of every
loopiteration, except the first. See alsoinit_func_tree()andinit_func(). If overriding,supermust be called.- Parameters
 t_start – The time in seconds in global time.
t_startwill be set to this value. All subsequent calls to the function with a time value will be relative to this given time.
- class ceed.function.plugin.GaussianNoise(**kwargs)
 Bases:
ceed.function.param_noise.NoiseBaseRepresents a Gaussian distribution.
- min_val
 The minimum value to clip the sampled value before returning it.
- max_val
 The maximum value to clip the sampled value before returning it.
- mean_val
 The mean of the distribution,
- stdev
 The standard deviation of the distribution,
- sample() float
 Samples the distribution and returns a new value.
- get_config() dict
 Returns a dict representation of the instance that can be then be used to reconstruct it with
ParameterNoiseFactory.make_instance().This is also used to display the instance parameters to the user. We infer the type of each parameter from the property value.
- get_prop_pretty_name() Dict[str, str]
 Returns a dict mapping names of the parameters used by the class to a nicer representation shown to the user.
- class ceed.function.plugin.UniformNoise(**kwargs)
 Bases:
ceed.function.param_noise.NoiseBaseRepresents a uniform distribution.
- min_val
 The minimum value of the range (inclusive).
- max_val
 The maximum value of the range (inclusive depending on the system).
- sample() float
 Samples the distribution and returns a new value.
- get_config() dict
 Returns a dict representation of the instance that can be then be used to reconstruct it with
ParameterNoiseFactory.make_instance().This is also used to display the instance parameters to the user. We infer the type of each parameter from the property value.
- get_prop_pretty_name() Dict[str, str]
 Returns a dict mapping names of the parameters used by the class to a nicer representation shown to the user.
- class ceed.function.plugin.DiscreteNoise(**kwargs)
 Bases:
ceed.function.param_noise.NoiseBaseRepresents a uniform distribution from equally spaced discrete values.
- start_value
 The first value in the list of values (inclusive).
- step
 The distance between values (e.g. if it’s 1 and
start_valueis 0 andnum_valuesis 5, we have0, 1, 2, 3, 4).
- num_values
 The total number of values (e.g. if it’s 5 and
start_valueis 0 andstepis 1, we have0, 1, 2, 3, 4).
- with_replacement
 Whether, when sampling the distribution, to sample with replacement.
If False, then
num_valuesmust be at least as large asnofsample_seq(), if the distribution is used to sample more than once, e.g. if each loop iteration is sampled.
- sample() float
 Samples the distribution and returns a new value.
- sample_seq(n) List[float]
 Samples the distribution
ntimes and returns a list of values.By default it just calls
sample()ntimes to get the samples.
- get_config() dict
 Returns a dict representation of the instance that can be then be used to reconstruct it with
ParameterNoiseFactory.make_instance().This is also used to display the instance parameters to the user. We infer the type of each parameter from the property value.
- get_prop_pretty_name() Dict[str, str]
 Returns a dict mapping names of the parameters used by the class to a nicer representation shown to the user.
- class ceed.function.plugin.DiscreteListNoise(**kwargs)
 Bases:
ceed.function.param_noise.NoiseBaseRepresents a uniform distribution from a list of discrete values.
- csv_list: str
 A comma-separated list of float or integers representing the items from from which to sample. It may have optional spaces between the items, in addition to the required commas.
- num_dup: int
 When
with_replacementisTrue,csv_listis duplicatednum_duptimes before we sample from it. This can ensure there are enough samples in the distribution.If
with_replacementisFalseand this is not1an error is raised. Same ifnum_dupis less than1.
- with_replacement: bool
 Whether, when sampling the distribution, to sample with replacement.
If False, then the number of items in
csv_listmust be at least as large asnofsample_seq(), if the distribution is used to sample more than once, e.g. if each loop iteration is sampled.
- sample() float
 Samples the distribution and returns a new value.
- sample_seq(n) List[float]
 Samples the distribution
ntimes and returns a list of values.By default it just calls
sample()ntimes to get the samples.
- get_config() dict
 Returns a dict representation of the instance that can be then be used to reconstruct it with
ParameterNoiseFactory.make_instance().This is also used to display the instance parameters to the user. We infer the type of each parameter from the property value.
- get_prop_pretty_name() Dict[str, str]
 Returns a dict mapping names of the parameters used by the class to a nicer representation shown to the user.
- ceed.function.plugin.get_ceed_functions(function_factory: ceed.function.FunctionFactoryBase) Iterable[Type[ceed.function.FuncType]]
 Returns all the function classes defined and exported in this file (
ConstFunc,LinearFunc, etc.).- Parameters
 function_factory – The
FunctionFactoryBaseinstance currently active in Ceed.
- ceed.function.plugin.get_ceed_distributions(function_factory: ceed.function.FunctionFactoryBase) Iterable[Type[ceed.function.param_noise.NoiseType]]
 Returns all the distribution classes defined and exported in this file (
GaussianNoise,UniformNoise, etc.).- Parameters
 function_factory – The
FunctionFactoryBaseinstance currently active in Ceed.