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:
GLIF1 (LIF) — Traditional leaky integrate-and-fire
GLIF2 (LIF_R) — LIF with biologically defined voltage reset rules
GLIF3 (LIF_ASC) — LIF with after-spike currents (adaptation)
GLIF4 (LIF_R_ASC) — LIF with reset rules and after-spike currents
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-3and minimum step sizeMIN_H = 1e-8ms, matching NEST’s GSL integrator behavior.Update Order (Per Simulation Step)
Record \(V_\mathrm{old}\) (relative to \(E_L\))
Integrate ODE system over \((t, t+dt]\) using RKF45
If not refractory:
Decay spike threshold component \(\theta_s\)
Compute time-averaged ASC \(\bar{I}_\mathrm{ASC,sum}\) and decay ASC values
Compute voltage-dependent threshold \(\theta_v\) (using \(V_\mathrm{old}\))
Update total threshold \(\theta = \theta_\infty + \theta_s + \theta_v\)
If \(V > \theta\): emit spike, apply reset rules
If refractory: decrement counter, clamp \(V\) to \(V_\mathrm{old}\)
Add incoming spike conductance jumps (scaled by \(e/\tau_\mathrm{syn}\))
Update external current buffer \(I_\mathrm{stim}\)
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 toE_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 ifspike_dependent_threshold=True. Default: -78.85 mV (same asE_L).th_spike_add (
float, optional) – Threshold additive constant \(\Delta\theta_s\) after spike (mV, dimensionless in NEST units). Only used ifspike_dependent_threshold=True. Default: 0.37 mV.th_spike_decay (
float, optional) – Spike threshold decay rate \(b_s\) in 1/ms. Must be > 0 ifspike_dependent_threshold=True. Default: 0.009 /ms.voltage_reset_fraction (
float, optional) – Voltage fraction coefficient \(f_v \in [0, 1]\) after spike. Only used ifspike_dependent_threshold=True. Default: 0.20.voltage_reset_add (
float, optional) – Voltage additive term \(V_\mathrm{add}\) after spike (mV, dimensionless). Only used ifspike_dependent_threshold=True. Default: 18.51 mV.th_voltage_index (
float, optional) – Voltage-dependent threshold leak \(a_v\) in 1/ms. Only used ifadapting_threshold=True. Default: 0.005 /ms.th_voltage_decay (
float, optional) – Voltage-dependent threshold decay rate \(b_v\) in 1/ms. Must be > 0 ifadapting_threshold=True. Default: 0.09 /ms.asc_init (
Sequence[float], optional) – Initial values of after-spike currents in pA. Tuple/list of lengthn_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 matchasc_init. Default: (0.003, 0.1) /ms.asc_amps (
Sequence[float], optional) – ASC amplitude jumps \(\Delta I_j\) on spike, in pA. Length must matchasc_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 matchasc_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 astau_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). Requiresspike_dependent_threshold=Trueandafter_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 toConstant(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
g9.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_m58.72 pF
\(C_\mathrm{m}\)
Membrane capacitance
t_ref3.75 ms
\(t_\mathrm{ref}\)
Absolute refractory period
V_reset-78.85 mV
\(V_\mathrm{reset}\)
Reset potential (absolute; GLIF1/3)
th_spike_add0.37 mV
\(\Delta\theta_s\)
Threshold additive constant after spike
th_spike_decay0.009 /ms
\(b_s\)
Spike threshold decay rate
voltage_reset_fraction0.20
\(f_v\)
Voltage fraction after spike
voltage_reset_add18.51 mV
\(V_\mathrm{add}\)
Voltage additive after spike
th_voltage_index0.005 /ms
\(a_v\)
Voltage-dependent threshold leak
th_voltage_decay0.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_thresholdFalse
Enable biologically defined reset (GLIF2/4/5)
after_spike_currentsFalse
Enable after-spike currents (GLIF3/4/5)
adapting_thresholdFalse
Enable voltage-dependent threshold (GLIF5)
I_e0.0 pA
\(I_e\)
Constant external current
V_initializerConstant(E_L)
Membrane potential initializer
spk_funReluGrad()
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_Linternally (matching NEST), but exposed as absolute values in mV.Threshold components:
_threshold_spike,_threshold_voltage, and_th_infare stored as numpy arrays (not JAX) for exact NEST replication.After-spike currents:
_ASCurrentsis 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 portk. 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
ValueErrorif parameter validation fails (invalid model combination, non-positive capacitance/conductance/time constants, mismatched sequence lengths).Raises
ValueErrorifV_reset >= V_th(relative toE_L).Integration may fail to converge if
dtis too large relative totau_synor 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_expSimpler conductance-based LIF with exponential synapses
gif_cond_exp_multisynapseGeneralized integrate-and-fire with exponential synapses
glif_pscCurrent-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, usesself.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:
- 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 toI_stimand used in next step). Default: 0.0 pA.- Returns:
spike – Binary spike output (float32), shape
(*in_size).- Return type:
jax.Array
See also
get_spikeCompute surrogate spike signal for gradient computation