From 7f044e9b5b49cf01981caaa2f6338d25f6d48536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikkel=20Elle=20Lepper=C3=B8d?= Date: Thu, 10 Oct 2019 11:44:14 +0200 Subject: [PATCH] stim response --- actions/stimulus-response/attributes.yaml | 14 +- .../data/10-calculate-stimulus-response.html | 26912 ++++++++-------- .../data/10-calculate-stimulus-response.ipynb | 554 +- .../data/figures/summary_histogram.png | Bin 10579 -> 10613 bytes actions/stimulus-response/data/results.csv | 2581 +- .../stimulus-response/modules/parameters.yaml | 4 +- 6 files changed, 15038 insertions(+), 15027 deletions(-) diff --git a/actions/stimulus-response/attributes.yaml b/actions/stimulus-response/attributes.yaml index 331d5436c..8dde448fc 100644 --- a/actions/stimulus-response/attributes.yaml +++ b/actions/stimulus-response/attributes.yaml @@ -1,7 +1,7 @@ -registered: '2019-10-03T08:37:34' -data: - figures: figures - statistics: statistics - notebook: 10-calculate-stimulus-response.ipynb - html: 10-calculate-stimulus-response.html - results: results.csv +registered: '2019-10-03T08:37:34' +data: + figures: figures + statistics: statistics + notebook: 10-calculate-stimulus-response.ipynb + html: 10-calculate-stimulus-response.html + results: results.csv diff --git a/actions/stimulus-response/data/10-calculate-stimulus-response.html b/actions/stimulus-response/data/10-calculate-stimulus-response.html index c49ba8843..ad86e6c4c 100644 --- a/actions/stimulus-response/data/10-calculate-stimulus-response.html +++ b/actions/stimulus-response/data/10-calculate-stimulus-response.html @@ -1,13456 +1,13456 @@ - - - - -10-calculate-stimulus-response - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
In [1]:
-
-
-
%load_ext autoreload
-%autoreload 2
-
- -
-
-
- -
-
-
-
In [2]:
-
-
-
import matplotlib.pyplot as plt
-%matplotlib inline
-import spatial_maps as sp
-import septum_mec.analysis.data_processing as dp
-import septum_mec.analysis.registration
-import expipe
-import os
-import pathlib
-import numpy as np
-import exdir
-import pandas as pd
-import optogenetics as og
-import quantities as pq
-import shutil
-from distutils.dir_util import copy_tree
-
-from septum_mec.analysis.stimulus_response import stimulus_response_latency, compute_response
-
-from tqdm import tqdm_notebook as tqdm
-from tqdm._tqdm_notebook import tqdm_notebook
-tqdm_notebook.pandas()
-
- -
-
-
- -
-
- - -
- -
- - -
-
08:31:41 [I] klustakwik KlustaKwik2 version 0.2.6
-
-
-
- -
-
- -
-
-
-
In [3]:
-
-
-
std_gaussian_kde = 0.04
-window_size = 0.03
-
- -
-
-
- -
-
-
-
In [4]:
-
-
-
data_loader = dp.Data()
-actions = data_loader.actions
-project = data_loader.project
-
- -
-
-
- -
-
-
-
In [5]:
-
-
-
output = pathlib.Path('output/stimulus-response')
-(output / 'figures').mkdir(parents=True, exist_ok=True)
-
- -
-
-
- -
-
-
-
In [6]:
-
-
-
identify_neurons = actions['identify-neurons']
-units = pd.read_csv(identify_neurons.data_path('units'))
-
- -
-
-
- -
-
-
-
In [7]:
-
-
-
def process(row):
-    
-    action_id = row['action']
-    channel_id = int(row['channel_group'])
-    unit_id = int(row['unit_name'])    
-    
-    spike_times = data_loader.spike_train(action_id, channel_id, unit_id)
-    
-    spike_times = np.array(spike_times)
-    
-    stim_times = data_loader.stim_times(action_id)
-    
-    nan_series = pd.Series({
-            't_e_peak': np.nan,
-            'p_e_peak': np.nan,
-            't_i_peak': np.nan,
-            'p_i_peak': np.nan
-        })
-    
-    if stim_times is None:
-        return nan_series
-    
-    stim_times = np.array(stim_times)
-    
-    times, spikes, kernel, p_e, p_i = stimulus_response_latency(
-        spike_times, stim_times, window_size, std_gaussian_kde)
-    
-    # if no spikes detected after stimulus nan is returned
-    if all(np.isnan([p_e, p_i])):
-        return nan_series
-        
-    t_e_peak, p_e_peak, t_i_peak, p_i_peak = compute_response(
-        spike_times, stim_times, times, kernel, p_e, p_i)
-
-    return pd.Series({
-        't_e_peak': t_e_peak,
-        'p_e_peak': p_e_peak,
-        't_i_peak': t_i_peak,
-        'p_i_peak': p_i_peak
-    })
-
- -
-
-
- -
-
-
-
In [ ]:
-
-
-
results = units.merge(
-    units.progress_apply(process, axis=1), 
-    left_index=True, right_index=True)
-
- -
-
-
- -
-
- - -
- -
- - - - - - - -
-
- - -
- -
- -
- -
- - -
-
/home/mikkel/apps/expipe-project/septum-mec/septum_mec/analysis/stimulus_response.py:33: RuntimeWarning: invalid value encountered in less
-  if any(times[idxs_i] < te_peak):
-
-
-
- -
-
- -
-
-
-
In [ ]:
-
-
-
results.loc[:, ['t_e_peak', 't_i_peak', 'p_e_peak', 'p_i_peak']].hist()
-plt.gcf().savefig(output / 'figures' / 'summary_histogram.png')
-
- -
-
-
- -
-
-
-
-

