Correlograms & ISI#
Show code cell content
import pynapple as nap
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
custom_params = {"axes.spines.right": False, "axes.spines.top": False}
sns.set_theme(style="ticks", palette="colorblind", font_scale=1.5, rc=custom_params)
Let’s generate some data. Here we have two neurons recorded together. We can group them in a TsGroup.
ts1 = nap.Ts(t=np.sort(np.random.uniform(0, 1000, 2000)), time_units="s")
ts2 = nap.Ts(t=np.sort(np.random.uniform(0, 1000, 1000)), time_units="s")
epoch = nap.IntervalSet(start=0, end=1000, time_units="s")
ts_group = nap.TsGroup({0: ts1, 1: ts2}, time_support=epoch)
print(ts_group)
Index rate
------- ------
0 2
1 1
Autocorrelograms#
We can compute their autocorrelograms meaning the number of spikes of a neuron observed in a time windows centered around its own spikes.
For this we can use the function compute_autocorrelogram
.
We need to specifiy the binsize
and windowsize
to bin the spike train.
autocorrs = nap.compute_autocorrelogram(
group=ts_group, binsize=100, windowsize=1000, time_units="ms", ep=epoch # ms
)
print(autocorrs)
0 1
-0.9 0.9700 1.15
-0.8 0.9775 1.01
-0.7 1.0275 0.99
-0.6 0.9875 0.98
-0.5 0.9200 1.06
-0.4 0.9975 1.03
-0.3 1.0150 0.95
-0.2 0.9975 0.97
-0.1 0.9500 0.94
0.0 0.0000 0.00
0.1 0.9500 0.94
0.2 0.9975 0.97
0.3 1.0150 0.95
0.4 0.9975 1.03
0.5 0.9200 1.06
0.6 0.9875 0.98
0.7 1.0275 0.99
0.8 0.9775 1.01
0.9 0.9700 1.15
The variable autocorrs
is a pandas DataFrame with the center of the bins
for the index and each column is an autocorrelogram of one unit in the TsGroup
.
Cross-correlograms#
Cross-correlograms are computed between pairs of neurons.
crosscorrs = nap.compute_crosscorrelogram(
group=ts_group, binsize=100, windowsize=1000, time_units="ms" # ms
)
print(crosscorrs)
0
1
-0.9 1.075
-0.8 1.065
-0.7 1.075
-0.6 0.990
-0.5 0.895
-0.4 1.000
-0.3 1.025
-0.2 0.800
-0.1 1.100
0.0 0.970
0.1 1.010
0.2 0.985
0.3 0.900
0.4 0.950
0.5 0.945
0.6 0.950
0.7 0.840
0.8 0.920
0.9 1.000
Column name (0, 1)
is read as cross-correlogram of neuron 0 and 1 with neuron 0 being the reference time.
Event-correlograms#
Event-correlograms count the number of event in the TsGroup
based on an event
timestamps object.
eventcorrs = nap.compute_eventcorrelogram(
group=ts_group, event = nap.Ts(t=[0, 10, 20]), binsize=0.1, windowsize=1
)
print(eventcorrs)
0 1
-0.9 0.000000 4.444444
-0.8 0.000000 0.000000
-0.7 0.000000 0.000000
-0.6 0.000000 0.000000
-0.5 0.000000 0.000000
-0.4 3.703704 0.000000
-0.3 3.703704 4.444444
-0.2 0.000000 0.000000
-0.1 0.000000 4.444444
0.0 0.000000 0.000000
0.1 1.851852 0.000000
0.2 0.000000 0.000000
0.3 1.851852 4.444444
0.4 0.000000 0.000000
0.5 0.000000 0.000000
0.6 0.000000 0.000000
0.7 0.000000 0.000000
0.8 1.851852 0.000000
0.9 0.000000 0.000000
Interspike interval (ISI) distribution#
The interspike interval distribution shows how the time differences between subsequent spikes (events) are distributed.
The input can be any object with timestamps. Passing epochs
restricts the computation to the given epochs.
The output will be a dataframe with the bin centres as index and containing the corresponding ISI counts per unit.
isi_distribution = nap.compute_isi_distribution(
data=ts_group, bins=10, epochs=epoch
)
print(isi_distribution)
0 1
0.352083 1519 502
1.055320 364 248
1.758556 86 130
2.461792 26 57
3.165029 4 32
3.868265 0 19
4.571501 0 7
5.274737 0 2
5.977974 0 1
6.681210 0 1
Show code cell source
for col in isi_distribution.columns:
plt.bar(
isi_distribution.index,
isi_distribution[col].values,
width=np.diff(isi_distribution.index).mean(),
alpha=0.5,
label=col,
align='center',
edgecolor='none'
)
plt.xlabel("ISI (s)")
plt.ylabel("Count")
plt.legend(title="Unit")
plt.show()

The bins
argument allows for choosing either the number of bins as an integer or the bin edges as an array directly:
isi_distribution = nap.compute_isi_distribution(
data=ts_group, bins=np.linspace(0, 3, 10), epochs=epoch
)
print(isi_distribution)
0 1
0.166667 963 275
0.500000 502 211
0.833333 261 141
1.166667 135 106
1.500000 77 74
1.833333 26 49
2.166667 20 45
2.500000 9 30
2.833333 3 17
Show code cell source
for col in isi_distribution.columns:
plt.bar(
isi_distribution.index,
isi_distribution[col].values,
width=np.diff(isi_distribution.index).mean(),
alpha=0.5,
label=col,
align='center',
edgecolor='none'
)
plt.xlabel("log ISI (s)")
plt.ylabel("Count")
plt.legend(title="Unit")
plt.show()

The log_scale
argument allows for applying the log-transform to the ISIs:
isi_distribution = nap.compute_isi_distribution(
data=ts_group, bins=10, log_scale=True, epochs=epoch
)
print(isi_distribution)
0 1
-7.191594 3 1
-6.229259 4 3
-5.266924 23 1
-4.304589 50 11
-3.342254 122 33
-2.379919 287 77
-1.417584 610 199
-0.455249 634 310
0.507086 260 296
1.469421 6 68
Show code cell source
for col in isi_distribution.columns:
plt.bar(
isi_distribution.index,
isi_distribution[col].values,
width=np.diff(isi_distribution.index).mean(),
alpha=0.5,
label=col,
align='center',
edgecolor='none'
)
plt.xlabel("log ISI (s)")
plt.ylabel("Count")
plt.legend(title="Unit")
plt.show()
