# Source code for brainmodels.neurons.MorrisLecar

# -*- coding: utf-8 -*-

import brainpy as bp
import brainpy.math as bm
from .base import Neuron

__all__ = [
'MorrisLecar'
]

[docs]class MorrisLecar(Neuron):
r"""The Morris-Lecar neuron model.

**Model Descriptions**

The Morris-Lecar model [1]_ (Also known as :math:I_{Ca}+I_K-model)
is a two-dimensional "reduced" excitation model applicable to
systems having two non-inactivating voltage-sensitive conductances.
This model was named after Cathy Morris and Harold Lecar, who
derived it in 1981. Because it is two-dimensional, the Morris-Lecar
model is one of the favorite conductance-based models in computational neuroscience.

The original form of the model employed an instantaneously
responding voltage-sensitive Ca2+ conductance for excitation and a delayed
voltage-dependent K+ conductance for recovery. The equations of the model are:

.. math::

\begin{aligned}
C\frac{dV}{dt} =& -  g_{Ca} M_{\infty} (V - V_{Ca})- g_{K} W(V - V_{K}) -
g_{Leak} (V - V_{Leak}) + I_{ext} \\
\frac{dW}{dt} =& \frac{W_{\infty}(V) - W}{ \tau_W(V)}
\end{aligned}

Here, :math:V is the membrane potential, :math:W is the "recovery variable",
which is almost invariably the normalized :math:K^+-ion conductance, and
:math:I_{ext} is the applied current stimulus.

**Model Examples**

.. plot::
:include-source: True

>>> import brainpy as bp
>>> import brainmodels
>>>
>>> group = brainmodels.neurons.MorrisLecar(1)
>>> runner = bp.StructRunner(group, monitors=['V', 'W'], inputs=('input', 100.))
>>> runner.run(1000)
>>>
>>> fig, gs = bp.visualize.get_figure(2, 1, 3, 8)
>>> bp.visualize.line_plot(runner.mon.ts, runner.mon.W, ylabel='W')
>>> bp.visualize.line_plot(runner.mon.ts, runner.mon.V, ylabel='V', show=True)

**Model Parameters**

============= ============== ======== =======================================================
**Parameter** **Init Value** **Unit** **Explanation**
------------- -------------- -------- -------------------------------------------------------
V_Ca          130            mV       Equilibrium potentials of Ca+.(mV)
g_Ca          4.4            \        Maximum conductance of corresponding Ca+.(mS/cm2)
V_K           -84            mV       Equilibrium potentials of K+.(mV)
g_K           8              \        Maximum conductance of corresponding K+.(mS/cm2)
V_Leak        -60            mV       Equilibrium potentials of leak current.(mV)
g_Leak        2              \        Maximum conductance of leak current.(mS/cm2)
C             20             \        Membrane capacitance.(uF/cm2)
V1            -1.2           \        Potential at which M_inf = 0.5.(mV)
V2            18             \        Reciprocal of slope of voltage dependence of M_inf.(mV)
V3            2              \        Potential at which W_inf = 0.5.(mV)
V4            30             \        Reciprocal of slope of voltage dependence of W_inf.(mV)
phi           0.04           \        A temperature factor. (1/s)
V_th          10             mV       The spike threshold.
============= ============== ======== =======================================================

**Model Variables**

================== ================= =========================================================
**Variables name** **Initial Value** **Explanation**
------------------ ----------------- ---------------------------------------------------------
V                  -20               Membrane potential.
W                  0.02              Gating variable, refers to the fraction of
opened K+ channels.
input              0                 External and synaptic input current.
spike              False             Flag to mark whether the neuron is spiking.
t_last_spike       -1e7              Last spike time stamp.
================== ================= =========================================================

**References**

.. [1] Meier, Stephen R., Jarrett L. Lancaster, and Joseph M. Starobin.
"Bursting regimes in a reaction-diffusion system with action
potential-dependent equilibrium." PloS one 10.3 (2015):
e0122401.
.. [2] http://www.scholarpedia.org/article/Morris-Lecar_model
.. [3] https://en.wikipedia.org/wiki/Morris%E2%80%93Lecar_model
"""

[docs]  def __init__(self, size, V_Ca=130., g_Ca=4.4, V_K=-84., g_K=8., V_leak=-60.,
g_leak=2., C=20., V1=-1.2, V2=18., V3=2., V4=30., phi=0.04,
V_th=10., method='exp_auto', name=None):
# initialization
super(MorrisLecar, self).__init__(size=size, method=method, name=name)

# params
self.V_Ca = V_Ca
self.g_Ca = g_Ca
self.V_K = V_K
self.g_K = g_K
self.V_leak = V_leak
self.g_leak = g_leak
self.C = C
self.V1 = V1
self.V2 = V2
self.V3 = V3
self.V4 = V4
self.phi = phi
self.V_th = V_th

# vars
self.W = bm.Variable(bm.ones(self.num) * 0.02)

def dV(self, V, t, W, Iext):
M_inf = (1 / 2) * (1 + bm.tanh((V - self.V1) / self.V2))
I_Ca = self.g_Ca * M_inf * (V - self.V_Ca)
I_K = self.g_K * W * (V - self.V_K)
I_Leak = self.g_leak * (V - self.V_leak)
dVdt = (- I_Ca - I_K - I_Leak + Iext) / self.C
return dVdt

def dW(self, W, t, V):
tau_W = 1 / (self.phi * bm.cosh((V - self.V3) / (2 * self.V4)))
W_inf = (1 / 2) * (1 + bm.tanh((V - self.V3) / self.V4))
dWdt = (W_inf - W) / tau_W
return dWdt

@property
def derivative(self):
return bp.JointEq([self.dV, self.dW])

[docs]  def update(self, _t, _dt):
V, self.W.value = self.integral(self.V, self.W, _t, self.input, dt=_dt)
spike = bm.logical_and(self.V < self.V_th, V >= self.V_th)
self.t_last_spike.value = bm.where(spike, _t, self.t_last_spike)
self.V.value = V
self.spike.value = spike
self.input[:] = 0.