Save to expipe

-
-
-
-
-
-
In [ ]:
-
-
-
action = project.require_action("stimulus-response")
-
- -
-
-
- -
-
-
-
In [ ]:
-
-
-
action.modules['parameters'] = {
-    'window_size': window_size,
-    'std_gaussian_kde': std_gaussian_kde
-}
-
- -
-
-
- -
-
-
-
In [ ]:
-
-
-
action.data['results'] = 'results.csv'
-results.to_csv(action.data_path('results'), index=False)
-
- -
-
-
- -
-
-
-
In [ ]:
-
-
-
stuff = {
-    "figures": "figures",
-#     "statistics": "statistics"
-}
-
-for key, value in stuff.items():
-    action.data[key] = value
-    data_path = action.data_path(key)
-    data_path.parent.mkdir(exist_ok=True, parents=True)
-    source = output / value
-    if source.is_file():
-        shutil.copy(source, data_path)
-    else:
-        copy_tree(str(source), str(data_path))
-
- -
-
-
- -
-
-
-
In [ ]:
-
-
-
septum_mec.analysis.registration.store_notebook(action, "10-calculate-stimulus-response.ipynb")
-
- -
-
-
- -
-
-
- - - - - - + + + + +10-calculate-stimulus-response + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
In [1]:
+
+
+
%load_ext autoreload
+%autoreload 2
+
+ +
+
+
+ +
+
+
+
In [2]:
+
+
+
import matplotlib.pyplot as plt
+%matplotlib inline
+import spatial_maps as sp
+import septum_mec.analysis.data_processing as dp
+import septum_mec.analysis.registration
+import expipe
+import os
+import pathlib
+import numpy as np
+import exdir
+import pandas as pd
+import optogenetics as og
+import quantities as pq
+import shutil
+from distutils.dir_util import copy_tree
+
+from septum_mec.analysis.stimulus_response import stimulus_response_latency, compute_response
+
+from tqdm import tqdm_notebook as tqdm
+from tqdm._tqdm_notebook import tqdm_notebook
+tqdm_notebook.pandas()
+
+ +
+
+
+ +
+
+ + +
+ +
+ + +
+
11:36:02 [I] klustakwik KlustaKwik2 version 0.2.6
+
+
+
+ +
+
+ +
+
+
+
In [3]:
+
+
+
std_gaussian_kde = 0.04
+window_size = 0.03
+
+ +
+
+
+ +
+
+
+
In [4]:
+
+
+
data_loader = dp.Data()
+actions = data_loader.actions
+project = data_loader.project
+
+ +
+
+
+ +
+
+
+
In [5]:
+
+
+
output = pathlib.Path('output/stimulus-response')
+(output / 'figures').mkdir(parents=True, exist_ok=True)
+
+ +
+
+
+ +
+
+
+
In [6]:
+
+
+
identify_neurons = actions['identify-neurons']
+units = pd.read_csv(identify_neurons.data_path('units'))
+
+ +
+
+
+ +
+
+
+
In [7]:
+
+
+
def process(row):
+    
+    action_id = row['action']
+    channel_id = int(row['channel_group'])
+    unit_id = int(row['unit_name'])    
+    
+    spike_times = data_loader.spike_train(action_id, channel_id, unit_id)
+    
+    spike_times = np.array(spike_times)
+    
+    stim_times = data_loader.stim_times(action_id)
+    
+    nan_series = pd.Series({
+            't_e_peak': np.nan,
+            'p_e_peak': np.nan,
+            't_i_peak': np.nan,
+            'p_i_peak': np.nan
+        })
+    
+    if stim_times is None:
+        return nan_series
+    
+    stim_times = np.array(stim_times)
+    
+    times, spikes, kernel, p_e, p_i = stimulus_response_latency(
+        spike_times, stim_times, window_size, std_gaussian_kde)
+    
+    # if no spikes detected after stimulus nan is returned
+    if all(np.isnan([p_e, p_i])):
+        return nan_series
+        
+    t_e_peak, p_e_peak, t_i_peak, p_i_peak = compute_response(
+        spike_times, stim_times, times, kernel, p_e, p_i)
+
+    return pd.Series({
+        't_e_peak': t_e_peak,
+        'p_e_peak': p_e_peak,
+        't_i_peak': t_i_peak,
+        'p_i_peak': p_i_peak
+    })
+
+ +
+
+
+ +
+
+
+
In [ ]:
+
+
+
results = units.merge(
+    units.progress_apply(process, axis=1), 
+    left_index=True, right_index=True)
+
+ +
+
+
+ +
+
+ + +
+ +
+ + + + + + + +
+
+ + +
+ +
+ +
+ +
+ + +
+
/home/mikkel/apps/expipe-project/septum-mec/septum_mec/analysis/stimulus_response.py:33: RuntimeWarning: invalid value encountered in less
+  if any(times[idxs_i] < te_peak):
+
+
+
+ +
+
+ +
+
+
+
In [ ]:
+
+
+
results.loc[:, ['t_e_peak', 't_i_peak', 'p_e_peak', 'p_i_peak']].hist()
+plt.gcf().savefig(output / 'figures' / 'summary_histogram.png')
+
+ +
+
+
+ +
+
+
+
+

