braintools.analysis.stats.jitter_spikes#
- braintools.analysis.stats.jitter_spikes(key, trains, width, method='uniform')#
Randomly displace every spike by an independent offset.
Spike jittering destroys temporal structure finer than
widthwhile keeping each neuron’s spike count and its slow rate profile [1] [2]. Statistics recomputed on many jittered copies give the null distribution of a significance test (the copies are called surrogate data in the literature).'uniform': offsets drawn from \(U(-w, w)\);'gaussian': offsets drawn from \(\mathcal{N}(0, w^2)\).
Spikes moved outside
[t_start, t_stop)are reflected back at the bounds, and the times are re-sorted per neuron.- Parameters:
key (
Array) – PRNG key, fromjax.random.keyorjax.random.PRNGKey.trains (
SpikeTrains) – Spike trains to jitter.width (
Any) – Jitter half-width ('uniform') or standard deviation ('gaussian'). Must be non-negative. A Quantity is converted to the unit of the spike times; a plain number is in milliseconds (thebrainstateconvention), and unitless spike times are taken to be in milliseconds as well.method (
str) – Offset distribution.
- Returns:
New trains with the same
counts, capacity,t_start,t_stopandoverflow. Valid times are sorted per neuron and lie in[t_start, t_stop); padding stays+infat the end.- Return type:
- Raises:
TypeError – If
trainsis not aSpikeTrains, orwidthis a Quantity that is not a time.ValueError – If
methodis unknown or a concretewidthis negative.
See also
shuffle_isiRandomise spike times while keeping the ISI distribution.
phase_randomizeRandomised copies of continuous signals.
Notes
Works under
jax.jitandjax.vmap; vmapping over a batch of keys produces a batch of independent jittered copies. The reflection is periodic, so offsets larger than the recording are folded back as well. Not intended for differentiation.References
Examples
>>> import brainunit as u >>> import jax >>> import jax.numpy as jnp >>> from braintools.spike import SpikeTrains >>> from braintools.analysis.stats import jitter_spikes >>> raster = jnp.zeros((100, 2)).at[::10, 0].set(1.).at[5, 1].set(1.) >>> st = SpikeTrains.from_dense(raster, dt=1. * u.ms) >>> jittered = jitter_spikes(jax.random.key(0), st, 2. * u.ms) >>> jittered.counts Array([10, 1], dtype=int32) >>> bool(u.math.all(u.math.abs(jittered.times[0] - st.times[0]) <= 2. * u.ms)) True >>> >>> # 100 independent copies for a significance test: >>> keys = jax.random.split(jax.random.key(1), 100) >>> copies = jax.vmap(lambda k: jitter_spikes(k, st, 2. * u.ms))(keys) >>> copies.times.shape (100, 2, 10)