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 .py files in the given directory and sub-directories for the named package that don’t start with a underscore (except for __init__.py of course, which is imported). For each imported module, it calls its get_ceed_functions and get_ceed_distributions function (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 FunctionFactoryBase instance 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_package is ceed.function.plugin because that’s the package containing name for the plugin directory. Then, they are imported as ceed.function.plugin and ceed.function.plugin.xyz, if the plugin directory also contains a xyz.py plugin file.

  • root – The full directory path that contains the plugins. E.g. for ceed.function.plugin it is ceed/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(), and register_all_functions() for an example how it’s used.

class ceed.function.plugin.ConstFunc(name='Const', description='y(t) = a', **kwargs)

Bases: ceed.function.CeedFunc

Defines 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.0 in 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 CeedFuncRef instances, 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.NoiseBase instance associated with it.

class ceed.function.plugin.LinearFunc(**kwargs)

Bases: ceed.function.CeedFunc

Defines a linearly increasing function.

The function is defined as y(t_in) = mt + b, where t = (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.0 in 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 CeedFuncRef instances, 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.NoiseBase instance associated with it.

class ceed.function.plugin.ExponentialFunc(**kwargs)

Bases: ceed.function.CeedFunc

Defines a double exponential function.

The function is defined as y(t_in) = Ae^-t/tau1 + Be^-t/tau2, where t = (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.0 in 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 CeedFuncRef instances, 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.NoiseBase instance associated with it.

class ceed.function.plugin.CosFunc(**kwargs)

Bases: ceed.function.CeedFunc

Defines a cosine function.

The function is defined as y(t_in) = Acos(2pi*f*t + th0*pi/180) + b, where t = (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.0 in 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 CeedFuncRef instances, 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.NoiseBase instance associated with it.

class ceed.function.plugin.CSVFunc(**kwargs)

Bases: ceed.function.CeedFunc

Defines 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 CeedFuncRef instances, 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 call init_func_tree() once for root, child_a, and child in that order. The root parameter passed will be the root function.

Then, it will call init_func() for root, child_a, and child 1, 5, and 15 times, respectively. Once for each time the function is started.

Finally, it will call init_loop_iteration() for root, child_a, and child 4, 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() and init_loop_iteration(). If overriding, super must be called.

Parameters

t_start – The time in seconds in global time. t_start will 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 loop iteration, except the first. See also init_func_tree() and init_func(). If overriding, super must be called.

Parameters

t_start – The time in seconds in global time. t_start will 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.NoiseBase

Represents 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.NoiseBase

Represents 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.NoiseBase

Represents 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_value is 0 and num_values is 5, we have 0, 1, 2, 3, 4).

num_values

The total number of values (e.g. if it’s 5 and start_value is 0 and step is 1, we have 0, 1, 2, 3, 4).

with_replacement

Whether, when sampling the distribution, to sample with replacement.

If False, then num_values must be at least as large as n of sample_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 n times and returns a list of values.

By default it just calls sample() n times 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.NoiseBase

Represents 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_replacement is True, csv_list is duplicated num_dup times before we sample from it. This can ensure there are enough samples in the distribution.

If with_replacement is False and this is not 1 an error is raised. Same if num_dup is less than 1.

with_replacement: bool

Whether, when sampling the distribution, to sample with replacement.

If False, then the number of items in csv_list must be at least as large as n of sample_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 n times and returns a list of values.

By default it just calls sample() n times 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 FunctionFactoryBase instance 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 FunctionFactoryBase instance currently active in Ceed.