用户教程--Workflow

编写cwl工作流

问题:如何将多个工具连接成一个工作流呢?
目标:了解如何从多个 CWL 工具描述构建工作流。

所谓的工作流,是将多个工具按照相互间输入输出的依赖关系串接在一起以执行更大操作的方法。下面展示一个工作流例子1st-workflow.cwl,该工作流主要包含两个工具tar-param.cwlarguments.cwl,实现从tar包中提取一个java源文件,然后编译它。

1st-workflow.cwl

cwlVersion: v1.0
class: Workflow
inputs:
  tarball: File
  name_of_file_to_extract: string

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

steps:
  untar:
    run: tar-param.cwl
    in:
      tarfile: tarball
      extractfile: name_of_file_to_extract
    out: [extracted_file]

  compile:
    run: arguments.cwl
    in:
      src: untar/extracted_file
    out: [classfile]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

上述inputs定义了工作流的输入,包含tarball,name_of_file_to_extract两个变量,可以使用YAML或JSON对象来指定对应的值。例如:

1st-workflow.yml

tarball:
  class: File
  path: hello.tar
name_of_file_to_extract: Hello.java
1
2
3
4

此时,我们运行下述命令,便可实现对hello.tar文件的解压和编译了

sixbox run 1st-workflow.cwl 1st-workflow-job.yml
1

工作流每个模块拆解:
1)cwlVersion字段表示该文件所使用的CWL规范(此处为V1.0), 2)class字段表示此文档描述的是一个工作流。

cwlVersion: v1.0
class: Workflow
1
2

3)inputs部分描述了工作流的输入。这是一个输入参数列表,其中每个参数由一个标识符和一个数据类型组成。这些参数可用作特定工作流程步骤的输入。

inputs:
  tarball: File
  name_of_file_to_extract: string
1
2
3

4)outputs部分描述了工作流的输出。这是一个输出参数列表,compiled_class为输出标量标识符,type指定输出类型为File, outputSource指明该输出结果来自于compile步骤的输出结果 classfile

outputs:
  compiled_class:
    type: File
    outputSource: compile/classfile
1
2
3
4

5)steps部分描述了工作流的实际每一个步骤。在这个例子中,第一步untar从一个 tar 文件中提取一个文件,第二步compile使用 java 编译器编译第一步中的文件。

run指明两个步骤运行的cwl工具分别是tar-param.cwlarguments.cwl

in列出该步骤的输入参数,例如untar步骤的两个输入参数为tarfileextractfilecompile步骤为src

out列出了该步骤预期的输出参数。

在该例子中第二步compile取决于第一步untar的结果,可以通过将第二个步骤的输出src定义为untar/extracted_file,表示src来自untar步骤的输出extracted_file

此外,工作流步骤不一定按它们列出的顺序运行,而是由步骤之间的依赖关系决定的。此外,不相互依赖的工作流步骤可以并行运行。

steps:
  untar:
    run: tar-param.cwl
    in:
      tarfile: tarball
      extractfile: name_of_file_to_extract
    out: [extracted_file]
  compile:
    run: arguments.cwl
    in:
      src: untar/extracted_file
    out: [classfile]
1
2
3
4
5
6
7
8
9
10
11
12

嵌套工作流

问题:如何将多个工作流连接在一起?
目标:了解如何从多个 CWL 工作流描述构建嵌套工作流

工作流是组合多个工具的方法,其本身也可以看作为一个工具。CWL 工作流可以用作另一个 CWL 工作流中的一个步骤。此时需要指定 SubworkflowFeatureRequirement。

requirements:
  SubworkflowFeatureRequirement: {}
1
2

下面是一个嵌套工作流的示例
1st-workflow.cwl

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"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

该工作流包含两个步骤,create-tar步骤打包一个包含java源码的tar包,compile步骤解压tar包,并编译。可以看出,在此例中工作流1st-workflow.cwl可以像CommandLineTool一样被当成一个工具使用。

在create-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");
                }
              }
1
2
3
4
5
6
7
8
9
10
11

在这种情况下,我们可以使用更简单的arguments形式,只要 CWL 工作流引擎支持ShellCommandRequirement。

  run:
    class: CommandLineTool
    requirements:
      ShellCommandRequirement: {}
    arguments:
      - shellQuote: false
        valueFrom: >
          tar cf hello.tar Hello.java
1
2
3
4
5
6
7
8

