Source code for teili.models.builder.combine

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""This file contains a set of functions used by the library to combine models.

Combine_neu_dict is used for combining neuron models
Combine_syn_dict is used for combining neuron models

Both functions use the var_replacer when the special overwrite character '%'
is found in the equations. If '%' is found in the middle of the equation,
like a modulo operation, substitutions are not performed.

Example:
    To use combine_neu_dict:

    >>> from teili.models.builder.combine import combine_neu_dict
    >>> combine_neu_dict(eq_templ, param_templ)

    To use combine_syn_dict:
    >>> from teili.models.builder.combine import combine_syn_dict
    >>> combine_syn_dict(eq_templ, param_templ)
"""


[docs]def combine_neu_dict(eq_templ, param_templ): """Function to combine neuron models into a single neuron model. This library offers this ability in order to combine single blocks into bigger and more complex Brian2 compatible models. combine_neu_dict also makes it possible to delete or overwrite an explicit function with the use of the special character '%'. Example: Example with two different dictionaries both containing the explicit function for the variable 'x': >>> x = theta >>> %x = gamma >>> x = gamma '%x' without any assignment will simply delete the variable from the output and from the parameter dictionary. To combine two dictionaries: >>> combine_neu_dict(eq_templ, param_templ) Args: eq_templ (dict): Dictionary containing different keywords and equations param_templ (dict): Dictionary containing different parameters for the equation Returns: dict: ['model'] Actually neuron model differential equation. dict: ['threshold'] Dictionary with equations specifying behaviour of synapse to post-synaptic spike. dict: ['reset'] Dictionary with equations specifying behaviour of synapse to pre-synaptic spike. dict: ['parameters'] Dictionary of parameters. """ model = '' threshold = '' reset = '' params = {} for d in param_templ: params.update(d) for k, eq in enumerate(eq_templ): newmodel = eq['model'] if '%' in newmodel: model, newmodel, params = var_replacer(model, newmodel, params) model += newmodel newthreshold = eq['threshold'] if '%' in newthreshold: threshold, newthreshold, params = var_replacer( threshold, newthreshold, params) threshold += newthreshold newreset = eq['reset'] if '%' in newreset: reset, newreset, params = var_replacer(reset, newreset, params) reset += newreset return {'model': model, 'threshold': threshold, 'reset': reset, 'parameters': params}
[docs]def combine_syn_dict(eq_templ, param_templ): """Function to combine synapse models into a single synapse model. This library offers this ability in order to combine single blocks into bigger and more complex Brian2 compatible models. combine_syn_dict also makes it possible to delete or overwrite an explicit function with the use of the special character '%'. Example with two different dictionaries both containing the explicit function for the variable 'x': Example: Example with two different dictionaries both containing the explicit function for the variable 'x': >>> x = theta >>> %x = gamma >>> x = gamma '%x' without any assignment will simply delete the variable from the output and from the parameter dictionary. To combine two dictionaries: >>> combine_syn_dict(eq_templ, param_templ) Args: eq_templ (dict): Dictionary containing different keywords and equations. param_templ (dict): Dictionary containing different parameters for the equation. Returns: dict: ['model'] Actually neuron model differential equation. dict: ['on_post'] Dictionary with equations specifying behaviour of synapse to post-synaptic spike. dict: ['on_pre'] Dictionary with equations specifying behaviour of synapse to pre-synaptic spike. dict: ['parameters'] Dictionary of parameters. """ model = '' on_pre = '' on_post = '' params = {} for k, eq in enumerate(eq_templ): newmodel = eq['model'] if '%' in eq['model']: model, newmodel, params = var_replacer(model, newmodel, params) model += newmodel newon_pre = eq['on_pre'] if '%' in eq['on_pre']: on_pre, newon_pre, params = var_replacer(on_pre, newon_pre, params) on_pre += newon_pre newon_post = eq['on_post'] if '%' in eq['on_post']: on_post, newon_post, params = var_replacer( on_post, newon_post, params) on_post += newon_post params.update(param_templ[k]) return {'model': model, 'on_pre': on_pre, 'on_post': on_post, 'parameters': params}
[docs]def var_replacer(first_eq, second_eq, params): """Function to delete variables from equations and parameters. It works with couples of strings and a dict of parameters: first_eq, second_eq and params It searches for every line in second_eq for the special character '%' removing it, and then searching for the variable (even if in differential form '%dx/dt') and erasing every line in first_eq starting with that variable (every explicit equation). If the character '=' or ':' is not in the line containing the variable in second_eq the entire line would be erased. Args: first_eq (string): The first subset of equations that we want to expand or overwrite. second_eq (string): The second subset of equations which will be added to first_eq. It also contains '%' for overwriting or erasing lines in first_eq. params (dict): Dictionary of parameters to be replaced. Returns: result_first_eq: The first_eq string containing the replaced variable equations. result_second_eq: The second_eq string without the lines containing the special character '%'. params: The parameter dictionary not containing the removed/replaced variables. Examples: >>> '%x = theta' --> 'x = theta' >>> '%x' --> '' This feature allows to remove equations in the template that we don't want to compute by writing '%[variable]' in the other equation blocks. To replace variables and lines: >>> from teili.models.builder.combine import var_replacer >>> var_replacer(first_eq, second_eq, params) """ result_first_eq = first_eq.splitlines() result_second_eq = second_eq.splitlines() for k, line in enumerate(second_eq.splitlines()): if '%' in line: # if the replace character '%' is found, extract the variable # Checks if string before '%' is empty or not. If it is, '%' is # the first non-whitespace character and replacement can proceed str_before_char = line.split('%', 1)[0].strip() if str_before_char: continue var = line.split('%', 1)[1].split()[0] line = line.replace("%", "", 1) if '/' in var: var = var.split('/', 1)[0][1:] remove_flag = False else: remove_flag = True diffvar = 'd' + var + '/dt' for kk, line2 in enumerate(first_eq.splitlines()): # now look for the variable in the equation lines extracted from # first_eq if (var in line2) or (diffvar in line2): # if i found a variable i need to check then if it's in explicit form # meaning it's followed by ":" or "=" # e.g. "var = x+1" or "var : 1" if ((var == line2.replace(':', '=').split('=', 1)[0].split()[0]) or (diffvar in line2.replace(':', '=').split('=', 1)[0].split()[0])): result_first_eq[kk] = line # after replacing the "%" flagged line in the result_first_eq # remove that line from the result_second_eq result_second_eq[k] = "" try: if remove_flag: params.pop(var) else: pass except KeyError: pass result_first_eq = "\n".join(result_first_eq) result_second_eq = "\n".join(result_second_eq) return result_first_eq, result_second_eq, params