In [201]:
import os
from importlib import reload
import numpy as np
import pandas as pd
from epitopepredict import plotting, base, peptutils, web, config
from epitopepredict import __version__
from IPython.display import HTML
import panel as pn
import panel.widgets as pnw
helppage = 'http://epitopepredict.readthedocs.io/en/latest/webapp.html'
css_file=(os.path.join(base.module_path,'static/custom.css'))
js_files = {'sortable': os.path.join(base.module_path,'static/sorttable.js')}
css=''.join(open(css_file,'r').readlines())
pn.extension(raw_css=[css])
pn.config.js_files=js_files
In [202]:
t = pn.widgets.TextInput()
m = pn.pane.Markdown("")
def callback(target, event):
target.object = '##' + event.new
t.link(m, callbacks={'value': callback})
t.value="hello"
pn.Row(t,m)
Out[202]:
In [203]:
html="""
<script type="text/javascript" src="%s"></script>
""" %os.path.join(base.module_path,'static/sorttable.js')
df=preds[0].data
res=df[:20].to_html(classes=['sortable'])
div = '<div class="scrollingArea">%s</div>' %res
pn.Column(pn.pane.HTML(html),pn.pane.HTML(div))
Out[203]:
In [ ]:
def predictions_dashboard(path):
"""Dashboard for viewing results from epitopepredict runs."""
#folder_input = pn.widgets.TextInput(name='path', value='../zaire_test', width=400,width_policy='fit')
#reload_btn = pn.widgets.Button(name='reload',width=100,button_type='primary')
names = web.get_file_lists(path)
if names is None:
return
preds = web.get_predictors(path,name=names[0])
print (preds)
seqname = pnw.Select(name='name', value=names[0], options=names)
cutoff_slider = pnw.FloatSlider(name='cutoff', value=.95,start=.75,end=.99,step=0.01)
cutoff_method = pnw.Select(name='cutoff method', value='default', options=['default','rank'])
n_select = pnw.FloatSlider(name='n',value=1,start=1,end=8,step=1)
plot_select = pnw.Select(name='plot view', value='tracks', options=['tracks', 'sequence'])
table_select = pnw.Select(name='table view', value='promiscuous', options=['promiscuous','binders'])
colorseq_box = pnw.Checkbox(name='color sequences', value=False)
header = pn.pane.Markdown('__total sequences: %s__' %len(names), css_classes=['main'])
tables = pn.Tabs(width=900)
plot = pn.pane.Bokeh(width=800)
debug = pn.pane.Markdown('test',style={'font-size': '10pt','background-color':'yellow'})
summary_plot = pn.pane.Bokeh()
summary_table_tabs = pn.Tabs()
recalc_button = pnw.Button(name='recalculate',width=200)
def update_banner():
"""Update the banner"""
fullpath = os.path.abspath(path)
banner = pn.Row(pn.pane.Markdown('<h4>epitopepredict: %s</h4> [help](%s) version %s' %(fullpath,helppage,__version__),
css_classes=['divheader'],
sizing_mode='stretch_width'))
return banner
def update_header(target, event):
names = web.get_file_lists(event.new)
target.object = "_total sequences: %s_" %str(len(names))
return
def callback_getpath(event):
path = os.path.getcwd()
folder.value = path
def update_plot(preds,name,cutoff,n,kind):
"""Plot data view"""
if kind == 'tracks':
p = plotting.bokeh_plot_tracks(preds,name=name,cutoff=cutoff,n=n,width=1000,title=name)
plot.object = p
elif kind == 'sequence':
p = bokeh_plot_sequence(preds,name=name,cutoff=cutoff,n=n,width=1000,
title=name,color_sequence=colorseq_box.value)
plot.object = p
return p
def update_tables(preds,name,n):
"""Tabular views of results"""
P = preds[0]
view = table_select.value
tables.clear()
for P in preds:
if view == 'promiscuous':
df = P.promiscuous_binders(n=n,name=name)
else:
df = P.get_binders(name=name)
res = df.to_html(classes="tinytable sortable")
div = '<div class="scrollingArea">%s</div>' %res
tables.append((P.name, div))
#tables.append((P.name,pn.pane.HTML('<p>hddsadsadsasda</p>',width=700)))
return
def update(event):
"""Update all elements"""
name = seqname.value
n = n_select.value
cutoff = cutoff_slider.value
kind = plot_select.value
debug.object = name
preds = web.get_predictors(path,name=name)
update_plot(preds,name=name,cutoff=cutoff,n=n,kind=kind)
update_tables(preds,name,n)
return
def update_summary(path):
"""Summary info for folder"""
data = web.get_summary_tables(path)
df = pd.concat(data, sort=True).reset_index()
#plot = plotting.bokeh_summary_plot(df)
#summary_plot.object = plot
summary_table_tabs.clear()
a = web.aggregate_summary(data)
div = web.get_scrollable_table(a)
summary_table_tabs.append(('all', div))
names = list(data.keys())
for n in names:
df = data[n]
res = df.to_html(classes="tinytable sortable")
div = '<div class="scrollingArea">%s</div>' %res
summary_table_tabs.append((n, div))
return
@pn.depends(seqname.param.value,n_select.param.value)
def download_link(name,n):
if preds is None:
return
df = preds[0].promiscuous_binders(n=n,name=name)
df.to_csv()
return pn.Pane(HTML('<a>download</a>'),width=700)
info = pn.pane.Markdown(web.get_readme())
banner = update_banner()
update_summary(path)
#reload_btn.param.watch(load_predictors, 'clicks')
#reload_btn.param.trigger()
seqname.param.watch(update, 'value')
cutoff_slider.param.watch(update, 'value')
n_select.param.watch(update, 'value')
table_select.param.watch(update, 'value')
plot_select.param.watch(update, 'value')
seqname.param.trigger('options', 'value')
top = pn.Row(header)#,download_link)
left = pn.Column(plot,tables,margin=10,sizing_mode='stretch_width')
right = pn.Column(seqname,cutoff_slider,cutoff_method,n_select,plot_select,
table_select,colorseq_box,css_classes=['widget-box'],width=200)
center = pn.Row(left,right)
#bottom = pn.Row(table)
main = pn.Column(top,center)
summarypane = pn.Column(recalc_button,(pn.Row(summary_table_tabs)))
tabs = pn.Tabs(('summary', summarypane),('sequence',main),('about',info))
#tabs.append()
app = pn.Column(banner,tabs, sizing_mode='stretch_width')
return app
reload(web)
reload(plotting)
path = '../zaire_test/'
#path= '../results_malaria/'
app = predictions_dashboard(path)
app
In [304]:
path='../zaire_test'
#path='../results_malaria'
names = web.get_file_lists(path)
name=names[5]
preds = web.get_predictors(path,name=name)
preds
Out[304]:
In [314]:
def bokeh_plot_sequence(preds, name=None, n=2, cutoff=.95, cutoff_method='default',
width=1000, color_sequence=False, title=''):
"""Plot sequence view of binders """
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, LinearAxis, Grid, Range1d, Text, Rect, CustomJS, Slider, RangeSlider, FactorRange
from bokeh.layouts import gridplot, column
colors = []
seqs = []
text = []
alleles = []
ylabels = []
pcolors = plotting.get_bokeh_colors()
for P in preds:
print (P.name)
df = P.data
#get sequence from results dataframe
seq = base.sequence_from_peptides(df)
l = base.get_length(df)
b = P.get_binders(name=name, cutoff=cutoff, cutoff_method=cutoff_method)
pb = P.promiscuous_binders(name=name, cutoff=cutoff, n=n, cutoff_method=cutoff_method)
b = b[b.pos.isin(pb.pos)] #only promiscuous
grps = b.groupby('allele')
al = list(grps.groups)
alleles.extend(al)
ylabels.extend([P.name+' '+i for i in al])
currseq=[seq for i in al]
seqs.extend(currseq)
t = [i for s in currseq for i in s]
text.extend(t)
print (len(seqs),len(text))
for a in al:
pos=[]
f = list(b[b.allele==a].pos)
for i in f:
pos.extend(np.arange(i,i+l))
if color_sequence is True:
c = plotting.get_sequence_colors(seq)
else:
c = ['white' for i in seq]
for i in pos:
c[i] = pcolors[P.name]
colors.extend(c)
#put into columndatasource for plotting
N = len(seqs[0])
S = len(alleles)
x = np.arange(1, N+1)
y = np.arange(0,S,1)
xx, yy = np.meshgrid(x, y)
gx = xx.ravel()
gy = yy.flatten()
recty = gy+.5
source = ColumnDataSource(dict(x=gx, y=gy, recty=recty, text=text, colors=colors))
plot_height = len(seqs)*15+60
x_range = Range1d(0,N+1, bounds='auto')
L=100
if len(seq)<100:
L=len(seq)
view_range = (0,L)
viewlen = view_range[1]-view_range[0]
fontsize="8.5pt"
tools="xpan, reset, save"
p = figure(title=title, plot_width=width, plot_height=plot_height, x_range=view_range, y_range=ylabels, tools=tools,
min_border=0, sizing_mode='stretch_both', lod_factor=10, lod_threshold=1000)
seqtext = Text(x="x", y="y", text="text", text_align='center',text_color="black",
text_font="monospace", text_font_size=fontsize)
rects = Rect(x="x", y="recty", width=1, height=1, fill_color="colors", line_color='gray', fill_alpha=0.6)
p.add_glyph(source, rects)
p.add_glyph(source, seqtext)
p.xaxis.major_label_text_font_style = "bold"
p.grid.visible = False
p.toolbar.logo = None
#preview view (no text)
p1 = figure(title=None, plot_width=width, plot_height=S*3+5, x_range=x_range, y_range=(0,S), tools=[],
min_border=0, sizing_mode='stretch_width', lod_factor=10, lod_threshold=10)
rects = Rect(x="x", y="recty", width=1, height=1, fill_color="colors", line_color=None, fill_alpha=0.6)
previewrect = Rect(x=viewlen/2,y=S/2, width=viewlen, height=S*.99, line_color='darkblue', fill_color=None)
p1.add_glyph(source, rects)
p1.add_glyph(source, previewrect)
p1.yaxis.visible = False
p1.grid.visible = False
p1.toolbar_location = None
#callback for slider move
jscode="""
var start = cb_obj.value[0];
var end = cb_obj.value[1];
x_range.setv({"start": start, "end": end})
rect.width = end-start;
rect.x = start+rect.width/2;
var fac = rect.width/width;
console.log(fac);
if (fac>=.14) { fontsize = 0;}
else { fontsize = 8.5; }
text.text_font_size=fontsize+"pt";
"""
callback = CustomJS(
args=dict(x_range=p.x_range,rect=previewrect,text=seqtext,width=p.plot_width), code=jscode)
slider = RangeSlider (start=0, end=N, value=(0,L), step=10, callback_policy="throttle")
slider.js_on_change('value_throttled', callback)
#callback for plot drag
jscode="""
start = parseInt(range.start);
end = parseInt(range.end);
slider.value[0] = start;
rect.width = end-start;
rect.x = start+rect.width/2;
"""
p.x_range.callback = CustomJS(args=dict(slider=slider, range=p.x_range, rect=previewrect),
code=jscode)
p = gridplot([[p1],[p],[slider]], toolbar_location="below", merge_tools=False)
return p
reload(plotting)
p = bokeh_plot_sequence(preds, n=2, title=name)#, color_sequence=True)
pn.pane.Bokeh(p, width=1400)
Out[314]:
In [ ]:
data = web.get_summary_tables(path)
def aggregate_summary(data):
X = pd.concat(data).reset_index().rename(columns={'level_0':'predictor'})
a = pd.pivot_table(X,index=['locus_tag','length'],columns=['predictor'],values=['clusters','binders','binder_density']).reset_index()
a = a.fillna('-')
return a
a = aggregate_summary(data)
print (a)
In [ ]:
def summ_plot(df, height=400):
from bokeh.models import ColumnDataSource, LinearColorMapper
from bokeh.plotting import figure
from bokeh.models.glyphs import Text, Rect, Circle
from bokeh.transform import transform
source = ColumnDataSource(data=df)
colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce", "#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
mapper = LinearColorMapper(palette=colors, low=df.binders.min(), high=df.binders.max())
text_props = {"text_align": "left", "text_baseline": "middle", "text_font": "18"}
tools = "pan,wheel_zoom,hover,reset,save"
prednames = list(df.predictor.unique())
names = list(df.name.unique())
p = figure(plot_height=height,tools=tools,x_range=prednames,y_range=names)
hm = Rect(x='predictor', y='name',fill_color=transform('binders', mapper), width=1, height=1)
r = Text(x='predictor', y="name", text="top_peptide", **text_props)
p.add_glyph(source, hm)
p.add_glyph(source, r)
p.toolbar.logo = None
return p
X = pd.concat(data).reset_index().rename(columns={'level_0':'predictor'})
print (X[:2])
p=summ_plot(X)
#pn.pane.Bokeh(p)
In [174]:
reload(plotting)
p = plotting.bokeh_plot_tracks(preds, width=1000, height=400, cutoff=.95, title='test')
pn.pane.Bokeh(p)
Out[174]:
In [ ]:
def bokeh_test(n=20,height=400):
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.models.glyphs import Text, Rect, Circle
data = {'x_values': np.random.random(n),
'y_values': np.random.random(n)}
source = ColumnDataSource(data=data)
tools = "pan,wheel_zoom,hover,tap,reset,save"
p = figure(plot_height=height,tools=tools)
#c = Circle(x='x_values', y='y_values', radius=.02, line_color='black', fill_color='blue', fill_alpha=.6)
c=p.circle(x='x_values', y='y_values', radius=.02, line_color='black', fill_color='blue', fill_alpha=.6, source=source)
#p.add_glyph(source, c)
return p
reload(plotting)
#s = pn.pane.Str('aas')
s = pnw.IntSlider(start=1,end=10,value=1)
p = bokeh_test(n=50)
pp = pn.panel(p)
#s.jslink(c.glyph, value='line_width')
#pp.link(s, callbacks={'xrange.start': callback})
#pp.jslink(s, **{'x': 'value'})
#p.js_on_event('tap', code)
pn.Row(s, pp)
In [31]:
template = """
{% extends base %}
<!-- goes in body -->
{% block postamble %}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="/home/damien/gitprojects/epitopepredict/epitopepredict/static/custom.css">
{% endblock %}
<!-- goes in body -->
{% block contents %}
<h1>epitopepredict app</h1>
<p>This a test.</p>
<br>
<div>
<div class="row">
<div class="col-sm">
{{ embed(roots.A) }}
</div>
</div>
</div>
{% endblock %}
"""
In [32]:
tmpl = pn.Template(template)
tmpl.add_panel('A', app)
tmpl.servable()
Out[32]:
In [ ]: