diff --git a/NAMESPACE b/NAMESPACE index 685cb95..9d11af7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -13,6 +13,7 @@ importFrom(DelayedArray,path) importFrom(DelayedArray,realize) importFrom(Rarr,zarr_overview) importFrom(S4Vectors,metadata) +importFrom(SingleCellExperiment,colData) importFrom(SingleCellExperiment,int_colData) importFrom(SingleCellExperiment,int_metadata) importFrom(SpatialData,channels) @@ -27,7 +28,7 @@ importFrom(ggplot2,element_line) importFrom(ggplot2,element_text) importFrom(ggplot2,geom_point) importFrom(ggplot2,geom_polygon) -importFrom(ggplot2,geom_tile) +importFrom(ggplot2,geom_raster) importFrom(ggplot2,ggplot) importFrom(ggplot2,guide_legend) importFrom(ggplot2,guides) diff --git a/R/AllGenerics.R b/R/AllGenerics.R index fda170e..96c05ae 100644 --- a/R/AllGenerics.R +++ b/R/AllGenerics.R @@ -5,13 +5,6 @@ setGeneric("rotate", \(x, t, ...) standardGeneric("rotate")) setGeneric("transform", \(x, ...) standardGeneric("transform")) setGeneric("translation", \(x, t, ...) standardGeneric("translation")) -# tbl ---- - -setGeneric("hasTable", \(x, i, ...) standardGeneric("hasTable")) -setGeneric("getTable", \(x, i, ...) standardGeneric("getTable")) -setGeneric("setTable", \(x, i, ...) standardGeneric("setTable")) -setGeneric("valTable", \(x, i, ...) standardGeneric("valTable")) - # plt ---- setGeneric("plotImage", \(x, ...) standardGeneric("plotImage")) diff --git a/R/plotImage.R b/R/plotImage.R index e71e38d..2cf6098 100644 --- a/R/plotImage.R +++ b/R/plotImage.R @@ -159,24 +159,11 @@ plotSpatialData <- \() ggplot() + scale_y_reverse() + .theme return(NULL) } -.guess_scale <- \(x, w, h) { - n <- length(dim(x)) - i <- ifelse(n == 3, -1, TRUE) - d <- vapply(x@data, dim, numeric(n)) - d <- apply(d, 2, \(.) sum(abs(.[i]-c(h, w)))) - which.min(d) -} - -.get_img_data <- \(x, k=NULL, w=800, h=800) { - if (!is.null(k)) return(data(x, k)) - data(x, .guess_scale(x, w, h)) -} - #' @importFrom methods as #' @importFrom grDevices rgb #' @importFrom DelayedArray realize .df_i <- \(x, k=NULL, ch=NULL, c=NULL, cl=NULL) { - a <- .get_img_data(x, k) + a <- .get_multiscale_data(x, k) ch <- .ch_idx(x, ch) if (!.is_rgb(x)) a <- a[ch, , , drop=FALSE] diff --git a/R/plotLabel.R b/R/plotLabel.R index 5493100..f390555 100644 --- a/R/plotLabel.R +++ b/R/plotLabel.R @@ -3,6 +3,10 @@ #' #' @param x \code{SpatialData} object. #' @param i character string or index; the label element to plot. +#' @param j name of target coordinate system. +#' @param k index of the scale of an image; by default (NULL), will auto-select +#' scale in order to minimize memory-usage and blurring for a target size of +#' 800 x 800px; use Inf to plot the lowest resolution available. #' @param c the default, NULL, gives a binary image of whether or not #' a given pixel is non-zero; alternatively, a character string specifying #' a \code{colData} column or row name in a \code{table} annotating \code{i}. @@ -34,10 +38,10 @@ #' # TODO: did a small fix to color scheme below, will fix example later #' # pal <- hcl.colors(n, "Spectral") #' pal_d <- hcl.colors(10, "Spectral") -#' p + plotLabel(x, i, "id", pal=pal_d) +#' p + plotLabel(x, i, c = "id", pal=pal_d) #' #' # coloring by 'assay' data -#' p + plotLabel(x, i, "channel_1_sum") +#' p + plotLabel(x, i, c = "channel_1_sum") NULL #' @rdname plotLabel @@ -47,20 +51,35 @@ NULL #' @importFrom methods as #' @importFrom ggplot2 #' scale_fill_manual scale_fill_gradientn -#' aes geom_tile theme unit guides guide_legend +#' aes geom_raster theme unit guides guide_legend +#' @importFrom SingleCellExperiment colData #' @export -setMethod("plotLabel", "SpatialData", \(x, i=1, c=NULL, +setMethod("plotLabel", "SpatialData", \(x, i=1, j=1, k=NULL, c=NULL, a=0.5, pal=c("red", "green"), nan=NA, assay=1) { if (is.numeric(i)) i <- labelNames(x)[i] i <- match.arg(i, labelNames(x)) - y <- as.matrix(as(data(label(x, i)), "DelayedArray")) - df <- data.frame(x=c(col(y)), y=c(row(y)), z=c(y)) + y <- label(x, i) + ym <- as.matrix(.get_multiscale_data(label(x, i), k)) + df <- data.frame(x=c(col(ym)), y=c(row(ym)), z=c(ym)) + # transformation + if (is.numeric(j)) + j <- CTname(y)[j] + ts <- CTpath(x, i, j) + df[,c("x", "y")] <- .trans_xy(df[,c("x", "y")], ts) aes <- aes(.data[["x"]], .data[["y"]]) if (!is.null(c)) { stopifnot(length(c) == 1, is.character(c)) t <- table(x, hasTable(x, i, name=TRUE)) ik <- .instance_key(t) - idx <- match(df$z, int_colData(t)[[ik]]) + # TODO: search ik in both internal and regular colData for now + # thus perhaps update, SpatialData::valTable instead + # idx <- match(df$z, int_colData(t)[[ik]]) + if(ik %in% names(int_colData(t))){ + coldata <- int_colData(t)[[ik]] + } else { + coldata <- colData(t)[[ik]] + } + idx <- match(df$z, coldata) df$z <- valTable(x, i, c, assay=assay)[idx] if (c == ik) df$z <- factor(df$z) aes$fill <- aes(.data[["z"]])[[1]] @@ -83,5 +102,5 @@ setMethod("plotLabel", "SpatialData", \(x, i=1, c=NULL, theme(legend.position="none"), scale_fill_manual(NULL, values=pal)) } - list(thm, do.call(geom_tile, list(data=df, mapping=aes, alpha=a))) + list(thm, do.call(geom_raster, list(data=df, mapping=aes, alpha=a))) }) \ No newline at end of file diff --git a/R/utils.R b/R/utils.R index 7f95287..d56f192 100644 --- a/R/utils.R +++ b/R/utils.R @@ -45,4 +45,19 @@ .DTYPE_MAX_VALUES <- c("uint8" = 255, "uint16" = 65535, "uint32" = 4294967295, - "uint64" = 2^64 - 1) \ No newline at end of file + "uint64" = 2^64 - 1) + +# guess scale of image or label +.guess_scale <- \(x, w, h) { + n <- length(dim(x)) + i <- ifelse(n == 3, -1, TRUE) + d <- vapply(x@data, dim, numeric(n)) + d <- apply(d, 2, \(.) sum(abs(.[i]-c(h, w)))) + which.min(d) +} + +# get multiscale +.get_multiscale_data <- \(x, k=NULL, w=800, h=800) { + if (!is.null(k)) return(data(x, k)) + data(x, .guess_scale(x, w, h)) +} \ No newline at end of file diff --git a/man/plotLabel.Rd b/man/plotLabel.Rd index db7a1ea..d819bb8 100644 --- a/man/plotLabel.Rd +++ b/man/plotLabel.Rd @@ -8,6 +8,8 @@ \S4method{plotLabel}{SpatialData}( x, i = 1, + j = 1, + k = NULL, c = NULL, a = 0.5, pal = c("red", "green"), @@ -20,6 +22,12 @@ \item{i}{character string or index; the label element to plot.} +\item{j}{name of target coordinate system.} + +\item{k}{index of the scale of an image; by default (NULL), will auto-select +scale in order to minimize memory-usage and blurring for a target size of +800 x 800px; use Inf to plot the lowest resolution available.} + \item{c}{the default, NULL, gives a binary image of whether or not a given pixel is non-zero; alternatively, a character string specifying a \code{colData} column or row name in a \code{table} annotating \code{i}.} @@ -58,8 +66,8 @@ n <- length(unique(t$id)) # TODO: did a small fix to color scheme below, will fix example later # pal <- hcl.colors(n, "Spectral") pal_d <- hcl.colors(10, "Spectral") -p + plotLabel(x, i, "id", pal=pal_d) +p + plotLabel(x, i, c = "id", pal=pal_d) # coloring by 'assay' data -p + plotLabel(x, i, "channel_1_sum") +p + plotLabel(x, i, c = "channel_1_sum") } diff --git a/tests/testthat/Rplots.pdf b/tests/testthat/Rplots.pdf new file mode 100644 index 0000000..2015d48 Binary files /dev/null and b/tests/testthat/Rplots.pdf differ diff --git a/tests/testthat/test-plotArray.R b/tests/testthat/test-plotArray.R index da13cc4..95ce0af 100644 --- a/tests/testthat/test-plotArray.R +++ b/tests/testthat/test-plotArray.R @@ -22,11 +22,11 @@ test_that(".guess_scale", { dim <- lapply(c(6, 3), \(.) c(3, rep(., 2))), \(.) array(sample(seq_len(255), prod(.), replace=TRUE), dim=.))) # manual scale - expect_identical(.get_img_data(img, k=1), lys[[1]]) - expect_identical(.get_img_data(img, k=2), lys[[2]]) + expect_identical(.get_multiscale_data(img, k=1), lys[[1]]) + expect_identical(.get_multiscale_data(img, k=2), lys[[2]]) # automatic scale - expect_identical(.get_img_data(img, k=NULL, w=5, h=7), lys[[1]]) - expect_identical(.get_img_data(img, k=NULL, w=2, h=2), lys[[2]]) + expect_identical(.get_multiscale_data(img, k=NULL, w=5, h=7), lys[[1]]) + expect_identical(.get_multiscale_data(img, k=NULL, w=2, h=2), lys[[2]]) }) test_that("plotImage()", { @@ -61,11 +61,13 @@ test_that("plotLabel()", { expect_s3_class(q, "ggplot") expect_equal(q$coordinates$ratio, 1) expect_is(q$layers[[1]]$mapping$fill, "quosure") + # multiscale + y <- label(x, "blobs_multiscale_labels") + y <- y[,seq_len(32)] # same thing but different # alpha q <- p + plotLabel(x, i, a=a <- runif(1)) expect_identical(q$layers[[1]]$aes_params$alpha, a) expect_error(show(plotSpatialData() + plotLabel(x, i, a="....."))) expect_error(show(plotSpatialData() + plotLabel(x, i, a=c(1, 2)))) - # TODO: use 'annotation_raster' - # TODO: multiscale plotting + # TODO: should we use 'annotation_raster' ? }) diff --git a/vignettes/SpatialData.plot.Rmd b/vignettes/SpatialData.plot.Rmd index b85f20d..146858a 100644 --- a/vignettes/SpatialData.plot.Rmd +++ b/vignettes/SpatialData.plot.Rmd @@ -93,8 +93,8 @@ pal_d <- hcl.colors(10, "Spectral") pal_c <- hcl.colors(9, "Inferno")[-9] a <- p + plotLabel(x, i) # simple binary image -b <- p + plotLabel(x, i, "id", pal=pal_d) # 'colData' -c <- p + plotLabel(x, i, "channel_1_sum", pal=pal_c) + +b <- p + plotLabel(x, i, c = "id", pal=pal_d) # 'colData' +c <- p + plotLabel(x, i, c = "channel_1_sum", pal=pal_c) + theme(legend.key.width=unit(1, "lines")) # 'assay' (a | b | c) + @@ -224,7 +224,7 @@ Colorectal carcinoma, 25 MB; no shapes, no points. pal <- hcl.colors(8, "Spectral") wrap_plots(nrow=1, lapply(seq(3), \(.) plotSpatialData() + plotImage(x, .) + - plotLabel(x, ., "Cluster", pal=pal))) + + plotLabel(x, ., c = "Cluster", pal=pal))) + plot_layout(guides="collect") ``` @@ -317,7 +317,7 @@ x <- mask(x, "blobs_image", i, fun=mean) (t <- getTable(x, i)) # visualize side-by-side ps <- lapply(paste(seq_len(3)), \(.) - plotSpatialData() + plotLabel(x, i, .) + + plotSpatialData() + plotLabel(x, i, c = .) + ggtitle(paste("channel", ., "sum"))) wrap_plots(ps, nrow=1) & theme( legend.position="bottom", diff --git a/vignettes/SpatialData.plot.html b/vignettes/SpatialData.plot.html deleted file mode 100644 index 4ba2178..0000000 --- a/vignettes/SpatialData.plot.html +++ /dev/null @@ -1,1273 +0,0 @@ - - - - - - - - - - - - - - -SpatialData.plot - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - -

Contents

-
- -
- -
library(ggplot2)
-library(patchwork)
-library(ggnewscale)
-library(SpatialData)
-library(SpatialData.data)
-library(SpatialData.plot)
-library(SingleCellExperiment)
-
-

1 Introduction

-

The SpatialData package contains a set of reader and plotting functions for -spatial omics data stored as SpatialData -.zarr files that follow OME-NGFF specs.

-

Each SpatialData object is composed of five layers: images, labels, shapes, -points, and tables. Each layer may contain an arbitrary number of elements.

-

Images and labels are represented as ZarrArrays (Rarr). -Points and shapes are represented as arrow objects linked -to an on-disk .parquet file. As such, all data are represented out of memory.

-

Element annotation as well as cross-layer summarizations (e.g., count matrices) -are represented as SingleCellExperiment as tables.

-
x <- file.path("extdata", "blobs.zarr")
-x <- system.file(x, package="SpatialData")
-(x <- readSpatialData(x, anndataR=FALSE))
-
## class: SpatialData
-## - images(2):
-##   - blobs_image (3,64,64)
-##   - blobs_multiscale_image (3,64,64)
-## - labels(2):
-##   - blobs_labels (64,64)
-##   - blobs_multiscale_labels (64,64)
-## - points(1):
-##   - blobs_points (200)
-## - shapes(3):
-##   - blobs_circles (5,circle)
-##   - blobs_multipolygons (2,polygon)
-##   - blobs_polygons (5,polygon)
-## - tables(1):
-##   - table (3,10)
-## coordinate systems:
-## - global(8): blobs_image blobs_multiscale_image ... blobs_polygons
-##   blobs_points
-## - scale(1): blobs_labels
-## - translation(1): blobs_labels
-## - affine(1): blobs_labels
-## - sequence(1): blobs_labels
-
-
-

