Nothing
# -----------------------------------------------------------------------------
# Helper functions to modify the server side of the shiny app
# -----------------------------------------------------------------------------
# Function to generate colours
.create_colours <- function(x){
cur_col <- c("#70C389", "#39BEB4", "#3F85A7", "#494579", "#5B1C55",
"#971B4B", "#C81F43", "#F26738", "#F79C1D", "#F7CD0F",
"#EBE24A", "#B4D55A")
return(cur_col[x])
}
# Function to report gate bounds
.brushRange <- function(brush) {
if (is.null(brush)) {
return(NULL)
}
paste0("xmin = ", round(brush$xmin, 1), " xmax = ", round(brush$xmax, 1),
" ymin = ", round(brush$ymin, 1), " ymax = ", round(brush$ymax, 1))
}
# Helper function to clear objects
.clearObjects <- function(objValues, iter){
lapply(seq_len(length(reactiveValuesToList(objValues))), function(cur_obj){
if (cur_obj > iter) {
objValues[[paste0("object", cur_obj)]] <- NULL
}
})
}
# Helper function to reset brush
.clearBrush <- function(input, session, iter){
cur_brushs <- reactiveValuesToList(input)
cur_brushs <- cur_brushs[grepl("plot_brush", names(cur_brushs))]
lapply(seq_len(length(cur_brushs)), function(cur_obj){
if (cur_obj > iter) {
session$resetBrush(paste0("plot_brush", cur_obj))
}
})
}
# Generate help text
.general_help <- function(){
tagList(
h3("Using the Shiny application"),
p("This help page provides a recommended workflow on how to most ",
"efficiently use the app. The workflow is solely a recommendation - ",
"the app provides full flexibility to change settings during each ",
"step. To see the full documentation, please refer to the help page ",
"found at", em("?cytomapperShiny")),
h3("1. Select the number of plots"),
p("The slider under ", em("General controls"),
" can be used to specify ",
"the number of plots on which to perform gating. Up to two markers ",
"can be visualized per plot."),
h3("2. Select the sample"),
p("The ", em("assay"), " dropdown selection under ",
em("General controls"), " allows the user to specify on",
"which assay entry to perform gating. In most cases, a log- or ",
"arcsinh-transformation can help to distinguish between 'positive' ",
"and 'negative' populations."),
h3("3. Select the markers"),
p("For each plot, up to two markers can be specified. If selecting ",
"a single marker, please specify this marker in the first of the ",
"two dropdown menus. A violin plot is used to visualize the ",
"expression of a single marker while a scatter plot is used to ",
"visualize the expression of two markers."),
h3("4. Gate cells"),
p("When selecting cells in one plot, only those cells are visualized ",
"on the following plot. Once markers, the assay or the number of ",
"plots are changed, gates are cleared."),
h3("5. Observe the selected cells"),
p("After gating, the selected cells are visualized on the ",
"corresponding images by switching to the ",
em("Images"), " tab. By default, the first marker is selected. ",
"The user can change the displayed marker or press reset marker ",
"to switch to the markers used for gating. If a multi-channel ",
"image object is provided, the contrast of the image can be ",
"changed. The right panel visualizes the selected cells either ",
"by filling in the segmentation masks or by outlining the ",
"cells on the images."),
h3("6. Change samples"),
p("Samples can now be iteratively changed using the dropdown ",
"menu under ", em("General controls"), ". The gates will remain ",
"on the plots and can be adjusted for each sample."),
h3("7. Save the selected cells"),
p("Finally, the selected cells can be saved by clicking the download ",
"button next to the '?' symbol. The selected cells will be stored ",
"as a ", em("SingleCellExperiment"), " object in .rds format.",
"Per selection, the user can provide a ", em("Cell label"),
" that will be stored in the ", em("colData"), " under the ",
em("cytomapper_CellLabel"), " entry of the downloaded object.")
)
}
# Create general observers for header
#' @importFrom utils capture.output
.create_general_observer <- function(input, si){
# Return session info
observeEvent(input$SessionInfo, {
showModal(modalDialog(
pre(paste(capture.output(si), collapse = "\n")),
size = "l",fade = TRUE,
footer = NULL, easyClose = TRUE,
title = "Session Info",
))
})
# Return helptext
observeEvent(input$Help, {
showModal(modalDialog(
.general_help(),
size = "l",fade = TRUE,
footer = NULL, easyClose = TRUE,
title = "Help",
))
})
}
# Create interactive observers
#' @importFrom matrixStats rowRanges
.create_interactive_observer <- function(object, img_id, input, session,
rValues, objValues){
# Next Image Observer
observeEvent(input$next.sample, {
img_IDs <- unique(colData(object)[,img_id])
cur_index <- match(input$sample, img_IDs)
updated_index <- ifelse(cur_index == length(img_IDs), 1, cur_index + 1)
# return updated img_id
updated_sample <- img_IDs[updated_index]
updateSelectInput(session, inputId = "sample",
choices = unique(img_IDs),
selected = updated_sample)
}, ignoreInit = TRUE)
# Previous Image Observer
observeEvent(input$previous.sample, {
img_IDs <- unique(colData(object)[,img_id])
cur_index <- match(input$sample, img_IDs)
updated_index <- ifelse(cur_index == 1, length(img_IDs), cur_index - 1)
# return updated img_id
updated_sample <- img_IDs[updated_index]
updateSelectInput(session, inputId = "sample",
choices = unique(img_IDs),
selected = updated_sample)
}, ignoreInit = TRUE)
# Select first object
observeEvent(input$sample, {
objValues$object1 <- object[,colData(object)[,img_id] == input$sample]
updateTabsetPanel(session, "tabbox1",
selected = "tab1")
}, ignoreInit = TRUE)
observeEvent(input$assay, {
# Save ranges
cur_ranges <- rowRanges(assay(object, input$assay))
rownames(cur_ranges) <- rownames(object)
rValues$ranges <- cur_ranges
# Reset gates and objects
.clearObjects(objValues, iter = 1)
.clearBrush(input, session, iter = 1)
}, ignoreInit = TRUE)
# Plot change observer - change tab if number of plots ar changed
observeEvent(input$plotCount, {
updateTabsetPanel(session, "tabbox1",
selected = "tab1")
# Reset gates and objects
.clearObjects(objValues, iter = 1)
.clearBrush(input, session, iter = 0)
})
# Assay change observer - change tab if assay changes
observeEvent(input$assay, {
updateTabsetPanel(session, "tabbox1",
selected = "tab1"
)
# Reset gates and objects
.clearObjects(objValues, iter = 1)
.clearBrush(input, session, iter = 1)
})
# Marker change observer - change tab if markers change
observeEvent({
lapply(seq_len(24), function(cur_mark){
input[[paste0("Marker_", cur_mark)]]
})
}, {
updateTabsetPanel(session, "tabbox1",
selected = "tab1"
)
# Reset gates and objects
.clearObjects(objValues, iter = 1)
.clearBrush(input, session, iter = 1)
})
}
# Create updateSelectizeInput objects
.create_updateSelectizeInput <- function(object, img_id, input, session){
# Store image IDs and marker names
img_IDs <- colData(object)[,img_id]
markers <- rownames(object)
updateSelectizeInput(session, inputId = "sample",
choices = unique(img_IDs),
selected = unique(img_IDs)[1])
updateSelectizeInput(session, inputId = "assay",
choices = assayNames(object),
server = TRUE,
selected = assayNames(object)[1])
observeEvent(input$plotCount, {
for (i in seq_len(input$plotCount)) {
cur_val <- (i * 2) - 1
updateSelectizeInput(session, paste0("Marker_", cur_val),
choices = markers,
server = TRUE,
selected = "")
updateSelectizeInput(session, paste0("Marker_", cur_val + 1),
choices = markers,
server = TRUE,
selected = "")
}
})
observeEvent(input$resetMarkers, {
cur_markers <- .select_markers(input, exprs_marker_update = FALSE)
updateSelectInput(session, "exprs_marker_1",
choices = markers,
selected = cur_markers[1])
updateSelectInput(session, "exprs_marker_2",
choices = markers,
selected = ifelse(length(cur_markers) > 1,
cur_markers[2], ""))
})
}
# Create selectInput options in sidebar
.addPlots_sidebar <- function(input) {
renderUI({
lapply(seq_len(input$plotCount), function(cur_plot) {
cur_val <- (cur_plot * 2) - 1
wellPanel(
h3(paste("Plot", cur_plot), style = "color: black"),
selectizeInput(paste0("Marker_", cur_val),
label = span(paste("Select marker", cur_val),
style = "color: black; padding-top: 0px"),
choices = NULL,
options = list(placeholder = 'Select marker',
maxItems = 1)),
selectizeInput(paste0("Marker_", cur_val + 1),
label = span(paste("Select marker",
cur_val + 1),
style = "color: black; padding-top: 0px"),
choices = NULL,
options = list(placeholder = 'Select marker',
maxItems = 1)),
style = paste0("background-color: ", .create_colours(cur_plot),
"; border-color: ", .create_colours(cur_plot),
"; padding-bottom: 0px; padding-top: 0px"))
})
})
}
.addPlots_tab1 <- function(input) {
renderUI({
cur_row <- ceiling(input$plotCount / 3)
# Generate boxes
box_list <- lapply(seq_len(input$plotCount), function(cur_plot) {
cur_val <- (cur_plot * 2) - 1
# Create brush options
cur_brush_opts <- brushOpts(paste0("plot_brush", cur_plot),
fill = .create_colours(cur_plot),
stroke = .create_colours(cur_plot),
direction = "xy",
resetOnNew = FALSE)
box(plotOutput(paste0("scatter", cur_plot),
brush = cur_brush_opts),
verbatimTextOutput(paste0("info", cur_plot)),
title = paste("Plot", cur_plot),
status = "primary",
width = 4)
})
lapply(seq_len(cur_row), function(cr) {
cur_val <- (cr * 3) - 2
fluidRow(box_list[seq.int(cur_val, cur_val + 2)])
})
})
}
.addPlots_tab2 <- function(input, object, mask, image) {
if (is.null(mask) && is.null(image)) {
return(NULL)
} else if (!is.null(image)) {
contrast_input_1 <- numericInput("contrast_marker_1",
label = span(paste("Contrast marker 1"),
style = "color: black; padding-top: 0px"),
value = 1)
contrast_input_2 <- numericInput("contrast_marker_2",
label = span(paste("Contrast marker 2"),
style = "color: black; padding-top: 0px"),
value = 1)
} else {
contrast_input_1 <- contrast_input_2 <- NULL
}
markers <- rownames(object)
renderUI({
fluidRow(box(column(width = 12,
actionButton("resetMarkers", label = "Reset markers",
style = "background-color: #46EC46; color: black;")),
column(width = 6,
selectInput("exprs_marker_1",
label = span(paste("Select marker 1"),
style = "color: black"),
choices = markers),
contrast_input_1),
column(width = 6,
selectInput("exprs_marker_2",
label = span(paste("Select marker 2"),
style = "color: black"),
choices = c(markers, ""),
selected = ""),
contrast_input_2),
column(width = 12,
svgPanZoomOutput("image_expression", height = "300px")),
title = "Expression", status = "primary",
width = 6, height = "550px"),
box(
column(width = 12,
svgPanZoomOutput("image_selection")),
title = "Selection", id = "selection", status = "primary",
width = 6, height = "550px"))
})
}
# Function to allow brushing
#' @importFrom S4Vectors metadata
#' @importFrom SummarizedExperiment metadata<-
.brushObject <- function(input, session, objValues, iter){
cur_val <- (iter * 2) - 1
if (is.null(objValues[[paste0("object", iter)]])) {
return(NULL)
}
# Build data frame
cur_df <- as.data.frame(t(assay(objValues[[paste0("object", iter)]],
input$assay)))
cur_df$sample <- input$sample
# Brush the data.frame
cur_selection <- brushedPoints(cur_df, input[[paste0("plot_brush", iter)]],
allRows = TRUE)
# Save the Gate
cur_gate <- list()
gate <- matrix(data = c(input[[paste0("plot_brush", iter)]]$xmin,
input[[paste0("plot_brush", iter)]]$xmax,
input[[paste0("plot_brush", iter)]]$ymin,
input[[paste0("plot_brush", iter)]]$ymax),
nrow = 2, ncol = 2,
byrow = TRUE,
dimnames = list(
c(input[[paste0("plot_brush", iter)]]$mapping$x,
input[[paste0("plot_brush", iter)]]$mapping$y),
c("min", "max")
)
)
if (rownames(gate)[1] == "sample") {
gate <- gate[-1, , drop = FALSE]
}
cur_gate$gate <- gate
cur_gate$exprs_values <- input$assay
cur_gate$img_id <- input$sample
# Save gates
next_obj <- objValues[[paste0("object", iter)]]
if (!is.null(metadata(next_obj)) && iter == 1) {
cur_meta <- list(metadata = metadata(next_obj))
cur_meta[[paste0("cytomapper_gate_", iter)]] <- cur_gate
metadata(next_obj) <- cur_meta
} else {
metadata(next_obj)[[paste0("cytomapper_gate_", iter)]] <- cur_gate
}
if (sum(cur_selection$selected_) > 0) {
objValues[[paste0("object", iter + 1)]] <-
next_obj[,cur_selection$selected_]
} else {
# Set next object to NULL
objValues[[paste0("object", iter + 1)]] <- NULL
# Clear all following objects
.clearObjects(objValues, iter)
}
}
# Scatter plot helpers
.plotScatter <- function(input, rValues, objValues, iter, cur_val){
if (!is.null(objValues[[paste0("object", iter)]])) {
cur_df <- as.data.frame(t(assay(objValues[[paste0("object", iter)]],
input$assay)))
cur_df$sample <- input$sample
p <- ggplot(cur_df) +
geom_point(aes_(as.name(input[[paste0("Marker_", cur_val)]]),
as.name(input[[paste0("Marker_", cur_val + 1)]])),
show.legend = FALSE) +
theme(panel.background = element_blank()) +
ylim(c(rValues$ranges[input[[paste0("Marker_", cur_val + 1)]], 1],
rValues$ranges[input[[paste0("Marker_",
cur_val + 1)]], 2])) +
xlim(c(rValues$ranges[input[[paste0("Marker_", cur_val)]], 1],
rValues$ranges[input[[paste0("Marker_", cur_val)]], 2]))
if (!is.null(objValues[[paste0("object", iter + 1)]])) {
cur_df_1 <- as.data.frame(t(assay(objValues[[paste0("object",
iter + 1)]],
input$assay)))
cur_df_1$sample <- input$sample
p <- p + geom_point(aes_(as.name(input[[paste0("Marker_",
cur_val)]]),
as.name(input[[paste0("Marker_",
cur_val + 1)]])),
show.legend = FALSE, data = cur_df_1,
colour = "red")
}
} else {
# We need to simulate a dataframe to allow brushing
cur_df <- data.frame(row.names = "ph")
cur_df[[input[[paste0("Marker_", cur_val)]]]] <- 1
cur_df[[input[[paste0("Marker_", cur_val + 1)]]]] <- 1
p <- ggplot(cur_df) +
geom_blank(aes_(as.name(input[[paste0("Marker_", cur_val)]]),
as.name(input[[paste0("Marker_", cur_val + 1)]])),
show.legend = FALSE) +
ylim(c(rValues$ranges[input[[paste0("Marker_", cur_val + 1)]], 1],
rValues$ranges[input[[paste0("Marker_", cur_val + 1)]], 2])) +
xlim(c(rValues$ranges[input[[paste0("Marker_", cur_val)]], 1],
rValues$ranges[input[[paste0("Marker_", cur_val)]], 2])) +
xlab(input[[paste0("Marker_", cur_val)]]) +
ylab(input[[paste0("Marker_", cur_val + 1)]]) +
theme(panel.background = element_blank())
}
return(p)
}
# Violin plot helper
.plotViolin <- function(input, rValues, objValues, iter, cur_val, cell_id){
if (!is.null(objValues[[paste0("object", iter)]])) {
cur_df <- as.data.frame(t(assay(objValues[[paste0("object", iter)]],
input$assay)))
cur_df$sample <- input$sample
# If fewer than 3 points are selected, we will use point
# instead of violin plots
if (nrow(cur_df) < 3) {
p <- ggplot(cur_df) +
geom_point(aes_(x = quote(sample),
y = as.name(input[[paste0("Marker_", cur_val)]])),
show.legend = FALSE) +
xlab(input$sample) +
theme(axis.text.x = element_blank(),
panel.background = element_blank()) +
ylim(c(rValues$ranges[input[[paste0("Marker_", cur_val)]], 1],
rValues$ranges[input[[paste0("Marker_", cur_val)]], 2]))
} else {
p <- ggplot(cur_df) +
geom_violin(aes_(x = quote(sample),
y = as.name(input[[paste0("Marker_", cur_val)]])),
show.legend = FALSE) +
geom_quasirandom(aes_(x = quote(sample),
y = as.name(input[[paste0("Marker_",
cur_val)]])),
show.legend = FALSE,
groupOnX = TRUE) +
xlab(input$sample) +
theme(axis.text.x = element_blank(),
panel.background = element_blank()) +
ylim(c(rValues$ranges[input[[paste0("Marker_", cur_val)]], 1],
rValues$ranges[input[[paste0("Marker_", cur_val)]], 2]))
}
if (!is.null(objValues[[paste0("object", iter + 1)]])) {
cur_df$selected <-
colData(objValues[[paste0("object", iter)]])[,cell_id] %in%
colData(objValues[[paste0("object", iter + 1)]])[,cell_id]
if (nrow(cur_df) < 3) {
p <- p +
geom_point(aes_(x = quote(sample),
y = as.name(input[[paste0("Marker_",
cur_val)]]),
colour = quote(selected)),
show.legend = FALSE, data = cur_df) +
scale_colour_manual(values = c(`FALSE` = "black",
`TRUE` = "red"))
} else {
p <- p +
geom_quasirandom(aes_(x = quote(sample),
y = as.name(input[[paste0("Marker_",
cur_val)]]),
colour = quote(selected)),
show.legend = FALSE, data = cur_df,
groupOnX = TRUE) +
scale_colour_manual(values = c(`FALSE` = "black",
`TRUE` = "red"))
}
}
} else {
# We need to simulate a dataframe to allow brushing
cur_df <- data.frame(row.names = "ph")
cur_df[[input[[paste0("Marker_", cur_val)]]]] <- 1
cur_df$sample <- 1
p <- ggplot(cur_df) +
geom_blank(aes_(x = quote(sample),
y = as.name(input[[paste0("Marker_", cur_val)]])),
show.legend = FALSE) +
ylim(c(rValues$ranges[input[[paste0("Marker_", cur_val)]], 1],
rValues$ranges[input[[paste0("Marker_", cur_val)]], 2])) +
xlim(c(0.5, 1.5)) +
ylab(input[[paste0("Marker_", cur_val)]]) +
xlab(input$sample) +
theme(axis.text.x = element_blank(),
panel.background = element_blank())
}
return(p)
}
# Create scatter plots
#' @import ggplot2
#' @importFrom ggbeeswarm geom_quasirandom
.createScatter <- function(input, session, rValues, objValues,
iter, img_id, cell_id){
renderPlot({
req(input$sample)
cur_val <- (iter * 2) - 1
if (iter == 1) {
req(rValues$ranges, objValues$object1,
input$assay, input$Marker_1)
} else {
req(rValues$ranges, input[[paste0("plot_brush", iter - 1)]],
input$assay, input[[paste0("Marker_", cur_val)]])
}
if (iter > 1 && is.null(input[[paste0("plot_brush", iter - 1)]])) {
return(NULL)
}
if (is.null(input[[paste0("plot_brush", iter)]])) {
.clearObjects(objValues, iter)
.clearBrush(input, session, iter)
} else {
.brushObject(input, session, objValues, iter = iter)
}
# Plot scatter or violin
if (input[[paste0("Marker_", cur_val + 1)]] != "") {
p <- .plotScatter(input, rValues, objValues, iter, cur_val)
} else {
p <- .plotViolin(input, rValues, objValues, iter, cur_val, cell_id)
}
return(p)
})
}
# Helper function to select markers
# By default, we want to display the expression of the marker on
# which gating was performed last.
# The user can further select other markers for displaying
.select_markers <- function(input, exprs_marker_update = TRUE){
if (exprs_marker_update && !is.null(input$exprs_marker_1) &&
input$exprs_marker_1 != "") {
if (input$exprs_marker_2 != "") {
cur_markers <- c(input$exprs_marker_1, input$exprs_marker_2)
}
else{
cur_markers <- input$exprs_marker_1
}
} else {
req(input$Marker_1)
cur_input <- reactiveValuesToList(input)
cur_markers <- cur_input[grepl("Marker_", names(cur_input))]
cur_markers <- cur_markers[unlist(lapply(cur_markers,
function(x){x != ""}))]
# Subset markers to those of the last gate + 1
cur_brushes <- cur_input[grepl("plot_brush", names(cur_input))]
if(length(cur_brushes) > 0) {
cur_brushes <- cur_brushes[!unlist(lapply(cur_brushes, is.null))]
}
if (length(cur_brushes) > 0) {
max_brush <- max(as.numeric(sub("plot_brush", "",
names(cur_brushes))))
if (!is.null(input[[paste0("Marker_",
((max_brush + 1) * 2) - 1)]]) &&
input[[paste0("Marker_", ((max_brush + 1) * 2) - 1)]] != "") {
cur_markers <- cur_markers[
names(cur_markers) == paste0("Marker_",
((max_brush + 1) * 2) - 1) |
names(cur_markers) == paste0("Marker_",
(max_brush + 1) * 2)]
} else {
cur_markers <- cur_markers[
names(cur_markers) == paste0("Marker_",
((max_brush) * 2) - 1) |
names(cur_markers) == paste0("Marker_", (max_brush) * 2)]
}
} else {
cur_markers <- cur_markers[names(cur_markers) == "Marker_1" |
names(cur_markers) == "Marker_2"]
}
max_marker <- max(as.numeric(sub("Marker_", "", names(cur_markers))))
if (max_marker %% 2 == 0) {
cur_markers <- c(cur_markers[[paste0("Marker_", max_marker - 1)]],
cur_markers[[paste0("Marker_", max_marker)]])
} else {
cur_markers <- cur_markers[[paste0("Marker_", max_marker)]]
}
}
return(cur_markers)
}
# Helper function to define bcg parameter when using plotPixels()
.select_contrast <- function(input){
cur_markers <- .select_markers(input)
if (length(cur_markers) == 1) {
cur_bcg <- list(c(0, input$contrast_marker_1, 1))
names(cur_bcg) <- cur_markers
} else {
cur_bcg <- list(c(0, input$contrast_marker_1, 1),
c(0, input$contrast_marker_2, 1))
names(cur_bcg) <- cur_markers
}
return(cur_bcg)
}
# Visualize marker expression on images
#' @importFrom svgPanZoom svgPanZoom renderSvgPanZoom
#' @importFrom svglite stringSVG
.createImageExpression <- function(input, object, mask,
image, img_id, cell_id, ...){
renderSvgPanZoom({
cur_markers <- .select_markers(input)
cur_bcg <- .select_contrast(input)
if (is.null(image)) {
cur_mask <- mask[mcols(mask)[,img_id] == input$sample]
suppressMessages(svgPanZoom(stringSVG(
plotCells(object = object,
mask = cur_mask,
cell_id = cell_id,
img_id = img_id,
colour_by = cur_markers,
exprs_values = input$assay,
...)),
zoomScaleSensitivity = 0.4, maxZoom = 20,
controlIconsEnabled = TRUE, viewBox = FALSE))
} else {
if (length(cur_markers) > 1) {
validate(need(cur_markers[1] != cur_markers[2],
message = "Please specify two different markers"))
}
cur_image <- image[mcols(image)[,img_id] == input$sample]
suppressMessages(svgPanZoom(stringSVG(
plotPixels(image = cur_image,
colour_by = cur_markers,
bcg = cur_bcg,
...)),
zoomScaleSensitivity = 0.4, maxZoom = 20,
controlIconsEnabled = TRUE, viewBox = FALSE))
}
})
}
# Visualize selected cells on images
#' @importFrom svgPanZoom svgPanZoom renderSvgPanZoom
#' @importFrom svglite stringSVG
#' @importFrom S4Vectors metadata
.createImageSelection <- function(input, objValues,
mask, image, img_id, cell_id, ...){
renderSvgPanZoom({
cur_val <- (input$plotCount * 2) - 1
req(input$plot_brush1)
cur_markers <- .select_markers(input)
cur_bcg <- .select_contrast(input)
cur_object <- reactiveValuesToList(objValues)
cur_object <- cur_object[!unlist(lapply(cur_object, is.null))]
cur_ln <- length(cur_object)
cur_object <- cur_object[[paste0("object", length(cur_object))]]
cur_mask <- mask[mcols(mask)[,img_id] == input$sample]
if (unique(mcols(cur_mask)[,img_id]) !=
unique(colData(cur_object)[,img_id])) {
return(NULL)
}
if (is.null(image)) {
if (cur_ln == 1) {
suppressMessages(svgPanZoom(stringSVG(
plotCells(mask = cur_mask,
legend = NULL,
...)),
zoomScaleSensitivity = 0.4, maxZoom = 20,
controlIconsEnabled = TRUE, viewBox = FALSE))
} else {
cur_object$selected <- TRUE
suppressMessages(svgPanZoom(stringSVG(
plotCells(object = cur_object,
mask = cur_mask,
cell_id = cell_id,
img_id = img_id,
colour_by = "selected",
colour = list(selected = c("TRUE" = "dark red",
"FALSE" = "gray")),
legend = NULL,
...)),
zoomScaleSensitivity = 0.4, maxZoom = 20,
controlIconsEnabled = TRUE, viewBox = FALSE))
}
} else {
if (length(cur_markers) > 1) {
validate(need(cur_markers[1] != cur_markers[2],
message = "Please specify two different markers"))
}
cur_image <- image[mcols(image)[,img_id] == input$sample]
if (cur_ln == 1) {
suppressMessages(svgPanZoom(stringSVG(
plotPixels(image = cur_image,
colour_by = cur_markers,
legend = NULL,
bcg = cur_bcg,
...)),
zoomScaleSensitivity = 0.4, maxZoom = 20,
controlIconsEnabled = TRUE, viewBox = FALSE))
} else {
cur_object$selected <- TRUE
suppressMessages(svgPanZoom(stringSVG(
plotPixels(image = cur_image,
object = cur_object,
mask = cur_mask,
cell_id = cell_id,
img_id = img_id,
colour_by = cur_markers,
outline_by = "selected",
colour = list(selected = c("TRUE" = "white",
"FALSE" = "gray")),
legend = NULL,
bcg = cur_bcg,
...)),
zoomScaleSensitivity = 0.4, maxZoom = 20,
controlIconsEnabled = TRUE, viewBox = FALSE))
}
}
})
}
# Download the selected data
#' @importFrom S4Vectors metadata
#' @importFrom SummarizedExperiment metadata<-
#' @importFrom utils sessionInfo
.downloadSelection <- function(input, objValues){
downloadHandler(
filename = function(){
paste0(input$labelCellsBy, ".rds")
},
content = function(file){
cur_object <- reactiveValuesToList(objValues)
cur_object <- cur_object[!unlist(lapply(cur_object, is.null))]
cur_object <- cur_object[[paste0("object", length(cur_object))]]
cur_object$cytomapper_CellLabel <- input$labelCellsBy
# Add session info
metadata(cur_object)$cytomapper_SessionInfo <- sessionInfo()
# Add date
metadata(cur_object)$cytomapper_GatingDate <- Sys.Date()
saveRDS(cur_object, file)
}
)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.