braintools.analysis.spike.psth

Contents

braintools.analysis.spike.psth#

braintools.analysis.spike.psth(trains, events, window, bin_size, *, rate=True)#

Compute the event-aligned peri-stimulus time histogram (PSTH).

The spikes of every neuron are aligned to each event and counted in consecutive bins covering the window [-t_before, t_after) around the event, then summed over the events.

Parameters:
  • trains (SpikeTrains) – Spike trains with N neurons.

  • events (Any) – Event (trial onset) times of shape (E,), in the time frame of the spike trains. Non-finite entries (e.g. +inf padding) are ignored, so a variable number of events fits a static shape. A plain number is in milliseconds.

  • window (Sequence[Any]) – (t_before, t_after): the histogram spans [-t_before, t_after) relative to each event, i.e. t_before is the time before the event (a positive value reaches into the past). Static. Plain numbers are in milliseconds.

  • bin_size (Any) – Bin width, static and positive. A plain number is in milliseconds.

  • rate (bool) – If True, return the trial-averaged rate in Hz, count / (E_valid * bin_size), with E_valid the number of finite events. If False, return the summed spike counts.

Return type:

Tuple[Array, Any]

Returns:

  • values (jax.Array) – Rates in Hz (float) or counts (int32), shape (n_bins, N), with n_bins = ceil((t_before + t_after) / bin_size). The rate is nan when there is no finite event.

  • bin_edges (jax.Array or Quantity) – Edges relative to the event, shape (n_bins + 1,), starting at -t_before; a Quantity when the spike times carry units, otherwise plain milliseconds.

Raises:
  • TypeError – If trains is not a SpikeTrains, or window/bin_size are traced.

  • ValueError – If events is not 1-D, bin_size is not positive, or the window has non-positive length.

See also

cross_correlogram

Lag histograms with spikes as the alignment events.

braintools.spike.SpikeTrains.bin

Binning from the recording start.

Notes

Bin i is the half-open interval [edge_i, edge_{i+1}); a spike exactly on an edge belongs to the later bin. When bin_size does not divide the window, the last bin is still a full bin and ends after t_after. Windows extending beyond the recording are not corrected: the missing part simply contributes no spikes.

Spike counts are found with searchsorted on the sorted spike times, in O(E N n_bins log K) time. The events are processed in batches of a static size chosen so that each step’s temporaries hold at most about \(2^{21}\) elements (at least one event), and the counts are accumulated with lax.scan; peak memory is therefore O(N K + N n_bins + 2^21) rather than O(N E n_bins). Under an outer jax.vmap the per-step memory is multiplied by the batch size of that vmap. Works under jax.jit and jax.vmap (e.g. over trials or sessions) with static window and bin_size; the counts are not differentiable.

Examples

>>> import brainunit as u
>>> import jax.numpy as jnp
>>> from braintools.spike import SpikeTrains
>>> from braintools.analysis.spike import psth
>>> raster = jnp.zeros((100, 1)).at[jnp.array([20, 21, 61, 63]), 0].set(1)
>>> st = SpikeTrains.from_dense(raster, dt=1. * u.ms)
>>> events = jnp.array([20., 60., jnp.inf]) * u.ms   # last event is padding
>>> counts, edges = psth(st, events, window=(2. * u.ms, 4. * u.ms),
...                      bin_size=2. * u.ms, rate=False)
>>> counts[:, 0]
Array([0, 3, 1], dtype=int32)
>>> edges
Quantity([-2.  0.  2.  4.], "ms")
>>> rates, _ = psth(st, events, window=(2. * u.ms, 4. * u.ms), bin_size=2. * u.ms)
>>> rates[:, 0]
Array([  0., 750., 250.], dtype=float32)