单细胞转录组学已经改变了我们表征细胞状态的能力,但对生物学更深入的理解需要的不仅仅是对细胞进行简单分类。 随着测量细胞不同维度信息的新方法的出现,一个关键的分析挑战是整合这些数据集以更好地了解细胞特性和功能。 例如,用户可以在同一个生物系统上执行 scRNA-seq 和 scATAC-seq 实验,并使用同一组细胞类型标签一致地注释两个数据集。 但由于以单细胞分辨率下收集到的基因组数据稀疏,而且 scRNA-seq 数据中缺乏可解释的marker基因,scATAC-seq 数据集常常难以注释。使得整合分析具有比较大的挑战性。
2019 年发表的一篇cell详细介绍了整合从同一生物系统收集的 scRNA-seq 和 scATAC-seq 数据集的方法。
在这个vignette中,主要演示了以下分析:
- 如何使用带注释的 scRNA-seq 数据集对 scATAC-seq 实验的细胞进行注释
- 如何共同可视化(co-embed)来自 scRNA-seq 和 scATAC-seq 的细胞
- 如何将 scATAC-seq 细胞投影到源自 scRNA-seq 实验的 UMAP
整合步骤包括如下步骤:
从ATAC-seq中估计RNA-seq表达水平,即从ATAC-seq reads定量基因表达活跃度
使用LSI学习ATAC-seq数据的内部结构
鉴定ATAC-seq和RNA-seq数据集的锚点
数据集间进行transfer,包括聚类的标签,在ATAC-seq数据中推测RNA水平用于共嵌入分析
该vignette使用的演示数据集是 10x Genomics 的公开可用的包含约 12,000 个人类 PBMC“多组学”数据集。在该数据集中,同样的细胞同时检测了scRNA-seq 和 scATAC-seq 信息。 出于演示的目的,我们将数据集视为源自两个不同的实验并将它们整合在一起。 由于它们最初是在相同的细胞中测量的,因此我们可以使用它来评估积分的准确性。 强调:在这里使用多组数据集只是为了演示和评估目,用户可以将这些方法应用于分别测得的 scRNA-seq 和 scATAC-seq 数据集(一般是同一份样品同时检测 scRNA-seq 和 scATAC-seq,但如果数据是分别采集的,也就是同一份样品分成了两份采集的scRNA-seq 和 scATAC-seq,同样也可以这样整合)。 我们提供了一个单独的加权最近邻分析 weighted nearest neighbors (WNN),它描述了多组学单细胞数据的分析策略。(可以整合CITEseq的数据)
1. 加载和预处理数据
library(SeuratData)
# install the dataset and load requirements
InstallData("pbmcMultiome")
library(Seurat)
library(Signac)
library(EnsDb.Hsapiens.v86)
library(ggplot2)
library(cowplot)
# load both modalities 加载的是已经注释好了的数据集
pbmc.rna <- LoadData("pbmcMultiome", "pbmc.rna")
pbmc.atac <- LoadData("pbmcMultiome", "pbmc.atac")
分别处理单细胞转录组和ATAC的数据
# repeat QC steps performed in the WNN vignette
pbmc.rna <- subset(pbmc.rna, seurat_annotations != "filtered")
pbmc.atac <- subset(pbmc.atac, seurat_annotations != "filtered")
对scRNAseq的数据进行常规降维聚类
# Perform standard analysis of each modality independently RNA analysis
pbmc.rna <- NormalizeData(pbmc.rna)
pbmc.rna <- FindVariableFeatures(pbmc.rna)
pbmc.rna <- ScaleData(pbmc.rna)
pbmc.rna <- RunPCA(pbmc.rna)
pbmc.rna <- RunUMAP(pbmc.rna, dims = 1:30)
对ATAC的数据进行处理
# ATAC analysis add gene annotation information
annotations <- GetGRangesFromEnsDb(ensdb = EnsDb.Hsapiens.v86)
seqlevelsStyle(annotations) <- "UCSC"
genome(annotations) <- "hg38"
Annotation(pbmc.atac) <- annotations
# We exclude the first dimension as this is typically correlated with sequencing depth
pbmc.atac <- RunTFIDF(pbmc.atac)
pbmc.atac <- FindTopFeatures(pbmc.atac, min.cutoff = "q0")
pbmc.atac <- RunSVD(pbmc.atac)
pbmc.atac <- RunUMAP(pbmc.atac, reduction = "lsi", dims = 2:30, reduction.name = "umap.atac", reduction.key = "atacUMAP_")
对peak矩阵进行处理使用的隐语义索引(Latent semantic indexing, LSI)
的方法对scATAC-seq数据进行降维。该步骤学习scATAC-seq数据的内部结构,并且在转换信息时对锚点恰当权重的决定很重要。(相当于scRNAseq的PCA,得到的结果储存在reduction这个槽子中,后面umap降维输入的也是‘lsi’降维的结果。)
lsi算法的理解参考:ArchR降维分析
p1 <- DimPlot(pbmc.rna, group.by = "seurat_annotations", label = TRUE,repel = T) + NoLegend() + ggtitle("RNA")
p2 <- DimPlot(pbmc.atac, group.by = "orig.ident", label = FALSE) + NoLegend() + ggtitle("ATAC")
p1 + p2
2. Identifying anchors between scRNA-seq and scATAC-seq datasets
为了识别 scRNA-seq 和 scATAC-seq 之间的“锚点”,我们首先使用了Signac 包中的GeneActivity () 函数,通过量化上游 2 kb 区域和 gene body 中的 ATAC-seq counts来粗略估计每个基因的转录活性。 然后将来自 scATAC-seq 数据的基因活性评分与来自 scRNA-seq 的基因表达量化一起用作CCA (canonical correlation analysis) 的输入。 我们对从 scRNA-seq 数据集中识别为高度可变的所有基因进行这种量化。(和单细胞多组数据的锚点整合看起来是一样的)
# quantify gene activity
gene.activities <- GeneActivity(pbmc.atac, features = VariableFeatures(pbmc.rna))
# add gene activities as a new assay
pbmc.atac[["ACTIVITY"]] <- CreateAssayObject(counts = gene.activities)
# normalize gene activities
DefaultAssay(pbmc.atac) <- "ACTIVITY"
pbmc.atac <- NormalizeData(pbmc.atac)
pbmc.atac <- ScaleData(pbmc.atac, features = rownames(pbmc.atac))
# Identify anchors
transfer.anchors <- FindTransferAnchors(reference = pbmc.rna, query = pbmc.atac, features = VariableFeatures(object = pbmc.rna),
reference.assay = "RNA", query.assay = "ACTIVITY", reduction = "cca")
3. 通过label transfer注释scATAC-seq的细胞
识别锚点后,我们可以将注释从 scRNA-seq 数据集中转移到 scATAC-seq 细胞上。 注释存储在 seurat_annotations 中,并作为 refdata 参数的输入。 输出将包含一个矩阵,其中包含每个 ATAC-seq 细胞的预测和置信度分数。
celltype.predictions <- TransferData(anchorset = transfer.anchors, refdata = pbmc.rna$seurat_annotations,
weight.reduction = pbmc.atac[["lsi"]], dims = 2:30)
pbmc.atac <- AddMetaData(pbmc.atac, metadata = celltype.predictions)
⚠️需要注意的是,在TransferData()
的时候,选的PC数是2:30,差异最大的dim1却没有被选择。
在 FindTransferAnchors() 中,当在 scRNA-seq 数据集之间传输时,我们通常将 PCA 结构从参考集投射到新的数据集上。 然而,当跨组学分析时(比如在这里将scRNA-seq 数据集transfer到scATAC上),我们发现 CCA 更好地捕获了共享特征相关结构,因此在这里设置 reduction = 'cca'。(PCA和CCA的区别) 此外,默认情况下,在 TransferData() 中,我们使用相同的投影 PCA 结构来计算影响细胞预测结果的锚点局部邻域的权重。 在 scRNA-seq 到 scATAC-seq 的transfer中,我们使用通过在 ATAC-seq 数据上计算 LSI 学习到的低维空间来计算这些权重,因为这可以更好地捕捉 ATAC-seq 数据的内部结构。
Transfer后,通过scRNA-seq 数据集预测得到的ATAC-seq 细胞注释存储在 predict.id 槽中。 由于这些细胞是使用多组试剂盒检测的,因此我们还有一个可用于评估的真实注释。 可以看到预测的和实际的注释非常相似。
pbmc.atac$annotation_correct <- pbmc.atac$predicted.id == pbmc.atac$seurat_annotations
p1 <- DimPlot(pbmc.atac, group.by = "predicted.id", label = TRUE) + NoLegend() + ggtitle("Predicted annotation")
p2 <- DimPlot(pbmc.atac, group.by = "seurat_annotations", label = TRUE) + NoLegend() + ggtitle("Ground-truth annotation")
p1 | p2
在这个例子中,scRNA-seq的数据可以~90% 预测得到scATAC-seq数据的注释。 此外,prediction.score.max 量化了与我们预测的注释相关的不确定性。 我们可以看到,正确注释的细胞通常与高预测分数(>90%)相关联,而注释错误的细胞与极低的预测分数(<50%)相关联。 不正确的assignment往往出现在密切相关的细胞类型(比如 Intermediate vs. Naive B细胞)。
predictions <- table(pbmc.atac$seurat_annotations, pbmc.atac$predicted.id)
predictions <- predictions/rowSums(predictions) # normalize for number of cells in each cell type
predictions <- as.data.frame(predictions)
p1 <- ggplot(predictions, aes(Var1, Var2, fill = Freq)) + geom_tile() + scale_fill_gradient(name = "Fraction of cells",
low = "#ffffc8", high = "#7d0025") + xlab("Cell type annotation (RNA)") + ylab("Predicted cell type label (ATAC)") +
theme_cowplot() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
correct <- length(which(pbmc.atac$seurat_annotations == pbmc.atac$predicted.id))
incorrect <- length(which(pbmc.atac$seurat_annotations != pbmc.atac$predicted.id))
data <- FetchData(pbmc.atac, vars = c("prediction.score.max", "annotation_correct"))
p2 <- ggplot(data, aes(prediction.score.max, fill = annotation_correct, colour = annotation_correct)) +
geom_density(alpha = 0.5) + theme_cowplot() + scale_fill_discrete(name = "Annotation Correct",
labels = c(paste0("FALSE (n = ", incorrect, ")"), paste0("TRUE (n = ", correct, ")"))) + scale_color_discrete(name = "Annotation Correct",
labels = c(paste0("FALSE (n = ", incorrect, ")"), paste0("TRUE (n = ", correct, ")"))) + xlab("Prediction Score")
p1 + p2
4. Co-embedding scRNA-seq and scATAC-seq datasets
除了跨组学转移标签外,还可以在同一图上可视化 scRNA-seq 和 scATAC-seq 细胞。 我们强调这一步主要是为了可视化(可选的步骤)。 通常,当我们在 scRNA-seq 和 scATAC-seq 数据集之间进行整合分析时,我们主要关注如上所述的标签转移。 我们在下面展示了我们的共嵌入工作流程,并再次强调这是出于演示目的,特别是在这种特殊情况下,scRNA-seq 数据和 scATAC-seq 数据实际上是在相同的细胞中测量的。
为了执行共嵌入,我们首先根据先前计算的锚点将 RNA 表达“输入”到 scATAC-seq 细胞中,然后合并数据集。
# note that we restrict the imputation to variable genes from scRNA-seq, but could impute the
# full transcriptome if we wanted to
genes.use <- VariableFeatures(pbmc.rna)
refdata <- GetAssayData(pbmc.rna, assay = "RNA", slot = "data")[genes.use, ]
# refdata (input) contains a scRNA-seq expression matrix for the scRNA-seq cells. imputation
# (output) will contain an imputed scRNA-seq matrix for each of the ATAC cells
imputation <- TransferData(anchorset = transfer.anchors, refdata = refdata, weight.reduction = pbmc.atac[["lsi"]],
dims = 2:30)
pbmc.atac[["RNA"]] <- imputation
coembed <- merge(x = pbmc.rna, y = pbmc.atac)
# Finally, we run PCA and UMAP on this combined object, to visualize the co-embedding of both
# datasets
coembed <- ScaleData(coembed, features = genes.use, do.scale = FALSE)
coembed <- RunPCA(coembed, features = genes.use, verbose = FALSE)
coembed <- RunUMAP(coembed, dims = 1:30)
DimPlot(coembed, group.by = c("orig.ident", "seurat_annotations"))