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))
# 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))
├── 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)