glif_cond#

class brainpy.state.glif_cond(in_size, g=Quantity(9.43, 'nS'), E_L=Quantity(-78.85, 'mV'), V_th=Quantity(-51.68, 'mV'), C_m=Quantity(58.72, 'pF'), t_ref=Quantity(3.75, 'ms'), V_reset=Quantity(-78.85, 'mV'), th_spike_add=0.37, th_spike_decay=0.009, voltage_reset_fraction=0.2, voltage_reset_add=18.51, th_voltage_index=0.005, th_voltage_decay=0.09, asc_init=(0.0, 0.0), asc_decay=(0.003, 0.1), asc_amps=(-9.18, -198.94), asc_r=(1.0, 1.0), tau_syn=(0.2, 2.0), E_rev=(0.0, -85.0), spike_dependent_threshold=False, after_spike_currents=False, adapting_threshold=False, I_e=Quantity(0., 'pA'), V_initializer=None, spk_fun=ReluGrad(alpha=0.3, width=1.0), spk_reset='hard', name=None)#

Conductance-based generalized leaky integrate-and-fire (GLIF) neuron model.

Implements the five-level GLIF model hierarchy from Teeter et al. (2018) [1], with conductance-based alpha-function synapses and adaptive RKF45 integration. Designed for fitting to Allen Institute single-neuron electrophysiology data. Supports multiple receptor ports with distinct reversal potentials and synaptic time constants.

Model Selection

The five GLIF variants are:

  1. GLIF1 (LIF) — Traditional leaky integrate-and-fire

  2. GLIF2 (LIF_R) — LIF with biologically defined voltage reset rules

  3. GLIF3 (LIF_ASC) — LIF with after-spike currents (adaptation)

  4. GLIF4 (LIF_R_ASC) — LIF with reset rules and after-spike currents

  5. GLIF5 (LIF_R_ASC_A) — LIF with reset rules, after-spike currents, and voltage-dependent threshold

Model mechanism selection is controlled by three boolean parameters:

Model

spike_dependent_threshold

after_spike_currents

adapting_threshold

GLIF1

False

False

False

GLIF2

True

False

False

GLIF3

False

True

False

GLIF4

True

True

False

GLIF5

True

True

True

Mathematical Formulation

1. Membrane Dynamics

The membrane potential \(V\) (tracked relative to \(E_L\) internally) evolves according to:

\[C_\mathrm{m} \frac{dV}{dt} = -g \cdot V - \sum_k g_k(t) \left( V + E_L - E_{\mathrm{rev},k} \right) + I_\mathrm{e} + I_\mathrm{ASC,sum}\]

where:

  • \(g\) — membrane (leak) conductance

  • \(g_k(t)\) — synaptic conductance for receptor port \(k\)

  • \(E_{\mathrm{rev},k}\) — reversal potential for port \(k\)

  • \(I_\mathrm{e}\) — constant external current

  • \(I_\mathrm{ASC,sum}\) — sum of after-spike currents (GLIF3/4/5 only)

2. Synaptic Conductances (Alpha Function)

Each receptor port \(k\) has a conductance modeled by an alpha function with two state variables \(dg_k\) and \(g_k\):

\[\frac{d(dg_k)}{dt} = -\frac{dg_k}{\tau_{\mathrm{syn},k}}\]
\[\frac{dg_k}{dt} = dg_k - \frac{g_k}{\tau_{\mathrm{syn},k}}\]

On a presynaptic spike with weight \(w\), the derivative is incremented:

\[dg_k \leftarrow dg_k + w \cdot \frac{e}{\tau_{\mathrm{syn},k}}\]

This normalization ensures that a spike of weight 1.0 produces a peak conductance of 1 nS at time \(t = \tau_{\mathrm{syn},k}\).

3. After-Spike Currents (GLIF3/4/5)

After-spike currents (ASC) model spike-triggered adaptation as exponentially decaying currents. Each ASC component \(I_j\) decays with rate \(k_j\):

\[I_j(t+dt) = I_j(t) \cdot \exp(-k_j \cdot dt)\]

The time-averaged ASC over a simulation step uses the exact integral (stable coefficient method):

