scRNA-seq擬時分析 || Monocle2 踩坑教程

擬時(pseudotime)分析,又稱細胞軌跡(cell trajectory)分析,通過擬時分析可以推斷出發育過程細胞的分化軌跡或細胞亞型的演化過程,在發育相關研究中使用頻率較高。主要基于關鍵基因的表達模式,在擬時間中對單個細胞進行排序,模擬出時間發育過程的動態變化。

既然講到所謂的擬時分析不過是一種排序而已,那么我們就要知道排序的基本要素:

  • 對什么排序
  • 如何判斷先后順序
  • 如何尋找分支點(如果分支的話)

早在20世紀30年代,數量生態學領域前蘇聯學者Ranensky就提出了排序的概念,并發展了一個簡單的排序方法(見Sobolev和Utekhin 1973),但只限于在前蘇聯傳播(Greig-Smith 1980),Ramensky當時應用一個或兩個環境因子梯度去排列植物群落,他用的名詞是德文“ordnung”。經過多年的發展,排序技術依然是一種在低維空間排布高維數據的降維技術。當我們講到排序的時候,離不開降維;講到降維的時候,離不開特征提取(或者選擇)。

那么對應到擬時分析的描述中:1)關鍵基因就是特征選擇的結果,2)擬時間就是排序空間,3)排序就是細胞的演化軌跡。所有的擬時分析都離不開這三點。具體地:

Monocle引入了在偽時間(擬時間)內對單個細胞排序的策略,利用單個細胞的非同步進程,將它們置于與細胞分化等生物學過程相對應的軌跡上。Monocle利用先進的機器學習技術(反向圖嵌入)從單細胞數據中學習顯式的主圖來對細胞進行排序,該方法能夠可靠、準確地解決復雜的生物學過程。

Monocle2 可以做什么?

  • Clustering, classifying, and counting cells
  • Constructing single-cell trajectories.
  • Differential expression analysis

當然我們關心的是第二個功能了,但是不防也看一下它的其他功能。算法原理可以參看文章Reversed graph embedding resolves complex single-cell developmental trajectories

Monocle 2通過反向圖嵌入學習單細胞軌跡的方法。每個細胞都可以表示為高維空間中的一個點,其中每個維對應于有序基因的表達水平。高維數據首先通過PCA(默認方法)、擴散圖(diffusion maps)等幾種降維方法中的任何一種投影到較低的維空間。然后Monocle 2在自動選擇的數據中心集上構造一個生成樹。然后,該算法細胞移動到樹中最近的頂點,不斷更新頂點的位置以“適合”細胞,學習新的生成樹,并迭代地繼續這個過程,直到樹和細胞的位置收斂為止。在整個過程中,Monocle 2保持了高維空間和低維空間之間的可逆映射,從而既學習了軌跡,又降低了數據的維數。一旦Monocle 2習得這棵樹,并選擇一個tip作為“根”。每個細胞的偽時間計算為其沿樹到根的測地距離(Geodesic Distance,在圖論中,Geodesic Distance 就是圖中兩節點的最短路徑的距離),并根據主圖自動分配其分支。

主要過程如下,最難理解的應該是反轉圖嵌入,對算法感興趣的同學可以研究一下流行學習的知識。

  • dpFeature selection, identifying genes that define biological process 確定和生物過程有關的基因
    selecting the genes differentially expressed between clusters of cells identified with tSNE dimension reduction followed by density peak clustering選擇差異表達基因;
  • 反向圖嵌入(GRE):默認DDRTree。它是一種流形學習算法,旨在將主要圖形嵌入高維單細胞RNA-seq數據中,找到高維基因表達空間與低維空間映射,同時在這個縮小的空間中學習圖的結構(K個質心)來解決這個問題;
  • 偽時間分配和分支計算:利用DDRTree構建MST,將細胞投影到MST上,MST遞歸計算偽時間;

算法層面適可而止。

seurat2monocle
library(monocle)
#<-importCDS(pbmc,import_all = TRUE)
#Load Seurat object
pbmc <- readRDS('D:\\Users\\Administrator\\Desktop\\RStudio\\single_cell\\filtered_gene_bc_matrices\\hg19pbmc_tutorial.rds')

#Extract data, phenotype data, and feature data from the SeuratObject
data <- as(as.matrix(pbmc@assays$RNA@counts), 'sparseMatrix')
pd <- new('AnnotatedDataFrame', data = pbmc@meta.data)
fData <- data.frame(gene_short_name = row.names(data), row.names = row.names(data))
fd <- new('AnnotatedDataFrame', data = fData)

#Construct monocle cds
monocle_cds <- newCellDataSet(data,
                              phenoData = pd,
                              featureData = fd,
                              lowerDetectionLimit = 0.5,
                              expressionFamily = negbinomial.size())

如果你只有count矩陣可以這么讀入:

#do not run
HSMM_expr_matrix <- read.table("fpkm_matrix.txt")
HSMM_sample_sheet <- read.delim("cell_sample_sheet.txt")
HSMM_gene_annotation <- read.delim("gene_annotations.txt")

pd <- new("AnnotatedDataFrame", data = HSMM_sample_sheet)
fd <- new("AnnotatedDataFrame", data = HSMM_gene_annotation)
HSMM <- newCellDataSet(as.matrix(HSMM_expr_matrix),
    phenoData = pd, featureData = fd)

