ac_generator

ac_generator#

class brainpy.state.ac_generator(in_size=1, amplitude=Quantity(0., 'pA'), offset=Quantity(0., 'pA'), frequency=Quantity(0., 'Hz'), phase=0.0, start=Quantity(0., 'ms'), stop=None, origin=Quantity(0., 'ms'), name=None)#

AC current generator – NEST-compatible stimulation device.

Generate a sinusoidal current with a constant DC offset and gate the output with a half-open activity window using NEST-compatible parameter semantics.

1. Model equations

For each output channel, the emitted current is

\[\begin{split}I(t) = \begin{cases} I_0 + A\sin(\omega t + \phi) & \text{if } t_{\mathrm{start}} \le t < t_{\mathrm{stop}}, \\ 0 & \text{otherwise}, \end{cases}\end{split}\]

where \(\omega = 2\pi f / 1000\) (rad/ms) when \(f\) is given in Hz and simulation time \(t\) is in ms, and

\[t_{\mathrm{start}} = t_0 + t_{\mathrm{start,rel}}, \qquad t_{\mathrm{stop}} = t_0 + t_{\mathrm{stop,rel}}.\]

If stop is None, then \(t_{\mathrm{stop}} = +\infty\).

2. Rotation-matrix interpretation

The NEST reference implementation propagates the oscillator state with an exact rotation matrix (Rotter and Diesmann, 1999):

\[\begin{split}\begin{pmatrix} y_0^{n+1} \\ y_1^{n+1} \end{pmatrix} = \begin{pmatrix} \cos(\omega h) & -\sin(\omega h) \\ \sin(\omega h) & \cos(\omega h) \end{pmatrix} \begin{pmatrix} y_0^n \\ y_1^n \end{pmatrix},\end{split}\]

with initial state \(y_0(0) = A\cos\phi\), \(y_1(0) = A\sin\phi\) and output \(I(t) = y_1(t) + I_0\). This implementation instead evaluates the equivalent closed-form expression \(A\sin(\omega t + \phi)\) directly via jax.numpy.sin(), which is numerically identical but stateless.

3. Timing semantics and computational implications

The active interval is the half-open set \([t_{\mathrm{start}},\, t_{\mathrm{stop}})\). Since neuron states are advanced from t to t + dt in each step, a current enabled at \(t_{\mathrm{start}}\) first affects the membrane trajectory after that update (observable at \(t_{\mathrm{start}} + dt\)); the last active update starts at \(t_{\mathrm{stop}} - dt\). Because the phase is tied to absolute simulation time t, windowing by start/stop does not reset the oscillator phase. Per-call complexity is \(O(\prod \mathrm{varshape})\), dominated by one sine evaluation and one conditional mask.

Parameters:
  • in_size (Size, optional) – Output size/shape specification understood by brainstate.nn.Dynamics. The emitted current shape is self.varshape derived from in_size. Default is 1.

  • amplitude (ArrayLike, optional) – Sinusoidal amplitude \(A\) (typically pA). Scalars or arrays are accepted and broadcast to self.varshape via braintools.init.param(). Default is 0. * u.pA.

  • offset (ArrayLike, optional) – Constant DC offset \(I_0\) added to the sinusoid (typically pA), broadcast to self.varshape. Default is 0. * u.pA.

  • frequency (ArrayLike, optional) – Oscillation frequency \(f\) in Hz (or a unitless numeric interpreted as Hz). Converted internally to \(\omega = 2\pi f / 1000\) (rad/ms). Broadcast to self.varshape. Default is 0. * u.Hz.

  • phase (ArrayLike, optional) – Initial phase \(\phi_{\mathrm{deg}}\) in degrees (NEST convention). Converted internally as \(\phi = \phi_{\mathrm{deg}} \cdot 2\pi / 360\). Stored as a dimensionless scalar or array broadcast to self.varshape. Default is 0..

  • start (ArrayLike, optional) – Relative activation time \(t_{\mathrm{start,rel}}\) (typically ms), broadcast to self.varshape. Effective start is origin + start. Default is 0. * u.ms.

  • stop (ArrayLike or None, optional) – Relative deactivation time \(t_{\mathrm{stop,rel}}\) (typically ms), broadcast to self.varshape when provided. Effective stop is origin + stop and the upper bound is exclusive. None means the sinusoid is never deactivated. Default is None.

  • origin (ArrayLike, optional) – Global time origin \(t_0\) (typically ms) added to both start and stop, broadcast to self.varshape. Default is 0. * u.ms.

  • name (str or None, optional) – Optional node name passed to brainstate.nn.Dynamics.

