2021-11-05 • Vary I/E synaptic conductances
Contents
2021-11-05 • Vary I/E synaptic conductances¶
Prelude¶
from voltage_to_wiring_sim.notebook_init import *
Preloading: numpy, numba, matplotlib.pyplot, seaborn.
Importing from submodules … ✔
Imported `np`, `mpl`, `plt`, `sns`, `pd`
Imported codebase (`voltage_to_wiring_sim`) as `v`
Imported `*` from `v.support.units`
Setup autoreload
v.print_reproducibility_info()
This cell was last run by lpxtf3
on DUIP74576
on Thu 11 Nov 2021, at 19:13 (UTC+0000).
Last git commit (Fri 05 Nov 2021, 17:08).
Uncommited changes to 5 files.
Calculate¶
from voltage_to_wiring_sim.experiments.N_to_1_IE import Params, simulate_and_test_connections, eval_performance
base_params = Params()
v.pprint(base_params)
Params
------
sim_duration = 600
timestep = 0.0001
τ_syn = 0.007
neuron_params = {'C': 1e-10, 'a': 30.0, 'b': -2e-09, 'c': -0.05, ...}
imaging_spike_SNR = 20
window_duration = 0.1
num_spike_trains = 30
p_inhibitory = 0.2
p_connected = 0.7
spike_rate = 20
Δg_syn_exc = 4E-10
Δg_syn_inh = 1.6E-09
v_syn_exc = 0
v_syn_inh = -0.065
rng_seed = 0
New parameters: Δg_syn _exc and _inh.
Note that other base parameters have been changed wrt previous notebooks: inh syn rev pot, and 4:1 exc:inh inputs, and 70% connected.
@v.cache_to_disk("2021-11-05__vary_Δgsyn_IE")
def sim_test_eval(params: Params):
sim_data, _, test_summaries = simulate_and_test_connections(params)
evalu_p_0_05, _, AUC, AUC_exc, AUC_inh = eval_performance(sim_data, test_summaries)
output_spike_rate = sim_data.izh_output.spike_times.size / params.sim_duration
return (output_spike_rate,
evalu_p_0_05.TPR_exc, evalu_p_0_05.TPR_inh, evalu_p_0_05.FPR,
AUC, AUC_exc, AUC_inh)
from joblib import Parallel, delayed
runner = Parallel(n_jobs=-1)
# output printing is not done here, but in jupyter terminal.
def run_parallel(f, args):
return runner(delayed(f)(arg) for arg in args);
from dataclasses import replace
from itertools import product
dgsyn_ratios = [0.5, 1, 2, 4, 8, 16, 32]
def get_dgsyn_vals(ratio, dgsyn_exc = 0.4 * nS):
return dict(Δg_syn_exc=dgsyn_exc,
Δg_syn_inh=dgsyn_exc * ratio)
seeds = [0, 1, 2];
seeds = [0, 1, 2, 3, 4, 5];
seeds = np.arange(20);
f = sim_test_eval
args = [replace(base_params,
**get_dgsyn_vals(ratio),
rng_seed=seed,
)
for (ratio, seed) in product(dgsyn_ratios, seeds)];
%%time
results = run_parallel(f, args);
Wall time: 7.59 s
M = np.reshape(results, (len(dgsyn_ratios), len(seeds), -1))
(output_spike_rate,
TPR_exc, TPR_inh, FPR,
AUC, AUC_exc, AUC_inh) = (M[:,:,i] for i in range(M.shape[-1]))
Plot¶
def plot_dots_and_mean(data, ax, x, c="0.2", label=None, ms=6, lw=5):
ax.plot(x, data, "o", alpha=0.3, c=c, ms=ms)
ax.plot(x, np.mean(data, axis=-1), "-", c=c, label=label, lw=lw)
smaller = dict(ms=4, lw=3);
def make_syncond_ax():
fig, ax = plt.subplots()
ax.set_xscale('log')
ax.set_xticks(dgsyn_ratios)
ax.set_xticklabels(f"{d:g}" for d in dgsyn_ratios)
ax.set_xlabel("Synaptic conductance ratio $\; Δg_{inh} \; / \; Δg_{exc}$")
return fig, ax
plot = partial(plot_dots_and_mean, x=dgsyn_ratios);
fig, ax = make_syncond_ax();
ax.set_ylim(0.5, 1.02)
# plot(ax, AUC);
plot(AUC_exc, ax, c=v.color_exc, label="Excitatory conn.")
plot(AUC_inh, ax, c=v.color_inh, label="Inhibitory conn.", **smaller)
ax.set_ylabel("Area under ROC curve")
ax.legend();
fig, ax = make_syncond_ax();
plot(TPR_exc, ax, c=v.color_exc, label="Excitatory conn.")
plot(TPR_inh, ax, c=v.color_inh, label="Inhibitory conn.", **smaller)
plot(FPR, ax, c=v.color_unconn, label="Non-connections")
ax.set_ylabel("Fraction detected as connection")
# ax.yaxis.set_major_formatter(mpl.ticker.PercentFormatter(xmax=1))
ax.legend();
np.mean(FPR, axis=-1)
array([0.04444, 0.06111, 0.07778, 0.03889, 0.07222, 0.05, 0.05556])
fig, ax = make_syncond_ax()
plot(output_spike_rate, ax, lw=4, ms=4)
ax.set_ylabel("Output spike rate (Hz)");
Investigate ROC¶
Why, at ratio = 2, is AUC perfectly 1 always, but FPR goes as high as 40% at p = 0.05?
sim_and_test = v.cache_to_disk(None)(simulate_and_test_connections)
eval_perf = v.cache_to_disk(None)(eval_performance);
d, td, ts = sim_and_test(Params(rng_seed=0, **get_dgsyn_vals(ratio=2)))
evalu_p_0_05, thr_sweep, AUC, AUC_exc, AUC_inh = eval_performance(d, ts);
evalu_p_0_05.FPR
0.2222222222222222
TPR_exc = [c.evaluation.TPR_exc for c in thr_sweep]
TPR_inh = [c.evaluation.TPR_inh for c in thr_sweep]
FPR = [c.evaluation.FPR for c in thr_sweep]
fig, ax = plt.subplots()
step_kwargs = dict(marker=".")
ax.step(FPR, TPR_inh, where="post", clip_on=False, **step_kwargs)
ax.fill_between(FPR, TPR_inh, step="post", alpha=0.1, color="grey")
ax.set_aspect("equal")
ax.set(
xlabel="#FP / #unconnected",
ylabel="#TP / #connected_inh",
xlim=(0, 1),
ylim=(0, 1),
);
[c.p_value_threshold for c in thr_sweep]
[0.0, 0.01, 0.03, 0.28, 0.52, 0.67, 0.72, 0.88, 0.91, 0.99]
import pandas as pd
df = pd.DataFrame(ts)
df["conn"] = d.is_connected.astype(int)
df["EI"] = ["exc" if e else "inh" for e in d.is_excitatory]
df
p_value | p_value_type | relative_STA_height | conn | EI | |
---|---|---|---|---|---|
0 | 0.01 | < | 1.946213 | 1 | inh |
1 | 0.01 | < | 2.115577 | 1 | inh |
2 | 0.01 | < | 2.096411 | 1 | inh |
3 | 0.01 | < | 2.029915 | 1 | inh |
4 | 0.99 | = | 0.843468 | 0 | inh |
5 | 0.88 | = | 0.897993 | 0 | inh |
6 | 0.01 | < | 2.721153 | 1 | exc |
7 | 0.01 | < | 3.138538 | 1 | exc |
8 | 0.01 | < | 2.724142 | 1 | exc |
9 | 0.01 | < | 3.210947 | 1 | exc |
10 | 0.01 | < | 2.833998 | 1 | exc |
11 | 0.01 | < | 3.325955 | 1 | exc |
12 | 0.01 | < | 2.849604 | 1 | exc |
13 | 0.01 | < | 3.031652 | 1 | exc |
14 | 0.01 | < | 2.975779 | 1 | exc |
15 | 0.01 | < | 3.274779 | 1 | exc |
16 | 0.01 | < | 2.737663 | 1 | exc |
17 | 0.01 | < | 3.190077 | 1 | exc |
18 | 0.01 | < | 2.983896 | 1 | exc |
19 | 0.01 | < | 3.080062 | 1 | exc |
20 | 0.01 | < | 3.150776 | 1 | exc |
21 | 0.01 | < | 2.667729 | 1 | exc |
22 | 0.01 | < | 3.062099 | 1 | exc |
23 | 0.28 | = | 1.049534 | 0 | exc |
24 | 0.72 | = | 0.935894 | 0 | exc |
25 | 0.03 | = | 1.174938 | 0 | exc |
26 | 0.91 | = | 0.900700 | 0 | exc |
27 | 0.03 | = | 1.215529 | 0 | exc |
28 | 0.52 | = | 0.986098 | 0 | exc |
29 | 0.67 | = | 0.953430 | 0 | exc |
So the culprits are rows 25 and 27: unconnected, but only 3 out of the 100 shuffled STA’s were larger than the real STA. (We’d expect it to be 50 / 100, as the reality is that they’re unconnected).
Imagine if there were only unconnected pairs. ..
So the reason for perfect AUC is..
How was it constructed? for all 30 (pre, post)-pairs, test_connection
, and a resulting p-value which gives proportion of shuffled STAs that are larger than real STA.
These p-values are aggregated and made unique, then used to actually classify each pair.
Is it to be expected that FPR = 0.05 at p < 0.05?
Yes.
How to choose p-value threshold?
“at p < x%, x out of 100 shuffled spike trains are allowed to have a higher STA than the real spike train”.
So yes, p 0.05 is weird, would make more sense to say: “NO shuffled spike trains are allwed to have higher STA”
<=> p < 1/num_shuffles i.e. 0.01.
btw is this p-value here compatible with general p-value definition?
“probability of obtaining results at least as extreme as observed if no effect”
-» “probability of obtaining STA at least as high if not connected”
So yes, very compatible.
Is it weird to do thresholding on p-values?
How is definition above expanded to threshold:
“We detect a connection if the probability of obtaining STA at least as large if they were not connected is 5%”
Inspect signals¶
from voltage_to_wiring_sim.experiments.N_to_1_IE import indices_where
fig, axes = plt.subplots(nrows=3, ncols=3, **v.figsize(width=1000))
for i, ratio in enumerate([0.5, 4, 16]):
d, td, ts = sim_and_test(replace(base_params, **get_dgsyn_vals(ratio=ratio)))
vm = d.izh_output.V_m
ax = v.plot_signal(vm.slice(t_start=10*second, duration=3*second) / mV, ax=axes[0, i])
ax.axhline(np.median(vm) / mV, c='C1')
ax.set_ylim(-68, -22);
ax.set_xlabel("Time (s)")
ax.set_title("$Δg_{inh} \; / \; Δg_{exc} = " + f"{ratio:g}$", pad=18)
ax_e = v.plot_STA(td[indices_where(d.is_excitatory & d.is_connected)[0]].original_STA, ax=axes[1, i])
ax_i = v.plot_STA(td[indices_where(d.is_inhibitory & d.is_connected)[0]].original_STA, ax=axes[2, i])
ylims = (min(ax_i.get_ylim()[0], ax_e.get_ylim()[0]),
max(ax_i.get_ylim()[1], ax_e.get_ylim()[1]))
ax_e.set_ylim(ylims)
ax_i.set_ylim(ylims)
if i == 0:
ax.set_ylabel("Membrane pot. (mV)");
ax_e.set_ylabel("STA of VI signal for an" + '\n' + r"$\bf{excitatory}$ conn. (mV)")
ax_i.set_ylabel("STA of VI signal for an" + '\n' + r"$\bf{inhibitory}$ conn. (mV)")
else:
ax_e.set_ylabel(None)
ax_i.set_ylabel(None)
fig.tight_layout()
d, td, ts = sim_and_test(Params(rng_seed=0, **get_dgsyn_vals(ratio=4)));
v.plot_signal(d.izh_output.V_m.slice(10*second, 1*second) / mV);
Reproducibility¶
v.print_reproducibility_info(verbose=True)
This cell was last run by lpxtf3
on DUIP74576
on Thu 11 Nov 2021, at 19:16 (UTC+0000).
Last git commit (Fri 05 Nov 2021, 17:08).
Uncommited changes to:
M codebase/voltage_to_wiring_sim/__init__.py
M codebase/voltage_to_wiring_sim/experiments/N_to_1_IE.py
M codebase/voltage_to_wiring_sim/support/plot_style.py
M notebooks/2021-09-16__vary_E_vs_I.ipynb
?? "notebooks/2021-11-05__vary_\316\224gsyn_IE.ipynb"
Platform:
Windows-10
CPython 3.9.6 (C:\miniforge3\python.exe)
Intel(R) Xeon(R) W-2123 CPU @ 3.60GHz
Dependencies of voltage_to_wiring_sim
and their installed versions:
numpy 1.21.1
matplotlib 3.4.2
numba 0.53.1
joblib 1.0.1
seaborn 0.11.1
scipy 1.7.0
preload 2.2
nptyping 1.4.2
Full conda list:
# packages in environment at C:\miniforge3:
#
# Name Version Build Channel
argon2-cffi 20.1.0 py39hb82d6ee_2 conda-forge
async_generator 1.10 py_0 conda-forge
attrs 21.2.0 pyhd8ed1ab_0 conda-forge
backcall 0.2.0 pyh9f0ad1d_0 conda-forge
backports 1.0 py_2 conda-forge
backports.functools_lru_cache 1.6.4 pyhd8ed1ab_0 conda-forge
black 21.9b0 pyhd8ed1ab_1 conda-forge
bleach 3.3.1 pyhd8ed1ab_0 conda-forge
brotlipy 0.7.0 py39hb82d6ee_1001 conda-forge
ca-certificates 2021.10.8 h5b45459_0 conda-forge
certifi 2021.10.8 py39hcbf5309_1 conda-forge
cffi 1.14.6 py39h0878f49_0 conda-forge
chardet 4.0.0 py39hcbf5309_1 conda-forge
charset-normalizer 2.0.0 pyhd8ed1ab_0 conda-forge
click 7.1.2 pypi_0 pypi
colorama 0.4.4 pyh9f0ad1d_0 conda-forge
colorful 0.5.4 pypi_0 pypi
conda 4.10.3 py39hcbf5309_2 conda-forge
conda-package-handling 1.7.3 py39hb3671d1_0 conda-forge
cryptography 3.4.7 py39hd8d06c1_0 conda-forge
cycler 0.10.0 pypi_0 pypi
dataclasses 0.8 pyhc8e2a94_3 conda-forge
debugpy 1.4.1 py39h415ef7b_0 conda-forge
decorator 5.0.9 pyhd8ed1ab_0 conda-forge
defusedxml 0.7.1 pyhd8ed1ab_0 conda-forge
entrypoints 0.3 pyhd8ed1ab_1003 conda-forge
icu 68.2 h0e60522_0 conda-forge
idna 3.1 pyhd3deb0d_0 conda-forge
importlib-metadata 4.6.1 py39hcbf5309_0 conda-forge
ipykernel 6.0.3 py39h832f523_0 conda-forge
ipython 7.25.0 py39h832f523_1 conda-forge
ipython_genutils 0.2.0 py_1 conda-forge
jedi 0.18.0 py39hcbf5309_2 conda-forge
jinja2 3.0.1 pyhd8ed1ab_0 conda-forge
joblib 1.0.1 pypi_0 pypi
jpeg 9d h8ffe710_0 conda-forge
jsonschema 3.2.0 pyhd8ed1ab_3 conda-forge
jupyter_client 6.1.12 pyhd8ed1ab_0 conda-forge
jupyter_contrib_core 0.3.3 py_2 conda-forge
jupyter_contrib_nbextensions 0.5.1 pyhd8ed1ab_2 conda-forge
jupyter_core 4.7.1 py39hcbf5309_0 conda-forge
jupyter_highlight_selected_word 0.2.0 py39hcbf5309_1002 conda-forge
jupyter_latex_envs 1.4.6 pyhd8ed1ab_1002 conda-forge
jupyter_nbextensions_configurator 0.4.1 py39hcbf5309_2 conda-forge
jupyterlab_pygments 0.1.2 pyh9f0ad1d_0 conda-forge
kiwisolver 1.3.1 pypi_0 pypi
libclang 11.1.0 default_h5c34c98_1 conda-forge
libiconv 1.16 he774522_0 conda-forge
libpng 1.6.37 h1d00b33_2 conda-forge
libsodium 1.0.18 h8d14728_1 conda-forge
libxml2 2.9.12 hf5bbc77_0 conda-forge
libxslt 1.1.33 h65864e5_2 conda-forge
libzlib 1.2.11 h8ffe710_1013 conda-forge
llvmlite 0.36.0 pypi_0 pypi
lxml 4.6.3 py39h4fd7cdf_0 conda-forge
markupsafe 2.0.1 py39hb82d6ee_0 conda-forge
matplotlib 3.4.2 pypi_0 pypi
matplotlib-inline 0.1.2 pyhd8ed1ab_2 conda-forge
menuinst 1.4.17 py39hcbf5309_1 conda-forge
miniforge_console_shortcut 2.0 h57928b3_0 conda-forge
mistune 0.8.4 py39hb82d6ee_1004 conda-forge
mypy_extensions 0.4.3 py39hcbf5309_4 conda-forge
nbclient 0.5.3 pyhd8ed1ab_0 conda-forge
nbconvert 6.1.0 py39hcbf5309_0 conda-forge
nbformat 5.1.3 pyhd8ed1ab_0 conda-forge
nest-asyncio 1.5.1 pyhd8ed1ab_0 conda-forge
notebook 6.4.0 pyha770c72_0 conda-forge
nptyping 1.4.2 pypi_0 pypi
numba 0.53.1 pypi_0 pypi
numpy 1.21.1 pypi_0 pypi
openssl 1.1.1l h8ffe710_0 conda-forge
packaging 21.0 pyhd8ed1ab_0 conda-forge
pandas 1.3.1 pypi_0 pypi
pandoc 2.14.1 h8ffe710_0 conda-forge
pandocfilters 1.4.2 py_1 conda-forge
parso 0.8.2 pyhd8ed1ab_0 conda-forge
pathspec 0.9.0 pyhd8ed1ab_0 conda-forge
pickleshare 0.7.5 py_1003 conda-forge
pillow 8.3.1 pypi_0 pypi
pip 21.2.1 pyhd8ed1ab_0 conda-forge
platformdirs 2.3.0 pyhd8ed1ab_0 conda-forge
preload 2.2 pypi_0 pypi
prettyprinter 0.18.0 pypi_0 pypi
prometheus_client 0.11.0 pyhd8ed1ab_0 conda-forge
prompt-toolkit 3.0.19 pyha770c72_0 conda-forge
pycosat 0.6.3 py39hb82d6ee_1006 conda-forge
pycparser 2.20 pyh9f0ad1d_2 conda-forge
pygments 2.9.0 pyhd8ed1ab_0 conda-forge
pympler 0.9 pypi_0 pypi
pyopenssl 20.0.1 pyhd8ed1ab_0 conda-forge
pyparsing 2.4.7 pyh9f0ad1d_0 conda-forge
pyqt 5.12.3 py39hcbf5309_7 conda-forge
pyqt-impl 5.12.3 py39h415ef7b_7 conda-forge
pyqt5-sip 4.19.18 py39h415ef7b_7 conda-forge
pyqtchart 5.12 py39h415ef7b_7 conda-forge
pyqtwebengine 5.12.1 py39h415ef7b_7 conda-forge
pyrsistent 0.17.3 py39hb82d6ee_2 conda-forge
pysocks 1.7.1 py39hcbf5309_3 conda-forge
python 3.9.6 h7840368_1_cpython conda-forge
python-dateutil 2.8.2 pyhd8ed1ab_0 conda-forge
python_abi 3.9 2_cp39 conda-forge
pytz 2021.1 pypi_0 pypi
pywin32 300 py39hb82d6ee_0 conda-forge
pywinpty 1.1.3 py39h99910a6_0 conda-forge
pyyaml 6.0 py39hb82d6ee_0 conda-forge
pyzmq 22.1.0 py39he46f08e_0 conda-forge
qt 5.12.9 h5909a2a_4 conda-forge
regex 2021.10.23 py39hb82d6ee_1 conda-forge
requests 2.26.0 pyhd8ed1ab_0 conda-forge
ruamel_yaml 0.15.80 py39hb82d6ee_1004 conda-forge
scipy 1.7.0 pypi_0 pypi
seaborn 0.11.1 pypi_0 pypi
send2trash 1.7.1 pyhd8ed1ab_0 conda-forge
setuptools 49.6.0 py39hcbf5309_3 conda-forge
six 1.16.0 pyh6c4a22f_0 conda-forge
sqlite 3.36.0 h8ffe710_0 conda-forge
terminado 0.10.1 py39hcbf5309_0 conda-forge
testpath 0.5.0 pyhd8ed1ab_0 conda-forge
tomli 1.2.2 pyhd8ed1ab_0 conda-forge
tornado 6.1 py39hb82d6ee_1 conda-forge
tqdm 4.61.2 pyhd8ed1ab_1 conda-forge
traitlets 5.0.5 py_0 conda-forge
typed-ast 1.4.3 py39hb82d6ee_1 conda-forge
typing_extensions 3.10.0.2 pyha770c72_0 conda-forge
typish 1.9.2 pypi_0 pypi
tzdata 2021a he74cb21_1 conda-forge
ucrt 10.0.20348.0 h57928b3_0 conda-forge
urllib3 1.26.6 pyhd8ed1ab_0 conda-forge
vc 14.2 hb210afc_5 conda-forge
voltage-to-wiring-sim 0.1 dev_0 <develop>
vs2015_runtime 14.29.30037 h902a5da_5 conda-forge
wcwidth 0.2.5 pyh9f0ad1d_2 conda-forge
webencodings 0.5.1 py_1 conda-forge
wheel 0.36.2 pyhd3deb0d_0 conda-forge
win_inet_pton 1.1.0 py39hcbf5309_2 conda-forge
wincertstore 0.2 py39hcbf5309_1006 conda-forge
winpty 0.4.3 4 conda-forge
winshell 0.6 pypi_0 pypi
yaml 0.2.5 he774522_0 conda-forge
zeromq 4.3.4 h0e60522_0 conda-forge
zipp 3.5.0 pyhd8ed1ab_0 conda-forge
zlib 1.2.11 h8ffe710_1013 conda-forge