這里重點是理解CellDataSet 的數據結構。

  • exprs, a numeric matrix of expression values, where rows are genes, and columns are cells
  • phenoData, an AnnotatedDataFrame object, where rows are cells, and columns are cell attributes** (such as cell type, culture condition, day captured, etc.)
  • featureData, an AnnotatedDataFrame object, where rows are features (e.g. genes), and columns are gene attributes, such as biotype, gc content, etc.

官網給出許多其他建議以及讀入數據的注意事項,需要注意的是,如果是UMI數據,不應該在創建CellDataSet之前自己對其進行標準化。也不應該試圖將UMI計數轉換為相對豐度(通過將其轉換為FPKM/TPM數據)。Monocle將在內部執行所有需要的標準化步驟。自己將其正常化可能會破壞Monocle的一些關鍵步驟。

數據過濾(QC)
> HSMM<-monocle_cds
## 歸一化 
> HSMM <- estimateSizeFactors(HSMM)
> HSMM <- estimateDispersions(HSMM)
#Filtering low-quality cells
> HSMM <- detectGenes(HSMM, min_expr = 3 )
> print(head(fData(HSMM)))
              gene_short_name num_cells_expressed
AL627309.1         AL627309.1                   9
AP006222.2         AP006222.2                   3
RP11-206L10.2   RP11-206L10.2                   5
RP11-206L10.9   RP11-206L10.9                   3
LINC00115           LINC00115                  18
NOC2L                   NOC2L                 254
> expressed_genes <- row.names(subset(fData(HSMM),
+                                     num_cells_expressed >= 10))
> print(head(pData(HSMM)))
               orig.ident nCount_RNA nFeature_RNA percent.mt RNA_snn_res.0.5 seurat_clusters Size_Factor num_genes_expressed
AAACATACAACCAC     pbmc3k       2419          779  3.0177759               1               1          NA                 779
AAACATTGAGCTAC     pbmc3k       4903         1352  3.7935958               3               3          NA                1352
AAACATTGATCAGC     pbmc3k       3147         1129  0.8897363               1               1          NA                1129
AAACCGTGCTTCCG     pbmc3k       2639          960  1.7430845               2               2          NA                 960
AAACCGTGTATGCG     pbmc3k        980          521  1.2244898               6               6          NA                 521
AAACGCACTGGTAC     pbmc3k       2163          781  1.6643551               1               1          NA                 781
細胞分類(Classifying)

Monocle提供了一個簡單的系統,可以根據您選擇的marker基因的表達來標記細胞。您只需提供Monocle可以用來注釋每個單元格的一組函數。

CDC20 <- row.names(subset(fData(HSMM), gene_short_name == "CDC20"))
GABPB2 <- row.names(subset(fData(HSMM),
                             gene_short_name == "GABPB2"))

cth <- newCellTypeHierarchy()
cth <- addCellType(cth, "CDC20", classify_func =
                     function(x) { x[CDC20,] >= 1 })
cth <- addCellType(cth, "GABPB2", classify_func = function(x){ x[GABPB2,] >= 1 })

HSMM <- classifyCells(HSMM, cth, 0.1)
table(pData(HSMM)$CellType)

 CDC20  GABPB2 Unknown 
      4      69    2565 

我只是隨意拿幾個基因來試一下

pie <- ggplot(pData(HSMM),
              aes(x = factor(1), fill = factor(CellType))) + geom_bar(width = 1)
pie + coord_polar(theta = "y") +
  theme(axis.title.x = element_blank(), axis.title.y = element_blank())
聚類

第一步是決定用哪些基因來進行聚類(特征選擇)。我們可以使用所有的基因,但是我們將包括很多沒有表達到足夠高水平來提供有意義的信號的基因,它們只會給系統增加噪音。我們可以根據平均表達水平篩選基因,我們還可以選擇細胞間異常變異的基因。這些基因往往對細胞狀態有很高的信息含量。

#Clustering cells without marker genes 

disp_table <- dispersionTable(HSMM)
unsup_clustering_genes <- subset(disp_table, mean_expression >= 0.1)
HSMM <- setOrderingFilter(HSMM, unsup_clustering_genes$gene_id)
plot_ordering_genes(HSMM)

紅線表示單片基于這種關系對色散的期望。我們標記用于聚類的基因用黑點表示,其他的用灰點表示。

# Plots the percentage of variance explained by the each component based on PCA from the normalized expression data using the same procedure used in reduceDimension function.
# HSMM@auxClusteringData[["tSNE"]]$variance_explained <- NULL
plot_pc_variance_explained(HSMM, return_all = F) # norm_method='log'

> HSMM <- reduceDimension(HSMM, max_components = 2, num_dim = 10,
+                         reduction_method = 'tSNE', verbose = T)
Remove noise by PCA ...
Reduce dimension by tSNE ...
> HSMM <- clusterCells(HSMM, num_clusters = 2)
Distance cutoff calculated to 2.589424 
> plot_cell_clusters(HSMM, 1, 2, color = "CellType",
+                    markers = c("CDC20", "GABPB2"))

我發現指定cluster為5的時候,只能畫出來4個,為什么?

HSMM <- clusterCells(HSMM, num_clusters = 5)
plot_cell_clusters(HSMM, 1, 2)

Monocle允許我們減去“無趣的”變異源的影響,以減少它們對集群的影響。您可以使用到clusterCells和其他幾個Monocle函數的residualmodelformula astr參數來實現這一點。此參數接受一個R模型公式字符串,該字符串指定要在cluster之前減去。

HSMM <- reduceDimension(HSMM, max_components = 2, num_dim = 2,
                        reduction_method = 'tSNE',
                        residualModelFormulaStr = "~Size_Factor + num_genes_expressed",
                        verbose = T)
HSMM <- clusterCells(HSMM, num_clusters = 5)
plot_cell_clusters(HSMM, 1, 2, color = "Cluster")  # 圖不放了

plot_cell_clusters(HSMM, 1, 2, color = "Cluster") +
  facet_wrap(~CellType)

monocle 支持半監督聚類Clustering cells using marker genes來定義細胞以及外部導入細胞類型(Imputing cell type)(cell與type對應文件),這里均不再展示。

構建軌跡

在發育過程中,細胞會對刺激做出反應,并在整個生命過程中,從一種功能“狀態”轉變為另一種功能“狀態”。不同狀態的細胞表達不同的基因,產生蛋白質和代謝物的動態重復序列,從而完成它們的工作。當細胞在不同狀態間移動時,會經歷一個轉錄重組的過程,其中一些基因被沉默,另一些基因被激活。這些瞬時狀態通常很難描述,因為在更穩定的端點狀態之間純化細胞可能是困難的或不可能的。

單細胞RNA-Seq可以使您在不需要純化的情況下看到這些狀態。然而,要做到這一點,我們必須確定每個細胞的可能狀態區間。

Monocle介紹了利用RNA-Seq進行單細胞軌跡分析的策略。Monocle不是通過實驗將細胞純化成離散狀態,而是使用一種算法來學習每個細胞必須經歷的基因表達變化序列,作為動態生物學過程的一部分。一旦它了解了基因表達變化的整體“軌跡”,Monocle就可以將每個細胞置于軌跡中的適當位置。

然后,您可以使用Monocle的微分分析工具包來查找在軌跡過程中受到調控的基因,如查找作為偽時間函數變化的基因。如果這個過程有多個結果,Monocle將重建一個“分支”軌跡。這些分支與細胞的“決策”相對應,Monocle提供了強大的工具來識別受它們影響的基因,并參與這些基因的形成以及如何進行分析分支。Monocle依靠一種叫做反向圖嵌入的機器學習技術來構建單細胞軌跡。

在開始之前您也需要問,什么是擬時(偽時間)分析。

偽時間是衡量單個細胞在細胞分化等過程中取得了多大進展的指標。在許多生物學過程中,細胞并不是完全同步的。在細胞分化等過程的單細胞表達研究中,捕獲的細胞在分化方面可能分布廣泛。也就是說,在同一時間捕獲的細胞群中,有些細胞可能已經很長時間了,而有些細胞甚至還沒有開始這個過程。

當您想要了解在細胞從一種狀態轉換到另一種狀態時所發生的調節更改的順序時,這種異步性會產生主要問題。跟蹤同時捕獲的細胞間的表達可以產生對基因動力學一個大致的認識,該基因表達的明顯變異性將非常高。Monocle根據每個cell在學習軌跡上的進展對其進行排序,從而緩解了由于異步而產生的問題。

Monocle不是跟蹤表達式隨時間變化的函數,而是跟蹤沿軌跡變化的函數,我們稱之為偽時間。偽時間是一個抽象的分化單位:它只是一個cell到軌跡起點的距離,沿著最短路徑測量。軌跡的總長度是由細胞從起始狀態移動到結束狀態所經歷的總轉錄變化量來定義的。

The ordering workflow
  • Step 1: choosing genes that define progress
  • Step 2: reducing the dimensionality of the data
  • Step 3: ordering the cells in pseudotime
基因的選擇

首先,我們必須決定我們將使用哪些基因來定義細胞在肌生成過程中的進展。我們最終想要的是一組基因,能夠隨著我們研究過程的進展而增加(或減少)表達。

理想情況下,我們希望盡可能少地使用正在研究的系統生物學的先驗知識。我們希望從數據中發現重要的排序基因,而不是依賴于文獻和教科書,因為這可能會在排序中引入偏見。我們將從一種更簡單的方法開始,但是我們通常推薦一種更復雜的方法,稱為“dpFeature”。

diff_test_res <- differentialGeneTest(HSMM[expressed_genes,],
                                      fullModelFormulaStr = "~percent.mt")
ordering_genes <- row.names (subset(diff_test_res, qval < 0.1)) ## 不要也寫0.1 ,而是要寫0.01。

HSMM <- setOrderingFilter(HSMM, ordering_genes)
plot_ordering_genes(HSMM)

根據時間點的差異分析來選擇基因通常是非常有效的,但是如果我們沒有時間序列數據呢?如果細胞在我們的生物過程中是異步分化的(通常是這樣),Monocle通常可以從同時捕獲的單個種群重建它們的軌跡。下面是兩種選擇基因的方法,它們完全不需要知道實驗的設計。

一旦我們有了一個用于排序的基因id列表,我們就需要在HSMM對象中設置它們,因為接下來的幾個函數將依賴于它們。

降維
#Trajectory step 2: reduce data dimensionality  
HSMM <- reduceDimension(HSMM, max_components = 2,
                            method = 'DDRTree')
排序
#Trajectory step 3: order cells along the trajectory  
HSMM <- orderCells(HSMM)
plot_cell_trajectory(HSMM, color_by = "seurat_clusters")

有了樹結構分類顏色是可以侄自己指定的。軌跡呈樹形結構,Monocle事先不知道應該調用樹的哪個軌跡中的哪個來調用“開始”,所以我們經常不得不再次使用root_state參數調用orderCells來指定開始。首先,我們繪制軌跡,這次按“狀態”給細胞上色。

plot_cell_trajectory(HSMM, color_by = "State")
plot_cell_trajectory(HSMM, color_by = "Pseudotime")

“狀態”只是自定義的某術語,表示一段分支。下面的函數便于識別包含seurat_clusters編號為零的大多數細胞的狀態。然后我們可以把它傳遞給orderCells。這個函數只是為了演示如何自定義root_state ,更簡單的方法是?orderCells 看如何設置。

GM_state <- function(cds){
  if (length(unique(pData(cds)$State)) > 1){
    T0_counts <- table(pData(cds)$State, pData(cds)$seurat_clusters)[,"0"]
    return(as.numeric(names(T0_counts)[which
                                       (T0_counts == max(T0_counts))]))
  } else {
    return (1)
  }
}
HSMM_1 <- orderCells(HSMM, root_state = GM_state(HSMM))
plot_cell_trajectory(HSMM_1, color_by = "Pseudotime")

可以看出不同的排序條件擬時方向是不一樣的。同時如果想看每個狀態下細胞的分化可以指定分面,當然你也可以指定其他的分面方式。

plot_cell_trajectory(HSMM_myo, color_by = "State") +
    facet_wrap(~State, nrow = 1)

如果沒有timeseries,可能需要根據某些標記基因的表達位置來設置根,使用您對系統的生物學知識。例如,在這個實驗中,高度增殖的祖細胞群產生兩種有絲分裂后的細胞。所以根應該有表達高水平增殖標記的細胞。我們可以使用抖動圖找出對應于快速增殖的狀態

blast_genes <- row.names(subset(fData(HSMM),
                                gene_short_name %in% c("CCNB2", "NOC2L", "CDC20")))
plot_genes_jitter(HSMM[blast_genes,],
                  grouping = "State",
                  min_expr = 0.1)

單個基因的時間變化(我可以隨意選擇基因而你不可以,你要選有意義的生活)

HSMM_expressed_genes <-  row.names(subset(fData(HSMM),
                                          num_cells_expressed >= 10))
HSMM_filtered <- HSMM[HSMM_expressed_genes,]
my_genes <- row.names(subset(fData(HSMM_filtered),
                             gene_short_name %in% c("YWHAB", "ICAM2", "ICAM2")))
cds_subset <- HSMM_filtered[my_genes,]
plot_genes_in_pseudotime(cds_subset, color_by = "seurat_clusters")

差異分析

差異基因表達分析是RNA-Seq實驗中的一項常見任務。Monocle可以幫助你找到不同細胞群間差異表達的基因,并評估這些變化的統計顯著性。這些比較要求您有一種方法將細胞收集到兩個或更多組中。這些組由每個CellDataSet的表現型數據表中的列定義。Monocle將評估不同細胞群中每個基因表達水平的顯著性。

marker_genes <- row.names(subset(fData(HSMM),
                                 gene_short_name %in% c("MEF2C", "MEF2D", "MYF5",
                                                        "ANPEP", "PDGFRA","MYOG",
                                                        "TPM1",  "TPM2",  "MYH2",
                                                        "MYH3",  "NCAM1", "TNNT1",
                                                        "TNNT2", "TNNC1", "CDK1",
                                                        "CDK2",  "CCNB1", "CCNB2",
                                                        "CCND1", "CCNA1", "ID1")))


diff_test_res <- differentialGeneTest(HSMM[marker_genes,],
                                      fullModelFormulaStr = "~percent.mt")
> head(diff_test_res)
      status           family       pval      qval gene_short_name num_cells_expressed use_for_ordering
MEF2D     OK negbinomial.size 0.10544931 0.4590520           MEF2D                   1            FALSE
CCNB1     OK negbinomial.size 0.45277970 0.7043240           CCNB1                   1            FALSE
MEF2C     OK negbinomial.size 0.28733226 0.5028315           MEF2C                   2            FALSE
TPM2      OK negbinomial.size 0.94348541 0.9696949            TPM2                   0            FALSE
CDK1      OK negbinomial.size 0.12768261 0.4590520            CDK1                   0            FALSE
CCND1     OK negbinomial.size 0.04021331 0.4590520           CCND1                   0            FALSE


MYOG_ID1 <- HSMM[row.names(subset(fData(HSMM),
                                      gene_short_name %in% c("CCND1", "CCNB2"))),]
plot_genes_jitter(MYOG_ID1, grouping = "seurat_clusters", ncol= 2)

選擇對區分細胞類型有意義的基因(Finding Genes that Distinguish Cell Type or State )
#Finding Genes that Distinguish Cell Type or State 
to_be_tested <- row.names(subset(fData(HSMM),
                                 gene_short_name %in% c("CDC20", "NCAM1", "ANPEP")))
cds_subset <- HSMM[to_be_tested,]


diff_test_res <- differentialGeneTest(cds_subset,
                                      fullModelFormulaStr = "~CellType")
diff_test_res[,c("gene_short_name", "pval", "qval")]

plot_genes_jitter(cds_subset,
                  grouping = "CellType",
                  color_by = "CellType",
                  nrow= 1,
                  ncol = NULL,
                  plot_trend = TRUE)

full_model_fits <-
  fitModel(cds_subset,  modelFormulaStr = "~CellType")
reduced_model_fits <- fitModel(cds_subset, modelFormulaStr = "~1")
diff_test_res <- compareModels(full_model_fits, reduced_model_fits)
diff_test_res

      status           family        pval       qval
CDC20     OK negbinomial.size 0.007822883 0.02346865
NCAM1     OK negbinomial.size 0.791131484 0.88906005
ANPEP     OK negbinomial.size 0.889060052 0.88906005

Monocle中的差異分析過程非常靈活:您在測試中使用的模型公式可以包含pData表中作為列存在的任何項,包括Monocle在其他分析步驟中添加的列。例如,如果您使用集群細胞,您可以使用集群作為模型公式來測試cluster之間不同的基因。

Finding Genes that Change as a Function of Pseudotime

Monocle的主要工作是將細胞按照生物過程(如細胞分化)的順序排列,而不事先知道要查看哪些基因。一旦這樣做了,你就可以分析細胞,找到隨著細胞進步而變化的基因。例如,你可以發現當細胞“成熟”時,基因顯著上調。

to_be_tested <- row.names(subset(fData(HSMM),
                                 gene_short_name %in% c("MYH3", "MEF2C", "CCNB2", "TNNT1")))
cds_subset <- HSMM[to_be_tested,]

diff_test_res <- differentialGeneTest(cds_subset,
                                      fullModelFormulaStr = "~sm.ns(Pseudotime)")

diff_test_res[,c("gene_short_name", "pval", "qval")]

      gene_short_name         pval         qval
MEF2C           MEF2C 2.996841e-02 3.995789e-02
CCNB2           CCNB2 5.328721e-03 1.065744e-02
MYH3             MYH3 6.371156e-01 6.371156e-01
TNNT1           TNNT1 1.634704e-12 6.538818e-12

plot_genes_in_pseudotime(cds_subset, color_by = "seurat_clusters")
Clustering Genes by Pseudotemporal Expression Pattern

在研究時間序列基因表達研究時,一個常見的問題是:“哪些基因遵循相似的動力學趨勢?”Monocle可以通過將具有相似趨勢的基因分組來幫助你回答這個問題,這樣你就可以分析這些基因組,看看它們有什么共同之處。Monocle提供了一種方便的方法來可視化所有偽時間相關的基因。函數plot_pseudotime_heatmap接受一個CellDataSet對象(通常只包含重要基因的子集),并生成與plot_genes_in_pseudotime類似的平滑表達曲線.然后,它將這些基因聚類并使用pheatmap包繪制它們。這允許您可視化基因模塊,這些模塊在偽時間內共同變化。

注意下面的num_clusters 指的是基因可以聚成幾個類,而不是細胞。

diff_test_res <- differentialGeneTest(HSMM[marker_genes,],
                                      fullModelFormulaStr = "~sm.ns(Pseudotime)")
sig_gene_names <- row.names(subset(diff_test_res, qval < 0.1))
plot_pseudotime_heatmap(HSMM[sig_gene_names,],
                        num_clusters = 6,
                        cores = 1,
                        show_rownames = T)
Multi-Factorial Differential Expression Analysis

Monocle可以在多個因素存在的情況下進行差異分析,這可以幫助你減去一些因素來看到其他因素的影響。在下面的簡單例子中,Monocle測試了三個基因在成肌細胞和成纖維細胞之間的差異表達,同時減去percent.mt的影響。為此,我們必須同時指定完整模型和簡化模型。完整的模型同時捕捉細胞類型和percent.mt的影響。

to_be_tested <-
  row.names(subset(fData(HSMM),
                   gene_short_name %in% c("TPM1", "MYH3", "CCNB2", "GAPDH")))

cds_subset <- HSMM[to_be_tested,]

diff_test_res <- differentialGeneTest(cds_subset,
                                      fullModelFormulaStr = "~CellType + percent.mt",
                                      reducedModelFormulaStr = "~percent.mt")
diff_test_res[,c("gene_short_name", "pval", "qval")]

      gene_short_name       pval      qval
GAPDH           GAPDH 0.07990737 0.1598147
CCNB2           CCNB2 0.04148172 0.1598147
TPM1             TPM1 0.90861287 0.9086129
MYH3             MYH3 0.77085745 0.9086129

plot_genes_jitter(cds_subset,
                  grouping = "seurat_clusters", color_by = "CellType", plot_trend = TRUE) +
  facet_wrap( ~ feature_label, scales= "free_y")
Analyzing Branches in Single-Cell Trajectories

通常,單細胞的軌跡包括分支。分支的產生是因為細胞執行替代基因表達程序。在發育過程中,當細胞做出命運的選擇時,分支就會出現在軌跡中:一個發育譜系沿著一條路徑前進,而另一個譜系產生第二條路徑。Monocle包含用于分析這些分支事件的廣泛功能。