2 Visualization

-
-

2.0.1 Images

-

Image/LabelArrays are linked to potentially multiscale .zarr stores. -Their show method includes the scales available for a given element:

-
image(x, "blobs_image")
-
## class: ImageArray  
-## Scales (1): (3,64,64)
-
image(x, "blobs_multiscale_image")
-
## class: ImageArray (MultiScale) 
-## Scales (3): (3,64,64) (3,32,32) (3,16,16)
-

Internally, multiscale ImageArrays are stored as a list of ZarrArray, e.g.:

-
i <- image(x, "blobs_multiscale_image")
-vapply(i@data, dim, numeric(3))
-
##      [,1] [,2] [,3]
-## [1,]    3    3    3
-## [2,]   64   32   16
-## [3,]   64   32   16
-

To retrieve a specific scale’s ZarrArray, we can use data(., k), -where k specifies the target scale. This also works for plotting:

-
wrap_plots(nrow=1, lapply(seq(3), \(.) 
-    plotSpatialData() + plotImage(x, i=2, k=.)))
-

-
-
-

2.0.2 Labels

-
i <- "blobs_labels"
-t <- getTable(x, i)
-t$id <- sample(letters, ncol(t))
-table(x) <- t
-
-p <- plotSpatialData()
-pal_d <- hcl.colors(10, "Spectral")
-pal_c <- hcl.colors(9, "Inferno")[-9]
-
-a <- p + plotLabel(x, i) # simple binary image
-b <- p + plotLabel(x, i, "id", pal=pal_d) # 'colData'
-c <- p + plotLabel(x, i, "channel_1_sum", pal=pal_c) + 
-    theme(legend.key.width=unit(1, "lines")) # 'assay'
-
-(a | b | c) + 
-    plot_layout(guides="collect") & 
-    theme(legend.position="bottom")
-

