noise_generator#
- class brainpy.state.noise_generator(in_size=1, mean=Quantity(0., 'pA'), std=Quantity(0., 'pA'), noise_dt=None, std_mod=Quantity(0., 'pA'), frequency=Quantity(0., 'Hz'), phase=0.0, start=Quantity(0., 'ms'), stop=None, origin=Quantity(0., 'ms'), seed=None, name=None)#
Gaussian white-noise current generator compatible with NEST.
Generate a piecewise-constant Gaussian current with optional sinusoidal modulation of the noise standard deviation and a NEST-style activity window.
1. Stochastic process and update rule
Let \(\delta\) be the configured noise update period. For each channel and noise interval index \(j\), this implementation samples
\[A_j = \mu + \xi_j \sigma_{\mathrm{eff}}(t_j), \qquad \xi_j \sim \mathcal{N}(0, 1),\]then emits \(I(t)=A_j\) for \(t_j \le t < t_j + \delta\) while the generator is active. The effective standard deviation is
\[\sigma_{\mathrm{eff}}(t) = \sqrt{\max\!\left(\sigma^2 + \sigma_{\mathrm{mod}}^2 \sin(\omega t + \phi),\, 0\right)}, \qquad \omega = \frac{2\pi f}{1000}.\]The non-negativity clamp follows the implementation exactly:
maximum(., 0)is applied beforesqrtso modulation never yields invalid real values.2. Variance approximation and assumptions
For an LIF membrane receiving the unmodulated process (\(\sigma_{\mathrm{mod}}=0\)) with \(\delta \ll \tau_m\), the asymptotic membrane potential variance is approximated by
\[\Sigma^2 = \frac{\delta \tau_m \sigma^2}{2 C_m^2}.\]This approximation assumes linear subthreshold dynamics, stationary statistics, and sufficiently small update period relative to membrane time constant. Increasing \(\delta\) increases drive variance linearly and shifts the spectrum away from ideal white-noise behavior.
3. Timing semantics and computational implications
The activity window is half-open: \([t_0 + t_{\mathrm{start,rel}},\ t_0 + t_{\mathrm{stop,rel}})\). Therefore,
startis inclusive andstopis exclusive.Noise amplitudes are refreshed when
step_counter % round(noise_dt / dt) == 0. Ifnoise_dt is None, thennoise_dt = dtand updates occur every simulation step.This implementation is vectorized over
self.varshapeand performs one PRNG split and one Gaussian draw perupdate()call, followed by a mask that either accepts the new sample or retains the previous amplitude. Work per call is \(O(\prod \mathrm{varshape})\).- Parameters:
in_size (
Size, optional) – Output size/shape specification forbrainstate.nn.Dynamics. The generated current shape isself.varshapederived fromin_size. Default is1.mean (
ArrayLike, optional) – Mean current \(\mu\) (typically pA). Scalars or arrays are accepted and broadcast toself.varshapebybraintools.init.param(). Default is0. * u.pA.std (
ArrayLike, optional) – Baseline standard deviation \(\sigma\) (typically pA), broadcast toself.varshape. Default is0. * u.pA.noise_dt (
ArrayLikeorNone, optional) – Noise refresh interval \(\delta\) (typically ms).Nonemeans use simulationdtat runtime. Values are converted to integer steps byround(noise_dt / dt); valid execution requires this rounded value to be at least1for every channel. Default isNone.std_mod (
ArrayLike, optional) – Modulation amplitude \(\sigma_{\mathrm{mod}}\) (typically pA) for the sinusoidal term in \(\sigma_{\mathrm{eff}}\). Broadcast toself.varshape. Default is0. * u.pA.frequency (
ArrayLike, optional) – Modulation frequency \(f\) in Hz (or unitless values interpreted as Hz), broadcast toself.varshape. Converted internally to rad/ms using \(\omega = 2\pi f/1000\). Default is0. * u.Hz.phase (
ArrayLike, optional) – Modulation phase in degrees, broadcast toself.varshape. Converted internally as \(\phi = \mathrm{phase}\cdot 2\pi/360\). Default is0..start (
ArrayLike, optional) – Relative activation time \(t_{\mathrm{start,rel}}\) (typically ms), broadcast toself.varshape. Effective lower bound isorigin + start. Default is0. * u.ms.stop (
ArrayLikeorNone, optional) – Relative deactivation time \(t_{\mathrm{stop,rel}}\) (typically ms), broadcast toself.varshapewhen provided. Effective upper bound isorigin + stopand is exclusive.Nonemeans no upper bound. Default isNone.origin (
ArrayLike, optional) – Time origin \(t_0\) (typically ms), broadcast toself.varshapeand added tostart/stop. Default is0. * u.ms.seed (
intorNone, optional) – PRNG seed used byjax.random.PRNGKey()ininit_state().Noneselects deterministic fallback seed0. Default isNone.name (
strorNone, optional) – Optional node name passed tobrainstate.nn.Dynamics.
Parameter Mapping
Table 25 Parameter mapping to model symbols# Parameter
Default
Math symbol
Semantics
mean0. * u.pA\(\mu\)
Mean of the Gaussian current samples.
std0. * u.pA\(\sigma\)
Baseline standard deviation of the noise process.
noise_dtNone\(\delta\)
Interval between sample refreshes; defaults to simulation
dt.std_mod0. * u.pA\(\sigma_{\mathrm{mod}}\)
Amplitude of sinusoidal modulation in variance term.
frequency0. * u.Hz\(f\)
Modulation frequency converted to \(\omega=2\pi f/1000\).
phase0.\(\phi_{\mathrm{deg}}\)
Modulation phase in degrees, converted to radians in update.
start0. * u.ms\(t_{\mathrm{start,rel}}\)
Relative lower activity bound added to
origin.stopNone\(t_{\mathrm{stop,rel}}\)
Relative upper activity bound added to
origin.origin0. * u.ms\(t_0\)
Global time offset for both activity boundaries.
- Raises:
ValueError – If
in_sizeis invalid or if array-like parameters cannot be broadcast toself.varshapebybraintools.init.param().KeyError – If runtime environment keys such as
't'or'dt'are missing whenupdate()is called.TypeError – If unitful/unitless arithmetic is incompatible (for example invalid combinations among time, frequency, and current parameters).
ZeroDivisionError – If
round(noise_dt / dt)evaluates to0so modulo scheduling inupdate()attempts division by zero.
Notes
NEST describes independent random currents per target neuron. In this implementation, one generator instance emits one current vector per call; downstream targets reading the same channel receive the same value for that step. Use separate generator instances to guarantee independent streams.
See also
dc_generatorConstant current stimulation device.
ac_generatorSinusoidal current stimulation device.
step_current_generatorPiecewise-constant current stimulation device.
References
Examples
Basic usage: unmodulated white-noise drive injected into a single neuron.
>>> import brainpy >>> import brainstate >>> import saiunit as u >>> with brainstate.environ.context(dt=0.1 * u.ms): ... stim = brainpy.state.noise_generator( ... in_size=1, ... mean=0.0 * u.pA, ... std=100.0 * u.pA, ... noise_dt=0.2 * u.ms, ... seed=42, ... ) ... neuron = brainpy.state.iaf_psc_delta(1) ... neuron.init_state() ... with brainstate.environ.context(t=1.0 * u.ms): ... current = stim.update() ... _ = neuron.update(x=current)
Sinusoidally modulated noise: variance oscillates at gamma frequency (40 Hz) within a restricted activity window.
>>> import brainpy >>> import saiunit as u >>> gen = brainpy.state.noise_generator( ... in_size=4, ... mean=50.0 * u.pA, ... std=80.0 * u.pA, ... noise_dt=1.0 * u.ms, ... std_mod=40.0 * u.pA, ... frequency=40.0 * u.Hz, ... phase=0.0, ... start=10.0 * u.ms, ... stop=110.0 * u.ms, ... seed=0, ... )
- init_state(batch_size=None, **kwargs)[source]#
Initialize RNG and internal state buffers for piecewise noise updates.
- Parameters:
batch_size (
intorNone, optional) – Optional batch dimension forwarded tobraintools.init.param()when allocatingcurrent_amp.Nonekeeps unbatched state. Default isNone.**kwargs (
Any) – Extra keyword arguments accepted for API compatibility withbrainstate.nn.Dynamics. They are currently unused.
- Raises:
TypeError – If
seedcannot be interpreted byjax.random.PRNGKey().ValueError – If
batch_sizeor shape metadata is incompatible withbraintools.init.param().
Notes
The PRNG key is stored as a plain Python/JAX attribute rather than a
brainstate.ShortTermState, meaning it is not managed by the brainstate state-management system and will not be checkpointed automatically. Reproducible runs therefore require re-callinginit_statewith the sameseedbefore each simulation.See also
noise_generator.updateUses
_rng_key,current_amp, and_step_counterpopulated by this method.
Examples
>>> import brainstate >>> import saiunit as u >>> from brainpy.state import noise_generator >>> with brainstate.environ.context(dt=0.1 * u.ms): ... gen = noise_generator( ... in_size=2, ... std=50.0 * u.pA, ... seed=7, ... ) ... gen.init_state()
- update()[source]#
Advance the generator one simulation step and return current output.
- Returns:
out – Current-like quantity with shape
self.varshape. If active, values equal the cached piecewise-constant amplitude sampled frommean + N(0,1) * effective_std; otherwise values are zero.- Return type:
jax.Array- Raises:
KeyError – If environment keys
't'or'dt'are missing.TypeError – If unit conversions/comparisons are invalid (for example incompatible units in
noise_dt,dt, or time bounds).ZeroDivisionError – If
round(noise_dt / dt)is0and modulo scheduling is evaluated with zero divisor.
Notes
The update proceeds in four phases each call:
Step scheduling –
noise_dtis resolved to a whole number of simulation stepsdt_steps = round(noise_dt / dt). A boolean flagneed_update = (step_counter % dt_steps) == 0gates whether a new amplitude is drawn.Effective standard deviation – computed as
\[\sigma_{\mathrm{eff}} = \sqrt{\max\!\left(\sigma^2 + \sigma_{\mathrm{mod}}^2 \sin(\omega t + \phi),\, 0\right)}\]using
u.math.maximum()beforeu.math.sqrt()so the radicand is always non-negative.Sample draw –
noise = jax.random.normal(subkey, varshape); the PRNG key is advanced every call regardless ofneed_update.Masked update –
current_ampretains its previous value on steps whereneed_updateisFalse, avoiding redundant draws while keeping the sample schedule deterministic.
The activity window is
origin + start <= t < origin + stop(lower-bounded only whenstop is None). While inactive the output is exactly zero regardless ofcurrent_amp.See also
noise_generator.init_stateMust be called before the first update.
noise_generatorClass-level parameter definitions and model equations.
ac_generator.updateWindowed sinusoidal-current update rule.