Skip to content

Excitable

Excitable kinetics shared by the biology packages: FitzHugh-Nagumo kinetics, theta neurons, and spike resets.

FitzHughNagumoInteraction(label, *, target, fast='v', slow='w', a=0.7, b=0.8, epsilon=0.08, I=0.0)

Bases: Interaction

FitzHugh-Nagumo kinetics of a fast variable v and a slow recovery w of a target.

The fast variable follows v' = v - v³/3 - w + I and the recovery w' = epsilon (v + a - b w). On a field the kinetics act on every cell, and a diffusion of the fast variable makes the medium excitable.

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
target Annotated[str, RoleSpec()]

The path of the element or field whose states follow the kinetics.

required
fast str

The name of the fast state, such as a membrane potential.

'v'
slow str

The name of the slow recovery state.

'w'
a Annotated[float, ParameterSpec()]

The offset of the recovery.

0.7
b Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The damping of the recovery.

0.8
epsilon Annotated[float, ParameterSpec(domain=open(0, oo))]

The time scale of the recovery.

0.08
I Annotated[float, ParameterSpec()]

The applied current.

0.0

Raises:

Type Description
ValidationError

A state name is not a name, or the fast and the slow state are the same.

Examples:

>>> from typing import Annotated
>>> from skcomplex.core.components.elements import Element
>>> from skcomplex.core.components.system import System
>>> from skcomplex.core.engine.runtime import Simulation
>>> from skcomplex.systems.biology.common.excitable import FitzHughNagumoInteraction
>>> from skcomplex.core.specs import StateSpec
>>> class CellElement(Element):
...     def __init__(
...         self, label, visual=None, *, v: Annotated[float, StateSpec()] = -1.2,
...         w: Annotated[float, StateSpec()] = -0.6,
...     ):
...         super().__init__(label, visual=visual)
...         self.v = v
...         self.w = w
>>> kinetics = FitzHughNagumoInteraction('kinetics', target='cell', I=0.5)
>>> system = System(elements=[CellElement('cell')], interactions=[kinetics])
>>> trajectory = Simulation(system, dt=0.1).prepare().run(until=100.0).trajectory_
>>> bool(trajectory.values('cell.v').max() > 1.5)
True
Source code in src/skcomplex/systems/biology/common/excitable/_fitzhugh_nagumo.py
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
def __init__(
    self,
    label: str,
    *,
    target: Annotated[str, RoleSpec()],
    fast: str = 'v',
    slow: str = 'w',
    a: Annotated[float, ParameterSpec()] = 0.7,
    b: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 0.8,
    epsilon: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.08,
    I: Annotated[float, ParameterSpec()] = 0.0,
) -> None:
    super().__init__(label)
    self.target = target
    self.fast = fast
    self.slow = slow
    self.a = a
    self.b = b
    self.epsilon = epsilon
    self.I = I

SpikeResetInteraction(label, *, target, state='v', threshold=1.0, after=0.0, kicked=None, kick=0.0)

Bases: CrossingInteraction

Spike of a neuron, which resets its potential when it crosses a threshold upwards and kicks a second state.

When the potential v rises through threshold, it is set to after, and the state kicked, such as a recovery variable or a synaptic trace, grows by kick. Every spike is an event labelled by the interaction.

Parameters:

Name Type Description Default
label str

The label of the interaction and of its events.

required
target Annotated[str, RoleSpec()]

The path of the neuron.

required
state str

The name of the potential.

'v'
threshold Annotated[float, ParameterSpec()]

The potential of a spike.

1.0
after Annotated[float, ParameterSpec()]

The potential after a spike.

0.0
kicked str | None

The name of the state a spike increments, or None for none.

None
kick Annotated[float, ParameterSpec()]

The increment of the kicked state at a spike.

0.0

Raises:

Type Description
ValidationError

The direction is not -1, 0, or 1, or the guard or a new value is not a function.

Examples:

>>> from skcomplex.core.components.elements import CompartmentElement
>>> from skcomplex.core.components.interactions import RateInteraction
>>> from skcomplex.core.components.system import System
>>> from skcomplex.core.engine.runtime import Simulation
>>> from skcomplex.systems.biology.neuroscience import SpikeResetInteraction
>>> drive = RateInteraction('drive', target='neuron', state='n', rate=1.0)
>>> spike = SpikeResetInteraction('spike', target='neuron', state='n', threshold=1.0, after=0.0)
>>> system = System(elements=[CompartmentElement('neuron')], interactions=[drive, spike])
>>> trajectory = Simulation(system, dt=0.25).prepare().run(until=2.1).trajectory_
>>> [round(event.time, 6) for event in trajectory.events]
[1.0, 2.0]
Source code in src/skcomplex/systems/biology/common/excitable/_spike_reset.py
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
def __init__(
    self,
    label: str,
    *,
    target: Annotated[str, RoleSpec()],
    state: str = 'v',
    threshold: Annotated[float, ParameterSpec()] = 1.0,
    after: Annotated[float, ParameterSpec()] = 0.0,
    kicked: str | None = None,
    kick: Annotated[float, ParameterSpec()] = 0.0,
) -> None:
    super().__init__(
        label,
        target=target,
        guard=self._get_guard,
        reset=self._get_resets(state, kicked),
        direction=1,
    )
    self.state = state
    self.threshold = threshold
    self.after = after
    self.kicked = kicked
    self.kick = kick

ThetaNeuronElement(label, visual=None, *, theta=0.0, eta=1.0)

Bases: Element

Theta neuron of Ermentrout and Kopell, theta' = (1 - cos theta) + (1 + cos theta) eta, a spiking phase.

The neuron fires when its phase passes π. With eta > 0 it fires periodically with period π / sqrt(eta), and with eta < 0 it is excitable. The change of variable V = tan(theta / 2) turns it into the quadratic integrate-and-fire neuron V' = V² + eta.

Parameters:

Name Type Description Default
label str

The label of the neuron or the group.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
theta Annotated[float, StateSpec(period=2 * pi)]

The initial phase.

0.0
eta Annotated[float, ParameterSpec()]

The excitability.

1.0

Examples:

>>> from skcomplex.core.components.elements import GroupElement
>>> from skcomplex.systems.biology.neuroscience import ThetaNeuronElement
>>> GroupElement('neurons', element=ThetaNeuronElement, size=10, values={'eta': 0.5}).size
10
Source code in src/skcomplex/systems/biology/common/excitable/_theta_neuron.py
43
44
45
46
47
48
49
50
51
52
53
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    theta: Annotated[float, StateSpec(period=2 * pi)] = 0.0,
    eta: Annotated[float, ParameterSpec()] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.theta = theta
    self.eta = eta