-
-
-

2.0.3 Points

-
i <- "blobs_points"
-p <- plotSpatialData()
-# mock up a 'table'
-f <- list(
-  numbers=\(n) runif(n),
-  letters=\(n) sample(letters, n, TRUE))
-y <- setTable(x, i, f)
-# demo. viz. capabilities
-a <- p + plotPoint(y, i) # simple dots
-b <- p + plotPoint(y, i, "letters") # discrete coloring
-c <- p + plotPoint(y, i, "numbers") # continuous coloring
-a | b | c
-

-
-
-

2.0.4 Shapes

-
p <- plotSpatialData()
-a <- p +
-  ggtitle("polygons") +
-  plotShape(x, "blobs_polygons")
-b <- p +
-  ggtitle("multipolygons") +
-  plotShape(x, "blobs_multipolygons")
-c <- p +
-  ggtitle("circles") +
-  plotShape(x, "blobs_circles")
-wrap_plots(a, b, c)
-

-
-
-

2.0.5 Layering

-
p <- plotSpatialData()
-# joint
-all <- p +
-    plotImage(x) +
-    plotLabel(x, a=1/3) +
-    plotShape(x, 1) +
-    plotShape(x, 3) +
-    new_scale_color() +
-    plotPoint(x, c="genes") +
-    ggtitle("layered")
-# split
-one <- list(
-    p + plotImage(x) + ggtitle("image"),
-    p + plotLabel(x) + ggtitle("labels"),
-    p + plotShape(x, 1) + ggtitle("circles"),
-    p + plotShape(x, 3) + ggtitle("polygons"),
-    p + plotPoint(x, c="genes") + ggtitle("points"))
-wrap_plots(c(list(all), one), nrow=2)
-

