Elephant, neo, quantities, and Spike to Field Coherence
Authors
Setup
Import Libraries
import numpy as np
import quantities as pq
from tqdm import tqdm
import neo
from elephant.sta import spike_field_coherence
from pathlib import Path
import xarray as xrUtility Functions
Run the cell below, but feel free to ignore this code — it’s some utility functions we’ll use later for convenience.
def calc_wavelet_spectrum(sig, sampling_frequency, wavelet = "cmor1.5-1.0", widths = np.logspace(start=3, stop=10, num=50, base=2)):
'''
Calculates the time-resolved power spectrum of a signal using morlet wavelets
Args:
sig: signal that the wavelet spectrum is calculated for
sampling_frequency: sampling frequency of signal
wavelet: the type of wavelet (bandwidth and ...) to apply in transform
widths: scales (inverse of frequencies) that the spectrum are calculated for
Returns:
freqs: frequencies for which the the spectral values are calculated
spectrum: complex time-resolved spectrum containing both amplitude and phase over time
'''
sampling_period = 1/sampling_frequency
spectrum, freqs = pywt.cwt(sig, widths, wavelet, sampling_period=sampling_period)
return freqs, spectrum
def convert_spikes_to_timestamps(spike_counts):
'''
Takes array containing spike counts of units across trials and time and converts the data
to timestamps of time points of spikes for each unit and trial
Args:
spike_counts: array with spike count data
returns:
timestamps_all_units: dictionary with timestamps organized by units, trials, time
'''
timestamps_all_units = dict()
for iunit in range(spike_counts.shape[0]):
timestamps_trials = dict()
for itrial in range(spike_counts.shape[1]):
timestamps= np.where(spike_counts[iunit,itrial].values)[0]
timestamps_trials[itrial] = timestamps
timestamps_all_units[iunit] = timestamps_trials
return timestamps_all_units
def create_neo_lfp(lfp, sampling_frequency):
"""Put lfp data in time window in neo format"""
return neo.AnalogSignal(
lfp.values.T, # The lfp must be transposed to have time on the first dimension for neo
units=pq.V,
sampling_rate=sampling_frequency*pq.Hz
)
def get_coherence_all_trials(lfp, timestamps, sampling_frequency_lfp):
"""Loops through all neurons in an area and all trials and calculates the spike field coherence """
sfc_all_cells = []
for icell in tqdm(timestamps.keys()):
sfc_all_trials = []
for itrial in range(lfp.shape[1]):
lfp_neo = neo.AnalogSignal(lfp[:,itrial].values.T, units=pq.V, sampling_rate=sampling_frequency_lfp*pq.Hz)
spiketrain_neo = neo.core.SpikeTrain(timestamps[icell][itrial], units=pq.ms, t_stop = 1.5*pq.s)
# calculate spike field coherence
sf_coherence, freqs = spike_field_coherence(lfp_neo, spiketrain_neo)
sfc_all_trials.append(sf_coherence.T)
sfc_all_cells.append(np.array(sfc_all_trials))
return np.array(sfc_all_cells)
class utils:
calc_wavelet_spectrum = calc_wavelet_spectrum
convert_spikes_to_timestamps = convert_spikes_to_timestamps
create_neo_lfp = create_neo_lfp
get_coherence_all_trials = get_coherence_all_trialsDownload Dataset
import owncloud
owncloud.Client.from_public_link('https://uni-bonn.sciebo.de/s/M56DCkpyCJ9FRoi', folder_password="ibots"
).get_file('/', 'dataset_session_754312389.nc')TrueIntroduction
In this notebook, you will learn how to use the libraries elephant, neo, and quantities when working with electrophysiological data as well as how to calculate the spike-field coherence between recorded spikes and LFP.
import quantities as pq
import neo
import numpy as np
import matplotlib.pyplot as pltSection 1: Quantities. Adding units to variables
Checking the units of your final answer in a calculation is a good way to make sure that your calculation is correct. If your answer has the wrong units, then there’s definitely something wrong with the calculation. In Python, we typically don’t have units attached to variables, so we have to keep track of them through a calculation ourselves. However, there are libraries that allow you to attach units to variables, so that it can tracked automatically. One of those libraries is quantities, which we’ll be working with in this section.
| Code | Description |
|---|---|
pq.A |
Creates the quantities unit Ampere |
pq.V |
Creates the quantities unit Volt |
pq.Hz |
Creates the quantities unit Hertz |
pq.s |
Creates the quantities unit seconds |
pq.ms |
Creates the quantities unit milliseconds |
pq. |
If you only write “pq.”, you will see a list of all the functions and attributes belonging to pq. The attributes will be the different units you can create. Scrolling through the list is one way to find the unit you need. |
x = 10*pq.Hz |
Creates the variable x containing the value 10 with the unit Hz (Hertz) attached. |
x = np.array([1,2,3] * pq.ms) |
Create a variable x containing three values with units milliseconds. |
x.units |
Get the units of the variable x. |
x.magnitude |
Get the magnitude (value) of the variable x without the unit. |
x * y or x / y |
Multiplication or division between two variables with units will also multiply or divide the units of those variables. |
Exercises
Example: Create a variable named current that has the value 5 and unit Ampere (A). Display the current variable.
The output should be array(5.) * A, which says that it’s an array containing the value 5 multiplied with the unit A (for Ampere).
current = 5*pq.A
currentarray(5.) * AExercise: Create a variable named potential which contains the value 10 and has the unit Volt. Display the potential variable.
Solution
potential = 10 * pq.V
potentialarray(10.) * VExercise: Create and display a variable named time_points which contains the three values [10,20,30] and has the unit seconds.
Solution
time_points = [10,20,30] * pq.s
time_pointsarray([10., 20., 30.]) * sExercise: Get the units of the potential variable. The output should be array(1.) * V.
Solution
potential.unitsarray(1.) * VExercise: Get the units of the time variable. The output should be array(1.) * s.
Solution
time_points.unitsarray(1.) * sExercise: Get the values (the magnitude) of the time_points variable (that is, the values of the array without the unit). The output should be array([10., 20., 30.]).
Solution
time_points.magnitudearray([10., 20., 30.])Exercise: Multiply distance a with distance b. What’s the resulting unit?
a = 10*pq.m
b = 2*pq.mSolution
a*barray(20.) * m**2Exercise: Divide distance a with distance b. What unit does the result have?
a = 10*pq.m
b = 2*pq.mSolution
a/barray(5.) * dimensionlessAnswer: The result is dimensionless, meaning that it has no unit.
Section 2: Neo: Representing Electrophysiology Data in Python
With Neo, you can store data, metadata, as well as the relationships between different parts of the data together in one Neo object.
Representing time series data
AnalogSignal: Continuous data sampled in regular intervalsIrregularlySampledSignal: Continuous data sampled in irregular intervals
| Code | Description |
|---|---|
anasig = neo.AnalogSignal(signal, units = pq.V, sampling_rate, t_start) |
Creates an analog signal neo object containing continuous signal data sampled at regular intervals. Required metadata: physical unit of samples, timestamps of the samples (first timestamp and sampling interval) |
anasig.annotate(quality='excellent', date='2030-05-27) |
Add annotations (additional, optional metadata) to the neo AnalogSignal object. |
spiketrain = neo.SpikeTrain(timestamps, units='ms',t_stop=300*pq.ms) |
Make a neo SpikeTrain object containing the timestamps at which a cell spiked. t_stop specifies the end of the time window (the highest possible timestamp value) in units of milliseconds (pq.ms). |
neo_object.magnitude |
Get the values (the magnitude of the signal, for example) of the neo object without the unit. |
neo_object.units |
Get the units of neo object. |
np.random.random(size=(nrows,ncols)) |
Creates an array containing random values between 0 and 1 with nrows number of rows and ncols number of columns. |
Exercises
Example: Create an AnalogSignal object out of the recorded_potential variable representing a fictional LFP trace from a single channel. The signal object should have units V (Volt), a sampling rate of 1000 Hz, and start at 0 ms.
recorded_potential = [0,1,2,3,4,5,5,4,3,2,1,0]lfp_trace = neo.AnalogSignal(recorded_potential,
units='V',
sampling_rate=1000.*pq.Hz,
t_start=0*pq.ms)
lfp_traceAnalogSignal with 1 channels of length 12; units V; datatype int64
sampling rate: 1000.0 Hz
time: 0.0 ms to 12.0 msExercise: Create an AnalogSignal object of the recorded_potential variable containing fictional LFP traces from 2 recording channels with 50 samples over time. The signal should have units uV (microvolt), a sampling rate of 10000 Hz, and start at 0 ms.
Solution
recorded_potential = np.random.random((50,2))
lfp_trace = neo.AnalogSignal(recorded_potential,
units='uV',
sampling_rate=10000*pq.Hz,
t_start=0*pq.ms)
lfp_traceAnalogSignal with 2 channels of length 50; units uV; datatype float64
sampling rate: 10000.0 Hz
time: 0.0 ms to 5.0 msExercise: Annotate your AnalogSignal from either the previous exercise or the example with the recording date (for example, today’s date). Display the variable containing the AnalogSignal to check that the annotations are included.
Solution
# solution
lfp_trace.annotate(date='2024-03-11')
lfp_traceAnalogSignal with 2 channels of length 50; units uV; datatype float64
annotations: {'date': '2024-03-11'}
sampling rate: 10000.0 Hz
time: 0.0 ms to 5.0 msYou can also use neo to store spike train data together with metadata in the same object.
Exercise: Create a SpikeTrain object containing the timestamps (the time points at which the neuron fired) [50, 100, 200] of neuron. Give it units ms and have the period start at 0 and stop 300 ms. Display the spike train.
Solution
timestamps = [50, 100, 200]
spike_train = neo.SpikeTrain(timestamps,
units='ms',
t_start=0,
t_stop=300)
spike_trainSpikeTrain containing 3 spikes; units ms; datatype float64
time: 0.0 ms to 300.0 msYou can always show the timestamps by typing .magnitude behind the spike train object, like in the cell below (simply run it, you don’t need to add to the code).
spike_train.magnitudearray([ 50., 100., 200.])Exercise: Create a SpikeTrain object out of the variable timestamps containing the time points at which a neuron fired. Give it units ms and have the period start at 100 and stop 300 ms. Display the spike train. How many spikes does it say that there are?
timestamps = [120,140,160,180,200,220,240]Solution
spike_train = neo.SpikeTrain(timestamps,
units='ms',
t_start=100*pq.ms,
t_stop=250*pq.ms)
spike_trainSpikeTrain containing 7 spikes; units ms; datatype float64
time: 100.0 ms to 250.0 msExercise: Get the magnitude of the neo SpikeTrain object.
Solution
spike_train.magnitudearray([120., 140., 160., 180., 200., 220., 240.])Section 3: Spike-field coherence between LGN spikes and V1 LFP
Coherence is a measure of the linear association between two signals. The spike-field coherence is the association between the spike train of a single neuron and the LFP trace in a single channel and can be used to quantify the relationship between spikes and LFP.
| Code | Description |
|---|---|
lfp_neo = utils.create_neo_lfp(lfp_V1[:,itrial], sampling_frequency_lfp) |
Utility function to create an analog signal neo object containing the LFP from a single trial itrial. |
spiketrain = neo.core.SpikeTrain(timestamps, t_stop = 1.5*pq.s) |
Make a neo SpikeTrain object containing the timestamps at which a cell spiked. t_stop specifies the end of the time window (the highest possible timestamp value) in units of seconds (pq.s). |
sf_coherence, freqs = spike_field_coherence(lfp_neo, spiketrain=st) |
Calculate the spike-field coherence (sfc) between a spike train and an LFP trace. |
plt.pcolormesh(x, y, C, cmap = 'plasma', shading = 'gouraud') |
Make a 2D colormap of values in a 2D array (C) against x and y values. The optional parameters cmap and shading defines, respectively, the colormap and the smoothing applied to the plot. |
plt.plot(x, y) |
Plots the data in y against the corresponding values in x. |
plt.xlim([some_lower_xlim, some_upper_xlim]) |
Limit the x-axis in a plot to be between the numbers some_lower_xlim and some_upper_xlim. |
transposed_data = data.T |
Transposes the dimensions of the data. An array of dimensions N x M will be transposed to M x N. |
np.nanmean(data, axis = (dim_num)) |
Calculate the average of the data across the dim_num dimension of the array while ignoring all NaN-values. |
Load dataset
Run cells below to load dataset and extract LFP and spike data.
Exercises
loadpath = 'dataset_session_754312389.nc'
dataset_path = Path(loadpath)
dataset = xr.load_dataset(dataset_path)
dataset<xarray.Dataset> Size: 225MB
Dimensions: (channel_depth: 23, trial_nr: 75, time_lfp: 1875,
time_csd: 1875, time_whole_rec_lfp: 373124,
time_whole_rec_ecp: 373124, unit_id_LGN: 27,
time_spikes: 1500, unit_id_V1: 91, unit_id_LM: 13,
stimulus_start_times: 75, stimulus_stop_times: 75,
channel_id: 23)
Coordinates: (12/13)
* channel_depth (channel_depth) int64 184B 0 -40 -80 ... -840 -880
* trial_nr (trial_nr) int32 300B 0 1 2 3 4 5 ... 70 71 72 73 74
* time_lfp (time_lfp) float64 15kB -1e+03 -999.2 ... 499.2
* time_csd (time_csd) float64 15kB -1e+03 -999.2 ... 499.2
* time_whole_rec_lfp (time_whole_rec_lfp) float64 3MB 1.286e+06 ... 1....
* time_whole_rec_ecp (time_whole_rec_ecp) float64 3MB 1.286e+06 ... 1....
... ...
* time_spikes (time_spikes) float64 12kB -999.5 -998.5 ... 499.5
* unit_id_V1 (unit_id_V1) int32 364B 951795075 ... 951798053
* unit_id_LM (unit_id_LM) int32 52B 951791074 ... 951792163
* stimulus_start_times (stimulus_start_times) float64 600B 1.29e+06 ... ...
* stimulus_stop_times (stimulus_stop_times) float64 600B 1.29e+06 ... 1...
* channel_id (channel_id) int32 92B 850144538 ... 850144362
Data variables:
lfp_V1 (channel_depth, trial_nr, time_lfp) float64 26MB ...
csd_V1 (channel_depth, trial_nr, time_csd) float64 26MB ...
lfp_whole_recording_V1 (channel_depth, time_whole_rec_lfp) float64 69MB ...
ecp_whole_recording_V1 (channel_depth, time_whole_rec_ecp) float64 69MB ...
spike_counts_LGN (unit_id_LGN, trial_nr, time_spikes) int16 6MB 0 ...
spike_counts_V1 (unit_id_V1, trial_nr, time_spikes) int16 20MB 0 ...
spike_counts_LM (unit_id_LM, trial_nr, time_spikes) int16 3MB 0 ....
pupil_width (trial_nr) float64 600B 39.12 40.53 ... 46.57 44.31
run_speed (trial_nr) float64 600B 1.155 1.597 ... 1.251 1.711
Attributes:
time_unit: millisecond
lfp_unit: Volt
channel_depth_unit: micrometer
note_channel_depth: Measured in distance from electrode closest t...
sampling_frequency_lfp: 1250
sampling_frequency_spikes: 1000
sampling_frequency_unit: Hz
stimulus_onset: 1000
stimulus_offset: 1250- channel_depth: 23
- trial_nr: 75
- time_lfp: 1875
- time_csd: 1875
- time_whole_rec_lfp: 373124
- time_whole_rec_ecp: 373124
- unit_id_LGN: 27
- time_spikes: 1500
- unit_id_V1: 91
- unit_id_LM: 13
- stimulus_start_times: 75
- stimulus_stop_times: 75
- channel_id: 23
- channel_depth(channel_depth)int640 -40 -80 -120 ... -800 -840 -880
array([ 0, -40, -80, -120, -160, -200, -240, -280, -320, -360, -400, -440, -480, -520, -560, -600, -640, -680, -720, -760, -800, -840, -880]) - trial_nr(trial_nr)int320 1 2 3 4 5 6 ... 69 70 71 72 73 74
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74], dtype=int32) - time_lfp(time_lfp)float64-1e+03 -999.2 ... 498.4 499.2
array([-1000. , -999.2, -998.4, ..., 497.6, 498.4, 499.2])
- time_csd(time_csd)float64-1e+03 -999.2 ... 498.4 499.2
array([-1000. , -999.2, -998.4, ..., 497.6, 498.4, 499.2])
- time_whole_rec_lfp(time_whole_rec_lfp)float641.286e+06 1.286e+06 ... 1.584e+06
array([1285609.738645, 1285610.538645, 1285611.338645, ..., 1584106.565384, 1584107.365384, 1584108.165384]) - time_whole_rec_ecp(time_whole_rec_ecp)float641.286e+06 1.286e+06 ... 1.584e+06
array([1285609.738645, 1285610.538645, 1285611.338645, ..., 1584106.565384, 1584107.365384, 1584108.165384]) - unit_id_LGN(unit_id_LGN)int32951782498 951782516 ... 951798528
array([951782498, 951782516, 951782530, 951782631, 951782683, 951782699, 951782744, 951782795, 951782832, 951782895, 951787033, 951792341, 951792375, 951792398, 951792418, 951792441, 951792504, 951792544, 951797077, 951798318, 951798391, 951798404, 951798553, 951798681, 951801317, 951798434, 951798528], dtype=int32) - time_spikes(time_spikes)float64-999.5 -998.5 ... 498.5 499.5
array([-999.5, -998.5, -997.5, ..., 497.5, 498.5, 499.5])
- unit_id_V1(unit_id_V1)int32951795075 951795086 ... 951798053
array([951795075, 951795086, 951795098, 951795140, 951795163, 951795222, 951795238, 951795256, 951795269, 951795290, 951795309, 951795317, 951795403, 951797419, 951795458, 951795474, 951795487, 951795495, 951795554, 951795680, 951795563, 951795611, 951795663, 951795688, 951795706, 951795713, 951795721, 951797465, 951795729, 951795737, 951795747, 951795873, 951795753, 951795782, 951795792, 951795760, 951795768, 951795775, 951795807, 951795824, 951795832, 951795839, 951795858, 951795880, 951795886, 951795896, 951795918, 951797520, 951797539, 951797553, 951795936, 951795943, 951795967, 951795976, 951797567, 951797489, 951796016, 951796073, 951796125, 951796165, 951796176, 951796229, 951797633, 951796333, 951797647, 951797664, 951796352, 951796494, 951797718, 951796542, 951796556, 951797730, 951796585, 951797742, 951796629, 951796639, 951796660, 951796696, 951796791, 951797776, 951796866, 951796906, 951796928, 951796949, 951797595, 951797613, 951797709, 951797764, 951797811, 951797995, 951798053], dtype=int32) - unit_id_LM(unit_id_LM)int32951791074 951791093 ... 951792163
array([951791074, 951791093, 951791202, 951791214, 951791273, 951791305, 951791297, 951791401, 951791422, 951791467, 951791442, 951791453, 951792163], dtype=int32) - stimulus_start_times(stimulus_start_times)float641.29e+06 1.294e+06 ... 1.584e+06
array([1289613.25125, 1293616.60125, 1299621.62125, 1301623.29125, 1303624.97125, 1307628.33125, 1309629.95125, 1319638.32125, 1329646.71125, 1333650.07125, 1337653.40125, 1341656.74125, 1351665.05125, 1357670.12125, 1361673.43125, 1371681.84125, 1373683.47125, 1375685.17125, 1383691.83125, 1387695.15125, 1397703.53125, 1401706.88125, 1403708.58125, 1407711.93125, 1411715.25125, 1413716.94125, 1415718.63125, 1417720.26125, 1419721.95125, 1421723.62125, 1423725.25125, 1427728.62125, 1429730.28125, 1431731.94125, 1433733.62125, 1435735.32125, 1441740.33125, 1447745.31125, 1451748.67125, 1459755.38125, 1461757.06125, 1467762.05125, 1473767.09125, 1481773.75125, 1485777.10125, 1489780.46125, 1491782.12125, 1493783.81125, 1497787.16125, 1501790.48125, 1503792.14125, 1505793.80125, 1511798.87125, 1515802.17125, 1517803.89125, 1519805.55125, 1521807.23125, 1529813.91125, 1531815.57125, 1533817.23125, 1537820.57125, 1541823.93125, 1543825.60125, 1545827.30125, 1547828.93125, 1551832.29125, 1553833.96125, 1563842.35125, 1565843.99125, 1569847.35125, 1571849.02125, 1573850.69125, 1575852.34125, 1577854.07125, 1583859.05125]) - stimulus_stop_times(stimulus_stop_times)float641.29e+06 1.294e+06 ... 1.584e+06
array([1289863.450591, 1293866.800591, 1299871.820591, 1301873.490591, 1303875.173091, 1307878.525591, 1309880.158091, 1319888.525591, 1329896.908091, 1333900.265591, 1337903.598091, 1341906.940591, 1351915.258091, 1357920.320591, 1361923.638091, 1371932.033091, 1373933.675591, 1375935.370591, 1383942.035591, 1387945.363091, 1397953.738091, 1401957.083091, 1403958.778091, 1407962.128091, 1411965.450591, 1413967.138091, 1415968.823091, 1417970.465591, 1419972.150591, 1421973.823091, 1423975.460591, 1427978.823091, 1429980.490591, 1431982.153091, 1433983.830591, 1435985.523091, 1441990.535591, 1447995.523091, 1451998.875591, 1460005.585591, 1462007.260591, 1468012.260591, 1474017.293091, 1482023.960591, 1486027.308091, 1490030.665591, 1492032.325591, 1494034.013091, 1498037.360591, 1502040.685591, 1504042.350591, 1506044.010591, 1512049.070591, 1516052.383091, 1518054.088091, 1520055.753091, 1522057.428091, 1530064.110591, 1532065.775591, 1534067.438091, 1538070.778091, 1542074.135591, 1544075.808091, 1546077.498091, 1548079.138091, 1552082.495591, 1554084.165591, 1564092.550591, 1566094.193091, 1570097.553091, 1572099.225591, 1574100.895591, 1576102.553091, 1578104.268091, 1584109.255591]) - channel_id(channel_id)int32850144538 850144530 ... 850144362
array([850144538, 850144530, 850144522, 850144514, 850144506, 850144498, 850144490, 850144482, 850144474, 850144466, 850144458, 850144450, 850144442, 850144434, 850144426, 850144418, 850144410, 850144402, 850144394, 850144386, 850144378, 850144370, 850144362], dtype=int32)
- lfp_V1(channel_depth, trial_nr, time_lfp)float64-8.516e-06 -1.156e-05 ... 6.131e-06
array([[[-8.51569421e-06, -1.15631923e-05, -3.76924291e-07, ..., -2.17654367e-06, 1.68119712e-07, -6.94200500e-06], [ 2.81771330e-08, 6.29403676e-06, 9.98029865e-06, ..., 1.01304291e-05, 5.93295341e-06, 1.72969475e-05], [-1.27271427e-06, -3.68783112e-06, -4.46340366e-06, ..., 3.65666426e-06, 2.96670978e-06, 1.24568597e-06], ..., [ 4.70565253e-06, 1.94317598e-06, 1.20455675e-06, ..., 4.07503496e-06, 7.65054254e-06, 3.91673831e-06], [ 8.38144661e-07, 2.28123812e-06, 3.70896321e-06, ..., 1.34013793e-05, 1.15462596e-05, 8.42411093e-06], [ 7.32479652e-06, 1.07711181e-06, 7.00885884e-06, ..., 1.92065863e-05, 1.92065863e-05, 1.92065863e-05]], [[ 3.91952787e-06, 1.70056905e-06, 5.97275690e-06, ..., 4.06974274e-06, 4.04094749e-06, -4.68055730e-06], [-4.10311367e-06, 5.00856269e-06, 6.20500275e-06, ..., 8.75868311e-06, 5.69604080e-06, 8.57744575e-06], [ 1.09646506e-06, 1.62070262e-06, 1.10953040e-07, ..., 1.01990671e-05, -8.36754580e-06, -1.43387447e-05], ... [-6.46738552e-06, -1.19701456e-05, -2.41882630e-05, ..., -2.31175915e-05, -2.37374262e-05, -7.53926446e-06], [ 2.91850049e-05, 2.81713398e-05, 5.17618757e-05, ..., 4.44764295e-05, 4.08778688e-05, 3.83233192e-05], [-1.80642354e-05, -1.06068608e-05, -3.71177368e-06, ..., 1.48063260e-05, 1.48063260e-05, 1.48063260e-05]], [[ 4.42062699e-05, 5.99208645e-05, 7.60618853e-05, ..., 9.85508013e-05, 8.87923195e-05, 8.02998878e-05], [-6.30930699e-06, 2.14882295e-05, 5.40961203e-06, ..., -6.18517313e-05, -8.49961217e-05, -7.07025406e-05], [ 1.32347041e-04, 9.66830285e-05, 9.77152893e-05, ..., -3.68393584e-05, -2.08663734e-05, -1.27901811e-05], ..., [ 7.59530363e-07, -9.00525049e-06, -1.95382678e-05, ..., -2.78150664e-05, -1.46349189e-05, 3.65395950e-06], [ 3.22381374e-05, 3.90163375e-05, 6.39709157e-05, ..., 5.17422904e-05, 4.94353600e-05, 3.90770304e-05], [-2.50190016e-05, -1.82145705e-05, -1.97245214e-05, ..., 6.13148062e-06, 6.13148062e-06, 6.13148062e-06]]]) - csd_V1(channel_depth, trial_nr, time_csd)float64-0.04729 -0.04843 ... 0.004271
array([[[-0.04729251, -0.04843248, -0.03745331, ..., -0.0506883 , -0.05553956, -0.06003479], [-0.01093619, 0.01574628, 0.00914164, ..., 0.00598613, 0.01101591, 0.03123014], [-0.03696462, -0.04099173, -0.03852095, ..., 0.00098069, -0.0050393 , -0.01264635], ..., [-0.01247878, 0.00877942, 0.02265446, ..., 0.00331111, 0.03482657, 0.01182155], [-0.00745365, -0.01184343, -0.0143719 , ..., -0.00701411, -0.00677321, 0.00801698], [-0.00185681, 0.00029347, 0.01247577, ..., 0.04692436, 0.04692436, 0.04692436]], [[-0.05243487, -0.04187987, -0.01951768, ..., 0.00767212, 0.02122529, -0.00091668], [-0.03800667, -0.0267893 , 0.00151346, ..., -0.06356118, -0.05255179, -0.02253284], [-0.13918267, -0.15069373, -0.14869443, ..., -0.08287076, -0.10533221, -0.11878146], ... [-0.0317182 , -0.0291328 , -0.04440809, ..., 0.0128667 , -0.00803555, 0.00140582], [-0.00313798, -0.02211998, 0.00973861, ..., 0.01834821, 0.02898202, 0.03053275], [ 0.01935376, 0.02458448, 0.02770717, ..., 0.0335107 , 0.0335107 , 0.0335107 ]], [[ 0.05527245, 0.06647928, 0.08365367, ..., 0.03946655, -0.00638597, 0.01617121], [ 0.00484864, 0.04955322, 0.00056809, ..., -0.02495747, -0.04720462, -0.05647099], [ 0.14248465, 0.09267001, 0.12532577, ..., -0.02102215, 0.01070787, -0.00105385], ..., [ 0.02074605, 0.01291679, -0.00810403, ..., -0.00440359, 0.01890968, 0.03686672], [-0.03145411, -0.01193072, 0.05258549, ..., 0.06270049, 0.05033156, 0.03718263], [-0.01626375, -0.00653823, -0.01209703, ..., 0.00427089, 0.00427089, 0.00427089]]]) - lfp_whole_recording_V1(channel_depth, time_whole_rec_lfp)float641.131e-05 2.316e-05 ... 6.131e-06
array([[ 1.13123117e-05, 2.31601759e-05, 2.56464473e-05, ..., 2.90957718e-05, 2.80686400e-05, 1.92065863e-05], [ 1.25864221e-05, 2.61936713e-05, 2.05721887e-05, ..., 2.51329249e-05, 1.10562717e-05, 1.14064589e-05], [ 1.06294434e-05, 1.20898434e-05, 1.05466595e-05, ..., 4.39547441e-06, 2.49921901e-06, -3.03491628e-06], ..., [-1.51105564e-05, -2.86651554e-05, -2.43583384e-05, ..., 1.55104740e-05, 1.08842192e-05, 7.88508374e-06], [-2.60411104e-05, -3.63399664e-05, -2.41173628e-05, ..., 4.57287775e-05, 2.16324211e-05, 1.48063260e-05], [-1.92918607e-05, -3.23216874e-05, -2.71540780e-05, ..., 5.95832945e-05, 2.76861759e-05, 6.13148062e-06]]) - ecp_whole_recording_V1(channel_depth, time_whole_rec_ecp)float641.131e-05 2.316e-05 ... 6.131e-06
array([[ 1.13123117e-05, 2.31601759e-05, 2.56464473e-05, ..., 2.90957718e-05, 2.80686400e-05, 1.92065863e-05], [ 1.25864221e-05, 2.61936713e-05, 2.05721887e-05, ..., 2.51329249e-05, 1.10562717e-05, 1.14064589e-05], [ 1.06294434e-05, 1.20898434e-05, 1.05466595e-05, ..., 4.39547441e-06, 2.49921901e-06, -3.03491628e-06], ..., [-1.51105564e-05, -2.86651554e-05, -2.43583384e-05, ..., 1.55104740e-05, 1.08842192e-05, 7.88508374e-06], [-2.60411104e-05, -3.63399664e-05, -2.41173628e-05, ..., 4.57287775e-05, 2.16324211e-05, 1.48063260e-05], [-1.92918607e-05, -3.23216874e-05, -2.71540780e-05, ..., 5.95832945e-05, 2.76861759e-05, 6.13148062e-06]]) - spike_counts_LGN(unit_id_LGN, trial_nr, time_spikes)int160 0 0 0 0 0 0 0 ... 1 0 0 0 0 0 0 0
array([[[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., ... ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 1, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]]], dtype=int16) - spike_counts_V1(unit_id_V1, trial_nr, time_spikes)int160 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0
array([[[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 1, ..., 0, 0, 0], ..., ... ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]]], dtype=int16) - spike_counts_LM(unit_id_LM, trial_nr, time_spikes)int160 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0
array([[[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., ... ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 1], ..., [0, 0, 0, ..., 0, 1, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], [[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]]], dtype=int16) - pupil_width(trial_nr)float6439.12 40.53 53.87 ... 46.57 44.31
array([39.11652012, 40.53014519, 53.86896327, 50.82396045, 52.16879212, 57.96043078, 54.92497335, 55.54967205, 43.90274746, 44.79854897, 38.38702834, 40.71644189, 37.98256784, 35.66463223, 33.77803219, 37.33170246, 34.40298455, 33.56487003, 34.8366242 , 34.23566353, 37.82023369, 36.64031488, 34.90016986, 34.01127022, 34.01676223, 33.07691675, 36.24898149, 34.31897366, 32.37205121, 32.29131936, 31.22026173, 32.11667831, 35.9407955 , 33.83439488, 40.32179372, 40.2773362 , 36.8416765 , 38.28154173, 32.92621992, 34.10611125, 32.64213782, 35.34716687, 38.83240189, 41.4527341 , 40.80453453, 34.4518716 , 33.54378434, 34.76110284, 39.39896604, 38.12986388, 35.01399576, 36.1764032 , 36.91026669, 38.09285533, 37.47092614, 35.08431869, 34.10750204, 33.98908271, 33.49633874, 31.95082717, 36.40762283, 33.54301125, 30.16956358, 34.97767163, 35.73862834, 37.5021579 , 46.90415398, 64.55582159, 65.24024526, 62.84832274, 63.79648979, 64.1050437 , 54.12537803, 46.57182176, 44.30600894]) - run_speed(trial_nr)float641.155 1.597 6.057 ... 1.251 1.711
array([ 1.15461545, 1.59668837, 6.056658 , 5.15987544, 8.52760497, 11.22847943, 4.57915849, 3.55552612, 1.21703267, 1.14123532, 1.22313026, 1.45219009, 1.27881682, 1.28545771, 1.30252225, 1.45938978, 1.23683681, 1.35499306, 1.24373061, 1.72814998, 1.10057218, 1.12037113, 1.0171456 , 1.12698213, 1.23746278, 1.0051122 , 1.22995347, 1.18035543, 1.33973747, 1.31655126, 1.42316228, 1.16454631, 1.1175898 , 1.33965127, 1.44008401, 1.27856107, 1.08369774, 1.2852668 , 1.22042713, 0.93635542, 1.10224883, 1.3656531 , 1.14346642, 1.34443297, 1.27934364, 1.22477016, 0.89182778, 1.08752668, 1.29883034, 1.38104512, 0.96683534, 1.19810534, 0.99052094, 0.9343001 , 1.71404147, 1.51968473, 1.23845685, 0.84848258, 1.59605601, 1.25635954, 1.22987165, 1.64782276, 1.75731669, 1.67665638, 1.42473997, 1.02886151, 5.65275275, 8.34342969, 9.03230058, 10.64468513, 8.17371765, 1.18762197, 1.36400808, 1.25093511, 1.71061779])
- channel_depthPandasIndex
PandasIndex(Index([ 0, -40, -80, -120, -160, -200, -240, -280, -320, -360, -400, -440, -480, -520, -560, -600, -640, -680, -720, -760, -800, -840, -880], dtype='int64', name='channel_depth')) - trial_nrPandasIndex
PandasIndex(Index([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74], dtype='int32', name='trial_nr')) - time_lfpPandasIndex
PandasIndex(Index([ -1000.0, -999.1999999999999, -998.4, -997.5999999999999, -996.8, -995.9999999999999, -995.1999999999998, -994.3999999999999, -993.5999999999998, -992.7999999999998, ... 492.00000000004263, 492.80000000004276, 493.6000000000429, 494.4000000000428, 495.20000000004273, 496.00000000004286, 496.800000000043, 497.6000000000429, 498.40000000004284, 499.20000000004296], dtype='float64', name='time_lfp', length=1875)) - time_csdPandasIndex
PandasIndex(Index([ -1000.0, -999.1999999999999, -998.4, -997.5999999999999, -996.8, -995.9999999999999, -995.1999999999998, -994.3999999999999, -993.5999999999998, -992.7999999999998, ... 492.00000000004263, 492.80000000004276, 493.6000000000429, 494.4000000000428, 495.20000000004273, 496.00000000004286, 496.800000000043, 497.6000000000429, 498.40000000004284, 499.20000000004296], dtype='float64', name='time_csd', length=1875)) - time_whole_rec_lfpPandasIndex
PandasIndex(Index([1285609.7386445338, 1285610.5386446053, 1285611.338644677, 1285612.1386447486, 1285612.9386448204, 1285613.7386448921, 1285614.5386449639, 1285615.3386450356, 1285616.1386451072, 1285616.938645179, ... 1584100.9653832503, 1584101.7653833218, 1584102.5653833936, 1584103.365383465, 1584104.1653835368, 1584104.9653836086, 1584105.7653836801, 1584106.5653837519, 1584107.3653838234, 1584108.1653838952], dtype='float64', name='time_whole_rec_lfp', length=373124)) - time_whole_rec_ecpPandasIndex
PandasIndex(Index([1285609.7386445338, 1285610.5386446053, 1285611.338644677, 1285612.1386447486, 1285612.9386448204, 1285613.7386448921, 1285614.5386449639, 1285615.3386450356, 1285616.1386451072, 1285616.938645179, ... 1584100.9653832503, 1584101.7653833218, 1584102.5653833936, 1584103.365383465, 1584104.1653835368, 1584104.9653836086, 1584105.7653836801, 1584106.5653837519, 1584107.3653838234, 1584108.1653838952], dtype='float64', name='time_whole_rec_ecp', length=373124)) - unit_id_LGNPandasIndex
PandasIndex(Index([951782498, 951782516, 951782530, 951782631, 951782683, 951782699, 951782744, 951782795, 951782832, 951782895, 951787033, 951792341, 951792375, 951792398, 951792418, 951792441, 951792504, 951792544, 951797077, 951798318, 951798391, 951798404, 951798553, 951798681, 951801317, 951798434, 951798528], dtype='int32', name='unit_id_LGN')) - time_spikesPandasIndex
PandasIndex(Index([ -999.5, -998.5, -997.5, -996.4999999999999, -995.5, -994.4999999999999, -993.5, -992.4999999999999, -991.5, -990.4999999999999, ... 490.50000000000006, 491.50000000000006, 492.50000000000006, 493.50000000000006, 494.50000000000006, 495.50000000000006, 496.50000000000006, 497.50000000000006, 498.50000000000006, 499.50000000000006], dtype='float64', name='time_spikes', length=1500)) - unit_id_V1PandasIndex
PandasIndex(Index([951795075, 951795086, 951795098, 951795140, 951795163, 951795222, 951795238, 951795256, 951795269, 951795290, 951795309, 951795317, 951795403, 951797419, 951795458, 951795474, 951795487, 951795495, 951795554, 951795680, 951795563, 951795611, 951795663, 951795688, 951795706, 951795713, 951795721, 951797465, 951795729, 951795737, 951795747, 951795873, 951795753, 951795782, 951795792, 951795760, 951795768, 951795775, 951795807, 951795824, 951795832, 951795839, 951795858, 951795880, 951795886, 951795896, 951795918, 951797520, 951797539, 951797553, 951795936, 951795943, 951795967, 951795976, 951797567, 951797489, 951796016, 951796073, 951796125, 951796165, 951796176, 951796229, 951797633, 951796333, 951797647, 951797664, 951796352, 951796494, 951797718, 951796542, 951796556, 951797730, 951796585, 951797742, 951796629, 951796639, 951796660, 951796696, 951796791, 951797776, 951796866, 951796906, 951796928, 951796949, 951797595, 951797613, 951797709, 951797764, 951797811, 951797995, 951798053], dtype='int32', name='unit_id_V1')) - unit_id_LMPandasIndex
PandasIndex(Index([951791074, 951791093, 951791202, 951791214, 951791273, 951791305, 951791297, 951791401, 951791422, 951791467, 951791442, 951791453, 951792163], dtype='int32', name='unit_id_LM')) - stimulus_start_timesPandasIndex
PandasIndex(Index([1289613.2512503476, 1293616.6012503474, 1299621.6212503475, 1301623.2912503474, 1303624.9712503476, 1307628.3312503474, 1309629.9512503473, 1319638.3212503474, 1329646.7112503473, 1333650.0712503474, 1337653.4012503475, 1341656.7412503476, 1351665.0512503474, 1357670.1212503475, 1361673.4312503475, 1371681.8412503474, 1373683.4712503473, 1375685.1712503475, 1383691.8312503477, 1387695.1512503477, 1397703.5312503476, 1401706.8812503475, 1403708.5812503477, 1407711.9312503475, 1411715.2512503476, 1413716.9412503475, 1415718.6312503477, 1417720.2612503476, 1419721.9512503475, 1421723.6212503477, 1423725.2512503476, 1427728.6212503475, 1429730.2812503476, 1431731.9412503475, 1433733.6212503477, 1435735.3212503477, 1441740.3312503477, 1447745.3112503476, 1451748.6712503475, 1459755.3812503477, 1461757.0612503476, 1467762.0512503476, 1473767.0912503477, 1481773.7512503476, 1485777.1012503477, 1489780.4612503476, 1491782.1212503477, 1493783.8112503474, 1497787.1612503477, 1501790.4812503476, 1503792.1412503477, 1505793.8012503476, 1511798.8712503477, 1515802.1712503475, 1517803.8912503475, 1519805.5512503476, 1521807.2312503476, 1529813.9112503477, 1531815.5712503477, 1533817.2312503476, 1537820.5712503474, 1541823.9312503478, 1543825.6012503474, 1545827.3012503476, 1547828.9312503475, 1551832.2912503476, 1553833.9612503476, 1563842.3512503474, 1565843.9912503478, 1569847.3512503477, 1571849.0212503476, 1573850.6912503475, 1575852.3412503474, 1577854.0712503474, 1583859.0512503476], dtype='float64', name='stimulus_start_times')) - stimulus_stop_timesPandasIndex
PandasIndex(Index([1289863.4505906447, 1293866.8005906448, 1299871.8205906446, 1301873.490590645, 1303875.1730906446, 1307878.5255906447, 1309880.1580906447, 1319888.5255906447, 1329896.9080906447, 1333900.2655906447, 1337903.5980906447, 1341906.9405906445, 1351915.2580906446, 1357920.3205906448, 1361923.6380906447, 1371932.0330906445, 1373933.6755906448, 1375935.370590645, 1383942.0355906447, 1387945.3630906448, 1397953.738090645, 1401957.0830906448, 1403958.7780906446, 1407962.128090645, 1411965.450590645, 1413967.1380906447, 1415968.823090645, 1417970.4655906449, 1419972.1505906447, 1421973.8230906448, 1423975.4605906447, 1427978.823090645, 1429980.4905906448, 1431982.1530906449, 1433983.8305906449, 1435985.5230906447, 1441990.5355906447, 1447995.5230906447, 1451998.8755906448, 1460005.5855906447, 1462007.2605906448, 1468012.2605906453, 1474017.2930906452, 1482023.960590645, 1486027.3080906447, 1490030.6655906448, 1492032.3255906447, 1494034.0130906447, 1498037.3605906449, 1502040.6855906448, 1504042.350590645, 1506044.0105906448, 1512049.0705906448, 1516052.3830906448, 1518054.088090645, 1520055.753090645, 1522057.4280906445, 1530064.1105906446, 1532065.7755906447, 1534067.4380906445, 1538070.7780906446, 1542074.1355906448, 1544075.8080906447, 1546077.4980906448, 1548079.1380906447, 1552082.495590645, 1554084.165590645, 1564092.5505906448, 1566094.193090645, 1570097.5530906448, 1572099.2255906449, 1574100.8955906448, 1576102.5530906448, 1578104.2680906446, 1584109.255590645], dtype='float64', name='stimulus_stop_times')) - channel_idPandasIndex
PandasIndex(Index([850144538, 850144530, 850144522, 850144514, 850144506, 850144498, 850144490, 850144482, 850144474, 850144466, 850144458, 850144450, 850144442, 850144434, 850144426, 850144418, 850144410, 850144402, 850144394, 850144386, 850144378, 850144370, 850144362], dtype='int32', name='channel_id'))
- time_unit :
- millisecond
- lfp_unit :
- Volt
- channel_depth_unit :
- micrometer
- note_channel_depth :
- Measured in distance from electrode closest to scalp
- sampling_frequency_lfp :
- 1250
- sampling_frequency_spikes :
- 1000
- sampling_frequency_unit :
- Hz
- stimulus_onset :
- 1000
- stimulus_offset :
- 1250
# extract LFP data
lfp_V1 = dataset['lfp_V1']
channels_depth = dataset['channel_depth']
time_trial_lfp = lfp_V1.time_lfp
sampling_frequency_lfp = dataset.sampling_frequency_lfp# extract spike data
spike_counts_LGN = dataset['spike_counts_LGN']
spike_counts_V1 = dataset['spike_counts_V1']
spike_counts_LM = dataset['spike_counts_LM']# convert spike counts to timestamps
timestamps_LGN = convert_spikes_to_timestamps(spike_counts_LGN)
timestamps_V1 = convert_spikes_to_timestamps(spike_counts_V1)
timestamps_LM = convert_spikes_to_timestamps(spike_counts_LM)Example: Compute the spike field coherence between the LFP in trial 0 and the LGN spike train in trial 0 for cell 0. Plot the coherence using plt.pcolormesh.
itrial = 0
lfp_neo = utils.create_neo_lfp(lfp_V1[:,itrial], sampling_frequency_lfp)
icell = 0
timestamps = timestamps_LGN[icell][itrial]
spiketrain_neo = neo.core.SpikeTrain(timestamps, units=pq.ms, t_stop = 1500*pq.ms)
# calculate spike field coherence
sf_coherence, freqs = spike_field_coherence(lfp_neo, spiketrain_neo)plt.pcolormesh(freqs, channels_depth, sf_coherence.T, cmap = 'inferno', shading = 'gouraud')
plt.xlabel('Frequency (Hz)')
plt.ylabel(r'Depth ($\mu$m)');
plt.title(f'Spike field coherence in trial {itrial} between LGN cell nr. {icell} and V1 LFP')
plt.colorbar()Exercise: Compute the spike field coherence between the LFP and the LGN spike train in trial at index 5 for cell at index 2. Plot the coherence using plt.pcolormesh. You can use the utility function to create the LFP neo object (found both in the reference table and the example above.)
Note: In this case, the resulting plot will mainly contain noise, so don’t expect to see any structure that you can interpret from the plot.
Solution
itrial = 5
lfp_neo = utils.create_neo_lfp(lfp_V1[:,itrial], sampling_frequency_lfp)
icell = 2
timestamps = timestamps_LGN[icell][itrial]*pq.ms
spiketrain_neo = neo.core.SpikeTrain(timestamps, t_stop = 1500*pq.ms)
# calculate spike field coherence
sf_coherence, freqs = spike_field_coherence(lfp_neo, spiketrain_neo)plt.pcolormesh(freqs, channels_depth, sf_coherence.T, cmap = 'inferno', shading = 'gouraud')
plt.xlabel('Frequency (Hz)')
plt.ylabel(r'Depth ($\mu$m)');
plt.title(f'Spike field coherence in trial {itrial} between LGN cell nr. {icell} and V1 LFP')
plt.colorbar()For single trials and single cells it’s often not possible to identify any clear relationships in the spike-field coeherence. If you average over cells, over trials, or both, potential relationships should become more visible.
DEMO: Calculate the spike-field coherence between between LGN spike trains and V1 LFP in trial 0 for all cells. Loop through all cells, calculate the spike-field coherence, and store the result in a list.
Make a colormap plot of the average spike-field coherence across cells with pcolormesh. Are there any frequencies where the coherence seems to be notably higher?
# provided
itrial = 0
lfp_neo = utils.create_neo_lfp(lfp_V1[:,itrial], sampling_frequency_lfp)
sfc_all_cells_LGN = []
for icell in timestamps_LGN.keys():
spiketrain_neo = neo.core.SpikeTrain(timestamps_LGN[icell][itrial], units=pq.ms, t_stop = 1500*pq.ms)
# calculate spike field coherence
sfc, freqs = spike_field_coherence(lfp_neo, spiketrain_neo)
sfc_all_cells_LGN.append(sfc.T)
sfc_cell_avg = np.nanmean(sfc_all_cells_LGN, axis = 0)# solution
plt.pcolormesh(freqs, channels_depth, sfc_cell_avg, cmap = 'inferno', shading = 'gouraud')
plt.xlabel('Frequency (Hz)')
plt.ylabel(r'Depth ($\mu$m)');
plt.xlim([0, 200])
plt.colorbar()Exercise: Compute the average spike field coherence between LGN spikes and V1 LFP (the variable named sfc_all_cells_LGN) across both cells AND channels and plot the result in a 1D against the frequencies. Are the major peak(s) where you would expect if you compare to the 2D colormap plot of coherence across channels above?
Hint: You may have to use np.nanmean to calculate the average, in case there are NaNs in the calculated coherence for some cells.
Solution
sfc_avg = np.nanmean(sfc_all_cells_LGN, axis = (0,1))
plt.plot(freqs, sfc_avg)
plt.xlabel('Frequency (Hz)')
plt.xlim([0,200]);Example: Calculate the spike-field coherence between between LGN spike trains and V1 LFP for all trials AND for all cells. Compute the average across cells, channels, trials and plot the result against the frequencies.
At which frequencies are the two main peaks in the spike-field coherence between LGN spikes and V1 LFP?
sfc_all_trials_LGN = utils.get_coherence_all_trials(lfp_V1, timestamps_LGN, sampling_frequency_lfp)
sfc_trial_avg_chan_avg_LGN = np.nanmean(sfc_all_trials_LGN, axis = (0, 1, 2))
plt.plot(freqs, sfc_trial_avg_chan_avg_LGN)
plt.xlim([0,200])
plt.xlabel('Frequencies (Hz)')
plt.ylabel('Spectral coherence score (a. u.)')
plt.title('Trial avg. spike-field coherence between LGN spikes\nand V1 LFP. Averaged across all channels');Let’s check which peaks in the spike-field coherence between LGN spikes and V1 LFP can also be found in the spike-field coherence between spikes in LM or V1 and V1 LFP. If a peak in the spike-field coherence can be observed for all three areas - LGN, V1, and LM - then that’s an indication that it’s an oscillation that permeates the whole brain region. If a peak can only be observed for one area, that indicates a specific relationship between the spikes in that area (at a certain frequency) and the V1 LFP.
Exercise: Calculate the spike-field coherence between LM spike trains and V1 LFP for all trials AND for all cells. Compute the average across cells, channels, trials and plot the result against the frequencies.
Which of the peaks observed in the spike-field coherence between LGN spikes and V1 LFP can also be observed here?
Solution
sfc_all_trials_LM = utils.get_coherence_all_trials(lfp_V1, timestamps_LM, sampling_frequency_lfp)
sfc_trial_avg_chan_avg_LM = np.nanmean(sfc_all_trials_LM, axis = (0, 1, 2))
plt.plot(freqs, sfc_trial_avg_chan_avg_LM)
plt.xlim([0,200])
plt.xlabel('Frequencies (Hz)')
plt.ylabel('Spectral coherence score (a. u.)')
plt.title('Trial avg. spike-field coherence between LM spikes\nand V1 LFP. Averaged across all channels');
0%| | 0/13 [00:00<?, ?it/s]
8%|████████▏ | 1/13 [00:01<00:18, 1.51s/it]
15%|████████████████▍ | 2/13 [00:02<00:16, 1.49s/it]
23%|████████████████████████▋ | 3/13 [00:04<00:14, 1.46s/it]
31%|████████████████████████████████▉ | 4/13 [00:05<00:13, 1.47s/it]
38%|█████████████████████████████████████████▏ | 5/13 [00:07<00:11, 1.49s/it]
46%|█████████████████████████████████████████████████▍ | 6/13 [00:08<00:10, 1.49s/it]
54%|█████████████████████████████████████████████████████████▌ | 7/13 [00:10<00:08, 1.49s/it]
62%|█████████████████████████████████████████████████████████████████▊ | 8/13 [00:11<00:07, 1.50s/it]
69%|██████████████████████████████████████████████████████████████████████████ | 9/13 [00:13<00:05, 1.49s/it]
77%|█████████████████████████████████████████████████████████████████████████████████▌ | 10/13 [00:14<00:04, 1.50s/it]
85%|█████████████████████████████████████████████████████████████████████████████████████████▋ | 11/13 [00:16<00:03, 1.51s/it]
92%|█████████████████████████████████████████████████████████████████████████████████████████████████▊ | 12/13 [00:17<00:01, 1.52s/it]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:19<00:00, 1.52s/it]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████| 13/13 [00:19<00:00, 1.50s/it]Exercise: Calculate the spike-field coherence between between V1 spike trains and V1 LFP for all trials AND for all cells. Compute the average across cells, channels, trials and plot the result against the frequencies.
Which of the peaks observed in the spike-field coherence between LGN spikes and V1 LFP can also be observed here?
Solution
sfc_all_trials_V1 = utils.get_coherence_all_trials(lfp_V1, timestamps_V1, sampling_frequency_lfp)
sfc_trial_avg_chan_avg_V1 = np.nanmean(sfc_all_trials_V1, axis = (0, 1, 2))
plt.plot(freqs, sfc_trial_avg_chan_avg_V1)
plt.xlim([0,200])
plt.xlabel('Frequencies (Hz)')
plt.ylabel('Spectral coherence score (a. u.)')
plt.title('Trial avg. spike-field coherence between V1 spikes\nand V1 LFP. Averaged across all channels');
0%| | 0/91 [00:00<?, ?it/s]
1%|█▏ | 1/91 [00:01<02:14, 1.49s/it]
2%|██▎ | 2/91 [00:03<02:13, 1.50s/it]
3%|███▌ | 3/91 [00:04<02:12, 1.50s/it]
4%|████▋ | 4/91 [00:05<02:10, 1.50s/it]
5%|█████▉ | 5/91 [00:07<02:10, 1.52s/it]
7%|███████ | 6/91 [00:09<02:10, 1.53s/it]
8%|████████▏ | 7/91 [00:10<02:09, 1.54s/it]
9%|█████████▍ | 8/91 [00:12<02:07, 1.53s/it]
10%|██████████▌ | 9/91 [00:13<02:06, 1.54s/it]
11%|███████████▋ | 10/91 [00:15<02:05, 1.55s/it]
12%|████████████▊ | 11/91 [00:16<02:04, 1.56s/it]
13%|█████████████▉ | 12/91 [00:18<02:03, 1.56s/it]
14%|███████████████▏ | 13/91 [00:20<02:02, 1.57s/it]
15%|████████████████▎ | 14/91 [00:21<02:00, 1.57s/it]
16%|█████████████████▍ | 15/91 [00:23<01:59, 1.57s/it]
18%|██████████████████▋ | 16/91 [00:24<01:57, 1.57s/it]
19%|███████████████████▊ | 17/91 [00:26<01:54, 1.55s/it]
20%|████████████████████▉ | 18/91 [00:27<01:53, 1.55s/it]
21%|██████████████████████▏ | 19/91 [00:29<01:50, 1.54s/it]
22%|███████████████████████▎ | 20/91 [00:30<01:49, 1.54s/it]
23%|████████████████████████▍ | 21/91 [00:32<01:49, 1.56s/it]
24%|█████████████████████████▋ | 22/91 [00:34<01:47, 1.55s/it]
25%|██████████████████████████▊ | 23/91 [00:35<01:45, 1.55s/it]
26%|███████████████████████████▉ | 24/91 [00:37<01:42, 1.52s/it]
27%|█████████████████████████████ | 25/91 [00:38<01:40, 1.52s/it]
29%|██████████████████████████████▎ | 26/91 [00:40<01:39, 1.53s/it]
30%|███████████████████████████████▍ | 27/91 [00:41<01:36, 1.51s/it]
31%|████████████████████████████████▌ | 28/91 [00:42<01:33, 1.49s/it]
32%|█████████████████████████████████▊ | 29/91 [00:44<01:32, 1.49s/it]
33%|██████████████████████████████████▉ | 30/91 [00:45<01:30, 1.48s/it]
34%|████████████████████████████████████ | 31/91 [00:47<01:27, 1.47s/it]
35%|█████████████████████████████████████▎ | 32/91 [00:48<01:25, 1.46s/it]
36%|██████████████████████████████████████▍ | 33/91 [00:50<01:25, 1.47s/it]
37%|███████████████████████████████████████▌ | 34/91 [00:51<01:23, 1.47s/it]
38%|████████████████████████████████████████▊ | 35/91 [00:53<01:22, 1.48s/it]
40%|█████████████████████████████████████████▉ | 36/91 [00:54<01:21, 1.48s/it]
41%|███████████████████████████████████████████ | 37/91 [00:56<01:20, 1.49s/it]
42%|████████████████████████████████████████████▎ | 38/91 [00:57<01:19, 1.49s/it]
43%|█████████████████████████████████████████████▍ | 39/91 [00:59<01:17, 1.48s/it]
44%|██████████████████████████████████████████████▌ | 40/91 [01:00<01:15, 1.49s/it]
45%|███████████████████████████████████████████████▊ | 41/91 [01:02<01:14, 1.48s/it]
46%|████████████████████████████████████████████████▉ | 42/91 [01:03<01:12, 1.47s/it]
47%|██████████████████████████████████████████████████ | 43/91 [01:05<01:10, 1.46s/it]
48%|███████████████████████████████████████████████████▎ | 44/91 [01:06<01:09, 1.48s/it]
49%|████████████████████████████████████████████████████▍ | 45/91 [01:08<01:09, 1.50s/it]
51%|█████████████████████████████████████████████████████▌ | 46/91 [01:09<01:07, 1.51s/it]
52%|██████████████████████████████████████████████████████▋ | 47/91 [01:11<01:07, 1.53s/it]
53%|███████████████████████████████████████████████████████▉ | 48/91 [01:12<01:06, 1.54s/it]
54%|█████████████████████████████████████████████████████████ | 49/91 [01:14<01:04, 1.54s/it]
55%|██████████████████████████████████████████████████████████▏ | 50/91 [01:15<01:03, 1.54s/it]
56%|███████████████████████████████████████████████████████████▍ | 51/91 [01:17<01:02, 1.56s/it]
57%|████████████████████████████████████████████████████████████▌ | 52/91 [01:19<01:00, 1.56s/it]
58%|█████████████████████████████████████████████████████████████▋ | 53/91 [01:20<00:59, 1.56s/it]
59%|██████████████████████████████████████████████████████████████▉ | 54/91 [01:22<00:57, 1.55s/it]
60%|████████████████████████████████████████████████████████████████ | 55/91 [01:23<00:55, 1.55s/it]
62%|█████████████████████████████████████████████████████████████████▏ | 56/91 [01:25<00:54, 1.56s/it]
63%|██████████████████████████████████████████████████████████████████▍ | 57/91 [01:26<00:52, 1.55s/it]
64%|███████████████████████████████████████████████████████████████████▌ | 58/91 [01:28<00:51, 1.56s/it]
65%|████████████████████████████████████████████████████████████████████▋ | 59/91 [01:29<00:49, 1.55s/it]
66%|█████████████████████████████████████████████████████████████████████▉ | 60/91 [01:31<00:48, 1.56s/it]
67%|███████████████████████████████████████████████████████████████████████ | 61/91 [01:33<00:46, 1.56s/it]
68%|████████████████████████████████████████████████████████████████████████▏ | 62/91 [01:34<00:45, 1.56s/it]
69%|█████████████████████████████████████████████████████████████████████████▍ | 63/91 [01:36<00:43, 1.55s/it]
70%|██████████████████████████████████████████████████████████████████████████▌ | 64/91 [01:37<00:41, 1.53s/it]
71%|███████████████████████████████████████████████████████████████████████████▋ | 65/91 [01:39<00:39, 1.52s/it]
73%|████████████████████████████████████████████████████████████████████████████▉ | 66/91 [01:40<00:37, 1.51s/it]
74%|██████████████████████████████████████████████████████████████████████████████ | 67/91 [01:42<00:36, 1.50s/it]
75%|███████████████████████████████████████████████████████████████████████████████▏ | 68/91 [01:43<00:34, 1.51s/it]
76%|████████████████████████████████████████████████████████████████████████████████▎ | 69/91 [01:45<00:33, 1.50s/it]
77%|█████████████████████████████████████████████████████████████████████████████████▌ | 70/91 [01:46<00:31, 1.50s/it]
78%|██████████████████████████████████████████████████████████████████████████████████▋ | 71/91 [01:48<00:29, 1.49s/it]
79%|███████████████████████████████████████████████████████████████████████████████████▊ | 72/91 [01:49<00:28, 1.50s/it]
80%|█████████████████████████████████████████████████████████████████████████████████████ | 73/91 [01:51<00:26, 1.50s/it]
81%|██████████████████████████████████████████████████████████████████████████████████████▏ | 74/91 [01:52<00:25, 1.51s/it]
82%|███████████████████████████████████████████████████████████████████████████████████████▎ | 75/91 [01:54<00:24, 1.52s/it]
84%|████████████████████████████████████████████████████████████████████████████████████████▌ | 76/91 [01:55<00:22, 1.53s/it]
85%|█████████████████████████████████████████████████████████████████████████████████████████▋ | 77/91 [01:57<00:21, 1.53s/it]
86%|██████████████████████████████████████████████████████████████████████████████████████████▊ | 78/91 [01:58<00:19, 1.52s/it]
87%|████████████████████████████████████████████████████████████████████████████████████████████ | 79/91 [02:00<00:18, 1.51s/it]
88%|█████████████████████████████████████████████████████████████████████████████████████████████▏ | 80/91 [02:01<00:16, 1.50s/it]
89%|██████████████████████████████████████████████████████████████████████████████████████████████▎ | 81/91 [02:03<00:14, 1.49s/it]
90%|███████████████████████████████████████████████████████████████████████████████████████████████▌ | 82/91 [02:04<00:13, 1.50s/it]
91%|████████████████████████████████████████████████████████████████████████████████████████████████▋ | 83/91 [02:06<00:12, 1.51s/it]
92%|█████████████████████████████████████████████████████████████████████████████████████████████████▊ | 84/91 [02:07<00:10, 1.52s/it]
93%|███████████████████████████████████████████████████████████████████████████████████████████████████ | 85/91 [02:09<00:09, 1.51s/it]
95%|████████████████████████████████████████████████████████████████████████████████████████████████████▏ | 86/91 [02:10<00:07, 1.52s/it]
96%|█████████████████████████████████████████████████████████████████████████████████████████████████████▎ | 87/91 [02:12<00:06, 1.53s/it]
97%|██████████████████████████████████████████████████████████████████████████████████████████████████████▌ | 88/91 [02:13<00:04, 1.53s/it]
98%|███████████████████████████████████████████████████████████████████████████████████████████████████████▋ | 89/91 [02:15<00:03, 1.54s/it]
99%|████████████████████████████████████████████████████████████████████████████████████████████████████████▊ | 90/91 [02:16<00:01, 1.52s/it]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████| 91/91 [02:18<00:00, 1.51s/it]
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████| 91/91 [02:18<00:00, 1.52s/it]Section 4: Elephant for analyzing spike data
Elephant is a library in Python made specifically for analyzing electrophysiological data. In this section, you’ll explore some of its functions to calculate spike statistics.
| Code | Description |
|---|---|
spike_train = homogeneous_poisson_process(rate=some_rate*pq.Hz, t_start=0.*pq.s, t_stop=10.*pq.s) |
Generates a poisson process spiketrain firing at a rate some_rate for 10 seconds. |
spike_train2 = homogeneous_gamma_process(a=3, b=10*pq.Hz, t_start=0.*pq.s, t_stop=10.*pq.s) |
Generates a gamma process spiketrain firing at a rate some_rate for 10 seconds. |
stats.mean_firing_rate(spike_train) |
Calculates the average firing rate of the spiketrain. |
isi = stats.isi(spike_train) |
Calculates the inter-spike interval (ISI) of the spiketrain. |
stats.cv2(isi) |
Calculates the spike interval variability (CV2 score) for a spike train. |
plt.eventplot([spike_train1.magnitude, spike_train2.magnitude]) |
Creates a raster plot for two spike trains. |
stats.time_histogram(spike_trains=spike_train1, bin_size=1*pq.ms) |
Computes the spike counts per unit time (for example per millisecond) from timestamps. |
Exercises
from elephant.spike_train_generation import homogeneous_poisson_process, homogeneous_gamma_process
from elephant import statistics as statsGenerate spike data
Run the cell below to generate three spike trains using Elephant. Two spike trains are generated by a poisson process and the last one is generated by a gamma process.
np.random.seed(2)
spike_trainA = homogeneous_poisson_process(rate=3*pq.Hz, t_start=0.*pq.s, t_stop=20.*pq.s)
spike_trainB = homogeneous_poisson_process(rate=6*pq.Hz, t_start=0.*pq.s, t_stop=20.*pq.s)
spike_trainC = homogeneous_gamma_process(a=3, b=6*pq.Hz, t_start=0.*pq.s, t_stop=20.*pq.s)
spike_trainASpikeTrain containing 68 spikes; units s; datatype float64
time: 0.0 s to 20.0 sRun the cell below to create a raster plot of the three spike trains.
plt.figure(figsize=(8, 3))
plt.eventplot([spike_trainA.magnitude, spike_trainB.magnitude, spike_trainC.magnitude])
plt.xlabel('Time (s)')
plt.yticks([0, 1, 2], labels=["Poisson process spike train A", "Poisson process spike train B", "Gamma process spike train C"]);Example: Calculate average firing rate of spike train A.
firing_rate = stats.mean_firing_rate(spike_trainA)
firing_ratearray(3.4) * 1/sExercise: Calculate the average firing rate of spike train B.
Solution
firing_rate = stats.mean_firing_rate(spike_trainB)
firing_ratearray(6.55) * 1/sYou can calculate the inter-spike intervals (ISI) for a spike train where you get the unit included (it should say * s at the end of the array containing the ISIs when you display it).
Exercise: Calculate the ISI for spike train A using elephant’s function stats.isi.
Solution
isi_spike_trainA = stats.isi(spike_trainA)
isi_spike_trainAarray([0.00875608, 0.26591931, 0.19050011, 0.18178717, 0.13365914, ...,
0.06179894, 0.11558582, 0.24749264, 0.1470088 , 0.01558505]) * sExercise: Calculate the ISI for spike train B.
Solution
isi_spike_trainB = stats.isi(spike_trainB)
isi_spike_trainBarray([0.07202087, 0.1334472 , 0.60143601, 0.01994301, 0.0626329 , ...,
0.28215394, 0.02347772, 0.07093529, 0.03897143, 0.33671316]) * sExercise: Calculate the ISI for spike train C.
Solution
isi_spike_trainC = stats.isi(spike_trainC)
isi_spike_trainCarray([0.78341479, 0.12469095, 0.3933329 , 0.68786487, 0.2856468 , ...,
0.09028663, 0.70179214, 0.27786033, 0.31526487, 0.26520429]) * sThe interspike intervals can be used to determine whether a spiking neuron is in a bursting, tonic, or poisson firing mode. A bursting neuron fires very often in a short time window but is otherwise mostly silent. A tonic firing mode means that the neuron is firing at highly regular intervals. A poisson firing mode means that the neuron is firing at random and is neither bursting nor in tonic firing mode.
A metric to calculate the the spike interval variability called the CV2 score (stats.CV2) is computed from the interspike interval of a neuron. If the CV2 score is 1 (or close to 1), the neuron is firing in a poisson firing mode. If it’s > 1, then the neuron is bursting. If it’s 0 (or close to 0), then the neuron is in tonic firing mode.
Example: Calculate the CV2 of the inter-spike interval (ISI) spike train A.
cv2_spike_trainA = stats.cv2(isi_spike_trainA)
cv2_spike_trainA0.9653690108731857Exercise: Calculate the CV2 of the inter-spike interval (ISI) spike train B.
Solution
cv2_spike_trainB = stats.cv2(isi_spike_trainB)
cv2_spike_trainB0.9636532783667118Exercise: Calculate the CV2 of the inter-spike interval (ISI) spike train C.
Which spike trains have a CV2 score closest to 1? Is it the ones you would have expected considering which spike trains were generated with a poisson process?
Solution
cv2_spike_trainC = stats.cv2(isi_spike_trainC)
cv2_spike_trainC0.7245379330293805