iaf_psc_delta_ps#
- class brainpy.state.iaf_psc_delta_ps(in_size, E_L=Quantity(-70., "mV"), C_m=Quantity(250., "pF"), tau_m=Quantity(10., "ms"), t_ref=Quantity(2., "ms"), V_th=Quantity(-55., "mV"), V_reset=Quantity(-70., "mV"), I_e=Quantity(0., "pA"), V_min=None, V_initializer=Constant(value=-70. mV), spk_fun=ReluGrad(alpha=0.3, width=1.0), spk_reset='hard', refractory_input=False, ref_var=False, name=None)#
NEST-compatible
iaf_psc_delta_pswith precise spike timing.Description
iaf_psc_delta_psis a current-based leaky integrate-and-fire neuron with delta-shaped synaptic jumps (weights in mV), exact linear subthreshold integration, and precise off-grid spike timing inside each global simulation step. The implementation follows NESTmodels/iaf_psc_delta_ps.{h,cpp}semantics, including event ordering by within-step offsets, analytic threshold-crossing localization for current-driven spikes, and optional accumulation of refractory-time inputs.1. Linear Membrane Dynamics and Exact Closed-Form Propagator
The subthreshold membrane potential dynamics are
\[\frac{dV_m}{dt} = -\frac{V_m - E_L}{\tau_m} + \frac{I_\mathrm{ext}(t) + I_e}{C_m},\]with piecewise-constant \(I_\mathrm{ext}\) over each simulation step.
Defining \(U = V_m - E_L\), \(R = \tau_m / C_m\), and a constant current over an interval \(\Delta t\), exact integration gives
\[U(t + \Delta t) = U(t)e^{-\Delta t/\tau_m} + R(I_\mathrm{ext}+I_e)\left(1 - e^{-\Delta t/\tau_m}\right).\]The code evaluates this update with
expm1-based algebra for numerical stability when \(\Delta t/\tau_m\) is small, which reduces cancellation error in fine-step simulations.2. Spike Generation Mechanisms and Precise Spike-Time Derivation
Two spike mechanisms are implemented:
Instantaneous event-driven spikes: if an incoming delta event at offset \(\delta\) pushes \(U \ge U_{th}\), spike time is the event time exactly.
Current-driven spikes: if propagation yields \(U \ge U_{th}\), spike offset is solved analytically from the exact trajectory:
\[\Delta t_\mathrm{cross} = -\tau_m \log\frac{V_\infty - U}{V_\infty - U_{th}}, \quad V_\infty = R(I_\mathrm{ext}+I_e).\]
The model stores:
last_spike_time: absolute spike time in ms,last_spike_offset: off-grid offset relative to the right border of the current grid step (NEST semantics),last_spike_step: on-grid step index used internally for refractory logic.
3. Refractory Handling and Deferred Refractory-Input Accumulation
After a spike, membrane potential is reset to
V_resetand clamped during the absolute refractory period.In NEST
iaf_psc_delta_ps, refractory duration in steps is derived asfloor(t_ref / dt)(viaTime(...).get_steps()) and must be at least one simulation step. This implementation enforces the same runtime constraint.By default, spikes arriving during refractory are discarded. If
refractory_input=True, they are accumulated and exponentially damped until end of refractoriness, then applied once at refractory release, matching NEST.4. Event Ordering, Assumptions, Constraints, and Computational Implications
For each simulation step the update proceeds as follows:
Optional immediate spike if state starts super-threshold.
Process within-step events in offset order (start to end of step):
propagate to event time (if non-refractory),
check current-driven crossing,
apply event jump and check instant crossing.
Propagate remaining interval (if any).
Store new external current input buffer for next step.
Assumptions and constraints used by the implementation:
Parameter tensors are scalar or broadcastable to
self.varshape.Required physical inequalities are validated at construction:
V_reset < V_th,C_m > 0,tau_m > 0,t_ref >= 0, and ifV_minis provided thenV_reset >= V_min.Runtime requires
floor(t_ref / dt) >= 1anddt > 0.Every precise event offset must satisfy
0 <= offset <= dt.
Computationally, the update iterates scalar-wise over
np.ndindexacross the full state shape and processes all local events in each cell, so cost is \(O(|\mathrm{state}| \cdot K)\) per step forKevents (excluding input aggregation).- Parameters:
in_size (
Size) – Population shape specification used to deriveself.varshape. Scalar integer for 1D populations or tuple for multi-dimensional.E_L (
ArrayLike, optional) – Resting membrane potential \(E_L\) in mV. Scalar or array-like broadcastable toself.varshape. Default is-70. * u.mV.C_m (
ArrayLike, optional) – Membrane capacitance \(C_m\) in pF, broadcastable toself.varshape. Must be strictly positive elementwise. Default is250. * u.pF.tau_m (
ArrayLike, optional) – Membrane time constant \(\tau_m\) in ms, broadcastable toself.varshape. Must be strictly positive elementwise. Default is10. * u.ms.t_ref (
ArrayLike, optional) – Absolute refractory duration \(t_{ref}\) in ms, broadcastable toself.varshape. At runtime converted to steps byfloor(t_ref / dt)and must produce at least one step. Default is2. * u.ms.V_th (
ArrayLike, optional) – Spike threshold \(V_{th}\) in mV, broadcastable toself.varshape. Default is-55. * u.mV.V_reset (
ArrayLike, optional) – Reset potential \(V_{reset}\) in mV, broadcastable toself.varshape. Must satisfyV_reset < V_thelementwise. Default is-70. * u.mV.I_e (
ArrayLike, optional) – Constant external current \(I_e\) in pA, broadcastable toself.varshape. Added to buffered current each propagation segment. Default is0. * u.pA.V_min (
ArrayLikeorNone, optional) – Optional lower membrane bound \(V_{min}\) in mV, broadcastable toself.varshape.Nonedisables lower clipping (uses-inf). Default isNone.V_initializer (
Callable, optional) – Initializer used byinit_state()to create membrane stateV. Must return values unit-compatible with mV and shape-compatible withself.varshape(and optional batch prefix). Default isbraintools.init.Constant(-70. * u.mV).spk_fun (
Callable, optional) – Surrogate spike nonlinearity used byget_spike()and returned byupdate(). Receives normalized threshold distance tensor. Default isbraintools.surrogate.ReluGrad().spk_reset (
str, optional) – Reset mode forwarded toNeuron.'hard'matches NEST hard-reset behavior. Default is'hard'.refractory_input (
bool, optional) – IfFalse, delta events received during refractory are ignored. IfTrue, they are exponentially weighted intorefractory_spike_bufferand applied at refractory release. Default isFalse.ref_var (
bool, optional) – IfTrue, exposes additional stateself.refractorymirroringself.is_refractoryfor introspection. Default isFalse.
Parameter Mapping
Table 2 Parameter mapping to model symbols# Parameter
Type / shape / unit
Default
Math symbol
Semantics
in_sizeSize; scalar/tuplerequired
–
Defines
self.varshapefor all state/parameter broadcasts.E_LArrayLike, broadcastable to
self.varshape(mV)-70. * u.mV\(E_L\)
Resting membrane potential and origin of transformed state
U.C_mArrayLike, broadcastable (pF),
> 0250. * u.pF\(C_m\)
Converts current to membrane-rate contribution.
tau_mArrayLike, broadcastable (ms),
> 010. * u.ms\(\tau_m\)
Leak/relaxation time constant in exact propagator.
t_refArrayLike, broadcastable (ms), runtime
floor(t_ref/dt) >= 12. * u.ms\(t_{ref}\)
Absolute refractory duration.
V_thandV_resetArrayLike, broadcastable (mV), with
V_reset < V_th-55. * u.mV,-70. * u.mV\(V_{th}\), \(V_{reset}\)
Threshold and post-spike reset levels.
I_eArrayLike, broadcastable (pA)
0. * u.pA\(I_e\)
Constant injected current term.
V_minArrayLike broadcastable (mV) or
NoneNone\(V_{min}\)
Optional lower clip on membrane potential.
V_initializerCallable returning mV-compatible values
Constant(-70. * u.mV)–
Initializes membrane state
V.spk_funCallable
ReluGrad()–
Surrogate spike output function.
spk_resetstr
'hard'–
Reset policy inherited from base neuron class.
refractory_inputbool
False–
Controls treatment of refractory-time delta events.
ref_varbool
False–
Exposes persistent refractory state variable.
namestr | None
None–
Optional node identifier.
- Raises:
ValueError – If validated construction/runtime constraints fail, including invalid parameter inequalities (for example
V_reset >= V_th), non-positive time constants/capacitance,dt <= 0, invalid event offsets, orfloor(t_ref / dt) < 1.TypeError – If provided arguments are incompatible with expected unit arithmetic (mV, pA, pF, ms) or callable interfaces.
KeyError – If required simulation context entries (
tand/ordt) are missing whenupdate()is called.AttributeError – If
update()is called beforeinit_state()creates required state variables.
- V#
Membrane potential state in mV, shape
self.varshape(or with leading batch dimension whenbatch_sizeis specified).- Type:
brainstate.HiddenState
- I_stim#
One-step buffered continuous current input in pA. Applied in the next update call (NEST ring-buffer semantics).
- Type:
brainstate.ShortTermState
- last_spike_time#
Absolute precise spike time (ms) for the latest emitted spike. Initialized to
-1e7 * u.ms(far past) to indicate no prior spike.- Type:
brainstate.ShortTermState
- last_spike_step#
Integer (
jnp.int32) step index associated with the latest emitted spike. Initialized to-1.- Type:
brainstate.ShortTermState
- last_spike_offset#
Precise within-step offset (ms) measured from the step right boundary (NEST convention:
0at step end,dtat step start).- Type:
brainstate.ShortTermState
- is_refractory#
Boolean mask indicating which neurons are currently in the absolute refractory period.
- Type:
brainstate.ShortTermState
- refractory_spike_buffer#
Deferred refractory-time delta contribution (mV). Non-zero only when
refractory_input=True; accumulates exponentially decayed delta events and is released at end of refractoriness.- Type:
brainstate.ShortTermState
- refractory#
Mirror of
is_refractoryexposed for external inspection. Present only whenref_var=True.- Type:
brainstate.ShortTermState
Notes
xpassed toupdate(x=...)is buffered intoI_stimand applied on the next step, mirroring NEST ring-buffer semantics for current events.Delta inputs from
add_delta_inputare interpreted as on-grid events at step end (offset0).Additional within-step precise events can be supplied through
update(spike_events=...)where each event is(offset, weight)or{'offset': ..., 'weight': ...}in units of ms and mV.This model uses
floor(t_ref / dt)for refractory step conversion (matching NESTiaf_psc_delta_ps), whereasiaf_psc_deltausesceil(t_ref / dt).
Examples
Basic usage with constant current drive:
>>> import brainpy >>> import brainstate >>> import saiunit as u >>> with brainstate.environ.context(dt=0.1 * u.ms): ... neu = brainpy.state.iaf_psc_delta_ps(in_size=2, t_ref=2.0 * u.ms) ... neu.init_state() ... with brainstate.environ.context(t=0.0 * u.ms): ... spk = neu.update(x=200.0 * u.pA) ... _ = spk.shape
Precise within-step spike events with
refractory_input=True:>>> import brainpy >>> import brainstate >>> import saiunit as u >>> with brainstate.environ.context(dt=0.1 * u.ms): ... neu = brainpy.state.iaf_psc_delta_ps(in_size=1, refractory_input=True) ... neu.init_state() ... with brainstate.environ.context(t=0.0 * u.ms): ... _ = neu.update(spike_events=[(0.04 * u.ms, 2.5 * u.mV)])
References
See also
iaf_psc_deltaCurrent-based LIF with delta synapses (on-grid spike times)
iaf_cond_expConductance-based LIF with exponential synapses
- get_spike(V=None)[source]#
Evaluate surrogate spike activation for a voltage tensor.
- Parameters:
V (
ArrayLikeorNone, optional) – Voltage values in mV, broadcast-compatible withself.varshape(or current state shape when batched). IfNone, usesself.V.value.- Returns:
out – Output of
self.spk_funevaluated on normalized threshold distance(V - V_th) / (V_th - V_reset)with same shape asV.- Return type:
- Raises:
TypeError – If
Vcannot participate in unit-compatible arithmetic.
- init_state(batch_size=None, **kwargs)[source]#
Initialize membrane, timing, and refractory runtime states.
- Parameters:
- Raises:
ValueError – If initializer outputs cannot be broadcast to target state shape.
TypeError – If initializer values are not unit-compatible with mV/pA/ms states.
- update(x=Quantity(0., 'pA'), spike_events=None)[source]#
Advance one simulation step with optional precise within-step events.
- Parameters:
x (
ArrayLike, optional) – External current input in pA. This value is buffered intoself.I_stimand applied in the next update call, matching NEST ring-buffer current semantics.spike_events (
SequenceordictortupleorNone, optional) – Optional precise delta events applied in the current step. Accepted formats are(offset, weight),{'offset': ..., 'weight': ...}, or a sequence of such events.offsetis in ms measured from the step right boundary with NEST convention (0at step end,dtat step start).weightis a voltage jump in mV and may be scalar or broadcastable to neuron state shape.
- Returns:
out – Surrogate spike output from
get_spike()with shapeself.V.value.shape. Elements corresponding to neurons that spiked in this step are forced slightly above threshold before surrogate evaluation to encode emitted spikes after hard reset.- Return type:
jax.Array- Raises:
ValueError – If
dt <= 0, iffloor(t_ref / dt) < 1, if event offsets are outside[0, dt], or if event structures are invalid.KeyError – If simulation context does not provide required
t/dt.AttributeError – If state variables are unavailable because
init_state()was not called beforeupdate().TypeError – If inputs or internal values are not unit-compatible with expected pA/mV/ms arithmetic.