odetoolbox package

odetoolbox._analysis(indict, disable_stiffness_check: bool = False, disable_analytic_solver: bool = False, preserve_expressions: Union[bool, Iterable[str]] = False, simplify_expression: str = 'sympy.simplify(expr)', log_level: Union[str, int] = 30) → Tuple[List[Dict[KT, VT]], odetoolbox.system_of_shapes.SystemOfShapes, List[odetoolbox.shapes.Shape]]

Like analysis(), but additionally returns shape_sys and shapes.

For internal use only!

odetoolbox._dependency_analysis(shape_sys, shapes, differential_order_symbol)

Perform dependency analysis and plot dependency graph.

odetoolbox._find_variable_definition(indict, name: str, order: int) → Optional[str]

Find the definition (as a string in the input dictionary) of variable named name with order order, and return it as a string. Return None if a definition by that name and order could not be found.

odetoolbox._from_json_to_shapes(indict, options_dict) → List[odetoolbox.shapes.Shape]

Process the input, construct Shape instances.

Parameters:
  • indict – ODE-toolbox input dictionary.
  • options_dict – ODE-toolbox global configuration dictionary.
odetoolbox._get_all_first_order_variables(indict) → Iterable[str]

Return a list of variable names, containing those variables that were defined as a first-order ordinary differential equation in the input.

odetoolbox._init_logging(log_level: Union[str, int] = 30)

Initialise message logging.

Parameters:log_level – Sets the logging threshold. Logging messages which are less severe than log_level will be ignored. Log levels can be provided as an integer or string, for example “INFO” (more messages) or “WARN” (fewer messages). For a list of valid logging levels, see https://docs.python.org/3/library/logging.html#logging-levels
odetoolbox._read_global_config(indict, default_config)

Process global configuration options.

odetoolbox.analysis(indict, disable_stiffness_check: bool = False, disable_analytic_solver: bool = False, preserve_expressions: Union[bool, Iterable[str]] = False, simplify_expression: str = 'sympy.simplify(expr)', log_level: Union[str, int] = 30) → List[Dict[KT, VT]]

The main entry point of the ODE-toolbox API.

Parameters:
  • indict – Input dictionary for the analysis. For details, see https://ode-toolbox.readthedocs.io/en/master/#input
  • disable_stiffness_check – Whether to perform stiffness checking.
  • disable_analytic_solver – Set to True to return numerical solver recommendations, and no propagators, even for ODEs that are analytically tractable.
  • preserve_expressions – Set to True, or a list of strings corresponding to individual variable names, to disable internal rewriting of expressions, and return same output as input expression where possible. Only applies to variables specified as first-order differential equations.
  • simplify_expression – For all expressions expr that are rewritten internally: the contents of this parameter string are evaluated with eval() in Python to obtain the final output expression. Override for custom expression simplification steps. Example: "sympy.logcombine(sympy.powsimp(sympy.expand(expr)))".
  • log_level – Sets the logging threshold. Logging messages which are less severe than log_level will be ignored. Log levels can be provided as an integer or string, for example “INFO” (more messages) or “WARN” (fewer messages). For a list of valid logging levels, see https://docs.python.org/3/library/logging.html#logging-levels
Returns:

The result of the analysis. For details, see https://ode-toolbox.readthedocs.io/en/latest/index.html#output

Submodules

odetoolbox.analytic_integrator module

class odetoolbox.analytic_integrator.AnalyticIntegrator(solver_dict, spike_times, enable_caching=True)

Bases: odetoolbox.integrator.Integrator

Integrate a dynamical system by means of the propagators returned by ODE-toolbox.

__init__(solver_dict, spike_times, enable_caching=True)
Parameters:
  • solve_dict – The results dictionary returned by a call to odetoolbox.analysis().
  • spike_times – For each variable, used as a key, the list of times at which a spike occurs.
  • enable_caching – Allow caching of results between requested times.
_update_step(delta_t, initial_values)

Apply propagator to update the state, starting from initial_values, by timestep delta_t.

Parameters:
  • delta_t – Timestep to take.
  • initial_values – A dictionary mapping variable names (as strings) to initial value expressions.
disable_cache_update()

