braintools.analysis.stats.jitter_spikes

Contents

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 width while 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, from jax.random.key or jax.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 (the brainstate convention), 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_stop and overflow. Valid times are sorted per neuron and lie in [t_start, t_stop); padding stays +inf at the end.

Return type:

SpikeTrains

Raises:
  • TypeError – If trains is not a SpikeTrains, or width is a Quantity that is not a time.

  • ValueError – If method is unknown or a concrete width is negative.

See also

shuffle_isi

Randomise spike times while keeping the ISI distribution.

phase_randomize

Randomised copies of continuous signals.

Notes

Works under jax.jit and jax.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)