Skip to content

Commit

Permalink
Merge pull request #82 from LieberInstitute/stitched_plotting
Browse files Browse the repository at this point in the history
Stitched plotting
  • Loading branch information
lcolladotor authored Jul 2, 2024
2 parents e0947a2 + 0b68372 commit d2b0c75
Show file tree
Hide file tree
Showing 12 changed files with 426 additions and 0 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export(vis_grid_gene)
import(ExperimentHub)
import(MatrixGenerics)
import(SingleCellExperiment)
import(SpatialExperiment)
import(ggplot2)
import(grid)
import(paletteer)
Expand Down
75 changes: 75 additions & 0 deletions R/prep_stitched_data.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#' Prepare stitched data for plotting
#'
#' Given a \code{SpatialExperiment} built with \code{visiumStitched::build_spe()}
#' <http://research.libd.org/visiumStitched/reference/build_spe.html>, drop
#' exluded spots (specified by \code{spe$exclude_overlapping}) and compute an
#' appropriate spot size for plotting with \code{vis_gene()} or
#' \code{vis_clus()}, assuming the plot will be written to a PDF of default
#' dimensions (i.e. \code{width = 7} and \code{height = 7}).
#'
#' @param spe A \code{SpatialExperiment} built with
#' \code{visiumStitched::build_spe()}, containing a logical
#' \code{spe$exclude_overlapping} column specifying which spots to display in
#' plots
#' @inheritParams vis_clus
#'
#' @return A list with names \code{spe} and \code{point_size} containing a
#' filtered, ready-to-plot \code{SpatialExperiment} and an appopriate spot size
#' (passed to \code{vis_gene()} or \code{vis_clus()}), respectively
#'
#' @import SpatialExperiment
#' @author Nicholas J. Eagles
#' @keywords internal
prep_stitched_data = function(spe, point_size, image_id) {
# State assumptions about columns expected to be in the colData
expected_cols <- c("array_row", "array_col", "exclude_overlapping")
if (!all(expected_cols %in% colnames(colData(spe)))) {
stop(
sprintf(
'Missing at least one of the following colData columns: "%s"',
paste(expected_cols, collapse = '", "')
),
call. = FALSE
)
}

if(any(is.na(spe$exclude_overlapping))) {
stop("spe$exclude_overlapping must not have NAs", call. = FALSE)
}

# Drop excluded spots; verify some spots are not excluded
subset_cols = !spe$exclude_overlapping
if (length(which(subset_cols)) == 0) {
stop(
"spe$exclude_overlapping must include some FALSE values to plot",
call. = FALSE
)
}
spe <- spe[, subset_cols]

# Compute an appropriate spot size for this sample

# Determine some pixel values for the horizontal bounds of the spots
MIN_COL <- min(spatialCoords(spe)[, "pxl_row_in_fullres"])
MAX_COL <- max(spatialCoords(spe)[, "pxl_row_in_fullres"])

# The distance between spots (in pixels) is double the average distance
# between array columns
INTER_SPOT_DIST_PX <- 2 * (MAX_COL - MIN_COL) /
(max(spe$array_col) - min(spe$array_col))

# Find the appropriate spot size for this donor. This can vary because
# ggplot downscales a plot to fit desired output dimensions (in this
# case presumably a square region on a PDF), and stitched images can vary
# in aspect ratio. Also, lowres images always have a larger image
# dimension of 1200, no matter how many spots fit in either dimension.
small_image_data <- imgData(spe)[
imgData(spe)$image_id == image_id,
]

# The coefficient of 100 was determined empirically
point_size <- point_size * 100 * INTER_SPOT_DIST_PX *
small_image_data$scaleFactor / max(dim(small_image_data$data[[1]]))

return(list(spe = spe, point_size = point_size))
}
26 changes: 26 additions & 0 deletions R/vis_clus.R
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@
#' alpha blending already, which will make non-NA values pop up more and the NA
#' values will show with a lighter color. This behavior is lost when `alpha` is
#' set to a non-`NA` value.
#' @param is_stitched A \code{logical(1)} vector: If true, expects a
#' \code{SpatialExperiment} built with \code{visiumStitched::build_spe()}
#' <http://research.libd.org/visiumStitched/reference/build_spe.html>; in
#' particular, expects a logical colData column \code{exclude_overlapping}
#' specifying which spots to exclude from the plot. Sets \code{auto_crop = FALSE}
#' when TRUE.
#' @param ... Passed to [paste0()][base::paste] for making the title of the
#' plot following the `sampleid`.
#'
Expand Down Expand Up @@ -116,6 +122,7 @@ vis_clus <- function(spe,
point_size = 2,
auto_crop = TRUE,
na_color = "#CCCCCC40",
is_stitched = FALSE,
...) {
# Verify existence and legitimacy of 'sampleid'
if (
Expand All @@ -130,7 +137,26 @@ vis_clus <- function(spe,
)
}

# Check validity of spatial coordinates
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
)
}