芭芭拉·特雷特琳和她的同事們在史蒂夫·奎克的實驗室里進行了一項實驗,他們從正在發育的老鼠肺中獲取細胞。他們在細胞發育的早期捕獲細胞,之后當肺包含兩種主要類型的上皮細胞(AT1和AT2),以及即將決定成為AT1或AT2的細胞時。Monocle可以將這個過程重構為一個分支軌跡,讓你可以非常詳細地分析決策點。下圖顯示了使用Monocle的一些數據重建的一般方法。有一個單獨的分支,標記為“1”。當細胞從樹的左上方通過樹枝的早期發育階段通過時,哪些基因發生了變化?哪些基因在分支間有差異表達?為了回答這個問題,Monocle為您提供了一個特殊的統計測試:分支表達式分析建模,或BEAM。

lung <- load_lung()
plot_cell_trajectory(lung, color_by = "Time")

# 圖如下

BEAM_res <- BEAM(lung, branch_point = 1, cores = 1)
BEAM_res <- BEAM_res[order(BEAM_res$qval),]
BEAM_res <- BEAM_res[,c("gene_short_name", "pval", "qval")]

使用一種特殊類型的熱圖,您可以可視化所有明顯依賴于分支的基因的變化。這張熱圖同時顯示了兩種血統的變化。它還要求您選擇要檢查的分支點。列是偽時間中的點,行是基因,偽時間的開始在熱圖的中間。當你從熱圖的中間讀到右邊的時候,你正在跟隨一個偽時間譜系。當你讀到左邊時,另一個。這些基因是分層聚類的,因此您可以可視化具有類似的依賴于序列的基因模塊.

plot_genes_branched_heatmap(lung[row.names(subset(BEAM_res,
                                                  qval < 1e-4)),],
                            branch_point = 1,
                            num_clusters = 4,
                            cores = 1,
                            use_gene_short_name = T,
                            show_rownames = T)


那么問題來了,這個圖應該怎么看呢?

github上面是這樣回答的:

https://github.com/cole-trapnell-lab/monocle-release/issues/219
monocle2 擬時間分支點分析結果解讀

lung_genes <- row.names(subset(fData(lung),
                               gene_short_name %in% c("Ccnd2", "Sftpb", "Pdpn")))
plot_genes_branched_pseudotime(lung[lung_genes,],
                               branch_point = 1,
                               color_by = "Time",
                               ncol = 1)


