Compare antibody neutralization values¶
Compare neutralization values for COV2-2130 and 2130-1-0114-112 antibodies
Import Python modules:
[1]:
import os
import pickle
import altair as alt
import pandas as pd
from functools import reduce
import yaml
Read configuration:
[2]:
with open("config.yaml") as f:
config = yaml.safe_load(f)
[3]:
antibodies = ['COV2-2130','2130-1-0114-112']
Now get the averaged polyclonal
model fits:
[4]:
neutralization = []
for antibody in antibodies:
with open(os.path.join(config["escape_dir"], f"{antibody}.pickle"), "rb") as f:
model = pickle.load(f)
with open(os.path.join(config["escape_dir"], f"{antibody}_avg.csv"), "rb") as h:
variants_df = pd.read_csv(h)
variants_df['aa_substitutions'] = variants_df['mutation']
variants_df = variants_df.filter(['aa_substitutions', 'times_seen'], axis=1)
variants_df['antibody'] = antibody
model.icXX(variants_df)
neutralization.append(model.icXX(variants_df))
[5]:
neutralization = reduce(lambda x, y: pd.merge(x, y, on = 'aa_substitutions',
suffixes=('_COV2-2130', '_2130-1-0114-112')), neutralization)
[6]:
#read in functional effects
func_effect = pd.read_csv(config["muteffects_observed"])
func_effect['aa_substitutions'] = func_effect['wildtype'] + func_effect['reference_site'].astype(str) + func_effect['mutant']
func_effect
func_effect = func_effect[['aa_substitutions', 'effect']].copy()
neutralization = pd.merge(neutralization, func_effect,
how='left',
on=['aa_substitutions']
)
[7]:
#filter for replicates, times_seen and functional effects
neutralization = neutralization.loc[(neutralization['n_models_COV2-2130'] >= 2) & (neutralization['n_models_2130-1-0114-112'] >= 2)]
neutralization = neutralization.loc[(neutralization['times_seen_COV2-2130'] >= 3) & (neutralization['times_seen_2130-1-0114-112'] >= 3)]
neutralization = neutralization.loc[(neutralization['effect'] >= -1.38)]
[8]:
#remove some excess columns
neutralization.drop(['antibody_COV2-2130', 'antibody_2130-1-0114-112',
'n_models_COV2-2130', 'frac_models_COV2-2130',
'n_models_2130-1-0114-112', 'frac_models_2130-1-0114-112' ], axis=1, inplace=True)
Now plot the results. We will plot the median IC50s across the replicate polyclonal
fits for each antibody. This is an interactive plot that you can mouse over for details:
[9]:
corr_chart = (
alt.Chart(neutralization)
.encode(
x=alt.X(
"median_IC50_COV2-2130",
title="COV2-2130 IC50 (arbitrary units)",
scale=alt.Scale(type="log", domainMax=1000, domainMin = 0.003),
),
y=alt.Y(
"median_IC50_2130-1-0114-112",
title="2130-1-0114-112 IC50 (arbitrary units)",
scale=alt.Scale(type="log", domainMax=1000, domainMin = 0.003),
),
tooltip=[
alt.Tooltip(c, format=".3g") if neutralization[c].dtype == float
else c
for c in neutralization.columns.tolist()
],
)
.mark_circle(filled=True, size=60, opacity=0.3)
.configure_axis(grid=False)
.resolve_scale(y="independent", x="independent")
.properties(width=300, height=300)
)
corr_chart
[9]:
[ ]: