前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >空间转录组数据注释分析:SPOTlight反卷积

空间转录组数据注释分析:SPOTlight反卷积

作者头像
生信技能树
发布2025-03-24 14:06:52
发布2025-03-24 14:06:52
14000
代码可运行
举报
文章被收录于专栏:生信技能树生信技能树
运行总次数:0
代码可运行

空间分辨的基因表达谱对于理解组织结构和功能至关重要。然而,空间转录组学(Spatial Transcriptomics, ST)分析技术缺乏单细胞分辨率,并且需要结合scRNA-seq 信息来解析空间索引数据集。

利用这两种数据类型的优点,Holger Heyn 团队开发了 SPOTlight 这一计算工具,于2021年5月21号发表在NAR杂志上,标题为《SPOTlight: seeded NMF regression to deconvolute spatial transcriptomics spots with single-cell transcriptomes》。

它能够整合ST和scRNA-seq数据,以推断复杂组织中细胞类型和状态的位置。SPOTlight的核心是基于种子的非负矩阵分解(seeded Non-negative Matrix Factorization, NMF)回归,该方法通过使用细胞类型标记基因进行初始化,并利用非负最小二乘法(Non-negative Least Squares, NNLS)来进一步解析ST捕获位置(spot)的空间分布。

SPOTlight官网:https://github.com/MarcElosua/SPOTlight

软件安装

我这里选择了github上面的最新版本:

代码语言:javascript
代码运行次数:0
运行
复制
# 设置一下镜像
## 使用西湖大学的 Bioconductor镜像
options(BioC_mirror="https://mirrors.westlake.edu.cn/bioconductor")
options("repos"=c(CRAN="https://mirrors.westlake.edu.cn/CRAN/"))

#install.packages("devtools")
library(devtools)
install_github("https://github.com/MarcElosua/SPOTlight")

本次分析参考教程:

https://github.com/MarcElosua/SPOTlight/blob/main/vignettes/SPOTlight_kidney.Rmd

输入数据

输入的数据有:

  • ST (sparse) matrix:空间表达矩阵,可以是raw count,标准化后的data,行为基因,列为spot
  • Single cell (sparse) matrix:单细胞表达矩阵,可以是raw count,标准化后的data,行为基因,列为细胞
  • Vector:单细胞的每个细胞注释标签向量,顺序对应单细胞矩阵的列
  • 其他格式:输入数据还可以为SpatialExperimentSingleCellExperiment对象

本次使用数据,空转来自 10x 官网,为小鼠的肾脏:https://support.10xgenomics.com/spatial-gene-expression/datasets/1.1.0/V1_Mouse_Kidney

小鼠单细胞数据来自文章:https://www.nature.com/articles/s41586-020-2496-1,超过35w的细胞,我们这里只用其中的kidney。

这两个数据都可以从 TENxVisiumData 包中得到:

为了减少由年龄和批次效应引入的潜在噪声,这里的单细胞数据会选择来自同一年龄阶段的细胞。

代码语言:javascript
代码运行次数:0
运行
复制
rm(list=ls())
library(ggplot2)
library(SPOTlight)
library(SingleCellExperiment)
library(SpatialExperiment)
library(scater)
library(scran)

# 数据准备
# 空转数据
library(TENxVisiumData)
spe <- MouseKidneyCoronal()
spe
# 将spe的行名转为基因名字
head(rownames(spe))
rownames(spe) <- rowData(spe)$symbol
# 先保存一下,下次可以直接导入
library(qs)
qsave(spe, file="spe.qs")


# 单细胞数据
library(TabulaMurisSenisData)
sce <- TabulaMurisSenisDroplet(tissues = "Kidney")$Kidney
sce
# 先保存一下,下次可以直接导入
qsave(sce, file="sce.qs")
table(sce$free_annotation, sce$age)

# 选择同一个时间段的细胞:18m mice
sce <- sce[, sce$age == "18m"]
# Keep cells with clear cell type annotations
sce <- sce[, !sce$free_annotation %in% c("nan", "CD45")]
sce

数据预处理

