mirror of
https://github.com/johrpan/ubigen.git
synced 2025-10-26 19:57:24 +01:00
Add gene selector for custom genes
This commit is contained in:
parent
780e608ee1
commit
5f5670171d
8 changed files with 168 additions and 36 deletions
|
|
@ -25,4 +25,5 @@ Imports:
|
||||||
DT,
|
DT,
|
||||||
plotly,
|
plotly,
|
||||||
glue,
|
glue,
|
||||||
shiny
|
shiny,
|
||||||
|
shinyvs
|
||||||
|
|
|
||||||
10
NAMESPACE
10
NAMESPACE
|
|
@ -1,13 +1,5 @@
|
||||||
# Generated by roxygen2: do not edit by hand
|
# Generated by roxygen2: do not edit by hand
|
||||||
|
|
||||||
export(run_app)
|
export(run_app)
|
||||||
|
import(data.table)
|
||||||
import(shiny)
|
import(shiny)
|
||||||
importFrom(data.table,":=")
|
|
||||||
importFrom(data.table,.BY)
|
|
||||||
importFrom(data.table,.EACHI)
|
|
||||||
importFrom(data.table,.GRP)
|
|
||||||
importFrom(data.table,.I)
|
|
||||||
importFrom(data.table,.N)
|
|
||||||
importFrom(data.table,.NGRP)
|
|
||||||
importFrom(data.table,.SD)
|
|
||||||
importFrom(data.table,data.table)
|
|
||||||
|
|
|
||||||
99
R/gene_selector.R
Normal file
99
R/gene_selector.R
Normal file
|
|
@ -0,0 +1,99 @@
|
||||||
|
#' Create the UI for a gene selector.
|
||||||
|
#'
|
||||||
|
#' @param id ID for namespacing.
|
||||||
|
#'
|
||||||
|
#' @return The user interface
|
||||||
|
#' @noRd
|
||||||
|
gene_selector_ui <- function(id) {
|
||||||
|
named_genes <- ubigen::genes[hgnc_name != ""]
|
||||||
|
named_genes <- unique(named_genes, by = "hgnc_name")
|
||||||
|
gene_choices <- named_genes$gene
|
||||||
|
names(gene_choices) <- named_genes$hgnc_name
|
||||||
|
|
||||||
|
verticalLayout(
|
||||||
|
selectInput(
|
||||||
|
NS(id, "identifier_type"),
|
||||||
|
verticalLayout(
|
||||||
|
strong("Gene identifiers"),
|
||||||
|
paste0(
|
||||||
|
"Select whether you want to pick or enter custom genes to assess ",
|
||||||
|
"how ubiquitous they are."
|
||||||
|
)
|
||||||
|
),
|
||||||
|
choices = list(
|
||||||
|
"Select from list" = "list",
|
||||||
|
"Enter HGNC symbols" = "hgnc",
|
||||||
|
"Enter Ensembl gene IDs" = "ensembl"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
tabsetPanel(
|
||||||
|
id = NS(id, "custom_input"),
|
||||||
|
type = "hidden",
|
||||||
|
tabPanelBody(
|
||||||
|
"list",
|
||||||
|
shinyvs::virtualSelectInput(
|
||||||
|
NS(id, "selected_genes"),
|
||||||
|
label = NULL,
|
||||||
|
choices = gene_choices,
|
||||||
|
multiple = TRUE,
|
||||||
|
search = TRUE,
|
||||||
|
selectAllOnlyVisible = TRUE
|
||||||
|
),
|
||||||
|
),
|
||||||
|
tabPanelBody(
|
||||||
|
"hgnc",
|
||||||
|
textAreaInput(
|
||||||
|
NS(id, "hgnc_names_raw"),
|
||||||
|
label = NULL,
|
||||||
|
height = "250px"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
tabPanelBody(
|
||||||
|
"ensembl",
|
||||||
|
textAreaInput(
|
||||||
|
NS(id, "gene_ids_raw"),
|
||||||
|
label = NULL,
|
||||||
|
height = "250px"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#' Application logic for the gene selector.
|
||||||
|
#'
|
||||||
|
#' @param id ID for namespacing.
|
||||||
|
#'
|
||||||
|
#' @return A reactive containing the selected gene IDs.
|
||||||
|
#' @noRd
|
||||||
|
gene_selector_server <- function(id) {
|
||||||
|
moduleServer(id, function(input, output, session) {
|
||||||
|
observe({
|
||||||
|
updateTabsetPanel(
|
||||||
|
session,
|
||||||
|
"custom_input",
|
||||||
|
selected = input$identifier_type
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
reactive({
|
||||||
|
gene_ids <- if (input$identifier_type == "list") {
|
||||||
|
input$selected_genes
|
||||||
|
} else if (input$identifier_type == "hgnc") {
|
||||||
|
inputs <- unique(strsplit(input$hgnc_names_raw, "\\s+")[[1]])
|
||||||
|
inputs <- inputs[inputs != ""]
|
||||||
|
ubigen::genes[hgnc_name %chin% inputs, gene]
|
||||||
|
} else {
|
||||||
|
inputs <- unique(strsplit(input$gene_ids_raw, "\\s+")[[1]])
|
||||||
|
inputs <- inputs[inputs != ""]
|
||||||
|
ubigen::genes[gene %chin% inputs, gene]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length(gene_ids > 100)) {
|
||||||
|
gene_ids[seq_len(100)]
|
||||||
|
} else {
|
||||||
|
gene_ids
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
56
R/plots.R
56
R/plots.R
|
|
@ -1,35 +1,59 @@
|
||||||
#' Create a plot showing an overview over the provided ranking.
|
#' Create a plot showing an overview over the provided ranking.
|
||||||
#'
|
#'
|
||||||
#' @param ranked_data The ranking to visualize.
|
#' @param ranked_data The ranking to visualize.
|
||||||
|
#' @param highlighted_genes Genes that will be marked.
|
||||||
#' @param sample_proportion Proportion of rows to use as the shown sample.
|
#' @param sample_proportion Proportion of rows to use as the shown sample.
|
||||||
#'
|
#'
|
||||||
#' @return A `plotly` figure.
|
#' @return A `plotly` figure.
|
||||||
#' @noRd
|
#' @noRd
|
||||||
overview_plot <- function(ranked_data, sample_proportion = 0.05) {
|
overview_plot <- function(ranked_data,
|
||||||
plotly::plot_ly() |>
|
highlighted_genes = NULL,
|
||||||
|
sample_proportion = 0.05) {
|
||||||
|
figure <- plotly::plot_ly() |>
|
||||||
plotly::add_lines(
|
plotly::add_lines(
|
||||||
data = ranked_data[sample(
|
data = ranked_data[sample(
|
||||||
nrow(ranked_data),
|
nrow(ranked_data),
|
||||||
sample_proportion * nrow(ranked_data)
|
sample_proportion * nrow(ranked_data)
|
||||||
)],
|
)],
|
||||||
x = ~rank,
|
x = ~rank,
|
||||||
y = ~score
|
y = ~score,
|
||||||
|
hoverinfo = "skip"
|
||||||
) |>
|
) |>
|
||||||
plotly::layout(
|
plotly::layout(
|
||||||
xaxis = list(title = "Ranks"),
|
xaxis = list(title = "Ranks"),
|
||||||
yaxis = list(title = "Score")
|
yaxis = list(title = "Score")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!is.null(highlighted_genes)) {
|
||||||
|
figure <- figure |>
|
||||||
|
plotly::add_markers(
|
||||||
|
data = ranked_data[gene %chin% highlighted_genes],
|
||||||
|
x = ~rank,
|
||||||
|
y = ~score,
|
||||||
|
text = ~ glue::glue(
|
||||||
|
"<b>{hgnc_name}</b><br>",
|
||||||
|
"Score: {round(score, digits = 2)}<br>",
|
||||||
|
"Rank: {rank}<br>",
|
||||||
|
"Percentile: {round(percentile * 100, digits = 2)}%"
|
||||||
|
),
|
||||||
|
hoverinfo = "text",
|
||||||
|
showlegend = FALSE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
figure
|
||||||
}
|
}
|
||||||
|
|
||||||
#' Create plot showing the distribution of scores using `plotly`.
|
#' Create plot showing the distribution of scores using `plotly`.
|
||||||
#'
|
#'
|
||||||
#' @param ranked_data Data on genes with precomputed ranks.
|
#' @param ranked_data Data on genes with precomputed ranks.
|
||||||
|
#' @param highlighted_genes Genes that will be marked.
|
||||||
#' @param ranks How may ranks the x-axis should include. If this parameter is
|
#' @param ranks How may ranks the x-axis should include. If this parameter is
|
||||||
#' `NULL`, all ranks will be shown.
|
#' `NULL`, all ranks will be shown.
|
||||||
#'
|
#'
|
||||||
#' @return A `plotly` figure for rendering.
|
#' @return A `plotly` figure for rendering.
|
||||||
#' @noRd
|
#' @noRd
|
||||||
scores_plot <- function(ranked_data, ranks = 1000) {
|
scores_plot <- function(ranked_data, highlighted_genes = NULL, ranks = 1000) {
|
||||||
data <- if (is.null(ranks)) {
|
data <- if (is.null(ranks)) {
|
||||||
ranked_data
|
ranked_data
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -42,20 +66,26 @@ scores_plot <- function(ranked_data, ranks = 1000) {
|
||||||
glue::glue("Ranks (1 to {ranks})")
|
glue::glue("Ranks (1 to {ranks})")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data[, group := data.table::fifelse(
|
||||||
|
gene %chin% highlighted_genes,
|
||||||
|
"Your genes",
|
||||||
|
"All genes"
|
||||||
|
)]
|
||||||
|
|
||||||
plotly::plot_ly() |>
|
plotly::plot_ly() |>
|
||||||
plotly::add_markers(
|
plotly::add_markers(
|
||||||
data = data,
|
data = data,
|
||||||
x = ~rank,
|
x = ~rank,
|
||||||
y = ~score,
|
y = ~score,
|
||||||
text = ~hgnc_name,
|
name = ~group,
|
||||||
customdata = ~percentile,
|
text = ~ glue::glue(
|
||||||
hovertemplate = paste0(
|
"<b>{hgnc_name}</b><br>",
|
||||||
"<b>%{text}</b><br>",
|
"Score: {round(score, digits = 2)}<br>",
|
||||||
"Rank: %{x}<br>",
|
"Rank: {rank}<br>",
|
||||||
"Score: %{y:.2}<br>",
|
"Percentile: {round(percentile * 100, digits = 2)}%"
|
||||||
"Percentile: %{customdata:.2%}",
|
),
|
||||||
"<extra></extra>"
|
hoverinfo = "text",
|
||||||
)
|
showlegend = FALSE
|
||||||
) |>
|
) |>
|
||||||
plotly::layout(
|
plotly::layout(
|
||||||
xaxis = list(title = ranks_label),
|
xaxis = list(title = ranks_label),
|
||||||
|
|
|
||||||
13
R/server.R
13
R/server.R
|
|
@ -17,8 +17,17 @@ server <- function(input, output) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
|
|
||||||
output$overview_plot <- plotly::renderPlotly(overview_plot(ranked_data()))
|
custom_genes <- gene_selector_server("custom_genes")
|
||||||
output$scores_plot <- plotly::renderPlotly(scores_plot(ranked_data()))
|
|
||||||
|
output$overview_plot <- plotly::renderPlotly(overview_plot(
|
||||||
|
ranked_data(),
|
||||||
|
highlighted_genes = custom_genes()
|
||||||
|
))
|
||||||
|
|
||||||
|
output$scores_plot <- plotly::renderPlotly(scores_plot(
|
||||||
|
ranked_data(),
|
||||||
|
highlighted_genes = custom_genes()
|
||||||
|
))
|
||||||
|
|
||||||
output$selected_genes <- DT::renderDataTable({
|
output$selected_genes <- DT::renderDataTable({
|
||||||
selected_points <- plotly::event_data("plotly_selected")
|
selected_points <- plotly::event_data("plotly_selected")
|
||||||
|
|
|
||||||
7
R/style.R
Normal file
7
R/style.R
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
#' Custom CSS to tweak the rendering.
|
||||||
|
#' @noRd
|
||||||
|
custom_css <- function() {
|
||||||
|
tags$head(
|
||||||
|
tags$style(".nav-hidden { height: 0 }")
|
||||||
|
)
|
||||||
|
}
|
||||||
5
R/ui.R
5
R/ui.R
|
|
@ -8,12 +8,15 @@ ui <- function() {
|
||||||
primary = "#7d19bf"
|
primary = "#7d19bf"
|
||||||
),
|
),
|
||||||
title = "Ubigen",
|
title = "Ubigen",
|
||||||
|
header = custom_css(),
|
||||||
tabPanel(
|
tabPanel(
|
||||||
"Explore",
|
"Explore",
|
||||||
sidebarLayout(
|
sidebarLayout(
|
||||||
sidebarPanel(
|
sidebarPanel(
|
||||||
width = 3,
|
width = 3,
|
||||||
h3("Features"),
|
h3("My genes"),
|
||||||
|
gene_selector_ui("custom_genes"),
|
||||||
|
h3("Scoring"),
|
||||||
selectInput(
|
selectInput(
|
||||||
"cross_sample_metric",
|
"cross_sample_metric",
|
||||||
verticalLayout(
|
verticalLayout(
|
||||||
|
|
|
||||||
11
R/utils.R
11
R/utils.R
|
|
@ -1,13 +1,4 @@
|
||||||
# Various things that should be imported into the package namespace.
|
# Various things that should be imported into the package namespace.
|
||||||
#' @importFrom data.table :=
|
#' @import data.table
|
||||||
#' @importFrom data.table .BY
|
|
||||||
#' @importFrom data.table .EACHI
|
|
||||||
#' @importFrom data.table .GRP
|
|
||||||
#' @importFrom data.table .I
|
|
||||||
#' @importFrom data.table .N
|
|
||||||
#' @importFrom data.table .NGRP
|
|
||||||
#' @importFrom data.table .SD
|
|
||||||
#' @importFrom data.table data.table
|
|
||||||
#'
|
|
||||||
#' @import shiny
|
#' @import shiny
|
||||||
NULL
|
NULL
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue