Skip to contents

Introduction

Recent advancements in multiplexed tissue imaging allow for examination of tissue microenvironments in great detail. These cutting-edge technologies offer invaluable insights into cellular heterogeneity and spatial architectures, playing a crucial role in decoding mechanisms of treatment response and disease progression.

However, gaining a deep understanding of complex spatial patterns remains challenging. SpaTopic implements a novel spatial topic model to integrate both cell type and spatial information to identify the complex spatial tissue structures without human intervention. The Collapsed Gibbs sampling algorithm is used for model inference. Contrasting to computationally intensive K-nearest-neighbor-based cell neighborhood analysis approaches, SpaTopic is more scalable to large-scale image datasets without extracting neighborhood information for every single cell.

SpaTopic can be applied either on a single image or across multiple images.

Set-up

We use a non-small cell lung cancer image to illustrate how to use SpaTopic. The data object here can be download from here, with original public resources available on the nanostring website. These images were generated using a 960-plex CoxMx RNA panel on the Nanostring CoxMx Spatial Molecular Imager platform. We selected Lung5-1 sample and annotated cells using Azimuth based on the human lung reference v1.0. The Lung5-1 sample contains 38 annotated cell types. Since we used healthy lung tissue as the reference, tumor cells were labeled as ’basal’ cells. More informaion can be found here.

## We use Seurat v5 package to visualize the results.
## If you still use Seurat v4, you will have the error
library(Seurat, quietly = TRUE);packageVersion("Seurat")
#> [1] '5.0.2'
## Load the Seurat object for the image
load("~/Documents/Research/github/SpaTopic_data/nanostring_example.rdata")
## for large dataset
options(future.globals.maxSize = 1e9)

We can use the Seurat function ImageDimPlot to visualize the distribution of cell types on the image.

library(ggplot2)
celltype.plot <-ImageDimPlot(nano.obj, fov = "lung5.rep1", axes = TRUE, cols = "glasbey",dark.background = T)
celltype.plot+theme(legend.position = "bottom",legend.direction = "vertical")

Topic Inference on a Single Image

Now, our data is ready. Below we show an example how to use SpaTopic to identify tissue architectures from multiplexed images.

Input

The required input of SpaTopic is a data frame containing cells within on a single image or a list of data frames for multiple images. Each data frame consists of four columns: The image ID, X, Y cell coordinates, and cell type.

You may use the function Seurat5obj_to_SpaTopic() to extract input data from a typical Seurat v5 object. The column name for cell type information need to be provided via option group.by.

library(SpaTopic);packageVersion("SpaTopic")
#> [1] '1.1.0.9900'
library(sf)
## Prepare input from Seurat Object
dataset<-Seurat5obj_to_SpaTopic(object = nano.obj, group.by = "predicted.annotation.l1",image = "image1")
head(dataset)
#>      image        X        Y           type
#> 1_1 image1 4215.889 158847.7      Dendritic
#> 2_1 image1 6092.889 158834.7     Macrophage
#> 3_1 image1 7214.889 158843.7 Neuroendocrine
#> 4_1 image1 7418.889 158813.7     Macrophage
#> 5_1 image1 7446.889 158845.7     Macrophage
#> 6_1 image1 3254.889 158838.7          CD4 T

Gibbs Sampling

This step takes around 90 seconds on a regular laptop

## Gibbs sampling for SpaTopic
system.time(gibbs.res<-SpaTopic_inference(dataset, ntopics = 7, sigma = 50, region_radius = 400))
#> number of cells per image:
#> 100149
#> Start initialization...
#> Numer of Initializations:
#> 10
#> Min perplexity during initialization:
#> 11.6302259709245
#> number of region centers selected:
#> 971
#> number of cells per region on average:
#> 103.140061791967
#> Finish initialization. Start Gibbs sampling...
#> Gibbs sampling done.
#> Output model perplexity:
#> 11.3156329380619
#>    user  system elapsed 
#>  54.056   0.074  54.179

Topic Content and Distribution

SpaTopic identify seven topics from the image. Below we use the heatmap to show the cell type composition within each topic.

library(pheatmap)
m <- as.data.frame(gibbs.res$Beta)
pheatmap::pheatmap(t(m))

We assign each cell to a topic with the highest posterior probability and visualize the distribution of cell topics over the image.

prob<-as.matrix(gibbs.res$Z.trace)
nano.obj$Topic<-as.factor(apply(prob,1,which.max))
library(ggplot2)
palatte<- c("#0000FFFF","#FF0000FF","#00FF00FF","#009FFFFF","#FF00B6FF","#005300FF","#FFD300FF")
ImageDimPlot(nano.obj, fov = "lung5.rep1", group.by = "Topic", axes = TRUE, 
                           dark.background = T,cols = palatte) + ggtitle("Topic") 

Compare to BuildNicheAssay() in Seurat v5

We compare SpaTopic to the function BuildNicheAssay() in Seurat v5. It took around 5 min on the same laptop.

### NOT RUN!! We use the pre-computed result
system.time(nano.obj <- BuildNicheAssay(object = nano.obj, "lung5.rep1", group.by = "predicted.annotation.l1",
                            niches.k = 7, neighbors.k = 100))

We also visualize the distribution of seven niches over the same image.

nano.obj$niches<-factor(nano.obj$niches)
nano.obj$niches<-ordered(nano.obj$niches,levels = c(1,2,3,4,5,6,7))
## try to match the colors of topics
palatte2<- c("#FF00B6FF","#0000FFFF","#FFD300FF","#009FFFFF","#FF0000FF","#005300FF","#00FF00FF")
ImageDimPlot(nano.obj, fov = "lung5.rep1", group.by = "niches", axes = TRUE, dark.background = T,cols = palatte2) + ggtitle("Niches") 

Topic Inference on Multiple Images

SpaTopic can identify common tissue patterns across multiple images. The input should be a list of data frames. See an example below (not run).

## tissue1, tissue2 are data frames of two different images.
gibbs.res<-SpaTopic_inference(list(A = tissue1, B = tissue2), ntopics = 7, sigma = 50, region_radius = 400) 

Please check more examples in SpaTopic Home Page.