\[\bar{I}_j = \frac{1 - \exp(-k_j \cdot dt)}{k_j \cdot dt} \cdot I_j(t)\]

On spike, ASC values are updated with amplitude and refractory decay:

\[I_j \leftarrow \Delta I_j + I_j \cdot r_j \cdot \exp(-k_j \cdot t_\mathrm{ref})\]

where \(\Delta I_j\) is the amplitude jump and \(r_j \in [0, 1]\) is the retention fraction.

4. Spike-Dependent Threshold (GLIF2/4/5)

The spike component of the threshold \(\theta_s\) decays exponentially:

\[\theta_s(t+dt) = \theta_s(t) \cdot \exp(-b_s \cdot dt)\]

On spike, after accounting for refractory decay, it is incremented:

\[\theta_s \leftarrow \theta_s \cdot \exp(-b_s \cdot t_\mathrm{ref}) + \Delta\theta_s\]

Voltage reset with spike-dependent threshold uses:

\[V \leftarrow f_v \cdot V_\mathrm{old} + V_\mathrm{add}\]

where \(f_v \in [0, 1]\) is the fraction coefficient and \(V_\mathrm{add}\) is the additive term (both in mV, dimensionless in NEST convention).

5. Voltage-Dependent Threshold (GLIF5)

The voltage component \(\theta_v\) evolves according to:

\[\theta_v(t+dt) = \phi \cdot (V_\mathrm{old} - \beta) \cdot P_\mathrm{decay} + \frac{1}{P_{\theta,v}} \cdot \left(\theta_v(t) - \phi \cdot (V_\mathrm{old} - \beta) - \frac{a_v}{b_v} \cdot \beta \right) + \frac{a_v}{b_v} \cdot \beta\]

where:

  • \(\phi = a_v / (b_v - g/C_m)\)

  • \(P_\mathrm{decay} = \exp(-g \cdot dt / C_m)\)

  • \(P_{\theta,v} = \exp(b_v \cdot dt)\)

  • \(\beta = (I_e + I_\mathrm{ASC,sum}) / g\)

The total threshold is the sum of all components:

\[\theta = \theta_\infty + \theta_s + \theta_v\]

Spike condition (checked after ODE integration):

\[V > \theta\]

Numerical Integration

The ODE system \([V, dg_0, g_0, dg_1, g_1, \ldots]\) is integrated using an adaptive RKF45(4,5) Runge-Kutta-Fehlberg method with error tolerance ATOL = 1e-3 and minimum step size MIN_H = 1e-8 ms, matching NEST’s GSL integrator behavior.

Update Order (Per Simulation Step)

  1. Record \(V_\mathrm{old}\) (relative to \(E_L\))

  2. Integrate ODE system over \((t, t+dt]\) using RKF45

  3. If not refractory:

    1. Decay spike threshold component \(\theta_s\)

    2. Compute time-averaged ASC \(\bar{I}_\mathrm{ASC,sum}\) and decay ASC values

    3. Compute voltage-dependent threshold \(\theta_v\) (using \(V_\mathrm{old}\))

    4. Update total threshold \(\theta = \theta_\infty + \theta_s + \theta_v\)

    5. If \(V > \theta\): emit spike, apply reset rules

  4. If refractory: decrement counter, clamp \(V\) to \(V_\mathrm{old}\)

  5. Add incoming spike conductance jumps (scaled by \(e/\tau_\mathrm{syn}\))

  6. Update external current buffer \(I_\mathrm{stim}\)

  7. Save \(V_\mathrm{old}\) for next step

