跳转至

750. 单细胞表面蛋白CITE-seq进阶

一句话概述:CITE-seq同时测量每个细胞的mRNA和表面蛋白,进阶分析包括多模态整合、加权最近邻(WNN)分析、蛋白特异性聚类——就像同时看一个人的"身份证"(基因表达)和"工作服"(表面蛋白)来更精确地判断他的身份。


核心知识点速查表

概念白话解释关键工具
CITE-seq用抗体标记测表面蛋白+RNA10x, BioLegend
ADTAntibody-Derived Tag,抗体来源的标签TotalSeq
WNN加权最近邻,综合RNA和蛋白信息Seurat v4+
CLR中心对数比变换,ADT归一化方法Seurat
DSB去除背景和技术噪声的ADT归一化dsb R包
多模态同时分析RNA+蛋白两种数据Seurat, muon

一、原理(白话版)

1.1 为什么需要CITE-seq?

单纯的scRNA-seq有个问题: - mRNA表达≠蛋白表达(转录后调控、蛋白半衰期) - 很多免疫细胞标记蛋白(CD4、CD8、CD45)在mRNA水平很难区分 - 流式/CyTOF看蛋白但不看RNA

CITE-seq的解决方案:同时测两者 - RNA → 知道基因在干什么 - 蛋白 → 知道细胞"长什么样"(表型)

1.2 进阶分析要点

分析内容目的
ADT归一化(DSB)更准确的蛋白表达定量
WNN分析综合RNA和蛋白做更好的聚类
RNA-蛋白一致性哪些基因mRNA和蛋白相关
蛋白特异性标记找到只在蛋白水平区分的细胞亚群

二、数据处理与归一化

2.1 Seurat处理CITE-seq

# ===== Seurat处理CITE-seq数据 =====
library(Seurat)

# 读取10x数据(包含RNA和ADT两个矩阵)
data <- Read10X("filtered_feature_bc_matrix/")
# data是一个列表:
# data$`Gene Expression` → RNA矩阵
# data$`Antibody Capture` → ADT矩阵

# 创建Seurat对象(先用RNA)
seurat_obj <- CreateSeuratObject(
  counts = data$`Gene Expression`,  # RNA counts
  project = "CITE-seq",
  min.cells = 3,   # 基因至少在3个细胞中表达
  min.features = 200  # 细胞至少表达200个基因
)

# 添加ADT数据作为新的Assay
seurat_obj[["ADT"]] <- CreateAssayObject(
  counts = data$`Antibody Capture`[, colnames(seurat_obj)]  # 匹配同样的细胞
)

# 查看ADT蛋白列表
rownames(seurat_obj[["ADT"]])
# CD3, CD4, CD8, CD19, CD56, CD14, CD45RA, CD45RO, ...

2.2 ADT归一化(DSB方法 vs CLR)

# ===== 方法一:CLR归一化(Seurat默认)=====
seurat_obj <- NormalizeData(
  seurat_obj,
  assay = "ADT",           # 对ADT做归一化
  normalization.method = "CLR",  # 中心对数比变换
  margin = 2                # 按细胞归一化(margin=2)
)

# ===== 方法二:DSB归一化(推荐,更准确)=====
# DSB可以利用空液滴(empty droplets)作为背景噪声估计
library(dsb)

# 需要:正常细胞的ADT counts + 空液滴的ADT counts
# 空液滴从Cell Ranger的raw_feature_bc_matrix中获取(未过滤的)
raw_data <- Read10X("raw_feature_bc_matrix/")
raw_adt <- raw_data$`Antibody Capture`

# 区分细胞和空液滴
# 简单方法:用RNA的UMI总数区分
rna_umi <- colSums(raw_data$`Gene Expression`)
cell_barcodes <- colnames(seurat_obj)  # 已过滤的细胞barcode
empty_barcodes <- setdiff(names(rna_umi[rna_umi < 100]),  # UMI<100的是空液滴
                          cell_barcodes)

# 运行DSB归一化
cell_adt <- as.matrix(data$`Antibody Capture`[, cell_barcodes])
empty_adt <- as.matrix(raw_adt[, empty_barcodes[1:min(10000, length(empty_barcodes))]])

dsb_norm <- DSBNormalizeProtein(
  cell_protein_matrix = cell_adt,  # 细胞的ADT counts
  empty_drop_matrix = empty_adt,   # 空液滴的ADT counts
  denoise.counts = TRUE,            # 去噪
  use.isotype.control = TRUE,       # 使用同型对照
  isotype.control.name.vec = c("IgG1", "IgG2a", "IgG2b")  # 同型对照抗体名
)

# 将DSB结果替换到Seurat对象
seurat_obj[["ADT"]] <- CreateAssayObject(data = dsb_norm)

2.3 WNN分析(加权最近邻)

# ===== WNN:整合RNA和蛋白信息的聚类 =====

# RNA标准流程
DefaultAssay(seurat_obj) <- "RNA"
seurat_obj <- NormalizeData(seurat_obj)
seurat_obj <- FindVariableFeatures(seurat_obj)
seurat_obj <- ScaleData(seurat_obj)
seurat_obj <- RunPCA(seurat_obj, npcs = 30)

# ADT降维
DefaultAssay(seurat_obj) <- "ADT"
VariableFeatures(seurat_obj) <- rownames(seurat_obj[["ADT"]])
seurat_obj <- ScaleData(seurat_obj)
seurat_obj <- RunPCA(seurat_obj, reduction.name = "apca",
                     reduction.key = "apca_")  # ADT的PCA

