美文网首页
Common Workflow Language [三]

Common Workflow Language [三]

作者: 生信师姐 | 来源:发表于2020-06-30 18:13 被阅读0次

十一 Advanced Inputs

如何描述哪些参数必须和不必须使用?
学习如何使用记录来描述输入之间的关系。

有时候一个工具几个参数必须一起使用(相互依赖) ,或者几个参数不能一起使用(排他)。 可以使用记录和类型联合将参数组合在一起来描述这两种情况。

record.cwl

#!/usr/bin/env cwl-runner

cwlVersion: v1.0
class: CommandLineTool
inputs:
  dependent_parameters: ******
    type:
      type: record
      name: dependent_parameters
      fields:
        itemA:
          type: string
          inputBinding:
            prefix: -A
        itemB:
          type: string
          inputBinding:
            prefix: -B
  exclusive_parameters: ******
    type:
      - type: record
        name: itemC
        fields:
          itemC:
            type: string
            inputBinding:
              prefix: -C
      - type: record
        name: itemD
        fields:
          itemD:
            type: string
            inputBinding:
              prefix: -D
outputs:
  example_out:
    type: stdout
stdout: output.txt
baseCommand: echo

record-job1.yml

dependent_parameters:
  itemA: one
exclusive_parameters:
  itemC: three

$ cwl-runner record.cwl record-job1.yml
Workflow error, try again with --debug for more information:
Invalid job input record:
record-job1.yml:1:1: the `dependent_parameters` field is not valid because
                       missing required field `itemB`

在第一个例子中,你不能只使用itemA而不使用itemB

record-job2.yml

dependent_parameters:
  itemA: one
  itemB: two
exclusive_parameters:
  itemC: three
  itemD: four

$ cwl-runner record.cwl record-job2.yml
record-job2.yml:6:3: invalid field `itemD`, expected one of: 'itemC'
[job record.cwl] /home/example$ echo \
    -A \
    one \
    -B \
    two \
    -C \
    three > /home/example/output.txt
[job record.cwl] completed success
{
    "example_out": {
        "location": "file:///home/example/11-records/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$329fe3b598fed0dfd40f511522eaf386edb2d077",
        "size": 23,
        "path": "/home/example/output.txt"
    }
}
Final process status is success
$ cat output.txt
-A one -B two -C three

在第二个示例中,itemCitemD是排他的,因此只有itemC被添加到命令行,itemD被忽略。

record-job3.yml

dependent_parameters:
  itemA: one
  itemB: two
exclusive_parameters:
  itemD: four

$ cwl-runner record.cwl record-job3.yml
[job record.cwl] /home/example$ echo \
    -A \
    one \
    -B \
    two \
    -D \
    four > /home/example/output.txt
[job record.cwl] completed success
{
    "example_out": {
        "location": "file:///home/example/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$77f572b28e441240a5e30eb14f1d300bcc13a3b4",
        "size": 22,
        "path": "/home/example/output.txt"
    }
}
Final process status is success
$ cat output.txt
-A one -B two -D four

在第三个示例中,只提供了itemD ,因此它出现在命令行上。

总结

  • 使用record字段将参数组在一起。
  • 同一参数中的多个record被视为排他的。

十二 环境变量

工具在受限制的环境中运行,并且不从父进程继承大多数环境变量。 可以使用EnvVarRequirement为工具设置环境变量。

env.cwl

#!/usr/bin/env cwl-runner

cwlVersion: v1.0
class: CommandLineTool
baseCommand: env
requirements:            ******
  EnvVarRequirement:
    envDef:
      HELLO: $(inputs.message)
inputs:
  message: string
outputs:
  example_out:
    type: stdout
stdout: output.txt

echo-job.yml

message: Hello world!
$ cwl-runner env.cwl echo-job.yml
[job env.cwl] /home/example$ env > /home/example/output.txt
[job env.cwl] completed success
{
    "example_out": {
        "location": "file:///home/example/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$1ca16a840b14807b2fd3323022c476b06a150e2f",
        "size": 94,
        "path": "/home/example/output.txt"
    }
}
Final process status is success
$ cat output.txt
HELLO=Hello world!
PATH=/bin:/usr/bin:/usr/local/bin
HOME=/home/example
TMPDIR=/tmp/tmp63Obpk