Disallow caching of results between requested times.

enable_cache_update()

Allow caching of results between requested times.

get_all_variable_symbols()
get_value(t)

Get numerical solution of the dynamical system at time t.

Parameters:t – The time to compute the solution for.
reset()

Reset time to zero and state to initial values.

set_initial_values(vals)

Set initial values, i.e. the state of the system at \(t = 0\). This will additionally cause the system state to be reset to \(t = 0\) and the new initial conditions.

Parameters:vals – New initial values.

odetoolbox.dependency_graph_plotter module

class odetoolbox.dependency_graph_plotter.DependencyGraphPlotter

Bases: object

Use graphviz to plot a dependency graph between state variables.

classmethod plot_graph(shapes, dependency_edges, node_is_lin, fn=None)

Plot graph and write to file.

Parameters:
  • shapes – List of Shape instances.
  • dependency_edges – List of edges returned from dependency analysis.
  • node_is_lin – List of Booleans returned from dependency analysis.
  • fn – Filename to write PNG image as.

odetoolbox.integrator module

class odetoolbox.integrator.Integrator

Bases: object

Integrate a dynamical system by means of the propagators returned by ODE-toolbox (base class).

all_variable_symbols = []
get_sorted_spike_times()

Returns a global, sorted list of spike times.

Return all_spike_times:
 A sorted list of all spike times for all variables.
Return all_spike_times_sym:
 For the spike at time all_spike_times[i], the variables to which that spike applies are listed in all_spike_times_sym[i].
get_spike_times()

Get spike times.

Return spike_times:
 For each variable, used as a key, the list of spike times associated with it.
set_spike_times(spike_times: Dict[str, List[float]])

Internally converts to a global, sorted list of spike times.

Parameters:spike_times – For each variable, used as a key, the list of spike times associated with it.

odetoolbox.mixed_integrator module

class odetoolbox.mixed_integrator.MixedIntegrator(numeric_integrator, system_of_shapes, shapes, analytic_solver_dict=None, parameters=None, spike_times=None, random_seed=123, max_step_size=inf, integration_accuracy_abs=1e-06, integration_accuracy_rel=1e-06, sim_time=1.0, alias_spikes=False)

Bases: odetoolbox.integrator.Integrator

Mixed numeric+analytic integrator. Supply with a result from ODE-toolbox analysis; calculates numeric approximation of the solution.

__init__(numeric_integrator, system_of_shapes, shapes, analytic_solver_dict=None, parameters=None, spike_times=None, random_seed=123, max_step_size=inf, integration_accuracy_abs=1e-06, integration_accuracy_rel=1e-06, sim_time=1.0, alias_spikes=False)
Parameters:
  • numeric_integrator – A method from the GSL library for evolving ODEs, e.g. odeiv.step_rk4
  • system_of_shapes – Dynamical system to solve.
  • shapes – List of shapes in the dynamical system.
  • analytic_solver_dict – Analytic solver dictionary from ODE-toolbox analysis result.
  • parameters – Dictionary mapping parameter name (as string) to value expression.
  • spike_times – For each variable, used as a key, the list of times at which a spike occurs.
  • random_seed – Random number generator seed.
  • max_step_size – The maximum step size taken by the integrator.
  • integration_accuracy_abs – Absolute integration accuracy.
  • integration_accuracy_rel – Relative integration accuracy.
  • sim_time – How long to simulate for.
  • alias_spikes – Whether to alias spike times to the numerical integration grid. False means that precise integration will be used for spike times whenever possible. True means that after taking a timestep \(dt\) and arriving at \(t\), spikes from \(\langle t - dt, t]\) will only be processed at time \(t\).
integrate_ode(initial_values=None, h_min_lower_bound=5e-09, raise_errors=True, debug=False)

This function computes the average step size and the minimal step size that a given integration method from GSL uses to evolve a certain system of ODEs during a certain simulation time, integration method from GSL and spike train.

Parameters:
  • initial_values – A dictionary mapping variable names (as strings) to initial value expressions.
  • h_min_lower_bound – The minimum acceptable step size.
  • raise_errors – Stop and raise exception when error occurs, or try to continue.
  • debug – Return extra values useful for debugging.