Parameters:
  • in_size (Size) – Shape of the neuron population. Can be an int for 1D or tuple for multi-D.

  • g (ArrayLike, optional) – Membrane (leak) conductance in nS. Broadcast to population shape. Default: 9.43 nS (from Allen Cell 490626718 GLIF5).

  • E_L (ArrayLike, optional) – Resting membrane potential (leak reversal) in mV. Default: -78.85 mV.

  • V_th (ArrayLike, optional) – Instantaneous spike threshold (absolute) in mV. Default: -51.68 mV. Internally, threshold is tracked relative to E_L.

  • C_m (ArrayLike, optional) – Membrane capacitance in pF. Must be strictly positive. Default: 58.72 pF.

  • t_ref (ArrayLike, optional) – Absolute refractory period in ms. During this period, voltage is clamped and spike detection is disabled. Must be > 0. Default: 3.75 ms.

  • V_reset (ArrayLike, optional) – Reset potential (absolute) in mV for GLIF1/3 models. Ignored if spike_dependent_threshold=True. Default: -78.85 mV (same as E_L).

  • th_spike_add (float, optional) – Threshold additive constant \(\Delta\theta_s\) after spike (mV, dimensionless in NEST units). Only used if spike_dependent_threshold=True. Default: 0.37 mV.

  • th_spike_decay (float, optional) – Spike threshold decay rate \(b_s\) in 1/ms. Must be > 0 if spike_dependent_threshold=True. Default: 0.009 /ms.

  • voltage_reset_fraction (float, optional) – Voltage fraction coefficient \(f_v \in [0, 1]\) after spike. Only used if spike_dependent_threshold=True. Default: 0.20.

  • voltage_reset_add (float, optional) – Voltage additive term \(V_\mathrm{add}\) after spike (mV, dimensionless). Only used if spike_dependent_threshold=True. Default: 18.51 mV.

  • th_voltage_index (float, optional) – Voltage-dependent threshold leak \(a_v\) in 1/ms. Only used if adapting_threshold=True. Default: 0.005 /ms.

  • th_voltage_decay (float, optional) – Voltage-dependent threshold decay rate \(b_v\) in 1/ms. Must be > 0 if adapting_threshold=True. Default: 0.09 /ms.

  • asc_init (Sequence[float], optional) – Initial values of after-spike currents in pA. Tuple/list of length n_asc. Default: (0.0, 0.0) pA.

  • asc_decay (Sequence[float], optional) – ASC decay rates \(k_j\) in 1/ms. All values must be > 0. Length must match asc_init. Default: (0.003, 0.1) /ms.

  • asc_amps (Sequence[float], optional) – ASC amplitude jumps \(\Delta I_j\) on spike, in pA. Length must match asc_init. Negative values cause hyperpolarizing adaptation. Default: (-9.18, -198.94) pA.

  • asc_r (Sequence[float], optional) – ASC retention fraction coefficients \(r_j \in [0, 1]\). Length must match asc_init. Default: (1.0, 1.0).

  • tau_syn (Sequence[float], optional) – Synaptic alpha-function time constants \(\tau_{\mathrm{syn},k}\) in ms, one per receptor port. All values must be > 0. Default: (0.2, 2.0) ms (fast excitatory, slow inhibitory).

  • E_rev (Sequence[float], optional) – Synaptic reversal potentials \(E_{\mathrm{rev},k}\) in mV, one per receptor port. Must have same length as tau_syn. Default: (0.0, -85.0) mV (excitatory, inhibitory).

  • spike_dependent_threshold (bool, optional) – Enable biologically defined voltage reset rules (GLIF2/4/5). Default: False.

  • after_spike_currents (bool, optional) – Enable after-spike currents (adaptation) (GLIF3/4/5). Default: False.

  • adapting_threshold (bool, optional) – Enable voltage-dependent threshold component (GLIF5 only). Requires spike_dependent_threshold=True and after_spike_currents=True. Default: False.

  • I_e (ArrayLike, optional) – Constant external current in pA. Broadcast to population shape. Default: 0.0 pA.

  • V_initializer (Callable, optional) – Initializer for membrane potential. If None, defaults to Constant(E_L).

  • spk_fun (Callable, optional) – Surrogate gradient function for spike generation. Default: ReluGrad().

  • spk_reset (str, optional) – Spike reset mode: 'hard' (stop gradient) or 'soft' (subtract threshold). Default: 'hard'.

  • name (str, optional) – Name of the neuron population.

Parameter Mapping

Parameter

Default

Math equivalent

Description

in_size

(required)

Population shape

g

9.43 nS

\(g\)

Membrane (leak) conductance

E_L

-78.85 mV

\(E_L\)

Resting membrane potential

V_th

-51.68 mV

