| Title: | Shiny App to Explore Single-Cell Analysis |
|---|---|
| Description: | Interactive and modular shiny app for single-cell and spatial transcriptomic data exploration and management. Visualize cell clusters or groups using interactive cell embeddings, e.g. UMAP or t-SNE, or spatial views. Explore cell composition and quality control metrics using the metadata viewer module. Investigate the effect of clustering resolutions or compare annotation sources using cluster tree. Visualize gene expression using cell embeddings or in spatial context with feature plots and coexpression plots or in cell clusters using dotplots, violin plots. Manage marker tables from single-cell or pseudo-bulk analyses and track genes of interest using the gene scratchpad. Choose interesting cells with lasso selection directly from interactive plots and export for downstream analysis. Slice and dice datasets with custom filters based on cell metadata, gene expression or lasso selections. Efficiently handle large datasets using custom downsampling controls. CascadeR has cross-ecosystem compatibility with support for Seurat, SingleCellExperiment and AnnData objects. In addition, the app includes an integrated platform to manage multiple projects and user access that can be run on a central server to share with collaborators. |
| Authors: | Apratim Mitra [aut, cre] (ORCID: <https://orcid.org/0000-0003-3279-0054>), Ryan Dale [fnd] (ORCID: <https://orcid.org/0000-0003-2664-3744>) |
| Maintainer: | Apratim Mitra <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.99.0 |
| Built: | 2026-09-19 01:24:55 UTC |
| Source: | https://github.com/BiocStaging/cascadeR |
Add new cascade analysis
add_cascade_analysis( obj_path, data_dir, project, analysis, cluster_markers = NULL, de_markers = NULL, conserved_markers = NULL, overwrite = FALSE, execute = FALSE )add_cascade_analysis( obj_path, data_dir, project, analysis, cluster_markers = NULL, de_markers = NULL, conserved_markers = NULL, overwrite = FALSE, execute = FALSE )
obj_path |
path to Seurat/anndata object |
data_dir |
output data directory. For convenience use the same data directory for all cascade projects. |
project |
project name. Creates a subfolder with this name inside data_dir if it doesn't exist. |
analysis |
analysis label. Creates a subfolder with this name inside data_dir/project |
cluster_markers |
(optional) path(s) to tab-delimited file(s) containing cluster markers. Output from Seurat's FindAllMarkers and scanpy's rank_genes_groups are supported. |
de_markers |
(optional) path(s) to tab-delimited file(s) containing differentially expressed markers from Seurat's FindMarkers or scanpy's rank_genes_groups. |
conserved_markers |
(optional) path(s) to tab-delimited file(s) containing conserved markers from Seurat's FindConservedMarkers function. |
overwrite |
boolean, if TRUE, existing analysis folder will be overwritten (default=FALSE) |
execute |
boolean, set this to TRUE to actually run the commands (default=FALSE) |
Invisibly returns NULL; called for the side effect of printing or executing setup commands.
local({ data_dir <- tempfile("cascade-data-") dir.create(data_dir) obj_path <- tempfile("object-", fileext = ".rds") file.create(obj_path) on.exit(unlink(c(data_dir, obj_path), recursive = TRUE)) add_cascade_analysis( obj_path = obj_path, data_dir = data_dir, project = "project1", analysis = "analysis1", execute = FALSE ) })local({ data_dir <- tempfile("cascade-data-") dir.create(data_dir) obj_path <- tempfile("object-", fileext = ".rds") file.create(obj_path) on.exit(unlink(c(data_dir, obj_path), recursive = TRUE)) add_cascade_analysis( obj_path = obj_path, data_dir = data_dir, project = "project1", analysis = "analysis1", execute = FALSE ) })
Seurat:::BlendExpression for arbitrary number of bins n = 1, means 10 bins n = 2, means 100 bins ...
BlendExpression2(data, n = 1)BlendExpression2(data, n = 1)
data |
2-column matrix with gene expression to be blended |
n |
integer, defines number of bins = 10^n (default=1) |
NOTE: not used
data.frame with blended expression
Seurat:::BlendMap function converted to plotly.
BlendMap2(color.matrix, dimnames = NULL)BlendMap2(color.matrix, dimnames = NULL)
color.matrix |
matrix of colors |
dimnames |
axis labels |
NOTE: this is not used
plotly handle
This is a stripped down version of Seurat::BuildClusterTree for anndata objects. It takes the same arguments as the Seurat function.
BuildClusterTree2( object, features = NULL, dims = NULL, reduction = "X_pca", clust_column = "leiden" )BuildClusterTree2( object, features = NULL, dims = NULL, reduction = "X_pca", clust_column = "leiden" )
object |
anndata object |
features |
genes to use for building cluster tree |
dims |
dimensions to use. This is only used if reduction is pca. |
reduction |
reduction to use for cluster tree |
clust_column |
column to use for grouping cells |
phylogenetic tree
This function takes a username and returns a list with two elements:
check_user_access(al, u, admin = "admin")check_user_access(al, u, admin = "admin")
al |
list with access settings; should have two elements - user_group & data_area |
u |
user name |
admin |
Admin user group |
user_group: one element vector data_area: vector of data areas
list with user_group and data_area entries, or NULL if no access is found
# save access details to file home <- Sys.getenv('HOME') # create carnation data area if it doesn't exist cascade_home <- file.path(home, 'cascade/data') if(!dir.exists(cascade_home)) dir.create(cascade_home) create_access_yaml(user = 'admin', user_group = 'admin', data_area = cascade_home) # get current user access details al <- read_access_yaml() lst <- check_user_access(al, u='admin')# save access details to file home <- Sys.getenv('HOME') # create carnation data area if it doesn't exist cascade_home <- file.path(home, 'cascade/data') if(!dir.exists(cascade_home)) dir.create(cascade_home) create_access_yaml(user = 'admin', user_group = 'admin', data_area = cascade_home) # get current user access details al <- read_access_yaml() lst <- check_user_access(al, u='admin')
Cluster tree module
clustreeUI(id, panel) clustreeServer(id, obj, filtered, args, reload_global, config)clustreeUI(id, panel) clustreeServer(id, obj, filtered, args, reload_global, config)
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
obj |
Cascade app object |
filtered |
cell barcodes for filtering object |
args |
reactive list with global args, 'grp_by' for grouping variable and 'dimred' for which dimension reduction to use |
reload_global |
reactive to reload module |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for the cluster tree Server called for the side effect of rendering cluster tree plots.
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = list( all = metadata_levels, filtered = metadata_levels ), cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(clustreeUI("clustree", "sidebar")), shiny::mainPanel(clustreeUI("clustree", "main")) ) ) server <- function(input, output, session) { clustreeServer( "clustree", obj = app_object, filtered = shiny::reactive({ colnames(obj) }), args = shiny::reactive({ global_args }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = list( all = metadata_levels, filtered = metadata_levels ), cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(clustreeUI("clustree", "sidebar")), shiny::mainPanel(clustreeUI("clustree", "main")) ) ) server <- function(input, output, session) { clustreeServer( "clustree", obj = app_object, filtered = shiny::reactive({ colnames(obj) }), args = shiny::reactive({ global_args }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) } shiny::shinyApp(ui, server)
Metadata viewer module
clustSummaryUI(id, panel) clustSummaryServer(id, obj, filtered, args, reload_global, config)clustSummaryUI(id, panel) clustSummaryServer(id, obj, filtered, args, reload_global, config)
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
obj |
Cascade app object |
filtered |
cell barcodes for filtering object |
args |
reactive list with elements, 'grp_by' for grouping variable and 'dimred' for which dimension reduction to use |
reload_global |
reactive to trigger reload |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for the metadata viewer Server called for the side effect of rendering metadata summary outputs.
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) numeric_cols <- vapply(metadata, is.numeric, logical(1)) metadata_numeric <- lapply(metadata[numeric_cols], function(x) { x <- x[!is.na(x)] hh <- graphics::hist(x, breaks = 20, plot = FALSE) data.frame(mids = hh$mids, counts = hh$counts) }) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = list( all = metadata_levels, filtered = metadata_levels ), metadata_numeric = list( all = metadata_numeric, filtered = metadata_numeric ), cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(clustSummaryUI("metadata", "sidebar")), shiny::mainPanel(clustSummaryUI("metadata", "main")) ) ) server <- function(input, output, session) { clustSummaryServer( "metadata", obj = app_object, filtered = shiny::reactive({ colnames(obj) }), args = shiny::reactive({ global_args }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) numeric_cols <- vapply(metadata, is.numeric, logical(1)) metadata_numeric <- lapply(metadata[numeric_cols], function(x) { x <- x[!is.na(x)] hh <- graphics::hist(x, breaks = 20, plot = FALSE) data.frame(mids = hh$mids, counts = hh$counts) }) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = list( all = metadata_levels, filtered = metadata_levels ), metadata_numeric = list( all = metadata_numeric, filtered = metadata_numeric ), cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(clustSummaryUI("metadata", "sidebar")), shiny::mainPanel(clustSummaryUI("metadata", "main")) ) ) server <- function(input, output, session) { clustSummaryServer( "metadata", obj = app_object, filtered = shiny::reactive({ colnames(obj) }), args = shiny::reactive({ global_args }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) } shiny::shinyApp(ui, server)
Coexpression plot module
coexpressionPlotUI(id, panel) coexpressionPlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, all_selected, show_selection, reset_selection, reload_global, refresh, config )coexpressionPlotUI(id, panel) coexpressionPlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, all_selected, show_selection, reset_selection, reload_global, refresh, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
app_object |
Cascade app object |
filtered |
barcodes to filter object |
genes_to_plot |
reactive list with genes in scratchpad |
args |
reactive list with elements: 'assay' for selected assay, 'dimred' for which dimension reduction to use and 'grp_by' for grouping variable |
gene_choices |
reactive list with all genes present in object |
all_selected |
reactive containing list of selected points |
show_selection |
reactive to show selection |
reset_selection |
reactive to reset selection |
reload_global |
reactive to trigger reload |
refresh |
reactive to trigger plot refresh from sidebar button |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for coexpression plot Server returns reactive expression containing selected points from the coexpression plot
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shiny::sidebarPanel(coexpressionPlotUI("coexpression", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(coexpressionPlotUI("coexpression", "main")), shiny::verbatimTextOutput("selected") ) ) server <- function(input, output, session) { selected <- coexpressionPlotServer( "coexpression", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shiny::sidebarPanel(coexpressionPlotUI("coexpression", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(coexpressionPlotUI("coexpression", "main")), shiny::verbatimTextOutput("selected") ) ) server <- function(input, output, session) { selected <- coexpressionPlotServer( "coexpression", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
Filter control module
controlUI(id, label) controlServer(id, full_obj, column, global, default = "all")controlUI(id, label) controlServer(id, full_obj, column, global, default = "all")
id |
string, input id |
label |
string, heading for controls |
full_obj |
reactive, object used to generate controls. can be data frame or list |
column |
string or reactive list, name of column or list element present in full_obj used to generate controls |
global |
reactive list used to set input externally |
default |
numeric vector or string, which elements to initialize with. If 'all' (default) all elements are selected, otherwise, can specify indices as numeric integer(s). |
UI returns filter controls UI Server returns reactive expression containing the selected filter values
metadata <- data.frame( cluster = factor(rep(c("A", "B"), each = 4), levels = c("A", "B")), condition = factor(rep(c("ctrl", "stim"), times = 4), levels = c("ctrl", "stim")) ) ui <- shiny::fluidPage( controlUI("cluster_filter", "Cluster"), shiny::verbatimTextOutput("selected") ) server <- function(input, output, session) { selected <- controlServer( "cluster_filter", full_obj = shiny::reactive({ metadata }), column = "cluster", global = shiny::reactive({ NULL }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)metadata <- data.frame( cluster = factor(rep(c("A", "B"), each = 4), levels = c("A", "B")), condition = factor(rep(c("ctrl", "stim"), times = 4), levels = c("ctrl", "stim")) ) ui <- shiny::fluidPage( controlUI("cluster_filter", "Cluster"), shiny::verbatimTextOutput("selected") ) server <- function(input, output, session) { selected <- controlServer( "cluster_filter", full_obj = shiny::reactive({ metadata }), column = "cluster", global = shiny::reactive({ NULL }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
This function creates an access yaml file. This is primarily intended for the first run.
create_access_yaml(user, user_group, data_area)create_access_yaml(user, user_group, data_area)
user |
User name |
user_group |
User group |
data_area |
Path to data area containing RDS files |
Invisibly returns NULL; called for the side effect of writing the access yaml file.
local({ access_dir <- tempfile("cascade-access-") dir.create(access_dir) old <- Sys.getenv("CASCADE_ACCESS_YAML", unset = NA_character_) Sys.setenv(CASCADE_ACCESS_YAML = access_dir) on.exit({ if (is.na(old)) { Sys.unsetenv("CASCADE_ACCESS_YAML") } else { Sys.setenv(CASCADE_ACCESS_YAML = old) } unlink(access_dir, recursive = TRUE) }) create_access_yaml("user1", "lab1", "/data/lab1") })local({ access_dir <- tempfile("cascade-access-") dir.create(access_dir) old <- Sys.getenv("CASCADE_ACCESS_YAML", unset = NA_character_) Sys.setenv(CASCADE_ACCESS_YAML = access_dir) on.exit({ if (is.na(old)) { Sys.unsetenv("CASCADE_ACCESS_YAML") } else { Sys.setenv(CASCADE_ACCESS_YAML = old) } unlink(access_dir, recursive = TRUE) }) create_access_yaml("user1", "lab1", "/data/lab1") })
Cell embeddings module
dimredUI(id, panel) dimredServer( id, obj, filtered, args, all_selected, show_selection, reset_selection, reload_global, config )dimredUI(id, panel) dimredServer( id, obj, filtered, args, all_selected, show_selection, reset_selection, reload_global, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
obj |
Cascade app object |
filtered |
barcodes to filter object |
args |
reactive list with global args, 'grp_by' for grouping variable and 'dimred' for which dimension reduction to use |
all_selected |
reactive containing list of selected points |
show_selection |
reactive to show selection |
reset_selection |
reactive to reset selection |
reload_global |
reactive to trigger reload |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for cell embeddings Server returns reactive expression containing selected points from embedding plots
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = list( all = metadata_levels, filtered = metadata_levels ), cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(dimredUI("dimred", "sidebar")), shiny::mainPanel( dimredUI("dimred", "main"), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- dimredServer( "dimred", obj = app_object, filtered = shiny::reactive({ colnames(obj) }), args = shiny::reactive({ global_args }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = list( all = metadata_levels, filtered = metadata_levels ), cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(dimredUI("dimred", "sidebar")), shiny::mainPanel( dimredUI("dimred", "main"), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- dimredServer( "dimred", obj = app_object, filtered = shiny::reactive({ colnames(obj) }), args = shiny::reactive({ global_args }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
UI & server for download file module
downloadFileUI(id) downloadFileServer(id, data, file_type)downloadFileUI(id) downloadFileServer(id, data, file_type)
id |
Input id |
data |
reactive w data frame |
file_type |
reactive/static value used for output filename |
Shiny UI & server for the file download button module
Download button module
downloadPlotUI(id) downloadPlotServer(id, outplot, plot_type, direction = NULL)downloadPlotUI(id) downloadPlotServer(id, outplot, plot_type, direction = NULL)
id |
Input id |
outplot |
reactive plot handle |
plot_type |
reactive/static value used for output filename |
direction |
direction of phylogenetic tree |
Shiny UI & server element for the plot download button module
Lightweight dotplot reimplementation to run only on data frame with gene expression and metadata.
dotplot( df, xcol, ycol, split = NULL, scale = TRUE, dot.scale = 10, col.min = -2.5, col.max = 2.5 )dotplot( df, xcol, ycol, split = NULL, scale = TRUE, dot.scale = 10, col.min = -2.5, col.max = 2.5 )
df |
data.frame with gene expression data |
xcol |
x-axis grouping variable |
ycol |
genes to show (on y-axis). can be multiple |
split |
faceting variable |
scale |
should data be scaled? Default: TRUE |
dot.scale |
dot size scaling factor (default: 10) |
col.min |
if data is scaled, this is the lower limit of values (default: -2.5) |
col.max |
if data is scaled, this is the upper limit of values (default: 2.5) |
ggplot2 handle
df <- data.frame( cluster = factor(rep(c("A", "B"), each = 4)), condition = factor(rep(c("ctrl", "stim"), times = 4)), GeneA = c(0, 2, 4, 5, 1, 3, 6, 8), GeneB = c(1, 0, 3, 2, 5, 0, 7, 4) ) dotplot(df, xcol = "cluster", ycol = c("GeneA", "GeneB"), scale = FALSE) dotplot(df, xcol = "cluster", ycol = "GeneA", split = "condition")df <- data.frame( cluster = factor(rep(c("A", "B"), each = 4)), condition = factor(rep(c("ctrl", "stim"), times = 4)), GeneA = c(0, 2, 4, 5, 1, 3, 6, 8), GeneB = c(1, 0, 3, 2, 5, 0, 7, 4) ) dotplot(df, xcol = "cluster", ycol = c("GeneA", "GeneB"), scale = FALSE) dotplot(df, xcol = "cluster", ycol = "GeneA", split = "condition")
Dotplot module
dotPlotUI(id, panel) dotPlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, reload_global, refresh, config )dotPlotUI(id, panel) dotPlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, reload_global, refresh, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
app_object |
Cascade app object |
filtered |
barcodes to filter object |
genes_to_plot |
reactive list with genes in scratchpad |
args |
reactive list with elements: 'assay' for selected assay, 'dimred' for which dimension reduction to use and 'grp_by' for grouping variable |
gene_choices |
reactive list with all genes present in object |
reload_global |
reactive to trigger reload |
refresh |
reactive to trigger plot refresh from sidebar button |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for dotplot module Server called for the side effect of rendering a dotplot.
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shiny::sidebarPanel(dotPlotUI("dotplot", "sidebar")), shiny::mainPanel(shiny::tabsetPanel(dotPlotUI("dotplot", "main"))) ) server <- function(input, output, session) { dotPlotServer( "dotplot", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shiny::sidebarPanel(dotPlotUI("dotplot", "sidebar")), shiny::mainPanel(shiny::tabsetPanel(dotPlotUI("dotplot", "main"))) ) server <- function(input, output, session) { dotPlotServer( "dotplot", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) } shiny::shinyApp(ui, server)
This is a wrapper around umap_ly that uses four colors for four categories instead of a blend matrix.
feature_blend( df, xcol, ycol, blend_cols, colors, split = NULL, col_threshold_1 = 0.5, col_threshold_2 = 0.5, n = 100, bin_mode = "range", neutral_color = "lightgray", showlegend = TRUE, showticklabels = TRUE, type = "scattergl", marker_size = 2, margin = 0.03, alpha = 0.3, free_axes = FALSE, width = NULL, height = NULL, source = "A" )feature_blend( df, xcol, ycol, blend_cols, colors, split = NULL, col_threshold_1 = 0.5, col_threshold_2 = 0.5, n = 100, bin_mode = "range", neutral_color = "lightgray", showlegend = TRUE, showticklabels = TRUE, type = "scattergl", marker_size = 2, margin = 0.03, alpha = 0.3, free_axes = FALSE, width = NULL, height = NULL, source = "A" )
df |
data.frame with plotting data |
xcol |
x-axis coordinates |
ycol |
y-axis coordinates |
blend_cols |
columns to blend |
colors |
3 color vector (geneA, geneB, merge) |
split |
metadata column to split plot by |
col_threshold_1 |
blending threshold for gene 1 |
col_threshold_2 |
blending threshold for gene 2 |
n |
number of bins for color range |
bin_mode |
how to bin? can be 'range' (gene expression binned into n bins) or 'quantile' (cells binned into n bins by exp) |
neutral_color |
double negative color |
showlegend |
should legend be shown? |
showticklabels |
should tick labels be drawn? |
type |
type of plotly trace (default: 'scattergl') |
marker_size |
size of markers |
margin |
margin of plot (should be between 0 & 1) |
alpha |
marker opacity |
free_axes |
should subplots have free axes? |
width |
width of plot in pixels. If NULL (default), plot is auto-sized. |
height |
height of plot in pixels. if NULL (default), plot is auto-sized. |
source |
name of source to return data from |
list with plot data and plotly handle
df <- data.frame( UMAP_1 = c(-1, 0, 1, 2), UMAP_2 = c(0, 1, 0, -1), GeneA = c(0, 5, 0, 10), GeneB = c(0, 0, 8, 10) ) blended <- feature_blend( df, xcol = "UMAP_1", ycol = "UMAP_2", blend_cols = c("GeneA", "GeneB"), colors = c("#ff0000", "#0000ff", "#ff00ff"), n = 10 ) names(blended) blended$datadf <- data.frame( UMAP_1 = c(-1, 0, 1, 2), UMAP_2 = c(0, 1, 0, -1), GeneA = c(0, 5, 0, 10), GeneB = c(0, 0, 8, 10) ) blended <- feature_blend( df, xcol = "UMAP_1", ycol = "UMAP_2", blend_cols = c("GeneA", "GeneB"), colors = c("#ff0000", "#0000ff", "#ff00ff"), n = 10 ) names(blended) blended$data
Interactive feature plot
feature_ly( df, xcol, ycol, color, colors, crange = NULL, split = NULL, label_cols = NULL, row_view = "auto", showscale = TRUE, reversescale = FALSE, showticklabels = TRUE, marker_size = 2, margin = 0.03, alpha = 0.3, free_axes = FALSE, reorder = TRUE, width = NULL, height = NULL, title_mode = "color", source = "A" )feature_ly( df, xcol, ycol, color, colors, crange = NULL, split = NULL, label_cols = NULL, row_view = "auto", showscale = TRUE, reversescale = FALSE, showticklabels = TRUE, marker_size = 2, margin = 0.03, alpha = 0.3, free_axes = FALSE, reorder = TRUE, width = NULL, height = NULL, title_mode = "color", source = "A" )
df |
data.frame with expresion data & plot coordinates |
xcol |
x-axis coordinates |
ycol |
y-axis coordinates |
color |
color column. should be numeric |
colors |
plotly color scale. should be continuous |
crange |
range of gene expression to show on plot |
split |
column to split plots by |
label_cols |
Additional metadata columns to use for labeling pts |
row_view |
how should plots be laid out? can be 'single' or 'auto' |
showscale |
show the color scale? |
reversescale |
should we reverse the color scale? |
showticklabels |
should tick labels be drawn? |
marker_size |
marker size |
margin |
plot margin |
alpha |
marker opacity |
free_axes |
should subplots have free axes? |
reorder |
should be sort cells in ascending order of expression? |
width |
width of plot in pixels |
height |
height of plot in pixels |
title_mode |
string specifying how axes should be titled. If 'color' (default), the y-axis is titled with the coloring variable; if 'xy', xcol and ycol are used as labels. |
source |
name of source to return data from |
plotly handle
df <- data.frame( UMAP_1 = c(-1, 0, 1, 2), UMAP_2 = c(0, 1, 0, -1), GeneA = c(0, 2, 4, 8) ) feature_ly( df, xcol = "UMAP_1", ycol = "UMAP_2", color = "GeneA", colors = "Viridis", crange = c(0, 8) )df <- data.frame( UMAP_1 = c(-1, 0, 1, 2), UMAP_2 = c(0, 1, 0, -1), GeneA = c(0, 2, 4, 8) ) feature_ly( df, xcol = "UMAP_1", ycol = "UMAP_2", color = "GeneA", colors = "Viridis", crange = c(0, 8) )
Feature plot module
featurePlotUI(id, panel) featurePlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, all_selected, show_selection, reset_selection, reload_global, refresh, config )featurePlotUI(id, panel) featurePlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, all_selected, show_selection, reset_selection, reload_global, refresh, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
app_object |
Cascade app object |
filtered |
barcodes to filter object |
genes_to_plot |
reactive list with genes in scratchpad |
args |
reactive list with elements: 'assay' for selected assay, 'dimred' for which dimension reduction to use and 'grp_by' for grouping variable |
gene_choices |
reactive list with all genes present in object |
all_selected |
reactive containing list of selected points |
show_selection |
reactive to show selection |
reset_selection |
reactive to reset selection |
reload_global |
reactive to trigger reload |
refresh |
reactive to trigger plot refresh from sidebar button |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for feature plot Server returns reactive expression containing selected points from the feature plot
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(featurePlotUI("feature", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(featurePlotUI("feature", "main")), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- featurePlotServer( "feature", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ "GeneA" }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(featurePlotUI("feature", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(featurePlotUI("feature", "main")), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- featurePlotServer( "feature", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ "GeneA" }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
This function checks for an environment variable 'CASCADE_ACCESS_YAML' to specify directory containing access yaml. If env variable does not exist uses home directory as save location.
get_access_path()get_access_path()
path to access yaml
The expression of a gene present in columns of a data frame are binned based either on the range of observed expression ('range') or quantiles of cells where the gene is expressed.
get_binned_exp(df, bins = 100, mode = "range")get_binned_exp(df, bins = 100, mode = "range")
df |
data.frame with expression data |
bins |
number of bins |
mode |
how to calculate bins? options are 'range' or 'quantile' |
data.frame
This interactive legend is shown in the sidebar to help visually select coexpression blend threshold.
get_coexp_legend( colors, dimnames, xline, yline, n = 100, neutral_color = "lightgray", margin = 0.03 )get_coexp_legend( colors, dimnames, xline, yline, n = 100, neutral_color = "lightgray", margin = 0.03 )
colors |
3-color vector (geneA, geneB, both) |
dimnames |
names to show on x & y axis |
xline |
x-axis threshold |
yline |
y-axis threshold |
n |
number of bins |
neutral_color |
color to use for negative cells |
margin |
plot margin |
plotly handle
get_coexp_legend( colors = c("#ff0000", "#0000ff", "#ff00ff"), dimnames = c("GeneA", "GeneB"), xline = 0.25, yline = 0.75, n = 20, neutral_color = "#eeeeee" )get_coexp_legend( colors = c("#ff0000", "#0000ff", "#ff00ff"), dimnames = c("GeneA", "GeneB"), xline = 0.25, yline = 0.75, n = 20, neutral_color = "#eeeeee" )
Get data frame with counts of cells binned into four categories based on expression of two genes
get_coexp_tbl( df, genes, n = 100, threshold1 = 0.5, threshold2 = 0.5, bin_mode = "range" )get_coexp_tbl( df, genes, n = 100, threshold1 = 0.5, threshold2 = 0.5, bin_mode = "range" )
df |
data.frame with gene expression data |
genes |
genes to calculate coexpression for |
n |
number of bins |
threshold1 |
percentile to define expression for gene 1 |
threshold2 |
percentile to define expression for gene 2 |
bin_mode |
how to bin? can be 'range' (gene expression binned into n bins) or 'quantile' (cells binned into n bins by expression quantiles) |
both genes low
gene A low, gene B high
gene A high, gene B low
gene A high, gene B high
data.frame with co-expression counts
df <- data.frame( GeneA = c(0, 10, 0, 10), GeneB = c(0, 0, 10, 10) ) get_coexp_tbl(df, genes = c("GeneA", "GeneB"), n = 10)df <- data.frame( GeneA = c(0, 10, 0, 10), GeneB = c(0, 0, 10, 10) ) get_coexp_tbl(df, genes = c("GeneA", "GeneB"), n = 10)
Function to return coexpression plot colormaps
get_coexplt_colors(x)get_coexplt_colors(x)
x |
character, name of color map. Can be 'red-blue' or 'red-green' |
4 color vector: (neutral, gene A, gene B, merge)
This function reads the config.yaml and returns the list
get_config()get_config()
list containing config items
cfg <- get_config()cfg <- get_config()
Plotly trace to add labels to existing plot.
get_label_trace(plot_data, labeled_pts, split = FALSE)get_label_trace(plot_data, labeled_pts, split = FALSE)
plot_data |
plotly plot data |
labeled_pts |
points to label |
split |
column by which plot is split |
plotly handle
This function calculates the limits of a numeric vector and returns them after rounding to specified number of significant digits.
get_limits(gq, sig_digits = 3, na.rm = TRUE)get_limits(gq, sig_digits = 3, na.rm = TRUE)
gq |
numeric vector |
sig_digits |
significant digits for rounding |
na.rm |
remove NAs? Default: TRUE |
vector of length 2 with min, max
This function takes in a path to an RDS file and returns a string to be used as project name
get_project_name_from_path( x, depth = 2, end_offset = 0, staging_dir = "staged", fsep = .Platform$file.sep )get_project_name_from_path( x, depth = 2, end_offset = 0, staging_dir = "staged", fsep = .Platform$file.sep )
x |
character path to RDS file |
depth |
integer how many levels below path to look? |
end_offset |
integer how far from the end of path to end? |
staging_dir |
name of staging directory |
fsep |
file separator to split path with |
So if the path is: /path/to/project/test/clustered.Rds and depth=2 & end_offset=0 this returns: project/test
project name
get_project_name_from_path( "/path/to/project/test/clustered.Rds", depth = 2, fsep = "/" ) get_project_name_from_path( "/path/project/staged/test/clustered.Rds", depth = 2, staging_dir = "staged", fsep = "/" )get_project_name_from_path( "/path/to/project/test/clustered.Rds", depth = 2, fsep = "/" ) get_project_name_from_path( "/path/project/staged/test/clustered.Rds", depth = 2, staging_dir = "staged", fsep = "/" )
This function calculates most variable genes from either Seurat or anndata objects.
get_var_genes(obj, obj_type, assay_name)get_var_genes(obj, obj_type, assay_name)
obj |
object to get variable genes from |
obj_type |
type of object being used. can be 'seurat' or 'anndata' |
assay_name |
name of assay for variable genes. Ignored if obj_type == 'anndata'. |
vector of gene names
Module UI & server for help buttons.
helpButtonUI(id) helpButtonServer(id, ...)helpButtonUI(id) helpButtonServer(id, ...)
id |
Module id. This also doubles as prefixes for help text files. |
... |
other params passed to helpModal() |
UI returns tagList with help button UI. Server invisibly returns NULL (used for side effects).
library(shiny) # app with a single help button to show DE summary table details if(interactive()){ shinyApp( ui = fluidPage( helpButtonUI('dimred_help') ), server = function(input, output, session){ helpButtonServer('dimred_help') } ) }library(shiny) # app with a single help button to show DE summary table details if(interactive()){ shinyApp( ui = fluidPage( helpButtonUI('dimred_help') ), server = function(input, output, session){ helpButtonServer('dimred_help') } ) }
This generates a modal dialog that includes text from a markdown file.
helpModal(mdfile, title = NULL, ...)helpModal(mdfile, title = NULL, ...)
mdfile |
path to markdown file |
title |
Title of modal dialog |
... |
other params passed to modalDialog() |
Shiny modal dialog
This function installs 'plotly' and 'kaleido' python packages in an environment to allow PDF downloads from plotly plots, and 'anndata' to allow h5ad files.
install_cascade(envname, ...)install_cascade(envname, ...)
envname |
name of the python environment |
... |
parameters passed to reticulate::py_install |
Return value from reticulate::py_install(); called for the side effect of installing Python packages.
install_cascade()install_cascade()
Line plot module
linePlotUI(id, panel) linePlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, reload_global, refresh, config )linePlotUI(id, panel) linePlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, reload_global, refresh, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
app_object |
Cascade app object |
filtered |
barcodes to filter object |
genes_to_plot |
reactive list with genes in scratchpad |
args |
reactive list with elements: 'assay' for selected assay, 'dimred' for which dimension reduction to use and 'grp_by' for grouping variable |
gene_choices |
reactive list with all genes present in object |
reload_global |
reactive to trigger reload |
refresh |
reactive to trigger plot refresh from sidebar button |
config |
reactive list with config settings |
Shiny UI & server elements for the line plot module
Shiny module server return value; called for the side effect of rendering a line plot.
This creates a small normalized Seurat object with an RNA assay, metadata, identities, and a two-dimensional UMAP reduction. It is intended for documentation examples and lightweight module demos.
make_example_seurat_object( genes = paste0("Gene", LETTERS[seq_len(4)]), cells = paste0("cell", seq_len(8)), assay = "RNA" )make_example_seurat_object( genes = paste0("Gene", LETTERS[seq_len(4)]), cells = paste0("cell", seq_len(8)), assay = "RNA" )
genes |
character vector of gene names to include. |
cells |
character vector of cell names to include. |
assay |
assay name to use when creating the object. |
A Seurat object.
obj <- make_example_seurat_object() objobj <- make_example_seurat_object() obj
Marker plots module
markerPlotUI(id, panel) markerPlotServer( id, obj, filtered, genes_to_plot, args, gene_choices, all_selected, show_selection, reset_selection, reload_global, config )markerPlotUI(id, panel) markerPlotServer( id, obj, filtered, genes_to_plot, args, gene_choices, all_selected, show_selection, reset_selection, reload_global, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
obj |
Cascade app object |
filtered |
barcodes to filter object |
genes_to_plot |
reactive list with genes in scratchpad |
args |
reactive list with elements: 'assay' for selected assay, 'dimred' for which dimension reduction to use and 'grp_by' for grouping variable |
gene_choices |
reactive list with all genes present in object |
all_selected |
reactive containing list of selected points |
show_selection |
reactive to show selection |
reset_selection |
reactive to reset selection |
reload_global |
reactive to trigger reload |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for marker plots Server returns reactive expression containing selected points from marker plot modules
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = list( all = metadata_levels, filtered = metadata_levels ), cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(markerPlotUI("markers", "sidebar")), shiny::mainPanel( markerPlotUI("markers", "main"), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- markerPlotServer( "markers", obj = app_object, filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = list( all = metadata_levels, filtered = metadata_levels ), cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(markerPlotUI("markers", "sidebar")), shiny::mainPanel( markerPlotUI("markers", "main"), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- markerPlotServer( "markers", obj = app_object, filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
Generalized marker table module
markerTableGeneralUI(id, panel, type, label = NULL) markerTableGeneralServer( id, obj, type, genes_to_plot, reset_genes, global_args, args, reload_global, config )markerTableGeneralUI(id, panel, type, label = NULL) markerTableGeneralServer( id, obj, type, genes_to_plot, reset_genes, global_args, args, reload_global, config )
id |
Input id |
panel |
string, can be 'sidebar', 'selection' or 'main' |
type |
string, used to define type of table |
label |
string, label for table |
obj |
reactive list with marker tables |
genes_to_plot |
reactive list of genes to plot |
reset_genes |
reactive to trigger gene selection reset |
global_args |
reactive list with global settings |
args |
reactive list with 'max_padj', 'max_lfc' |
reload_global |
reactive to trigger global args reload |
config |
reactive list with config settings |
UI returns sidebar/selection/main panel UI elements for a marker table Server returns reactive expression containing marker filters and selected genes
marker_tbl <- data.frame( gene = c("GeneA", "GeneB", "GeneC", "GeneD"), cluster = c("A", "A", "B", "B"), avg_log2FC = c(1.2, 0.7, 1.1, 0.8), pct.1 = c(0.9, 0.8, 0.85, 0.75), pct.2 = c(0.2, 0.3, 0.25, 0.35), p_val_adj = c(0.001, 0.02, 0.005, 0.03) ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel( markerTableGeneralUI( "allmarkers", panel = "sidebar", type = "allmarkers", label = "Cluster Markers" ), markerTableGeneralUI( "allmarkers", panel = "selection", type = "allmarkers", label = "Cluster Markers" ) ), shiny::mainPanel( shiny::tabsetPanel( markerTableGeneralUI( "allmarkers", panel = "main", type = "allmarkers", label = "Cluster Markers" ) ), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- markerTableGeneralServer( "allmarkers", obj = shiny::reactive({ list(markers = marker_tbl) }), type = "allmarkers", genes_to_plot = shiny::reactive({ character() }), reset_genes = shiny::reactive({ NULL }), global_args = shiny::reactive({ list() }), args = shiny::reactive({ list(max_padj = 0.1, min_lfc = 0) }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)marker_tbl <- data.frame( gene = c("GeneA", "GeneB", "GeneC", "GeneD"), cluster = c("A", "A", "B", "B"), avg_log2FC = c(1.2, 0.7, 1.1, 0.8), pct.1 = c(0.9, 0.8, 0.85, 0.75), pct.2 = c(0.2, 0.3, 0.25, 0.35), p_val_adj = c(0.001, 0.02, 0.005, 0.03) ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel( markerTableGeneralUI( "allmarkers", panel = "sidebar", type = "allmarkers", label = "Cluster Markers" ), markerTableGeneralUI( "allmarkers", panel = "selection", type = "allmarkers", label = "Cluster Markers" ) ), shiny::mainPanel( shiny::tabsetPanel( markerTableGeneralUI( "allmarkers", panel = "main", type = "allmarkers", label = "Cluster Markers" ) ), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- markerTableGeneralServer( "allmarkers", obj = shiny::reactive({ list(markers = marker_tbl) }), type = "allmarkers", genes_to_plot = shiny::reactive({ character() }), reset_genes = shiny::reactive({ NULL }), global_args = shiny::reactive({ list() }), args = shiny::reactive({ list(max_padj = 0.1, min_lfc = 0) }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
This is a master wrapper for generalized marker tables.
markerTableUI(id, panel) markerTableServer(id, obj, genes_to_plot, reset_genes, reload_global, config)markerTableUI(id, panel) markerTableServer(id, obj, genes_to_plot, reset_genes, reload_global, config)
id |
Input id |
panel |
string, can be 'global', 'sidebar', 'selection' or 'main' |
obj |
Cascade app object |
genes_to_plot |
reactive with list of genes to be plotted/selected |
reset_genes |
reactive to trigger gene selection reset |
reload_global |
reactive to trigger reload |
config |
reactive list with config settings |
UI returns global/sidebar/selection/main panel UI elements for marker tables Server returns reactive expression containing selected marker genes
# example obj obj <- make_example_seurat_object() marker_tbl <- data.frame( gene = c("GeneA", "GeneB", "GeneC", "GeneD"), cluster = c("A", "A", "B", "B"), avg_log2FC = c(1.2, 0.7, 1.1, 0.8), pct.1 = c(0.9, 0.8, 0.85, 0.75), pct.2 = c(0.2, 0.3, 0.25, 0.35), p_val_adj = c(0.001, 0.02, 0.005, 0.03) ) app_object <- list( rds = obj, allmarkers = marker_tbl, consmarkers = NULL, demarkers = NULL ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel( markerTableUI("markers", "global"), markerTableUI("markers", "sidebar"), markerTableUI("markers", "selection") ), shiny::mainPanel( markerTableUI("markers", "main"), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- markerTableServer( "markers", obj = app_object, genes_to_plot = shiny::reactive({ character() }), reset_genes = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() marker_tbl <- data.frame( gene = c("GeneA", "GeneB", "GeneC", "GeneD"), cluster = c("A", "A", "B", "B"), avg_log2FC = c(1.2, 0.7, 1.1, 0.8), pct.1 = c(0.9, 0.8, 0.85, 0.75), pct.2 = c(0.2, 0.3, 0.25, 0.35), p_val_adj = c(0.001, 0.02, 0.005, 0.03) ) app_object <- list( rds = obj, allmarkers = marker_tbl, consmarkers = NULL, demarkers = NULL ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel( markerTableUI("markers", "global"), markerTableUI("markers", "sidebar"), markerTableUI("markers", "selection") ), shiny::mainPanel( markerTableUI("markers", "main"), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- markerTableServer( "markers", obj = app_object, genes_to_plot = shiny::reactive({ character() }), reset_genes = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
This is a stripped-down lightweight version of Seurat's internal function adapted for an anndata object that has genes in columns not rows.
PseudoBulkExpression2( object, pb.method = "average", features = NULL, group.by = "ident" )PseudoBulkExpression2( object, pb.method = "average", features = NULL, group.by = "ident" )
object |
anndata object |
pb.method |
pseudo-bulk method. Can be 'average' (default) or 'aggregate'. |
features |
features to analyze. Default is all features in the object |
group.by |
metadata column to group cells by |
matrix with pseudo-bulk counts
This function reads the access yaml file and returns user groups and data areas as a list of data frames.
read_access_yaml()read_access_yaml()
list with user group and data area settings
local({ access_dir <- tempfile("cascade-access-") dir.create(access_dir) old <- Sys.getenv("CASCADE_ACCESS_YAML", unset = NA_character_) Sys.setenv(CASCADE_ACCESS_YAML = access_dir) on.exit({ if (is.na(old)) { Sys.unsetenv("CASCADE_ACCESS_YAML") } else { Sys.setenv(CASCADE_ACCESS_YAML = old) } unlink(access_dir, recursive = TRUE) }) create_access_yaml("user1", "lab1", "/data/lab1") read_access_yaml() })local({ access_dir <- tempfile("cascade-access-") dir.create(access_dir) old <- Sys.getenv("CASCADE_ACCESS_YAML", unset = NA_character_) Sys.setenv(CASCADE_ACCESS_YAML = access_dir) on.exit({ if (is.na(old)) { Sys.unsetenv("CASCADE_ACCESS_YAML") } else { Sys.setenv(CASCADE_ACCESS_YAML = old) } unlink(access_dir, recursive = TRUE) }) create_access_yaml("user1", "lab1", "/data/lab1") read_access_yaml() })
Interactive shiny dashboard for exploring single-cell or spatial RNA-Seq data.
run_cascade(credentials = NULL, passphrase = NULL, enable_admin = TRUE, ...)run_cascade(credentials = NULL, passphrase = NULL, enable_admin = TRUE, ...)
credentials |
path to encrypted sqlite db with user credentials. |
passphrase |
passphrase for credentials db. |
enable_admin |
if TRUE, admin view is shown. Note, this is only available if credentials have sqlite backend. |
... |
parameters passed to shinyApp() call |
Shiny app object
shiny::runApp( run_cascade() )shiny::runApp( run_cascade() )
This function removes special characters from strings. Meant to be used to sanitize column names of a data frame before plotting.
sanitize_colnames(cnames, bad_char = "\\W+", repl = "_")sanitize_colnames(cnames, bad_char = "\\W+", repl = "_")
cnames |
column names to sanitize |
bad_char |
regex with characters to be replaced with 'repl' |
repl |
replacement character |
sanitized string vector
This function saves access details (user groups and data areas) to the designated access yaml file.
save_access_yaml(lst)save_access_yaml(lst)
lst |
list of data frames with user_groups and data_areas |
Invisibly returns NULL; called for the side effect of writing the access yaml file.
local({ access_dir <- tempfile("cascade-access-") dir.create(access_dir) old <- Sys.getenv("CASCADE_ACCESS_YAML", unset = NA_character_) Sys.setenv(CASCADE_ACCESS_YAML = access_dir) on.exit({ if (is.na(old)) { Sys.unsetenv("CASCADE_ACCESS_YAML") } else { Sys.setenv(CASCADE_ACCESS_YAML = old) } unlink(access_dir, recursive = TRUE) }) save_access_yaml(list( user_group = list(user1 = "lab1", user2 = "lab2"), data_area = list(lab1 = "/data/lab1", lab2 = "/data/lab2") )) read_access_yaml() })local({ access_dir <- tempfile("cascade-access-") dir.create(access_dir) old <- Sys.getenv("CASCADE_ACCESS_YAML", unset = NA_character_) Sys.setenv(CASCADE_ACCESS_YAML = access_dir) on.exit({ if (is.na(old)) { Sys.unsetenv("CASCADE_ACCESS_YAML") } else { Sys.setenv(CASCADE_ACCESS_YAML = old) } unlink(access_dir, recursive = TRUE) }) save_access_yaml(list( user_group = list(user1 = "lab1", user2 = "lab2"), data_area = list(lab1 = "/data/lab1", lab2 = "/data/lab2") )) read_access_yaml() })
Gene-gene scatter plot module
scatterPlotUI(id, panel) scatterPlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, all_selected, show_selection, reset_selection, reload_global, refresh, config )scatterPlotUI(id, panel) scatterPlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, all_selected, show_selection, reset_selection, reload_global, refresh, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
app_object |
Cascade app object |
filtered |
barcodes to filter object |
genes_to_plot |
reactive list with genes in scratchpad |
args |
reactive list with elements: 'assay' for selected assay, 'dimred' for which dimension reduction to use and 'grp_by' for grouping variable |
gene_choices |
reactive list with all genes present in object |
all_selected |
reactive containing list of selected points |
show_selection |
reactive to show selection |
reset_selection |
reactive to reset selection |
reload_global |
reactive to trigger reload |
refresh |
reactive to trigger plot refresh from sidebar button |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for scatter plot Server returns reactive expression containing selected points from the scatter plot
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap", assay_list = list(RNA = c("counts", "data")) ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(scatterPlotUI("scatter", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(scatterPlotUI("scatter", "main")), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- scatterPlotServer( "scatter", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap", assay_list = list(RNA = c("counts", "data")) ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(scatterPlotUI("scatter", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(scatterPlotUI("scatter", "main")), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- scatterPlotServer( "scatter", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
UI & server for selection module
selectionUI(id) selectionServer(id, selections, obj)selectionUI(id) selectionServer(id, selections, obj)
id |
Input id |
selections |
reactive list w selections |
obj |
reactive app object |
Shiny UI & server for the download selection button module
Module UI & server for user access details interface.
settingsUI(id, panel, username) settingsServer(id, details, depth, end_offset, assay_fun, config)settingsUI(id, panel, username) settingsServer(id, details, depth, end_offset, assay_fun, config)
id |
Module id |
panel |
context for generating ui elements ('sidebar' or 'main') |
username |
user name |
details |
reactive list with user name & app location details |
depth |
project name depth |
end_offset |
project name end offset |
assay_fun |
function to parse assay names from file path |
config |
reactive list with config settings |
UI returns tagList with module UI Server returns reactive with list containing user access details
library(shiny) # default username username <- reactive({ NULL }) # internal carnation config config <- reactiveVal(get_config()) # regex to find carnation files pattern <- reactive({ config()$server$pattern }) # access permissions assay.list <- reactiveValues(l=read_access_yaml()) if(interactive()){ shinyApp( ui = fluidPage( sidebarPanel(uiOutput('settings_sidebar')), mainPanel(uiOutput('settings_main')) ), server = function(input, output, session){ output$settings_main <- renderUI({ settingsUI('settings', panel='main', username=username) }) output$settings_sidebar <- renderUI({ settingsUI('settings', panel='sidebar', username=username) }) settings <- settingsServer('p', details=reactive({ list(username=username, where=NULL) }), depth=3, end_offset=1, assay_fun=function(x) basename(dirname(x)), config ) } ) }library(shiny) # default username username <- reactive({ NULL }) # internal carnation config config <- reactiveVal(get_config()) # regex to find carnation files pattern <- reactive({ config()$server$pattern }) # access permissions assay.list <- reactiveValues(l=read_access_yaml()) if(interactive()){ shinyApp( ui = fluidPage( sidebarPanel(uiOutput('settings_sidebar')), mainPanel(uiOutput('settings_main')) ), server = function(input, output, session){ output$settings_main <- renderUI({ settingsUI('settings', panel='main', username=username) }) output$settings_sidebar <- renderUI({ settingsUI('settings', panel='sidebar', username=username) }) settings <- settingsServer('p', details=reactive({ list(username=username, where=NULL) }), depth=3, end_offset=1, assay_fun=function(x) basename(dirname(x)), config ) } ) }
Spatial coexpression plot module
spatialCoexpressionPlotUI(id, panel) spatialCoexpressionPlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, slice, all_selected, show_selection, reset_selection, reload_global, refresh, config )spatialCoexpressionPlotUI(id, panel) spatialCoexpressionPlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, slice, all_selected, show_selection, reset_selection, reload_global, refresh, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
app_object |
Cascade app object |
filtered |
barcodes to filter object |
genes_to_plot |
reactive list with genes in scratchpad |
args |
reactive list with elements: 'assay' for selected assay, 'dimred' for which dimension reduction to use and 'grp_by' for grouping variable |
gene_choices |
reactive list with all genes present in object |
slice |
reactive with slices to be used for plotting |
all_selected |
reactive containing list of selected points |
show_selection |
reactive to show selection |
reset_selection |
reactive to reset selection |
reload_global |
reactive to trigger reload |
refresh |
reactive to trigger plot refresh from sidebar button |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for spatial coexpression plot Server returns reactive expression containing selected points from the spatial coexpression plot
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) spatial_coords <- data.frame( rn = colnames(obj), slice = as.character(metadata$orig.ident), imagecol = rep(c(1, 2, 1, 2), length.out = ncol(obj)), imagerow = rep(c(1, 1, 2, 2), length.out = ncol(obj)), stringsAsFactors = FALSE ) imagerow_max <- as.list( tapply(spatial_coords$imagerow, spatial_coords$slice, max) ) imagerow_min <- as.list( tapply(spatial_coords$imagerow, spatial_coords$slice, min) ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = spatial_coords, imagerow_max = imagerow_max, imagerow_min = imagerow_min ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(spatialCoexpressionPlotUI("spatial_coexp", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(spatialCoexpressionPlotUI("spatial_coexp", "main")), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- spatialCoexpressionPlotServer( "spatial_coexp", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), slice = shiny::reactive({ unique(spatial_coords$slice)[1] }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) spatial_coords <- data.frame( rn = colnames(obj), slice = as.character(metadata$orig.ident), imagecol = rep(c(1, 2, 1, 2), length.out = ncol(obj)), imagerow = rep(c(1, 1, 2, 2), length.out = ncol(obj)), stringsAsFactors = FALSE ) imagerow_max <- as.list( tapply(spatial_coords$imagerow, spatial_coords$slice, max) ) imagerow_min <- as.list( tapply(spatial_coords$imagerow, spatial_coords$slice, min) ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = spatial_coords, imagerow_max = imagerow_max, imagerow_min = imagerow_min ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(spatialCoexpressionPlotUI("spatial_coexp", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(spatialCoexpressionPlotUI("spatial_coexp", "main")), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- spatialCoexpressionPlotServer( "spatial_coexp", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), slice = shiny::reactive({ unique(spatial_coords$slice)[1] }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
Spatial feature plot module
spatialFeaturePlotUI(id, panel) spatialFeaturePlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, slice, all_selected, show_selection, reset_selection, reload_global, refresh, config )spatialFeaturePlotUI(id, panel) spatialFeaturePlotServer( id, app_object, filtered, genes_to_plot, args, gene_choices, slice, all_selected, show_selection, reset_selection, reload_global, refresh, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
app_object |
Cascade app object |
filtered |
barcodes to filter object |
genes_to_plot |
reactive list with genes in scratchpad |
args |
reactive list with elements: 'assay' for selected assay, 'dimred' for which dimension reduction to use and 'grp_by' for grouping variable |
gene_choices |
reactive list with all genes present in object |
slice |
reactive with slices to be used for plotting |
all_selected |
reactive containing list of selected points |
show_selection |
reactive to show selection |
reset_selection |
reactive to reset selection |
reload_global |
reactive to trigger reload |
refresh |
reactive to trigger plot refresh from sidebar button |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for spatial feature plot Server returns reactive expression containing selected points from the spatial feature plot
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) spatial_coords <- data.frame( rn = colnames(obj), slice = as.character(metadata$orig.ident), imagecol = rep(c(1, 2, 1, 2), length.out = ncol(obj)), imagerow = rep(c(1, 1, 2, 2), length.out = ncol(obj)), stringsAsFactors = FALSE ) imagerow_max <- as.list( tapply(spatial_coords$imagerow, spatial_coords$slice, max) ) imagerow_min <- as.list( tapply(spatial_coords$imagerow, spatial_coords$slice, min) ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = spatial_coords, imagerow_max = imagerow_max, imagerow_min = imagerow_min ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(spatialFeaturePlotUI("spatial_feature", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(spatialFeaturePlotUI("spatial_feature", "main")), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- spatialFeaturePlotServer( "spatial_feature", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ "GeneA" }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), slice = shiny::reactive({ unique(spatial_coords$slice)[1] }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) spatial_coords <- data.frame( rn = colnames(obj), slice = as.character(metadata$orig.ident), imagecol = rep(c(1, 2, 1, 2), length.out = ncol(obj)), imagerow = rep(c(1, 1, 2, 2), length.out = ncol(obj)), stringsAsFactors = FALSE ) imagerow_max <- as.list( tapply(spatial_coords$imagerow, spatial_coords$slice, max) ) imagerow_min <- as.list( tapply(spatial_coords$imagerow, spatial_coords$slice, min) ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = spatial_coords, imagerow_max = imagerow_max, imagerow_min = imagerow_min ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shinyjs::useShinyjs(), shiny::sidebarLayout( shiny::sidebarPanel(spatialFeaturePlotUI("spatial_feature", "sidebar")), shiny::mainPanel( shiny::tabsetPanel(spatialFeaturePlotUI("spatial_feature", "main")), shiny::verbatimTextOutput("selected") ) ) ) server <- function(input, output, session) { selected <- spatialFeaturePlotServer( "spatial_feature", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ "GeneA" }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), slice = shiny::reactive({ unique(spatial_coords$slice)[1] }), all_selected = shiny::reactive({ list() }), show_selection = shiny::reactive({ NULL }), reset_selection = shiny::reactive({ NULL }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) output$selected <- shiny::renderPrint({ selected() }) } shiny::shinyApp(ui, server)
Filter settings module server
subsetServer(id, obj, args, metadata_args, gene_choices, selected_points)subsetServer(id, obj, args, metadata_args, gene_choices, selected_points)
id |
Input id |
obj |
Cascade app object |
args |
reactive list with 'assay' with name of selected assay |
metadata_args |
reactive list with 'factor_levels' that has levels of categorical metadata & 'numeric_dist' that has distributions of numeric metadata |
gene_choices |
reactive list with all genes present in object |
selected_points |
reactive list with cell selections |
reactive expression containing filtered cell barcodes
Filter settings module ui
subsetUI(id)subsetUI(id)
id |
Input id |
Shiny UI elements for the filter settings module
Summary tab module
summaryUI(id, panel) summaryServer(id, obj, args)summaryUI(id, panel) summaryServer(id, obj, args)
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
obj |
Cascade app object |
args |
reactive with global arguments, 'project' & 'analysis' |
UI returns sidebar and main panel UI elements for summary module Server called for the side effect of rendering summary output.
obj <- make_example_seurat_object() app_object <- list( rds = obj, obj_type = "seurat", metadata = obj[[]], qc = NULL ) ui <- shiny::fluidPage( shiny::sidebarPanel(summaryUI("summary", "sidebar")), shiny::mainPanel(summaryUI("summary", "main")) ) server <- function(input, output, session) { summaryServer( "summary", obj = app_object, args = shiny::reactive({ list( project = file.path(tempdir(), "project1"), analysis = file.path(tempdir(), "project1", "analysis1", "object.rds") ) }) ) } shiny::shinyApp(ui, server)obj <- make_example_seurat_object() app_object <- list( rds = obj, obj_type = "seurat", metadata = obj[[]], qc = NULL ) ui <- shiny::fluidPage( shiny::sidebarPanel(summaryUI("summary", "sidebar")), shiny::mainPanel(summaryUI("summary", "main")) ) server <- function(input, output, session) { summaryServer( "summary", obj = app_object, args = shiny::reactive({ list( project = file.path(tempdir(), "project1"), analysis = file.path(tempdir(), "project1", "analysis1", "object.rds") ) }) ) } shiny::shinyApp(ui, server)
Interactive umap plot
umap_ly( df, xcol, ycol, color, colors, split = NULL, label_cols = NULL, showlegend = TRUE, showticklabels = TRUE, type = "scatter", highlight_click = TRUE, marker_size = 2, margin = 0.03, alpha = 0.3, free_axes = FALSE, width = NULL, height = NULL, source = "A" )umap_ly( df, xcol, ycol, color, colors, split = NULL, label_cols = NULL, showlegend = TRUE, showticklabels = TRUE, type = "scatter", highlight_click = TRUE, marker_size = 2, margin = 0.03, alpha = 0.3, free_axes = FALSE, width = NULL, height = NULL, source = "A" )
df |
data.frame with plotting data |
xcol |
x-axis coordinates |
ycol |
y-axis coordinates |
color |
column to color markers by |
colors |
colors to use for markers |
split |
metadata column to split by |
label_cols |
Additional metadata columns to use for labeling pts |
showlegend |
should legend be shown? |
showticklabels |
should tick labels be drawn? |
type |
type of plotly trace (default: 'scatter') |
highlight_click |
should points be highlighted on clicking |
marker_size |
size of markers |
margin |
margin of plot (should be between 0 & 1) |
alpha |
marker opacity |
free_axes |
should subplots have free axes? |
width |
width of plot in pixels. If NULL (default), plot is auto-sized. |
height |
height of plot in pixels. if NULL (default), plot is auto-sized. |
source |
name of source to return data from |
plotly handle
df <- data.frame( UMAP_1 = c(-1, 0, 1, 2), UMAP_2 = c(0, 1, 0, -1), cluster = factor(c("A", "A", "B", "B")) ) colors <- c(A = "#4477aa", B = "#cc6677") umap_ly( df, xcol = "UMAP_1", ycol = "UMAP_2", color = "cluster", colors = colors )df <- data.frame( UMAP_1 = c(-1, 0, 1, 2), UMAP_2 = c(0, 1, 0, -1), cluster = factor(c("A", "A", "B", "B")) ) colors <- c(A = "#4477aa", B = "#cc6677") umap_ly( df, xcol = "UMAP_1", ycol = "UMAP_2", color = "cluster", colors = colors )
Violin plot implemented in plotly. This works fine, but is a bit slower/takes the same time as the ggplot version. But the main issue is that combining multiple plots using subplot() results in very skinny violins.
This might be a good option for single gene plots.
violin_ly(df, xcol, ycol, color, colors, showlegend = FALSE)violin_ly(df, xcol, ycol, color, colors, showlegend = FALSE)
df |
data.frame with expression data |
xcol |
x-axis grouping column |
ycol |
values to show on y-axis |
color |
column to split violins by |
colors |
vector of colors to use (not used) |
showlegend |
boolean, should legend be shown? Default: FALSE |
NOTE: not used
plotly handle
Lightweight reimplementation of violin plot with additional splitting features. This works on just a data frame and does not need to be passed the entire object.
violin2( df, xcol, ycol, color = NULL, colors = NULL, draw_points = FALSE, scales = "fixed", text_scale = 1 )violin2( df, xcol, ycol, color = NULL, colors = NULL, draw_points = FALSE, scales = "fixed", text_scale = 1 )
df |
data.frame with expression data |
xcol |
x-axis grouping column |
ycol |
values to show on y-axis |
color |
column to split violins by |
colors |
vector of colors to use (not used) |
draw_points |
show points for each cell? Default: FALSE |
scales |
should y-axis be 'fixed' (default) or 'free' |
text_scale |
scaling factor for text labels. If < 1, text size is reduced and vice-versa |
ggplot2 handle
df <- data.frame( cluster = factor(rep(c("A", "B"), each = 4)), variable = rep(c("GeneA", "GeneB"), times = 4), value = c(0, 2, 4, 5, 1, 3, 6, 8) ) violin2(df, xcol = "cluster", ycol = "value")df <- data.frame( cluster = factor(rep(c("A", "B"), each = 4)), variable = rep(c("GeneA", "GeneB"), times = 4), value = c(0, 2, 4, 5, 1, 3, 6, 8) ) violin2(df, xcol = "cluster", ycol = "value")
Violin plot module
violinUI(id, panel) violinServer( id, app_object, filtered, genes_to_plot, args, gene_choices, reload_global, refresh, config )violinUI(id, panel) violinServer( id, app_object, filtered, genes_to_plot, args, gene_choices, reload_global, refresh, config )
id |
Input id |
panel |
string, can be 'sidebar' or 'main' |
app_object |
Cascade app object |
filtered |
barcodes to filter object |
genes_to_plot |
reactive list with genes in scratchpad |
args |
reactive list with elements: 'assay' for selected assay, 'dimred' for which dimension reduction to use and 'grp_by' for grouping variable |
gene_choices |
reactive list with all genes present in object |
reload_global |
reactive to trigger reload |
refresh |
reactive to trigger plot refresh from sidebar button |
config |
reactive list with config settings |
UI returns sidebar/main panel UI elements for violin plot Server called for the side effect of rendering a violin plot.
# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shiny::sidebarLayout( shiny::sidebarPanel(violinUI("violin", "sidebar")), shiny::mainPanel(shiny::tabsetPanel(violinUI("violin", "main"))) ) ) server <- function(input, output, session) { violinServer( "violin", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) } shiny::shinyApp(ui, server)# example obj obj <- make_example_seurat_object() # prep metadata metadata <- obj[[]] metadata_levels <- lapply( metadata[c("cluster", "condition", "orig.ident", "seurat_clusters")], levels ) # get grouping vars and colors grouping_vars <- names(metadata_levels) names(grouping_vars) <- paste0( grouping_vars, " (n = ", lengths(metadata_levels), ")" ) cluster_colors <- lapply(metadata_levels, function(lvls) { stats::setNames(rep_len(c("#4477aa", "#cc6677"), length(lvls)), lvls) }) app_object <- list( rds = obj, obj_type = "seurat", metadata = metadata, metadata_levels = metadata_levels, cluster_colors = cluster_colors, grouping_vars = grouping_vars, spatial_coords = NULL, imagerow_max = NULL, imagerow_min = NULL ) global_args <- list( assay = "RNA", slot = "data", grp_by = "cluster", dimred = "umap" ) config <- get_config() ui <- shiny::fluidPage( shiny::sidebarLayout( shiny::sidebarPanel(violinUI("violin", "sidebar")), shiny::mainPanel(shiny::tabsetPanel(violinUI("violin", "main"))) ) ) server <- function(input, output, session) { violinServer( "violin", app_object = shiny::reactive({ app_object }), filtered = shiny::reactive({ colnames(obj) }), genes_to_plot = shiny::reactive({ c("GeneA", "GeneB") }), args = shiny::reactive({ global_args }), gene_choices = shiny::reactive({ rownames(obj) }), reload_global = shiny::reactiveVal(0), refresh = shiny::reactiveVal(0), config = shiny::reactive({ config }) ) } shiny::shinyApp(ui, server)