总结

  • T工具在一个受限制的环境中运行,只有一组最小的环境变量。
  • 使用EnvVarRequirement字段在工具的环境中设置环境变量。

十三 JavaScript Expressions

  • 如果我想动态创建值,而 cwl 没有提供内置的方法,我该怎么做。

  • Learn how to insert JavaScript expressions into a CWL description.学习如何在CWL描述中插入JavaScript表达式。

如果你需要操纵输入参数,包括InlineJavascriptRequirement,然后在任何参数引用是合法的地方,你都可以提供一个 javascript 片段,这个片段将由 CWL runner 进行评估。

注意: javascript 表达式只能在绝对必要的时候使用。 在操作文件名、扩展名、路径等时,考虑是否可以使用内置的文件属性,如 basename、 nameroot、 nameext 等。

expression.cwl

#!/usr/bin/env cwl-runner

cwlVersion: v1.0
class: CommandLineTool
baseCommand: echo

requirements:
  InlineJavascriptRequirement: {}

inputs: []
outputs:
  example_out:
    type: stdout
stdout: output.txt
arguments:
  - prefix: -A
    valueFrom: $(1+1)
  - prefix: -B
    valueFrom: $("/foo/bar/baz".split('/').slice(-1)[0])
  - prefix: -C
    valueFrom: |
      ${
        var r = [];
        for (var i = 10; i >= 1; i--) {
          r.push(i);
        }
        return r;
      }

因为这个工具不需要任何inputs ,我们可以用一个(几乎)空的文件运行它:

empty.yml

{}

empty.yml’包含一个空 json 对象的描述。 Json 对象描述包含在大括号 {}中,因此空对象仅由一组空括号表示。

运行expression.cwl:

$ cwl-runner expression.cwl empty.yml
[job expression.cwl] /home/example$ echo \
    -A \
    2 \
    -B \
    baz \
    -C \
    10 \
    9 \
    8 \
    7 \
    6 \
    5 \
    4 \
    3 \
    2 \
    1 > /home/example/output.txt
[job expression.cwl] completed success
{
    "example_out": {
        "location": "file:///home/example/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$a739a6ff72d660d32111265e508ed2fc91f01a7c",
        "size": 36,
        "path": "/home/example/output.txt"
    }
}
Final process status is success
$ cat output.txt
-A 2 -B baz -C 10 9 8 7 6 5 4 3 2 1

注意:需求必须以数组的形式提供,每个条目(在这种情况下,只有class: InlineJavascriptRequirement)) 通过-标记。 使用相同的语法来描述附加的命令行参数。

Where are JavaScript expressions allowed?

Just like parameter references, you can use JavaScript Expressions only in certain fields. These are:

总结

  • 如果指定了使用InlineJavascriptRequirement,你可以包含 Javascript 表达式,这些表达式将被 cwl runner评估.
  • 表达式只在特定的字段中有效。
  • 表达式应该只在没有内置的 CWL 解决方案存在时使用。

十四 Creating Files at Runtime

Questions

  • 我是否在运行时从输入参数创建所需的输入文件?
  • 我如何调用脚本而不仅仅是一个简单的命令行?
  • 除了inputBinding,我还能如何向工具传递参数?

Objectives

  • 学习如何在运行中动态地创建文件
  • 学习如何在 bash 脚本中使用表达式。

有时候,需要动态地根据输入参数创建一个文件,例如一个工具,希望从文件而不是命令行参数读取输入配置,或者需要一个小型的wrapper shell 脚本。

要生成这样的文件,我们可以使用InitialWorkDirRequirement

createfile.cwl

class: CommandLineTool
cwlVersion: v1.0
baseCommand: ["sh", "example.sh"]

