SpatialData.plot

Installation

SpatialData.plot can be installed as follows:

if (require("BiocManager", quietly=TRUE))
    install.packages("BiocManager")
BiocManager::install("SpatialData.plot")

For the purpose of this vignette, we require the following dependencies:

library(ggplot2)
library(patchwork)
library(ggnewscale) 
library(spatialdataR)
library(SpatialData.plot)

Introduction

The SpatialData.plot package contains a set of 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.

We here demonstrate package functionality using a trivial example dataset. For more realistic technology-focused examples, we refer readers to the companion demo website.

x <- file.path("extdata", "blobs.zarr")
x <- system.file(x, package="SpatialData.plot")
(x <- readSpatialData(x))
## 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) [blobs_labels]
## coordinate systems(5):
## - 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

Visualization

SpatialData.plot provides 5 user-facing plotting functions:

  • plotSpatialData() renders a base (blank) ggplot with simple aesthetics and, importantly, a fixed axial ratio as to not distort spatial coordinates.
  • plotImage/Label/Point/Shape() render specific SpatialData elements; each requires specification of the element index/name i, and coordinate system j (by default, the first available element/system will be rendered); different functions further accept different arguments to control aesthetics.

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:  SpatialDataImage  
## Scales (1): (3,64,64)
image(x, "blobs_multiscale_image")
## class:  SpatialDataImage (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(data(i, k=NULL), 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(x) + plotImage(i=2, k=.)))

Labels

Like images, labels are represented as ZarrArray. Array values, however, are integers that correspond to different instances, typically linked to a table of annotations (e.g., expression values, observation metadata, etc.).

i <- "blobs_labels"
t <- getTable(x, i)
t$id <- sample(letters, ncol(t))
table(x) <- t

p <- plotSpatialData(x)
pal_d <- hcl.colors(10, "Spectral")
pal_c <- hcl.colors(9, "Inferno")[-9]

a <- p + plotLabel(i, pal="grey")                   # binary
b <- p + plotLabel(i, c="id", pal=pal_d)            # metadata
c <- p + plotLabel(i, c="channel_1_sum", pal=pal_c) # assay

(a | b | c) + 
    plot_layout(guides="collect") & 
    theme(legend.position="bottom")

Points

Elements of the points layer are rendered using geom_point(), and accepts both discrete and continuous color specifications.

i <- "blobs_points"
a <- p + plotPoint(i=i)
b <- p + plotPoint(i=i, col="genes")       # discrete
c <- p + plotPoint(i=i, col="instance_id") # continuous
(a | b | c) 

Shapes

For demonstration, we render each shape element present in the object, which includes all possible types: circles and (multi)polygons.

p <- plotSpatialData(x)
a <- p +
    labs(title="polygons") +
    plotShape(i="blobs_polygons")
b <- p +
    labs(title="multipolygons") +
    plotShape(i="blobs_multipolygons")
c <- p +
    labs(title="circles") +
    plotShape(i="blobs_circles")
(a | b | c)

Layering

Several SpatialData elements (images, labels, points, shapes) can be layered on-top of each other in ggplot-style using the +-operator. The return value of each such call remains a ggplot object, which accepts additional aesthetics. Note that specifying layer-specific fill/color requires setting up a new scale with ggnewscale::new_scale_fill/color(); an example is as follows:

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

Scalebars

A scalebar of a specified length (in the annotated unit) can be added using the scalebar() function.

plotSpatialData(x) +
    plotImage() +
    plotLabel(a=1/3) +
    scalebar(len=10, xrel=0.05, yrel=0.95)

Session info

## R version 4.6.1 (2026-06-24)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 26.04.1 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.32.so;  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: Etc/UTC
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
## [1] SpatialData.plot_0.99.9 spatialdataR_0.99.44    ggnewscale_0.5.2       
## [4] patchwork_1.3.2         ggplot2_4.0.3           BiocStyle_2.41.0       
## 
## loaded via a namespace (and not attached):
##  [1] tidyselect_1.2.1            grumpy_0.1.1               
##  [3] blob_1.3.0                  dplyr_1.2.1                
##  [5] farver_2.1.2                R.utils_2.13.0             
##  [7] S7_0.2.2                    fastmap_1.2.0              
##  [9] SingleCellExperiment_1.35.2 duckdb_1.5.6               
## [11] digest_0.6.39               lifecycle_1.0.5            
## [13] sf_1.1-3                    paws.storage_0.11.0        
## [15] magrittr_2.0.5              compiler_4.6.1             
## [17] rlang_1.3.0                 sass_0.4.10                
## [19] tools_4.6.1                 yaml_2.3.12                
## [21] knitr_1.52                  labeling_0.4.3             
## [23] S4Arrays_1.13.2             classInt_0.4-11            
## [25] curl_8.0.0                  reticulate_1.47.0          
## [27] DelayedArray_0.39.8         RColorBrewer_1.1-3         
## [29] abind_1.4-8                 KernSmooth_2.23-27         
## [31] withr_3.0.3                 purrr_1.2.2                
## [33] BiocGenerics_0.59.12        sys_3.4.3                  
## [35] R.oo_1.27.1                 grid_4.6.1                 
## [37] stats4_4.6.1                e1071_1.7-17               
## [39] scales_1.4.0                SummarizedExperiment_1.43.0
## [41] cli_3.6.6                   rmarkdown_2.32             
## [43] crayon_1.5.3                generics_0.1.4             
## [45] otel_0.2.0                  DBI_1.3.0                  
## [47] cachem_1.1.0                proxy_0.4-29               
## [49] BiocManager_1.30.27         XVector_0.53.0             
## [51] matrixStats_1.5.0           vctrs_0.7.3                
## [53] Matrix_1.7-6                jsonlite_2.0.0             
## [55] IRanges_2.47.5              S4Vectors_0.51.10          
## [57] RBGL_1.89.0                 maketools_1.3.2            
## [59] jquerylib_0.1.4             units_1.0-1                
## [61] glue_1.8.1                  ZarrArray_1.1.7            
## [63] gtable_0.3.6                Rarr_2.1.45                
## [65] GenomicRanges_1.65.4        tibble_3.3.1               
## [67] pillar_1.11.1               htmltools_0.5.9            
## [69] Seqinfo_1.3.2               graph_1.91.0               
## [71] dbplyr_2.6.0                R6_2.6.1                   
## [73] httr2_1.3.0                 wk_0.9.5                   
## [75] evaluate_1.0.5              lattice_0.23-1             
## [77] Biobase_2.73.2              R.methodsS3_1.8.2          
## [79] png_0.1-9                   duckspatial_1.2.1          
## [81] paws.common_0.9.0           bslib_0.12.0               
## [83] class_7.3-24                uuid_1.2-2                 
## [85] Rcpp_1.1.2                  SparseArray_1.13.4         
## [87] anndataR_1.3.2              xfun_0.61                  
## [89] MatrixGenerics_1.25.0       buildtools_1.0.0           
## [91] pkgconfig_2.0.3