#' Convert a SCE object to a SPE one
#'
#' This function converts a spot-level
#' [SingleCellExperiment-class][SingleCellExperiment::SingleCellExperiment-class]
#' (SCE) object as generated by `fetch_data()` to a
#' [SpatialExperiment-class][SpatialExperiment::SpatialExperiment-class] (SPE)
#' object.
#'
#' Note that the resulting object is a bit more complex than a regular SPE
#' because it contains the data from the spatialLIBD project which you might
#' otherwise have to generate for your own data.
#'
#' @param sce Defaults to the output of
#' `fetch_data(type = 'sce')`. This is a
#' \linkS4class{SingleCellExperiment}
#' object with the spot-level Visium data and information required for
#' visualizing the histology. See [fetch_data()] for more details.
#' @param imageData A `DataFrame()` with image data. Will be used with
#' [SpatialExperiment::imgData][SpatialExperiment::SpatialExperiment-methods].
#' If `NULL`, then this will be constructed for you assuming that you are
#' working with the original data from `spatialLIBD::fetch_data("sce")`.
#'
#' @return A a
#' [SpatialExperiment-class][SpatialExperiment::SpatialExperiment-class] object.
#' @export
#' @importFrom SpatialExperiment "imgData<-" "spatialCoordsNames<-"
#' "colData<-" SpatialImage
#' @importFrom jsonlite read_json
#' @importFrom methods new
#' @family SpatialExperiment-related functions
#' @author
#' Brenda Pardo, Leonardo Collado-Torres
#'
#' @examples
#'
#' if (enough_ram()) {
#' ## Download the sce data
#' sce <- fetch_data("sce")
#' ## Transform it to a SpatialExperiment object
#' spe <- sce_to_spe(sce)
#' }
sce_to_spe <- function(sce = fetch_data("sce"), imageData = NULL) {
sce <- check_sce(sce)
# Load assays
assays_visium <- SummarizedExperiment::assays(sce)
# Load rowData
rowData_visium <- SummarizedExperiment::rowData(sce)
## Re-case tissue
if (is.factor(sce$tissue)) sce$tissue <- sce$tissue == "1"
# Load colData
cols_to_drop <-
c(
"tissue",
"row",
"col",
"imagerow",
"imagecol"
)
colData_visium <-
SummarizedExperiment::colData(sce)[, !colnames(SummarizedExperiment::colData(sce)) %in% c(cols_to_drop, "height", "width", "barcode"), drop = FALSE]
names(colData_visium)[names(colData_visium) == "sample_name"] <- "sample_id"
# Load spatialCoords
spatialCoords_visium <-
SummarizedExperiment::colData(sce)[, colnames(SummarizedExperiment::colData(sce)) %in% cols_to_drop, drop = FALSE]
names(spatialCoords_visium) <-
c(
"in_tissue",
"array_row",
"array_col",
"pxl_row_in_fullres",
"pxl_col_in_fullres"
)
## Use the official sample id name
colnames(colData_visium)[colnames(colData_visium) == "sample_name"] <- "sample_id"
colData_visium$sample_id <- as.character(colData_visium$sample_id)
# Load reducedDim
reducedDimNames_visium <-
SingleCellExperiment::reducedDims(sce)
# Load images from the web for our data
if (is.null(imageData)) {
sample_id <- unique(colData_visium$sample_id)
url_images <-
paste0(
"https://spatial-dlpfc.s3.us-east-2.amazonaws.com/images/",
sample_id,
"_tissue_lowres_image.png"
)
# Load scaleFactors
url_scaleFactors <- paste0(
"https://raw.githubusercontent.com/LieberInstitute/",
"HumanPilot/master/10X/",
sample_id,
"/scalefactors_json.json"
)
names(url_scaleFactors) <- sample_id
scaleFactors_visium <-
lapply(url_scaleFactors, jsonlite::read_json)
## Create a list of images
spatial_img_list <- mapply(function(url) {
SpatialExperiment::SpatialImage(
url
)
}, url_images)
img_dat <- DataFrame(
sample_id = as.character(sample_id),
image_id = rep("lowres", length(sample_id)),
data = I(spatial_img_list),
scaleFactor = vapply(
scaleFactors_visium,
"[[",
numeric(1),
"tissue_lowres_scalef",
USE.NAMES = FALSE
)
)
imageData <- img_dat
## Fix things we had done that are not default:
# Scaling for lowres image: https://github.com/LieberInstitute/HumanPilot/blob/master/Analysis/Layer_Notebook.R#L118-L119
spatialCoords_visium$pxl_col_in_fullres <- spatialCoords_visium$pxl_col_in_fullres / img_dat$scaleFactor[match(colData_visium$sample_id, img_dat$sample_id)]
spatialCoords_visium$pxl_row_in_fullres <- spatialCoords_visium$pxl_row_in_fullres / img_dat$scaleFactor[match(colData_visium$sample_id, img_dat$sample_id)]
## Names of the columns is flipped at https://github.com/LieberInstitute/HumanPilot/blob/master/Analysis/Layer_Notebook.R#L116 compared to what
## SpatialExperiment does at https://github.com/drighelli/SpatialExperiment/blob/bf1b18b559ea2785d52db4e39a85f1d584aede45/R/read10xVisium.R#L170
# tmp <- spatialCoords_visium$pxl_row_in_fullres
# spatialCoords_visium$pxl_row_in_fullres <- spatialCoords_visium$pxl_col_in_fullres
# spatialCoords_visium$pxl_col_in_fullres <- tmp
## The above is no longer necessary thanks to https://github.com/drighelli/SpatialExperiment/commit/6710fe8b0a7919191ecce989bb6831647385ef5f
}
# ## Create object manually
# spe <- new("SpatialExperiment", SingleCellExperiment::SingleCellExperiment(
# rowData = rowData_visium,
# colData = colData_visium,
# assays = assays_visium,
# reducedDims = reducedDimNames_visium
# ))
#
# ## Add missing spatial info
# colData(spe) <- spatialCoords_visium
# SpatialExperiment::spatialCoordsNames(spe) <- c("pxl_col_in_fullres", "pxl_row_in_fullres")
# SpatialExperiment::imgData(spe) <- imageData
#
## This works now in SpatialExperiment version 1.1.701, so we no longer
## need the manual code from above
## The following code ultimately fails due to the current lack of support
## for multiple `sample_id`s, as in
## https://github.com/drighelli/SpatialExperiment/blob/a9e54fbd5af7fe676f8a5b29e4cfe113402070d4/R/SpatialExperiment.R#L143-L144
## or in
## https://github.com/drighelli/SpatialExperiment/blob/a9e54fbd5af7fe676f8a5b29e4cfe113402070d4/R/SpatialExperiment.R#L164
spe <- SpatialExperiment::SpatialExperiment(
rowData = rowData_visium,
colData = cbind(colData_visium, spatialCoords_visium),
assays = assays_visium,
reducedDims = reducedDimNames_visium,
sample_id = NULL,
spatialCoordsNames = c("pxl_col_in_fullres", "pxl_row_in_fullres"),
scaleFactors = img_dat$scaleFactor,
imgData = img_dat,
imageSources = url_images,
loadImage = FALSE
)
return(spe)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.