# ===== WNN核心步骤 =====
seurat_obj <- FindMultiModalNeighbors(
  seurat_obj,
  reduction.list = list("pca", "apca"),  # 两种降维结果
  dims.list = list(1:30, 1:15),          # 各自使用的维度数
  modality.weight.name = "RNA.weight"     # 权重名称
)

# WNN聚类
seurat_obj <- FindClusters(
  seurat_obj,
  graph.name = "wsnn",  # 使用WNN图
  algorithm = 3,        # SLM算法
  resolution = 0.5
)

# WNN UMAP
seurat_obj <- RunUMAP(
  seurat_obj,
  nn.name = "weighted.nn",     # 使用WNN
  reduction.name = "wnn.umap",  # 输出名称
  reduction.key = "wnnUMAP_"
)

# ===== 对比三种聚类 =====
p1 <- DimPlot(seurat_obj, reduction="wnn.umap", group.by="wsnn_res.0.5",
              label=TRUE) + ggtitle("WNN Clusters")
p2 <- DimPlot(seurat_obj, reduction="wnn.umap", group.by="wsnn_res.0.5",
              split.by=NULL) + ggtitle("RNA weight per cell")

# 查看每个细胞RNA和ADT权重
VlnPlot(seurat_obj, features="RNA.weight", group.by="wsnn_res.0.5") +
  ggtitle("RNA Weight by Cluster")
# RNA.weight接近1 → 该聚类主要由RNA信息驱动
# RNA.weight接近0 → 该聚类主要由蛋白信息驱动

# 可视化ADT蛋白表达
DefaultAssay(seurat_obj) <- "ADT"
FeaturePlot(seurat_obj, 
            features = c("CD3", "CD4", "CD8", "CD19", "CD14", "CD56"),
            reduction = "wnn.umap", ncol = 3)
ggsave("adt_markers_wnn.png", width=15, height=10, dpi=300)

三、RNA-蛋白一致性分析

# ===== 分析mRNA和蛋白表达的一致性 =====
library(ggplot2)

# 提取基因名对应关系(ADT名 vs RNA基因名)
# 通常ADT名如"CD3"对应RNA基因"CD3E"或"CD3D"
gene_protein_map <- data.frame(
  ADT = c("CD3", "CD4", "CD8a", "CD14", "CD19", "CD56"),
  Gene = c("CD3E", "CD4", "CD8A", "CD14", "CD19", "NCAM1")
)

# 提取表达值
rna_expr <- GetAssayData(seurat_obj, assay="RNA", layer="data")
adt_expr <- GetAssayData(seurat_obj, assay="ADT", layer="data")

# 计算相关性
correlations <- sapply(1:nrow(gene_protein_map), function(i) {
  gene <- gene_protein_map$Gene[i]
  adt <- gene_protein_map$ADT[i]

  if (gene %in% rownames(rna_expr) & adt %in% rownames(adt_expr)) {
    cor(rna_expr[gene, ], adt_expr[adt, ], method="spearman")
  } else {
    NA
  }
})

gene_protein_map$Correlation <- correlations
print(gene_protein_map)
# ADT  Gene   Correlation
# CD3  CD3E   0.72         ← 高相关:mRNA和蛋白一致
# CD4  CD4    0.58         ← 中等:有转录后调控
# CD14 CD14   0.81         ← 高相关

四、常见报错与解决

报错信息原因解决方案
ADT: all zerosADT数据未正确读取检查feature_ref.csv中的类型
DSB: no empty drops空液滴数据缺失使用raw_feature_bc_matrix
WNN: dimension mismatchRNA和ADT的细胞数不一致确保两个assay有相同的细胞
Negative DSB valuesDSB正常输出(可以有负值)负值=低于背景水平,正常
ADT normalization选择CLR vs DSB不确定有空液滴数据用DSB,没有用CLR

五、面试高频问题

Q1: WNN分析的优势是什么?

A: WNN为每个细胞自动学习RNA和蛋白的最优权重。有些细胞类型RNA信息更有用(如基因调控状态),有些蛋白信息更有用(如T细胞亚群的CD标记)。WNN不是简单地把两个模态合并,而是智能加权。

Q2: CLR和DSB归一化有什么区别?

A: CLR是成分数据变换,简单直接,不需要空液滴。DSB利用空液滴估计技术背景噪声并去除,同时用同型对照抗体去除非特异性结合,更准确但需要额外数据。

Q3: CITE-seq数据有什么局限性?

A: ①抗体panel有限(通常100-300个蛋白,远少于基因组);②抗体质量影响结果(非特异结合、批次差异);③成本高;④不是所有蛋白都有好的抗体。


六、速查表

# ===== CITE-seq分析速查 =====

# 创建对象
data <- Read10X("filtered_feature_bc_matrix/")
obj <- CreateSeuratObject(counts=data$`Gene Expression`)
obj[["ADT"]] <- CreateAssayObject(counts=data$`Antibody Capture`)

# ADT归一化
# CLR: NormalizeData(obj, assay="ADT", method="CLR")
# DSB: DSBNormalizeProtein(cell_adt, empty_adt)

# WNN分析
obj <- FindMultiModalNeighbors(obj,
  reduction.list=list("pca","apca"),
  dims.list=list(1:30, 1:15))
obj <- FindClusters(obj, graph.name="wsnn")
obj <- RunUMAP(obj, nn.name="weighted.nn")

# 关键蛋白标记:
# T细胞: CD3+  (CD4+ helper, CD8+ cytotoxic)
# B细胞: CD19+, CD20+
# NK: CD56+, CD16+
# 单核: CD14+
# DC: CD11c+, HLA-DR+