前言
??一般生物信息分析流程都包含很多的分析步驟,這些步驟之間的聯(lián)系也有很多情況。例如,流程的步驟中有不少是依賴上一步的結(jié)果,同時(shí)也有些步驟之間沒有聯(lián)系可以同時(shí)進(jìn)行,還有的步驟需要滿足某種情況才運(yùn)行,也有的步驟需要匯總很多樣本的結(jié)果來進(jìn)行分析,等等這些情況。那么一個(gè)好的流程應(yīng)該要滿足沒有依賴的步驟可以并行分析,需要上一步結(jié)果的步驟會(huì)自動(dòng)等待上一步驟執(zhí)行完畢并調(diào)用其結(jié)果,需要匯總很多步驟的結(jié)果時(shí)能夠自動(dòng)等待所有依賴步驟執(zhí)行完畢然后匯總他們的結(jié)果并調(diào)用,以及能夠處理一些其他的情況等。

??一個(gè)優(yōu)秀的流程工具應(yīng)該具備良好的組織性、復(fù)用性、支持多種集群架構(gòu),較低的上手及查錯(cuò)成本。那么有沒有這么好用的流程管理工具呢?答案是肯定的。今天我們就來分享一個(gè)非常好用且強(qiáng)大的流程管理工具——WDL。目前WDL就是這樣一個(gè)具備這種潛力的工具,WDL是Broad Institute開發(fā)的“human readable and writable”定義組織任務(wù)與工作流的一種語言。Cromwell(an execution engine that can run WDL scripts)是基于java編寫的可以很好地用來執(zhí)行WDL語言的引擎工具。WDL+Cromwell就是一套很好的分析流程解決方案。
WDL介紹
結(jié)構(gòu)
- WDL:整體是由一個(gè)workflow構(gòu)成,一般寫在一個(gè)后綴為“.wdl”的文件里面。
- workflow:整體有兩個(gè)部分構(gòu)成,一是位于頭部的input,該部分定義workflow級(jí)別的變量,所有的task都可以調(diào)用該部分的變量,如果很多步驟都需要使用的變量最好定義在這個(gè)部分方便使用;二是使用“call”關(guān)鍵字調(diào)用下面定義的task,這個(gè)部分的task順序不代表執(zhí)行時(shí)的順序,task的執(zhí)行順序有任務(wù)之間是否有引用關(guān)系來決定,如果任務(wù)之間沒有聯(lián)系就會(huì)平行執(zhí)行,如果有一個(gè)任務(wù)需要用到另一個(gè)任務(wù)的結(jié)果時(shí),可以在寫流程的時(shí)候指定好,這樣就在執(zhí)行的時(shí)候就會(huì)有先后順序。
- task:主要包含三個(gè)部分,一是位于頭部的input,該部分定義的是task級(jí)別的變量,也就直接給該task自己使用的變量;二是使用“command”關(guān)鍵字定義的具體命令部分,在這里面可以書寫的命令就是Linux命令寫的一樣命令;三是使用“output”關(guān)鍵字定義的輸出部分,這樣別的任務(wù)就可以調(diào)用這樣輸出結(jié)果,WDL也正是通過這個(gè)來定義任務(wù)間的執(zhí)行順序;主要是上面三個(gè)部分,還有一些可選部分,如可以通過runtime(使用集群時(shí)有效)、parameter_meta、meta等關(guān)鍵字來定義任務(wù)的運(yùn)行配置、參數(shù)信息、流程信息等。
- variable:定義變量的時(shí)候可以在類型關(guān)鍵字后面加一個(gè)“?”代表這個(gè)變量是可選的,也就是可以不提供值的變量,也可以給變量賦一個(gè)默認(rèn)值,這樣沒有另外給值時(shí)就會(huì)使用默認(rèn)值。由于執(zhí)行引擎Cromwell是基于java編寫的,所以定義的變量是強(qiáng)類型的,也就是需要顯示地聲明變量的類型,變量類型主要包括以下幾種:
String: 字符串類型,
Float : 浮點(diǎn)型數(shù)字,
Int: 整型的數(shù)字,
Boolean : 布爾類型,只有true和false兩種情況,
File: 文件類型,
Array : 數(shù)組類型,
Map: 字典類型,
Object : 對(duì)象類型,這個(gè)很少用到。
完整WDL示例
上面介紹完WDL基本構(gòu)成,大家現(xiàn)在知道一個(gè)WDL由哪些組件構(gòu)成的了,后面就是運(yùn)行這些組件來拼出自己需要的workflow,下面我給出一個(gè)盡量包含更多情況的示例,讓大家有一個(gè)直觀地感受,下面來看一下示例代碼:
workflow testwdl {
Int? thread = 6
String varwdl
String prefix
Array[Int] intarray = {1,2,3,4,5}
if(thread>5) {
call taska {
input:
vara = varwdl,
infile = taskb.outfile,
prefix = prefix
}
}
scatter (sample in intarray) {
call taskb {
input:
varb = 'testb',
thread = thread,
prefix = sample
}
}
}
task taska {
String vara
Array[File] infile
String prefix
command {
cat ${sep=" " infile} >${prefix}_${vara}.txt
}
}
task taskb {
String varb
Int thread
String prefix
command {
echo ${varb} ${thread} >${prefix}.txt
}
output {
File outfile = '${prefix}.txt'
}
}
上面的WDL描述了一個(gè)流程包含taska、taskb兩個(gè)任務(wù),taskb會(huì)打印一個(gè)文件里面包含“taskb”和threadb變量的值,taska會(huì)合并所有taskb的結(jié)果,且taska依賴taskb,也就會(huì)先執(zhí)行taskb任務(wù)。同時(shí)由于taskb任務(wù)被包含在scatter循環(huán)結(jié)構(gòu)中會(huì)被執(zhí)行多次,這里intarray長度為5,也就是taskb會(huì)并行執(zhí)行五次。taska需要引用taskb的結(jié)果,也就是需要等待所有taskb執(zhí)行完才會(huì)執(zhí)行,這里還需要注意一點(diǎn),taska的執(zhí)行還需要thread變量的值大于5,我這里默認(rèn)設(shè)置的是6,如果不修改則taskb執(zhí)行完肯定會(huì)執(zhí)行taska,如提供一個(gè)小于5的thread值,則即使taskb全部執(zhí)行完taska也不會(huì)執(zhí)行。
WDL執(zhí)行
流程寫好了,下面就可以執(zhí)行了,但是在執(zhí)行之前最好用工具檢驗(yàn)一下有沒有語法錯(cuò)誤(如果你相信自己寫的WDL沒有問題可以跳過這個(gè)步驟),這一步并不怎么耗時(shí),個(gè)人覺得還是有必要檢測一下免得運(yùn)行了也是出錯(cuò)。
- 驗(yàn)證WDL的有效性
java -jar womtool-51.jar validate test.wdl
如果輸出結(jié)果是“Success!”,那么恭喜你寫的WDL沒有語法錯(cuò)誤,可以接著運(yùn)行了。
- 生成提供變量值的json文件
#生成json文件
java -jar ~/software/cromwell-51/womtool-51.jar inputs test.wdl >test.json
#查看json文件
cat test.json
{
"testwdl.varwdl": "String",
"testwdl.intarray": "Array[Int] (optional, default = [1, 2, 3, 4, 5])",
"testwdl.prefix": "String",
"testwdl.thread": "Int? (optional, default = 6)"
}
從上面的代碼可以看出,我這里寫的WDL需要四個(gè)輸入,其中有兩個(gè)是有默認(rèn)值的變量,對(duì)于這兩個(gè)可以不用提供值,另外兩個(gè)給予相應(yīng)的值即可,例如,下面是我提供的名為“test.json”的json文件:
{
"testwdl.varwdl": "helloworld",
"testwdl.prefix": "test_wdl"
}
輸入的json文件也已備好,最后就可以執(zhí)行WDL了,具體執(zhí)行命令如下:
java -jar cromwell-51.jar run test.wdl --inputs test.json
流程執(zhí)行過程的細(xì)節(jié)都會(huì)被記錄在log文件中,如果成功地執(zhí)行了會(huì)在log文件中看到類似[2020-09-05 03:04:34,12] [info] SingleWorkflowRunnerActor workflow finished with status 'Succeeded'.提示語句。
WDL結(jié)果
流程執(zhí)行完畢默認(rèn)會(huì)在運(yùn)行流程的目錄下生成兩個(gè)目錄,cromwell-executions和cromwell-workflow-logs分別是執(zhí)行步驟的文件夾和log文件夾。下面來看一下結(jié)果文件夾目錄機(jī)構(gòu),如上面的WDL流程執(zhí)行完成后的結(jié)果目錄結(jié)構(gòu)如下所示:
├── cromwell-executions
│ └── testwdl
│ └── 91fd40bd-7a34-41b3-8540-3c9db7b6e580
│ ├── call-taska
│ │ ├── execution
│ │ ├── inputs
│ │ └── tmp.5fe66a06
│ └── call-taskb
│ ├── shard-0
│ ├── shard-1
│ ├── shard-2
│ ├── shard-3
│ └── shard-4
├── cromwell-workflow-logs
從上面的目錄結(jié)構(gòu)可以看出同一個(gè)WDL流程即使多次執(zhí)行最新的結(jié)果也不會(huì)覆蓋之前的結(jié)果,甚至在同一個(gè)目錄下運(yùn)行不同流程的WDL生成的結(jié)果也不會(huì)相互干擾,這些都得益于WDL的目錄結(jié)構(gòu)包含一層隨機(jī)字符串目錄,如這里的“91fd40bd-7a34-41b3-8540-3c9db7b6e580”,所以大家就放心大膽的運(yùn)行吧!最終每個(gè)task的運(yùn)行中間文件和結(jié)構(gòu)在相應(yīng)的execution文件下面。
如這里taska的結(jié)果在cromwell-executions/testwdl/91fd40bd-7a34-41b3-8540-3c9db7b6e580/call-taska/execution下面,最終的結(jié)果文件為test_wdl_helloworld.txt,內(nèi)容如下:
testb 6
testb 6
testb 6
testb 6
testb 6
現(xiàn)在是不是決定WDL很強(qiáng)大且容易上手,對(duì)于這么好的東西是不是有種相見恨晚的感覺,那還在等什么趕緊用起來吧!對(duì)于功能這里僅僅展示了一小部分,更多更強(qiáng)的功能留待大家自己在使用中摸索吧!
最后
??前面介紹了WDL的基本構(gòu)成和用法展示,這里給大家提供一下官網(wǎng)鏈接方便想深入學(xué)習(xí)的同學(xué),WDL官網(wǎng):https://support.terra.bio/hc/en-us/articles/360037117492-Getting-Started-with-WDL。順便附上執(zhí)行引擎Cromwell的下載地址,方便需要的同學(xué)下載,下載鏈接:https://github.com/broadinstitute/cromwell/releases。后續(xù)再更新如何配置集群的配置文件,讓W(xué)DL可以在集群上運(yùn)行,這樣就可以充分利用集群的資源提升流程整體的運(yùn)行速度,節(jié)省更多時(shí)間。emm,今天就先分享到這里吧。
