Neurons example via low-level, flexible interface

Prepare

from bayes_window import models
from bayes_window.fitting import fit_numpyro
from bayes_window.generative_models import generate_fake_spikes
import numpy as np
from sklearn.preprocessing import LabelEncoder

trans = LabelEncoder().fit_transform

Make some data

df, df_monster, index_cols, firing_rates = generate_fake_spikes(n_trials=2,
                                                                n_neurons=8,
                                                                n_mice=4,
                                                                dur=7, )


# df['log_isi'] = np.log10(df['isi'])

from bayes_window import visualization, utils
from importlib import reload

reload(visualization)
reload(utils)
y = 'isi'
ddf, dy = utils.make_fold_change(df,
                                 y=y,
                                 index_cols=('stim', 'mouse', 'neuron'),
                                 treatment_name='stim',
                                 do_take_mean=True)

visualization.plot_data(x='neuron', y=dy, color='mouse',  df=ddf)[0]

TODO leave axis labels here somehow

Estimate model

# y = list(set(df.columns) - set(index_cols))[0]
trace = fit_numpyro(y=df[y].values,
                    treatment=(df['stim']).astype(int).values,
                    condition=trans(df['neuron']),
                    group=trans(df['mouse']),
                    progress_bar=True,
                    model=models.model_hierarchical,
                    n_draws=100, num_chains=1, )
2021-11-25 04:25:17.115875: E external/org_tensorflow/tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_COMPAT_NOT_SUPPORTED_ON_DEVICE: forward compatibility was attempted on non supported HW
  0%|          | 0/1100 [00:00<?, ?it/s]
warmup:   0%|          | 1/1100 [00:06<1:50:32,  6.03s/it, 7 steps of size 3.98e-02. acc. prob=1.00]
warmup:   4%|▎         | 40/1100 [00:06<01:55,  9.18it/s, 1023 steps of size 6.91e-03. acc. prob=0.97]
warmup:   6%|▌         | 68/1100 [00:06<00:57, 17.83it/s, 1023 steps of size 9.05e-03. acc. prob=0.98]
warmup:   9%|▉         | 98/1100 [00:06<00:33, 30.15it/s, 1023 steps of size 9.00e-03. acc. prob=0.98]
warmup:  12%|█▏        | 130/1100 [00:06<00:20, 47.07it/s, 1023 steps of size 2.11e-02. acc. prob=0.98]
warmup:  16%|█▋        | 179/1100 [00:06<00:11, 81.24it/s, 255 steps of size 1.66e-02. acc. prob=0.98] 
warmup:  24%|██▍       | 265/1100 [00:06<00:05, 158.51it/s, 255 steps of size 1.21e-02. acc. prob=0.99]
warmup:  32%|███▏      | 351/1100 [00:06<00:03, 245.60it/s, 255 steps of size 1.32e-02. acc. prob=0.99]
warmup:  38%|███▊      | 414/1100 [00:06<00:02, 297.07it/s, 1023 steps of size 4.78e-03. acc. prob=0.99]
warmup:  43%|████▎     | 475/1100 [00:06<00:01, 335.91it/s, 511 steps of size 7.81e-03. acc. prob=0.99] 
warmup:  51%|█████▏    | 564/1100 [00:07<00:01, 442.06it/s, 383 steps of size 1.19e-02. acc. prob=0.99]
warmup:  60%|█████▉    | 656/1100 [00:07<00:00, 544.85it/s, 255 steps of size 1.02e-02. acc. prob=0.99]
warmup:  67%|██████▋   | 735/1100 [00:07<00:00, 601.48it/s, 255 steps of size 9.83e-03. acc. prob=0.99]
warmup:  76%|███████▌  | 836/1100 [00:07<00:00, 702.86it/s, 511 steps of size 1.09e-02. acc. prob=0.99]
warmup:  84%|████████▍ | 926/1100 [00:07<00:00, 753.16it/s, 511 steps of size 1.09e-02. acc. prob=0.99]
sample:  92%|█████████▏| 1014/1100 [00:07<00:00, 787.23it/s, 511 steps of size 1.08e-02. acc. prob=0.99]
sample: 100%|██████████| 1100/1100 [00:07<00:00, 800.16it/s, 255 steps of size 1.08e-02. acc. prob=0.99]
sample: 100%|██████████| 1100/1100 [00:07<00:00, 143.05it/s, 255 steps of size 1.08e-02. acc. prob=0.99]

