既然我们知道了如何编写工作流,我们就可以开始利用ScatterFeatureRequirement了。该特性告诉运行程序,您希望在输入列表上多次运行工具或工作流。然后,工作流将输入作为数组,并将对数组中的每个元素运行指定的步骤,就像它是单个输入一样。这允许您在多个输入上运行相同的工作流,而不必生成许多不同的命令或输入yaml文件。
requirements:
ScatterFeatureRequirement: {}
新用户可能想要使用scatter的最常见原因是对不同的样本执行相同的分析。让我们从一个简单的工作流开始,调用我们的第一个示例,并接受一个字符串数组作为工作流的输入:
scatter-workflow.cwl
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: Workflow
requirements:
ScatterFeatureRequirement: {}
inputs:
message_array: string[]
steps:
echo:
run: 1st-tool.cwl
scatter: message
in:
message: message_array
out: []
outputs: []
除了包括ScatterFeatureRequirement在内的requirements部分,这里发生了什么?
首先,注意这里的主要工作流级别输入需要一个字符串数组。
inputs:
message_array: string[]
在这里,我们向step echo添加了一个名为scatter的新字段。这个字段告诉跑步者,我们想要为这个特定的步骤分散输入。注意,在scatter之后列出的输入名是步骤的输入之一,而不是工作流级别的输入。
steps:
echo:
run: 1st-tool.cwl
scatter: message
in:
message: message_array
out: []
对于我们的第一次散播,它就这么简单!由于我们的工具不收集任何输出,我们仍然在工作流中使用outputs:[],但如果你希望工作流的最终输出现在有多个输出需要收集,请确保将其更新为数组类型!
使用以下输入文件:
scatter-job.yml
message_array:
- Hello world!
- Hola mundo!
- Bonjour le monde!
- Hallo welt!
提醒一下,1st-tool.cwl只是在消息上调用命令echo。如果我们调用cwl-runner scatter-workflow.cwl scatter-job.yml命令行:
$ cwl-runner scatter-workflow.cwl scatter-job.yml
[workflow scatter-workflow.cwl] start
[step echo] start
[job echo] /tmp/tmp0hqmg400$ echo \
'Hello world!'
Hello world!
[job echo] completed success
[step echo] start
[job echo_2] /tmp/tmpu65_m1zw$ echo \
'Hola mundo!'
Hola mundo!
[job echo_2] completed success
[step echo] start
[job echo_3] /tmp/tmp5cs7a2wh$ echo \
'Bonjour le monde!'
Bonjour le monde!
[job echo_3] completed success
[step echo] start
[job echo_4] /tmp/tmp301wo7p8$ echo \
'Hallo welt!'
Hallo welt!
[job echo_4] completed success
[step echo] completed success
[workflow scatter-workflow.cwl] completed success
{}
Final process status is success
您可以看到,工作流对messagearray的每个元素调用了多次echo。好的,那么如果我们想在一个工作流中分散执行两个步骤呢?
让我们像上面那样执行一个简单的回显,但是通过添加以下行来捕获stdout,而不是添加输出
_1st-tool-mod.cwl
outputs:
echo_out:
type: stdout
并添加第二个步骤,该步骤使用wc计算每个文件中的字符数。见下面的工具:
wc-tool.cwl
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: CommandLineTool
baseCommand: wc
arguments: ["-c"]
inputs:
input_file:
type: File
inputBinding:
position: 1
outputs: []
现在,我们如何结合散射?记住散射场在每一步下面:
scatter-two-steps.cwl
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: Workflow
requirements:
ScatterFeatureRequirement: {}
inputs:
message_array: string[]
steps:
echo:
run: 1st-tool-mod.cwl
scatter: message
in:
message: message_array
out: [echo_out]
wc:
run: wc-tool.cwl
scatter: input_file
in:
input_file: echo/echo_out
out: []
outputs: []
在这里,我们在每个步骤下都放置了scatter。对于这个示例来说,这很好,因为它运行得很快,但是如果您正在为一个更复杂的工作流运行许多示例,那么您可能希望考虑另一种选择。在这里,我们在每个步骤上独立运行scatter,但由于第二步并不依赖于完成所有语言的第一步,所以我们没有有效地使用scatter功能。第二步需要一个数组作为第一步的输入,所以它会一直等到第一步中的所有内容都完成之后才开始执行任何操作。假装回声你好世界!执行需要1分钟,输出上的wc -c需要3分钟,并返回Hallo welt!执行需要5分钟,输出的wc需要3分钟。即使echo Hello World!可以在4分钟内完成,实际上它将在8分钟内完成,因为第一步必须等待echo Hallo welt!你可以看到这可能无法很好地扩展。
好,那么我们如何分散在可以独立于其他样本进行的步骤上呢?记住在第21章中,我们可以把整个工作流变成另一个工作流中的一个简单步骤!将我们的两步工作流转换为单步子工作流:
scatter-nested-workflow.cwl
#!/usr/bin/env cwl-runner
cwlVersion: v1.0
class: Workflow
requirements:
ScatterFeatureRequirement: {}
SubworkflowFeatureRequirement: {}
inputs:
message_array: string[]
steps:
subworkflow:
run:
class: Workflow
inputs:
message: string
outputs: []
steps:
echo:
run: 1st-tool-mod.cwl
in:
message: message
out: [echo_out]
wc:
run: wc-tool.cwl
in:
input_file: echo/echo_out
out: []
scatter: message
in:
message: message_array
out: []
outputs: []
现在分散作用于单个步骤,但该步骤包含两个步骤,因此每个步骤都是并行执行的。