4. 常见问题#
4.1. How do I create non "File
" types using 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)
4.2. How do I rename an input file?#
本示例演示如何在工具描述 (tool description) 中更改输入文件名称。如果要使用工作流中其它步骤产生的文件,但又不想使用这些文件创建时的默认名称,这时候更名操作可以派上用场。
requirements:
InitialWorkDirRequirement:
listing:
- entry: $(inputs.src1)
entryName: newName
- entry: $(inputs.src2)
entryName: $(inputs.src1.basename)_custom_extension
4.3. How do I rename an output file?#
本示例演示更改输出文件名,不再使用某个工具赋予它的默认名称:
cwlVersion: v1.0
class: CommandLineTool
requirements:
InlineJavascriptRequirement: {}
baseCommand: [ touch, otu_table.txt ]
inputs:
otu_table_name: string
outputs:
otu_table:
type: File
outputBinding:
glob: otu_table.txt
outputEval: ${self[0].basename=inputs.otu_table_name; return self;}
By modifying the basename
field in the outputEval
field, CWL workflow engines will rename
the file using the new name for subsequent steps or as a workflow-level output.
4.4. How do I reference a local script?#
引用本地脚本有两种方法:
The first method involves adding the path to a folder containing your scripts to the PATH
environment variable. This
allows you to execute the shell script directly (without explicitly using the sh
or bash
commands).
首先,将 "shebang" 添加为文件首行:
#!/bin/bash
然后,用 chmod +x scriptname.sh
命令将脚本设为可执行。
最后,修改 PATH
, 添加该脚本所在的目录。(把你自己的脚本保存在 $HOME/bin
目录下是较好的做法)。
export PATH=$PATH:$HOME/bin
这样,您就能用 baseCommand: scriptname.sh
直接运行脚本了。
#!/bin/bash
cwlVersion: v1.0
class: CommandLineTool
baseCommand: scriptname.sh
接下来若想共享您的工作,可将脚本存放在 Docker 格式的容器 (container) 中。
第二种方法是将 type: File
输入内容编写进脚本:
class: CommandLineTool
inputs:
my_script:
type: File
inputBinding:
position: 0
# other inputs go here
baseCommand: sh
outputs: []
4.5. How can I set self
-based input bindings for optional inputs?#
目前,如果缺失的可选输入项用到了 self
, cwltool
将无法处理。在更高明的解决办法出现前,下面的例子可作为临时变通一用。
#!/usr/bin/env cwl-runner
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: []
4.6. How can I model a "one-or-the-other" parameter?#
以下示例演示的,是根据某个布尔参数的取值,来指定添加到命令行的字符串。
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: []
4.7. How do I connect a solo value to an input that expects an array of that type?#
Add a MultipleInputFeatureRequirement
along with
linkMerge: merge_nested
:
merge_nested
输入必须是一个数组,每个输入链接只包含一个条目。如果使用单个链接指定“merge_nested”,则链接中的值必须包含在单项列表中。
Which means "create a list with exactly these sources as elements".
换言之:如果目标的类型是 File[]
(元素类型为 File
的数组),而源是单独一个 File
,那么将 MultipleInputFeatureRequirements
添加到工作流级别的 requirements
,并在目标步骤相应的 in
条目下添加 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
4.8. How do make an input optional? 💯#
若要令某个输入参数为可选,请在其类型声明中添加问号。
inputs:
InputRead1:
type: File
inputBinding:
position: 100
#Optional Inputs
isCasava:
type: boolean?
inputBinding:
position: 1
prefix: "--casava"
4.9. How do I specify an input that must come from a list of predefined values (i.e. How do I use enum inputs) ?#
某些命令行标志需要特定的参数值;对此,可以在 CWL 中声明枚举类型。此处指定 null, 这样的编程风格称为“长格式” (long form)。它的作用与其他输入上的问号相同。
Format:
type:
- "null"
- type: enum
symbols:
- bam
- sam
- bam_mapped
- sam_mapped
- fastq
inputBinding:
position: 2
prefix: "--format"
4.10. How do I describe dependent or exclusive input parameters(e.g. How do I use record inputs)?#
如果部分命令行标志之间存在 互斥 或 依赖 的关系,可以为其定义专门的记录类型 (record type)。此处也可以指定 null 创建可选输入。
#Using record inputs to create mutually exclusive inputs
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:
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"
4.11. How do I set mutually exclusive parameters?#
为了正确地设置记录输入类型的字段,您需要将字典传递给输入,以正确设置参数。具体方法是使用内联 JavaScript 返回以待设置字段为主键的字典。此处设定了 source (源)字段,以指示工作流中要充当其键值的输入。
steps:
build_hisat2_index:
run: ../Tools/Hisat2-Index.cwl
in:
InputFiles:
source: FastaFiles
valueFrom : |
${return {"fasta": self};}
IndexName: IndexName
out: [indexes]
4.12. How can I set Booleans?#
可使用 default(默认)字段设置
input:
default: true
4.13. What should I do when concatenating strings in inputs?#
为此必须使用 valueFrom 而非 default 字段。
input:
valueFrom: |
My String: $(input.stringvalue)
4.14. I get cwltool
errors due to filenames with space characters inside. What should I do?#
默认情况下,cwltool
不允许某些字符出现在文件名中。
例如,文件名 a space is here.txt
包含三个空格字符。
ERROR Workflow error, try again with --debug for more information:
Invalid filename: 'a space is here.txt' contains illegal characters
如果不能避开这些危险的字符,您可以为 cwltool
传递 --relax-path-checks
选项。
4.15. What should I do when I get CWL Parameter Reference error due to hyphen in an input identifier?#
如 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.
但执行时导致如下错误:
$ 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.
该文件如下
cwlVersion: v1.0
class: CommandLineTool
baseCommand: [qiime, metadata, tabulate]
arguments:
- prefix: --m-input-file
valueFrom: $(inputs.sample-input)
inputs:
sample-input: File
outputs: []
问题由 -
(连字符)引发。
valueFrom: $(inputs.sample-input)
# ^ this is problem
...
inputs:
sample-input: File
# ^ this is problem
To fix this error, change -
(hyphen) to _
(underscore):
valueFrom: $(inputs.sample_input)
# ^ changed here
...
inputs:
sample_input: File
# ^ changed here
如果不能改动输入标识符,您可使用另一种 CWL 参数引用句法:
valueFrom: $(inputs["sample-input"])
4.16. How do I use CWL and cwltool with Singularity?#
CWL 标准是依照 Docker 容器格式建立的,其参考运行程序和另外几种 CWL 实现均支持适应 Singularity 引擎运行 Docker 格式容器。不过,直接指定 Singularity 格式容器不在 CWL 标准之内。
4.17. How do I debug the JavaScript in my CWL tool?#
您可使用 cwltool
的 –js-console
选项,也可以考虑为您的代码创建 JavaScript 或 TypeScript 项目后使用 expressionLib
加载, 比如: https://github.com/common-workflow-language/common-workflow-language/blob/master/v1.0/v1.0/template-tool.cwl#L6-L8