注意shellQuote: false这里的使用,否则shell会将"tar cf hello.tar Hello.java"当成整个二进制文件来尝试执行。
这里的>块意味着换行符被剥离,因此可以在多行上编写单个命令。同样,|我们上面使用的将保留换行符。
在 CWL 中应谨慎使用 Shell 命令,因为这意味着您“跳出”了工作流程,不再具有可重用性和可扩展性。为了可重复性和可移植性,建议仅将 shell 命令与DockerRequirement提示一起使用,以便在预定好的 shell 环境中执行命令。 您是否注意到我们没有将tar cf工具拆分为单独的文件,而是将其嵌入到 CWL 工作流文件中?这通常不是最佳实践,因为该工具无法重复使用。在这种情况下这样做的原因是因为命令行是硬编码的,文件名仅在此工作流程中有意义。
嵌套工作流可以成为生成更高级别的功能性和可重用工作流单元的强大功能 - 但就像创建 CWL 工具描述一样,必须注意提高其在多个工作流中的可用性。

分散工作流

问题:如何并行运行工具或工作流?
目标:了解如何创建可以在输入列表上运行一个步骤的工作流。

前面我们已经知道如何编写工作流,我们可以开始使用ScatterFeatureRequirement. 此功能告诉运行器您希望在输入列表上多次运行工具或工作流。然后,工作流将输入作为数组,并将在数组的每个元素上运行指定的步骤,就好像它是单个输入一样。这允许您在多个输入上运行相同的工作流程,而无需生成许多不同的命令或输入 yaml 文件。

requirements:
  ScatterFeatureRequirement: {}
1
2

scatter 的最常见例子是对不同的样本执行相同的分析。让我们从一个简单的工作流开始,该工作流调用我们的第一个示例并将字符串数组作为工作流的输入:
scatter-workflow.cwl

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: []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

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

inputs:
  message_array: string[] 
1
2

在这里,我们向 echo步骤添加了一个新字段scatter。该字段告诉运行器,我们希望在此特定步骤的此输入上进行并行。请注意,在 scatter 之后列出的输入名称是步骤的输入之一,而不是工作流级别的输入。

steps:
  echo:
    run: 1st-tool.cwl
    scatter: message
    in:
      message: message_array
    out: []
1
2
3
4
5
6
7

这就是分散工作流的一个示例,就这么简单!由于我们的工具不收集任何输出,我们使用了outputs: [],但如果您希望工作流的最终输出现在有多个输出要收集,请确保也将其更新为数组类型!

使用以下输入YAML文件:
scatter-job.yml

message_array: 
  - Hello world!
  - Hola mundo!
  - Bonjour le monde!
  - Hallo welt!
1
2
3
4
5

此时我们使用sixbox run运行即可看到,工作流对message_array的每个元素调用echo步骤:

sixbox run scatter-workflow.cwl scatter-job.yml
1

那么,如果我们想在工作流中分散两个步骤呢? 让我们执行一个类似于上面的简单echo,但是通过添加以下行而不是输出来捕获stdout: []
1st-tool-mod.cwl

cwlVersion: v1.0
class: CommandLineTool
baseCommand: echo
inputs:
  message:
    type: string
    inputBinding:
      position: 1
outputs:
  echo_out:
    type: stdout
1
2
3
4
5
6
7
8
9
10
11

并添加第二个步骤,用wc计算每个文件中的字符数。请参阅下面的工具:
wc-tool.cwl

cwlVersion: v1.0
class: CommandLineTool
baseCommand: wc
arguments: ["-c"]
inputs:
  input_file:
    type: File
    inputBinding:
      position: 1
outputs: []
1
2
3
4
5
6
7
8
9
10

现在,我们如何合并scatter?请记住,scatter字段位于每个步骤下: scatter-two-steps.cwl

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: []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

在这里,我们在每个步骤下设定了scatter。这对于本示例来说很好,因为它运行速度很快,但如果您正在为更复杂的工作流程运行许多示例,您可能希望考虑替代方案。在这里,我们在每个步骤上独立运行 scatter,但由于第二步需要一个数组作为输入,而这个数组来自于第一步,所以它会等到第一步中的所有内容都完成后再做任何事情。
假设echo Hello World!执行需要 1 分钟,wc -c输出需要 3 分钟,echo Hallo welt!执行需要 5 分钟,wc输出需要 3 分钟。虽然echo Hello World!可以在4分钟内完成,它实际上会在8分钟内完成,因为第一步必须等待echo Hallo welt!。您可以看到这可能无法很好地扩展。

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

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: []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

