poisson_generator#

class brainpy.state.poisson_generator(in_size=1, rate=Quantity(0., 'Hz'), start=Quantity(0., 'ms'), stop=None, origin=Quantity(0., 'ms'), rng_seed=0, name=None)#

Poisson spike generator compatible with NEST.

Description

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

1. Point-process model and discretization

Let r be the configured homogeneous rate in spikes/s and \(\Delta t\) be the simulation step in ms. For one output train, the count in one discrete bin is sampled as

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

The factor 1000 converts milliseconds to seconds, so \(\lambda_n\) is dimensionless. This is the standard bin-count reduction of a homogeneous Poisson process where \(\mathbb{P}(K_n=k)=e^{-\lambda_n}\lambda_n^k/k!\).

Implementation detail: update() draws one vectorized Poisson sample with shape=self.varshape via jax.random.poisson. Each element is an independent train; values are integer multiplicities 0, 1, 2, ... and are not clipped to binary spikes.

2. Activity window and NEST timing semantics

The active interval follows NEST StimulationDevice::is_active for spike generators:

\[t_{\min} < t \le t_{\max}, \qquad t_{\min} = origin + start,\quad t_{\max} = origin + stop.\]

Therefore start is exclusive and stop is inclusive. Internally, times are projected to integer steps with round(time_ms / dt_ms) and activity is evaluated as t_min_step < curr_step <= t_max_step.

3. Assumptions, constraints, and computational implications

Scalar parameters are converted to float64 in public units (Hz or ms). If dt is available, finite origin, start, and stop must lie on the simulation grid (absolute tolerance 1e-12 in time/dt ratio). Cache refresh is triggered when dt changes. Per-step runtime is \(O(\prod \text{varshape})\) for sampling and memory is proportional to output size. When rate <= 0 or inactive, the update path returns a zero int64 array without Poisson sampling.

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

  • rate (ArrayLike, optional) – Scalar firing rate in spikes/s (Hz). Accepted forms are any ArrayLike with exactly one element, optionally a saiunit.Quantity convertible to u.Hz. Must satisfy rate >= 0. Default is 0.0 * u.Hz.

  • start (ArrayLike, optional) – Scalar relative start time in ms (exclusive lower bound after adding origin). Must be scalar-convertible to float64 and, when dt is available, grid representable. Default is 0.0 * u.ms.

  • stop (ArrayLike or None, optional) – Scalar relative stop time in ms (inclusive upper bound after adding origin). None is mapped to +inf. If finite, must be scalar-convertible and grid representable when dt is available. Must satisfy stop >= start after conversion. Default is None.

  • origin (ArrayLike, optional) – Scalar time origin offset in ms added to both start and stop. Must be scalar-convertible and grid representable when dt is available. Default is 0.0 * u.ms.

  • rng_seed (int, optional) – Seed used to initialize jax.random.PRNGKey inside init_state(). Different seeds lead to different stochastic realizations for otherwise identical parameters. Default is 0.

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

Parameter Mapping

Table 31 Parameter mapping to model symbols#

Parameter

Default

Math symbol

Semantics

rate

0.0 * u.Hz

\(r\)

Homogeneous firing rate in spikes/s.

start

0.0 * u.ms

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

Relative exclusive lower bound of activity.

stop

None

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

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

origin

0.0 * u.ms

\(t_0\)

Global offset added to start and stop.

in_size

1

Defines self.varshape (number/shape of independent trains).

rng_seed

0

Seed for JAX key state used by Poisson sampling.

Raises:
  • ValueError – If rate < 0; if stop < start; if time/rate inputs are not scalar-convertible; or if finite origin/start/stop are not multiples of simulation resolution when dt is available.

  • TypeError – If unit conversion to u.Hz or u.ms fails for supplied inputs.

  • KeyError – At runtime, if required simulation context entries (for example dt via brainstate.environ.get_dt()) are missing.

Notes

  • update lazily initializes RNG state if init_state() has not been called explicitly.

  • Parameter updates through set() recompute cached step bounds when dt is present in the environment.

  • As in NEST, one generator can fan out to many targets while maintaining independent trains per output element.

Examples

>>> import brainpy
>>> import brainstate
>>> import saiunit as u
>>> with brainstate.environ.context(dt=0.1 * u.ms):
...     gen = brainpy.state.poisson_generator(
...         in_size=(2, 3),
...         rate=1200.0 * u.Hz,
...         start=5.0 * u.ms,
...         stop=20.0 * u.ms,
...         rng_seed=11,
...     )
...     with brainstate.environ.context(t=10.0 * u.ms):
...         counts = gen.update()
...     _ = counts.shape
>>> import brainpy
>>> import saiunit as u
>>> gen = brainpy.state.poisson_generator(rate=500.0 * u.Hz)
>>> gen.set(start=2.0 * u.ms, stop=None, origin=1.0 * u.ms)
>>> params = gen.get()
>>> _ = params['rate'], params['stop']

See also

poisson_generator_ps

Precise-time Poisson generator with dead time.

inhomogeneous_poisson_generator

Piecewise-constant time-varying Poisson rate.

sinusoidal_poisson_generator

Sinusoidally modulated Poisson rate.

References

get()[source]#

