iaf_chxk_2008#

class brainpy.state.iaf_chxk_2008(in_size, V_th=Quantity(-45., "mV"), g_L=Quantity(100., "nS"), C_m=Quantity(1000., "pF"), E_ex=Quantity(20., "mV"), E_in=Quantity(-90., "mV"), E_L=Quantity(-60., "mV"), tau_syn_ex=Quantity(1., "ms"), tau_syn_in=Quantity(1., "ms"), I_e=Quantity(0., "pA"), tau_ahp=Quantity(0.5, "ms"), E_ahp=Quantity(-95., "mV"), g_ahp=Quantity(443.8, "nS"), ahp_bug=False, gsl_error_tol=0.001, V_initializer=Constant(value=-60. mV), g_ex_initializer=Constant(value=0. nS), g_in_initializer=Constant(value=0. nS), g_ahp_initializer=Constant(value=0. nS), spk_fun=ReluGrad(alpha=0.3, width=1.0), spk_reset='hard', name=None)#

NEST-compatible iaf_chxk_2008 with alpha synapses and precise AHP timing.

Description

iaf_chxk_2008 is a conductance-based leaky integrate-and-fire neuron with alpha-function excitatory/inhibitory synaptic conductances and a spike-triggered after-hyperpolarization (AHP) conductance, developed for modeling retina-LGN transmission (Casti et al., 2008). The implementation follows NEST models/iaf_chxk_2008.{h,cpp} semantics: adaptive RKF45 integration, threshold crossing from below, precise in-step spike timing via linear interpolation, spike-triggered AHP kicks with exact sub-step decay, and optional ahp_bug mode that reproduces the historical single-AHP behavior from the original Fortran code.

1. Membrane and conductance dynamics

Let \(V_m\) be membrane potential (mV), \(g_\mathrm{ex}\), \(g_\mathrm{in}\), \(g_\mathrm{ahp,state}\) be conductance states (nS), and \(I_\mathrm{stim}\) be the one-step buffered external current (pA). Subthreshold dynamics are

\[\frac{dV_m}{dt} = \frac{-I_\mathrm{leak} - I_{\mathrm{syn,ex}} - I_{\mathrm{syn,in}} - I_\mathrm{ahp} + I_e + I_\mathrm{stim}}{C_m},\]

where

\[I_\mathrm{leak} = g_L (V_m - E_L), \quad I_{\mathrm{syn,ex}} = g_\mathrm{ex}(V_m - E_\mathrm{ex}),\]
\[I_{\mathrm{syn,in}} = g_\mathrm{in}(V_m - E_\mathrm{in}), \quad I_\mathrm{ahp} = g_\mathrm{ahp,state}(V_m - E_\mathrm{ahp}).\]

Each conductance channel (excitatory, inhibitory, AHP) evolves as an alpha-function state pair \((dg, g_\mathrm{state})\):

\[\frac{d\,dg}{dt} = -\frac{dg}{\tau}, \qquad \frac{dg_\mathrm{state}}{dt} = dg - \frac{g_\mathrm{state}}{\tau}.\]

Incoming spike weights (nS) are interpreted with sign convention: positive weights drive excitatory channel, negative weights (absolute value) drive inhibitory channel. Jumps are applied to \(dg\) with NEST normalization:

\[dg_\mathrm{ex} \leftarrow dg_\mathrm{ex} + \frac{e}{\tau_\mathrm{ex}} w_+, \qquad dg_\mathrm{in} \leftarrow dg_\mathrm{in} + \frac{e}{\tau_\mathrm{in}} |w_-|.\]

2. Precise output spike timing and AHP kick

A spike is emitted only on threshold crossing from below:

\[V_m(t_k^-) < V_{th} \;\wedge\; V_m(t_k^+) \ge V_{th}.\]

When a crossing is detected, the precise in-step spike time is computed by linear interpolation. Let \(dt_\mathrm{spike}\) be the duration from spike time to step end:

\[dt_\mathrm{spike} = h \frac{V_m(t_k^+) - V_{th}}{V_m(t_k^+) - V_m(t_k^-)},\]

where \(h\) is the step size. The AHP alpha is initialized at spike time and decayed forward to step end:

