step_current_generator#
- class brainpy.state.step_current_generator(in_size=1, amplitude_times=(), amplitude_values=(), start=Quantity(0., 'ms'), stop=None, origin=Quantity(0., 'ms'), name=None)#
Piecewise-constant current generator – NEST-compatible stimulation device.
Generate a deterministic piecewise-constant current trace and gate it with a half-open activity window using NEST-compatible time semantics.
1. Model equations
Let \(\{(t_k, a_k)\}_{k=1}^{K}\) be the configured change-time/current pairs, where \(t_k\) are times (ms) and \(a_k\) are currents (pA). Define the scheduled amplitude
\[\begin{split}A(t) = \begin{cases} 0, & t < t_1, \\ a_k, & t_k \le t < t_{k+1},\ k=1,\dots,K-1, \\ a_K, & t \ge t_K. \end{cases}\end{split}\]The output is gated by
\[g(t) = \mathbf{1}\!\left[t \ge t_0+t_{\mathrm{start,rel}}\right] \cdot \mathbf{1}\!\left[t < t_0+t_{\mathrm{stop,rel}}\right],\]with the second indicator omitted when
stop is None. Final output:\[I(t) = g(t)\,A(t).\]2. Timing semantics, assumptions, and constraints
NEST timing is matched by selecting, at time
t, the most recent change point witht_k <= t. In discrete simulation with stepdt, this corresponds to applying a change exactly from the step whose environment time equals the configured change time.Enforced constraints in this implementation:
len(amplitude_times) == len(amplitude_values).amplitude_timesare strictly increasing.
Inputs accepted but not explicitly constrained:
Unitless
amplitude_timesare interpreted as ms.Unitless
amplitude_valuesare interpreted as pA.Positive-time-only schedules are recommended by NEST, but positivity is not explicitly validated here.
3. Computational implications
Each
update()call usesu.math.searchsorted()to find the active plateau, then selects the pre-broadcast current array forself.varshapeand applies one boolean mask. Per-call complexity is \(O(\log K + \prod \mathrm{varshape})\), with \(K\) schedule entries.- Parameters:
in_size (
Size, optional) – Output size/shape specification consumed bybrainstate.nn.Dynamics. The emitted current has shapeself.varshapederived fromin_size. Default is1.amplitude_times (
Sequence, optional) – Ordered sequence of change times with lengthK. Entries may be unitful times (typically ms) or unitless numerics. Passed directly tou.math.asarray(), which validates unit consistency across all entries. Must be strictly increasing. Default is().amplitude_values (
Sequence, optional) – Sequence of current plateaus with lengthKmatchingamplitude_timeselementwise. Entries may be unitful currents (typically pA) or unitless numerics. Each entry is converted viau.math.asarray()and expanded to the maximum ndim found across all entries (by prepending size-1 axes); the results are stacked to a shape that is broadcastable to(K, *varshape). Default is().start (
ArrayLike, optional) – Relative start time \(t_{\mathrm{start,rel}}\) (typically ms), broadcast toself.varshapeviabraintools.init.param(). Effective lower bound isorigin + start(inclusive). Default is0. * u.ms.stop (
ArrayLikeorNone, optional) – Relative stop time \(t_{\mathrm{stop,rel}}\) (typically ms), broadcast toself.varshapewhen provided. Effective upper bound isorigin + stop(exclusive).Nonemeans no upper bound. Default isNone.origin (
ArrayLike, optional) – Time origin \(t_0\) (typically ms) added tostartandstop, broadcast toself.varshape. Default is0. * u.ms.name (
strorNone, optional) – Optional node name passed tobrainstate.nn.Dynamics.
Parameter Mapping
Table 26 Parameter mapping to model symbols# Parameter
Default
Math symbol
Semantics
amplitude_times()\(t_k\)
Change times for piecewise-constant plateaus.
amplitude_values()\(a_k\)
Plateau currents selected at and after corresponding
t_k.start0. * u.ms\(t_{\mathrm{start,rel}}\)
Relative inclusive lower bound of activity window.
stopNone\(t_{\mathrm{stop,rel}}\)
Relative exclusive upper bound of activity window.
origin0. * u.ms\(t_0\)
Global offset added to
startandstop.- Raises:
ValueError – If
amplitude_timesandamplitude_valueslengths differ, or ifamplitude_timesis not strictly increasing.TypeError – If
u.math.asarray()detects unit inconsistency across entries, or if unitful/unitless arithmetic is invalid during broadcasting or time-window comparisons.KeyError – At update time, if simulation time
't'is missing frombrainstate.environ.
Notes
NEST recommends specifying
amplitude_timeson a grid of simulation resolutiondt. Using off-grid change times is allowed but may shift the effective change by up to onedtstep depending on floating-point rounding when comparingt >= amp_time. Usedc_generatorwhen only a single constant plateau is needed;step_current_generatoris the preferred device when the current must take different values at different intervals within a single simulation run.See also
dc_generatorConstant current stimulation device.
ac_generatorSinusoidal current stimulation device.
noise_generatorGaussian white-noise current stimulation device.
References
Examples
>>> import brainpy >>> import brainstate >>> import saiunit as u >>> with brainstate.environ.context(dt=0.1 * u.ms): ... stim = brainpy.state.step_current_generator( ... in_size=1, ... amplitude_times=[10.0 * u.ms, 50.0 * u.ms, 80.0 * u.ms], ... amplitude_values=[200.0 * u.pA, -100.0 * u.pA, 500.0 * u.pA], ... start=5.0 * u.ms, ... stop=120.0 * u.ms, ... ) ... with brainstate.environ.context(t=60.0 * u.ms): ... current = stim.update() ... _ = current.shape
>>> import brainpy >>> import saiunit as u >>> stim1 = brainpy.state.step_current_generator( ... amplitude_times=[0.0 * u.ms, 100.0 * u.ms, 200.0 * u.ms], ... amplitude_values=[300.0 * u.pA, 0.0 * u.pA, -150.0 * u.pA], ... ) >>> stim2 = brainpy.state.step_current_generator( ... in_size=10, ... amplitude_times=[50.0 * u.ms, 150.0 * u.ms], ... amplitude_values=[400.0 * u.pA, 100.0 * u.pA], ... start=40.0 * u.ms, ... stop=180.0 * u.ms, ... origin=10.0 * u.ms, ... )
- update()[source]#
Compute scheduled current at environment time
t.The implementation is fully compatible with
jax.jit: the schedule look-up usesu.math.searchsorted()on the staticamplitude_timesarray, whiletremains a traced value throughout.- Returns:
out – Current quantity with shape
self.varshape. For each output channel, value equals the latest scheduled plateau whose change time is<= t; channels outside the active window[origin + start, origin + stop)are set to zero (or all active whenstop is None).- Return type:
Quantity- Raises:
KeyError – If
brainstate.environhas no't'entry.
Notes
Both
amplitude_timesandtare divided byu.msto obtain dimensionless arrays before callingu.math.searchsorted().u.math.searchsorted(..., side='right') - 1returns the index of the most-recently-passed change point, or-1whentprecedes all change times (zero current).u.math.clip()keeps the index in bounds for the gather;u.math.where()then suppresses the result when the index is negative. Start is inclusive and stop is exclusive, matching NEST semantics.See also
step_current_generatorClass-level parameter definitions and model equations.
dc_generator.updateWindowed constant-current update rule.
ac_generator.updateWindowed sinusoidal-current update rule.