Authors
Affiliations

Helena L. Crowell

CNAG, Barcelona, Spain

Daria Lazic

EMBL, Heidelberg, Germany

Published

May 30, 2026

CSAMA

In this demo, we’ll be analyzing 5K-plex Xenium (10x Genomics) data on a tissue section from a human breast cancer biopsy, derived from here. These include the following elements:

  • two image objects:
    • hematoxylin and eosin staining (“he_image”), and
    • 4-plex immunofluorescence image (“morphology_focus”)
  • two shape objects:
    • cell membrane (“cell_boundaries”), and
    • nuclei segmentation (“nucleus_boundaries”)
  • one table object:
    • gene \(\times\) cell transcript counts
      (based on “cell_boundaries”)
  • one point object:
    • individual RNA transcripts
      (across 5,101 genes)

Preamble

Dataset

A size-reduced example dataset has been deposited on Zenodo. We’ll retrieve the compressed SpatialData .zarr store together with a reference scRNA-seq dataset in .h5ad format (Janesick et al. 2023), decompress both archives, and stash their on-disk file paths for later:

# scRNA-seq data (.h5ad)
url_h5 <- file.path(
    "https://zenodo.org/records/20178278/files",
    "BC_scRNAseq_subset.h5ad.zip?download=1")

# retrieve
zip_h5 <- tempfile(fileext=".h5ad.zip")
download.file(url_h5, zip_h5, quiet=TRUE)

# decompress
fnm_h5 <- unzip(zip_h5, exdir=dirname(zip_h5))
h5 <- grep("h5ad$", fnm_h5, value=TRUE)
cat(basename(h5))
BC_scRNAseq_subset.h5ad
# SpatialData store (.zarr)
url_zs <- file.path(
    "https://zenodo.org/records/20180722/files",
    "BC_10x_xenium_sdata.zarr.zip?download=1")

# retrieve
zip_zs <- tempfile(fileext=".zarr.zip")
download.file(url_zs, zip_zs, quiet=TRUE)

