Skip to content

Commit

Permalink
refactor perturbation shiny
Browse files Browse the repository at this point in the history
  • Loading branch information
Sichao25 committed Oct 9, 2023
1 parent 6d1f923 commit 7c8b6ef
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 37 deletions.
113 changes: 76 additions & 37 deletions dynamo/shiny/perturbation.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,91 +20,130 @@ def perturbation_web_app(input_adata: AnnData):
"""
try:
import shiny.experimental as x
from htmltools import div
from htmltools import HTML, div
from shiny import App, Inputs, Outputs, reactive, Session, render, ui
except ImportError:
raise ImportError("Please install shiny and htmltools before running the web application!")

app_ui = x.ui.page_sidebar(
x.ui.sidebar(
ui.include_css(css_path),
div("Streamline Plot", class_="bold-subtitle"),
ui.input_text("base_color", "The key to color the cells: ", value="cell_type"),
ui.input_text(
"base_streamline_basis", "The perturbation output as the basis of plot: ", value="umap"
),
x.ui.accordion(
x.ui.accordion_panel(
div("Perturbation", class_="bold-subtitle"),
ui.input_text("selected_genes", "Genes to perform perturbation: ", placeholder="e.g. GATA1"),
ui.input_text("emb_basis", "Basis from which the vector field is reconstructed: ", value="umap"),
ui.input_text(
"expression", "Expression value to encode the genetic perturbation: ", placeholder="e.g. -100"
),
div("Perturbation Setting", class_="bold-subtitle"),
ui.input_slider("n_genes", "Number of genes to perturb:", min=1, max=5, value=1),
ui.output_ui("selectize_genes"),
ui.input_action_button(
"activate_perturbation", "Run perturbation", class_="btn-primary"
),
value="Perturbation",
),
x.ui.accordion_panel(
div("Streamline Plot After Perturbation", class_="bold-subtitle"),
ui.input_text("color", "The key to color the cells: ", value="cell_type"),
div("Streamline Plot Setting", class_="bold-subtitle"),
ui.input_slider("n_colors", "Number of observations:", min=1, max=5, value=1),
ui.output_ui("selectize_color"),
ui.input_text(
"streamline_basis", "The perturbation output as the basis of plot: ", value="umap_perturbation"
"streamline_basis", "The perturbation output as the basis of plot: ", value="umap"
),
ui.input_action_button(
"activate_streamline_plot", "Streamline plot", class_="btn-primary"
),
value="Streamline Plot",
value="Streamline Plot Setting",
),
open=False,
open=True,
),
width=500,
),
ui.div(
div("Streamline Plot", class_="bold-subtitle"),
x.ui.output_plot("base_plot"),
div("In-silico Perturbation Information", class_="bold-subtitle"),
ui.output_table("activate_perturbation"),
div("Streamline Plot After Perturbation", class_="bold-subtitle"),
x.ui.output_plot("perturbation_plot"),
div("in silico perturbation", class_="bold-title"),
div(HTML("<br><br>")),
div("Perturbation function in Dynamo can be used to either upregulating or suppressing a single or "
"multiple genes in a particular cell or across all cells to perform in silico genetic perturbation. "
"Dynamo first calculates the perturbation velocity vector from the input expression value and "
"the analytical Jacobian from our vector field function Because Jacobian encodes the instantaneous "
"changes of velocity of any genes after increasing any other gene, the output vector will produce the "
"perturbation effect vector after propagating the genetic perturbation through the gene regulatory "
"network. Then Dynamo projects the perturbation vector to low dimensional space.",
class_="explanation"),
div(HTML("<br><br>")),
x.ui.card(
div("Streamline Plot", class_="bold-subtitle"),
x.ui.output_plot("base_plot"),
),
x.ui.card(
div("Streamline Plot After Perturbation", class_="bold-subtitle"),
x.ui.output_plot("perturbation_plot"),
),
),
)

def server(input: Inputs, output: Outputs, session: Session):
adata = input_adata.copy()

@output
@render.ui
def selectize_color():
ui_list = ui.TagList()
for i in range(input.n_colors()):
ui_list.append(
ui.input_selectize(
"base_color_" + str(i),
"Color key " + str(i) + " :",
choices=list(adata.obs.keys()) + list(adata.var_names),
selected="cell_type",
),
)

return ui_list

@output
@render.ui
def selectize_genes():
ui_list = ui.TagList()
for i in range(input.n_genes()):
ui_list.extend(
(
ui.input_selectize(
"target_gene_" + str(i),
"Genes " + str(i) + " to perform perturbation:",
choices=list(adata.var_names),
),
ui.input_slider(
"expression_" + str(i),
"Expression value to encode the genetic perturbation: ",
min=-200, max=200, value=-100,
),
),

)
return ui_list

@output
@render.plot()
def base_plot():
color = input.base_color().split(",")
color = [getattr(input, "base_color_" + str(i))() for i in range(input.n_colors())]

axes_list = streamline_plot(adata, color=color, basis=input.base_streamline_basis(),
axes_list = streamline_plot(adata, color=color, basis=input.streamline_basis(),
save_show_or_return="return")

return filter_fig(plt.gcf())

@output
@render.table
@reactive.Effect
@reactive.event(input.activate_perturbation)
def activate_perturbation():
selected_genes = input.selected_genes().split(",")
expression = [int(txt) for txt in input.expression().split(",")]
df = pd.DataFrame({"Genes": selected_genes, "Values": expression})
selected_genes = [getattr(input, "target_gene_" + str(i))() for i in range(input.n_genes())]
expression = [getattr(input, "expression_" + str(i))() for i in range(input.n_genes())]

perturbation(adata, selected_genes, expression, emb_basis=input.emb_basis())

return df
perturbation(adata, selected_genes, expression, emb_basis=input.streamline_basis())

@output
@render.plot()
@reactive.event(input.activate_streamline_plot)
def perturbation_plot():
color = input.color().split(",")

axes_list = streamline_plot(adata, color=color, basis=input.streamline_basis(), save_show_or_return="return")
color = [getattr(input, "base_color_" + str(i))() for i in range(input.n_colors())]
axes_list = streamline_plot(adata, color=color, basis=input.streamline_basis() + "_perturbation", save_show_or_return="return")

return filter_fig(plt.gcf())

app = App(app_ui, server, debug=True)
app.run()
app.run()
1 change: 1 addition & 0 deletions dynamo/shiny/styles.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.bold-title {
font-weight: bold;
font-size: 20px;
text-align: center;
}

.bold-subtitle {
Expand Down

0 comments on commit 7c8b6ef

Please sign in to comment.