-
-
-
-

3 Examples

-
-

3.1 MERFISH

-

In this example data, we do not have a label for the shape polygons. -Such labels could be morphological regions annotated by pathologists.

-
dir.create(td <- tempfile())
-pa <- unzip_spd_demo(
-    zipname="merfish.zarr.zip", 
-    dest=td, source="biocOSN")
-(x <- readSpatialData(pa, anndataR=FALSE))
-
## class: SpatialData
-## - images(1):
-##   - rasterized (1,522,575)
-## - labels(0):
-## - points(1):
-##   - single_molecule (3714642)
-## - shapes(2):
-##   - anatomical (6,polygon)
-##   - cells (2389,circle)
-## - tables(1):
-##   - table (268,2389)
-## coordinate systems:
-## - global(4): rasterized anatomical cells single_molecule
-

There are only 2389 cells, but -3,714,642 -molecules, so that we downsample a random subset of 1,000 for visualization:

-
# downsample 1,000 points
-n <- length(p <- point(x))
-q <- p[sample(n, 1e3)]
-(point(x, "1k") <- q)
-
## class: PointFrame
-## count: 1000 
-## data(3): x y cell_type
-
# layered visualization
-plotSpatialData() +
-    plotImage(x) +
-    new_scale_color() +
-    plotPoint(x, i="1k", c="cell_type", s=0.2) +
-    new_scale_color() +
-    plotShape(x, i="anatomical") +
-    scale_color_manual(values=hcl.colors(6, "Spectral")) 
-

-
# bounding-box query
-qu <- list(xmin=1800, xmax=2400, ymin=5000, ymax=5400)
-bb <- geom_rect(do.call(aes, qu), data.frame(qu), col="yellow", fill=NA)
-y <- SpatialData(images=list("."=do.call(query, c(list(x=image(x)), qu))))
-plotSpatialData() + plotImage(x) + bb | plotSpatialData() + plotImage(y)
-

