内容

1介绍

pipeComp是一个简单的框架,便于管道涉及各个步骤和参数的比较。最初开发基准单细胞RNA序列(scRNAseq)管道:

pipeComp,一般计算管道的评价框架,揭示了高性能单细胞RNA-seq预处理工具
Pierre-Luc日尔曼,安东尼Sonrel &马克·D·罗宾逊基因组生物学2020年,doi:10.1186 / s13059 - 020 - 02136 - 7

然而,框架可以应用于任何其他上下文。这个描述介绍了包和框架;信息关于scRNAseq管道和评估指标,看到pipeComp_scRNA装饰图案。对于一个完全不同的实例,介绍了创建一个新的PipelineDefinition,请参阅pipeComp_dea装饰图案。

2安装

安装使用:

BiocManager:安装(“身为/ pipeComp”)

因为pipeComp是一般管道基准测试框架,我们试图限制包的依赖降到最低。使用scRNA-seq管道和包装,但是,需要进一步包安装。检查是否满足了这些依赖关系对于一个给定的PipelineDefinition和选择,明白了checkPipelinePackages ?



3pipeComp概述

PipeComp和PipelineDefinition的概述

图1:PipeComp和PipelineDefinition的概述

pipeComp是建立在S4类PipelineDefinition它定义了一个基本的抽象工作流不同步骤(这可以拥有任意数量的参数,包括子程序),如图1所示。执行管道时,每一步都是连续应用到一个对象开始。重要的是,函数的步骤相关的具体方法,但应该是通用的,而通过比较方法参数(如管道分开包装器函数定义的名称)。通常,阶跃函数将应用包装器对象,没有更多。此外,每一步可以评价函数,以一步的输出作为输入,输出评价指标。最后,函数可以指定聚合这些指标跨多个数据集(以防evalation输出不是data.frame data.frames或列表)。

运行一个基准除了需要一组选择的值的参数。例如,参数选择值描绘在图1中可以定义如下:

库(pipeComp)替代< -列表(par1 = c (“function_A”、“function_B”), par2 = 1:3, par3 = TRUE, #……parN = c (10、25、50))

每个参数(列表)的位置可以任意数量的替代标量值(如字符、数字、逻辑)。函数的名称,等等function_Afunction_B(这应该加载环境中),如果能获得通过PipelineDefinition允许它。这意味着应该创建包装器的不同方法,和包装器函数的名称作为替代参数值传递。

给定一个PipelineDefinition,一个替代参数和基准数据集列表,列表runPipeline(图1 b)函数通过所有的组合参数,避免再计算相同的步骤(使用相同的参数)两次,编译动态评估,以避免潜在的巨大的中间数据存储:

res < - runPipeline(数据集,选择,pipelineDef = PipelineDefinition)

聚合评价指标为每个参数的组合,以及计算时间,返回如下结构:年代

除了(聚合)返回的输出函数,runPipeline会产生至少一个RDS文件(保存根据output.prefix参数)每个数据集* .evaluation.rds包含(非聚集)评估结果在每一步,虽然.endOutputs.rds文件(假设saveEndResults = TRUE)包含每个组合的最终输出(即最后一个步骤的输出)。

pipeComp包包括一个PipelineDefinition单细胞测序RNA (scRNAseq)数据。关于这个应用程序的更多信息和示例的输出,看到pipeComp_scRNA装饰图案。



3.1只运行组合的一个子集

而不是运行参数的所有可能的组合,可以只运行他们的一个子集梳子参数的runPipeline。参数接受一个矩阵的参数指标)或data.frame(因素),可以手动构建的,但是最简单的方法是首先创建组合,然后去掉无用的:

梳子< - buildCombMatrix(替代品)头(梳理)
# # 1 # # par1 par2 par3 parN function_A 1真的10 # # 2 function_A 1真的25 # # 3 function_A 1真的50 # # 4 function_A 2真的10 # # 5 function_A 2真的25 # # 6 function_A 2真的50

然后我们可以删除一些之前传递的参数组合runPipeline:

梳子< -梳子[(梳$ par1 ! =“function_A”|梳子par2美元= = 2),]res < - runPipeline(数据集,选择,pipelineDef = PipelineDefinition nthreads = 3,梳梳)

3.2处理PipelineDefinition对象

3.2.1之上创建一个PipelineDefinition

PipelineDefinition最低限度,对象是一组函数连续执行前一个的输出,并可选地伴随着评估和聚合函数。一个简单的管道可以构造如下:

