该推文首发于公众号:单细胞天地
在前两讲中,我们已经完整介绍了CD4+ T细胞的提取及其亚群细分的流程。本讲将聚焦于单细胞分析领域中的重要工具——inferCNV,用于判断不同细胞亚群的CNV变化。尽管本讲内容在课程的连贯性上可能略显跳跃,但考虑到该工具在肿瘤研究中的重要性和以及其技术难度相对较低,我们仍在中级篇阶段对其进行回顾和学习。
本次内容涉及到的工程文件可通过网盘获得:初级篇2 链接: https://pan.baidu.com/s/1ETVEkJNCJSe9NU7_aLEPVA 提取码: znmb 。
上一讲CD4+T细胞细分后结果:中级篇2,链接: https://pan.baidu.com/s/1y-HHLXoXsJbgWKCdz26-gQ 提取码: yx93 。
此外,可以向“生信技能树”公众号发送关键词‘单细胞’,直接获取Seurat V5版本的完整代码。
既往推文:
inferCNV分析简介
InferCNV用于分析肿瘤单细胞RNA测序数据,通过比较肿瘤细胞与参考"正常"细胞的基因表达强度,识别体细胞大规模染色体拷贝数变异的证据(如整条染色体或大片段染色体的扩增或缺失)。该方法可生成展示肿瘤基因组各染色体区域相对表达强度的热图,相较于正常细胞,肿瘤基因组中过度富集或缺失的区域通常会直观显现。
inferCNV分析的意义
对单细胞分析的时候会根据关键基因/标记进行细胞分群,基本上可以把大部分的细胞亚群给区分开来,但如果某些基因/标记广泛地存在于多种细胞亚群时,此时应进一步寻找其他的关键基因/标记进行区分,这种分析策略是“常规流程”。对于肿瘤细胞和正常细胞而言,我们常会遇到某些关键基因/标记在两者中均表达的情况(转录组水平),此时通过“常规流程”仍难以区分细胞的良恶性,因此换个角度来辅助区分良恶性细胞就显得尤为重要。
肿瘤细胞通常具有更多的CNV,而正常细胞则较为稳定,因此如果有一种工具能够可视化拷贝数变异的情况那么是不是就可以辅助鉴别良恶性细胞呢?基于这种情况inferCNV就应运而生了。
图中的红色部分是References(Cells),也就是我们自行定义的对照(正常)细胞。这些对照细胞可以是相对于肿瘤细胞的正常细胞(癌与非癌),也可选用免疫细胞进行对照。蓝色部分是Observations(Cells),也就是我们想要重点分析的细胞。灰色部分是细胞的图注,上边的色块代表了对照细胞的情况,该图研究者纳入了Microglia/Macrophage 和 Oligodendrocytes (non-malignant) 作为对照细胞,恶性细胞作为观察细胞。
红色方框部分代表的是分层聚类树,其中第一列色柱代表的是所有观察组细胞的分层聚类,第二列色柱则是与所提供输入的观察组细胞分类相对应。
按照箭头看向对照和观察组细胞,在红色箭头处代表了malignant_MGH36细胞群,这群细胞相比于观察组(蓝色箭头)在chr1, 4, 19中存在更显著的染色体缺失,在chr11, 21中存在更显著的染色体扩增。同样的我们可以看其他的三群恶性细胞,也均存在不同区域的染色体拷贝数异常。
该结果显示1个正常样本作为对照组,10个肿瘤样本作为观察组。整体情况观察下来可以发现肿瘤组样本相比于对照组来说还是存在了很明显的染色体拷贝数异常。红色方框中的第二列色柱是代表了P10肿瘤样本的信息,中间还混了一小部分的P05患者的信息,从聚类树分层后的色柱来看,P10肿瘤样本还可以进一步的细分为多群。蓝色方框中的第二列色柱中存在很多肿瘤样本的信息,但从聚类树分层后的色柱来看,这些肿瘤样本信息应当分成同一群。
同样的数据,修改了cluster_by_groups的值之后聚类树的图形出现了变化。在不按照k_obs_groups分组之后,主要根据每个样本内部的情况进行分组,可以发现不同样本内部也存在着很大的异质性(红色方框)。
该结果显示前期分析得到了17个细胞亚群,其中第15个亚群根据关键基因/标记推测认为可能是正常细胞群,因此通过inferCNV进行辅助分析判断第15个亚群是否是正常细胞群,从结果来看确实也符合正常细胞亚群的猜测。而根据聚类树结果来看,k_obs_groups分组和细胞亚群分组一致。
不按照k_obs_groups分组之后,我们可以明显发现很多细胞亚群之间没有十分明显的界限,也就是说这个结果提示我们在后续聚类的时候可以把很多细胞亚群合并成同一群。
rm(list = ls())
library(infercnv)
library(Seurat)
library(gplots)
library(ggplot2)
library(qs)
sce <- qread("./4-Corrective-data/sce.all.qs")
#检查一下自己导入进来的数据
DimPlot(sce,reduction = 'umap',
label = TRUE,pt.size = 0.5) +NoLegend()
dir.create("11-infercnv")
setwd("./11-infercnv")
创建InferCNV对象前需要准备好三个文件:conut matrix;cell type annotations;gene ordering file
官方提供了基因排序文件:https://data.broadinstitute.org/Trinity/CTAT/cnv/,当然自行制作也十分迅速。
table(Idents(sce))
table(sce@meta.data$seurat_clusters)
table(sce@meta.data$orig.ident)
# 提取部分细胞
sce@meta.data
sce <- sce[,sce$celltype %in% c("plasma","fibroblasts","epithelial/cancer cells")]
# 文件制作1:表达量矩阵
# 除了用GetAssayData函数其实也可以直接sce@assays$RNA@count即可
dat <- GetAssayData(sce,layer = 'counts',assay = 'RNA')
dat[1:4,1:4]
# 文件制作2:样本的描述
groupinfo <- data.frame(v1 = colnames(dat),v2 = sce@meta.data$celltype)
head(groupinfo)
# v1 v2
# 1 GSM5688706_WGC_AACACACGTGCTTCAA-1 epithelial/cancer cells
# 2 GSM5688706_WGC_AACACACTCCCGTTCA-1 epithelial/cancer cells
# 3 GSM5688706_WGC_AACACACTCTGCTAGA-1 plasma
# 4 GSM5688706_WGC_AACCATGAGGCACAAC-1 plasma
# 5 GSM5688706_WGC_AACCATGCAAAGCTCT-1 epithelial/cancer cells
# 6 GSM5688706_WGC_AACCCAAGTGCCGTAC-1 plasma
# 文件制作3:基因在染色体中的坐标
library(AnnoProbe)
#annoGene 函数返回一个数据框,包含输入基因的详细注释信息。
#注释信息可能包括基因名称、染色体位置、基因描述等。
geneInfor <- annoGene(rownames(dat),"SYMBOL","human") #物种需要小心哦
# 使用逻辑条件来移除包含 chrM, chrX, 和 chrY 的行
geneInfor <- geneInfor[!geneInfor$chr %in% c("chrM", "chrX", "chrY"), ]
#提取chr后后面的数字并转化为num,从而按这个num排序
#sub函数用于把chr替换为空
geneInfor$chr_num <- as.numeric(sub("chr", "", geneInfor$chr))
colnames(geneInfor)
#with函数的作用是简化写法,可问gpt
geneInfor <- geneInfor[with(geneInfor,order(chr_num,start)),c(1,4:6)]
geneInfor <- geneInfor[!duplicated(geneInfor[,1]),]
length(unique(geneInfor[,1]))
head(geneInfor)
# SYMBOL chr start end
# 23 AP006222.2 chr1 266855 268655
# 51 FAM87B chr1 817371 819837
# 53 LINC00115 chr1 826206 827522
# 55 FAM41C chr1 868071 876903
# 62 SAMD11 chr1 923928 944581
# 63 NOC2L chr1 944203 959309
#保留行名在geneInfor第一列中存在的行。
dat <- dat[rownames(dat) %in% geneInfor[,1],]
#match(x, table):match函数返回x中每个元素在table中的位置索引。
#获得位置后对dat进行重新排序使其跟geneInfor中的顺序一致
dat <- dat[match(geneInfor[,1],rownames(dat)),]
dim(dat)
head(groupinfo)
dat[1:4,1:4]
table(groupinfo$v2)
dim(groupinfo)
#为了节约计算机资源,直接抽样
#如果真实项目请不要用抽样
#kp <- sample(1:nrow(groupinfo),500)
#groupinfo <- groupinfo[kp,]
#dat <- dat[,kp]
# 保存矩阵文件
#expFile:是一个变量,存储写入的文件的文件名或路径。在这里文件名是expFile.txt。
expFile <- 'expFile.txt' #定义输出文件名
colnames(dat) <- gsub("-", "_", colnames(dat))
write.table(dat, file = expFile, sep = '\t', quote = F)
# 保存细胞注释文件
groupFiles <- 'groupFiles.txt'
groupinfo$v1 <- gsub("-", "_", groupinfo$v1)
write.table(groupinfo,file = groupFiles, sep = '\t',
quote = F, col.names = F, row.names = F)
# 保存基因排序文件
head(geneInfor)
geneFile <- 'geneFile.txt'
write.table(geneInfor, file = geneFile, sep = '\t',
quote = F, col.names = F, row.names = F)
创建infercnv_obj对象:
正式运行infercnv::run:
#创建对象,请注意文件需要一一对应哦!
#ref_group_names 这里的细胞是正常对照,然后跟其他的细胞比较
infercnv_obj <- CreateInfercnvObject(raw_counts_matrix = expFile,
annotations_file = groupFiles,
delim = "\t",
gene_order_file = geneFile,
ref_group_names = c("plasma","fibroblasts") #这里用plasma和fibroblasts做参照
)
infercnv_obj <- infercnv::run(infercnv_obj,
cutoff = 0.1, #smart-seq选择1,10X选择0.1
out_dir = "infercnv_output", # dir is auto
# 是否根据细胞注释文件的分组
# 对肿瘤细胞进行分组
# 影响read.dendrogram, 如果有多个细胞类型,且设置为TRUE,
# 后续的read.dendrogram无法执行
cluster_by_groups = TRUE, #是否根据细胞类型(由细胞注释文件中定义)
hclust_method = "ward.D2",# ward.D2 方法进行层次聚类
analysis_mode = "subclusters", # 默认是samples,推荐是subclusters
denoise = TRUE, # 去噪音
HMM = F, ##特别耗时间,是否要去背景噪音
plot_steps = F, #不在每个步骤后生成图形。
leiden_resolution = "auto", #可以手动调参数
num_threads = 16 # 16线程工作,加快速度,一般电脑不建议哈
)
去噪音前后图。去之前也看得出肿瘤细胞相比于其他两种细胞来说有更多CNV改变
增加中值滤波,让视觉效果更明显
infercnv_obj_medianfiltered = infercnv::apply_median_filtering(infercnv_obj)
infercnv::plot_cnv(infercnv_obj_medianfiltered,
out_dir='./example_output/',
output_filename='infercnv.median_filtered',
x.range="auto",
x.center=1,
title = "infercnv",
color_safe_pal = FALSE)
setwd("..")
接下来使用曾老师的方法去检查拷贝数变异的情况
rm(list = ls())
options(stringsAsFactiors = F)
library(phylogram)
library(gridExtra)
library(grid)
require(dendextend)
require(ggthemes)
library(tidyverse)
library(Seurat)
library(infercnv)
library(miscTools)
sce <- qread("./4-Corrective-data/sce.all.qs")
dir.create("11-infercnv")
setwd("./11-infercnv")
# 提取想要的细胞
sce <- sce[,sce$celltype %in% c("plasma","fibroblasts","epithelial/cancer cells")]
# 提取infercnv_obj
infer_CNV_obj<-readRDS('./infercnv_output/run.final.infercnv_obj')
expr <- infer_CNV_obj@expr.data
expr[1:4,1:4]
data_cnv <- as.data.frame(expr)
dim(expr)
colnames(data_cnv)
rownames(data_cnv)
table(sce$orig.ident)
table(sce$seurat_clusters)
#记得要改一下sce中的列名
colnames(sce) <- gsub("-","_",colnames(sce))
meta <- sce@meta.data
#要根据参数修改哦,这里的对照组有plasma和fibroblast
if(T){
tmp1 = expr[,infer_CNV_obj@reference_grouped_cell_indices$plasma]
tmp = tmp1
tmp2 = expr[,infer_CNV_obj@reference_grouped_cell_indices$fibroblast]
tmp= cbind(tmp1,tmp2)
down=mean(rowMeans(tmp)) - 2 * mean( apply(tmp, 1, sd))
up=mean(rowMeans(tmp)) + 2 * mean( apply(tmp, 1, sd))
oneCopy=up-down
oneCopy
a1= down- 2*oneCopy
a2= down- 1*oneCopy
down;up
a3= up + 1*oneCopy
a4= up + 2*oneCopy
cnv_score_table<-infer_CNV_obj@expr.data
cnv_score_table[1:4,1:4]
cnv_score_mat <- as.matrix(cnv_score_table)
# Scoring
cnv_score_table[cnv_score_mat > 0 & cnv_score_mat < a2] <- "A" #complete loss. 2pts
cnv_score_table[cnv_score_mat >= a2 & cnv_score_mat < down] <- "B" #loss of one copy. 1pts
cnv_score_table[cnv_score_mat >= down & cnv_score_mat < up ] <- "C" #Neutral. 0pts
cnv_score_table[cnv_score_mat >= up & cnv_score_mat <= a3] <- "D" #addition of one copy. 1pts
cnv_score_table[cnv_score_mat > a3 & cnv_score_mat <= a4 ] <- "E" #addition of two copies. 2pts
cnv_score_table[cnv_score_mat > a4] <- "F" #addition of more than two copies. 2pts
# Check
table(cnv_score_table[,1])
# Replace with score
cnv_score_table_pts <- cnv_score_mat
rm(cnv_score_mat)
#
cnv_score_table_pts[cnv_score_table == "A"] <- 2
cnv_score_table_pts[cnv_score_table == "B"] <- 1
cnv_score_table_pts[cnv_score_table == "C"] <- 0
cnv_score_table_pts[cnv_score_table == "D"] <- 1
cnv_score_table_pts[cnv_score_table == "E"] <- 2
cnv_score_table_pts[cnv_score_table == "F"] <- 2
cnv_score_table_pts[1:4,1:4]
str(as.data.frame(cnv_score_table_pts[1:4,1:4]))
cell_scores_CNV <- as.data.frame(colSums(cnv_score_table_pts))
colnames(cell_scores_CNV) <- "cnv_score"
}
#可视化
head(cell_scores_CNV)
score=cell_scores_CNV
head(score)
meta$totalCNV = score[match(colnames(sce),
rownames(score)),1]
p <- ggplot(meta, aes(x= celltype,
y=totalCNV,
fill=celltype)) +
geom_boxplot();print(p)
ggsave("totalCNV.pdf",plot = p, width = 9,height = 7,dpi = 300)
从CNV的结果确实能够看到epithelial/cancer cells与fibroblast和plasma细胞的差异。
本次分析完成了inferCNV工具的实践流程。inferCNV可以帮助我们从RNA水平推测细胞的CNV变化,并辅助开展多种分析工作。例如,它可以用于区分肿瘤细胞和正常细胞,识别基因组CNV,以及探索进化关系和克隆异质性。因此,inferCNV是单细胞分析中必须掌握的重要工具。
致谢:感谢曾老师以及生信技能树团队全体成员。更多精彩内容可关注公众号:生信技能树,单细胞天地,生信菜鸟团等公众号。
注:若对内容有疑惑或者有发现明确错误的朋友,请联系后台(欢迎交流)。更多相关内容可关注公众号:生信方舟
- END -
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有