\[\Delta dg_\mathrm{ahp} = \frac{g_\mathrm{ahp} e}{\tau_\mathrm{ahp}} \exp\!\left(-\frac{dt_\mathrm{spike}}{\tau_\mathrm{ahp}}\right),\]
\[\Delta g_\mathrm{ahp,state} = \Delta dg_\mathrm{ahp}\, dt_\mathrm{spike}.\]

If ahp_bug=True, these values replace the current AHP state (single AHP mode); otherwise they are added (multiple AHP accumulation).

3. Numerical integration via RKF45

The seven coupled ODEs (\(V_m\), three \(dg\) states, three \(g_\mathrm{state}\) variables) are integrated using Runge-Kutta-Fehlberg 4(5) with adaptive step size control. Local truncation error is estimated by comparing 4th and 5th order solutions and step size is adjusted to keep error below gsl_error_tol. Minimum step size is _MIN_H = 1e-8 ms and iteration limit is _MAX_ITERS = 10000 per global step.

4. Update order matching NEST semantics

Each simulation step follows NEST ordering:

  1. Integrate all ODE states over \([t, t+dt]\) via RKF45.

  2. Check threshold crossing from below; if crossed, compute precise spike time and apply AHP kick at that time (with ahp_bug mode if enabled).

  3. Apply arriving signed spike weights to \(dg_\mathrm{ex}\) and \(dg_\mathrm{in}\) after integration completes.

  4. Store incoming continuous current x into buffered I_stim for next step (NEST current-event timing convention).

5. Assumptions, constraints, and failure modes

  • Parameters are scalar or broadcastable to self.varshape.

  • Construction-time constraints enforce C_m > 0, tau_syn_ex > 0, tau_syn_in > 0, tau_ahp > 0.

  • No explicit reset or refractory period: neuron can spike repeatedly if voltage remains above threshold.

  • Adaptive integration can fail if _MAX_ITERS is exceeded; in practice this is rare with reasonable parameter values.

  • Continuous input x passed to update() is delayed by one step via I_stim (ring-buffer semantics), while spike events are applied after ODE integration.

  • Per-step complexity is \(O(|\mathrm{state}| \cdot K_\mathrm{iter})\) where \(K_\mathrm{iter}\) is the number of RKF45 substeps (typically 1-5 per global step).

Parameters:
  • in_size (Size) – Population shape specification. Model parameters and states are broadcast to self.varshape derived from in_size.

  • V_th (ArrayLike, optional) – Spike threshold voltage \(V_{th}\) in mV, broadcastable to self.varshape. Default is -45. * u.mV.

  • g_L (ArrayLike, optional) – Leak conductance \(g_L\) in nS, broadcastable to self.varshape. Default is 100. * u.nS.

  • C_m (ArrayLike, optional) – Membrane capacitance \(C_m\) in pF, broadcastable to self.varshape. Must be strictly positive elementwise. Default is 1000. * u.pF.

  • E_ex (ArrayLike, optional) – Excitatory reversal potential \(E_\mathrm{ex}\) in mV, broadcastable to self.varshape. Default is 20. * u.mV.

  • E_in (ArrayLike, optional) – Inhibitory reversal potential \(E_\mathrm{in}\) in mV, broadcastable to self.varshape. Default is -90. * u.mV.

  • E_L (ArrayLike, optional) – Resting potential \(E_L\) in mV, broadcastable to self.varshape. Default is -60. * u.mV.

  • tau_syn_ex (ArrayLike, optional) – Excitatory alpha time constant \(\tau_\mathrm{ex}\) in ms, broadcastable to self.varshape. Must be strictly positive elementwise. Default is 1. * u.ms.

  • tau_syn_in (ArrayLike, optional) – Inhibitory alpha time constant \(\tau_\mathrm{in}\) in ms, broadcastable to self.varshape. Must be strictly positive elementwise. Default is 1. * u.ms.

  • I_e (ArrayLike, optional) – Constant external current \(I_e\) in pA, broadcastable to self.varshape. Added in each integration substep. Default is 0. * u.pA.

  • tau_ahp (ArrayLike, optional) – AHP alpha time constant \(\tau_\mathrm{ahp}\) in ms, broadcastable to self.varshape. Must be strictly positive elementwise. Default is 0.5 * u.ms.

  • E_ahp (ArrayLike, optional) – AHP reversal potential \(E_\mathrm{ahp}\) in mV, broadcastable to self.varshape. Default is -95. * u.mV.

  • g_ahp (ArrayLike, optional) – AHP kick conductance scale \(g_\mathrm{ahp}\) in nS, broadcastable to self.varshape. Controls magnitude of AHP alpha initialized at each spike. Default is 443.8 * u.nS.

  • ahp_bug (ArrayLike, optional) – Boolean flag (broadcastable to self.varshape) enabling historical single-AHP bug mode. If True, each spike replaces existing AHP state with new AHP kick. If False, AHP kicks accumulate. Default is False.

  • gsl_error_tol (ArrayLike, optional) – Unitless local RKF45 error tolerance, broadcastable and strictly positive. Default is 1e-3.

  • V_initializer (Callable, optional) – Initializer used by init_state() for membrane potential V. Must return mV-compatible values with shape compatible with self.varshape. Default is braintools.init.Constant(-60. * u.mV).

  • g_ex_initializer (Callable, optional) – Initializer for excitatory conductance state g_ex (nS). Default is braintools.init.Constant(0. * u.nS).

  • g_in_initializer (Callable, optional) – Initializer for inhibitory conductance state g_in (nS). Default is braintools.init.Constant(0. * u.nS).

  • g_ahp_initializer (Callable, optional) – Initializer for AHP conductance state g_ahp_state (nS). Default is braintools.init.Constant(0. * u.nS).

  • spk_fun (Callable, optional) – Surrogate spike function used by get_spike() and update(). Receives normalized threshold distance tensor. Default is braintools.surrogate.ReluGrad().

  • spk_reset (str, optional) – Reset policy forwarded to Neuron. 'hard' matches NEST behavior. Default is 'hard'.

  • name (str or None, optional) – Optional node name.