spe_sub <- spe[, spe$sample_id == sampleid]

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
}

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

vis_clus_p(
Expand Down
20 changes: 20 additions & 0 deletions R/vis_gene.R
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ vis_gene <-
auto_crop = TRUE,
na_color = "#CCCCCC40",
multi_gene_method = c("z_score", "pca", "sparsity"),
is_stitched = FALSE,
...) {
multi_gene_method <- rlang::arg_match(multi_gene_method)
# Verify existence and legitimacy of 'sampleid'
Expand All @@ -192,7 +193,26 @@ vis_gene <-
stop(sprintf("'%s' is not an assay in 'spe'", assayname), call. = FALSE)
}

# Check validity of spatial coordinates
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
)
}

spe_sub <- spe[, spe$sample_id == sampleid]

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
}

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

# Verify legitimacy of names in geneid
Expand Down
4 changes: 4 additions & 0 deletions inst/extdata/metadata_Visium_LS.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Title,Description,BiocVersion,Genome,SourceType,SourceUrl,SourceVersion,Species,TaxonomyId,Coordinate_1_based,DataProvider,Maintainer,RDataClass,DispatchClass,RDataPath,Tags
Visium_LS_spe,SpatialExperiment object at the spot-level for the spatially stitched lateral septum human brain (LS) spatial transcriptomics data (n = 3) from the Visium platform from 10x Genomics generated by the Lieber Institute for Brain Development (LIBD) and available through the spatialLIBD Bioconductor package.,3.19,GRCh38,GTF,https://bioconductor.org/packages/spatialLIBD,June 11 2024,Homo sapiens,9606,TRUE,LIBD,Leonardo Collado-Torres <[email protected]>,SpatialExperiment,Rds,spatialLIBD/spatialLIBD_files/Visium_LS_spe.rds,VisiumLS_Visium_stitched_spatialLIBD
Visium_LS_spaceranger,Spaceranger outputs for the spatially stitched lateral septum human brain (LS) spatial transcriptomics data (n = 3) from the Visium platform from 10x Genomics generated by the Lieber Institute for Brain Development (LIBD) and available through the spatialLIBD Bioconductor package. Can be used with visiumStitched::build_spe() to construct a SpatialExperiment.,3.19,GRCh38,Zip,https://bioconductor.org/packages/spatialLIBD,June 11 2024,Homo sapiens,9606,TRUE,LIBD,Leonardo Collado-Torres <[email protected]>,list,Zip,spatialLIBD/spatialLIBD_files/Visium_LS_spaceranger.zip,VisiumLS_Visium_stitched_spatialLIBD
Visium_LS_ImageJ_out,Stitched PNG image and XML file from aligning lateral septum human brain (LS) spatial transcriptomics data (n = 3) in ImageJ. Data to align was from the Visium platform from 10x Genomics generated by the Lieber Institute for Brain Development (LIBD) and is available through the spatialLIBD Bioconductor package.,3.19,GRCh38,Zip,https://bioconductor.org/packages/spatialLIBD,June 11 2024,Homo sapiens,9606,TRUE,LIBD,Leonardo Collado-Torres <[email protected]>,list,Zip,spatialLIBD/spatialLIBD_files/Visium_LS_imagej_out.zip,VisiumLS_Visium_stitched_spatialLIBD
Loading

0 comments on commit d2b0c75

Please sign in to comment.