-
-
-

3.2 VisiumHD

-

Mouse intestine, 1GB; 4 image resolutions and 3 shapes at 2, 8, and 16 \(\mu\)m.

-
dir.create(td <- tempfile())
-pa <- unzip_spd_demo(
-    zipname="visium_hd_3.0.0_io.zip", 
-    dest=td, source="biocOSN")
-(x <- readSpatialData(pa, images=4, shapes=3, tables=FALSE))
-
## class: SpatialData
-## - images(1):
-##   - Visium_HD_Mouse_Small_Intestine_lowres_image (3,558,600)
-## - labels(0):
-## - points(0):
-## - shapes(1):
-##   - Visium_HD_Mouse_Small_Intestine_square_016um (91033,circle)
-## - tables(3):
-##   - square_002um (19059,5479660)
-##   - square_008um (19059,351817)
-##   - square_016um (19059,91033)
-## coordinate systems:
-## - downscaled_lowres(2): Visium_HD_Mouse_Small_Intestine_lowres_image
-##   Visium_HD_Mouse_Small_Intestine_square_016um
-## - global(1): Visium_HD_Mouse_Small_Intestine_square_016um
-## - downscaled_hires(1): Visium_HD_Mouse_Small_Intestine_square_016um
-
qu <- list(xmin=100, xmax=300, ymin=200, ymax=400)
-bb <- geom_rect(do.call(aes, qu), data.frame(qu), col="black", fill=NA)
-y <- SpatialData(images=list("."=do.call(query, c(list(x=image(x)), qu))))
-plotSpatialData() + plotImage(x) + bb | plotSpatialData() + plotImage(y)
-

-
-
-

3.3 MibiTOF

-

Colorectal carcinoma, 25 MB; no shapes, no points.

-
dir.create(td <- tempfile())
-pa <- unzip_spd_demo(
-    zipname="mibitof.zip", 
-    dest=td, source="biocOSN")
-(x <- readSpatialData(pa, anndataR=FALSE))
-
## class: SpatialData
-## - images(3):
-##   - point16_image (3,1024,1024)
-##   - point23_image (3,1024,1024)
-##   - point8_image (3,1024,1024)
-## - labels(3):
-##   - point16_labels (1024,1024)
-##   - point23_labels (1024,1024)
-##   - point8_labels (1024,1024)
-## - points(0):
-## - shapes(0):
-## - tables(1):
-##   - table (36,3309)
-## coordinate systems:
-## - point16(2): point16_image point16_labels
-## - point23(2): point23_image point23_labels
-## - point8(2): point8_image point8_labels
-
pal <- hcl.colors(8, "Spectral")
-wrap_plots(nrow=1, lapply(seq(3), \(.)
-    plotSpatialData() + plotImage(x, .) + 
-    plotLabel(x, ., "Cluster", pal=pal))) +
-    plot_layout(guides="collect")
-

-
-
-

3.4 CyCIF (MCMICRO)

-

Small lung adenocarcinoma, 250 MB; 1 image, 2 labels, 2 tables.

-
dir.create(td <- tempfile())
-pa <- unzip_spd_demo(
-    zipname="mcmicro_io.zip", 
-    dest=td, source="biocOSN")
-(x <- readSpatialData(pa, anndataR=FALSE))
-
## class: SpatialData
-## - images(1):
-##   - exemplar-001_image (12,3139,2511)
-## - labels(2):
-##   - exemplar-001_cell (3139,2511)
-##   - exemplar-001_nuclei (3139,2511)
-## - points(0):
-## - shapes(0):
-## - tables(2):
-##   - exemplar-001--ilastik_cell (12,11607)
-##   - exemplar-001--unmicst_cell (12,11170)
-## coordinate systems:
-## - global(3): exemplar-001_image exemplar-001_cell exemplar-001_nuclei
-

Getting channel names for the image:

-
channels(image(x))
-
##  [1] "DNA_6" "ELANE" "CD57"  "CD45"  "DNA_7" "CD11B" "SMA"   "CD16"  "DNA_8"
-## [10] "ECAD"  "FOXP3" "NCAM"
-

