美文网首页
Common Workflow Language [五]

Common Workflow Language [五]

作者: 生信师姐 | 来源:发表于2020-07-22 10:59 被阅读0次

二十一 嵌套工作流

问题:如何将多个工作流连接在一起?

目标:了解如何从多个CWL工作流构造嵌套工作流。

工作流是组合多个工具以执行更大操作的方法。我们还可以将工作流视为工具本身;如果工作流引擎支持SubworkflowFeatureRequirement,则CWL工作流可以用作另一个CWL工作流中的一个步骤:

requirements:
  SubworkflowFeatureRequirement: {}

下面是一个使用我们的1st-workflow.cwl作为嵌套工作流:

nestedworkflows.cwl

#!/usr/bin/env cwl-runner

cwlVersion: v1.0
class: Workflow

inputs: []

outputs:
  classout:
    type: File
    outputSource: compile/compiled_class

requirements:
  SubworkflowFeatureRequirement: {}

steps:
  compile:
    run: 1st-workflow.cwl
    in:
      tarball: create-tar/tar_compressed_java_file
      name_of_file_to_extract:
        default: "Hello.java"
    out: [compiled_class]

  create-tar:
    in: []
    out: [tar_compressed_java_file]
    run:
      class: CommandLineTool
      requirements:
        InitialWorkDirRequirement:
          listing:
            - entryname: Hello.java
              entry: |
                public class Hello {
                  public static void main(String[] argv) {
                      System.out.println("Hello from Java");
                  }
                }
      inputs: []
      baseCommand: [tar, --create, --file=hello.tar, Hello.java]
      outputs:
        tar_compressed_java_file:
          type: File
          streamable: true
          outputBinding:
            glob: "hello.tar"

compile步骤看工作流和内部工作流的可视化

这两个步骤的工作流从create-tar步骤开始,该步骤连接到橙色的compile 步骤;compile 是另一个工作流。我们看到紫色的固定的字符串"Hello.java" 被提供为name_of_file_to_extract

图片.png
图片.png

CWLWorkflow可以作为一个step使用,就像CommandLineTool一样,它的CWL文件包含在run中。然后,可以将工作流输入(inpex)和输出(classout)映射为步骤的输入/输出。

  compile:
    run: 1st-workflow.cwl
    in:
      inp:
        source: create-tar/tar
      ex:
        default: "Hello.java"
    out: [classout]

我们的1st-workflow.cwl是用工作流输入参数化的,所以在运行它时,我们必须提供一个作业文件来表示tar文件和*.java文件名。这通常是最佳实践,因为这意味着它可以在多个父工作流中重用,甚至可以在同一工作流中的多个步骤中重用。

这里我们使用default:'来硬编码"Hello.java" 作为ex输入,但是我们的工作流还需要在inp处有一个tar文件,我们将在create-tar步骤中准备该文件。此时,重构1st-workflow.cwl以拥有更具体的输入/输出名称可能是一个好主意,因为这些名称也出现在它作为工具的使用中。

也可以使用不太通用的方法,避免作业文件中的外部依赖关系。因此,在这个工作流中,我们可以在将其添加到tar文件之前,使用前面提到的InitialWorkDirRequirement生成一个硬编码Hello.java文件。

  create-tar:
    requirements:
      InitialWorkDirRequirement:
        listing:
          - entryname: Hello.java
            entry: |
              public class Hello {
                public static void main(String[] argv) {
                    System.out.println("Hello from Java");
                }
              }

在这种情况下,我们可以假设Hello.java而不是参数化,因此只要CWL工作流引擎支持ShellCommandRequirement,我们就可以使用更简单的arguments形式:

  run:
    class: CommandLineTool
    requirements:
      ShellCommandRequirement: {}
    arguments:
      - shellQuote: false
        valueFrom: >
          tar cf hello.tar Hello.java

注意:这里使用了shellQuote: false,否则shell将尝试执行带引号的二进制文件"tar cf hello.tar Hello.java"

