wdl脚本实战及细节
教程:https://github.com/openwdl/wdl
wdl概述:每个wdl脚本包含一个workflow,每个workflow包含多个task,通过调用task执行命令。适合于流程化的多个步骤,例如后一个步骤依赖前一个步骤的产生结果。
- task的input由workflow指定,缺失则会报错;
- task的output指定后将在运行结束后检验,如果没有正确输出则会报错。
写一个wdl脚本
- 其中黄色部分为必须包含的结构,定义输入变量传递
wdl脚本功能:
- 接收
json
文件task_variable, path(定义输出文件地址); - 执行command中指令,输出对应语句到
${path}/Hello.txt
文件; - 检验输出文件是否存在
## Workflow-level comments
workflow workflow_name {
## set variable
String workflow_variable
String path
## call <task name>
call task_name {
input:task_variable=workflow_variable, path=path
}
}
# Task-level comments
task task_name{
String task_variable
String path
String out = "${path}/Hello.txt"
# Execute shell commands
command {
echo 'Hello ${task_variable}' > ${out}
}
output {
File out_path= "${out}"
}
}
{
"workflow_name.workflow_variable":"world",
"workflow_name.path":"/home/script"
}
其他模板参考
- 在json文件中直接指定task级输入变量
## Workflow-level comments
version 1.0
workflow WorkflowOne {
call TaskOne
call TaskTwo
}
# Task-level comments
task TaskOne {
StringOne inOne
# specify parameter value (inOne) in `input.json` file
command {
echo '${inOne}'
}
output {
String out = read_string(stdout())
}
}
task TaskTwo {
StringTwo inTwo
# specify parameter value (inTwo) in `input.json` file
command {
echo '${inTwo}'
}
output {
String out = read_string(stdout())
}
}
input.json :
{
"WorkflowOne.TaskOne.StringOne": "my first string",
"WorkflowOne.TaskTwo.StringTwo": "my second string"
}
- 在json文件中指定workflow级别输入,通过参数传递task输入
version 1.0
workflow HelloInput {
input {
String name
}
call WriteGreeting {
input : name = name
}
}
```shell
task WriteGreeting {
input {
String name
}
# specify parameter value (name) in `input.json` file
command {
echo 'hello ${name}!'
}
output {
File response = stdout()
}
runtime {
docker: 'ubuntu:latest'
}
}
input.json :
{
"HelloInput.name": "Input Workflow World"
}
运行wdl脚本
wdl脚本 本身不可以执行,需要对应的软件,例如使用Cromwell运行脚本
cromwell 下载地址:https://github.com/broadinstitute/cromwell/releases/tag/86
有两种模式可以运行:
# run (single workflow)
java -jar cromwell-XY.jar run ./path/file.wdl
java -jar cromwell-XY.jar run ./path/file.wdl --inputs ./path/input.json
# sever (multiples) mode
java -jar -server cromwell-XY.jar run ./path/server.wdl
wdl 变量
command中引用input变量使用~{}表明实际包含的变量
task task_A{
input{
String id
String output
}
command <<<
echo ~{id} > ~{output}.txt
>>>
output {
File out = "~{output}.txt"
}
}
踩坑记录
command语法和shell脚本差异:在command中引用input变量可以使用${}结构,但是不可以使用$调用input变量;command中新定义的shell变量使用$调用,不可以使用${}。
# 正确案例
input {
String name
}
command {
text ="Hello ${name}"
echo $text # text使用$表示
}
# 报错案例
input {
String name
}
command {
text ="Hello ${name}"
echo ${text} # text不是input中定义的变量,报错
}
wdl字符串拼接 : 使用~{}表示引用变量 或者 使用${}
String tmp_result = "~{outdirSample + '/' + sampleID}.tmp.result"
语法检查工具womtool
下载地址:https://github.com/broadinstitute/cromwell/releases/tag/86
测试wdl是否有效:如果成功输出“Success!”,失败则输出具体错误信息
$ java -jar womtool-86.jar validate test.wdl
ERROR: Old style workflow output references 'test.name' which doesn't exist (line 61, col 3):
test.name
$ java -jar womtool-86.jar validate HelloWorld.wdl
Success!
批量检查文件夹下的wdl有效性:
ls | grep '\.wdl$' | xargs -I {} sh -c 'echo "Validating {}"; java -jar womtool-86.jar validate {}