Plotting with multiple image channels:

-
plotSpatialData() + plotImage(x,
-    ch=c("DNA_6", "CD45", "CD57"), 
-    c=c("blue", "cyan", "yellow"),
-    cl=list(NULL, c(0, 0.1), NULL))
-

-
-
-

3.5 IMC (Steinbock)

-

4 different cancers (SCCHN, BCC, NSCLC, CRC), 820 MB; 14 images, 14 labels, 1 table.

-
dir.create(td <- tempfile())
-pa <- unzip_spd_demo(
-    zipname="steinbock_io.zip", 
-    dest=td, source="biocOSN")
-x <- readSpatialData(pa, anndataR=FALSE)
-
-

3.5.1 channels

-
plotSpatialData() + plotImage(x,
-    i="Patient3_003_image",
-    ch=c(6, 22, 39),
-    c=c("blue", "cyan", "yellow"))
-

-
-
-

3.5.2 contrasts

-
i <- image(x, "Patient3_003_image")
-image(x, "crop") <- i[, 200:400, 200:400]
-lapply(list(c(0.2, 1), c(0, 0.8), c(0, 1.2)), \(.) {
-    plotSpatialData() + plotImage(x, 
-        i="crop", 
-        ch=c(6, 22, 39), 
-        cl=list(1, 1, .),
-        c=c("blue", "cyan", "yellow")) +
-        ggtitle(sprintf("[%s, %s]", .[1], .[2]))
-}) |> wrap_plots(nrow=1) + plot_layout(guides="collect")
-

-
-
-
-
-

4 Masking

-

Back to blobs…

-
x <- file.path("extdata", "blobs.zarr")
-x <- system.file(x, package="SpatialData")
-x <- readSpatialData(x, tables=FALSE)
-
i <- "blobs_circles"
-x <- mask(x, "blobs_points", i)
-(t <- getTable(x, i))
-
## class: SingleCellExperiment 
-## dim: 2 5 
-## metadata(0):
-## assays(1): counts
-## rownames(2): gene_a gene_b
-## rowData names(0):
-## colnames(5): 1 2 3 4 5
-## colData names(0):
-## reducedDimNames(0):
-## mainExpName: NULL
-## altExpNames(0):
-
p <- plotSpatialData() + 
-    plotPoint(x, c="genes") +
-    scale_color_manual(values=c("tomato", "cornflowerblue")) +
-    new_scale_color()
-lapply(names(c <- c(a="red", b="blue")), \(.)
-    p + plotShape(x, i, c=paste0("gene_", .)) + 
-        scale_color_gradient2(
-            low="grey", high=c[.],
-            limits=c(0, 8), n.breaks=5)) |>
-    wrap_plots() + plot_layout(guides="collect")
-

-
# compute channel-wise means
-i <- "blobs_labels"
-table(x) <- NULL
-x <- mask(x, "blobs_image", i, fun=mean)
-(t <- getTable(x, i))
-
## class: SingleCellExperiment 
-## dim: 3 10 
-## metadata(0):
-## assays(1): counts
-## rownames(3): 1 2 3
-## rowData names(0):
-## colnames(10): 12 11 ... 16 4
-## colData names(0):
-## reducedDimNames(0):
-## mainExpName: NULL
-## altExpNames(0):
-
# visualize side-by-side
-ps <- lapply(paste(seq_len(3)), \(.) 
-    plotSpatialData() + plotLabel(x, i, .) + 
-    ggtitle(paste("channel", ., "sum"))) 
-wrap_plots(ps, nrow=1) & theme(
-    legend.position="bottom", 
-    legend.title=element_blank(),
-    legend.key.width=unit(1, "lines"),
-    legend.key.height=unit(0.5, "lines"))
-

-
-
-

5 Session info