my_pip < - PipelineDefinition(列表(step1 = function (x, param1){#做x和param1 x},步骤2 = function (x, method1 param2){得到(method1) (x, param2) # method1适用于x,与param2},将发髻= function (x, param3) {x <——some_fancy_function (x, param3) #函数也可以输出评估通过“intermediate_return”槽:e < - my_evaluation_function (x)列表(x = x, intermediate_return = e)})) my_pip
# # PipelineDefinition对象有以下步骤:# # - step1 (x, param1) # # -步骤2 (x, method1 param2) # # -步骤3 (x, param3)

PipelineDefinition还可以包括每一步的描述或评价和聚合函数。例如:

my_pip < PipelineDefinition(列表(step1 = function (x, meth1) {(meth1) (x)},步骤2 = function (x, meth2){得到(meth2) (x)}),评价=列表(步骤2 =函数c (x)(平均=平均(x) max = max (x))),描述=列表(步骤1 =“这个步骤meth1适用于x”。步骤2 =“这个步骤meth2适用于x。”)) my_pip
# # PipelineDefinition对象有以下步骤:# # - step1 (x, meth1) # #这个步骤meth1适用于x。# # -步骤2 (x, meth2) * # #这个步骤meth2适用于x。

运行虚拟数据和功能:

数据集< -列表(ds1 = 1:3, ds2 = c(5、10、15))替代< -列表(meth1 = c(“日志”、“√”),meth2 =“cumsum”) tmpdir1 < - paste0 (tempdir (),“/”) res < - runPipeline(数据集,选择、my_pip output.prefix = tmpdir1)
# # 2的数据集上运行2管道设置使用1线程
# # # #完成运行在所有的数据集
# # # #聚合结果……
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的
# #聚合评价结果为:步骤2
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的
res评价步骤2美元
# #数据集meth1 meth2意味着马克斯# # 1 ds1日志cumsum 0.8283022 - 1.791759 # # 2 ds1 sqrt cumsum 2.5201593 - 4.146264 # # 3 ds2日志cumsum 4.0471780 - 6.620073 # # 4 ds2 sqrt cumsum 5.6352475 - 9.271329

可以通过计算时间res美元运行;他们可以访问每个组合的管道总,或步进式的方式。他们也可以绘制使用plotElapsed(见下文)。评价结果可以通过访问res评估美元和策划evalHeatmap(见下文)。

3.2.2操纵一个PipelineDefinition

实现一些通用的方法PipelineDefinition对象,包括显示,的名字,长度,(,as.list。这意味着,例如,一个步骤可以从管道在以下方式:

my_pip [1]
# # PipelineDefinition对象有以下步骤:# # -步骤2 (x, meth2) * # #这个步骤meth2适用于x。

步骤可以添加使用addPipelineStep功能:

pip2 < - addPipelineStep (my_pip, name =“newstep”=“步骤1”)pip2
# # PipelineDefinition对象有以下步骤:# # - step1 (x, meth1) # #这个步骤meth1适用于x。# # - newstep (x) # # -步骤2 (x, meth2) * # #这个步骤meth2适用于x。

函数可以通过指定的新一步的观点addPipelineStep或之后通过stepFn:

stepFn (pip2、“newstep”、类型=“函数”)< -函数(x, newparam) {do_something (x, newparam)} pip2
# # PipelineDefinition对象有以下步骤:# # - step1 (x, meth1) # #这个步骤meth1适用于x。# # - newstep (x, newparam) # # -步骤2 (x, meth2) * # #这个步骤meth2适用于x。

最后,参数()方法可以用来提取参数为每个步骤,和defaultArguments方法可以用来获取或设置默认参数。



3.3合并的结果不同runPipeline调用

之前的电话runPipeline为每个数据集产生一个评估文件:

列表。文件(tmpdir1模式=“评价\ \ .rds”)
# # res.ds1.evaluation [1]”。rds res.ds2.evaluation.rds”

他们的聚合可以反复阅读这些文件和手动调用aggregatePipelineResults:

ds < -列表。文件(tmpdir1模式= \ \”评价。rds”, full.names = TRUE)名称(ds) < - basename (ds) res1 < readPipelineResults (resfiles = ds) res < - aggregatePipelineResults (res1)
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的
# #聚合评价结果为:步骤2
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的

此外,不同的调用的结果runPipeline(有部分不同的数据集和/或参数组合)可以合并在一起,提供的PipelineDefinition是相同的。为了说明这一点,我们首先让另一个runPipeline电话使用稍微不同的替代参数值:

选择< -列表(meth1 = c (“log2”、“√”), meth2 =“cumsum”) tmpdir2 < - paste0 (tempdir (),“/”) res < - runPipeline(数据集,选择、my_pip output.prefix = tmpdir2)
# # 2的数据集上运行2管道设置使用1线程
# # # #完成运行在所有的数据集
# # # #聚合结果……
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的
# #聚合评价结果为:步骤2
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的

然后加载(非聚集)每次运行的结果文件,并将它们合并使用mergePipelineResults:

res1 < - readPipelineResults (tmpdir1)它< - readPipelineResults (tmpdir2) res < - mergePipelineResults (res1它)
# # # # $ res1 ds1 ds2 # # 2 2 # # # # $它# # ds1 ds2 # # 2 2 # # # # $ # #合并ds1 ds2 # # 2 2

我们可以聚合结果做一个运行:

res < - aggregatePipelineResults (res)
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的
# #聚合评价结果为:步骤2
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的
res评价步骤2美元
# #数据集meth1 meth2意味着马克斯# # 1 ds1 log2 cumsum 1.194988 - 2.584963 # # 2 ds1 sqrt cumsum 2.520159 - 4.146264 # # 3 ds2 log2 cumsum 5.838844 - 9.550747 # # 4 ds2 sqrt cumsum 5.635248 - 9.271329



3.4处理错误

3.4.1调试

错误通常来自包装方法,并从内部调试runPipeline可以通过多线程很复杂。因为这个原因runPipeline包装在错误消息的附加信息。这将是一个错误报告的例子:

误差与参数:数据集的mydataset filt =宽大,规范=常态。测试中,k = 20步“正常化”,评估命令:“pipDef[[“正常化”]](x = x,规范=“norm.test”)的错误:错误得到(规范)(x):没有足够的细胞!

出错的数据集,管道报告步骤和具体的参数,使您试图重复错误外,更容易调试。

3.4.2跳过错误和修复它们

一个有用的行为runPipeline继续当遇到错误,所以成功的结果是不会丢失。这种行为可以启用的skipErrors = TRUE论点。我们可以说明这个哑管道上方,通过添加另一个必然会产生一个错误:

脆弱的。有趣的< -函数(x){如果(任何(x > 10))停止(“太大了!”)2 x ^}替代美元meth1 < - c(替代meth1美元,“fragile.fun”) res < - runPipeline(数据集,选择、my_pip、输出。前缀= tmpdir1 skipErrors = TRUE)
# # 2的数据集上运行3管道设置使用1线程
# #误差与参数数据集的ds2: # # meth1 =脆弱。有趣,meth2 = cumsum # #在步骤“步骤1”中,评估命令:# #“pipDef[[“步骤1”]](x = x, meth1 =“fragile.fun”)“# #错误:# #得到误差(meth1) (x):太大!
# # # #完成运行在所有的数据集
# # # #在运行中遇到的一些错误:
数据集# # # 1步ds2 meth1 = fragile.fun
# #所有结果保存,但只有那些分析成功的所有数据将被保留为聚合。
# # # #聚合结果……
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的
# #聚合评价结果为:步骤2
# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的# #警告type.convert.default (y[[我]]):”。“应该调用者指定的# #;使用真正的

显示的错误消息,只有成功的所有数据集分析聚合:

res评价步骤2美元
# #数据集meth1 meth2意味着马克斯# # 1 ds1 log2 cumsum 1.194988 - 2.584963 # # 2 ds1 sqrt cumsum 2.520159 - 4.146264 # # 3 ds2 log2 cumsum 5.838844 - 9.550747 # # 4 ds2 sqrt cumsum 5.635248 - 9.271329

然而,所有成功的结果(例如,包括“脆弱。有趣”的ds1”)保存在非聚合文件。这意味着一个可以纠正有问题的功能,重新运行失败的分析(即只在“ds2”在这种情况下),并合并结果与第一批mergePipelineResults ?)。



3.5策划的结果

pipeComp有两个通用绘图函数可以用于任何PipelineDefinition:evalHeatmapplotElapsed。此外,该计划包括pipeline-specific绘图函数(参见pipeComp_scRNApipeComp_dea小插曲)。

3.5.1运行时间

可以策划与运行时间plotElapsed功能:

plotElapsed (res agg.by = FALSE)

在本例中,我们显示所有测试组合,但在大多数情况下agg.by参数将用于聚合结果感兴趣的参数。

评价结果可以通过策划evalHeatmap功能:

evalHeatmap (res, = c(“的意思是”,“马克斯”))

默认情况下,热图打印实际的度量值,而颜色映射到相应的数据。具体地说,pipeComp颜色映射到√(签署的数量(matrix-wise)(列)的平均绝对偏差值。我们发现这个映射是特别有用,因为不同的颜色在数据集有类似的意义,以及颜色不是主要捕获异常值或基线数据集之间的差异。这种行为可以改变的规模函数的参数。对于更复杂的例子evalHeatmap,看到它的用法pipeComp_scRNA装饰图案,或参考函数的帮助。



更复杂的,“现实”的创建的示例PipelineDefinition,请参阅pipeComp_dea装饰图案。评价输出的一个复杂的例子,请参阅pipeComp_scRNA装饰图案。