inhomogeneous_poisson_generator#
- class brainpy.state.inhomogeneous_poisson_generator(in_size=1, rate_times=None, rate_values=None, allow_offgrid_times=False, start=Quantity(0., 'ms'), stop=None, origin=Quantity(0., 'ms'), rng_seed=0, name=None)#
Inhomogeneous Poisson spike generator with NEST-compatible scheduling.
Emit Poisson-distributed spike multiplicities from a piecewise-constant rate schedule and replicate NEST update ordering for future rate changes.
1. Stochastic model and one-step-ahead schedule semantics
Let \(\Delta t\) be the simulation resolution in ms and \(n \in \mathbb{N}\) the current step index with \(t_n = n \Delta t\). The generator maintains an internal rate \(r_n\) in spikes/s. For each configured pair \((t_k, v_k) =\)
(rate_times[k], rate_values[k]), the requested time is aligned to a grid step \(s_k\):\[\begin{split}s_k = \begin{cases} \mathrm{round}(t_k / \Delta t), & \text{if representable on grid}, \\ \left\lceil t_k / \Delta t \right\rceil, & \text{if off-grid and ``allow\_offgrid\_times`` is True}. \end{cases}\end{split}\]During
update(), entries with \(s_k \le n\) are skipped as past events. The next unapplied entry is consumed exactly when \(s_k = n + 1\), i.e., one simulation step ahead of delivery. This one-step-ahead convention reproduces NEST device ordering and avoids retroactive rate jumps.For active steps with \(r_n > 0\), per-output spike multiplicities are sampled independently as
\[K_n \sim \mathrm{Poisson}(\lambda_n), \quad \lambda_n = \frac{r_n \,\Delta t}{1000},\]where the factor of 1000 converts Hz × ms to a dimensionless Poisson mean. Returned values are non-negative integers and may exceed 1 for high firing rates or large time steps.
2. Activity window, assumptions, and constraints
Activity is gated by the NEST spike-device convention using a half-open-on-the-left interval:
\[t_{\min} < t_n \le t_{\max}, \quad t_{\min} = t_0 + t_{\mathrm{start,rel}},\; t_{\max} = t_0 + t_{\mathrm{stop,rel}}.\]Therefore,
startis an exclusive lower bound andstopis an inclusive upper bound in timestamp space. Ifstop is None, \(t_{\max} = +\infty\) and no upper cutoff is applied.The following schedule constraints are enforced at
set()call time:rate_timesandrate_valuesmust always be provided together.Flattened lengths of both arrays must match after conversion.
Aligned schedule steps \(s_k\) must form a strictly increasing sequence; duplicate grid positions are rejected.
Each configured rate time must lie strictly in the future relative to the environment time reported by
brainstate.environat the momentset()is called.
3. Computational implications
Schedule preprocessing in
set()is \(O(K)\), where \(K\) is the number of configured change points. The per-stepupdate()cost is \(O(M + \prod \mathrm{varshape})\), where \(M\) is the number of outdated entries skipped in that call (amortized \(O(1)\) over a full simulation). Poisson sampling is vectorized overself.varshapeviajax.random.poisson, yielding statistically independent output trains for each element in the output array.- Parameters:
in_size (
Size, optional) – Output size/shape specification forbrainstate.nn.Dynamics.self.varshapederived fromin_sizegives the shape of the sampled multiplicity array returned by eachupdate()call. Default is1.rate_times (
Sequence[ArrayLike]orArrayLikeorNone, optional) – Scheduled rate-change times with logical shape(K,). Entries are interpreted as milliseconds and stored internally as a flattenednp.ndarraywith dtypefloat64after grid alignment.Nonemeans no schedule is configured at construction time. Must be provided together withrate_values. Default isNone.rate_values (
Sequence[ArrayLike]orArrayLikeorNone, optional) – Scheduled firing rates in spikes/s (Hz) paired one-to-one withrate_times, logical shape(K,). Stored as a flattenednp.ndarraywith dtypefloat64. Must be provided together withrate_times. Default isNone.allow_offgrid_times (
bool, optional) – Grid-alignment policy forrate_timesentries that do not fall exactly on a simulation time step. IfFalse, any off-grid time raisesValueError. IfTrue, off-grid times are aligned upward (ceiling) to the nearest representable grid step, subject to a small absolute tolerance of1e-12to absorb floating-point round- off. Default isFalse.start (
ArrayLike, optional) – Scalar relative start time \(t_{\mathrm{start,rel}}\) in ms. Added tooriginto form the exclusive lower bound of the active interval. Unitless scalars are treated as ms;saiunit.Quantityvalues are converted automatically. Default is0. * u.ms.stop (
ArrayLikeorNone, optional) – Scalar relative stop time \(t_{\mathrm{stop,rel}}\) in ms. Added tooriginto form the inclusive upper bound of the active interval.Nonedisables the upper bound (\(t_{\max} = +\infty\)). Default isNone.origin (
ArrayLike, optional) – Scalar time offset \(t_0\) in ms applied to bothstartandstop. Allows shifting the activity window without modifying the relativestart/stopvalues. Default is0. * u.ms.rng_seed (
int, optional) – Integer seed used to initialize thejax.random.PRNGKeyfor Poisson sampling. Changing the seed produces a statistically independent output spike train for otherwise identical parameters. Default is0.name (
strorNone, optional) – Optional human-readable name for the dynamics node passed tobrainstate.nn.Dynamics. Default isNone.
Parameter Mapping
Table 33 Parameter mapping to model symbols# Parameter
Default
Math symbol
Semantics
rate_timesNone\(t_k\)
Scheduled rate-change times, aligned to grid steps \(s_k\).
rate_valuesNone\(v_k\)
Scheduled firing rates (spikes/s) applied when \(s_k = n + 1\).
start0. * u.ms\(t_{\mathrm{start,rel}}\)
Relative exclusive lower bound of the active interval.
stopNone\(t_{\mathrm{stop,rel}}\)
Relative inclusive upper bound;
Nonemeans no upper cutoff.origin0. * u.ms\(t_0\)
Global time offset added to both
startandstop.allow_offgrid_timesFalse—
Off-grid policy: strict grid validation or upward ceiling alignment.
rng_seed0—
Seed for the JAX PRNG key used in Poisson sampling.
- Raises:
ValueError – If
stop < startat construction time; ifrate_timesandrate_valuesare not provided together; if their flattened lengths differ; if any configured time is not strictly in the future; if aligned grid steps are not strictly increasing; if an off-grid time is supplied whileallow_offgrid_timesisFalse; or if any time-like parameter is not scalar-convertible.TypeError – If unit conversion or numeric coercion fails for any time or rate input (e.g., incompatible
saiunit.Quantitydimensions).KeyError – At runtime during
update(), if the simulation context accessed viabrainstate.environis missing the requireddtkey.
Notes
Output values are spike counts per step (
0, 1, 2, ...), not binary spikes. High firing rates or large time steps may produce multiplicities greater than one.Calling
set()with a new non-empty schedule atomically resets the internal schedule pointer to index 0, matching NEST setter semantics.Calling
update()without a priorinit_state()call will lazily initialize state variables on the first invocation.The
rng_keystate is split (not folded) at each call, so the Poisson samples are statistically independent across time steps and across different elements ofself.varshape.
See also
poisson_generatorHomogeneous Poisson stimulation device.
sinusoidal_poisson_generatorSinusoidally modulated Poisson device.
step_rate_generatorPiecewise-constant deterministic rate generator.
References
Examples
Create a generator that fires at 800 Hz during
(5, 20]ms then goes silent, and read out the per-neuron spike counts at stept = 6 ms:>>> import brainpy >>> import brainstate >>> import saiunit as u >>> with brainstate.environ.context(dt=0.1 * u.ms): ... gen = brainpy.state.inhomogeneous_poisson_generator( ... in_size=4, ... rate_times=[5.0 * u.ms, 20.0 * u.ms], ... rate_values=[800.0 * u.Hz, 0.0 * u.Hz], ... start=0.0 * u.ms, ... stop=30.0 * u.ms, ... rng_seed=7, ... ) ... gen.init_state() ... with brainstate.environ.context(t=6.0 * u.ms): ... counts = gen.update() ... _ = counts.shape # (4,), dtype int64
Allow off-grid rate times and inspect the aligned schedule via
get():>>> import brainpy >>> import brainstate >>> import saiunit as u >>> with brainstate.environ.context(dt=0.1 * u.ms): ... gen = brainpy.state.inhomogeneous_poisson_generator( ... allow_offgrid_times=True, ... ) ... gen.set( ... rate_times=[1.23 * u.ms, 2.34 * u.ms], ... rate_values=[10.0 * u.Hz, 20.0 * u.Hz], ... ) ... params = gen.get() ... # params['rate_times'] contains ceil-aligned ms values ... _ = params['allow_offgrid_times'] # True
- get()[source]#
Return current schedule and timing parameters in NEST-style format.
Serializes all user-configurable generator parameters into a plain Python dict. This mirrors the
nest.GetStatusinterface so that parameter introspection and round-tripping viaset()/get()work as expected.- Returns:
params – Dictionary with the following keys:
'rate_times'(floatorlist[float]): Grid-aligned rate-change times in ms. A single-entry schedule is returned as a barefloat; a multi-entry schedule as a Pythonlist. An empty schedule returns an emptylist.'rate_values'(floatorlist[float]): Corresponding firing rates in spikes/s (Hz), same shape convention as'rate_times'.'allow_offgrid_times'(bool): Current off-grid alignment policy.'start'(float): Relative exclusive lower activity bound in ms.'stop'(float): Inclusive upper activity bound in ms, orfloat('inf')if no upper bound was set.'origin'(float): Global time offset in ms.
- Return type:
- init_state(batch_size=None, **kwargs)[source]#
Initialize transient schedule pointer and RNG state.
Creates the three
brainstate.ShortTermStateobjects required byupdate(): the schedule pointer_rate_idx(int64scalar), the currently active firing rate_rate_hz(float64scalar, initialized to0.0), and the JAX PRNG keyrng_keyseeded fromself.rng_seed.This method is idempotent with respect to the configured schedule: the existing
_rate_times_ms,_rate_values_hz, and_rate_stepsarrays are left unchanged; only the runtime-mutable state variables are (re-)created.
- set(*, rate_times=<object object>, rate_values=<object object>, allow_offgrid_times=<object object>)[source]#
Update the rate schedule and/or off-grid policy with NEST-compatible validation.
Replaces the current piecewise-constant rate schedule with a new one, optionally updating the off-grid alignment policy at the same time. All provided times are validated against the current simulation clock (must be strictly in the future), aligned to the simulation grid, and checked for strict monotonicity.
Passing
rate_times=[]andrate_values=[]clears the schedule: internal arrays are set to empty and the schedule pointer is reset to 0.- Parameters:
rate_times (
Sequence[ArrayLike]orArrayLike, optional) – New rate-change times in ms. Inputs are flattened to shape(K,)and stored asnp.ndarray[float64]after grid alignment. Must be provided together withrate_values; omitting one while supplying the other raisesValueError. If omitted entirely (sentinel_UNSET), the existing schedule is left unchanged.rate_values (
Sequence[ArrayLike]orArrayLike, optional) – New firing rates in spikes/s (Hz) paired one-to-one withrate_times. Stored asnp.ndarray[float64]. Must have exactly the same flattened length asrate_times.allow_offgrid_times (
bool, optional) – If supplied, updatesself.allow_offgrid_times. Changing this flag is only permitted whenrate_timesis also being set in the same call, or when no schedule has been configured yet. Attempting to change the flag with an existing non-empty schedule and without new times raisesValueError.
- Raises:
ValueError – If exactly one of
rate_times/rate_valuesis provided (must supply both or neither); if their flattened lengths differ; ifallow_offgrid_timesis changed while an existing non-empty schedule is in place without also providing new times; if any time value is not strictly greater than the current environment time; if any two adjacent aligned grid steps are not strictly increasing; or if a time is off-grid andallow_offgrid_timesisFalse.TypeError – If unit conversion fails for
rate_timesorrate_valuesinputs (e.g., incompatiblesaiunit.Quantitydimensions).
- update()[source]#
Advance one simulation step and emit Poisson spike multiplicities.
Reads the current simulation time from
brainstate.environ, advances the schedule pointer past any entries whose grid step \(s_k \le n\), then applies the next scheduled rate change if \(s_k = n + 1\). When the generator is active (current time inside the activity window) and the current rate is positive, samples a Poisson multiplicity array overself.varshape. Otherwise returns a zero array.Lazy initialization: if
init_state()has not been called, this method initializes state variables on the first invocation.- Returns:
spikes – Per-output Poisson spike multiplicity for the current time step. Each element \(K_i \sim \mathrm{Poisson}(\lambda_n)\) where \(\lambda_n = r_n \Delta t / 1000\). Returns all-zero array when the generator is inactive or the current rate is zero.
- Return type:
jax.Array,shape ``self.varshape``,dtype ``int64``