Save to expipe

+
+
+
+
+
+
In [ ]:
+
+
+
action = project.require_action("stimulus-response")
+
+ +
+
+
+ +
+
+
+
In [ ]:
+
+
+
action.modules['parameters'] = {
+    'window_size': window_size,
+    'std_gaussian_kde': std_gaussian_kde
+}
+
+ +
+
+
+ +
+
+
+
In [ ]:
+
+
+
action.data['results'] = 'results.csv'
+results.to_csv(action.data_path('results'), index=False)
+
+ +
+
+
+ +
+
+
+
In [ ]:
+
+
+
copy_tree(output, str(action.data_path()))
+
+ +
+
+
+ +
+
+
+
In [ ]:
+
+
+
septum_mec.analysis.registration.store_notebook(action, "10-calculate-stimulus-response.ipynb")
+
+ +
+
+
+ +
+
+
+
In [ ]:
+
+
+
 
+
+ +
+
+
+ +
+
+
+ + + + + + diff --git a/actions/stimulus-response/data/10-calculate-stimulus-response.ipynb b/actions/stimulus-response/data/10-calculate-stimulus-response.ipynb index db9fae70a..b54834fb8 100644 --- a/actions/stimulus-response/data/10-calculate-stimulus-response.ipynb +++ b/actions/stimulus-response/data/10-calculate-stimulus-response.ipynb @@ -1,280 +1,274 @@ -{ - "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": [ - "08:31:41 [I] klustakwik KlustaKwik2 version 0.2.6\n" - ] - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "%matplotlib inline\n", - "import spatial_maps as sp\n", - "import septum_mec.analysis.data_processing as dp\n", - "import septum_mec.analysis.registration\n", - "import expipe\n", - "import os\n", - "import pathlib\n", - "import numpy as np\n", - "import exdir\n", - "import pandas as pd\n", - "import optogenetics as og\n", - "import quantities as pq\n", - "import shutil\n", - "from distutils.dir_util import copy_tree\n", - "\n", - "from septum_mec.analysis.stimulus_response import stimulus_response_latency, compute_response\n", - "\n", - "from tqdm import tqdm_notebook as tqdm\n", - "from tqdm._tqdm_notebook import tqdm_notebook\n", - "tqdm_notebook.pandas()" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "std_gaussian_kde = 0.04\n", - "window_size = 0.03" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "data_loader = dp.Data()\n", - "actions = data_loader.actions\n", - "project = data_loader.project" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "output = pathlib.Path('output/stimulus-response')\n", - "(output / 'figures').mkdir(parents=True, exist_ok=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "identify_neurons = actions['identify-neurons']\n", - "units = pd.read_csv(identify_neurons.data_path('units'))" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "def process(row):\n", - " \n", - " action_id = row['action']\n", - " channel_id = int(row['channel_group'])\n", - " unit_id = int(row['unit_name']) \n", - " \n", - " spike_times = data_loader.spike_train(action_id, channel_id, unit_id)\n", - " \n", - " spike_times = np.array(spike_times)\n", - " \n", - " stim_times = data_loader.stim_times(action_id)\n", - " \n", - " nan_series = pd.Series({\n", - " 't_e_peak': np.nan,\n", - " 'p_e_peak': np.nan,\n", - " 't_i_peak': np.nan,\n", - " 'p_i_peak': np.nan\n", - " })\n", - " \n", - " if stim_times is None:\n", - " return nan_series\n", - " \n", - " stim_times = np.array(stim_times)\n", - " \n", - " times, spikes, kernel, p_e, p_i = stimulus_response_latency(\n", - " spike_times, stim_times, window_size, std_gaussian_kde)\n", - " \n", - " # if no spikes detected after stimulus nan is returned\n", - " if all(np.isnan([p_e, p_i])):\n", - " return nan_series\n", - " \n", - " t_e_peak, p_e_peak, t_i_peak, p_i_peak = compute_response(\n", - " spike_times, stim_times, times, kernel, p_e, p_i)\n", - "\n", - " return pd.Series({\n", - " 't_e_peak': t_e_peak,\n", - " 'p_e_peak': p_e_peak,\n", - " 't_i_peak': t_i_peak,\n", - " 'p_i_peak': p_i_peak\n", - " })\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d3f0400c75c745c789907bd763bf2833", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HBox(children=(IntProgress(value=0, max=1281), HTML(value='')))" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/mikkel/apps/expipe-project/septum-mec/septum_mec/analysis/stimulus_response.py:33: RuntimeWarning: invalid value encountered in less\n", - " if any(times[idxs_i] < te_peak):\n" - ] - } - ], - "source": [ - "results = units.merge(\n", - " units.progress_apply(process, axis=1), \n", - " left_index=True, right_index=True)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "scrolled": false - }, - "outputs": [], - "source": [ - "results.loc[:, ['t_e_peak', 't_i_peak', 'p_e_peak', 'p_i_peak']].hist()\n", - "plt.gcf().savefig(output / 'figures' / 'summary_histogram.png')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Save to expipe" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "action = project.require_action(\"stimulus-response\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "action.modules['parameters'] = {\n", - " 'window_size': window_size,\n", - " 'std_gaussian_kde': std_gaussian_kde\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "action.data['results'] = 'results.csv'\n", - "results.to_csv(action.data_path('results'), index=False)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "stuff = {\n", - " \"figures\": \"figures\",\n", - "# \"statistics\": \"statistics\"\n", - "}\n", - "\n", - "for key, value in stuff.items():\n", - " action.data[key] = value\n", - " data_path = action.data_path(key)\n", - " data_path.parent.mkdir(exist_ok=True, parents=True)\n", - " source = output / value\n", - " if source.is_file():\n", - " shutil.copy(source, data_path)\n", - " else:\n", - " copy_tree(str(source), str(data_path))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "septum_mec.analysis.registration.store_notebook(action, \"10-calculate-stimulus-response.ipynb\")" - ] - } - ], - "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": 2 -} +{ + "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": [ + "11:36:02 [I] klustakwik KlustaKwik2 version 0.2.6\n" + ] + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "%matplotlib inline\n", + "import spatial_maps as sp\n", + "import septum_mec.analysis.data_processing as dp\n", + "import septum_mec.analysis.registration\n", + "import expipe\n", + "import os\n", + "import pathlib\n", + "import numpy as np\n", + "import exdir\n", + "import pandas as pd\n", + "import optogenetics as og\n", + "import quantities as pq\n", + "import shutil\n", + "from distutils.dir_util import copy_tree\n", + "\n", + "from septum_mec.analysis.stimulus_response import stimulus_response_latency, compute_response\n", + "\n", + "from tqdm import tqdm_notebook as tqdm\n", + "from tqdm._tqdm_notebook import tqdm_notebook\n", + "tqdm_notebook.pandas()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "std_gaussian_kde = 0.04\n", + "window_size = 0.03" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "data_loader = dp.Data()\n", + "actions = data_loader.actions\n", + "project = data_loader.project" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "output = pathlib.Path('output/stimulus-response')\n", + "(output / 'figures').mkdir(parents=True, exist_ok=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "identify_neurons = actions['identify-neurons']\n", + "units = pd.read_csv(identify_neurons.data_path('units'))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "def process(row):\n", + " \n", + " action_id = row['action']\n", + " channel_id = int(row['channel_group'])\n", + " unit_id = int(row['unit_name']) \n", + " \n", + " spike_times = data_loader.spike_train(action_id, channel_id, unit_id)\n", + " \n", + " spike_times = np.array(spike_times)\n", + " \n", + " stim_times = data_loader.stim_times(action_id)\n", + " \n", + " nan_series = pd.Series({\n", + " 't_e_peak': np.nan,\n", + " 'p_e_peak': np.nan,\n", + " 't_i_peak': np.nan,\n", + " 'p_i_peak': np.nan\n", + " })\n", + " \n", + " if stim_times is None:\n", + " return nan_series\n", + " \n", + " stim_times = np.array(stim_times)\n", + " \n", + " times, spikes, kernel, p_e, p_i = stimulus_response_latency(\n", + " spike_times, stim_times, window_size, std_gaussian_kde)\n", + " \n", + " # if no spikes detected after stimulus nan is returned\n", + " if all(np.isnan([p_e, p_i])):\n", + " return nan_series\n", + " \n", + " t_e_peak, p_e_peak, t_i_peak, p_i_peak = compute_response(\n", + " spike_times, stim_times, times, kernel, p_e, p_i)\n", + "\n", + " return pd.Series({\n", + " 't_e_peak': t_e_peak,\n", + " 'p_e_peak': p_e_peak,\n", + " 't_i_peak': t_i_peak,\n", + " 'p_i_peak': p_i_peak\n", + " })\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "476c31da67274b2396ed3f2ec54a8344", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "HBox(children=(IntProgress(value=0, max=1298), HTML(value='')))" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/mikkel/apps/expipe-project/septum-mec/septum_mec/analysis/stimulus_response.py:33: RuntimeWarning: invalid value encountered in less\n", + " if any(times[idxs_i] < te_peak):\n" + ] + } + ], + "source": [ + "results = units.merge(\n", + " units.progress_apply(process, axis=1), \n", + " left_index=True, right_index=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "results.loc[:, ['t_e_peak', 't_i_peak', 'p_e_peak', 'p_i_peak']].hist()\n", + "plt.gcf().savefig(output / 'figures' / 'summary_histogram.png')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Save to expipe" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "action = project.require_action(\"stimulus-response\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "action.modules['parameters'] = {\n", + " 'window_size': window_size,\n", + " 'std_gaussian_kde': std_gaussian_kde\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "action.data['results'] = 'results.csv'\n", + "results.to_csv(action.data_path('results'), index=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "copy_tree(output, str(action.data_path()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "septum_mec.analysis.registration.store_notebook(action, \"10-calculate-stimulus-response.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": 2 +} diff --git a/actions/stimulus-response/data/figures/summary_histogram.png b/actions/stimulus-response/data/figures/summary_histogram.png index 9c15bbf8be04c1b76de9f44ae1ece46d8faf3812..24a2a85fae921dd9abc331e843d1c7943169c98b 100644 GIT binary patch literal 10613 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