Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Miniature/spontaneous postsynaptic currents: Part 2

In part 1 we covered how to extract the mEPSCs or sEPSCs. In this chapter we will dive into a more rigorous analysis of PSCs as well as look at how the shape of a PSC effects their integration.

Source
from pathlib import Path

import numpy as np
import pandas as pd
from bokeh.io import output_notebook, show
from bokeh.layouts import column, row
from bokeh.models import ColumnDataSource, CustomJS, Select
from bokeh.plotting import figure
from scipy import stats

output_notebook()
Loading...
Loading...
url_path = Path().cwd().parent / "data"
pv = pd.read_csv(url_path / "pv/mini_data.csv")
msn = pd.read_csv(url_path / "msn/mini_data.csv")
dfs = {"PV": pv, "MSN": msn}
Source
columns = [
    "Est Tau (ms)",
    "Rise Time (ms)",
    "Amplitude (pA)",
    "Rise Rate (pA/ms)",
    "IEI (ms)",
]


def kde(data):
    min_val = min(data)
    max_val = max(data)
    padding = (max_val - min_val) * 0.1  # Add 10% padding
    grid_min = min_val - padding
    grid_max = max_val + padding
    grid_min = max(grid_min, 0)
    positions = np.linspace(grid_min, grid_max, num=124)
    kernel = stats.gaussian_kde(data)
    y = kernel(positions)
    return positions, y


source_dict = {key: {} for key in dfs.keys()}
for key, dataset in dfs.items():
    for i in columns:
        data = dataset[i].dropna()
        data = data[data != 0]
        positions, y = kde(data)
        source_dict[key][f"{i}_x_identity"] = positions
        source_dict[key][f"{i}_y_identity"] = y
        positions, y = kde(np.log10(data))
        source_dict[key][f"{i}_x_log"] = positions
        source_dict[key][f"{i}_y_log"] = y

    source_dict[key]["y"] = source_dict[key]["Amplitude (pA)_y_identity"]
    source_dict[key]["x"] = source_dict[key]["Amplitude (pA)_x_identity"]
    source_dict[key] = ColumnDataSource(source_dict[key])

Distributions of variables

Below we will look at the distribution of variables. Because you can usually get so many events you can get some very good distributions. One thing to note is all of our variables are bounded by from 0 to \infty. This means that log transforming the variables before grabbing the mean then exponentiating is recommended. However, nobody does this even though it is probably statistically more sound. You may also notice some bimodality in some of the measures. You can do things like fit a gaussian mixed model to the log transformed data then split the groups if the bimodality is not explained by some other variable like cell type, genotype, sex, etc.

Source
figs = []
for key, value in source_dict.items():
    fig = figure(height=250, width=350, title=key)
    line = fig.line(x="x", y="y", source=value, line_color="black")
    figs.append(fig)

menu = Select(title="Variables", value=columns[0], options=columns)
transform = Select(
    title="Transform",
    value="identity",
    options=["identity", "log"],
)

callback = CustomJS(
    args=dict(
        source=source_dict,
        keys=list(source_dict.keys()),
        menu=menu,
        transform=transform,
    ),
    code="""
    for (const item of keys) {
        source[item].data.y = source[item].data[`${menu.value}_y_${transform.value}`];
        source[item].data.x = source[item].data[`${menu.value}_x_${transform.value}`];
        source[item].change.emit();
    };
""",
)

menu.js_on_change("value", callback)
transform.js_on_change("value", callback)

show(obj=column(row(menu, transform), row(figs)))
Loading...
Loading...

Relationships between variables

Next we will look at whether there are correlations between variables.

figs = []
source_dict = {}
columns = ["Amplitude (pA)", "Est Tau (ms)", "Rise Time (ms)", "Rise Rate (pA/ms)"]
for key, value in dfs.items():
    temp_value = ColumnDataSource(value[columns])
    temp_value.data["x"] = temp_value.data[columns[0]].copy()
    temp_value.data["y"] = temp_value.data[columns[1]].copy()
    fig = figure(height=250, width=350, title=key)
    line = fig.scatter(x="x", y="y", source=temp_value, line_color="black")
    figs.append(fig)
    source_dict[key] = temp_value
menu1 = Select(title="X", value=columns[0], options=columns)
menu2 = Select(title="Y", value=columns[1], options=columns)
transform1 = Select(
    title="Transform x",
    value="identity",
    options=["identity", "log"],
)
transform2 = Select(
    title="Transform y",
    value="identity",
    options=["identity", "log"],
)

callback = CustomJS(
    args=dict(
        source=source_dict,
        keys=list(source_dict.keys()),
        menu1=menu1,
        menu2=menu2,
        transform2=transform2,
        transform1=transform1,
    ),
    code="""
    for (const item of keys) {
        let y = source[item].data[menu2.value].slice();
        let x = source[item].data[menu1.value].slice();
        if (transform2.value === "log") {
            y = y.map(value => Math.log(value));
        }
        if (transform1.value === "log") {
            x = x.map(value => Math.log(value));
        }
        source[item].data['y'] = y;
        source[item].data['x'] = x;
        source[item].change.emit();
    };
""",
)
menu1.js_on_change("value", callback)
menu2.js_on_change("value", callback)
transform1.js_on_change("value", callback)
transform2.js_on_change("value", callback)
show(obj=column(row(menu1, menu2), row(transform1, transform2), row(figs)))
Loading...
Loading...