Parameter Mapping

Table 12 Parameter mapping to model symbols#

Parameter

Type / shape / unit

Default

Math symbol

Semantics

in_size

Size; scalar/tuple

required

Defines self.varshape for parameter/state broadcasting.

V_th

ArrayLike, broadcastable to self.varshape (mV)

-45. * u.mV

\(V_{th}\)

Spike threshold voltage.

g_L

ArrayLike, broadcastable (nS)

100. * u.nS

\(g_L\)

Leak conductance.

C_m

ArrayLike, broadcastable (pF), > 0

1000. * u.pF

\(C_m\)

Membrane capacitance.

E_ex

ArrayLike, broadcastable (mV)

20. * u.mV

\(E_\mathrm{ex}\)

Excitatory reversal potential.

E_in

ArrayLike, broadcastable (mV)

-90. * u.mV

\(E_\mathrm{in}\)

Inhibitory reversal potential.

E_L

ArrayLike, broadcastable (mV)

-60. * u.mV

\(E_L\)

Resting potential.

tau_syn_ex

ArrayLike, broadcastable (ms), > 0

1. * u.ms

\(\tau_\mathrm{ex}\)

Excitatory alpha time constant.

tau_syn_in

ArrayLike, broadcastable (ms), > 0

1. * u.ms

\(\tau_\mathrm{in}\)

Inhibitory alpha time constant.

I_e

ArrayLike, broadcastable (pA)

0. * u.pA

\(I_e\)

Constant external current.

tau_ahp

ArrayLike, broadcastable (ms), > 0

0.5 * u.ms

\(\tau_\mathrm{ahp}\)

AHP alpha time constant.

E_ahp

ArrayLike, broadcastable (mV)

-95. * u.mV

\(E_\mathrm{ahp}\)

AHP reversal potential.

g_ahp

ArrayLike, broadcastable (nS)

443.8 * u.nS

\(g_\mathrm{ahp}\)

AHP kick conductance scale.

ahp_bug

ArrayLike broadcastable bool

False

Enable single-AHP historical bug mode.

gsl_error_tol

ArrayLike, broadcastable, unitless, > 0

1e-3

Local absolute tolerance for the embedded RKF45 error estimate.

V_initializer

Callable returning mV-compatible values

Constant(-60. * u.mV)

Initializes membrane state V.

g_ex_initializer

Callable returning nS-compatible values

Constant(0. * u.nS)

Initializes excitatory conductance.

g_in_initializer

Callable returning nS-compatible values

Constant(0. * u.nS)

Initializes inhibitory conductance.

