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 withNneurons.events (
Any) – Event (trial onset) times of shape(E,), in the time frame of the spike trains. Non-finite entries (e.g.+infpadding) 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_beforeis 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), withE_validthe number of finite events. If False, return the summed spike counts.
- Return type:
- Returns:
values (jax.Array) – Rates in Hz (float) or counts (
int32), shape(n_bins, N), withn_bins = ceil((t_before + t_after) / bin_size). The rate isnanwhen 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
trainsis not aSpikeTrains, orwindow/bin_sizeare traced.ValueError – If
eventsis not 1-D,bin_sizeis not positive, or the window has non-positive length.
See also
cross_correlogramLag histograms with spikes as the alignment events.
braintools.spike.SpikeTrains.binBinning from the recording start.
Notes
Bin
iis the half-open interval[edge_i, edge_{i+1}); a spike exactly on an edge belongs to the later bin. Whenbin_sizedoes not divide the window, the last bin is still a full bin and ends aftert_after. Windows extending beyond the recording are not corrected: the missing part simply contributes no spikes.Spike counts are found with
searchsortedon the sorted spike times, inO(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 withlax.scan; peak memory is thereforeO(N K + N n_bins + 2^21)rather thanO(N E n_bins). Under an outerjax.vmapthe per-step memory is multiplied by the batch size of thatvmap. Works underjax.jitandjax.vmap(e.g. over trials or sessions) with staticwindowandbin_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)