Add data back

# reload(utils)
# df_both, trace = utils.add_data_to_posterior(df, posterior=trace.posterior, y=y,
#                                              fold_change_index_cols=['neuron', 'stim', 'mouse_code', ],
#                                              treatment_name='stim', b_name='slope_per_condition',
#                                              posterior_index_name='neuron', group_name='mouse')
#
# + [markdown] hideCode=false hidePrompt=false
# # ## Plot data and posterior
#
# + hideCode=false hidePrompt=false
# # BayesWindow.regression_charts(df_both, y=f'{y} diff', x='neuron',color='mouse_code',title=y,hold_for_facet=False,add_box=False)
# reload(visualization)
#
# chart_d, _ = visualization.plot_data(df=df_both, x='neuron', y=f'{y} diff', color='mouse_code', highlight=False)
# chart_d
#
# + hideCode=false hidePrompt=false
# chart_p = visualization.plot_posterior(df=df_both, title=f'd_{y}', x='neuron', )
# chart_p
#
# + hideCode=false hidePrompt=false
# (chart_d + chart_p).resolve_scale(y='independent')
#
# + hideCode=false hidePrompt=false
# (chart_d + chart_p).facet(column='neuron')

Appendix: Elements of interactivity (WIP)

import altair as alt
y='isi'
color='mouse'
x='neuron'

base=alt.Chart(df).encode(
            x=x,
            color=f'{color}',
            y=alt.Y(f'mean({y})',
                    scale=alt.Scale(zero=False,
                                    domain=list(np.quantile(df[y], [.05, .95])))),
)
highlight = alt.selection(type='single', on='mouseover',
                          fields=[color], nearest=True)


lines=base.mark_line(clip=True, fill=None, opacity=.6, ).encode(
            size=alt.condition(~highlight, alt.value(1), alt.value(3))
        )
points = base.mark_circle().encode(
    opacity=alt.value(0),
    #axis=alt.Axis(labels=False, tickCount=0, title='')
).add_selection(
    highlight
)

lines+points
import altair as alt
y='isi'
color='mouse'
x='neuron'

base=alt.Chart(df).encode(
            x=x,
            color=f'{color}',
            y=alt.Y(f'mean({y})',
                    scale=alt.Scale(zero=False,
                                    domain=list(np.quantile(df[y], [.05, .95])))),
)

# Create a selection that chooses the nearest point & selects based on x-value
nearest = alt.selection(type='single', nearest=True, on='mouseover',
                        fields=[x], empty='none')


# Transparent selectors across the chart. This is what tells us
# the x-value of the cursor
selectors = alt.Chart(df).mark_point().encode(
    x=x,
    opacity=alt.value(0),
).add_selection(
    nearest
)

highlight = alt.selection(type='single', on='mouseover',
                          fields=[color], nearest=True)

lines=base.mark_line(clip=True, fill=None, opacity=.6, ).encode(
            #tooltip=color,
            size=alt.condition(~highlight, alt.value(1), alt.value(3))
        )

# Draw text labels near the points, and highlight based on selection
text = lines.mark_text(align='left', dx=5, dy=-5).encode(
    text=alt.condition(nearest, y, alt.value(' '))
)

points = base.mark_circle().encode(
    opacity=alt.value(0)
).add_selection(
    highlight
)

alt.layer(
    lines, selectors, points, text
)