Return current public parameters as scalar SI-compatible values.

Returns:

params – Dictionary with four float entries:

  • 'rate' – firing rate in spikes/s (Hz).

  • 'start' – relative exclusive lower bound in ms.

  • 'stop' – relative inclusive upper bound in ms; inf when no deactivation time has been set.

  • 'origin' – time origin offset in ms.

Return type:

dict

Notes

Returned values are plain Python float scalars (float64 precision). They mirror the internal scalar attributes set in __init__() or updated by set() and are not bound to any saiunit quantities.

See also

poisson_generator.set

Update one or more parameters in place.

Examples

>>> import brainpy
>>> import saiunit as u
>>> gen = brainpy.state.poisson_generator(
...     rate=800.0 * u.Hz,
...     start=5.0 * u.ms,
...     stop=100.0 * u.ms,
...     origin=2.0 * u.ms,
... )
>>> params = gen.get()
>>> params['rate']
800.0
>>> params['stop']
100.0
init_state(batch_size=None, **kwargs)[source]#

Initialize the RNG state used by Poisson sampling.

Parameters:
  • batch_size (int or None, optional) – Unused. Present for framework API compatibility with brainstate.nn.Dynamics. Default is None.

  • **kwargs (Any) – Unused keyword arguments accepted for API compatibility.

Notes

update() lazily calls this method on the first step if init_state has not been invoked explicitly. Calling init_state resets the RNG to the original seed, so repeated calls restart the stochastic sequence from the beginning.

See also

poisson_generator.update

Consumes rng_key populated here.

Examples

>>> import brainstate
>>> import saiunit as u
>>> from brainpy.state import poisson_generator
>>> with brainstate.environ.context(dt=0.1 * u.ms):
...     gen = poisson_generator(in_size=4, rate=800.0 * u.Hz, rng_seed=7)
...     gen.init_state()
set(*, rate=<object object>, start=<object object>, stop=<object object>, origin=<object object>)[source]#

Update public parameters and refresh the timing cache when needed.

Only keyword arguments that are explicitly passed are modified; omitted arguments retain their current values.

Parameters:
  • rate (ArrayLike or object, optional) – New scalar firing rate in spikes/s (Hz). Accepts any ArrayLike with exactly one element, or a saiunit.Quantity convertible to u.Hz. Must satisfy rate >= 0 after conversion. Omit to keep the current value.

  • start (ArrayLike or object, optional) – New scalar relative start time in ms (exclusive lower bound after adding origin). Must be scalar-convertible and, when dt is in the environment, grid-representable. Omit to keep the current value.

  • stop (ArrayLike or None or object, optional) – New scalar relative stop time in ms (inclusive upper bound after adding origin). None maps to +inf. Must satisfy stop >= start after conversion. Omit to keep the current value.

  • origin (ArrayLike or object, optional) – New scalar time origin offset in ms added to both start and stop. Must be scalar-convertible and grid-representable when dt is available. Omit to keep the current value.

Raises:
  • ValueError – If rate < 0 after conversion; if stop < start after conversion; or if any finite timing parameter is not representable on the current simulation grid (checked via _assert_grid_time()).

  • TypeError – If unit conversion to u.Hz or u.ms fails for any supplied value.

See also

poisson_generator.get

Read-back current parameter values.

Examples

>>> import brainpy
>>> import saiunit as u
>>> gen = brainpy.state.poisson_generator(rate=500.0 * u.Hz)
>>> gen.set(rate=1000.0 * u.Hz, stop=50.0 * u.ms)
>>> params = gen.get()
>>> _ = params['rate'], params['stop']
update()[source]#

Advance one simulation step and return per-step spike multiplicities.

Returns:

spikes – Integer array with dtype int64 and shape self.varshape. Each element is the number of spikes emitted by the corresponding independent output train in the current time step.

  • Active and rate > 0: entries are i.i.d. Poisson(\(\lambda\)) samples with \(\lambda = r \cdot \Delta t / 1000\).

  • Inactive or rate <= 0: all entries are exactly 0.

Return type:

jax.Array

Raises:
  • ValueError – If the timing cache is stale and a finite origin, start, or stop is not representable on the current simulation grid (checked by _assert_grid_time()).

  • KeyError – If dt is unavailable from brainstate.environ.get_dt() or t is expected but cannot be resolved.

Notes

The update proceeds as follows each call:

  1. Lazy init – If rng_key has not been created by init_state(), it is initialized automatically with self.rng_seed.

  2. Cache refresh – When dt changes from the previously cached value, _refresh_timing_cache() recomputes the integer step bounds \(t_{\min}\) and \(t_{\max}\).

  3. Rate guard – If rate <= 0, an all-zero array is returned without touching the PRNG state.

  4. Activity check – The current step index is compared against the cached step bounds: active iff \(t_{\min,\mathrm{step}} < \mathrm{curr\_step} \le t_{\max,\mathrm{step}}\). Inactive steps return zeros.

  5. Poisson draw – If active, one vectorized sample jax.random.poisson(lam, shape=self.varshape) is drawn via _sample_poisson(), consuming one PRNG split.

See also

poisson_generator.init_state

RNG initialization called lazily here.

poisson_generator.set

Update parameters between runs.