sinusoidal_poisson_generator#

class brainpy.state.sinusoidal_poisson_generator(in_size=1, rate=Quantity(0., 'Hz'), amplitude=Quantity(0., 'Hz'), frequency=Quantity(0., 'Hz'), phase=0.0, individual_spike_trains=True, start=Quantity(0., 'ms'), stop=None, origin=Quantity(0., 'ms'), rng_seed=0, name=None)#

Sinusoidally modulated Poisson spike generator compatible with NEST.

Description

sinusoidal_poisson_generator re-implements NEST’s stimulation device of the same name and emits per-step spike multiplicities.

1. Stochastic model and discretization

The instantaneous firing rate in spikes/s is

\[f(t) = \max\left( 0,\ r + a \sin\left( 2\pi f_{\mathrm{mod}} t / 1000 + \phi \right) \right),\]

where:

  • \(r\) is rate (spikes/s),

  • \(a\) is amplitude (spikes/s),

  • \(f_{\mathrm{mod}}\) is frequency (Hz),

  • \(\phi\) is phase (deg, internally converted to radians),

  • \(t\) is simulation time in ms.

For simulation resolution \(\Delta t\) in ms, each output train samples a Poisson multiplicity

\[K_n \sim \mathrm{Poisson}(\lambda_n), \qquad \lambda_n = f_n \Delta t / 1000,\]

where the 1000 factor converts Hz * ms to a dimensionless mean. K_n is an integer count 0, 1, 2, ... and may exceed 1.

2. Oscillator-state recurrence and derivation

Following NEST, sinusoidal modulation is stored in a rotated two-component oscillator state:

\[y_0(t) = a/1000 \cdot \cos(\omega t + \phi), \qquad y_1(t) = a/1000 \cdot \sin(\omega t + \phi),\]

with \(\omega = 2\pi f_{\mathrm{mod}}/1000\) (rad/ms). One-step propagation by \(\Delta t\) uses a rotation matrix \(R(\omega\Delta t)\):

\[\begin{split}\begin{bmatrix} y_0' \\ y_1' \end{bmatrix} = \begin{bmatrix} \cos(\omega\Delta t) & -\sin(\omega\Delta t) \\ \sin(\omega\Delta t) & \cos(\omega\Delta t) \end{bmatrix} \begin{bmatrix} y_0 \\ y_1 \end{bmatrix}.\end{split}\]

The post-rotation y_1' is then added to rate/1000 and clamped at zero before Poisson sampling. This avoids recomputing trigonometric functions each step and keeps per-step modulation update constant-time.

3. Update ordering (NEST source order)

The internal two-component oscillator state is updated exactly in the order used by NEST models/sinusoidal_poisson_generator.cpp:

  1. Start from the DC component rate.

  2. Rotate oscillator state (y_0, y_1) by one step.

  3. Add the rotated y_1 to obtain instantaneous rate.

  4. Clamp rate at zero.

  5. Sample Poisson multiplicities if active.

The per-step recorded rate value in NEST corresponds to this updated post-rotation rate. This implementation exposes it via get_recorded_rate().

4. Timing semantics

NEST currently classifies this model as CURRENT_GENERATOR in get_type(). Consequently, activity is evaluated with a two-step shift in StimulationDevice::is_active:

\[t_{\min} < (n + 2) \le t_{\max},\]

where n is current simulation step index and t_{\min} = \mathrm{origin} + \mathrm{start}, t_{\max} = \mathrm{origin} + \mathrm{stop} (in steps).

This differs from regular spike generators and is intentionally replicated here to match NEST behavior.

5. Assumptions, constraints, and computational implications

  • Public parameters are scalar-only; non-scalar values raise ValueError.

  • stop must satisfy stop >= start after unit conversion.

  • When dt is available, finite origin, start, and stop must be representable on the simulation grid.

  • If dt changes, timing caches and oscillator state are recomputed from absolute simulation time to preserve NEST-compatible behavior.

  • Per-step complexity is \(O(\prod \mathrm{varshape})\) for Poisson sampling and \(O(1)\) for oscillator/timing updates.

