In [1]:
# PyABC imports
from pyabc import (ABCSMC, Distribution, RV,
History, MedianEpsilon)
from pyabc.populationstrategy import AdaptivePopulationSize
from pyabc.epsilon import MedianEpsilon
from pyabc.sampler import MulticoreEvalParallelSampler
In [2]:
# Custom imports
from ionchannelABC import (ion_channel_sum_stats_calculator,
IonChannelAcceptor,
IonChannelDistance,
EfficientMultivariateNormalTransition,
calculate_parameter_sensitivity,
plot_parameter_sensitivity,
plot_regression_fit)
In [3]:
# Other necessary imports
import numpy as np
import subprocess
import pandas as pd
import io
import os
import tempfile
In [4]:
# Plotting imports
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
%config Inline.Backend.figure_format = 'retina'
In [5]:
from channels.icat_generic import icat as model
test = model.sample({})
In [6]:
measurements = model.get_experiment_data()
obs = measurements.to_dict()['y']
exp = measurements.to_dict()['exp']
errs = measurements.to_dict()['errs']
In [24]:
limits = dict(g_CaT=(0, 2),
v_offset=(0, 500),
Vhalf_b=(-100, 100),
k_b=(0, 10),
c_bb=(0, 10),
c_ab=(0, 100),
sigma_b=(0, 100),
Vmax_b=(-100, 100),
Vhalf_g=(-100, 100),
k_g=(-10, 0),
c_bg=(0, 50),
c_ag=(0, 500),
sigma_g=(0, 100),
Vmax_g=(-100, 100))
prior = Distribution(**{key: RV("uniform", a, b - a)
for key, (a,b) in limits.items()})
In [ ]:
In [8]:
distance_fn=IonChannelDistance(
obs=obs,
exp_map=exp,
err_bars=errs,
err_th=0.1)
In [9]:
parameters = ['icat.'+k for k in limits.keys()]
In [10]:
fitted, regression_fit, r2 = calculate_parameter_sensitivity(
model,
parameters,
distance_fn,
sigma=0.05,
n_samples=1000)
In [11]:
sns.set_context('talk')
grid = plot_parameter_sensitivity(fitted, plot_cutoff=0.05)
In [12]:
grid.savefig('results/icat-generic/sensitivity.pdf')
In [13]:
grid2 = plot_regression_fit(regression_fit, r2)
In [14]:
grid2.savefig('results/icat-generic/sensitivity_fit.pdf')
In [17]:
from ionchannelABC import plot_distance_weights
grid = plot_distance_weights(model, distance_fn)
In [18]:
grid.savefig('results/icat/dist_weights.pdf')
In [31]:
db_path = ("sqlite:///" +
os.path.join(tempfile.gettempdir(), "hl-1_icat-generic.db"))
print(db_path)
In [32]:
# Let's log all the sh!t
import logging
logging.basicConfig()
abc_logger = logging.getLogger('ABC')
abc_logger.setLevel(logging.DEBUG)
eps_logger = logging.getLogger('Epsilon')
eps_logger.setLevel(logging.DEBUG)
cv_logger = logging.getLogger('CV Estimation')
cv_logger.setLevel(logging.DEBUG)
In [33]:
from pyabc.populationstrategy import ConstantPopulationSize
In [34]:
abc = ABCSMC(models=model,
parameter_priors=prior,
distance_function=IonChannelDistance(
obs=obs,
exp_map=exp,
err_bars=errs,
err_th=0.1),
population_size=ConstantPopulationSize(1000),
#population_size=AdaptivePopulationSize(
# start_nr_particles=1000,
# mean_cv=0.2,
# max_population_size=1000,
# min_population_size=100),
summary_statistics=ion_channel_sum_stats_calculator,
transitions=EfficientMultivariateNormalTransition(),
eps=MedianEpsilon(),
sampler=MulticoreEvalParallelSampler(n_procs=12),
acceptor=IonChannelAcceptor())
In [35]:
abc_id = abc.new(db_path, obs)
In [36]:
history = abc.run(minimum_epsilon=0.1, max_nr_populations=30, min_acceptance_rate=0.01)
In [ ]:
history = abc.run(minimum_epsilon=0.1, max_nr_populations=30, min_acceptance_rate=0.01)
In [91]:
limits = dict(g_CaT=(0, 2),
v_offset=(0, 500),
Vhalf_b=(-100, 100),
k_b=(0, 10),
c_bb=(0, 10),
c_ab=(0, 100),
sigma_b=(0, 100),
Vmax_b=(-100, 100),
Vhalf_g=(-100, 100),
k_g=(-10, 0),
c_bg=(0, 50),
c_ag=(0, 1000), # increased 500 -> 1000
sigma_g=(0, 100),
Vmax_g=(-100, 100))
prior = Distribution(**{key: RV("uniform", a, b - a)
for key, (a,b) in limits.items()})
In [92]:
abc_continued = ABCSMC(models=model,
parameter_priors=prior,
distance_function=IonChannelDistance(
obs=obs,
exp_map=exp,
err_bars=errs,
err_th=0.1),
population_size=ConstantPopulationSize(1000),
#population_size=AdaptivePopulationSize(
# start_nr_particles=1000,
# mean_cv=0.2,
# max_population_size=1000,
# min_population_size=100),
summary_statistics=ion_channel_sum_stats_calculator,
transitions=EfficientMultivariateNormalTransition(),
eps=MedianEpsilon(),
sampler=MulticoreEvalParallelSampler(n_procs=12),
acceptor=IonChannelAcceptor())
In [94]:
abc_continued.load(db_path, 1)
Out[94]:
In [95]:
abc_continued.run(minimum_epsilon=0.1, max_nr_populations=30, min_acceptance_rate=0.01)
Out[95]:
In [19]:
history = History('sqlite:////storage/hhecm/cellrotor/chouston/results/icat-generic/hl-1_icat-generic.db')
#history = History('sqlite:////storage/hhecm/cellrotor/chouston/results/convergence/icat-generic/hl-1_icat3000.db')
#history = History('sqlite:////scratch/cph211/ion-channel-ABC/docs/examples/results/icat-generic/hl-1_icat-generic.db')
history.all_runs()
Out[19]:
In [20]:
#history.id = 5 # with v offset
history.id = 1
In [21]:
sns.set_context('talk')
In [22]:
df, w = history.get_distribution(m=0)
In [23]:
df.describe()
Out[23]:
In [13]:
#df2 = df
#df2['weight'] = w
#df_melt = df2.melt(value_vars=df2.columns[:-1],id_vars='weight')
In [14]:
#sns.relplot(x='value',y='weight',row='name',data=df_melt,facet_kws={'sharex': False, 'sharey': False})
In [25]:
from ionchannelABC import plot_parameters_kde
g = plot_parameters_kde(df, w, limits,aspect=12,height=0.6)
In [65]:
g.savefig('results/icat-generic/parameters_kde.pdf')
In [26]:
evolution = history.get_all_populations()
g = sns.relplot(x='t', y='epsilon', size='samples', data=evolution[evolution.t>=0])
#g.savefig('results/icat-generic/eps_evolution.pdf')
In [27]:
# Generate parameter samples
n_samples = 100
df, w = history.get_distribution(m=0)
th_samples = df.sample(n=n_samples, weights=w, replace=True).to_dict(orient='records')
In [28]:
# Generate sim results samples
samples = pd.DataFrame({})
for i, th in enumerate(th_samples):
output = model.sample(pars=th, n_x=50)
output['sample'] = i
output['distribution'] = 'post'
samples = samples.append(output, ignore_index=True)
In [29]:
from ionchannelABC import plot_sim_results
sns.set_context('talk')
g = plot_sim_results(samples, obs=measurements)
# Set axis labels
xlabels = ["voltage, mV", "voltage, mV", "voltage, mV", "time, ms", "time, ms","voltage, mV"]
ylabels = ["current density, pA/pF", "activation", "inactivation", "recovery", "normalised current","current density, pA/pF"]
for ax, xl in zip(g.axes.flatten(), xlabels):
ax.set_xlabel(xl)
for ax, yl in zip(g.axes.flatten(), ylabels):
ax.set_ylabel(yl)
In [70]:
g.savefig('results/icat-generic/icat_sim_results.pdf')
In [71]:
def plot_sim_results_all(samples: pd.DataFrame):
with sns.color_palette("gray"):
grid = sns.relplot(x='x', y='y',
col='exp',
units='sample',
kind='line',
data=samples,
estimator=None, lw=0.5,
alpha=0.5,
#estimator=np.median,
facet_kws={'sharex': 'col',
'sharey': 'col'})
return grid
In [72]:
grid2 = plot_sim_results_all(samples)
In [73]:
grid2.savefig('results/icat-generic/icat_sim_results_all.pdf')
In [74]:
# Mean current density
print(np.mean(samples[samples.exp==0].groupby('sample').min()['y']))
# Std current density
print(np.std(samples[samples.exp==0].groupby('sample').min()['y']))
In [75]:
import scipy.stats as st
peak_current = samples[samples['exp']==0].groupby('sample').min()['y'].tolist()
rv = st.rv_discrete(values=(peak_current, [1/len(peak_current),]*len(peak_current)))
In [76]:
print("median: {}".format(rv.median()))
print("95% CI: {}".format(rv.interval(0.95)))
In [77]:
# Voltage of peak current density
idxs = samples[samples.exp==0].groupby('sample').idxmin()['y']
print("mean: {}".format(np.mean(samples.iloc[idxs]['x'])))
print("STD: {}".format(np.std(samples.iloc[idxs]['x'])))
In [78]:
voltage_peak = samples.iloc[idxs]['x'].tolist()
rv = st.rv_discrete(values=(voltage_peak, [1/len(voltage_peak),]*len(voltage_peak)))
print("median: {}".format(rv.median()))
print("95% CI: {}".format(rv.interval(0.95)))
In [79]:
# Half activation potential
# Fit of activation to Boltzmann equation
from scipy.optimize import curve_fit
grouped = samples[samples['exp']==1].groupby('sample')
def fit_boltzmann(group):
def boltzmann(V, Vhalf, K):
return 1/(1+np.exp((Vhalf-V)/K))
guess = (-30, 10)
popt, _ = curve_fit(boltzmann, group.x, group.y)
return popt
output = grouped.apply(fit_boltzmann).apply(pd.Series)
In [80]:
print(np.mean(output))
print(np.std(output))
In [81]:
Vhalf = output[0].tolist()
rv = st.rv_discrete(values=(Vhalf, [1/len(Vhalf),]*len(Vhalf)))
print("median: {}".format(rv.median()))
print("95% CI: {}".format(rv.interval(0.95)))
In [82]:
slope = output[1].tolist()
rv = st.rv_discrete(values=(slope, [1/len(slope),]*len(slope)))
print("median: {}".format(rv.median()))
print("95% CI: {}".format(rv.interval(0.95)))
In [83]:
# Half activation potential
grouped = samples[samples['exp']==2].groupby('sample')
def fit_boltzmann(group):
def boltzmann(V, Vhalf, K):
return 1-1/(1+np.exp((Vhalf-V)/K))
guess = (-100, 10)
popt, _ = curve_fit(boltzmann, group.x, group.y,
bounds=([-100, 1], [0, 30]))
return popt
output = grouped.apply(fit_boltzmann).apply(pd.Series)
In [84]:
print(np.mean(output))
print(np.std(output))
In [85]:
Vhalf = output[0].tolist()
rv = st.rv_discrete(values=(Vhalf, [1/len(Vhalf),]*len(Vhalf)))
print("median: {}".format(rv.median()))
print("95% CI: {}".format(rv.interval(0.95)))
In [86]:
slope = output[1].tolist()
rv = st.rv_discrete(values=(slope, [1/len(slope),]*len(slope)))
print("median: {}".format(rv.median()))
print("95% CI: {}".format(rv.interval(0.95)))
In [87]:
# Recovery time constant
grouped = samples[samples.exp==3].groupby('sample')
def fit_single_exp(group):
def single_exp(t, I_max, tau):
return I_max*(1-np.exp(-t/tau))
guess = (1, 50)
popt, _ = curve_fit(single_exp, group.x, group.y, guess)
return popt[1]
output = grouped.apply(fit_single_exp)
In [88]:
print(np.mean(output))
print(np.std(output))
In [89]:
tau = output.tolist()
rv = st.rv_discrete(values=(tau, [1/len(tau),]*len(tau)))
print("median: {}".format(rv.median()))
print("95% CI: {}".format(rv.interval(0.95)))
In [ ]: