Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: spatialLIBD
Title: spatialLIBD: an R/Bioconductor package to visualize spatially-resolved
transcriptomics data
Version: 1.23.2
Date: 2026-01-09
Version: 1.23.3
Date: 2026-06-07
Authors@R:
c(
person("Leonardo", "Collado-Torres", role = c("aut", "cre"),
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ export(sig_genes_extract)
export(sig_genes_extract_all)
export(sort_clusters)
export(vis_clus)
export(vis_clus_c)
export(vis_clus_p)
export(vis_gene)
export(vis_gene_c)
export(vis_gene_p)
export(vis_grid_clus)
export(vis_grid_gene)
Expand Down
13 changes: 12 additions & 1 deletion R/fetch_data.R
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ fetch_data <-
"LFF_spatial_ERC_snRNAseq_pseudobulk_broad",
"LFF_spatial_ERC_snRNAseq_pseudobulk_subcluster",
"LFF_spatial_ERC_snRNAseq_modeling_results_broad",
"LFF_spatial_ERC_snRNAseq_modeling_results_subcluster"
"LFF_spatial_ERC_snRNAseq_modeling_results_subcluster",
"spe_xenium_example"
),
destdir = tempdir(),
eh = ExperimentHub::ExperimentHub(),
Expand Down Expand Up @@ -409,6 +410,16 @@ fetch_data <-
file_name <- "sce_subcluster_pseudobulk-cell_type_anno.rds"
url <-
"https://www.dropbox.com/scl/fi/y42pv7k02luvznwqii2rm/sce_subcluster_modeling_results-cell_type_anno.rds?rlkey=17c0ybowjpejdxc71tuxlcfna&dl=1"
} else if (
type == "spe_xenium_example"
) {
tag <- "LFF_spatial_ERC"
hub_title <- type

## While EH is not set-up
file_name <- "spe_Xenium_test.rds"
url <-
"https://www.dropbox.com/scl/fi/y42pv7k02luvznwqii2rm/sce_subcluster_modeling_results-cell_type_anno.rds?rlkey=17c0ybowjpejdxc71tuxlcfna&dl=1"
}

file_path <- file.path(destdir, file_name)
Expand Down
134 changes: 101 additions & 33 deletions R/vis_clus.R
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,16 @@
#' particular, expects a logical colData column `exclude_overlapping`
#' specifying which spots to exclude from the plot. Sets `auto_crop = FALSE`.
#' @param guide_point_size A `numeric(1)` specifying the size of the points in
#' guide. Defaults to `point_size`. Increase to improve visability.
#' guide. Defaults to `point_size`. Increase to improve visibility.
#' @param datatype A `character(1)` specifying the type of spatial transcriptomics
#' data stored in `spe`. Supported options are:
#' \describe{
#' \item{`"Visium"`}{(Default) Expects `pxl_col_in_fullres` and
#' `pxl_row_in_fullres` as columns of `spatialCoords(spe)`. Enables
#' image handling via the `spatialData` slot.}
#' \item{`"Xenium"`}{Expects `x_centroid` and `y_centroid` as columns
#' of `spatialCoords(spe)`.}
#' }
#' @param ... Passed to [paste0()][base::paste] for making the title of the
#' plot following the `sampleid`.
#'
Expand All @@ -49,12 +58,12 @@
#' @export
#' @importFrom SpatialExperiment spatialCoords
#' @details This function subsets `spe` to the given sample and prepares the
#' data and title for [vis_clus_p()].
#' data and title for [vis_clus_p()] or [vis_clus_c()].
#'
#' @examples
#'
#' if (enough_ram()) {
#' ## Obtain the necessary data
#' ## Obtain the necessary data: Visium example
#' if (!exists("spe")) spe <- fetch_data("spe")
#'
#' ## Check the colors defined by Lukas M Weber
Expand Down Expand Up @@ -117,6 +126,26 @@
#' ... = " LIBD Layers"
#' )
#' print(p5)
#'
#' ## Obtain the necessary data: Xenium example
#' if (!exists("spe_xenium")) spe_xenium <- fetch_data("spe_xenium_example")
#'
#' spe_xenium$x_half <- ifelse(spatialCoords(spe_xenium)[,"x_centroid"] < 3088, "left", "right")
#'
#' p6 <- vis_clus(
#' spe = spe_xenium,
#' clustervar = "x_half",
#' sampleid = "sample2",
#' colors = c(left = "red", right = "blue"),
#' na_color = "white",
#' point_size = 1,
#' alpha = 0.5,
#' guide_point_size = 3,
#' datatype = "Xenium"
#' )
#' print(p6)
#'
#'
#'
#' }
vis_clus <- function(
Expand Down Expand Up @@ -145,6 +174,7 @@ vis_clus <- function(
na_color = "#CCCCCC40",
is_stitched = FALSE,
guide_point_size = point_size,
datatype = c("Visium", "Xenium"),
...) {
# Verify existence and legitimacy of 'sampleid'
if (
Expand All @@ -158,42 +188,80 @@ vis_clus <- function(
call. = FALSE
)
}

# Check validity of spatial coordinates

## subset spe to selected sample
spe_sub <- spe[, spe$sample_id == sampleid]

## Check for valid datatype
datatype <- match.arg(datatype)

if(datatype == "Visium"){

# Check validity of spatial coordinates by datatype
if (!setequal(c("pxl_col_in_fullres", "pxl_row_in_fullres"), colnames(spatialCoords(spe)))) {
stop(
"Abnormal spatial coordinates: should have 'pxl_row_in_fullres' and 'pxl_col_in_fullres' columns.",
call. = FALSE
)
stop(
"Abnormal spatial coordinates for Visium datatype: should have 'pxl_row_in_fullres' and 'pxl_col_in_fullres' columns.",
call. = FALSE
)
}

spe_sub <- spe[, spe$sample_id == sampleid]
d <- as.data.frame(cbind(colData(spe_sub), SpatialExperiment::spatialCoords(spe_sub)), optional = TRUE)

if (is_stitched) {
# Drop excluded spots and calculate an appropriate point size
temp <- prep_stitched_data(spe_sub, point_size, image_id)
spe_sub <- temp$spe
point_size <- temp$point_size

# Frame limits are poorly defined for stitched data
auto_crop <- FALSE
# Drop excluded spots and calculate an appropriate point size
temp <- prep_stitched_data(spe_sub, point_size, image_id)
spe_sub <- temp$spe
point_size <- temp$point_size
# Frame limits are poorly defined for stitched data
auto_crop <- FALSE
}

d <- as.data.frame(cbind(colData(spe_sub), SpatialExperiment::spatialCoords(spe_sub)), optional = TRUE)


vis_clus_p(
spe = spe_sub,
d = d,
clustervar = clustervar,
sampleid = sampleid,
spatial = spatial,
title = paste0(sampleid, ...),
colors = get_colors(colors, d[, clustervar]),
image_id = image_id,
alpha = alpha,
point_size = point_size,
auto_crop = auto_crop,
na_color = na_color
spe = spe_sub,
d = d,
clustervar = clustervar,
sampleid = sampleid,
spatial = spatial,
title = paste0(sampleid, ...),
colors = get_colors(colors, d[, clustervar]),
image_id = image_id,
alpha = alpha,
point_size = point_size,
auto_crop = auto_crop,
na_color = na_color
) +
guides(fill = guide_legend(override.aes = list(size = guide_point_size)))

} else if(datatype == "Xenium"){

if (datatype == "Xenium" & !setequal(c("x_centroid", "y_centroid"), colnames(spatialCoords(spe)))) {
stop(
"Abnormal spatial coordinates for Xenium datatype: should have 'x_centroid' and 'y_centroid' columns.",
call. = FALSE
)
}

d <- as.data.frame(cbind(colData(spe_sub), SpatialExperiment::spatialCoords(spe_sub)), optional = TRUE)

vis_clus_c(
spe = spe_sub,
d = d,
clustervar = clustervar,
sampleid = sampleid,
title = paste0(sampleid, ...),
colors = get_colors(colors, d[, clustervar]),
alpha = alpha,
point_size = point_size,
na_color = na_color
) +
guides(fill = guide_legend(override.aes = list(size = guide_point_size)))


}





}
118 changes: 118 additions & 0 deletions R/vis_clus_c.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#' Sample spatial cluster visualization workhorse function for Xenium data with
#' centroid based spatailCoords
#'
#' This function visualizes clusters or categorical variables for one given
#' sample at the cell-level. This is the function that does all the plotting
#' behind [vis_clus()] when `datatype = "Xenium"`. To visualize gene-level
#' (or any continuous variable) use [vis_gene_c()].
#'
#' @inheritParams vis_clus
#' @param d A `data.frame()` with the sample-level information. This is
#' typically obtained using `cbind(colData(spe), spatialCoords(spe))`.
#' @param title The title for the plot.
#'
#' @return A [ggplot2][ggplot2::ggplot] object.
#' @export
#' @importFrom tibble tibble
#' @importFrom SpatialExperiment imgData scaleFactors
#' @importFrom S4Vectors metadata
#' @importFrom grid rasterGrob unit
#' @family Spatial cluster visualization functions
#'
#' @examples
#'
#' if (enough_ram()) {
#' ## Obtain the necessary data
#' if (!exists("spe")) spe <- fetch_data("spe_xenium_example")
#'
#' # spe <- readRDS("../Xenium/XeniumIO_test/spe_Xenium_test.rds")
#'
#' ## Prepare the data for the plotting function
#' spe_sub <- spe[, spe$sample_id == "sample1"]
#'
#' # summary(spatialCoords(spe_sub)[,"x_centroid"])
#' # summary(spatialCoords(spe_sub)[,"y_centroid"])
#'
#' ## add catagorical variable
#' spe_sub$x_half <- ifelse(spatialCoords(spe_sub)[,"x_centroid"] < 3088, "left", "right")
#' table(spe_sub$x_half)
#'
#' p <- vis_clus_c(
#' spe = spe_sub,
#' d = as.data.frame(cbind(colData(spe_sub), SpatialExperiment::spatialCoords(spe_sub)), optional = TRUE),
#' clustervar = "x_half",
#' sampleid = "sample01.1",
#' #colors = libd_layer_colors,
#' colors = c(left = "red", right = "blue"),
#' title = "Xenium test",
#' point_size = 1,
#' alpha = 0.5
#' )
#' print(p)
#'
#' ## Clean up
#' rm(spe_sub)
#' }
vis_clus_c <-
function(spe,
d,
clustervar,
sampleid = unique(spe$sample_id)[1],
colors,
title,
alpha = NA,
point_size = 1,
auto_crop = TRUE,
na_color = "#CCCCCC40") {
## Some variables
x_centroid <- y_centroid <- key <- NULL
# stopifnot(all(c("x_centroid", "y_centroid", "key") %in% colnames(d)))


# ## Crop the image if needed
# if (auto_crop) {
# frame_lims <-
# frame_limits(spe, sampleid = sampleid, image_id = image_id)
# img <-
# img[frame_lims$y_min:frame_lims$y_max, frame_lims$x_min:frame_lims$x_max]
# adjust <-
# list(x = frame_lims$x_min, y = frame_lims$y_min)
# } else {
adjust <- list(x = 0, y = 0)
# }
#
p <- ggplot(
d,
aes(
x = x_centroid,
y = y_centroid,
fill = factor(!!sym(clustervar)),
key = key
)
)

p <- p +
geom_point(
shape = 21,
size = point_size,
stroke = 0,
colour = "transparent",
alpha = alpha
) +
coord_fixed(expand = FALSE) +
scale_fill_manual(values = colors, na.value = na_color) +
xlab("") + ylab("") +
labs(fill = NULL) +
ggtitle(title) +
theme_set(theme_bw(base_size = 20)) +
theme(
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
legend.box.spacing = unit(0, "pt")
)
return(p)
}
12 changes: 7 additions & 5 deletions R/vis_clus_p.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#' Sample spatial cluster visualization workhorse function
#' Sample spatial cluster visualization workhorse function for Visium data with
#' pixel based spatailCoords aligned to images.
#'
#' This function visualizes the clusters for one given sample at the spot-level
#' using (by default) the histology information on the background. This is the
#' function that does all the plotting behind [vis_clus()]. To visualize
#' gene-level (or any continuous variable) use [vis_gene_p()].
#' This function visualizes the clusters or categorical variables for one given
#' sample at the spot-level using (by default) the histology information on the
#' background. This is the function that does all the plotting behind
#' [vis_clus()]. To visualize gene-level (or any continuous variable) use
#' [vis_gene_p()].
#'
#' @inheritParams vis_clus
#' @param d A `data.frame()` with the sample-level information. This is
Expand Down
Loading
Loading