requirements:
  InitialWorkDirRequirement:           ******
    listing:
      - entryname: example.sh
        entry: |-
          PREFIX='Message is:'
          MSG="\${PREFIX} $(inputs.message)"
          echo \${MSG}

inputs:
  message: string
outputs:
  example_out:
    type: stdout
stdout: output.txt

在创建文件之前,任何表达式(比如$(inputs.message)都会被 CWL引擎展开; 这里在 inputmessage处插入value值。

Tip

CWL表达式独立于命令行工具调用期间后面使用的任何 shell 变量。 例如上面的 \${PREFIX}扩展为 ${PREFIX} ,由 shell 脚本而不是 cwl 引擎进行计算。

为了测试上面的CWL工具,使用这个作业提供 input的value值message:

echo-job.yml

message: Hello world!

在我们开始之前,让我们看看每一步的细节。命令 baseCommand: ["sh", "example.sh"]将执行命令sh example.sh。 这将运行我们在 shell 中创建的文件。

InitialWorkDirRequirement需要一个listing。由于listing是一个YAML数组,我们需要在数组的每个元素的第一行上有一个-。在本例中,我们只有一个元素。entryname:可以有任何value值,但必须与baseCommand中指定的值匹配。最后一部分是entry:,后面跟着是|-,这是YAML引用语法,意味着使用的是多行字符串(没有它,我们需要在一行上编写整个脚本)。

$ cwl-runner createfile.cwl echo-job.yml
[job createfile.cwl] /private/tmp/docker_tmphrqxxcdl$ sh \
    example.sh > /private/tmp/docker_tmphrqxxcdl/output.txt
Could not collect memory usage, job ended before monitoring began.
[job createfile.cwl] completed success
{
    "example_out": {
        "location": "file:///home/example/output.txt",
        "basename": "output.txt",
        "class": "File",
        "checksum": "sha1$9045abe4bd04dd8ccfe50c6ff61820b784b64aa7",
        "size": 25,
        "path": "/home/example/output.txt"
    }
}
Final process status is success
$ cat output.txt
Message is: Hello world!

总结

  • 使用InitialWorkDirRequirement来指定在工具运行时需要创建的输入文件。

十五 暂存输入文件

问题

  • 如果工具需要将输出写入到其输入文件存储的目录,该怎么办?

通常,输入文件位于与输出目录分开的只读目录中。如果底层工具希望将其输出文件与输入文件一起写入同一目录,则会出现问题。使用InitialWorkDirRequirement将输入文件暂存到输出目录中。在本例中,我们使用一个JavaScript表达式从其主目录路径中提取输入文件的base name。

linkfile.cwl

#!/usr/bin/env cwl-runner

cwlVersion: v1.0
class: CommandLineTool
hints:
  DockerRequirement:
    dockerPull: openjdk:9.0.1-11-slim
baseCommand: javac

requirements:
  InitialWorkDirRequirement:
    listing:
      - $(inputs.src)

inputs:
  src:
    type: File
    inputBinding:
      position: 1
      valueFrom: $(self.basename)

outputs:
  classfile:
    type: File
    outputBinding:
      glob: "*.class"

arguments-job.yml

src:
  class: File
  path: Hello.java

$ cwl-runner linkfile.cwl arguments-job.yml
[job 139928309171664] /home/example$ docker run -i --volume=/home/example/Hello.java:/var/lib/cwl/job557617295_examples/Hello.java:ro --volume=/home/example:/var/spool/cwl:rw --volume=/tmp/tmpmNbApw:/tmp:rw --workdir=/var/spool/cwl --read-only=true --net=none --user=1001 --rm --env=TMPDIR=/tmp java:7 javac Hello.java
Final process status is success
{
"classfile": {
  "size": 416,
  "location": "/home/example/Hello.class",
  "checksum": "sha1$2f7ac33c1f3aac3f1fec7b936b6562422c85b38a",
  "class": "File"
  }
}

总结

  • 输入文件通常保存在只读目录中。
  • 使用InitialWorkDirRequirement将输入文件暂存到工作目录中。

相关文章

网友评论

      本文标题:Common Workflow Language [三]

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