Returns:

Average and minimal step size, and elapsed wall clock time.

integrator_debug_plot(t_log, h_log, y_log, dir)
numerical_jacobian(t, y, params)

Compute the numerical values of the Jacobian matrix at the current time t and state y.

If the dynamics of variables \(x_1, \ldots, x_N\) is defined as \(x_i' = f_i\), then row \(i\) of the Jacobian matrix \(\mathbf{J}_i = \left[\begin{matrix}\frac{\partial f_i}{\partial x_0} & \cdots & \frac{\partial f_i}{\partial x_N}\end{matrix}\right]\).

Parameters:
  • t – Current time.
  • y – Current state vector of the dynamical system.
  • params – GSL parameters (not used here).
Returns:

Jacobian matrix \(\mathbf{J}\).

step(t, y, params)

“Stepping function”: compute the (numerical) value of the derivative of y over time, at the current time t and state y.

Parameters:
  • t – Current time.
  • y – Current state vector of the dynamical system.
  • params – GSL parameters (not used here).
Returns:

Updated state vector

exception odetoolbox.mixed_integrator.ParametersIncompleteException

Bases: Exception

Thrown in case not all parameters are assigned a numerical value before integration was attempted.

odetoolbox.shapes module

exception odetoolbox.shapes.MalformedInputException

Bases: Exception

Thrown in case an error occurred while processing malformed input.

class odetoolbox.shapes.Shape(symbol, order, initial_values, derivative_factors, diff_rhs_derivatives=0.0, lower_bound=None, upper_bound=None, derivative_symbol='__d', debug=False)

Bases: object

This class provides a canonical representation of a shape function independently of the way in which the user specified the shape. It assumes a differential equation of the general form (where bracketed superscript \({}^{(n)}\) indicates the \(n\)-th derivative with respect to time):

\[x^{(n)} = N + \sum_{i=0}^{n-1} c_i x^{(i)}\]

Any constant or nonlinear part is here contained in the term N.

In the input and output, derivatives are indicated by adding one prime (single quotation mark) for each derivative order. For example, in the expression

x''' = c0*x + c1*x' + c2*x'' + x*y + x**2

the symbol of the ODE would be x (i.e. without any qualifiers), order would be 3, derivative_factors would contain the linear part in the form of the list [c0, c1, c2], and the nonlinear part x*y + x**2 is stored in diff_rhs_derivatives.

EXPRESSION_SIMPLIFICATION_THRESHOLD = 1000
__init__(symbol, order, initial_values, derivative_factors, diff_rhs_derivatives=0.0, lower_bound=None, upper_bound=None, derivative_symbol='__d', debug=False)

Perform type and consistency checks and assign arguments to member variables.

Parameters:
  • symbol – Symbolic name of the shape without additional qualifiers like prime symbols or similar.
  • order – Order of the ODE representing the shape.
  • initial_values – Initial values of the ODE representing the shape. The dict contains order many key-value pairs: one for each derivative that occurs in the ODE. The keys are strings created by concatenating the variable symbol with as many single quotation marks (’) as the derivation order. The values are SymPy expressions.
  • derivative_factors – The factors for the derivatives that occur in the ODE. This list has to contain :path:`order` many values, i.e. one for each derivative that occurs in the ODE. The values have to be in ascending order, i.e. [c0, c1, c2] for the given example.
  • diff_rhs_derivatives – Nonlinear part of the ODE representing the shape, i.e. x*y + x**2 for the given example.
__str__()

Return str(self).

classmethod _parse_defining_expression(s: str) → Tuple[str, int, str]

Parse a defining expression, for example, if the ODE-toolbox JSON input file contains the snippet:

::
{
“expression”: “h’ = -g / tau**2 - 2 * h / tau”

}

then the corresponding defining expression is "h' = -g / tau**2 - 2 * h / tau".

This function parses that string and returns the variable name (h), the derivative order (1) and the right-hand side expression (-g / tau**2 - 2 * h / tau").

_sympy_autowrap_helpers = [('Min', -Abs(x - y)/2 + Abs(x + y)/2, [x, y]), ('Max', Abs(x - y)/2 + Abs(x + y)/2, [x, y]), ('Heaviside', (x + Abs(x))/(2*Abs(x) + 1.0e-300), [x])]
_sympy_globals = {'DiracDelta': DiracDelta, 'E': E, 'Float': <class 'sympy.core.numbers.Float'>, 'Function': Function, 'Heaviside': Heaviside, 'Integer': <class 'sympy.core.numbers.Integer'>, 'Pow': <class 'sympy.core.power.Pow'>, 'Symbol': <class 'sympy.core.symbol.Symbol'>, 'acos': acos, 'acosh': acosh, 'asin': asin, 'asinh': asinh, 'atanh': atanh, 'cos': cos, 'cosh': cosh, 'e': E, 'exp': exp, 'log': log, 'max': Max, 'min': Min, 'power': <class 'sympy.core.power.Pow'>, 'sin': sin, 'sinh': sinh, 't': t, 'tan': tan, 'tanh': tanh}
classmethod from_function(symbol: str, definition, max_t=100, max_order=4, all_variable_symbols=None, time_symbol=t, differential_order_symbol=__d, debug=False)

Create a Shape object given a function of time.

For a complete description of the algorithm, see https://ode-toolbox.readthedocs.io/en/latest/index.html#converting-direct-functions-of-time

Parameters:
  • symbol – The variable name of the shape (e.g. “alpha”, “I”)
  • definition – The definition of the shape (e.g. “(e/tau_syn_in) * t *  exp(-t/tau_syn_in)”)
  • all_variable_symbols – All known variable symbols. None or list of string.
Returns:

The canonical representation of the postsynaptic shape

Return type:

Shape

Example:
>>> Shape.from_function("I_in", "(e/tau) * t * exp(-t/tau)")
classmethod from_json(indict, all_variable_symbols=None, time_symbol=t, differential_order_symbol='__d', _debug=False)

Create a Shape instance from an input dictionary.

Parameters:
  • indict – Input dictionary, i.e. one element of the “dynamics” list supplied in the ODE-toolbox input dictionary.
  • all_variable_symbols – All known variable symbols. None or list of string.
  • time_symbol – sympy Symbol representing the independent time variable.
  • differential_order_symbol – String used for identifying differential order. XXX: only “__d” is supported for now.
classmethod from_ode(symbol: str, definition: str, initial_values: dict, all_variable_symbols=None, lower_bound=None, upper_bound=None, differential_order_symbol='__d', debug=False, **kwargs)

Create a Shape object given an ODE and initial values.

Note that shapes are only aware of their own state variables: if an equation for \(x\) depends on another state variable \(y\) of another shape, then \(y\) will appear in the nonlinear part of \(x\).

Parameters:
  • symbol – The symbol (variable name) of the ODE.
  • definition – The definition of the ODE.
  • initial_values – A dictionary mapping initial values to expressions.
  • all_variable_symbols – All known variable symbols. None or list of string.
Example:
>>> Shape.from_ode("alpha",
                  "-1/tau**2 * shape_alpha -2/tau * shape_alpha'",
                  {"alpha" : "0", "alpha'" : "e/tau", "0"]})
get_all_variable_symbols(shapes=None, derivative_symbol="'")

Get all variable symbols for this shape and all other shapes in shapes, without duplicates, in no particular order.

Returns:all_symbols
Return type:list of sympy.Symbol
get_initial_value(sym: str)

Get the initial value corresponding to the variable symbol.

Parameters:sym – String representation of a sympy symbol, e.g. “V_m’”
get_state_variables(derivative_symbol="'") → List[sympy.core.symbol.Symbol]

Get all variable symbols for this shape, ordered according to derivative order: [sym, dsym/dt, d^2sym/dt^2, ]

Returns:all_symbols
is_homogeneous(shapes=None, differential_order_symbol='__d')
Returns:False if and only if the shape has a nonzero right-hand side.
Return type:bool
is_lin_const_coeff(shapes=None)
Returns:True if and only if the shape is linear and constant coefficient in all known variable symbols in shapes.
Return type:bool
reconstitute_expr(derivative_symbol='__d')

Recreate SymPy expression from internal representation (linear coefficients and nonlinear part).

Parameters:differential_order_symbol – String used for identifying differential order. XXX: only “__d” is supported for now.
static split_lin_nonlin(expr, x)

Split an expression into the form a_0 * x[0] + a_1 * x[1] + + c. The coefficients a_0a_n are returned as lin_factors. The nonlinear remainder is returned as nonlin_term.

odetoolbox.spike_generator module

class odetoolbox.spike_generator.SpikeGenerator

Bases: object

classmethod _generate_homogeneous_poisson_spikes(T: float, rate: float, min_isi: float = 1e-06)

Generate spike trains for the given simulation length. Uses a Poisson distribution to create biologically realistic characteristics of the spike-trains.

Parameters:
  • T – Spikes are generated in the window \([0, T]\).
  • min_isi – Minimum time between two consecutive spikes.
Returns:

spike_times: For each symbol: a list with spike times

Return type:

Dict(str -> List(float))

classmethod _generate_regular_spikes(T: float, rate: float)

Generate spike trains for the given simulation length.

Parameters:T – Spikes are generated in the window \(\langle 0, T]\).
Returns:For each symbol: a list with spike times
Return type:Dict(str -> List(float))
classmethod spike_times_from_json(stimuli, sim_time, derivative_symbol='__d') → Mapping[str, List[float]]

Read or generate spike times according to a JSON specification.

Returns:spike_times: Each variable symbol is a key in the dictionary, and the list of spike times is the corresponding value. Symbol names use derivative_symbol to indicate differential order.

odetoolbox.stiffness module

class odetoolbox.stiffness.StiffnessTester(system_of_shapes, shapes, analytic_solver_dict=None, parameters=None, stimuli=None, random_seed=123, max_step_size=inf, integration_accuracy_abs=1e-06, integration_accuracy_rel=1e-06, sim_time=100.0, alias_spikes=False)

Bases: object

__init__(system_of_shapes, shapes, analytic_solver_dict=None, parameters=None, stimuli=None, random_seed=123, max_step_size=inf, integration_accuracy_abs=1e-06, integration_accuracy_rel=1e-06, sim_time=100.0, alias_spikes=False)
Parameters:
  • system_of_shapes – Dynamical system to solve.
  • shapes – List of shapes in the dynamical system.
  • analytic_solver_dict – Analytic solver dictionary from ODE-toolbox analysis result.
  • parameters – Dictionary mapping parameter name (as string) to value expression.
  • stimuli – Dictionary containing spiking stimuli.
  • random_seed – Random number generator seed.
  • max_step_size – The maximum step size taken by the integrator.
  • integration_accuracy_abs – Absolute integration accuracy.
  • integration_accuracy_rel – Relative integration accuracy.
  • sim_time – How long to simulate for.
  • alias_spikes – Whether to alias spike times to the numerical integration grid. False means that precise integration will be used for spike times whenever possible. True means that after taking a timestep \(dt\) and arriving at \(t\), spikes from \(\langle t - dt, t]\) will only be processed at time \(t\).
_draw_decision(step_min_imp, step_min_exp, step_average_imp, step_average_exp, machine_precision_dist_ratio=10, avg_step_size_ratio=6)

Decide which is the best integrator to use.

For details, see https://ode-toolbox.readthedocs.io/en/latest/index.html#numeric-solver-selection-criteria

Parameters:
  • step_min_imp – Minimum recommended step size returned for implicit solver.
  • step_min_exp – Minimum recommended step size returned for explicit solver.
  • step_average_imp – Average recommended step size returned for implicit solver.
  • step_average_exp – Average recommended step size returned for explicit solver.
_evaluate_integrator(integrator, h_min_lower_bound=1e-12, raise_errors=True, debug=True)

This function computes the average step size and the minimal step size that a given integration method from GSL uses to evolve a certain system of ODEs during a certain simulation time, integration method from GSL and spike train for a given maximal stepsize.

This function will reset the numpy random seed.

Parameters:
  • integrator – A method from the GSL library for evolving ODEs, e.g. odeiv.step_rk4.
  • h_min_lower_bound – The minimum acceptable step size. Integration will terminate with an error if this step size is reached.
  • raise_errors – Stop and raise exception when error occurs, or try to continue.
Return h_min:

Minimum recommended step size.

Return h_avg:

Average recommended step size.

Return runtime:

Wall clock runtime.

check_stiffness(raise_errors=False)

Perform stiffness testing: use implicit and explicit solvers to simulate the dynamical system, then decide which is the better solver to use.

For details, see https://ode-toolbox.readthedocs.io/en/latest/index.html#numeric-solver-selection-criteria

Returns:Either “implicit”, “explicit” or “warning”.
Return type:str
random_seed

odetoolbox.sympy_printer module

class odetoolbox.sympy_printer.SympyPrinter(settings=None)

Bases: sympy.printing.str.StrPrinter

_print_Exp1(expr)
_print_Function(expr)

Overrides base class method to print min() and max() functions in lowercase.

odetoolbox.sympy_printer._is_sympy_type(var)
odetoolbox.sympy_printer._is_zero(x)

Check if a sympy expression is equal to zero.

In the ideal case, we would like to use sympy.simplify() to do simplification of an expression before comparing it to zero. However, for expressions of moderate size (e.g. a few dozen terms involving exp() functions), it becomes unbearably slow. We therefore use this internal function, so that the simplification function can be easily switched over.

Tests by expand_mul only, suitable for polynomials and rational functions.

Ref.: https://github.com/sympy/sympy PR #13877 by @normalhuman et al. merged on Jan 27, 2018

odetoolbox.system_of_shapes module

class odetoolbox.system_of_shapes.SystemOfShapes(x, A: sympy.matrices.dense.MutableDenseMatrix, c, shapes)

Bases: object

Represent a dynamical system in the canonical form \(\mathbf{x}' = \mathbf{Ax} + \mathbf{c}\).

__init__(x, A: sympy.matrices.dense.MutableDenseMatrix, c, shapes)

Initialize a dynamical system in the canonical form \(\mathbf{x}' = \mathbf{Ax} + \mathbf{c}\).

Parameters:
  • A – Matrix containing linear part.
  • c – Vector containing nonlinear part.
classmethod from_shapes(shapes)

Construct the global system matrix \(\mathbf{A}\) and nonlinear parts vector \(\mathbf{c}\) on the basis of all shapes in shapes, and such that

\[\mathbf{x}' = \mathbf{Ax} + \mathbf{c}\]
generate_numeric_solver(state_variables=None, simplify_expression='sympy.simplify(expr)')

Generate the symbolic expressions for numeric integration state updates; return as JSON.

generate_propagator_solver(output_timestep_symbol='__h')

Generate the propagator matrix and symbolic expressions for propagator-based updates; return as JSON.

get_dependency_edges()
get_initial_value(sym)
get_jacobian_matrix()

Get the Jacobian matrix as symbolic expressions. Entries in the matrix are sympy expressions.

If the dynamics of variables \(x_1, \ldots, x_N\) is defined as \(x_i' = f_i\), then row \(i\) of the Jacobian matrix \(\mathbf{J}_i = \left[\begin{matrix}\frac{\partial f_i}{\partial x_0} & \cdots & \frac{\partial f_i}{\partial x_N}\end{matrix}\right]\).

get_lin_cc_symbols(E, differential_order_symbol='__d')

Retrieve the variable symbols of those shapes that are linear and constant coefficient. In the case of a higher-order shape, will return all the variable symbols with "__d" suffixes up to the order of the shape.

get_sub_system(symbols)

Return a new SystemOfShapes instance which discards all symbols and equations except for those in symbols. This is probably only sensible when the elements in symbols do not dependend on any of the other symbols that will be thrown away.

propagate_lin_cc_judgements(node_is_lin, E)

Propagate: if a node depends on a node that is not linear and constant coefficient, it cannot be linear and constant coefficient.

Parameters:
  • node_is_lin – Initial assumption about whether node is linear and constant coefficient.
  • E – List of edges returned from dependency analysis.
reconstitute_expr(state_variables=None, simplify_expression='sympy.simplify(expr)')

Reconstitute a sympy expression from a system of shapes (which is internally encoded in the form Ax + c).

Before returning, the expression is simplified using a custom series of steps, passed via the simplify_expression argument (see the ODE-toolbox documentation for more details).