Using SingleR to annotate single-cell RNA-seq data
参考:https://www.bioconductor.org/packages/release/bioc/html/SingleR.html
clp
21 June, 2020
用SingleR
对single-cell RNA-seq数据进行注释
1 前言
SingleR是single-cell RNA sequencing (scRNAseq) 数据的自动注释方法(Aran et al. 2019)。给出具有已知标签的样本(single-cell or bulk)的参考数据集,它基于与参考集的相似性来标记来自测试数据集的新的细胞。具体地说,对于每个test cell进行如下操作:
1.计算其表达谱与各参比样本表达谱之间的Spearman相关性。这是在所有标记对(pairs)之间联合识别的标记基因(labels)上完成的。
2.将每标签得分(per-label score)定义为相关性分布的固定分位数(默认情况下为0.8)。
3.对所有标签(labels)重复此操作,并将得分最高的标签作为该单细胞的注释。
4.可以选择执行微调步骤:
- 参考数据集子集设置为仅包括分数接近最大值的标签。
- 仅使用标签子集的标记基因重新计算分数。
- 重复此操作,直到保留一个标签。
自动注释提供了跨数据集传输生物知识的便捷方式。以这种方式,对于参考数据集,手动解释聚类和定义标记基因的负担只需完成一次,并且该知识可以以自动的方式传播到新的数据集。
1.1 安装R包
rm(list = ls())
options(stringsAsFactors = F)
options(BioC_mirror="https://mirrors.tuna.tsinghua.edu.cn/bioconductor/")
options("repos" = c(CRAN="http://mirrors.cloud.tencent.com/CRAN/"))
options(download.file.method = 'libcurl')
options(url.method='libcurl')
#BiocManager::install("SingleR")
2 Using the built-in references
SingleR
通过专用的数据检索功能提供了几个参考数据集(主要来自bulk RNA-seq or microarray data)。例如,我们使用HumanPrimaryCellAtlasData()
函数从人类初级细胞图谱(Human Primary Cell Atlas)获取参考数据,该函数返回一个SummarizedExperiment
对象,该对象包含带有样本标签(sample-level labels)的对数表达矩阵(matrix of log-expression values)。
library(SingleR)
hpca.se <- HumanPrimaryCellAtlasData()
hpca.se
#> class: SummarizedExperiment
#> dim: 19363 713
#> metadata(0):
#> assays(1): logcounts
#> rownames(19363): A1BG A1BG-AS1 ... ZZEF1 ZZZ3
#> rowData names(0):
#> colnames(713): GSM112490 GSM112491 ... GSM92233 GSM92234
#> colData names(2): label.main label.fine
测试数据集将取自La Manno et al. (2016)。 为了提高速度,将只标记此数据集中的前100个cells。
library(scRNAseq)
hESCs <- LaMannoBrainData('human-es')
hESCs <- hESCs[,1:100]
# SingleR() expects log-counts, but the function will also happily take raw
# counts for the test dataset. The reference, however, must have log-values.
library(scater)
hESCs <- logNormCounts(hESCs)
使用hpca.se
引用通过SingleR()
函数注释hESCs中的每个细胞,该函数使用上述算法。请注意,默认的标记检测方法是取每个基因的每个标签的中位数中具有最大正对数倍变化(positive log-fold changes)的基因。
pred.hesc <- SingleR(test = hESCs, ref = hpca.se, labels = hpca.se$label.main)
pred.hesc
#> DataFrame with 100 rows and 5 columns
#> scores
#> <matrix>
#> 1772122_301_C02 0.118426779945786:0.179699807625087:0.157326274226517:...
#> 1772122_180_E05 0.129708246318855:0.236277439793527:0.202370888668263:...
#> 1772122_300_H02 0.158201338525345:0.250060222727419:0.211831550178353:...
#> 1772122_180_B09 0.158778546217777:0.27716592787528:0.222681369744636:...
#> 1772122_180_G04 0.138505219642345:0.236658649096383:0.19092437361406:...
#> ... ...
#> 1772122_299_E07 0.145931041885859:0.241153701803065:0.217382763112476:...
#> 1772122_180_D02 0.122983434596168:0.239181076829949:0.181221997276501:...
#> 1772122_300_D09 0.129757310468164:0.233775092572195:0.196637664917917:...
#> 1772122_298_F09 0.143118885460347:0.262267367714562:0.214329641867196:...
#> 1772122_302_A11 0.0912854247387272:0.185945405472165:0.139232371863794:...
#> first.labels tuning.scores
#> <character> <DataFrame>
#> 1772122_301_C02 Neuroepithelial_cell 0.18244020296249:0.0991115652997192
#> 1772122_180_E05 Neuroepithelial_cell 0.137548373236792:0.0647133734667384
#> 1772122_300_H02 Neuroepithelial_cell 0.275798157639906:0.136969040146444
#> 1772122_180_B09 Neuroepithelial_cell 0.0851622797320583:0.0819878452425098
#> 1772122_180_G04 Neuroepithelial_cell 0.198841544187094:0.101662168246495
#> ... ... ...
#> 1772122_299_E07 Neuroepithelial_cell 0.176002520599547:0.0922503823656398
#> 1772122_180_D02 Neuroepithelial_cell 0.196760862365318:0.112480486219438
#> 1772122_300_D09 Neuroepithelial_cell 0.0816424287822026:0.0221368018363302
#> 1772122_298_F09 Neuroepithelial_cell 0.187249853552379:0.0671892835266423
#> 1772122_302_A11 Neuroepithelial_cell 0.156079956344163:0.105132159755961
#> labels pruned.labels
#> <character> <character>
#> 1772122_301_C02 Neuroepithelial_cell Neuroepithelial_cell
#> 1772122_180_E05 Neurons Neurons
#> 1772122_300_H02 Neuroepithelial_cell Neuroepithelial_cell
#> 1772122_180_B09 Neuroepithelial_cell Neuroepithelial_cell
#> 1772122_180_G04 Neuroepithelial_cell Neuroepithelial_cell
#> ... ... ...
#> 1772122_299_E07 Neuroepithelial_cell Neuroepithelial_cell
#> 1772122_180_D02 Neuroepithelial_cell Neuroepithelial_cell
#> 1772122_300_D09 Neuroepithelial_cell Neuroepithelial_cell
#> 1772122_298_F09 Neuroepithelial_cell Neuroepithelial_cell
#> 1772122_302_A11 Astrocyte Astrocyte
输出DataFrame的每一行都包含一个单细胞的预测结果。标签在微调之前(first.labels)、微调之后(labels)和修剪之后(pruned.labels)以及相关分数一起显示。作者总结了标签在细胞子集上的分布情况:
table(pred.hesc$labels)
#>
#> Astrocyte Neuroepithelial_cell Neurons
#> 14 81 5
在这一点上,值得注意的是,SingleR
与工作流/包(workflow/package)无关。上面的示例使用了SummarizedExperiment
对象,但是相同的函数将接受任何(log-)规一化表达矩阵。
3 Using single-cell references
这里,我们将使用scRNAseq包中的两个人类胰腺数据集。目的是使用一个预先标记的数据集来注释另一个未标记的数据集。首先,设置Muraro et al. (2016) 数据集作为参考。
library(scRNAseq)
sceM <- MuraroPancreasData()
# One should normally do cell-based quality control at this point, but for
# brevity's sake, we will just remove the unlabelled libraries here.
sceM <- sceM[,!is.na(sceM$label)]
sceM <- logNormCounts(sceM)
然后,我们设置了来自Grun et al. (2016)等人的测试数据集。为了加快演示速度,我们将子集设置为前100个细胞。
sceG <- GrunPancreasData()
sceG <- sceG[,colSums(counts(sceG)) > 0] # Remove libraries with no counts.
sceG <- logNormCounts(sceG)
sceG <- sceG[,1:100]
然后,我们运行SingleR()
,如前所述,但是使用的标记检测模式考虑了细胞间表达的差异。在这里,我们将使用Wilcoxon
排序和检验来确定标签之间每个成对比较的top markers。与默认的标记检测算法(对于中值经常为零可能失败的低覆盖数据)相比,这更慢,但更适合于单细胞数据。
pred.grun <- SingleR(test=sceG, ref=sceM, labels=sceM$label, de.method="wilcox")
table(pred.grun$labels)
#>
#> acinar beta delta duct endothelial
#> 53 4 1 41 1
4 Annotation diagnostics
4.1 Based on the scores within cells
SingleR
提供了一些基本但功能强大的可视化工具。plotScoreHeatmap()
显示所有引用标签上所有细胞的得分,这允许用户检查数据集中预测标签的可信度。每个细胞的实际分配标签显示在顶部的颜色栏中(color bar at the top);请注意,如果应用微调,这可能不是视觉上得分最高的标签,因为只有预调的分数(pre-tuned scores)可以在所有标签上直接进行比较。
plotScoreHeatmap(pred.grun)
对于此图,关键点是检查分数(scores)在每个细胞中的分布情况。理想情况下,每个细胞(即热图的列)应该有一个明显大于其他细胞的分数,这表明它明确地分配给了单个标签。给定细胞的相似分数分布表明分配是不确定的,尽管如果不确定性分布在不容易解决的相似细胞类型上,这可能是可以接受的。
我们还可以通过设置clusters=
或annotation_col=
来显示每个细胞的其他metadata信息。这在检查潜在的批次效应、条件之间的细胞类型组成差异、与非监督分析的聚类的关系等方面有时很有用。在下面的代码中,我们显示每个细胞来自哪个供体:
plotScoreHeatmap(pred.grun,
annotation_col=as.data.frame(colData(sceG)[,"donor",drop=FALSE]))
4.2 Based on the deltas across cells
pruneScores()
函数将删除潜在的质量不佳或不明确的分配。具体地说,基于每个细胞的“增量”(“delta”)(即,每个细胞的所有标签上的已分配标签的分数和中位数之间的差异)来识别模糊分配。低增量表示赋值不确定,如果引用中不存在细胞的真实标签,则这一点尤其相关。使用基于离群值的方法来识别用于修剪的确切阈值,该方法考虑了不同数据集中的相关性规模的差异。
to.remove <- pruneScores(pred.grun)
summary(to.remove)
#> Mode FALSE TRUE
#> logical 96 4
默认情况下,SingleR()
将在pruned.labels
字段中报告已删除的标签,在该字段中,低质量的分配将替换为NA
。但是,默认修剪阈值可能并不适用于每个数据集-有关更详细的讨论,请参阅?pruneScores
。我们提供了plotScoreDistribution()
来帮助确定阈值是否合适,方法是跨具有相同标签的细胞使用信息。这显示了跨细胞的增量的每标签分布,根据该分布,pruneScores()
将适当的阈值定义为均值以下的3个中位值绝对偏差(MAD)。
plotScoreDistribution(pred.grun, show = "delta.med", ncol = 3, show.nmads = 3)
如果必须调整某些调优参数,我们只需使用调整后的参数直接调用pruneScores()
即可。这里,如果要丢弃标签,我们将其设置为NA
,这也是SingleR()
在pruned.labels
中标记此类标签的方式。
new.pruned <- pred.grun$labels
new.pruned[pruneScores(pred.grun, nmads=5)] <- NA
table(new.pruned, useNA="always")
#> new.pruned
#> acinar beta delta duct endothelial <NA>
#> 53 4 1 41 1 0
4.3 Based on marker gene expression
另一个简单而有效的诊断是检查测试数据集中每个标签的标记基因的表达。我们从SingleR()
结果的元数据中提取标记的标识,并在scater
的plotHeatmap()
函数中使用它们,如下所示的beta
细胞标记。如果测试数据集中的一个细胞被确信地分配给了一个特定的标签,我们会期望它具有该标签的标记的强表达。至少,它应该表现出相对于分配给其他标签的细胞的那些标记的上调。
all.markers <- metadata(pred.grun)$de.genes
sceG$labels <- pred.grun$labels
# Beta cell-related markers
plotHeatmap(sceG, order_columns_by="labels",
features=unique(unlist(all.markers$beta)))
通过将此代码包装在循环中,我们可以对所有标签执行类似的操作,如下所示:
for (lab in unique(pred.grun$labels)) {
plotHeatmap(sceG, order_columns_by=list(I(pred.grun$labels)),
features=unique(unlist(all.markers[[lab]])))
}
热图特别有用,因为它们允许用户检查这些基因是否对该细胞类型的身份具有生物学意义。例如,预计β细胞会表达胰岛素,而它们这样做的事实给分配的正确性带来了更多的信心。相比之下,分数和增量更抽象,更难解释以用于诊断目的。如果识别出的分数没有意义,或者没有持续不断地上调,那么就有理由对数据的质量持怀疑态度。
5 Available references
legacy SingleR package提供包含归一化表达值和基于bulk RNA-seq, microarray和single-cell RNA-seq数据的细胞类型标签的RDA文件,这些数据来自:
- Blueprint (Martens and Stunnenberg 2013) and Encode (The ENCODE Project Consortium 2012),
- the Human Primary Cell Atlas (Mabbott et al. 2013),
- the murine ImmGen (Heng et al. 2008), and
- a collection of mouse data sets downloaded from GEO (Benayoun et al. 2019).
前三个参考数据集的bulk RNA-seq 和 microarray数据集是从预先分选的细胞群体中获得的,即这些样本的细胞标记大多是基于各自的分选/纯化策略而不是通过电子预测(in silico prediction)方法导出的。
还准备了来自bulk RNA-seq 和免疫细胞微阵列数据的另外三个参考数据集。这些数据集中的每一个也是从预先分类的细胞群体中获得的:
- The Database for Immune Cell Expression(/eQTLs/Epigenomics) (Schmiedel et al. 2018),
- Novershtern Hematopoietic Cell Data - GSE24759 - formerly known as Differentiation Map (Novershtern et al. 2011), and
- Monaco Immune Cell Data - GSE107011 (Monaco et al. 2019).
每个数据集的特征汇总如下:
image.png
每个数据集的详细信息可以在其检索功能的相应帮助页面上查看 (e.g., ?ImmGenData)。可以在下面的可折叠部分中查看每个集合中的可用样本类型。每个数据集中的细胞类型也被手动映射到Cell Ontology,后者为跨研究的标签比较提供了标准化的词汇表。
image.png
6 Reference options
6.1 Pseudo-bulk aggregation
单细胞参考数据集提供了与我们的测试数据集相似的比较,从而对后者中的细胞进行了更准确的分类(希望如此)。然而,与bulk引用相比,单细胞引用中的样本通常要多得多,这增加了分类所涉及的计算工作。我们通过将细胞聚类到每个标签的一个“pseudo-bulk”样本中来避免这种情况(例如,通过对对数表达式值进行平均),并使用这些样本作为引用,这允许我们获得与使用bulk引用(bulk references)相同的效率。
这种方法的明显代价是我们丢弃了关于每个标签内的细胞分布的潜在有用信息。如果属于异类种群的细胞远离种群中心,则可能不会被正确分配。我们试图通过在每个细胞内使用k-Means聚类来创建表示表达式空间的特定区域(即,矢量量化)的伪批量样本来保存某些信息。在给定具有个细胞的标签的情况下,我们创建个clusters,这在减少计算工作量和保持标签的内部分布之间提供了一个合理的折衷。
此聚合方法在aggregateReferences
函数中实现,该函数如下面Muraro et al. (2016) 数据集操作所示。该函数返回一个包含pseudo-bulk表达配置文件和相应标签的SummarizedExperiment
对象。
set.seed(100) # for the k-means step.
aggr <- aggregateReference(sceM, labels=sceM$label)
aggr
#> class: SummarizedExperiment
#> dim: 19059 116
#> metadata(0):
#> assays(1): logcounts
#> rownames(19059): A1BG-AS1__chr19 A1BG__chr19 ... ZZEF1__chr17
#> ZZZ3__chr1
#> rowData names(0):
#> colnames(116): alpha.1 alpha.2 ... mesenchymal.8 epsilon.1
#> colData names(1): label
然后,可以在SingleR()
中将生成的SummarizedExperiment
用作参考。
pred.aggr <- SingleR(sceG, aggr, labels=aggr$label)
table(pred.aggr$labels)
#>
#> acinar beta delta duct
#> 52 4 1 43
6.2 Using multiple references
在某些情况下,我们可能希望使用多个引用来注释测试数据集。这产生了一组更全面的细胞类型,这些细胞类型没有被任何单独的参考所覆盖,特别是当还考虑到分辨率的差异时。只需将多个对象传递给SingleR()
中的ref=
和label=
参数,即可支持使用多个引用。下面我们通过在La Manno et al. (2016)等人的注释中包含另一个引用(来自Blueprint-Encode)进行演示数据集:
bp.se <- BlueprintEncodeData()
pred.combined <- SingleR(test = hESCs,
ref = list(BP=bp.se, HPCA=hpca.se),
labels = list(bp.se$label.main, hpca.se$label.main))
输出与前面描述的形式相同,我们可以轻松访问组合的标签集:
table(pred.combined$labels)
#>
#> Astrocyte Neuroepithelial_cell Neurons
#> 4 63 33
我们的策略是分别对每个引用执行注释,然后跨引用采用得分最高的标签。这为组合来自多个引用的信息提供了一种轻量级的方法,同时避免了批次效应和预先协调的需要。(当然,这种方法的主要实际困难是相同的细胞类型在引用之间可能有不同的标签,这将需要在解释过程中进行一些隐式协调)。关于选择这种方法背后的理由的进一步评论可以在?"combine-predictions"
中找到。
6.3 Harmonizing labels
matchReferences()
函数的作用是:为两个引用之间的标签协调提供一种简单而优雅的方法。每个引用被用来注释另一个,并且计算每对标签之间相互分配的概率。接近于1概率表示在该对标签之间存在1:1的关系;另一方面,全零概率向量表示标签对于特定引用是唯一的。
matched <- matchReferences(bp.se, hpca.se,
bp.se$label.main, hpca.se$label.main)
pheatmap::pheatmap(matched, col=viridis::plasma(100))
可以使用类似上面的热图来指导协调,以在表示相同细胞类型或状态的所有标签上强制使用一致的词汇表(vocabulary)。统一最明显的好处是简化了对结果的解释。然而,更重要的效果是,来自多个参考文献的协调标签的存在允许分类机器防止参考文献之间不相关的批次效应。例如,在SingleR()
的例子中,如果标记基因在多个引用中持续上调,那么它们就会受到青睐,从而提高了对任何测试数据集中的技术特性的robustness。
我们强调,鉴于生物体系和技术的差异带来的风险,在这一过程中仍然需要一些人工干预。例如,神经元被认为是每个参考独一无二的,而HPCA数据中的平滑肌细胞与Blueprint/ENCODE数据中的成纤维细胞错误匹配。CD4+和CD8+T细胞也都被分配给“T细胞”,所以这里需要一些关于协调标记的可接受分辨率的决定。
另外,我们还可以使用此函数来识别两个独立的scRNA-seq分析之间的匹配簇。这是一种“标签外(off-label)”使用,涉及将clusters分配替换为标签的代理。然后,我们可以匹配聚类并集成来自多个数据集的结论,而不需要考虑批次校正和重新聚类的困难。
7 Advanced use
7.1 Improving efficiency
高阶用户可以将SingleR()
工作流拆分为两个单独的训练和分类(training and classification)步骤。这意味着只需要执行一次训练(例如,标记检测、最近邻索引的组装)。然后,如果测试特征集与训练集中的特征相同或超集(superset),则可以在具有不同测试数据集的多个分类之间复用所得到的数据结构。例如:
common <- intersect(rownames(hESCs), rownames(hpca.se))
trained <- trainSingleR(hpca.se[common,], labels=hpca.se$label.main)
pred.hesc2 <- classifySingleR(hESCs[common,], trained)
table(pred.hesc$labels, pred.hesc2$labels)
#>
#> Astrocyte Neuroepithelial_cell Neurons
#> Astrocyte 14 0 0
#> Neuroepithelial_cell 0 81 0
#> Neurons 0 0 5
其他效率改进可以通过以下几个论点来实现:
- 通过
BiocNeighbors
包中的BNPARAM=
参数,在trainSingleR()
中切换到最近邻居搜索的近似算法。 - 使用
BiocParallel
包中的BPPARAM=
参数并行classifySingleR()
中的微调(ine-tuning)步骤。
这些参数也可以在SingleR()
命令中指定。
7.2 Defining custom markers
用户还可以使用任何 DE testing machinery构建自己的标记列表。例如,我们可以使用scran中的方法执行配对t检验(pairwise t-tests),并从每个配对比较中获得前10个标记基因。
library(scran)
out <- pairwiseTTests(logcounts(sceM), sceM$label, direction="up")
markers <- getTopMarkers(out$statistics, out$pairs, n=10)
然后,我们通过genes=
参数将这些基因直接提供给SingleR()
。与默认方法相比,更集中的基因集还允许更快地执行注释。
pred.grun2 <- SingleR(test=sceG, ref=sceM, labels=sceM$label, genes=markers)
table(pred.grun2$labels)
#>
#> acinar beta delta duct pp unclear
#> 59 4 1 34 1 1
在某些情况下,标记可能只对特定标签可用,而不能用于标签之间的成对比较。这是通过向基因提供命名的字符载体列表来实现的。请注意,这可能不如list-of-lists方法强大,因为有关成对差异的信息会被丢弃。
label.markers <- lapply(markers, unlist, recursive=FALSE)
pred.grun3 <- SingleR(test=sceG, ref=sceM, labels=sceM$label, genes=label.markers)
table(pred.grun$labels, pred.grun3$labels)
#>
#> acinar beta delta duct pp
#> acinar 51 0 0 2 0
#> beta 0 4 0 0 0
#> delta 0 0 1 0 0
#> duct 2 0 0 39 0
#> endothelial 0 0 0 0 1
8 FAQs
如何将Seurat
, SingleCellExperiment
或cell_data_set
对象一起使用?
SingleR
与工作流无关 - 它所需要的只是标准化的计数(normalized counts)。README文件中提供了一个示例,说明如何将其结果映射回常见的单细胞数据对象。
在哪里可以找到适合我的数据的参考数据集?
scRNAseq
包含许多单细胞数据集,并且还在不断增加。ArrayExpress
和GEOquery
可分别用于下载ArrayExpress或GEO中的任何bulk or single-cell数据集。
9 Session information
sessionInfo()
#> R version 3.6.1 (2019-07-05)
#> Platform: x86_64-apple-darwin15.6.0 (64-bit)
#> Running under: macOS High Sierra 10.13.6
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/3.6/Resources/lib/libRlapack.dylib
#>
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> attached base packages:
#> [1] parallel stats4 stats graphics grDevices utils datasets
#> [8] methods base
#>
#> other attached packages:
#> [1] scran_1.14.6 scater_1.14.1
#> [3] ggplot2_3.3.1 scRNAseq_1.99.8
#> [5] SingleCellExperiment_1.8.0 SingleR_1.0.6
#> [7] SummarizedExperiment_1.16.0 DelayedArray_0.12.0
#> [9] BiocParallel_1.20.0 matrixStats_0.56.0
#> [11] Biobase_2.46.0 GenomicRanges_1.38.0
#> [13] GenomeInfoDb_1.22.0 IRanges_2.20.1
#> [15] S4Vectors_0.24.0 BiocGenerics_0.32.0
#> [17] BiocStyle_2.14.0
#>
#> loaded via a namespace (and not attached):
#> [1] bitops_1.0-6 bit64_0.9-7
#> [3] RColorBrewer_1.1-2 httr_1.4.1
#> [5] tools_3.6.1 R6_2.4.1
#> [7] irlba_2.3.3 vipor_0.4.5
#> [9] DBI_1.1.0 colorspace_1.4-1
#> [11] withr_2.2.0 tidyselect_1.1.0
#> [13] gridExtra_2.3 bit_1.1-15.2
#> [15] curl_4.3 compiler_3.6.1
#> [17] BiocNeighbors_1.4.1 labeling_0.3
#> [19] scales_1.1.1 rappdirs_0.3.1
#> [21] stringr_1.4.0 digest_0.6.25
#> [23] rmarkdown_2.2 XVector_0.26.0
#> [25] pkgconfig_2.0.3 htmltools_0.4.0
#> [27] limma_3.42.2 dbplyr_1.4.4
#> [29] fastmap_1.0.1 rlang_0.4.6
#> [31] RSQLite_2.2.0 shiny_1.4.0.2
#> [33] DelayedMatrixStats_1.8.0 farver_2.0.3
#> [35] generics_0.0.2 dplyr_1.0.0
#> [37] RCurl_1.98-1.2 magrittr_1.5
#> [39] BiocSingular_1.2.0 GenomeInfoDbData_1.2.2
#> [41] Matrix_1.2-18 Rcpp_1.0.4
#> [43] ggbeeswarm_0.6.0 munsell_0.5.0
#> [45] viridis_0.5.1 lifecycle_0.2.0
#> [47] edgeR_3.28.0 stringi_1.4.6
#> [49] yaml_2.2.1 zlibbioc_1.32.0
#> [51] BiocFileCache_1.10.0 AnnotationHub_2.18.0
#> [53] grid_3.6.1 blob_1.2.1
#> [55] promises_1.1.0 dqrng_0.2.1
#> [57] ExperimentHub_1.12.0 crayon_1.3.4
#> [59] lattice_0.20-41 locfit_1.5-9.4
#> [61] knitr_1.28 pillar_1.4.4
#> [63] igraph_1.2.5 glue_1.4.1
#> [65] BiocVersion_3.10.1 evaluate_0.14
#> [67] BiocManager_1.30.10 vctrs_0.3.1
#> [69] httpuv_1.5.4 gtable_0.3.0
#> [71] purrr_0.3.4 assertthat_0.2.1
#> [73] xfun_0.14 rsvd_1.0.3
#> [75] mime_0.9 xtable_1.8-4
#> [77] later_1.1.0.1 viridisLite_0.3.0
#> [79] pheatmap_1.0.12 tibble_3.0.1
#> [81] AnnotationDbi_1.48.0 beeswarm_0.2.3
#> [83] memoise_1.1.0 statmod_1.4.34
#> [85] ellipsis_0.3.1 interactiveDisplayBase_1.24.0