.. currentmodule:: brian

Library models
--------------

Membrane equations
^^^^^^^^^^^^^^^^^^
Library models are defined using the :class:`MembraneEquation` class. This is a subclass of
:class:`Equations` which is defined by a capacitance C and a sum of currents. The following instruction::

  eqs=MembraneEquation(200*pF)

defines the equation C*dvm/dt=0*amp, with the membrane capacitance C=200 pF. The name of the membrane potential
variable can be changed as follows::

  eqs=MembraneEquation(200*pF,vm='V')

The main interest of this class is that one can use it to build models by adding currents to a membrane
equation. The :class:`Current` class is a subclass of :class:`Equations` which defines a current to be added
to a membrane equation. For example::

  eqs=MembraneEquation(200*pF)+Current('I=(V0-vm)/R : amp',current_name='I')

defines the same equation as::

  eqs=Equations('''
  dvm/dt=I/(200*pF) : volt
  I=(V0-vm)/R : amp 
  ''')

The keyword ``current_name`` is optional if there is no ambiguity, i.e., if there is only one variable
or only one variable with amp units. As for standard equations, :class:`Current` objects can be initialised with
a multiline string (several equations). By default, the convention for the current direction is the one for injected
current. For the ionic current convention, use the :class:`IonicCurrent` class::

  eqs=MembraneEquation(200*pF)+IonicCurrent('I=(vm-V0)/R : amp')

Compartmental modelling
^^^^^^^^^^^^^^^^^^^^^^^
Compartmental neuron models can be created by merging several :class:`MembraneEquation` objects,
with the ``compartments`` module. If ``soma`` and ``dendrite`` are two compartments defined as
:class:`MembraneEquation` objects, then a neuron with those 2 compartments can be created as follows::

	neuron_eqs=Compartments({'soma':soma,'dendrite':dendrite})
	neuron_eqs.connect('soma','dendrite',Ra)
	neuron=NeuronGroup(1,model=neuron_eqs)

The :class:`Compartments` object is initialised with a dictionary of :class:`MembraneEquation` objects.
The returned object ``neuron_eqs`` is also a :class:`MembraneEquation` object, where the name of
each compartment has been appended to variable names (with a leading underscore).
For example, ``neuron.vm_soma`` refers to variable ``vm`` of the somatic compartment.
The ``connect`` method adds a coupling current between the two named compartments, with the given
resistance ``Ra``.

Integrate-and-Fire models
^^^^^^^^^^^^^^^^^^^^^^^^^
A few standard Integrate-and-Fire models are implemented in the ``IF`` library module::

  from brian.library.IF import *
  
All these functions return :class:`Equations` objects (more precisely, :class:`MembraneEquation` objects).
  
* Leaky integrate-and-fire model (``dvm/dt=(El-vm)/tau : volt``)::

    eqs=leaky_IF(tau=10*ms,El=-70*mV)
    
* Perfect integrator (``dvm/dt=Im/tau : volt``)::

    eqs=perfect_IF(tau=10*ms)

* Quadratic integrate-and-fire model (``C*dvm/dt=a*(vm-EL)*(vm-VT) : volt``)::

    eqs=quadratic_IF(C=200*pF,a=10*nS/mV,EL=-70*mV,VT=-50*mV)

* Exponential integrate-and-fire model (``C*dvm/dt=gL*(EL-vm)+gL*DeltaT*exp((vm-VT)/DeltaT) :volt``)::

    eqs=exp_IF(C=200*pF,gL=10*nS,EL=-70*mV,VT=-55*mV,DeltaT=3*mV)

In general, it is possible to define a neuron group with different parameter values for each neuron, by
passing strings at initialisation. For example, the following code defines leaky integrate-and-fire models
with heterogeneous resting potential values::

  eqs=leaky_IF(tau=10*ms,El='V0')+Equations('V0:volt')
  group=NeuronGroup(100,model=eqs,reset=0*mV,threshold=15*mV) 

Two-dimensional IF models
^^^^^^^^^^^^^^^^^^^^^^^^^
Integrate-and-fire models with two variables can display a very rich set of electrophysiological behaviours.
In Brian, two such models have been implemented: Izhikevich model and Brette-Gerstner adaptive exponential
integrate-and-fire model (also included in the ``IF`` module).
The equations are obtained in the same way as for one-dimensional models::

  eqs=Izhikevich(a=0.02/ms,b=0.2/ms)
  eqs=Brette_Gerstner(C=281*pF,gL=30*nS,EL=-70.6*mV,VT=-50.4*mV,DeltaT=2*mV,tauw=144*ms,a=4*nS)
  eqs=aEIF(C=281*pF,gL=30*nS,EL=-70.6*mV,VT=-50.4*mV,DeltaT=2*mV,tauw=144*ms,a=4*nS) # equivalent