> str(HSMM)
Formal class 'CellDataSet' [package "monocle"] with 19 slots
  ..@ reducedDimS          : num [1:2, 1:2638] -2.613 -0.652 -1.784 0.745 -2.376 ...
  .. ..- attr(*, "dimnames")=List of 2
  .. .. ..$ : NULL
  .. .. ..$ : chr [1:2638] "AAACATACAACCAC" "AAACATTGAGCTAC" "AAACATTGATCAGC" "AAACCGTGCTTCCG" ...
  ..@ reducedDimW          : num [1:281, 1:2] -0.0384 0.0812 -0.0465 0.0681 0.0655 ...
  ..@ reducedDimA          : num [1:2, 1:2638] 13.57 29.4 -2.74 -25.16 -9.3 ...
  ..@ reducedDimK          : num [1:2, 1:126] -2.305 -0.692 -1.711 0.538 -1.935 ...
  .. ..- attr(*, "dimnames")=List of 2
  .. .. ..$ : NULL
  .. .. ..$ : chr [1:126] "Y_1" "Y_2" "Y_3" "Y_4" ...
  ..@ minSpanningTree      :List of 10
  .. ..$ :List of 1
  .. .. ..$ Y_1: 'igraph.vs' Named int [1:2] 47 101
  .. .. .. ..- attr(*, "names")= chr [1:2] "Y_47" "Y_101"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..$ :List of 1
  .. .. ..$ Y_2: 'igraph.vs' Named int [1:2] 62 90
  .. .. .. ..- attr(*, "names")= chr [1:2] "Y_62" "Y_90"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..$ :List of 1
  .. .. ..$ Y_3: 'igraph.vs' Named int [1:2] 90 126
  .. .. .. ..- attr(*, "names")= chr [1:2] "Y_90" "Y_126"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..$ :List of 1
  .. .. ..$ Y_4: 'igraph.vs' Named int 106
  .. .. .. ..- attr(*, "names")= chr "Y_106"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..$ :List of 1
  .. .. ..$ Y_5: 'igraph.vs' Named int [1:2] 36 65
  .. .. .. ..- attr(*, "names")= chr [1:2] "Y_36" "Y_65"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..$ :List of 1
  .. .. ..$ Y_6: 'igraph.vs' Named int [1:2] 39 53
  .. .. .. ..- attr(*, "names")= chr [1:2] "Y_39" "Y_53"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..$ :List of 1
  .. .. ..$ Y_7: 'igraph.vs' Named int [1:2] 34 98
  .. .. .. ..- attr(*, "names")= chr [1:2] "Y_34" "Y_98"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..$ :List of 1
  .. .. ..$ Y_8: 'igraph.vs' Named int [1:2] 49 126
  .. .. .. ..- attr(*, "names")= chr [1:2] "Y_49" "Y_126"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..$ :List of 1
  .. .. ..$ Y_9: 'igraph.vs' Named int [1:2] 42 93
  .. .. .. ..- attr(*, "names")= chr [1:2] "Y_42" "Y_93"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..$ :List of 1
  .. .. ..$ Y_10: 'igraph.vs' Named int [1:2] 11 25
  .. .. .. ..- attr(*, "names")= chr [1:2] "Y_11" "Y_25"
  .. .. .. ..- attr(*, "env")=<weakref> 
  .. .. .. ..- attr(*, "graph")= chr "484d230c-94de-11e9-9f7f-07844984f7db"
  .. ..- attr(*, "class")= chr "igraph"
  ..@ cellPairwiseDistances: num [1:126, 1:126] 0 1.37 1.41 10.62 5.52 ...
  .. ..- attr(*, "dimnames")=List of 2
  .. .. ..$ : chr [1:126] "Y_1" "Y_2" "Y_3" "Y_4" ...
  .. .. ..$ : chr [1:126] "Y_1" "Y_2" "Y_3" "Y_4" ...
  ..@ expressionFamily     :Formal class 'vglmff' [package "VGAM"] with 22 slots
  .. .. ..@ blurb             : chr [1:6] "Negative-binomial distribution with size known\n\n" "Links:    " "loglink(mu)" "\n" ...
  .. .. ..@ constraints       :  expression({  constraints <- cm.zero.VGAM(constraints, x = x, NULL, M = M, predictors.names = predictors.names, M1 = 2) })
  .. .. ..@ deviance          :function ()  
  .. .. ..@ fini              :  expression({ })
  .. .. ..@ first             :  expression({ })
  .. .. ..@ infos             :function (...)  
  .. .. ..@ initialize        :  expression({  M1 <- 1  temp5 <- w.y.check(w = w, y = y, Is.nonnegative.y = TRUE, Is.integer.y = TRUE, ncol.w.max | __truncated__
  .. .. ..@ last              :  expression({  misc$link <- rep_len("loglink", NOS)  names(misc$link) <- mynames1  misc$earg <- vector("list", M) | __truncated__
  .. .. ..@ linkfun           :function ()  
  .. .. ..@ linkinv           :function (eta, extra = NULL)  
  .. .. ..@ loglikelihood     :function (mu, y, w, residuals = FALSE, eta, extra = NULL, summation = TRUE)  
  .. .. ..@ middle            :  expression({ })
  .. .. ..@ middle2           :  expression({ })
  .. .. ..@ summary.dispersion: logi(0) 
  .. .. ..@ vfamily           : chr "negbinomial.size"
  .. .. ..@ validparams       :function (eta, y, extra = NULL)  
  .. .. ..@ validfitted       :function ()  
  .. .. ..@ simslot           :function (object, nsim)  
  .. .. ..@ hadof             :function ()  
  .. .. ..@ charfun           :function ()  
  .. .. ..@ deriv             :  expression({  eta <- cbind(eta)  M <- ncol(eta)  kmat <- matrix(Inf, n, M, byrow = TRUE)  newemu <- list(theta = | __truncated__
  .. .. ..@ weight            :  expression({  ned2l.dmunb2 <- 1/mu - 1/(mu + kmat)  wz <- ned2l.dmunb2 * dmu.deta^2  c(w) * wz })
  ..@ lowerDetectionLimit  : num 1
  ..@ dispFitInfo          :<environment: 0x000000023e5e8110> 
  ..@ dim_reduce_type      : chr "DDRTree"
  ..@ auxOrderingData      :<environment: 0x000000002c5323c8> 
  ..@ auxClusteringData    :<environment: 0x00000000240fc8a0> 
  ..@ experimentData       :Formal class 'MIAME' [package "Biobase"] with 13 slots
  .. .. ..@ name             : chr ""
  .. .. ..@ lab              : chr ""
  .. .. ..@ contact          : chr ""
  .. .. ..@ title            : chr ""
  .. .. ..@ abstract         : chr ""
  .. .. ..@ url              : chr ""
  .. .. ..@ pubMedIds        : chr ""
  .. .. ..@ samples          : list()
  .. .. ..@ hybridizations   : list()
  .. .. ..@ normControls     : list()
  .. .. ..@ preprocessing    : list()
  .. .. ..@ other            : list()
  .. .. ..@ .__classVersion__:Formal class 'Versions' [package "Biobase"] with 1 slot
  .. .. .. .. ..@ .Data:List of 2
  .. .. .. .. .. ..$ : int [1:3] 1 0 0
  .. .. .. .. .. ..$ : int [1:3] 1 1 0
  ..@ assayData            :<environment: 0x000000005575c7a0> 
  ..@ phenoData            :Formal class 'AnnotatedDataFrame' [package "Biobase"] with 4 slots
  .. .. ..@ varMetadata      :'data.frame': 17 obs. of  1 variable:
  .. .. .. ..$ labelDescription: chr [1:17] NA NA NA NA ...
  .. .. ..@ data             :'data.frame': 2638 obs. of  17 variables:
  .. .. .. ..$ orig.ident                     : Factor w/ 1 level "pbmc3k": 1 1 1 1 1 1 1 1 1 1 ...
  .. .. .. ..$ nCount_RNA                     : num [1:2638] 2419 4903 3147 2639 980 ...
  .. .. .. ..$ nFeature_RNA                   : int [1:2638] 779 1352 1129 960 521 781 782 790 532 550 ...
  .. .. .. ..$ percent.mt                     : num [1:2638] 3.02 3.79 0.89 1.74 1.22 ...
  .. .. .. ..$ RNA_snn_res.0.5                : Factor w/ 9 levels "0","1","2","3",..: 2 4 2 3 7 2 5 5 1 6 ...
  .. .. .. ..$ seurat_clusters                : Factor w/ 9 levels "0","1","2","3",..: 2 4 2 3 7 2 5 5 1 6 ...
  .. .. .. ..$ Size_Factor                    : num [1:2638] 1.108 2.245 1.441 1.208 0.449 ...
  .. .. .. ..$ num_genes_expressed            : int [1:2638] 126 181 149 153 34 103 104 112 64 51 ...
  .. .. .. ..$ Cluster                        : Factor w/ 1 level "1": 1 1 1 1 1 1 1 1 1 1 ...
  .. .. .. ..$ peaks                          : logi [1:2638] FALSE FALSE FALSE FALSE FALSE FALSE ...
  .. .. .. ..$ halo                           : logi [1:2638] FALSE FALSE FALSE FALSE FALSE FALSE ...
  .. .. .. ..$ delta                          : num [1:2638] 0.401 0.442 1.031 0.205 0.812 ...
  .. .. .. ..$ rho                            : num [1:2638] 36 33.3 44.8 47.7 31.7 ...
  .. .. .. ..$ nearest_higher_density_neighbor: logi [1:2638] NA NA NA NA NA NA ...
  .. .. .. ..$ Pseudotime                     : num [1:2638] 12.277 11.115 13.023 0.723 16.159 ...
  .. .. .. ..$ State                          : Factor w/ 5 levels "1","2","3","4",..: 5 2 5 1 5 4 5 5 5 1 ...
  .. .. .. ..$ CellType                       : Factor w/ 3 levels "CDC20","GABPB2",..: 3 3 3 3 3 3 3 3 3 3 ...
  .. .. ..@ dimLabels        : chr [1:2] "sampleNames" "sampleColumns"
  .. .. ..@ .__classVersion__:Formal class 'Versions' [package "Biobase"] with 1 slot
  .. .. .. .. ..@ .Data:List of 1
  .. .. .. .. .. ..$ : int [1:3] 1 1 0
  ..@ featureData          :Formal class 'AnnotatedDataFrame' [package "Biobase"] with 4 slots
  .. .. ..@ varMetadata      :'data.frame': 3 obs. of  1 variable:
  .. .. .. ..$ labelDescription: chr [1:3] NA NA NA
  .. .. ..@ data             :'data.frame': 13714 obs. of  3 variables:
  .. .. .. ..$ gene_short_name    : Factor w/ 13714 levels "7SK.2","A1BG",..: 527 715 9394 9395 5971 7345 5750 8158 9747 4917 ...
  .. .. .. ..$ num_cells_expressed: int [1:13714] 0 0 0 0 0 1 0 0 0 6 ...
  .. .. .. ..$ use_for_ordering   : logi [1:13714] FALSE FALSE FALSE FALSE FALSE FALSE ...
  .. .. ..@ dimLabels        : chr [1:2] "featureNames" "featureColumns"
  .. .. ..@ .__classVersion__:Formal class 'Versions' [package "Biobase"] with 1 slot
  .. .. .. .. ..@ .Data:List of 1
  .. .. .. .. .. ..$ : int [1:3] 1 1 0
  ..@ annotation           : chr(0) 
  ..@ protocolData         :Formal class 'AnnotatedDataFrame' [package "Biobase"] with 4 slots
  .. .. ..@ varMetadata      :'data.frame': 0 obs. of  1 variable:
  .. .. .. ..$ labelDescription: chr(0) 
  .. .. ..@ data             :'data.frame': 2638 obs. of  0 variables
  .. .. ..@ dimLabels        : chr [1:2] "sampleNames" "sampleColumns"
  .. .. ..@ .__classVersion__:Formal class 'Versions' [package "Biobase"] with 1 slot
  .. .. .. .. ..@ .Data:List of 1
  .. .. .. .. .. ..$ : int [1:3] 1 1 0
  ..@ .__classVersion__    :Formal class 'Versions' [package "Biobase"] with 1 slot
  .. .. ..@ .Data:List of 5
  .. .. .. ..$ : int [1:3] 3 5 2
  .. .. .. ..$ : int [1:3] 2 42 0
  .. .. .. ..$ : int [1:3] 1 3 0
  .. .. .. ..$ : int [1:3] 1 0 0
  .. .. .. ..$ : int [1:3] 1 2 0

STREAM:一款scRNA-seq擬時分析工具
Clustering by fast search and find of density peaks
發表在 Science 上的一種新聚類算法
重磅消息:諾禾致源10X Genomics單細胞轉錄組產品全新升級
基迪奧10x單細胞轉錄組產品新升級
An overview of algorithms for estimating pseudotime in single-cell RNA-seq data
A set of tools supporting the development, execution, and benchmarking of trajectory inference methods.
hemberg-lab.github.io
Diffusion pseudotime robustly reconstructs lineage branching
dynverse
Monocle
A new statistical method allows researchers to infer different developmental processes from RNA-Seq data
Pseudotime estimation: deconfounding single cell time series
Your top 3 single-cell RNA sequencing analysis tools
Single-cell trajectory analysis
STREAM
MIA: Luca Pinello, Huidong Chen, Single-cell trajectories from omics; Jonathan Hsu, CRISPR tiling
使用monocle包進行pseudotime分析
關于細胞分化軌跡學習小筆記

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容