Parameters:
  • in_size (Size, optional) – Output size specification for brainstate.nn.Dynamics. The derived self.varshape is the shape of values returned by update(); each element corresponds to one emitted train. Default is 1.

  • rate (ArrayLike, optional) – Scalar baseline firing rate in spikes/s (Hz), shape () after conversion. Accepted inputs include scalar ArrayLike and saiunit.Quantity convertible to u.Hz. Default is 0.0 * u.Hz.

  • amplitude (ArrayLike, optional) – Scalar sinusoidal modulation amplitude in spikes/s (Hz), shape () after conversion. Units and conversion rules match rate. Default is 0.0 * u.Hz.

  • frequency (ArrayLike, optional) – Scalar modulation frequency in Hz, shape () after conversion. Internally converted to angular frequency in rad/ms. Default is 0.0 * u.Hz.

  • phase (ArrayLike, optional) – Scalar modulation phase in degrees, shape () after conversion. Internally converted to radians. Default is 0.0.

  • individual_spike_trains (bool, optional) – Sampling mode selector. If True, Poisson sampling is independent for each index of self.varshape. If False, one sampled multiplicity is broadcast to all outputs. Default is True.

  • start (ArrayLike, optional) – Scalar relative activation start time in ms, shape () after conversion. Activity uses NEST current-generator semantics with a two-step shifted check. Default is 0.0 * u.ms.

  • stop (ArrayLike or None, optional) – Scalar relative deactivation stop time in ms, shape () after conversion. None maps to +inf. Must satisfy stop >= start after conversion. Default is None.

  • origin (ArrayLike, optional) – Scalar global time offset in ms, shape () after conversion. Added to start and stop for activity-window bounds. Default is 0.0 * u.ms.

  • rng_seed (int, optional) – Seed used to initialize jax.random.PRNGKey in init_state() and lazy initialization in update(). Default is 0.

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

Parameter Mapping

Table 34 Parameter mapping to model symbols#

Parameter

Default

Math symbol

Semantics

rate

0.0 * u.Hz

\(r\)

Baseline firing rate in spikes/s.

amplitude

0.0 * u.Hz

\(a\)

Sinusoidal modulation amplitude in spikes/s.

frequency

0.0 * u.Hz

\(f_{\mathrm{mod}}\)

Modulation frequency in Hz.

phase

0.0

\(\phi\)

Modulation phase in degrees (internally radians).

start

0.0 * u.ms

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

Relative lower activity bound (NEST shifted semantics).

stop

None

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

Relative upper activity bound; None maps to +\infty.

origin

0.0 * u.ms

\(t_0\)

Global time offset applied to start/stop.

in_size

1

Defines output train count/shape via self.varshape.

individual_spike_trains

True

Independent-per-output sampling vs shared broadcast sample.

rng_seed

0

Seed for JAX random key evolution.

Raises:
  • ValueError – If any scalar-constrained parameter cannot be reduced to one value; if stop < start; or if finite origin/start/stop are not representable on the simulation grid when dt is available.

  • TypeError – If numeric/unit conversion fails for provided rate/time inputs.

  • KeyError – At runtime, if required simulation context keys (for example dt in update()) are unavailable through brainstate.environ.

Notes

  • Time parameters are validated on the simulation grid when dt is available, matching repository conventions used by other NEST-compatible generators.

  • The oscillator state is re-initialized from absolute simulation time whenever the simulation resolution changes, matching NEST pre-run calibration behavior.

  • Recorded rate from get_recorded_rate() is the post-rotation, post-clamp value in spikes/s used for current-step sampling logic.

Examples