\(V_\mathrm{th}\)

Instantaneous threshold (absolute)

C_m

58.72 pF

\(C_\mathrm{m}\)

Membrane capacitance

t_ref

3.75 ms

\(t_\mathrm{ref}\)

Absolute refractory period

V_reset

-78.85 mV

\(V_\mathrm{reset}\)

Reset potential (absolute; GLIF1/3)

th_spike_add

0.37 mV

\(\Delta\theta_s\)

Threshold additive constant after spike

th_spike_decay

0.009 /ms

\(b_s\)

Spike threshold decay rate

voltage_reset_fraction

0.20

\(f_v\)

Voltage fraction after spike

voltage_reset_add

18.51 mV

\(V_\mathrm{add}\)

Voltage additive after spike

th_voltage_index

0.005 /ms

\(a_v\)

Voltage-dependent threshold leak

th_voltage_decay

0.09 /ms

\(b_v\)

Voltage-dependent threshold decay rate

asc_init

(0.0, 0.0) pA

Initial values of ASC

asc_decay

(0.003, 0.1) /ms

\(k_j\)

ASC time constants (decay rates)

asc_amps

(-9.18, -198.94) pA

\(\Delta I_j\)

ASC amplitudes on spike

asc_r

(1.0, 1.0)

\(r_j\)

ASC fraction coefficient

tau_syn

(0.2, 2.0) ms

\(\tau_{\mathrm{syn},k}\)

Synaptic alpha-function time constants

E_rev

(0.0, -85.0) mV

\(E_{\mathrm{rev},k}\)

Synaptic reversal potentials

spike_dependent_threshold

False

Enable biologically defined reset (GLIF2/4/5)

after_spike_currents

False

Enable after-spike currents (GLIF3/4/5)

adapting_threshold

False

Enable voltage-dependent threshold (GLIF5)

I_e

0.0 pA

\(I_e\)

Constant external current

V_initializer

Constant(E_L)

Membrane potential initializer

spk_fun

ReluGrad()

Surrogate spike function

spk_reset

'hard'

Reset mode

V#

Membrane potential in mV (absolute, broadcast to population shape).

Type:

HiddenState

g_syn#

Synaptic conductances \(g_k\) in nS, one per receptor port.

Type:

list[HiddenState]

dg_syn#

Synaptic conductance derivatives \(dg_k\) in nS, one per receptor port.

Type:

list[HiddenState]

last_spike_time#

Time of last spike in ms.

Type:

ShortTermState

refractory_step_count#

Remaining refractory steps (int32), decremented each step.

Type:

ShortTermState

integration_step#

Internal RKF45 adaptive step size in ms (updated per neuron).

Type:

ShortTermState

I_stim#

Buffered external current in pA (applied with one-step delay).

Type:

ShortTermState

Notes

Implementation Details

  • Internal state convention: Membrane potential is tracked relative to E_L internally (matching NEST), but exposed as absolute values in mV.

  • Threshold components: _threshold_spike, _threshold_voltage, and _th_inf are stored as numpy arrays (not JAX) for exact NEST replication.

  • After-spike currents: _ASCurrents is a numpy array of shape (n_asc, *in_size).

  • Receptor port routing: Delta inputs (from projections) with keys containing 'receptor_<k>' (0-based) are routed to receptor port k. Inputs without a receptor tag default to receptor 0.

  • Stability constraint: For GLIF2/4/5, the reset condition must satisfy:

    \[E_L + f_v \cdot (V_\mathrm{th} - E_L) + V_\mathrm{add} < V_\mathrm{th} + \Delta\theta_s\]

    Otherwise the neuron may spike continuously.

  • Valid mechanism combinations: Only the five combinations listed in the parameter table are valid. Other combinations will raise ValueError.

  • Adaptive integration: RKF45 step size adapts per-neuron and is preserved across simulation steps.

Failure Modes

  • Raises ValueError if parameter validation fails (invalid model combination, non-positive capacitance/conductance/time constants, mismatched sequence lengths).

  • Raises ValueError if V_reset >= V_th (relative to E_L).

  • Integration may fail to converge if dt is too large relative to tau_syn or if threshold parameters cause continuous spiking.

