cells.spike_triggered_population_coupling
cells.spike_triggered_population_coupling(
spike_times,
spike_clusters,
cluster_ids,
lateral_um,
axial_um,
radius_um,
lags=0.08,
binsize=BINSIZE,
lowpass_hz=20.0,
)Population coupling of each cluster to its local, spatially-restricted population, as defined in Bimbard, Harris & Carandini, “Invariant activity sequences across the mouse brain” (bioRxiv 2025.12.20.695676), Methods section “Population coupling”, itself an extension of Okun et al. 2015 (Nature 521, 511-515).
For cluster i, let :math:g_i(t) be the mean, across every other cluster within radius_um of it on the probe, of the mean-centred binned firing:
.. math::
g_i(t) = \frac{1}{N_i - 1}\sum_{j \in \mathrm{neighbours}(i)} (f_j(t) - \mu_j)
The coupling at lag :math:\tau is then the spike-triggered average of :math:g_i, i.e. the (normalised) cross-correlation of cluster i’s spike train with :math:g_i:
.. math::
c_{i,\tau} = 100 \times \frac{1}{\lVert f_i \rVert}
\int f_i(t - \tau)\, g_i(t)\, dt
where :math:\lVert f_i \rVert is the number of spikes fired by cluster i. The result is expressed as a percentage and, by construction, is uncorrelated with a neuron’s own firing rate.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| spike_times | array_like | Spike times (s), one entry per spike. | required |
| spike_clusters | array_like | Cluster id of each spike (same length as spike_times); values are looked up in cluster_ids, so ids need not be contiguous or start at 0. |
required |
| cluster_ids | array_like | Cluster ids to compute the coupling for, and from which each cluster’s local population is built; defines the row order of the outputs and must align with lateral_um, axial_um. |
required |
| lateral_um | array_like | Cluster coordinates on the probe, one entry per entry of cluster_ids, in micrometres (the lateral_um / axial_um columns of :class:ModelClusters). |
required |
| axial_um | array_like | Cluster coordinates on the probe, one entry per entry of cluster_ids, in micrometres (the lateral_um / axial_um columns of :class:ModelClusters). |
required |
| radius_um | float | Inclusion radius for a cluster’s local population, in micrometres. A cluster with no other cluster within radius_um gets an all-nan coupling row. |
required |
| lags | float or (float, float) | Symmetric half-window (single float) or explicit (lag_min, lag_max) window of lags, in seconds, over which the coupling is returned. Default 0.08, i.e. [-80, 80] ms, as in Bimbard et al. 2025 (“we computed coupling within a [-80, 80] ms window”). |
0.08 |
| binsize | float | Bin size (s) used to bin the spike trains before cross-correlating. Default 1 ms, as in Bimbard et al. 2025. | BINSIZE |
| lowpass_hz | float or None | Cutoff (Hz) of the zero-phase, 3rd-order Butterworth low-pass filter applied to each coupling curve (“low-passed filtered the coupling with a 20 Hz cutoff”). None disables filtering. Default 20.0. | 20.0 |
Returns
| Name | Type | Description |
|---|---|---|
| iblutil.util.Bunch | stpc : numpy.ndarray (n_clusters, n_lags) Population coupling, in %, one row per entry of cluster_ids. tscale : numpy.ndarray (n_lags,) Lag axis (s) matching axis 1 of stpc. coupling_strength : numpy.ndarray (n_clusters,) Coupling at zero lag, stpc[:, tscale == 0]. coupling_delay : numpy.ndarray (n_clusters,) Centre of mass of the (filtered) coupling curve, in seconds, per the literal Methods definition (no absolute value). For a cluster whose coupling is weak and noisy enough that the curve’s signed sum is close to zero, this ratio can be ill-conditioned and land outside the lags window; such rows are more reliably screened out by coupling_strength than trusted for their delay. firing_rate : numpy.ndarray (n_clusters,) Mean firing rate (Hz) of each cluster over [spike_times.min(), spike_times.max()]. n_neighbours : numpy.ndarray (n_clusters,) Number of other clusters within radius_um, i.e. :math:N_i - 1. |
Notes
Memory and compute scale with n_clusters ** 2 * n_bins (the local-population sum) and n_clusters * n_bins (the batched FFT cross-correlation), where n_bins = duration / binsize. For very long recordings, pre-restrict spike_times / spike_clusters to the epoch of interest (e.g. spontaneous-activity periods, as in Bimbard et al. 2025) before calling this function.