如果数据集非常庞大,这里可以进行downsampling来进一步优化性能和计算资源,在文献中,软件测试了将每种细胞类型的细胞数量降采样到约100个,以及 将基因集限制为每种细胞类型的标记基因以及最多3000个高变基因,并不会影响模型的性能,详细描述见文献:

https://academic.oup.com/nar/article/49/9/e50/6129341

1.特征基因选择

我们的目标是识别那些驱动生物学异质性的高变基因。通过将这些基因输入到模型中,我们可以提高生物学结构的分辨率,并减少技术噪声。这里选择了非线粒体与核糖体的3000个hvg:

代码语言:javascript
代码运行次数:0
运行
复制
# Feature selection
sce <- logNormCounts(sce)

# Variance modelling
# 首先排除 ribosomal or mitochondrial 基因
genes <- !grepl(pattern = "^Rp[l|s]|Mt", x = rownames(sce))
table(genes)
dec <- modelGeneVar(sce, subset.row = genes)
plot(dec$mean, dec$total, xlab = "Mean log-expression", ylab = "Variance")
curve(metadata(dec)$trend(x), col = "blue", add = TRUE)
# Get the top 3000 genes.
hvg <- getTopHVGs(dec, n = 3000)
hvg
grep("CD3", hvg, ignore.case = T,value = T)

2.获取每种细胞类型的标记基因

接下来,获取每种细胞类型的标记基因。你可以使用任何方法,只要它能够返回一个权重,以表明该基因对该细胞类型的重要性。例如,可以使用avgLogFC(平均对数倍数变化)、AUC(曲线下面积)、pct.expressed(表达百分比)、p-value等。

代码语言:javascript
代码运行次数:0
运行
复制
# 2.细胞类型的特征基因
colLabels(sce) <- colData(sce)$free_annotation
# Compute marker genes
mgs <- scoreMarkers(sce, subset.row = genes)

mgs_fil <- lapply(names(mgs), function(i) {
  x <- mgs[[i]]
# Filter and keep relevant marker genes, those with AUC > 0.8
  x <- x[x$mean.AUC > 0.8, ]
# Sort the genes from highest to lowest weight
  x <- x[order(x$mean.AUC, decreasing = TRUE), ]
# Add gene and cluster id to the dataframe
  x$gene <- rownames(x)
  x$cluster <- i
  data.frame(x)
})
mgs_df <- do.call(rbind, mgs_fil)

3.Cell Downsampling

接下来,对每种细胞降采样到最多100个细胞。如果一种细胞类型的细胞数少于100个,则会使用所有细胞。

如果细胞身份在生物学上差异很大(例如B细胞、T细胞、巨噬细胞和上皮细胞),我们可以使用较少的细胞,因为它们的转录组特征会有很大差异。而在细胞身份转录组更相似的情况下,我们需要增加样本量(N),以便捕捉它们之间的生物学异质性。

根据作者的经验,在这个步骤中,如果你有一个来自多次实验的联合数据集,最好从同一批次中选择每种细胞类型的细胞。这将确保模型尽可能多地去除批次信号,从而真正学习到生物学信号。

为了本教程的目的,并加快分析速度,这里将每种细胞降采样到20个细胞:

代码语言:javascript
代码运行次数:0
运行
复制
# 3.Cell Downsampling
# 生成一个每种细胞类型的list对象
idx <- split(seq(ncol(sce)), sce$free_annotation)
# 降采样到每种细胞20个细胞,真实数据中需要使用100个以上
n_cells <- 20
cs_keep <- lapply(idx, function(i) {
  n <- length(i)
  if (n < n_cells)
    n_cells <- n
  sample(i, n_cells)
})
sce <- sce[, unlist(cs_keep)]
sce
table(sce$free_annotation)

反卷积Deconvolution

接下来运行 SPOTlight 对每个空间spot进行反卷积

代码语言:javascript
代码运行次数:0
运行
复制
## 反卷积
res <- SPOTlight(
  x = sce,
  y = spe,
  groups = as.character(sce$free_annotation),
  mgs = mgs_df,
  hvg = hvg,
  weight_id = "mean.AUC",
  group_id = "cluster",
  gene_id = "gene")


