系列回顾:
ArchR官网教程学习笔记1:Getting Started with ArchR
ArchR官网教程学习笔记2:基于ArchR推测Doublet
ArchR官网教程学习笔记3:创建ArchRProject
ArchR官网教程学习笔记4:ArchR的降维
ArchR官网教程学习笔记5:ArchR的聚类
ArchR官网教程学习笔记6:单细胞嵌入(Single-cell Embeddings)
ArchR官网教程学习笔记7:ArchR的基因评分和Marker基因
ArchR官网教程学习笔记8:定义与scRNA-seq一致的聚类
ArchR官网教程学习笔记9:ArchR的伪批量重复
ArchR官网教程学习笔记10:ArchR的call peak
ArchR官网教程学习笔记11:鉴定Marker峰
ArchR官网教程学习笔记12:Motif和Feature富集
ArchR官网教程学习笔记13:ChromVAR偏差富集
ArchR官网教程学习笔记14:ArchR的Footprinting分析
ArchR官网教程学习笔记15:ArchR的整合分析
为了在拟时间(pseudo-time)中对细胞进行排序,ArchR在ArchRProject中创建了细胞轨迹,这些轨迹可以在较低的N维子空间中对细胞进行排序。以前,我们在二维UMAP子空间中执行了这种排序,但ArchR改进了这种方法,使N维子空间(即LSI)内的比对成为可能。首先,ArchR需要一个用户自定义的轨迹主干,它提供了细胞组/cluster的粗略排序。例如:鉴于用户决定的cluster的身份,一个可以提供干细胞cluster的cluster ID,然后一个祖细胞cluster,然后是分化的细胞cluster,对应于一个已知或假定生物相关细胞轨迹(比如为HSC提供cluster ID, 然后GMP,最后到单核细胞)。接下来,对于每个cluster,ArchR计算每个细胞群/cluster在N维的平均坐标,并保留到这些平均坐标的欧氏距离位于所有细胞的前5%的细胞。接下来,ArchR沿着轨迹计算每个细胞从cluster i到cluster i+1的平均坐标,并计算一个伪时间向量(基于这些每个i的迭代的距离)。这允许ArchR为每个细胞确定一个N维坐标和拟时间值,作为基于欧氏距离的细胞组/cluster平均坐标的轨迹。(这句不太会翻译,原文在这:This allows ArchR to determine an N-dimensional coordinate and a pseudo-time value for each of the cells retained as part of the trajectory based on the Euclidean distance to the cell group/cluster mean coordinates. )然后,ArchR根据伪时间值对每个N维坐标进行连续轨迹拟合,使用smooth.spline
函数。之后,ArchR根据细胞在流形上最近点的欧几里得距离,将所有细胞对齐到轨迹上。然后,ArchR将此比对scales到100,并将此拟时间存储在ArchRProject中以供下游分析之用。
ArchR可以创建矩阵,在Arrow files中存储的特性之间传递拟时间趋势。例如,ArchR可以分析拟时间内TF偏差、基因评分或整合基因表达的变化,以识别贯穿细胞轨迹的动态调节因子或调控元件。首先,ArchR在细胞轨迹上以用户定义的小分位数增量(默认为1/100)对细胞进行分组。ArchR使用用户定义的平滑窗口(默认= 9/100)使用data.table::frollmean
功能对矩阵的每个特征进行平滑处理。然后,ArchR返回这个平滑拟时间x特征矩阵,作为下游分析的SummarizedExperiment
。ArchR还可以使用名称匹配(即带有chromVAR TF偏差的正向调节因子和基因评分/整合图谱)或使用低重叠细胞聚集的基因组位置重叠方法(即peak-to-gene linkages)将两个平滑伪时间x特征矩阵关联起来,如前面所述。因此,ArchR有助于跨细胞轨迹的综合分析,揭示跨多模动态数据的相关调控动力学。
(一)髓系(Myeloid)轨迹-单核细胞分化
在本节中,我们将创建一个近似于HSCs分化为完全分化单核细胞的细胞轨迹。首先,让我们回顾一下前面定义的cluster和cell types,它们存储在cellColData
中名为“clusters”和“Clusters2”的列中。在我们的UMAP嵌入上覆盖这些细胞分组显示了我们感兴趣的不同细胞类型。
#显示cluster
> p1 <- plotEmbedding(ArchRProj = projHeme5, colorBy = "cellColData", name = "Clusters", embedding = "UMAP")
#显示细胞类型
> p2 <- plotEmbedding(ArchRProj = projHeme5, colorBy = "cellColData", name = "Clusters2", embedding = "UMAP")
#出图
> ggAlignPlots(p1, p2, type = "h")
(1)UMAP拟时间与单独特征的绘制
我们将使用存储在“Clusters2”中的细胞类型定义。如上所述,我们正在创建一条从干细胞(“Progenitor”),通过连接的髓系祖细胞(“GMP”),到单核细胞(“Mono”)的轨迹。创建轨迹的第一步是以细胞组标签的有序向量的形式创建轨迹主干。
> trajectory <- c("Progenitor", "GMP", "Mono")
> trajectory
[1] "Progenitor" "GMP" "Mono"
我们使用addTrajectory()
函数创建一条轨迹,并将其添加到ArchRProject中。我们称这个轨迹为“MyeloidU”。这样做的目的是在cellColData
中创建一个名为“MyeloidU”的新列,它存储了轨迹中每个细胞的拟时间值。不属于轨迹的细胞用NA标记。
> projHeme5 <- addTrajectory(
ArchRProj = projHeme5,
name = "MyeloidU",
groupBy = "Clusters2",
trajectory = trajectory,
embedding = "UMAP",
force = TRUE
)
我们可以查看这些信息,发现每个细胞都有一个在0到100之间的唯一伪时间值。我们排除了有NA值的细胞,因为这些不是轨迹的一部分。
> head(projHeme5$MyeloidU[!is.na(projHeme5$MyeloidU)])
[1] 46.66808 55.72245 54.28390 44.57373 46.94309 45.82187
为了绘制这条轨迹,我们使用了plotTrajectory()
函数,该函数覆盖了UMAP嵌入的拟时间值,并显示了一个箭头,接近拟合后的轨迹路径。不属于轨迹的细胞呈灰色。在本例中,我们使用colorBy = "cellColData"来告诉ArchR在cellColData
中查找由名称指定的列——在本例中是“MyeloidU”拟时间轨迹。虽然它可能看起来比较不太正常,列出“MyeloidU”为trajectory
和name
,这样做是因为trajectory
告诉ArchR哪个细胞子集我们感兴趣,name
告诉ArchR如何给细胞子集上颜色。
> p <- plotTrajectory(projHeme5, trajectory = "MyeloidU", colorBy = "cellColData", name = "MyeloidU")
> p[[1]]
> plotPDF(p, name = "Plot-MyeloidU-Traj-UMAP.pdf", ArchRProj = projHeme5, addDOC = FALSE, width = 5, height = 5)
我们还可以在UMAP嵌入的轨迹上覆盖其他特征。这允许我们只在细胞内显示与我们的轨迹相关的特定特征。
如果你还没有将impute weights添加到你的projHeme5项目中,可以现在添加:
> projHeme5 <- addImputeWeights(projHeme5)
然后,我们可以绘制出“MyeloidU” 轨迹,但通过CEBPB基因的基因评分值给细胞着色。CEBPB基因是已知的单核细胞功能调节因子,在分化过程中变得活跃。我们通过colorBy
参数表示要使用的矩阵,通过name
参数表示要使用的特征。
> p1 <- plotTrajectory(projHeme5, trajectory = "MyeloidU", colorBy = "GeneScoreMatrix", name = "CEBPB", continuousSet = "horizonExtra")
我们可以重复这个过程,但是通过他们链接的基因表达通过GeneIntegrationMatrix
给细胞上色。
> p2 <- plotTrajectory(projHeme5, trajectory = "MyeloidU", colorBy = "GeneIntegrationMatrix", name = "CEBPB", continuousSet = "blueYellow")
plotTrajectory()
函数的作用是:返回一个相关图形的列表。列表中的第一个图是一个嵌入的UMAP,按照函数调用中指定的颜色着色。
将这些UMAP图并排比较基因评分和基因表达,我们可以看到CEBPB基因的活性在拟时间轨迹的后期对单核细胞具有高度特异性。
> ggAlignPlots(p1[[1]], p2[[1]], type = "h")
plotTrajectory()
返回的第二个图是拟时间相对于相关特征值(在本例中是CEBPB的基因评分或基因表达)的点图。在这种情况下,细胞被拟时间着色。
> ggAlignPlots(p1[[2]], p2[[2]], type = "h")
(2)拟时间热图
我们可以使用热图在拟时间中可视化许多特征的变化。为此,我们首先使用getTrajectory()
函数从ArchRProject检索感兴趣的轨迹,该函数将轨迹作为SummarizedExperiment对象返回。通过将相应的矩阵传递给useMatrix
参数,我们将为motifs、基因评分、基因表达和峰可接近性创建这些伪拟时间热图。
> trajMM <- getTrajectory(ArchRProj = projHeme5, name = "MyeloidU", useMatrix = "MotifMatrix", log2Norm = FALSE)
然后将SummarizedExperiment 传递给plotTrajectoryHeatmap()
函数:
> p1 <- plotTrajectoryHeatmap(trajMM, pal = paletteContinuous(set = "solarExtra"))
通过设置useMatrix = "GeneScoreMatrix"
,我们可以执行相同的步骤来获得基因评分的拟时间热图:
> trajGSM <- getTrajectory(ArchRProj = projHeme5, name = "MyeloidU", useMatrix = "GeneScoreMatrix", log2Norm = TRUE)
> p2 <- trajectoryHeatmap(trajGSM, pal = paletteContinuous(set = "horizonExtra"))
同样,通过设置useMatrix = "GeneIntegrationMatrix"
,我们可以得到基因表达的拟时间热图:
> trajGIM <- getTrajectory(ArchRProj = projHeme5, name = "MyeloidU", useMatrix = "GeneIntegrationMatrix", log2Norm = FALSE)
> p3 <- plotTrajectoryHeatmap(trajGIM, pal = paletteContinuous(set = "blueYellow"))
最后,通过设置useMatrix = "PeakMatrix"
,可以得到可接近峰的拟时间热图:
> trajPM <- getTrajectory(ArchRProj = projHeme5, name = "MyeloidU", useMatrix = "PeakMatrix", log2Norm = TRUE)
> p4 <- plotTrajectoryHeatmap(trajPM, pal = paletteContinuous(set = "solarExtra"))
最后保存四个热图:
> plotPDF(p1, p2, p3, p4, name = "Plot-MyeloidU-Traj-Heatmaps.pdf", ArchRProj = projHeme5, addDOC = FALSE, width = 6, height = 8)
(3)整合的拟时间分析
我们也可以进行整合分析,比如通过整合基因评分/基因表达与motif可接近性,在拟时间内识别正向调控的的TF因子。这可能是非常强大的,例如在识别分化过程中的driver因子。为此,我们使用correlateTrajectories()
函数,该函数接受从getTrajectories()
函数检索到的SummarizedExperiment 对象。
首先,我们找出伪时间里与TF基因评分相关的motif可接近性。
> corGSM_MM <- correlateTrajectories(trajGSM, trajMM)
correlateTrajectories()
的主要输出是一个列表对象,其中包含一个DataFrame
对象作为列表中的第一个条目。这个DataFrame
包含名为idx1、matchname1、name1和VarAssay1的列,它们对应于传递给correlateTrajectories()
函数的第一个轨迹(基因得分)中的索引、匹配名称、未修改名称和特征的方差分位。“方差分位数”是给定特征的标准化度量,它允许我们在不同的分析之间获得相关性。该DataFrame
包含了满足correlateTrajectories()
函数中指定的cutoffs的所有特性。
> corGSM_MM[[1]]
DataFrame with 38 rows and 12 columns
idx1 idx2 matchname1 matchname2 name1
1 82 1081 PRDM16 PRDM16 chr1:PRDM16
2 731 932 TAL1 TAL1 chr1:TAL1
3 2034 1002 ATF3 ATF3 chr1:ATF3
4 2369 1254 GATA3 GATA3 chr10:GATA3
5 2370 1254 GATA3 GATA3 chr10:GATA3-AS1
... ... ... ... ... ...
34 20780 1031 SNAI2 SNAI2 chr8:SNAI2
35 21036 1696 KLF10 KLF10 chr8:KLF10
36 21658 1003 NFIL3 NFIL3 chr9:NFIL3
37 21793 1078 KLF4 KLF4 chr9:KLF4
38 22097 1565 RXRA RXRA chr9:RXRA
name2 Correlation VarAssay1 VarAssay2
1 z:PRDM16_211 0.85014826559353 0.999740562978337 0.875287356321839
2 z:TAL1_62 0.696298473631261 0.882388550179444 0.989080459770115
3 z:ATF3_132 0.819469211756172 0.984779694729105 0.931609195402299
4 z:GATA3_384 0.732708704489167 0.837419466424525 0.991954022988506
5 z:GATA3_384 0.711284069415112 0.987201106931292 0.991954022988506
... ... ... ... ...
34 z:SNAI2_161 0.681024727630591 0.861547109439184 0.98448275862069
35 z:KLF10_826 0.533217470662006 0.930297920179876 0.860344827586207
36 z:NFIL3_133 0.82919544014856 0.993773511480088 0.895977011494253
37 z:KLF4_208 0.804088079166488 0.998919012409738 0.904022988505747
38 z:RXRA_695 0.579687074016823 0.913607471786224 0.897126436781609
TStat Pval FDR
1 15.983561542674 4.7273839846548e-29 7.73400019889526e-26
2 9.60359546878347 8.77882016024456e-16 3.59053744554003e-14
3 14.1546027210612 1.98559418498259e-25 5.4140534777192e-23
4 10.6583309726314 4.53341402479216e-18 3.22463710633042e-16
5 10.0175078671253 1.10887216067257e-16 5.33563192605979e-15
... ... ... ...
34 9.20683499132072 6.37374397310972e-15 2.27896264168966e-13
35 6.23962130337716 1.11991547934746e-08 1.27234841959198e-07
36 14.6855480197568 1.68977613968731e-26 6.91118441132108e-24
37 13.3892842533234 7.33134596013733e-24 1.49926024884808e-21
38 7.04262799929917 2.62343842259912e-10 4.42468583440429e-09
然后我们可以对相应的轨迹SummarizedExperiment对象进行子集化,使其只包含上面传递的显著性的元素。
> trajGSM2 <- trajGSM[corGSM_MM[[1]]$name1, ]
> trajMM2 <- trajMM[corGSM_MM[[1]]$name2, ]
为了最好地排列这些特征,我们可以创建一个新的轨迹,其中这两个轨迹的值相乘。这将允许我们创建并排的热图,并按照“行”进行相同的排序。
> trajCombined <- trajGSM2
> assay(trajCombined) <- t(apply(assay(trajGSM2), 1, scale)) + t(apply(assay(trajMM2), 1, scale))
我们可以从plotTrajectoryHeatmap()
函数的返回值中提取最优行序:
> combinedMat <- plotTrajectoryHeatmap(trajCombined, returnMat = TRUE, varCutOff = 0)
> rowOrder <- match(rownames(combinedMat), rownames(trajGSM2))
这样,我们现在就可以创建成对的热图了。首先,我们将创建基因评分轨迹的热图。我们通过rowOrder
参数指定所需的行顺序
> ht1 <- plotTrajectoryHeatmap(trajGSM2, pal = paletteContinuous(set = "horizonExtra"), varCutOff = 0, rowOrder = rowOrder)
然后,我们将为motif轨迹创建热图,再次通过rowOrder
参数指定行顺序:
>ht2 <- plotTrajectoryHeatmap(trajMM2, pal = paletteContinuous(set = "solarExtra"), varCutOff = 0, rowOrder = rowOrder)
将这两个热图并排绘制,我们可以看到这两个热图之间的行是匹配的。你可能注意到,分析同时捕获了GATA3和GATA3- as1 (GATA3的反义转录本)。反义转录本可以在后处理中手动删除,或者如果需要,可以通过程序删除。
> ht1 + ht2
我们可以重复同样的过程,但使用GeneIntegrationMatrix中的基因表达。因为这是相同的分析流程,所以我们不会对每个步骤重复解释:
> corGIM_MM <- correlateTrajectories(trajGIM, trajMM)
> corGIM_MM[[1]]
DataFrame with 39 rows and 12 columns
idx1 idx2 matchname1 matchname2 name1 name2
1 295 1601 RUNX3 RUNX3 chr1:RUNX3 z:RUNX3_731
2 680 1612 NFIA NFIA chr1:NFIA z:NFIA_742
3 1227 1512 MEF2D MEF2D chr1:MEF2D z:MEF2D_642
4 1936 1254 GATA3 GATA3 chr10:GATA3 z:GATA3_384
5 2036 1027 ZEB1 ZEB1 chr10:ZEB1 z:ZEB1_157
... ... ... ... ... ... ...
35 15859 997 CREB5 CREB5 chr7:CREB5 z:CREB5_127
36 16783 1022 CEBPD CEBPD chr8:CEBPD z:CEBPD_152
37 17463 1003 NFIL3 NFIL3 chr9:NFIL3 z:NFIL3_133
38 17560 1078 KLF4 KLF4 chr9:KLF4 z:KLF4_208
39 17803 1565 RXRA RXRA chr9:RXRA z:RXRA_695
Correlation VarAssay1 VarAssay2
1 0.860047343627608 0.801085963120262 0.986206896551724
2 0.894245099146662 0.854416429224235 0.92183908045977
3 0.712167453144056 0.842266544809419 0.855172413793103
4 0.853980182469668 0.800279554862642 0.991954022988506
5 0.758292172128321 0.846406107198538 0.92816091954023
... ... ... ...
35 0.945126143544879 0.913606795333584 0.909195402298851
36 0.863657822834346 0.992796086231923 0.999425287356322
37 0.794403875364849 0.921348314606742 0.895977011494253
38 0.869343633075701 0.983387989893016 0.904022988505747
39 0.878862330182784 0.943927745820117 0.897126436781609
TStat Pval FDR
1 16.6871751532611 2.13271762375757e-30 3.54183462516882e-29
2 19.7788605813507 5.46736754072656e-36 2.31120536948895e-34
3 10.0427370351419 9.77537930169305e-17 6.06073516704969e-16
4 16.2480926144105 1.46386532929263e-29 2.16094405752722e-28
5 11.5148618409319 6.50032103211223e-20 5.03774879988698e-19
... ... ... ...
35 28.6382309731165 2.07281898426153e-49 2.40965206920403e-47
36 16.9611989488559 6.48983675726322e-31 1.16068234312592e-29
37 12.947527156958 6.06031542413251e-23 5.87093056712836e-22
38 17.4138442225833 9.28541630505885e-32 1.83732705610739e-30
39 18.2367229609944 2.89442439140554e-33 8.41192088752235e-32
> trajGIM2 <- trajGIM[corGIM_MM[[1]]$name1, ]
> trajMM2 <- trajMM[corGIM_MM[[1]]$name2, ]
> trajCombined <- trajGIM2
> assay(trajCombined) <- t(apply(assay(trajGIM2), 1, scale)) + t(apply(assay(trajMM2), 1, scale))
> combinedMat <- plotTrajectoryHeatmap(trajCombined, returnMat = TRUE, varCutOff = 0)
> rowOrder <- match(rownames(combinedMat), rownames(trajGIM2))
> ht1 <- plotTrajectoryHeatmap(trajGIM2, pal = paletteContinuous(set = "blueYellow"), varCutOff = 0, rowOrder = rowOrder)
> ht2 <- plotTrajectoryHeatmap(trajMM2, pal = paletteContinuous(set = "solarExtra"), varCutOff = 0, rowOrder = rowOrder)
> ht1+ht2