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.

We present SpaTopic, which 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 method was originally developed for image segmentation in computer vision, incorporating spatial information into the flexible design of regions (image partitions, analogous to documents in language modeling). We further adapted and refined the approach to address unique challenges in cellular images and provide an efficient C++ implementation of the algorithm in this R package.

Contrasting to computationally intensive K-nearest-neighbor-based cell neighborhood analysis approaches (such as KNN-kmeans, the default neighborhood analysis in Seurat v5 R package), 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. Here we mainly followed the cell annoration step from Satija Lab, with more information 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.2.0'
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))
#> [14:49:07] [SpaTopic INFO] Number of cells per image: 100149
#> [14:49:07] [SpaTopic INFO] Start initialization...
#> [14:49:07] [SpaTopic INFO] Number of Initializations: 10
#> [14:49:26] [SpaTopic RESULT] Min perplexity during initialization: 11.6302
#> [14:49:26] [SpaTopic INFO] Number of region centers selected: 971
#> [14:49:26] [SpaTopic INFO] Average number of cells per region: 103.14
#> [14:49:26] [SpaTopic PROGRESS] Initialization complete. Starting Gibbs sampling...
#> [14:50:02] [SpaTopic COMPLETE] Gibbs sampling completed successfully
#> [14:50:02] [SpaTopic RESULT] Final model perplexity: 11.3156
#>    user  system elapsed 
#>  55.081   0.160  55.272

Print the result

print(gibbs.res)
#> SpaTopic Results
#> ----------------
#> Number of topics: 7 
#> Perplexity: 11.31563 
#> 
#> Topic Content(Topic distribution across cell types):
#>                                 topic1       topic2       topic3      topic4
#> Alveolar Epithelial Type 1 0.035870295 6.511503e-03 4.541367e-06 0.026643327
#> Alveolar Epithelial Type 2 0.025386476 3.553900e-02 4.541367e-06 0.017427665
#> Artery                     0.007545591 2.624548e-06 9.128148e-04 0.001856373
#> B                          0.018581190 5.800251e-04 3.446035e-01 0.015203195
#> Basal                      0.025846292 7.753466e-01 1.730261e-03 0.089193312
#>                                  topic5       topic6      topic7
#> Alveolar Epithelial Type 1 2.987411e-06 6.348481e-06 0.005341969
#> Alveolar Epithelial Type 2 2.987411e-06 6.348481e-06 0.006994451
#> Artery                     5.320579e-03 2.044846e-02 0.006041096
#> B                          1.912242e-02 3.434528e-03 0.018434717
#> Basal                      4.902342e-03 6.348481e-06 0.006549552
#> ...
#> 
#> Use $Z.trace for posterior probabilities of topic assignments for each cell
#> Use $cell_topics for final topic assignments for each cell
#> Use $parameters for accessing model parameters

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.

## you can can access the posterior probabilities of topic assignments for each cell
prob<-as.matrix(gibbs.res$Z.trace)
nano.obj$Topic<-as.factor(apply(prob,1,which.max))
## In the new version of SpaTopic, the final topic assignments is in cell topics.
nano.obj$Topic <- as.factor(gibbs.res$cell_topics)
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.