Parameter Mapping

Table 24 Parameter mapping to model symbols#

Parameter

Default

Math symbol

Semantics

amplitude

0. * u.pA

\(A\)

Peak sinusoidal excursion in current units (typically pA).

offset

0. * u.pA

\(I_0\)

Constant baseline current added to the sinusoid.

frequency

0. * u.Hz

\(f\)

Frequency in Hz; converted to \(\omega = 2\pi f/1000\) rad/ms.

phase

0.

\(\phi_{\mathrm{deg}}\)

Input phase in degrees; converted to radians each update step.

start

0. * u.ms

\(t_{\mathrm{start,rel}}\)

Relative start time; effective lower bound is origin + start.

stop

None

\(t_{\mathrm{stop,rel}}\)

Relative stop time; effective upper bound is origin + stop.

origin

0. * u.ms

\(t_0\)

Global offset applied to both window boundaries.

Raises:
  • ValueError – If in_size is invalid or any parameter cannot be broadcast to self.varshape by braintools.init.param().

  • TypeError – If unitful/unitless arithmetic is invalid during parameter initialization (e.g., incompatible units in amplitude or offset).

See also

dc_generator

Constant current stimulation device.

step_current_generator

Piecewise-constant current stimulation.

noise_generator

Gaussian white-noise current stimulation.

References

Examples

>>> import brainpy
>>> import brainstate
>>> import saiunit as u
>>> with brainstate.environ.context(dt=0.1 * u.ms):
...     stim = brainpy.state.ac_generator(
...         in_size=1,
...         amplitude=500.0 * u.pA,
...         offset=100.0 * u.pA,
...         frequency=100.0 * u.Hz,
...         phase=30.0,
...         start=5.0 * u.ms,
...         stop=50.0 * u.ms,
...     )
...     with brainstate.environ.context(t=10.0 * u.ms):
...         current = stim.update()
...     _ = current.shape
>>> import brainpy
>>> import saiunit as u
>>> ac1 = brainpy.state.ac_generator(
...     amplitude=200.0 * u.pA,
...     offset=50.0 * u.pA,
...     frequency=40.0 * u.Hz,
...     phase=0.0,
... )
>>> ac2 = brainpy.state.ac_generator(
...     amplitude=100.0 * u.pA,
...     offset=0.0 * u.pA,
...     frequency=80.0 * u.Hz,
...     phase=90.0,
...     start=10.0 * u.ms,
...     stop=60.0 * u.ms,
... )
update()[source]#

Compute the window-gated sinusoidal current at environment time t.

Returns:

current – Current-like quantity with shape self.varshape. For channels where origin + start <= t < origin + stop (or t >= origin + start when stop is None), values equal \(I_0 + A\sin(\omega t + \phi)\) where \(\omega = 2\pi f / 1000\) (rad/ms) and \(\phi = \phi_{\mathrm{deg}} \cdot 2\pi / 360\) (rad). Inactive channels are exactly zero.

Return type:

jax.Array

Raises:
  • KeyError – If the environment time key 't' is not available in brainstate.environ.

  • TypeError – If t, frequency, amplitude, or offset carry incompatible units preventing valid arithmetic.

Notes

Frequency and phase conversions are performed per call:

\[\omega = \frac{2\pi f}{1000} \, (\text{rad/ms}), \qquad \phi = \frac{\phi_{\mathrm{deg}} \cdot 2\pi}{360} \, (\text{rad}).\]

The waveform depends only on absolute t; the oscillator carries no internal state. Entering and leaving the activity window therefore does not reset or shift the phase. Start is inclusive and stop is exclusive, matching NEST semantics. If stop <= start (after adding origin), the active set is empty and the output is always zero.

See also

ac_generator

Class-level parameter definitions and model equations.

dc_generator.update

Windowed constant-current update rule.