# decompress
fnm_zs <- unzip(zip_zs, exdir=dirname(zip_zs))
zs <- grep("zarr$", dirname(fnm_zs), value=TRUE)
cat(basename(zs))
BC_10x_xenium_sdata.zarr
├── images
│   ├── he_image
│   │   ├── s0
│   │   │   ├── c
│   │   │   │   └── 0
│   │   │   │       ├── 0
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   ├── 6
│   │   │   │       │   └── 7
│   │   │   │       ├── 1
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   ├── 6
│   │   │   │       │   └── 7
│   │   │   │       ├── 2
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   ├── 6
│   │   │   │       │   └── 7
│   │   │   │       ├── 3
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   ├── 6
│   │   │   │       │   └── 7
│   │   │   │       ├── 4
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   ├── 6
│   │   │   │       │   └── 7
│   │   │   │       ├── 5
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   ├── 6
│   │   │   │       │   └── 7
│   │   │   │       ├── 6
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   ├── 6
│   │   │   │       │   └── 7
│   │   │   │       ├── 7
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   ├── 6
│   │   │   │       │   └── 7
│   │   │   │       └── 8
│   │   │   │           ├── 0
│   │   │   │           ├── 1
│   │   │   │           ├── 2
│   │   │   │           ├── 3
│   │   │   │           ├── 4
│   │   │   │           ├── 5
│   │   │   │           ├── 6
│   │   │   │           └── 7
│   │   │   └── zarr.json
│   │   ├── s1
│   │   │   ├── c
│   │   │   │   └── 0
│   │   │   │       ├── 0
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   └── 3
│   │   │   │       ├── 1
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   └── 3
│   │   │   │       ├── 2
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   └── 3
│   │   │   │       ├── 3
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   └── 3
│   │   │   │       └── 4
│   │   │   │           ├── 0
│   │   │   │           ├── 1
│   │   │   │           ├── 2
│   │   │   │           └── 3
│   │   │   └── zarr.json
│   │   ├── s2
│   │   │   ├── c
│   │   │   │   └── 0
│   │   │   │       ├── 0
│   │   │   │       │   ├── 0
│   │   │   │       │   └── 1
│   │   │   │       ├── 1
│   │   │   │       │   ├── 0
│   │   │   │       │   └── 1
│   │   │   │       └── 2
│   │   │   │           ├── 0
│   │   │   │           └── 1
│   │   │   └── zarr.json
│   │   ├── s3
│   │   │   ├── c
│   │   │   │   └── 0
│   │   │   │       ├── 0
│   │   │   │       │   └── 0
│   │   │   │       └── 1
│   │   │   │           └── 0
│   │   │   └── zarr.json
│   │   └── zarr.json
│   ├── morphology_focus
│   │   ├── s0
│   │   │   ├── c
│   │   │   │   └── 0
│   │   │   │       ├── 0
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   └── 6
│   │   │   │       ├── 1
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   └── 6
│   │   │   │       ├── 2
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   └── 6
│   │   │   │       ├── 3
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   └── 6
│   │   │   │       ├── 4
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   └── 6
│   │   │   │       ├── 5
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   └── 6
│   │   │   │       ├── 6
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   └── 6
│   │   │   │       ├── 7
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   ├── 3
│   │   │   │       │   ├── 4
│   │   │   │       │   ├── 5
│   │   │   │       │   └── 6
│   │   │   │       └── 8
│   │   │   │           ├── 0
│   │   │   │           ├── 1
│   │   │   │           ├── 2
│   │   │   │           ├── 3
│   │   │   │           ├── 4
│   │   │   │           ├── 5
│   │   │   │           └── 6
│   │   │   └── zarr.json
│   │   ├── s1
│   │   │   ├── c
│   │   │   │   └── 0
│   │   │   │       ├── 0
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   └── 3
│   │   │   │       ├── 1
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   └── 3
│   │   │   │       ├── 2
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   └── 3
│   │   │   │       ├── 3
│   │   │   │       │   ├── 0
│   │   │   │       │   ├── 1
│   │   │   │       │   ├── 2
│   │   │   │       │   └── 3
│   │   │   │       └── 4
│   │   │   │           ├── 0
│   │   │   │           ├── 1
│   │   │   │           ├── 2
│   │   │   │           └── 3
│   │   │   └── zarr.json
│   │   ├── s2
│   │   │   ├── c
│   │   │   │   └── 0
│   │   │   │       ├── 0
│   │   │   │       │   ├── 0
│   │   │   │       │   └── 1
│   │   │   │       ├── 1
│   │   │   │       │   ├── 0
│   │   │   │       │   └── 1
│   │   │   │       └── 2
│   │   │   │           ├── 0
│   │   │   │           └── 1
│   │   │   └── zarr.json
│   │   ├── s3
│   │   │   ├── c
│   │   │   │   └── 0
│   │   │   │       ├── 0
│   │   │   │       │   └── 0
│   │   │   │       └── 1
│   │   │   │           └── 0
│   │   │   └── zarr.json
│   │   └── zarr.json
│   └── zarr.json
├── points
│   ├── transcripts
│   │   ├── points.parquet
│   │   │   └── part.0.parquet
│   │   └── zarr.json
│   └── zarr.json
├── shapes
│   ├── cell_boundaries
│   │   ├── shapes.parquet
│   │   └── zarr.json
│   ├── nucleus_boundaries
│   │   ├── shapes.parquet
│   │   └── zarr.json
│   └── zarr.json
├── tables
│   ├── table
│   │   ├── X
│   │   │   ├── data
│   │   │   │   ├── c
│   │   │   │   │   ├── 0
│   │   │   │   │   ├── 1
│   │   │   │   │   ├── 10
│   │   │   │   │   ├── 11
│   │   │   │   │   ├── 12
│   │   │   │   │   ├── 13
│   │   │   │   │   ├── 14
│   │   │   │   │   ├── 15
│   │   │   │   │   ├── 2
│   │   │   │   │   ├── 3
│   │   │   │   │   ├── 4
│   │   │   │   │   ├── 5
│   │   │   │   │   ├── 6
│   │   │   │   │   ├── 7
│   │   │   │   │   ├── 8
│   │   │   │   │   └── 9
│   │   │   │   └── zarr.json
│   │   │   ├── indices
│   │   │   │   ├── c
│   │   │   │   │   ├── 0
│   │   │   │   │   ├── 1
│   │   │   │   │   ├── 10
│   │   │   │   │   ├── 11
│   │   │   │   │   ├── 12
│   │   │   │   │   ├── 13
│   │   │   │   │   ├── 14
│   │   │   │   │   ├── 15
│   │   │   │   │   ├── 2
│   │   │   │   │   ├── 3
│   │   │   │   │   ├── 4
│   │   │   │   │   ├── 5
│   │   │   │   │   ├── 6
│   │   │   │   │   ├── 7
│   │   │   │   │   ├── 8
│   │   │   │   │   └── 9
│   │   │   │   └── zarr.json
│   │   │   ├── indptr
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   └── zarr.json
│   │   ├── layers
│   │   │   └── zarr.json
│   │   ├── obs
│   │   │   ├── _index
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── cell_area
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── cell_id
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── centroid_x
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── centroid_y
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── control_codeword_counts
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── control_probe_counts
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── deprecated_codeword_counts
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── genomic_control_counts
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── nucleus_area
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── nucleus_count
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── region
│   │   │   │   ├── categories
│   │   │   │   │   ├── c
│   │   │   │   │   │   └── 0
│   │   │   │   │   └── zarr.json
│   │   │   │   ├── codes
│   │   │   │   │   └── zarr.json
│   │   │   │   └── zarr.json
│   │   │   ├── segmentation_method
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── total_counts
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── transcript_counts
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── unassigned_codeword_counts
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── z_level
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   └── zarr.json
│   │   ├── obsm
│   │   │   ├── spatial
│   │   │   │   ├── c
│   │   │   │   │   ├── 0
│   │   │   │   │   │   └── 0
│   │   │   │   │   └── 1
│   │   │   │   │       └── 0
│   │   │   │   └── zarr.json
│   │   │   └── zarr.json
│   │   ├── obsp
│   │   │   └── zarr.json
│   │   ├── raw
│   │   │   └── zarr.json
│   │   ├── uns
│   │   │   ├── spatialdata_attrs
│   │   │   │   ├── instance_key
│   │   │   │   │   ├── c
│   │   │   │   │   └── zarr.json
│   │   │   │   ├── region
│   │   │   │   │   ├── c
│   │   │   │   │   │   └── 0
│   │   │   │   │   └── zarr.json
│   │   │   │   ├── region_key
│   │   │   │   │   ├── c
│   │   │   │   │   └── zarr.json
│   │   │   │   └── zarr.json
│   │   │   └── zarr.json
│   │   ├── var
│   │   │   ├── _index
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── feature_types
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── gene_ids
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   ├── genome
│   │   │   │   ├── c
│   │   │   │   │   └── 0
│   │   │   │   └── zarr.json
│   │   │   └── zarr.json
│   │   ├── varm
│   │   │   └── zarr.json
│   │   ├── varp
│   │   │   └── zarr.json
│   │   └── zarr.json
│   └── zarr.json
└── zarr.json