-
## R version 4.4.1 Patched (2024-07-08 r86893)
-## Platform: aarch64-apple-darwin20
-## Running under: macOS Sonoma 14.2.1
-## 
-## Matrix products: default
-## BLAS:   /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib 
-## LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0
-## 
-## locale:
-## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
-## 
-## time zone: Europe/Madrid
-## tzcode source: internal
-## 
-## attached base packages:
-## [1] stats4    stats     graphics  grDevices utils     datasets  methods  
-## [8] base     
-## 
-## other attached packages:
-##  [1] SingleCellExperiment_1.28.1 SummarizedExperiment_1.36.0
-##  [3] Biobase_2.66.0              GenomicRanges_1.58.0       
-##  [5] GenomeInfoDb_1.42.1         IRanges_2.40.1             
-##  [7] S4Vectors_0.44.0            BiocGenerics_0.52.0        
-##  [9] MatrixGenerics_1.18.0       matrixStats_1.5.0          
-## [11] SpatialData.plot_0.99.2     SpatialData.data_0.99.2    
-## [13] SpatialData_0.99.23         ggnewscale_0.5.0           
-## [15] patchwork_1.3.0             ggplot2_3.5.1              
-## [17] BiocStyle_2.34.0           
-## 
-## loaded via a namespace (and not attached):
-##  [1] DBI_1.2.3               RBGL_1.82.0             rlang_1.1.4            
-##  [4] magrittr_2.0.3          Rarr_1.6.0              e1071_1.7-16           
-##  [7] compiler_4.4.1          RSQLite_2.3.9           dir.expiry_1.14.0      
-## [10] paws.storage_0.7.0      png_0.1-8               vctrs_0.6.5            
-## [13] stringr_1.5.1           pkgconfig_2.0.3         wk_0.9.4               
-## [16] crayon_1.5.3            fastmap_1.2.0           magick_2.8.5           
-## [19] dbplyr_2.5.0            XVector_0.46.0          labeling_0.4.3         
-## [22] paws.common_0.7.7       rmarkdown_2.29          graph_1.84.0           
-## [25] UCSC.utils_1.2.0        tinytex_0.54            purrr_1.0.2            
-## [28] bit_4.5.0.1             xfun_0.50               zlibbioc_1.52.0        
-## [31] cachem_1.1.0            jsonlite_1.8.9          blob_1.2.4             
-## [34] DelayedArray_0.32.0     tweenr_2.0.3            parallel_4.4.1         
-## [37] R6_2.5.1                bslib_0.8.0             stringi_1.8.4          
-## [40] reticulate_1.40.0       jquerylib_0.1.4         Rcpp_1.0.13-1          
-## [43] bookdown_0.42           assertthat_0.2.1        knitr_1.49             
-## [46] R.utils_2.12.3          Matrix_1.7-1            tidyselect_1.2.1       
-## [49] rstudioapi_0.17.1       abind_1.4-8             yaml_2.3.10            
-## [52] zellkonverter_1.16.0    curl_6.1.0              lattice_0.22-6         
-## [55] tibble_3.2.1            basilisk.utils_1.18.0   withr_3.0.2            
-## [58] evaluate_1.0.1          sf_1.0-19               polyclip_1.10-7        
-## [61] units_0.8-5             proxy_0.4-27            BiocFileCache_2.14.0   
-## [64] pillar_1.10.1           BiocManager_1.30.25     filelock_1.0.3         
-## [67] KernSmooth_2.23-26      generics_0.1.3          nanoarrow_0.6.0        
-## [70] munsell_0.5.1           scales_1.3.0            class_7.3-23           
-## [73] glue_1.8.0              tools_4.4.1             grid_4.4.1             
-## [76] colorspace_2.1-1        GenomeInfoDbData_1.2.13 basilisk_1.18.0        
-## [79] ggforce_0.4.2           cli_3.6.3               S4Arrays_1.6.0         
-## [82] arrow_18.1.0            dplyr_1.1.4             geoarrow_0.2.1         
-## [85] gtable_0.3.6            R.methodsS3_1.8.2       sass_0.4.9             
-## [88] digest_0.6.37           classInt_0.4-10         SparseArray_1.6.0      
-## [91] farver_2.1.2            memoise_2.0.1           htmltools_0.5.8.1      
-## [94] R.oo_1.27.0             lifecycle_1.0.4         httr_1.4.7             
-## [97] MASS_7.3-64             bit64_4.5.2
-
- - - - -
- - - - - - - - - - - - - - - - - -