septum-mec/actions/lfp_speed_stim/data/10_lfp_speed_stim.ipynb

415 lines
13 KiB
Plaintext
Raw Normal View History

2021-03-10 12:44:26 +00:00
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%load_ext autoreload\n",
"%autoreload 2"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"09:52:58 [I] klustakwik KlustaKwik2 version 0.2.6\n",
"/home/mikkel/.virtualenvs/expipe/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject\n",
" return f(*args, **kwds)\n",
"/home/mikkel/.virtualenvs/expipe/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject\n",
" return f(*args, **kwds)\n",
"/home/mikkel/.virtualenvs/expipe/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject\n",
" return f(*args, **kwds)\n"
]
}
],
"source": [
"import os\n",
"import pathlib\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from matplotlib import colors\n",
"import seaborn as sns\n",
"import re\n",
"import shutil\n",
"import pandas as pd\n",
"import scipy.stats\n",
"\n",
"import exdir\n",
"import expipe\n",
"from distutils.dir_util import copy_tree\n",
"import septum_mec\n",
"import spatial_maps as sp\n",
"import head_direction.head as head\n",
"import septum_mec.analysis.data_processing as dp\n",
"import septum_mec.analysis.registration\n",
"from septum_mec.analysis.plotting import violinplot, despine\n",
"from spatial_maps.fields import (\n",
" find_peaks, calculate_field_centers, separate_fields_by_laplace, \n",
" map_pass_to_unit_circle, calculate_field_centers, distance_to_edge_function, \n",
" which_field, compute_crossings)\n",
"from phase_precession import cl_corr\n",
"from spike_statistics.core import permutation_resampling\n",
"import matplotlib.mlab as mlab\n",
"import scipy.signal as ss\n",
"from scipy.interpolate import interp1d\n",
"from septum_mec.analysis.plotting import regplot\n",
"from skimage import measure\n",
"from tqdm.notebook import tqdm_notebook as tqdm\n",
"tqdm.pandas()\n",
"\n",
"import pycwt"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"max_speed = 1 # m/s only used for speed score\n",
"min_speed = 0.02 # m/s only used for speed score\n",
"position_sampling_rate = 1000 # for interpolation\n",
"position_low_pass_frequency = 6 # for low pass filtering of position\n",
"\n",
"box_size = [1.0, 1.0]\n",
"bin_size = 0.02\n",
"\n",
"speed_binsize = 0.02\n",
"\n",
"stim_mask = True\n",
"baseline_duration = 600"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"data_loader = dp.Data(\n",
" position_sampling_rate=position_sampling_rate, \n",
" position_low_pass_frequency=position_low_pass_frequency,\n",
" box_size=box_size, bin_size=bin_size, \n",
" stim_mask=stim_mask, baseline_duration=baseline_duration\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"project_path = dp.project_path()\n",
"project = expipe.get_project(project_path)\n",
"actions = project.actions\n",
"\n",
"output_path = pathlib.Path(\"output\") / \"lfp-speed-stim\"\n",
"(output_path / \"statistics\").mkdir(exist_ok=True, parents=True)\n",
"(output_path / \"figures\").mkdir(exist_ok=True, parents=True)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"identify_neurons = actions['identify-neurons']\n",
"sessions = pd.read_csv(identify_neurons.data_path('sessions'))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"channel_groups = []\n",
"for i, row in sessions.iterrows():\n",
" for ch in range(8):\n",
" row['channel_group'] = ch\n",
" channel_groups.append(row.to_dict())"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"sessions = pd.DataFrame(channel_groups)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"def signaltonoise(a, axis=0, ddof=0):\n",
" a = np.asanyarray(a)\n",
" m = a.mean(axis)\n",
" sd = a.std(axis=axis, ddof=ddof)\n",
" return np.where(sd == 0, 0, m / sd)\n",
"\n",
"\n",
"def remove_artifacts(anas, spikes=None, width=500, threshold=2, sampling_rate=None, fillval=0):\n",
" sampling_rate = sampling_rate or anas.sampling_rate.magnitude\n",
" times = np.arange(anas.shape[0]) / sampling_rate\n",
" anas = np.array(anas)\n",
" if anas.ndim == 1:\n",
" anas = np.reshape(anas, (anas.size, 1))\n",
" assert len(times) == anas.shape[0]\n",
" nchan = anas.shape[1]\n",
" if spikes is not None:\n",
" spikes = np.array(spikes)\n",
" for ch in range(nchan):\n",
" idxs, = np.where(abs(anas[:, ch]) > threshold)\n",
" for idx in idxs:\n",
" if spikes is not None:\n",
" t0 = times[idx-width]\n",
" stop = idx+width\n",
" if stop > len(times) - 1:\n",
" stop = len(times) - 1 \n",
" t1 = times[stop]\n",
" mask = (spikes > t0) & (spikes < t1)\n",
" spikes = spikes[~mask]\n",
" anas[idx-width:idx+width, ch] = fillval\n",
" if spikes is not None:\n",
" spikes = spikes[spikes <= times[-1]]\n",
" return anas, times, spikes\n",
" else:\n",
" return anas, times\n",
" \n",
"def find_theta_peak(p, f, f1, f2):\n",
" if np.all(np.isnan(p)):\n",
" return np.nan, np.nan\n",
" mask = (f > f1) & (f < f2)\n",
" p_m = p[mask]\n",
" f_m = f[mask]\n",
" peaks = find_peaks(p_m)\n",
" idx = np.argmax(p_m[peaks])\n",
" return f_m[peaks[idx]], p_m[peaks[idx]]"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"def zscore(a):\n",
" return (a - a.mean()) / a.std()\n",
"# return a"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"def compute_stim_freq(action_id):\n",
" stim_times = data_loader.stim_times(action_id)\n",
" if stim_times is None:\n",
" return\n",
" stim_times = np.array(stim_times)\n",
" return 1 / np.mean(np.diff(stim_times))"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"output = exdir.File(output_path / 'results')\n",
"\n",
"mother = pycwt.Morlet(80)\n",
"NFFT = 2056\n",
"\n",
"def process(row):\n",
" name = row['action'] + '-' + str(row['channel_group'])\n",
" stim_freq = compute_stim_freq(row['action'])\n",
" if stim_freq is None:\n",
" return\n",
" \n",
" flim = [stim_freq - 2, stim_freq + 2]\n",
" \n",
" lfp = data_loader.lfp(row.action, row.channel_group)\n",
" sample_rate = lfp.sampling_rate.magnitude\n",
" sampling_period = 1 / sample_rate\n",
" x, y, t, speed = map(data_loader.tracking(row.action).get, ['x', 'y', 't', 'v'])\n",
" cleaned_lfp, times = remove_artifacts(lfp)\n",
" speed = interp1d(t, speed, bounds_error=False, fill_value='extrapolate')(times)\n",
" peak_amp = {}\n",
" for i, ch in enumerate(cleaned_lfp.T):\n",
" pxx, freqs = mlab.psd(ch, Fs=lfp.sampling_rate.magnitude, NFFT=4000)\n",
" f, p = find_theta_peak(pxx, freqs, 6, 10)\n",
" peak_amp[i] = p\n",
"\n",
" theta_channel = max(peak_amp, key=lambda x: peak_amp[x])\n",
" signal = zscore(cleaned_lfp[:,theta_channel])\n",
" \n",
" if name in output:\n",
" return\n",
" \n",
" \n",
" results = output.require_group(name)\n",
" freqs = np.arange(*flim, .1)\n",
" wave, scales, freqs, coi, fft, fftfreqs = pycwt.cwt(\n",
" signal, sampling_period, freqs=freqs, wavelet=mother)\n",
" \n",
" power = (np.abs(wave)) ** 2\n",
" power /= scales[:, None] #rectify the power spectrum according to the suggestions proposed by Liu et al. (2007)\n",
" \n",
" theta_freq = np.array([freqs[i] for i in np.argmax(power, axis=0)])\n",
" theta_power = np.mean(power, axis=0)\n",
"\n",
" speed_bins = np.arange(min_speed, max_speed + speed_binsize, speed_binsize)\n",
" ia = np.digitize(speed, bins=speed_bins, right=True)\n",
" mean_freq = np.zeros_like(speed_bins)\n",
" mean_power = np.zeros_like(speed_bins)\n",
" for i in range(len(speed_bins)):\n",
" mean_freq[i] = np.mean(theta_freq[ia==i])\n",
" mean_power[i] = np.mean(theta_power[ia==i])\n",
" \n",
" freq_score = np.corrcoef(speed, theta_freq)[0,1]\n",
" power_score = np.corrcoef(speed, theta_power)[0,1]\n",
" \n",
" results.attrs = {\n",
" 'freq_score': float(freq_score),\n",
" 'sample_rate': float(sample_rate),\n",
" 'power_score': float(power_score),\n",
" 'action': row['action'],\n",
" 'channel_group': int(row['channel_group']),\n",
" 'max_speed': max_speed,\n",
" 'min_speed': min_speed,\n",
" 'position_low_pass_frequency': position_low_pass_frequency\n",
" }\n",
" \n",
" results.create_dataset('wavelet_power', data=power)\n",
" results.create_dataset('wavelet_freqs', data=freqs)\n",
" results.create_dataset('theta_freq', data=theta_freq)\n",
" results.create_dataset('theta_power', data=theta_power)\n",
" results.create_dataset('speed', data=speed)\n",
" results.create_dataset('mean_freq', data=mean_freq)\n",
" results.create_dataset('mean_power', data=mean_power)\n",
" results.create_dataset('speed_bins', data=speed_bins)\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1f5b845ccb4c460780c75e4829109535",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"HBox(children=(IntProgress(value=0, max=696), HTML(value='')))"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/mikkel/.virtualenvs/expipe/lib/python3.6/site-packages/numpy/core/fromnumeric.py:3257: RuntimeWarning: Mean of empty slice.\n",
" out=out, **kwargs)\n",
"/home/mikkel/.virtualenvs/expipe/lib/python3.6/site-packages/numpy/core/_methods.py:161: RuntimeWarning: invalid value encountered in double_scalars\n",
" ret = ret.dtype.type(ret / rcount)\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n"
]
}
],
"source": [
"sessions.progress_apply(process, axis=1);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Store results in Expipe action"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"action = project.require_action(\"lfp_speed_stim\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"action.data[\"results\"] = \"results.exdir\"\n",
"copy_tree(output_path, str(action.data_path()))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"septum_mec.analysis.registration.store_notebook(action, \"10_lfp_speed_stim.ipynb\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
}
},
"nbformat": 4,
"nbformat_minor": 4
}