# 提取反卷积矩阵:每一行为一个spot,每一列为一种细胞类型,值为细胞类型在spot中的相对百分比
# 行和一定为1
head(mat <- res$mat)[, 1:3]
dim(mat)
gead(rowSums(mat))
# 提取NMF模型
mod <- res$NMF

得到的mat 就是反卷积的结果了,每一行为一个spot,每一列为一种细胞类型,值为细胞类型在spot中的相对百分比,行和一定为1

反卷积结果可视化:饼图

1.Topic profiles

首先,评估每个 Topic profiles 特征对每种细胞身份的特异性。理想情况下,每种细胞身份都会有一个独特的 Topic profiles 与之关联,如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
## 可视化
plotTopicProfiles(
  x = mod,
  y = sce$free_annotation,
  facet = FALSE,
  min_prop = 0.01,
  ncol = 1) +
  theme(aspect.ratio = 1)

这里有两个细胞亚群有两个 Topic profiles

接下来,还需要确保来自同一细胞身份的所有细胞具有相似的 Topic profiles ,因为这将意味着SPOTlight已经为同一细胞身份的所有细胞学习到了一个一致的特征 signature:

代码语言:javascript
代码运行次数:0
运行
复制
plotTopicProfiles(
  x = mod,
  y = sce$free_annotation,
  facet = TRUE,
  min_prop = 0.01,
  ncol = 6)

最后,我们可以查看模型为每个Topic学到的基因。较高的值表明该基因对该Topic更为重要。在下表中,我们可以看到Topic1的top基因特征为B细胞(例如CD79ACD79BMS4A1等)。

代码语言:javascript
代码运行次数:0
运行
复制
library(NMF)
sign <- basis(mod)
colnames(sign) <- paste0("Topic", seq_len(ncol(sign)))
head(sign)
# This can be dynamically visualized with DT as shown below
DT::datatable(sign, fillContainer = TRUE, filter = "top")

2.Spatial Correlation Matrix

对反卷积得到的矩阵 mat 绘制一个相关性图,这个图是基于细胞类型比例得到的:

代码语言:javascript
代码运行次数:0
运行
复制
plotCorrelationMatrix(mat)

3.细胞类型共定位

既然我们已经知道了每个spot中存在的细胞类型,我们就可以绘制一个表示空间相互作用的图,其中细胞类型之间的连接线(边)会根据它们在同一spot中共同出现的频率而变得更粗(即连接更强):

代码语言:javascript
代码运行次数:0
运行
复制
plotInteractions(mat, which = "heatmap", metric = "prop")
plotInteractions(mat, which = "heatmap", metric = "jaccard")
plotInteractions(mat, which = "network")

3.空间切片上展示注释结果

使用饼图的形式展示每个spot中注释得到细胞类型:

代码语言:javascript
代码运行次数:0
运行
复制
## 饼图
ct <- colnames(mat)
# 占比小于0.1的不展示
mat[mat < 0.1] <- 0

# 颜色设置
paletteMartin <- c(
"#000000", "#004949", "#009292", "#ff6db6", "#ffb6db", 
"#490092", "#006ddb", "#b66dff", "#6db6ff", "#b6dbff", 
"#920000", "#924900", "#db6d00", "#24ff24", "#ffff6d")
pal <- colorRampPalette(paletteMartin)(length(ct))
names(pal) <- ct
pal

plotSpatialScatterpie(
  x = spe,
  y = mat,
  cell_types = colnames(mat),
  img = FALSE,
  scatterpie_alpha = 1,
  pie_scale = 0.4) +
  scale_fill_manual(
    values = pal,
    breaks = names(pal))

上面这个切片大饼图就是很多文献中使用的注释结果展示啦!在展示这个结果的时候作者将占比比较小的细胞类型进行了归0处理,后面绘图可以借鉴一下~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 生信技能树 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 软件安装
  • 输入数据
  • 数据预处理
    • 1.特征基因选择
    • 2.获取每种细胞类型的标记基因
    • 3.Cell Downsampling
  • 反卷积Deconvolution
  • 反卷积结果可视化:饼图
    • 1.Topic profiles
    • 2.Spatial Correlation Matrix
    • 3.细胞类型共定位
    • 3.空间切片上展示注释结果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档