>>> import brainpy
>>> import brainstate
>>> import saiunit as u
>>> with brainstate.environ.context(dt=0.1 * u.ms):
...     gen = brainpy.state.sinusoidal_poisson_generator(
...         in_size=4,
...         rate=800.0 * u.Hz,
...         amplitude=200.0 * u.Hz,
...         frequency=10.0 * u.Hz,
...         phase=90.0,
...         start=5.0 * u.ms,
...         stop=50.0 * u.ms,
...         rng_seed=123,
...     )
...     with brainstate.environ.context(t=10.0 * u.ms):
...         counts = gen.update()
...     _ = counts.shape
>>> import brainpy
>>> import brainstate
>>> import saiunit as u
>>> with brainstate.environ.context(dt=0.1 * u.ms):
...     gen = brainpy.state.sinusoidal_poisson_generator(
...         individual_spike_trains=False
...     )
...     gen.set(rate=500.0 * u.Hz, amplitude=300.0 * u.Hz, phase=45.0)
...     params = gen.get()
...     _ = params['rate'], params['amplitude']

See also

poisson_generator

Homogeneous Poisson generator.

inhomogeneous_poisson_generator

Piecewise-constant inhomogeneous Poisson generator.

sinusoidal_gamma_generator

Sinusoidally modulated gamma-renewal generator.

References

get()[source]#

Return current public parameters and oscillator state snapshot.

Returns:

Dictionary with keys rate, frequency, phase, amplitude, individual_spike_trains, start, stop, origin, y_0, and y_1. Rates are in spikes/s, times are in ms, and oscillator states are in spikes/ms.

Return type:

dict

get_recorded_rate()[source]#

Return latest post-update instantaneous rate in spikes/s.

Returns:

Most recent stored value of the post-rotation, post-clamp instantaneous rate. Returns 0.0 before state initialization.

Return type:

float

init_state(batch_size=None, **kwargs)[source]#

Initialize RNG, oscillator states, and cached recorded rate.

Parameters:
  • batch_size (int or None, optional) – Unused placeholder for brainstate.nn.Dynamics compatibility.

  • **kwargs – Unused extra keyword arguments.

set(*, rate=<object object>, amplitude=<object object>, frequency=<object object>, phase=<object object>, individual_spike_trains=<object object>, start=<object object>, stop=<object object>, origin=<object object>)[source]#

Set public parameters and refresh dependent cached state.

Parameters:
  • rate (ArrayLike or object, optional) – Scalar rate in spikes/s (Hz). _UNSET keeps current value.

  • amplitude (ArrayLike or object, optional) – Scalar sinusoidal amplitude in spikes/s (Hz). _UNSET keeps current value.

  • frequency (ArrayLike or object, optional) – Scalar frequency in Hz. _UNSET keeps current value.

  • phase (ArrayLike or object, optional) – Scalar phase in degrees. _UNSET keeps current value.

  • individual_spike_trains (bool or object, optional) – Sampling mode flag. _UNSET keeps current value.

  • start (ArrayLike or object, optional) – Scalar relative start time in ms. _UNSET keeps current value.

  • stop (ArrayLike, None, or object, optional) – Scalar relative stop time in ms, or None for +inf. _UNSET keeps current value.

  • origin (ArrayLike or object, optional) – Scalar origin time in ms. _UNSET keeps current value.

Raises:
  • ValueError – If scalar conversion fails, stop < start, or grid-time validation fails when dt is available.

  • TypeError – If unit or numeric conversion fails for supplied inputs.

update()[source]#

Advance generator by one simulation step and emit spike counts.

Returns:

int64 array with shape self.varshape. Values are per-step spike multiplicities sampled from the configured sinusoidal Poisson process, or zeros when inactive/non-positive-rate.

Return type:

jax.Array

Raises:
  • KeyError – If required environment entries (for example dt) are not available through brainstate.environ at runtime.

  • ValueError – If cached timing constraints become invalid after environment changes (for example non-grid-aligned finite time bounds).