and two state variables are defined: ``vm`` (membrane potential) and ``w`` (adaptation variable).
The equivalent equations for Izhikevich model are::

  dvm/dt=(0.04/ms/mV)*vm**2+(5/ms)*vm+140*mV/ms-w : volt
  dw/dt=a*(b*vm-w)                            : volt/second

and for Brette-Gerstner model::

  C*dvm/dt=gL*(EL-vm)+gL*DeltaT*exp((vm-VT)/DeltaT)-w :volt
  dw/dt=(a*(vm-EL)-w)/tauw : amp
  
To simulate these models, one needs to specify a threshold value, and a good choice is
``VT+4*DeltaT``. The reset is particular in these models since it is bidimensional:
vm->Vr and w->w+b. A specific reset class has been implemented for this purpose:
:class:`AdaptiveReset`, initialised with Vr and b. Thus, a typical construction of a group of
such models is::

  eqs=Brette_Gerstner(C=281*pF,gL=30*nS,EL=-70.6*mV,VT=-50.4*mV,DeltaT=2*mV,tauw=144*ms,a=4*nS)
  group=NeuronGroup(100,model=eqs,threshold=-43*mV,reset=AdaptiveReset(Vr=-70.6*mvolt,b=0.0805*nA))  

Synapses
^^^^^^^^
A few simple synaptic models are implemented in the module ``synapses``::

  from brian.library.synapses import *
  
All the following functions need to be passed the name of the variable upon which the received spikes
will act, and the name of the variable representing the current or conductance.
The simplest one is the exponential synapse::

  eqs=exp_synapse(input='x',tau=10*ms,unit=amp,output='x_current')

It is equivalent to::

  eqs=Equations('''
  dx/dt=-x/tau : amp
  x_out=x
  ''')

Here, ``x`` is the variable which receives the spikes and ``x_current`` is the variable to be inserted in
the membrane equation (since it is a one-dimensional synaptic model, the variables are the same).
If the output variable name is not defined, then it will be automatically generated by adding the
suffix ``_out`` to the input name.

Two other types of synapses are implemented. The alpha synapse (``x(t)=alpha*(t/tau)*exp(1-t/tau)``, where
``alpha`` is a normalising factor) is defined with the same syntax by::

  eqs=alpha_synapse(input='x',tau=10*ms,unit=amp)

and the bi-exponential synapse is defined by (``x(t)=(tau2/(tau2-tau1))*(exp(-t/tau1)-exp(-t/tau2))``,
up to a normalising factor)::

  eqs=biexp_synapse(input='x',tau1=10*ms,tau2=5*ms,unit=amp)

For all types of synapses, the normalising factor is such that the maximum of x(t) is 1.
These functions can be used as in the following example::

  eqs=MembraneEquation(C=200*pF)+Current('I=gl*(El-vm)+ge*(Ee-vm):amp')
  eqs+=alpha_synapse(input='ge_in',tau=10*ms,unit=siemens,output='ge')

where alpha conductances have been inserted in the membrane equation.

One can directly insert synaptic currents with the functions ``exp_current``, ``alpha_current``
and ``biexp_current``::

  eqs=MembraneEquation(C=200*pF)+Current('I=gl*(El-vm):amp')+\
      alpha_current(input='ge',tau=10*ms)

(the units is amp by default), or synaptic conductances with the functions ``exp_conductance``, ``alpha_conductance``
and ``biexp_conductance``::

  eqs=MembraneEquation(C=200*pF)+Current('I=gl*(El-vm):amp')+\
      alpha_conductance(input='ge',E=0*mV,tau=10*ms)

where ``E`` is the reversal potential.

Ionic currents
^^^^^^^^^^^^^^
A few standard ionic currents have implemented in the module ``ionic_currents``::

  from brian.library.ionic_currents import *
 
When the current name is not specified,
a unique name is generated automatically. Models can be constructed by adding currents to a
:class:`MembraneEquation`.

* Leak current (``gl*(El-vm)``)::

    current=leak_current(gl=10*nS,El=-70*mV,current_name='I')

* Hodgkin-Huxley K+ current::

    current=K_current_HH(gmax,EK,current_name='IK'):

* Hodgkin-Huxley Na+ current::

    current=Na_current_HH(gmax,ENa,current_name='INa'):