g_ahp_initializer

Callable returning nS-compatible values

Constant(0. * u.nS)

Initializes AHP conductance state.

spk_fun

Callable

ReluGrad()

Surrogate spike output nonlinearity.

spk_reset

str

'hard'

Reset mode inherited from base Neuron.

name

str | None

None

Optional node name.

Raises:
  • ValueError – If validated constraints fail (non-positive capacitance, non-positive time constants, non-positive gsl_error_tol).

  • TypeError – If provided arguments are incompatible with expected units/callables (mV, pA, pF, ms, nS).

  • KeyError – If simulation context values t and/or dt are missing when update() is called.

  • AttributeError – If update() is called before init_state() creates required runtime states.

V#

Membrane potential state in mV.

Type:

HiddenState

dg_ex#

Excitatory conductance rate-of-change state (nS/ms).

Type:

ShortTermState

g_ex#

Excitatory conductance state in nS.

Type:

HiddenState

dg_in#

Inhibitory conductance rate-of-change state (nS/ms).

Type:

ShortTermState

g_in#

Inhibitory conductance state in nS.

Type:

HiddenState

dg_ahp#

AHP conductance rate-of-change state (nS/ms).

Type:

ShortTermState

g_ahp_state#

AHP conductance state in nS.

Type:

HiddenState

I_stim#

One-step buffered external current in pA.

Type:

ShortTermState

integration_step#

Adaptive RKF45 step size hint in ms.

Type:

ShortTermState

last_spike_time#

Absolute precise spike time in ms.

Type:

ShortTermState

Notes

  • The model has no explicit membrane reset or refractory state: after crossing threshold, voltage continues to evolve and can spike again.

  • Continuous input x passed to update() is buffered and affects the next step (NEST current-event timing).

  • Like NEST, this model provides precise output spike timing via linear interpolation but does not process off-grid spike-input offsets.

  • RKF45 integration is performed via the adaptive integrator and written back into BrainUnit states at step end.

  • ahp_bug=True reproduces the original Fortran behavior where only one AHP is tracked; this is primarily for validation against legacy code.

Examples

Create a single neuron with default parameters and simulate:

>>> import brainstate as bs
>>> import saiunit as u
>>> import brainpy.state as bps
>>> neuron = bps.iaf_chxk_2008(1)
>>> with bs.environ.context(dt=0.1 * u.ms):
...     neuron.init_state()
...     spike = neuron.update(100. * u.pA)  # buffered to next step

Inspect AHP kick behavior after spike:

>>> neuron.V.value  # check membrane potential
>>> neuron.g_ahp_state.value  # check AHP conductance state

Recordables

V_m, g_ex, g_in, g_ahp, I_syn_ex, I_syn_in, I_ahp

References

get_spike(V=None)[source]#

Evaluate surrogate spike output from membrane voltage.

Parameters:

V (ArrayLike, optional) – Voltage values with shape broadcastable to self.varshape and units compatible with mV. If None, uses current state self.V.value.

Returns:

Surrogate spike activation produced by spk_fun((V - V_th) / |V_th - E_L|).

Return type:

ArrayLike

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.

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

Advance the neuron by one simulation step.

Parameters:
  • x (ArrayLike, optional) – Continuous external current input in pA, broadcastable to self.varshape. This value is stored into I_stim and applied at the next simulation step (one-step delay).

  • w_ex (ArrayLike or None, optional) – Excitatory synaptic weight increment (nS) to add to dg_ex after integration, scaled by e/tau_syn_ex. When None (default), the value is read from registered delta inputs with label 'w_ex'. Provide an explicit array for JIT-compatible (for_loop) usage.

  • w_in (ArrayLike or None, optional) – Inhibitory synaptic weight increment (nS), analogous to w_ex but for dg_in with label 'w_in'.

Returns:

Binary spike tensor with dtype jnp.float64 and shape self.V.value.shape. A value of 1.0 indicates a threshold crossing from below during the integrated interval \((t, t+dt]\).

Return type:

jax.Array

Notes

Integration uses an adaptive RKF45 loop. Spike detection and AHP kicks follow NEST semantics: crossing is checked at the global step level (comparing V before and after the full integration), and the AHP state is updated post-integration using linear interpolation of the spike time. Synaptic inputs (w_ex, w_in) are applied after integration.