Default Parameters

Default parameter values are from GLIF Model 5 of Cell 490626718 from the Allen Cell Type Database, fitted to mouse visual cortex layer 5 pyramidal neuron electrophysiology.

References

Examples

Example 1: GLIF1 (simple LIF) with dual-receptor synapses

>>> import brainpy.state as bst
>>> import saiunit as u
>>> import brainstate as bts
>>> # Create GLIF1 neuron (all mechanisms disabled)
>>> neuron = bst.glif_cond(
...     100,
...     spike_dependent_threshold=False,
...     after_spike_currents=False,
...     adapting_threshold=False,
...     tau_syn=(0.2, 2.0),  # fast excitatory, slow inhibitory
...     E_rev=(0.0, -85.0)   # mV
... )
>>> neuron.init_all_states()
>>> # Stimulate with constant current
>>> with bts.environ.context(dt=0.1 * u.ms):
...     for _ in range(100):
...         spike = neuron(200.0 * u.pA)

Example 2: GLIF5 (full model) with custom parameters

>>> # Create GLIF5 with all mechanisms enabled
>>> neuron = bst.glif_cond(
...     (10, 10),  # 10x10 population
...     spike_dependent_threshold=True,
...     after_spike_currents=True,
...     adapting_threshold=True,
...     g=10.0 * u.nS,
...     C_m=100.0 * u.pF,
...     tau_syn=(0.5, 1.5, 5.0),  # three receptor ports
...     E_rev=(0.0, 0.0, -80.0)   # two excitatory, one inhibitory
... )
>>> neuron.init_all_states()
>>> print(neuron.n_receptors)  # 3

Example 3: Multi-receptor input routing

>>> from brainevent.nn import FixedProb
>>> # Create projection targeting receptor 1
>>> proj = bst.align_post_projection(
...     pre=pre_neurons,
...     post=glif_neurons,
...     comm=FixedProb(0.1, weight=0.5 * u.nS),
...     label='receptor_1'  # route to receptor port 1
... )

See also

iaf_cond_exp

Simpler conductance-based LIF with exponential synapses

gif_cond_exp_multisynapse

Generalized integrate-and-fire with exponential synapses

glif_psc

Current-based GLIF variant

get_spike(V=None)[source]#

Generate surrogate spike signal from membrane potential.

Computes a differentiable spike signal by scaling membrane potential relative to threshold range and applying the surrogate gradient function.

Parameters:

V (ArrayLike, optional) – Membrane potential in mV. If None, uses self.V.value. Shape: (*batch_dims, *in_size).

Returns:

spike – Surrogate spike output in [0, 1], same shape as input. Values near 1 indicate spiking neurons.

Return type:

ArrayLike

Notes

Scaling: \(v_\mathrm{scaled} = (V - V_\mathrm{th}) / (V_\mathrm{th} - V_\mathrm{reset})\)

This method is used internally for gradient computation but does not affect the discrete spike logic in update().

init_state(**kwargs)[source]#

Initialize persistent and short-term state variables.

Parameters:

**kwargs – Unused compatibility parameters accepted by the base-state API.

Raises:
  • ValueError – If an initializer cannot be broadcast to requested shape.

  • TypeError – If initializer outputs have incompatible units/dtypes for the corresponding state variables.

property n_receptors#

Number of synaptic receptor ports.

Returns:

Number of receptor ports, determined by length of tau_syn.

Return type:

int

update(x=Quantity(0., 'pA'))[source]#

Perform a single simulation step with GLIF dynamics.

Executes the full GLIF update cycle: ODE integration via RKF45, threshold computation (spike/voltage-dependent components if enabled), spike detection, reset rules, refractory handling, and synaptic input application.

This method is JIT-traceable and compatible with brainstate.transform.for_loop.

Parameters:

x (ArrayLike, optional) – External current input in pA. Shape: scalar or (*in_size,). Applied with one-step delay (buffered to I_stim and used in next step). Default: 0.0 pA.

Returns:

spike – Binary spike output (float32), shape (*in_size).

Return type:

jax.Array

See also

get_spike

Compute surrogate spike signal for gradient computation