这里的>块意味着新行被剥离,因此可以在多行上编写单个命令。类似地,我们上面使用的|将保留换行符,结合ShellCommandRequirement,这将允许嵌入一个shell脚本。但是,在CWL中应该谨慎地使用Shell命令,因为这意味着您“跳出”工作流,不再获得可重用的组件、出处或可伸缩性。为了重现性和可移植性,建议只将shell命令与DockerRequirement 的提示(hint)一起使用,以便命令在可预测的shell环境中执行。

您是否注意到我们没有将tar cf工具拆分到单独的文件中,而是将其嵌入到CWL工作流文件中?这通常不是最佳实践,因为该工具无法重用。在这种情况下这样做的原因是命令行是硬编码的,文件名只在这个工作流中有意义。

在这个例子中,我们必须在外部准备一个tar文件,但这仅仅是因为我们的内部工作流被设计成将其作为输入。内部工作流的一个更好的重构方法是获取一个Java文件列表进行编译,这将简化它在其他工作流中作为工具步骤的使用。

嵌套工作流在生成高级功能和可重用工作流单元方面是非常强大的,但就像创建CWL工具描述一样,必须注意提高其在多个工作流中的可用性。

总结

  • 如果工作流引擎支持SubworkflowFeatureRequirement,则可以将一个工作流用作另一个工作流中的一个步骤。
  • 工作流在steps下指定,工作流程的描述文件作为 run 字段value的值提供。
  • 使用default指定字段的默认值,该值可以被输入对象中的值覆盖。
  • 使用 > 可忽略拆分为多行的长命令中的换行符。

二十二 Scattering Workflows

问题:如何并行运行工具或工作流?

既然我们知道了如何编写工作流,就可以开始使用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: []

除了requirements部分,包括ScatterFeatureRequirement,这里发生了什么?

inputs:
  message_array: string[]

首先,请注意,这里的主工作流级别的输入需要一个字符串数组。

steps:
  echo:
    run: 1st-tool.cwl
    scatter: message
    in:
      message: message_array
    out: []

这里我们在步骤echo中添加了一个名为scatter的新字段。这个字段告诉运行程序,在这个特定步骤中,我们希望分裂输入。请注意,分裂之后列出的输入名称是步骤的输入之一,而不是工作流级别的输入。

对于我们的第一次分裂,就这么简单!由于我们的工具不收集任何输出,所以我们在工作流中仍然使用outputs: [] ,但是如果希望工作流最终有多个输出要收集,请务必将其更新为数组类型!

Using the following input file:

scatter-job.yml

message_array: 
  - Hello world!
  - Hola mundo!
  - Bonjour le monde!
  - Hallo welt!

As a reminder, 1st-tool.cwl simply calls the command echo on a message. If we invoke cwl-runner scatter-workflow.cwl scatter-job.yml on the command line:

作为提醒,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

您可以看到,工作流对message_array的每个元素调用多次echo。那么,如果我们想分裂工作流中的两个步骤呢?

让我们像上面一样执行一个简单的echo,通过添加下面行而不是outputs: []来捕获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功能。第二步需要一个来自第一步的数组作为输入,所以它将等到第一步中的所有内容都完成之后再做任何事情。假设echo Hello World!需要1分钟来执行,wc -c的输出需要3分钟,echo Hallo welt! 执行需要5分钟,wc在该输出上需要3分钟。即使echo Hello World!本可以在4分钟内完成,但因为第一步必须等待 echo Hallo welt!,实际上8分钟内完成。

好的,那么我们如何分散在可以独立于其他样本的步骤上呢?记住第21章,我们可以使整个工作流成为另一个工作流中的一个步骤!将我们的两步工作流转换为单步子工作流:

Ok, so how do we scatter on steps that can proceed independent of other samples? Remember from chapter 21, that we can make an entire workflow a single step in another workflow! Convert our two step workflow to a single step subworkflow:

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: []

Now the scatter acts on a single step, but that step consists of two steps so each step is performed in parallel.

Key Points

  • A workflow can scatter over an input array in a step of a workflow, if the workflow engine supports the ScatterFeatureRequirement.
  • The scatter field is specified for each step you want to scatter
  • The scatter field references the step level inputs, not the workflow inputs
  • Scatter runs on each step specified independently

相关文章

网友评论

      本文标题:Common Workflow Language [五]

      本文链接:https://www.haomeiwen.com/subject/iqabkktx.html