Libraries

Throughout this demo, we’ll require the following R dependencies; these expect R v4.6.0 and Bioconductor v3.24 (devel/pre-release).

library(sf)
library(dplyr)
library(tidyr)
library(ggplot2)
library(anndataR)
library(scrapper)
library(patchwork)
library(reticulate)
library(SpatialData)
library(SpatialData.data)
library(SpatialData.plot)
library(SingleCellExperiment)

Visualization

Let’s load up the SpatialData object in R.

(sd <- readSpatialData(zs))
class: SpatialData
- images(2):
  - he_image (3,2141,1822)
  - morphology_focus (4,2111,1787)
- labels(0):
- points(1):
  - transcripts (2978451)
- shapes(2):
  - cell_boundaries (18626,circle)
  - nucleus_boundaries (18389,circle)
- tables(1):
  - table (5101,18626) [cell_boundaries]
coordinate systems(1):
- global(5): he_image morphology_focus cell_boundaries
  nucleus_boundaries transcripts

Histopathology

Let’s start out by visualization the hematoxylin and eosin (H&E) staining. H&E provides a high-contrast visualization of tissue microarchitecture and cellular morphology through differential staining of nuclear and cytoplasmic components. To date, whole-slide H&E images (WSIs) remain the clinical gold standard for cancer diagnosis, including tumor grading, staging, and prognosis.

plotSpatialData() + plotImage(sd)

We can also zoom into a particular region by specifying a bounding box and using crop() to subset the data accordingly across all layers:

bb <- list(
    xmin=15e3, xmax=18e3, 
    ymin=44e3, ymax=46e3)
sp <- crop(sd, bb)
plotSpatialData() + plotImage(sp)