现在,scatter作用于单个步骤,但该步骤由两个步骤组成,因此每个步骤都是并行执行的。

条件工作流

问题:如何编写带有条件的工作流?
目标:了解如何构建包含条件步骤的工作流。

下例中的工作流包含一个条件步骤,并根据输入执行。这允许工作流根据程序开始时或先前步骤给出的输入参数跳过其他步骤。
conditional-workflow.cwl

class: Workflow
cwlVersion: v1.2
inputs:
  val: int

steps:

  step1:
    in:
      in1: val
      a_new_var: val
    run: foo.cwl
    when: $(inputs.in1 < 1)
    out: [out1]

  step2:
    in:
      in1: val
      a_new_var: val
    run: foo.cwl
    when: $(inputs.a_new_var > 2)
    out: [out1]

outputs:
  out1:
    type: string
    outputSource:
      - step1/out1
      - step2/out1
    pickValue: first_non_null

requirements:
  InlineJavascriptRequirement: {}
  MultipleInputFeatureRequirement: {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

您会注意到的第一件事是,此工作流程仅兼容 1.2 版或更高版本的 CWL 标准

class: Workflow
cwlVersion: v1.2
1
2

工作流的第一步step1包含两个输入属性,当条件满足时会执行foo.cwl。新属性when是进行条件验证的地方。在这种情况下,只有当工作流中in1< 1才会执行此步骤。

steps:

  step1:
    in:
      in1: val
      a_new_var: val
    run: foo.cwl
    when: $(inputs.in1 < 1)
    out: [out1]
1
2
3
4
5
6
7
8
9

使用以下命令,cwltool cond-wf-003.1.cwl --val 0该值将通过第一个条件步骤,因此将被执行并显示在日志中,INFO [step step1] start而第二个步骤将被跳过,如下所示INFO [step step2] will be skipped

INFO [workflow ] start
INFO [workflow ] starting step step1
INFO [step step1] start
INFO [job step1] /private/tmp/docker_tmpdcyoto2d$ echo

INFO [job step1] completed success
INFO [step step1] completed success
INFO [workflow ] starting step step2
INFO [step step2] will be skipped
INFO [step step2] completed skipped
INFO [workflow ] completed success
{
    "out1": "foo 0"
}
INFO Final process status is success
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

当给定值3时,第一个条件步骤将不会执行,但第二个步骤将执行cwltool cond-wf-003.1.cwl --val 3

INFO [workflow ] start
INFO [workflow ] starting step step1
INFO [step step1] will be skipped
INFO [step step1] completed skipped
INFO [workflow ] starting step step2
INFO [step step2] start
INFO [job step2] /private/tmp/docker_tmpqwr93mxx$ echo

INFO [job step2] completed success
INFO [step step2] completed success
INFO [workflow ] completed success
{
    "out1": "foo 3"
}
INFO Final process status is success
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

如果不满足任何条件,例如在使用cwltool cond-wf-003.1.cwl --val 2工作流时将引发永久失败。

INFO [workflow ] start
INFO [workflow ] starting step step1
INFO [step step1] will be skipped
INFO [step step1] completed skipped
INFO [workflow ] starting step step2
INFO [step step2] will be skipped
INFO [step step2] completed skipped
ERROR [workflow ] Cannot collect workflow output: All sources for 'out1' are null
INFO [workflow ] completed permanentFail
WARNING Final process status is permanentFail
1
2
3
4
5
6
7
8
9
10

CWL其他参数(Miscellaneous)

这里列举了一些示例和简短说明的,这些示例和说明属于用户指南范围之外的操作 和/或 在CWL标准中尚未以清晰的方式实现的操作。

  1. Non “File” types 使用 evalFrom
cwlVersion: v1.0  # or v1.1
class: CommandLineTool
requirements:
  InlineJavascriptRequirement: {}

baseCommand: [ echo, "42" ]

inputs: []

stdout: my_number.txt

outputs:
  my_number:
    type: int
    outputBinding:
       glob: my_number.txt
       loadContents: True
       outputEval: $(parselnt(self[0].contents))

  my_number_as_string:
    type: string
    outputBinding:
       glob: my_number.txt
       loadContents: True
       outputEval: $(self[0].contents)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
  1. 重命名输入文件
    这个示例展示了如何更改输入文件的名称作为工具描述的一部分。当您从工作流的另一个步骤中生成文件,并且不想使用这些文件创建时给出的默认名称时,这可能会很有用。
requirements:
  InitialWorkDirRequirement:
    listing:
      - entry: $(inputs.src1)
        entryName: newName
      - entry: $(inputs.src2)
        entryName: $(inputs.src1.basename)_custom_extension
1
2
3
4
5
6
7
  1. 重命名输出文件
    这个例子展示了如何改变一个输出文件的名称,而非工具给它的默认名称:
cwlVersion: v1.0 # or v1.1
class: CommandLineTool
requirements:
  InlineJavascriptRequirement: {}

baseCommand: []

inputs: []

outputs:
 otu_table:
    type: File
    outputBinding:
      glob: otu_table.txt
      outputEval: ${self[0].basename=inputs.otu_table_name; return self;}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  1. 为可选参数提供self-basedinputBinding
    当前,如果cwltool的输入绑定使用了self,那么cwltool无法处理丢失的可选输入。下面是一个解决此问题的示例,等待一个更复杂的修复。
cwlVersion: v1.0
class: CommandLineTool

requirements: { InlineJavascriptRequirement: {} }

inputs:
  cfg:
    type: File?
    inputBinding:
      prefix: -cfg
      valueFrom: |
        ${ if(self === null) { return null;} else { return self.basename; } }

baseCommand: echo

outputs: []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 如何定义一个“one-or-the-other”参数
    下面是一个示例,说明如何根据给定的布尔参数的值来指定要添加到命令行中的不同字符串。
cwlVersion: v1.0
class: CommandLineTool
requirements:
  InlineJavascriptRequirement: {}
inputs:
  fancy_bool:
     type: boolean
     default: false  # or true
     inputBinding:
        valueFrom: ${if (self) { return "foo";} else { return "bar";}}

baseCommand: echo

outputs: []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  1. 将同类型单独的值连接成一个输入数组
    使用MultipleInputFeatureRequirement搭配linkMerge: merge_nested实现
    输入必须是一个数组,每个输入链接只能包含一个条目。如果" merge_nested "是用单个链接指定的,则该链接的值必须包装在一个单项列表中。 这意味着“创建一个以这些源作为元素的列表”,换句话说:如果目标是File[]类型(一个文件数组),而源是一个单一的File,那么将multipleinputfeatuerequirequirement添加到Workflow级别的需求中,并在目标步骤的适当条目下添加linkMerge: merge_nested
cwlVersion: v1.0
class: Workflow

requirements:
  MultipleInputFeatureRequirement: {}

inputs:
  readme: File

steps:
  first:
    run: tests/checker_wf/cat.cwl
    in:
     cat_in:  # type is File[]
       source: [ readme ]  # but the source is of type File
       linkMerge: merge_nested
    out: [txt]

outputs:
  result:
    type: File
    outputSource: first/txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  1. 可选输入
    若要使输入参数为可选,请在类型声明中添加问号。
inputs:
  InputRead1:
    type: File
    inputBinding:
      position: 100

  #Optional Inputs
  isCasava:
    type: boolean?
    inputBinding:
      position: 1
      prefix: "--casava"
1
2
3
4
5
6
7
8
9
10
11
12
  1. 枚举输入
    对于需要特定输入作为参数的命令行标志,可以在CWL中声明枚举类型。在这里指定null的作用和其他输入的问号是一样的。
Format:
  type:
    - "null"
    - type: enum
      symbols:
        - bam
        - sam
        - bam_mapped
        - sam_mapped
        - fastq
  inputBinding:
    position: 2
    prefix: "--format"
1
2
3
4
5
6
7
8
9
10
11
12
13
  1. 记录输入(Record inputs)
    对于相互排斥或依赖的命令行标志,可以定义一个特殊的记录类型。您还可以在这里指定null以创建可选输入。
#Using record inputs to create mutually exclusive inputs 此处forward 和reverse相互排斥只能二选一

  Strand:
    type:
      - "null"
      - type: record
        name: forward
        fields:
          forward:
              type: boolean
              inputBinding:
                prefix: "--fr-stranded"

      - type: record
        name: reverse
        fields:
          reverse:
            type: boolean
            inputBinding:
              prefix: "--rf-stranded"

  PseudoBam:
    type: boolean?
    inputBinding:
      prefix: "--pseudobam"

#Using record inputs to create dependent inputs  此处genomebam,gtf和chromosomes相互依赖
  
  GenomeBam:
    type:
      - "null"
      - type: record
        name: genome_bam
        fields:
          genomebam:
            type: boolean
            inputBinding:
              prefix: "--genomebam"

          gtf:
            type: File
            inputBinding:
              prefix: "--gtf"

          chromosomes:
            type: File
            inputBinding:
              prefix: "--chromosomes"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  1. 设置互斥参数
    前面我们提到了记录输入(Record inputs),为了正确地设置记录输入类型中的字段,需要向输入传递字典以正确地设置参数。这是通过使用内联javascript并返回带有你想要设置的字段的键的字典来完成的。source字段被设置为指示将使用来自工作流的输入作为值。
    例如下例中Hisat2-Index.cwlInputFiles设置了两个互斥的参数fastacsv, 工作流调用中需要通过${return {"fasta": self};}的字典形式选择fasta
#../Tools/Hisat2-Index.cwl 的部分代码示例,此处定义了Record inputs 
  InputFiles:
    format: 
      - http://edamontology.org/format_1929
      - http://edamontology.org/format_1930/format_3752
    type:
      - type: record
        name: fasta
        fields:
          fasta:
            type: File[]
            inputBinding:
              itemSeparator: ","
              position: 100
      - type: record
        name: csv
        fields:
          csv:
            type: string[]
            #format: http://edamontology.org/format_1930/format_3752
            inputBinding:
              itemSeparator: ","
              position: 101
              prefix: "-c"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#workflow调用../Tools/Hisat2-Index.cwl时,需要设置互斥参数 fasta or csv
steps:

  build_hisat2_index:
    run: ../Tools/Hisat2-Index.cwl
    in:
      InputFiles:
        source: FastaFiles
        valueFrom : | 
          ${return {"fasta": self};}

      IndexName: IndexName
    
    out: [indexes]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  1. 设置布尔值
    这些可以通过使用默认字段进行设置
input:
  default:true
1
2
  1. 在输入中连接字符串
    必须使用valueFrom字段而不是default。
input:
  valueFrom: |
     My String: $(input.stringvalue)
1
2
3
  1. 由于文件名中有空格字符导致的Cwltool错误
    默认情况下,Cwltool不允许在文件名中包含某些字符, 例如,文件名是空格,txt包含3个空格字符。
ERROR Workflow error, try again with --debug for more information:

Invalid filename: 'a space is here.txt' contains illegal characters
1
2
3

如果无法避免这些危险字符,则将--relax-path-checks传递给cwltool。

  1. 由于输入标识符中的连字符导致CWL参数参考错误

如果 cwltool --validate 返回 valid

$ cwltool --validate cwl/qiime.cwl
INFO /usr/local/bin/cwltool 1.0.20190831161204
INFO Resolved 'cwl/qiime.cwl' to 'file:///workspace/cwl/qiime.cwl'
cwl/qiime.cwl is valid CWL.
1
2
3
4

但执行的时候发生如下错误:

$ cwltool cwl/qiime.cwl --sample-input metadata.tsv 
INFO /usr/local/bin/cwltool 1.0.20190831161204
INFO Resolved 'cwl/qiime.cwl' to 'file:///workspace/cwl/qiime.cwl'
ERROR Workflow error, try again with --debug for more information:
cwl/qiime.cwl:14:5: Expression evaluation error:
                    Syntax error in parameter reference '(inputs.sample-input)'. This could be due
                    to using Javascript code without specifying InlineJavascriptRequirement.
1
2
3
4
5
6
7

文件内容如下:

cwlVersion: v1.0
class: CommandLineTool
baseCommand: [qiime, metadata, tabulate]
arguments:
  - prefix: --m-input-file
    valueFrom: $(inputs.sample-input)
inputs:
  sample-input: File
outputs: []
1
2
3
4
5
6
7
8
9

问题是由于- (hyphen charcter)导致的

valueFrom: $(inputs.sample-input)
                        # ^ this is problem
...

inputs:
  sample-input: File
      # ^ this is problem
1
2
3
4
5
6
7

- (hyphen) 改为 _(underscore) 即可解决

valueFrom: $(inputs.sample_input)
                        # ^ changed here

···
inputs:
  sample_input: File
      # ^ changed here
1
2
3
4
5
6
7

如果不能更改输入标识符,则可以使用另一种CWL参数参考语法:

valueFrom: $(inputs["sample-input"])
1