sinusoidal_gamma_generator#
- class brainpy.state.sinusoidal_gamma_generator(in_size=1, rate=Quantity(0., 'Hz'), amplitude=Quantity(0., 'Hz'), frequency=Quantity(0., 'Hz'), phase=0.0, order=1.0, individual_spike_trains=True, start=Quantity(0., 'ms'), stop=None, origin=Quantity(0., 'ms'), rng_seed=0, name=None)#
Sinusoidally modulated gamma spike generator compatible with NEST.
Description
sinusoidal_gamma_generatorre-implements NEST’s stimulation device of the same name. It emits binary spikes from an inhomogeneous gamma renewal process whose instantaneous rate is sinusoidally modulated.1. Instantaneous-rate model
The internal rate in spikes/ms is
\[\lambda(t) = r + a \sin(\omega t + \phi),\]with parameter-to-symbol conversion:
\(r = \mathrm{rate}/1000\),
\(a = \mathrm{amplitude}/1000\),
\(\omega = 2\pi \cdot \mathrm{frequency}/1000\) (rad/ms),
\(\phi = \mathrm{phase}\cdot\pi/180\) (rad).
The validated constraint
0 <= amplitude <= rateguarantees \(\lambda(t) \ge 0\) for all \(t\).2. Renewal integral, closed-form increment, and hazard
For gamma order \(k = \mathrm{order}\) and train-specific renewal origin \(t_0\), define the scaled integrated hazard as
\[\Lambda(t) = k \int_{t_0}^{t} \lambda(s)\,ds.\]The implementation keeps
t0_msandLambda_t0as per-train state variables and advances \(\Lambda\) each step via the closed-form increment computed in_delta_lambda():\[\Delta\Lambda = k r (t_b - t_a) - \frac{k a}{\omega}\Bigl[ \cos(\omega t_b + \phi) - \cos(\omega t_a + \phi) \Bigr].\]When
amplitude == 0orfrequency == 0(i.e. \(\omega = 0\)), the cosine term is omitted and \(\Delta\Lambda = k r (t_b - t_a)\), which avoids division by zero and recovers the homogeneous Poisson limit (\(k = 1\)) or homogeneous gamma limit (\(k > 1\)).The per-step hazard (already multiplied by
dt) evaluated at time \(t\) is\[h(t) = \Delta t \cdot \frac{k\,\lambda(t)\,\Lambda(t)^{k-1}\,e^{-\Lambda(t)}} {\Gamma(k,\,\Lambda(t))},\]where \(\Gamma(k, \Lambda)\) is the upper incomplete gamma function evaluated via
jax.lax.igammacandmath.gamma. The ratio \(h(t)\) approximates \(\Pr(\text{spike in } [t, t+\Delta t))\) under the gamma renewal model.3. Update ordering and activity-window semantics
Each call to
update()mirrors the ordering in NESTmodels/sinusoidal_gamma_generator.cpp:Evaluate time at the right edge of the current step:
t_eval = (step + 1) * dt.Compute \(\lambda(t_{\mathrm{eval}})\) and cache the value as the step-end instantaneous rate in spikes/s (accessible via
get_recorded_rate()).If the generator is active and \(\lambda(t_{\mathrm{eval}}) > 0\), compute the per-train hazard and sample Bernoulli decisions.
Reset
t0_msandLambda_t0tot_eval/0for any train that fired.Return binary spike outputs as
int64with shapeself.varshape.
NEST spike-generator activity semantics use the half-open-right window
\[t_{\min} < n \le t_{\max},\]where \(n\) is the current integer step index,
t_min = round((origin + start) / dt), andt_max = round((origin + stop) / dt)after projection to grid steps.4. Piecewise-integral semantics on parameter changes
When
set()is called after initialization, the existing per-train renewal state is first advanced to the change time \(t_c\) using the previous process parameters, then future increments use the new parameters:\[\Lambda(t) = \Lambda_{\mathrm{old}}(t_c) + k_{\mathrm{new}} \int_{t_c}^{t} \lambda_{\mathrm{new}}(s)\,ds.\]This preserves renewal history across parameter updates, matching NEST
SetStatusbehavior.5. Assumptions, constraints, and computational implications
Public parameters are scalarized to
float64(orintforrng_seed); non-scalar inputs raiseValueError.Enforced constraints:
order >= 1,0 <= amplitude <= rate, andstop >= start.When
dtis available at construction time, finiteorigin/start/stopmust be representable on the simulation grid (absolute tolerance1e-12intime / dtratio).individual_spike_trains=Trueallocates one independent renewal state per element ofself.varshapeand draws independent Bernoulli samples;individual_spike_trains=Falsemaintains one shared renewal state and broadcasts the single Bernoulli draw to all outputs.Per-step runtime is \(O(n_{\mathrm{trains}})\) for hazard evaluation and sampling, with memory \(O(n_{\mathrm{trains}})\) for
t0_msandLambda_t0.At most one spike per train can be emitted per step because spike decisions are independent Bernoulli trials against the per-step hazard.
- Parameters:
in_size (
Size, optional) – Output size specification forbrainstate.nn.Dynamics.self.varshapederived fromin_sizeis the exact output shape ofupdate(); each element corresponds to one emitted train. Default is1.rate (
ArrayLike, optional) – Scalar mean firing rate in spikes/s (Hz), shape()after conversion. Accepted as a scalarArrayLikeor asaiunit.Quantityconvertible tou.Hz. Must satisfy0 <= amplitude <= rate. Default is0.0 * u.Hz.amplitude (
ArrayLike, optional) – Scalar sinusoidal modulation amplitude in spikes/s (Hz), shape()after conversion. Must satisfy0 <= amplitude <= rateafter conversion; the constraint ensures \(\lambda(t) \ge 0\). Default is0.0 * u.Hz.frequency (
ArrayLike, optional) – Scalar modulation frequency in Hz, shape()after conversion. Internally mapped to angular frequency \(\omega = 2\pi f / 1000\) (rad/ms). Default is0.0 * u.Hz.phase (
ArrayLike, optional) – Scalar initial phase in degrees, shape()after conversion; internally converted to radians as \(\phi = \phi_{\deg} \pi / 180\). Default is0.0.order (
ArrayLike, optional) – Scalar gamma renewal order \(k\), shape()after conversion. Must satisfyorder >= 1; order1recovers an inhomogeneous Poisson process. Default is1.0.individual_spike_trains (
bool, optional) – Spike-generation mode selector. IfTrue, each output index inself.varshapemaintains independent renewal state(t0_ms, Lambda_t0)and receives independent Bernoulli draws. IfFalse, one shared renewal process is maintained and the same binary spike decision is broadcast to all outputs. Default isTrue.start (
ArrayLike, optional) – Scalar relative activation start time in ms, shape()after conversion. Effective lower activity bound isorigin + start; the bound is exclusive in step space (t_min_step < curr_step). Default is0.0 * u.ms.stop (
ArrayLikeorNone, optional) – Scalar relative deactivation stop time in ms, shape()after conversion.Nonemaps to+inf. Effective upper activity bound isorigin + stop; the bound is inclusive in step space (curr_step <= t_max_step). Must satisfystop >= startafter conversion. Default isNone.origin (
ArrayLike, optional) – Scalar origin offset in ms, shape()after conversion. Added tostartandstopto obtain the absolute activity boundst_minandt_max. Default is0.0 * u.ms.rng_seed (
int, optional) – Seed used to initializejax.random.PRNGKeyduringinit_state()and lazy initialization inupdate(). Default is0.name (
strorNone, optional) – Optional node name passed tobrainstate.nn.Dynamics. Default isNone.
Parameter Mapping
Table 36 Parameter mapping to model symbols# Parameter
Default
Math symbol
Semantics
rate0.0 * u.Hz\(r\)
Baseline firing-rate term in spikes/ms after division by
1000.amplitude0.0 * u.Hz\(a\)
Sinusoidal modulation amplitude in spikes/ms after division by
1000.frequency0.0 * u.Hz\(f\)
Frequency in Hz mapped to \(\omega = 2\pi f/1000\) (rad/ms).
phase0.0\(\phi\)
Phase in degrees mapped to radians as \(\phi_{\deg}\pi/180\).
order1.0\(k\)
Gamma renewal order;
1= inhomogeneous Poisson.start0.0 * u.ms\(t_{\mathrm{start,rel}}\)
Relative exclusive lower bound of activity window.
stopNone\(t_{\mathrm{stop,rel}}\)
Relative inclusive upper bound;
Nonemaps to \(+\infty\).origin0.0 * u.ms\(t_{\mathrm{origin}}\)
Global time offset added to
startandstop.in_size1—
Defines
self.varshapeand the total output train count.individual_spike_trainsTrue—
Independent per-output renewal states vs. shared broadcast process.
rng_seed0—
Seed for JAX random key initialization and splitting.
- Raises:
ValueError – If scalar-conversion fails due to non-scalar inputs; if
0 <= amplitude <= rateis violated; iforder < 1; ifstop < start; or if finiteorigin/start/stopare not multiples of the simulation resolution whendtis available.TypeError – If provided values cannot be converted to numeric values or to the required units (e.g. a non-convertible
u.Hzoru.msquantity).KeyError – At runtime in
update(), if required simulation-context entries (notablydt) are unavailable frombrainstate.environ.
Notes
Hazard values are computed in
float64; tiny negative \(\Lambda\) values arising from floating-point roundoff are clamped to zero before hazard evaluation.The value returned by
get_recorded_rate()is the step-end instantaneous rate in spikes/s, matching NEST’sraterecordable.Renewal state is revalidated against the timing grid whenever
dtchanges betweenupdate()calls.
Examples
Simulate a 2×3 array of independent sinusoidally modulated gamma trains:
>>> import brainpy >>> import brainstate >>> import saiunit as u >>> with brainstate.environ.context(dt=0.1 * u.ms): ... gen = brainpy.state.sinusoidal_gamma_generator( ... in_size=(2, 3), ... rate=50.0 * u.Hz, ... amplitude=20.0 * u.Hz, ... frequency=8.0 * u.Hz, ... phase=30.0, ... order=3.0, ... start=5.0 * u.ms, ... stop=80.0 * u.ms, ... rng_seed=9, ... ) ... with brainstate.environ.context(t=12.0 * u.ms): ... spikes = gen.update() ... _ = spikes.shape
Use
individual_spike_trains=Falseand update parameters at runtime:>>> import brainpy >>> import brainstate >>> import saiunit as u >>> with brainstate.environ.context(dt=0.1 * u.ms): ... gen = brainpy.state.sinusoidal_gamma_generator( ... individual_spike_trains=False ... ) ... gen.set(rate=40.0 * u.Hz, amplitude=10.0 * u.Hz, order=2.0) ... params = gen.get() ... _ = params['rate'], params['order']
See also
sinusoidal_poisson_generatorSinusoidally modulated Poisson generator.
gamma_sup_generatorSuperposition of independent gamma-renewal processes.
References
- get()[source]#
Return current public parameters as plain Python scalars.
- Returns:
out – Mapping of parameter names to their current values. Keys and value types are:
'rate':float— mean firing rate in spikes/s.'amplitude':float— sinusoidal modulation amplitude in spikes/s.'frequency':float— modulation frequency in Hz.'phase':float— modulation phase in degrees.'order':float— gamma renewal order \(k\).'individual_spike_trains':bool— spike-generation mode flag.'start':float— relative activation start in ms.'stop':float— relative deactivation stop in ms (float('inf')when no stop was set).'origin':float— time-origin offset in ms.
- Return type:
- get_recorded_rate()[source]#
Return the latest step-end instantaneous rate in spikes/s.
The value is updated by
update()at each simulation step to \(\lambda(t_{\mathrm{eval}}) \times 1000\) spikes/s, where \(t_{\mathrm{eval}} = (\mathrm{step} + 1) \times dt\) is the right edge of the current step. This matches NEST’sraterecordable quantity.- Returns:
out – Most recently cached instantaneous rate in spikes/s (
float64scalar). Returns0.0ifinit_state()has not been called yet.- Return type:
- init_state(batch_size=None, **kwargs)[source]#
Initialize random key and per-train renewal state.
Allocates three
brainstate.ShortTermStatevariables:rng_key: a JAXPRNGKeyseeded fromself.rng_seed.t0_ms: per-train renewal origin, initialized to the current simulation time (float64array of lengthself._num_trains).Lambda_t0: per-train accumulated scaled hazard att0_ms, initialized to zero (float64array of lengthself._num_trains)._recorded_rate_hz: cached step-end instantaneous rate in spikes/s, initialized to0.0.
The timing cache (
_t_min_step,_t_max_step) is also refreshed ifdtis available in the currentbrainstate.environcontext.- Parameters:
- Raises:
ValueError – If finite
origin/start/stopdo not lie on the simulation grid whendtis available.
- set(*, rate=<object object>, amplitude=<object object>, frequency=<object object>, phase=<object object>, order=<object object>, individual_spike_trains=<object object>, start=<object object>, stop=<object object>, origin=<object object>)[source]#
Update public parameters and refresh the process and timing caches.
Any parameter left at its sentinel value
_UNSETretains its current value. When called afterinit_state(), the internal renewal state is first advanced to the current simulation time using the previous process parameters before switching to the new ones, preserving the piecewise-integral semantics described in the class docstring. Ifindividual_spike_trainschanges in a way that alters the required number of trains,t0_msandLambda_t0are grown (new trains start fresh) or truncated accordingly.- Parameters:
rate (
ArrayLikeorNone, optional) – New scalar mean rate in spikes/s (Hz), shape()after conversion._UNSETretains the current value.amplitude (
ArrayLikeorNone, optional) – New scalar modulation amplitude in spikes/s (Hz), shape()after conversion._UNSETretains the current value.frequency (
ArrayLikeorNone, optional) – New scalar modulation frequency in Hz, shape()after conversion._UNSETretains the current value.phase (
ArrayLikeorNone, optional) – New scalar modulation phase in degrees, shape()after conversion._UNSETretains the current value.order (
ArrayLikeorNone, optional) – New scalar gamma order \(k\), shape()after conversion._UNSETretains the current value.individual_spike_trains (
boolorNone, optional) – New spike-generation mode._UNSETretains the current value.start (
ArrayLikeorNone, optional) – New scalar relative activation start time in ms, shape()after conversion._UNSETretains the current value.stop (
ArrayLike,None, orsentinel, optional) – New scalar relative stop time in ms, shape()after conversion; explicitNonemaps to+inf._UNSETretains the current value.origin (
ArrayLikeorNone, optional) – New scalar origin offset in ms, shape()after conversion._UNSETretains the current value.
- Raises:
ValueError – If scalar conversion fails due to non-scalar inputs; if the constraints
order >= 1,0 <= amplitude <= rate, orstop >= startare violated after resolving new values; or if finite timing parameters do not lie on the simulation grid whendtis available.TypeError – If numeric or unit conversion fails for any supplied input.
- update()[source]#
Advance one simulation step and emit binary spike events.
Reads the current time
tand resolutiondtfrombrainstate.environ, lazily callsinit_state()if state has not been allocated, and refreshes the timing cache ifdthas changed since the last call. The step-end timet_eval = (step + 1) * dtis used for rate evaluation and \(\Lambda\) accumulation. Trains outside the active window or with \(\lambda(t_{\mathrm{eval}}) \le 0\) receive zero spikes without consuming random draws.- Returns:
out –
int64JAX array with shapeself.varshape. Each element is0or1, giving the binary spike decision for the corresponding output train in the current step. Whenindividual_spike_trains=False, all elements share the same value.- Return type:
jax.Array- Raises:
KeyError – If
dtis not available in the currentbrainstate.environcontext.ValueError – If timing-parameter grid validation fails after the simulation resolution changes between calls.