## Copyright (c) 2022-2024 ScreenPro2 Development Team.
## All rights reserved.
## Gilbart Lab, UCSF / Arc Institute.
## Multi-Omics Tech Center, Arc Insititue.
import numpy as np
import pandas as pd
import bokeh
import bokeh.plotting
[docs]class DataDashboard:
def __init__(self):
pass
def _new_plot(self,title,tooltips,width,height,toolbar_location):
TOOLS = "box_select,box_zoom,lasso_select,reset,save,wheel_zoom,pan,copy,undo,redo,reset,examine,fullscreen"
# create a new plot with a specific size
p = bokeh.plotting.figure(
sizing_mode="stretch_width",
tools=TOOLS,
tooltips=tooltips,
toolbar_location=toolbar_location,
title=title,
max_width=width, height=height,
)
p.toolbar.autohide = True
return p
def _get_html(self, p):
html = bokeh.embed.file_html(p, bokeh.resources.CDN, "")
return html
[docs]class DrugScreenDashboard(DataDashboard):
def __init__(self, screen, treated, untreated, t0='T0', threshold=3, ctrl_label='negative_control',run_name='auto'):
self.screen = screen
self.threshold = threshold
self.ctrl_label = ctrl_label
self.run_name = run_name
self.gamma_score_name = f'gamma:{untreated}_vs_{t0}'
self.rho_score_name = f'rho:{treated}_vs_{untreated}'
self.plots = {}
super().__init__()
def _prep_data(self,screen, score_col='score', pvalue_col='pvalue'):
gamma = screen.getPhenotypeScores(
run_name=self.run_name,
score_name=self.gamma_score_name,
threshold=self.threshold,
ctrl_label=self.ctrl_label,
score_col=score_col,
pvalue_col=pvalue_col
)
rho = screen.getPhenotypeScores(
run_name=self.run_name,
score_name=self.rho_score_name,
threshold=self.threshold,
ctrl_label=self.ctrl_label,
score_col=score_col,
pvalue_col=pvalue_col
)
df = pd.DataFrame({
'target': rho['target'],
'rho_score': rho['score'],
'rho_pvalue': rho['pvalue'],
'rho_label': rho['label'],
'-log10(rho_pvalue)': np.log10(rho['pvalue']) * -1,
'gamma_score': gamma.loc[rho.index,'score'],
'gamma_pvalue': gamma.loc[rho.index,'pvalue'],
'gamma_label': gamma.loc[rho.index,'label'],
'-log10(gamma_pvalue)': np.log10(gamma.loc[rho.index,'pvalue']) * -1,
})
return df
def _plot_scatter(
self,
x_source,y_source,
xaxis_label,yaxis_label,
up_hit, down_hit,
hit_label_col,
x_min, x_max, y_min, y_max,
title='',
dot_size=1,
width=500, height=400,
toolbar_location='below',
legend_loc="top_left"
):
df = self._prep_data(self.screen)
if y_max == 'auto': y_max = df[y_source].max() * 1.2
if x_max == 'auto': x_max = df[x_source].max() * 1.2
if y_min == 'auto': y_min = df[y_source].min() * 1.2
if x_min == 'auto': x_min = df[x_source].min() * 1.2
TOOLTIPS = [
("name", "@target"),
("rho score", "@rho_score"),
("rho p-value", "@rho_pvalue"),
("rho label", "@rho_label"),
("gamma score", "@gamma_score"),
("gamma p-value", "@gamma_pvalue"),
("gamma label", "@gamma_label"),
]
p = self._new_plot(
title=title,
tooltips=TOOLTIPS,
width=width,
height=height,
toolbar_location=toolbar_location
)
source = bokeh.models.ColumnDataSource(
df.loc[df[hit_label_col] == 'target_non_hit',:]
)
p.scatter(
x=x_source, y=y_source,
source=source,
alpha=0.2,
size=dot_size * 1.2,
color='gray',
legend_label='target_non_hit',
name='circles'
)
# size_mapper=bokeh.models.LinearInterpolator(
# x=[df['1/gamma_score'].min(),df['1/gamma_score'].max()],
# y=[1,100]
# )
source = bokeh.models.ColumnDataSource(
df.loc[df[hit_label_col] == up_hit,:]
)
p.scatter(
x=x_source, y=y_source,
source=source,
alpha=0.8,
size=dot_size * 1.2,
# size={'field':'1/gamma_score','transform':size_mapper},
color='#fcae91',
legend_label=up_hit,
name='circles'
)
source = bokeh.models.ColumnDataSource(
df.loc[df[hit_label_col] == down_hit,:]
)
p.scatter(
x=x_source, y=y_source,
source=source,
alpha=0.8,
# size={'field':'1/gamma_score','transform':size_mapper},
size=dot_size * 1.2,
color='#bdd7e7',
legend_label=down_hit,
name='circles'
)
source = bokeh.models.ColumnDataSource(
df.loc[df[hit_label_col] == self.ctrl_label,:]
)
p.scatter(
x=x_source, y=y_source,
source=source,
alpha=0.2,
size=dot_size*0.8,
color='silver',
legend_label=self.ctrl_label,
name='circles'
)
# Set x-axis and y-axis labels
p.xaxis.axis_label = xaxis_label
p.xaxis.axis_label_text_font_style = 'normal'
p.yaxis.axis_label = yaxis_label
p.yaxis.axis_label_text_font_style = 'normal'
# Set x-axis limits
p.x_range.start = x_min
p.x_range.end = x_max
# Set y-axis limits
p.y_range.start = y_min
p.y_range.end = y_max
# Add legend
if legend_loc == False or legend_loc == None:
p.legend.visible = False
else:
p.legend.location = legend_loc
p.title.text = title
p.title.align = 'center'
p.title.text_font_size = '12pt'
p.title.text_font_style = 'bold'
return p
[docs] def RhoVolcanoPlot(
self,
x_source='rho_score', y_source='-log10(rho_pvalue)',
xaxis_label='phenotype score',
yaxis_label='-log10(p-value)',
up_hit='resistance_hit', down_hit='sensitivity_hit',
hit_label_col='rho_label',
x_min=-2.5, x_max=2.5, y_min=0, y_max='auto',
return_html=True,
**kwargs
):
p = self._plot_scatter(
x_source, y_source,
xaxis_label, yaxis_label,
up_hit, down_hit,
hit_label_col,
x_min, x_max, y_min, y_max,
**kwargs
)
if return_html:
return self._get_html(p)
self.plots.update(
{'RhoVolcanoPlot': p}
)
[docs] def GammaVolcanoPlot(
self,
x_source='gamma_score', y_source='-log10(gamma_pvalue)',
xaxis_label='phenotype score',
yaxis_label='-log10(p-value)',
up_hit='up_hit', down_hit='essential_hit',
hit_label_col='gamma_label',
x_min=-2.5, x_max=2.5, y_min=0, y_max='auto',
return_html=True,
**kwargs
):
p = self._plot_scatter(
x_source, y_source,
xaxis_label, yaxis_label,
up_hit, down_hit,
hit_label_col,
x_min, x_max, y_min, y_max,
**kwargs
)
if return_html:
return self._get_html(p)
self.plots.update(
{'GammaVolcanoPlot': p}
)
[docs] def RhoGammaScatter(
self,
x_source='rho_score', y_source='gamma_score',
xaxis_label='rho score',
yaxis_label='gamma score',
up_hit='resistance_hit', down_hit='sensitivity_hit',
hit_label_col='rho_label',
return_html=True,
x_min=-2.5, x_max=2.5, y_min=-2.5, y_max=2.5,
**kwargs
):
p = self._plot_scatter(
x_source, y_source,
xaxis_label, yaxis_label,
up_hit, down_hit,
hit_label_col,
x_min, x_max, y_min, y_max,
**kwargs
)
if return_html:
return self._get_html(p)
self.plots.update(
{'GammaRhoScatter': p}
)