WDL: 快速編寫屬于你的分析流程

前言

??一般生物信息分析流程都包含很多的分析步驟,這些步驟之間的聯(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)

  1. WDL:整體是由一個(gè)workflow構(gòu)成,一般寫在一個(gè)后綴為“.wdl”的文件里面。
  2. 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ì)有先后順序。
  3. 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ù)信息、流程信息等。
  4. 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ò)。

  1. 驗(yàn)證WDL的有效性
java -jar womtool-51.jar validate test.wdl

如果輸出結(jié)果是“Success!”,那么恭喜你寫的WDL沒有語法錯(cuò)誤,可以接著運(yùn)行了。

  1. 生成提供變量值的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,今天就先分享到這里吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容