寫在前面:今天突然想寫這個教程,花了一下午看資料,其實我前面是有一些基礎的,但是看的還是會很亂,所以想把這個包的脈絡寫一下,希望能夠可以跟大家討論一下并且自己以后使用這個包的時候也相當于翻閱說明書吧!!!
首先講一段話:
我的一個使用情景是,當我跑完seruat的標準流程后,不可能只看細胞數量之間的差異吧,所以想看細胞之間的發育軌跡,就想到了monocle,Attention:我是已經完成了seurat分析!!
所以大家能從上面這段話得到什么信息呢?信息:就是我只想用monocle對我的細胞進行軌跡分析,然而monocle這個包功能其實不單單是進行軌跡分析,它其實一直想要代替seruat這個包,所以它幾乎包括seurat所有的分析流程
假如你是沒有進行seurat分析的話,你可以嘗試一下用monocle進行分析
#加載包
library(Seurat)
library(monocle3)
library(tidyverse)
library(patchwork)
#導入數據
#在這里你需要導入三個數據:細胞的表達矩陣,meta信息,gene_annotation
data <- 細胞的表達矩陣
cell_metadata <- meta信息
gene_annotation <- data.frame(gene_short_name = rownames(data))
rownames(gene_annotation) <- rownames(data)
#創建CDS對象
cds <- new_cell_data_set(data,
cell_metadata = cell_metadata,
gene_metadata = gene_annotation) #這樣就獲得了monocle的對象了,可類比于創建seurat對象
#思考一下我們在創建了seurat對象后要干嘛呢?降維聚類分群,那么monocle也不例外
#NormalizeData+ScaleData+RunPCA
cds <- preprocess_cds(cds, num_dim = 50) #preprocess_cds函數相當于seurat中NormalizeData+ScaleData+RunPCA
plot_pc_variance_explained(cds) #像seurat一樣展示pc數
#umap降維
cds <- reduce_dimension(cds,preprocess_method = "PCA") #preprocess_method默認是PCA
#tSNE降維
cds <- reduce_dimension(cds, reduction_method="tSNE")
#聚類
cds <- cluster_cells(cds)
#那么我們到這里就完成了分群了,后面就是對于每一個群的細胞注釋和細胞類型的結果展示了,這個大家可以去看周運來老師的簡書,而我的目的不是這個
還記得我提出來的background嗎,我已經用seurat進行降維聚類分群和細胞注釋,所以我沒有必要monocle包給我做這些,對于使用了seurat分析流程的我們只想用monocle來做一個擬時序分析該怎么做呢?
#加載包
library(Seurat)
library(monocle3)
library(tidyverse)
library(patchwork)
rm(list=ls())
#導入我們的用seurat包分析得到的S4對象
pbmc <- readRDS("scRNAsub.rds")
#容易弄混的地方來了
#首先我們要得到seurat對象的表達矩陣
data <- GetAssayData(pbmc, assay = 'RNA', slot = 'counts')
#其次獲得meta信息
cell_metadata <- pbmc@meta.data
#然后要獲得gene_annotation
gene_annotation <- data.frame(gene_short_name = rownames(data))
rownames(gene_annotation) <- rownames(data)
#創建CDS對象
cds <- new_cell_data_set(data,
cell_metadata = cell_metadata,
gene_metadata = gene_annotation)
#為啥要這樣呢,這怎么解釋呢,你用monocle的包,所以要聽它的,還是要走一遍某些流程
#然后就是降維聚類分群
#NormalizeData+ScaleData+RunPCA
cds <- preprocess_cds(cds, num_dim = 50) #preprocess_cds函數相當于seurat中NormalizeData+ScaleData+RunPCA
plot_pc_variance_explained(cds) #像seurat一樣展示pc數
#umap降維
cds <- reduce_dimension(cds,preprocess_method = "PCA") #preprocess_method默認是PCA
#tSNE降維
cds <- reduce_dimension(cds, reduction_method="tSNE")
#聚類
cds <- cluster_cells(cds)
這里必須強調一下:剛開始我會糾結,monocle的降維聚類分群的結果會不會跟seurat不一樣呢,答案是肯定的,算法都不同,能一樣嗎,那豈不是改變了我們的初衷,只想做擬時序分析
那么解決辦法來了,我們可以用seurat分析得到umap結果覆蓋掉monocle分析得到的umap結果
cds.embed <- cds@int_colData$reducedDims$UMAP
int.embed <- Embeddings(pbmc, reduction = "umap")
int.embed <- int.embed[rownames(cds.embed),]
cds@int_colData$reducedDims$UMAP <- int.embed #因此我們以后只要是畫umap的點圖就跟seurat的圖片形狀是一樣的
#畫圖看一下
plot_cells(cds, reduction_method="UMAP", color_cells_by="seurat_clusters")
在這里我要講兩點:
第一:為什么一定要做降維聚類分群,因為我們是用monocle創建了一個全新的對象,我們只是導入了seurat對象里的表達矩陣,meta信息和genelist,所以這個cds是沒有進行降維聚類等操作,導致后面的擬時序分析是做不了的,假如你看了monocle的官網的話啊,你會知道的,官網上說-擬時序分析是基于低維度,所以必須對cds進行降維聚類分群。
第二:已經用seurat分析過的我們,可以在monocle流程里省去哪一些步驟呢,1.我們省去了找
marker基因,2.我們省去了細胞注釋,但是我們加進去的meta信息里有細胞類型和其他的一些信息,所以其實這一步可以因為我們用了seurat分析并輸入了它的meta信息而代替,所以我們還是相當于做了完整的monocle流程,只是有一些是用seurat做的結果罷了(歡迎一起討論這一點)
下面開始才是我們想要的:
擬時序分析
第一步:軌跡推斷
cds <- learn_graph(cds) #是的,就這么簡單,用 learn_graph即可
#畫圖 我們可以根據meta信息來畫出相關的圖片
head(colData(cds))
plot_cells(cds,
color_cells_by = "celltype",
label_groups_by_cluster=FALSE,
label_leaves=FALSE,
label_branch_points=TRUE,
group_label_size=4,
cell_size=1.5) #這個圖就可以看出細胞直接的分化軌跡了
#黑色的線顯示的是graph的結構。
#數字帶白色圓圈表示不同的結局,也就是葉子。
#數字帶黑色圓圈代表分叉點,從這個點開始,細胞可以有多個結局。
#這些數字可以通過label_leaves和label_branch_points參數設置。
第二步:選擇根 就是選擇細胞的起源 這也是monocle3與monocle2最大的區別,手動選擇(自定義)根 ,使用其中一種就可以!!!
#第一種:
cds = order_cells(cds) #在前陣子有bug 無法展示,現在好像又可以了
plot_cells(cds,
color_cells_by = "pseudotime",
label_cell_groups=FALSE,
label_leaves=TRUE,
label_branch_points=TRUE,
graph_label_size=1.5,
group_label_size=4,cell_size=1.5)
#第二種:用輔助線
p + geom_vline(xintercept = seq(-7,-6,0.25)) + geom_hline(yintercept = seq(0,1,0.25))
embed <- data.frame(Embeddings(pbmc, reduction = "umap"))
embed <- subset(embed, UMAP_1 > -6.75 & UMAP_1 < -6.5 & UMAP_2 > 0.24 & UMAP_2 < 0.25)
root.cell <- rownames(embed)
cds <- order_cells(cds, root_cells = root.cell) #這里就選擇了根
plot_cells(cds, color_cells_by = "pseudotime", label_cell_groups = FALSE,
label_leaves = FALSE, label_branch_points = FALSE)
#第三種:定義一個函數
# a helper function to identify the root principal points:
get_earliest_principal_node <- function(cds, time_bin="epithelial cells"){
cell_ids <- which(colData(cds)[, "celltype"] == time_bin)
closest_vertex <-cds@principal_graph_aux[["UMAP"]]$pr_graph_cell_proj_closest_vertex
closest_vertex <- as.matrix(closest_vertex[colnames(cds), ])
root_pr_nodes <-
igraph::V(principal_graph(cds)[["UMAP"]])$name[as.numeric(names(which.max(table(closest_vertex[cell_ids,]))))]
root_pr_nodes
}
cds = order_cells(cds, root_pr_nodes=get_earliest_principal_node(cds)) #很多人這里一直在哭訴error,那是都沒有理解這一步在干嘛,很多無腦運行別人的代碼,別人代碼選擇XX細胞作為根,你的數據集里又沒有,所以報錯說沒有node啦
第一種方法:
可以看出我選擇紅點的地方為發育起始點,我用的是第一種方法
第二種方法:
上面的發育軌跡是在一個二維的坐標上看的,monocle3搞了一個三維的發育軌跡,所以我們可以在三維空間內看發育軌跡(其實我覺得也那樣,無非是加多一個維度罷了) 但是假如你想畫三維的圖,你要定義一個function,就像第三種找root一樣,定義一個能找root的函數,因為就算是三維,你也要給別人一個根呀,否則怎么給你畫順序呢?
#第一步:定義一個function
get_earliest_principal_node <- function(cds, time_bin="epithelial cells"){
cell_ids <- which(colData(cds)[, "celltype"] == time_bin)
closest_vertex <-cds@principal_graph_aux[["UMAP"]]$pr_graph_cell_proj_closest_vertex
closest_vertex <- as.matrix(closest_vertex[colnames(cds), ])
root_pr_nodes <-
igraph::V(principal_graph(cds)[["UMAP"]])$name[as.numeric(names(which.max(table(closest_vertex[cell_ids,]))))]
root_pr_nodes
}
#第二步:降維到三維,并plot
cds_3d = reduce_dimension(cds, max_components = 3) #這里就降到三維嘛
cds_3d = cluster_cells(cds_3d)
cds_3d = learn_graph(cds_3d) #為啥這慢呢,因為他是在三維的基礎上去進行learn
cds_3d = order_cells(cds_3d, root_pr_nodes=get_earliest_principal_node(cds))
cds_3d_plot_obj = plot_cells_3d(cds_3d, color_cells_by="celltype")
cds_3d_plot_obj #這個會由于網絡的原因畫不出來
到這里大家應該能體會到了為什么前面不管你是不是seurat處理過的,都要對cds這個對象進行降維了吧,不然法畫圖呀
接下來是差異分析,就是找出哪一些基因在這個軌跡中變化最大
#計算基因按照軌跡的變化
Track_genes <- graph_test(cds, neighbor_graph="principal_graph", cores=6)
Track_genes <- Track_genes[,c(5,2,3,4,1,6)] %>% filter(q_value < 1e-3)
#挑選top10畫圖展示
Track_genes_sig <- Track_genes %>% top_n(n=10, morans_I) %>%
pull(gene_short_name) %>% as.character()
#基因表達趨勢圖
plot_genes_in_pseudotime(cds[Track_genes_sig,], color_cells_by="celltype",
min_expr=0.5, ncol = 2)
#FeaturePlot圖
plot_cells(cds, genes=Track_genes_sig, show_trajectory_graph=FALSE,
label_cell_groups=FALSE, label_leaves=FALSE)
#在這里運用到文章的話,應該可以這樣用,你可以用這些變化top基因來講一些東西,或者你可以show你自己fouce on的gene
然后就是還可以做一個尋找共表達模塊,怎么應用呢,就可以說是這個模塊導致他們狀態發生變化,然后查看一個模塊里的基因,再講一些東西
##尋找共表達模塊
genelist <- pull(Track_genes, gene_short_name) %>% as.character()
gene_module <- find_gene_modules(cds[genelist,], resolution=1e-2, cores = 10)
cell_group <- tibble::tibble(cell=row.names(colData(cds)),
cell_group=colData(cds)$celltype)
agg_mat <- aggregate_gene_expression(cds, gene_module, cell_group)
row.names(agg_mat) <- stringr::str_c("Module ", row.names(agg_mat))
pheatmap::pheatmap(agg_mat, scale="column", clustering_method="ward.D2")
最后,我們可以把monocle的擬時序結果導入seurat對象里了
#提取擬時分析結果返回seurat對象
pseudotime <- pseudotime(cds, reduction_method = 'UMAP')
pseudotime <- pseudotime[rownames(pbmc@meta.data)]
pbmc$pseudotime <- pseudotime
p = FeaturePlot(pbmc, reduction = "umap", features = "pseudotime")
# pseudotime中有無限值,無法繪圖。
ggsave("Pseudotime_Seurat.pdf", plot = p, width = 8, height = 6)
saveRDS(pbmc, file = "sco_pseudotime.rds")
References:
單細胞分析十八般武藝5:monocle3 - 云+社區 - 騰訊云 (tencent.com)
scRNA-seq數據分析 || Monocle3 - 簡書 (jianshu.com)
單細胞之軌跡分析-3:monocle3 - 簡書 (jianshu.com)
假如有講錯或理解不到位的地方歡迎大家指出哈!!!