WDL學(xué)習(xí)筆記

官網(wǎng)是用來學(xué)習(xí)的最好的地方(然而我也沒怎么看...)膜钓!

WDL是什么坚洽?

  • WDL是由Broad Institute開發(fā)的一種流程開發(fā)語言韭畸,全稱workflow description language喻犁。

WDL編輯器

使用Sublime Txet就可以,安裝WDL插件就可以漂亮地顯示W(wǎng)DL代碼了上岗。

一個WDL代碼示例

這是一個我老板用來跑RRBS的pipeline福荸,以此來學(xué)習(xí)。

workflow bismarkRRBS {

    String file_basename
    String masterFolder
    File Fastq_R1
    File? Fastq_R2
    Boolean paired
    Boolean MspI
    Int clip_R1
    Int? clip_R2
    Int three_prime_clip_R1
    Int? three_prime_clip_R2
    String genome_folder
    Int threadN

    String targetFolder = masterFolder + "/" + file_basename + "/"

    call makeDir as md1 {
        input:
            targetFolder = targetFolder
    }

    call makeDir as md2 {
        input:
            targetFolder = md1.outFolder + "report"
    }

    call trim_galore {
        input:
            Fastq_R1 = Fastq_R1,
            Fastq_R2 = Fastq_R2,
            clip_R1  = clip_R1,
            clip_R2  = clip_R2,
            three_prime_clip_R1 = three_prime_clip_R1,
            three_prime_clip_R2 = three_prime_clip_R2,
            paired   = paired,
            MspI     = MspI,
            targetFolder = md1.outFolder,
            reportFolder = md2.outFolder,
            file_basename = file_basename
    }

    call bismark {
        input:
            R1_trimmed = trim_galore.R1_trimmed,
            R2_trimmed = trim_galore.R2_trimmed,
            paired  = paired,
            threadN = threadN,
            file_basename = file_basename,
            genome_folder = genome_folder,
            targetFolder  = md1.outFolder,
            reportFolder  = md2.outFolder
    }

    call processBam {
        input:
            file_basename = file_basename,
            alignedBam    = bismark.alignedBam,
            genome_folder = genome_folder,
            alignedReport = bismark.alignedReport,
            paired  = paired,
            threadN = threadN,
            targetFolder = md1.outFolder,
            reportFolder = md2.outFolder
    }

    output {

        File DedupBam = processBam.DedupBam
        File DedupBam_index = processBam.DedupBam_index
    }


}


task trim_galore {

    File Fastq_R1
    File? Fastq_R2
    Boolean paired
    Boolean MspI
    Int clip_R1
    Int? clip_R2
    Int three_prime_clip_R1
    Int? three_prime_clip_R2
    String targetFolder
    String reportFolder
    String file_basename

    String s1 = if paired then "--paired" else ""
    String s2 = s1 + if (clip_R1 > 0) then " --clip_R1 " + clip_R1 else ""
    String s3 = s2 + if (three_prime_clip_R1 > 0) then " --three_prime_clip_R1 " + three_prime_clip_R1 else ""
    String s4 = s3 + if(paired && clip_R2 > 0) then " --clip_R2 " + clip_R2 else ""
    String s5 = s4 + if(MspI) then " --rrbs " else ""
    String commandText = s5 + if(paired && three_prime_clip_R2 > 0) then " --three_prime_clip_R2 " + three_prime_clip_R2 else ""

    command {

        mkdir trimmed 
        trim_galore ${commandText} -o trimmed --basename ${file_basename} ${Fastq_R1} ${Fastq_R2}

        cp trimmed/*report.txt ${reportFolder}
    }

    output{
        File R1_trimmed = if paired then "trimmed/${file_basename}_R1_val_1.fq.gz" else "trimmed/${file_basename}_trimmed.fq.gz"
        File R2_trimmed = if paired then "trimmed/${file_basename}_R2_val_2.fq.gz" else "/dev/null"
    }
}

task bismark {

    File R1_trimmed
    File? R2_trimmed
    Boolean paired
    Int threadN
    String file_basename
    String genome_folder
    String targetFolder
    String reportFolder

    String commandText = if paired then  " -1 " + R1_trimmed + " -2 " + R2_trimmed else R1_trimmed

    command {

        bismark --genome_folder ${genome_folder} \
            ${commandText} \
            -p ${threadN} \
            --rg_id ${file_basename} \
            --rg_sample ${file_basename} \
            --basename ${file_basename} \
            --temp_dir temp_dir \
            -o aligned

        cp aligned/*report.txt ${reportFolder}
    }

    output {

        File alignedBam = glob("aligned/*.bam")[0]
        File alignedReport = glob("aligned/*report.txt")[0]
    }
}

task processBam {

    File alignedBam
    File alignedReport
    File genome_folder
    String file_basename
    Boolean paired
    Int threadN
    String targetFolder
    String reportFolder

    String commandText  = if paired then "-p" else "-s"

    command {

        mkdir Dedup
        mkdir Call

        sambamba sort --natural-sort -m 8GB --tmpdir temp_dir -t ${threadN} -o ${file_basename}_nSorted.bam ${alignedBam}
        
        bismark_methylation_extractor ${commandText} --comprehensive --bedGraph --gzip --genome_folder ${genome_folder} \
            --multicore ${threadN} \
            -o Call ${file_basename}_nSorted.bam

        mv Call/*splitting_report.txt ${file_basename}_splitting_report.txt
        mv Call/*M-bias.txt ${file_basename}_M-bias.txt

        bismark2report --alignment_report ${alignedReport} \
            --mbias_report ${file_basename}_M-bias.txt \
            --splitting_report ${file_basename}_splitting_report.txt \
            -o ${file_basename}_report.html

        sambamba sort -m 8GB --tmpdir temp_dir -t ${threadN} -o ${file_basename}.bam ${file_basename}_nSorted.bam

        cp ${file_basename}.bam ${targetFolder}
        cp ${file_basename}.bam.bai ${targetFolder}
        cp ${file_basename}*.txt ${reportFolder}
        cp ${file_basename}_report.html ${targetFolder}
        cp -R Call ${targetFolder}
    }

    output {

        File DedupBam = "${file_basename}.bam"
        File DedupBam_index = "${file_basename}.bam.bai"
    }
}

task makeDir {

    String targetFolder

    command {
        
        if [ ! -d $targetFolder ] ; then
            mkdir ${targetFolder}
        else
            rm -rf ${targetFolder}
            mkdir ${targetFolder}
        fi
    }

    output {
        String outFolder = "${targetFolder}"
    }
}

WDL使用流程

WDL 腳本核心結(jié)構(gòu)包括 5 個基本組件:workflow, task, call, command 以及 output肴掷。workflow 即是描述整個流程的框架敬锐,其中調(diào)用( call )了不同的 task 。每一個 task 中又定義了各自的命令 command 和輸出結(jié)果 output呆瞻,位于workflow 外部台夺。通過json文件傳入?yún)?shù)。

結(jié)構(gòu)概覽:

# workflow部分
workflow your_workflow_name {
    String var1
    Int var2
    File var3
    ...
    
    call task_name1 {
        input:
            var1 = ...
            ...
    }
    
    ...
    
    output {
        ...
    }
}

# task部分
task task_name1 {
    String var1
    Int var2
    File var3
    ...
    
    command {
        ...
    }
    
    output{
    ...
    {
{

...

編寫workflow部分

這一部分就是編寫你的整個流程痴脾,包括聲明變量颤介、調(diào)用(call)任務(wù)(task),定義輸出等部分。

語法結(jié)構(gòu)為:

workflow workflow_name {
    var_type1 var1
    var_type2 var2
    ...
    
    call task1 {
        input:
            ...
    }
    
    call task1 {
        input:
            ...
    }
    
    output {
        File ...
    # 其實不太理解workflow部分的output有什么作用
}

在 WDL 中共有五種基本變量類型:

  • String 表示字符串
  • Float 為浮點數(shù)
  • Int 為整數(shù)
  • Boolean 為布爾型
  • File 表示文件

創(chuàng)建變量時,必須聲明變量類型:String str1 = "hello"

另外滚朵,WDL 還支持復(fù)合類型:

  • Array 為數(shù)組
  • Map 為字典
  • Object 為對象

有些聲明加上了一個 ? 冤灾,這表示該變量為可選變量。

使用變量:${var_name}

字符可以使用+直接相加辕近,合并后的字符之間無空格韵吨,相對應(yīng)R語言的paste0()函數(shù)

if語句:if xxx then xxx else,可讀性很高

按照示例代碼解釋一遍:

# 創(chuàng)建名為bismarkRRBS的workflow
workflow bismarkRRBS {

# 聲明所有要使用的變量
    String file_basename
    String masterFolder
    File Fastq_R1
    File? Fastq_R2
    Boolean paired
    Boolean MspI
    Int clip_R1
    Int? clip_R2
    Int three_prime_clip_R1
    Int? three_prime_clip_R2
    String genome_folder
    Int threadN

    String targetFolder = masterFolder + "/" + file_basename + "/"

# 調(diào)用任務(wù)亏推。要讀懂call部分学赛,還是要先看定義的task部分
    call makeDir as md1 {
        input:
            targetFolder = targetFolder
    }

    call makeDir as md2 {
        input:
            targetFolder = md1.outFolder + "report"
    }

    call trim_galore {
        input:
            Fastq_R1 = Fastq_R1,
            Fastq_R2 = Fastq_R2,
            clip_R1  = clip_R1,
            clip_R2  = clip_R2,
            three_prime_clip_R1 = three_prime_clip_R1,
            three_prime_clip_R2 = three_prime_clip_R2,
            paired   = paired,
            MspI     = MspI,
            targetFolder = md1.outFolder,
            reportFolder = md2.outFolder,
            file_basename = file_basename
    }

    call bismark {
        input:
            R1_trimmed = trim_galore.R1_trimmed,
            R2_trimmed = trim_galore.R2_trimmed,
            paired  = paired,
            threadN = threadN,
            file_basename = file_basename,
            genome_folder = genome_folder,
            targetFolder  = md1.outFolder,
            reportFolder  = md2.outFolder
    }

    call processBam {
        input:
            file_basename = file_basename,
            alignedBam    = bismark.alignedBam,
            genome_folder = genome_folder,
            alignedReport = bismark.alignedReport,
            paired  = paired,
            threadN = threadN,
            targetFolder = md1.outFolder,
            reportFolder = md2.outFolder
    }

    output {

        File DedupBam = processBam.DedupBam
        File DedupBam_index = processBam.DedupBam_index
    }

}

編寫task部分

task部分語法:

task task_name {
    var_type1 var1
    ...
    
    command {
        ...
    }
    output {
        ...
    }
}       

task的output部分可以被后面的task所調(diào)用,不用output聲明則不能被調(diào)用吞杭。

以結(jié)構(gòu)最簡單的創(chuàng)建目錄task為例:

# 創(chuàng)建名為makeDir的task
task makeDir {

# 聲明該task中要使用的變量
    String targetFolder
# 編寫該task的命令
    command {
        
        if [ ! -d $targetFolder ] ; then
            mkdir ${targetFolder}
        else
            rm -rf ${targetFolder}
            mkdir ${targetFolder}
        fi
    }
    
# 該task的定義了名為outFolder內(nèi)容為"${targetFolder}"的一個變量
    output {
        String outFolder = "${targetFolder}"
    }
}

創(chuàng)建json文件

編寫好的wdl腳本只是一個pipeline盏浇,沒有具體(specific)的參數(shù)。所用使用json文件進(jìn)行傳參芽狗。json文件以.json為后綴绢掰,其格式為:

{
    “workflow_name.var1":"specific_var1",
    “workflow_name.var1":"specific_var2",
    ...
}

需要注意的是,除了最后一行不需要加逗號童擎,其余行必須加逗號滴劲。

創(chuàng)建json文件的代碼:

# 創(chuàng)建包含配置信息的list
xList = list(var1 = ..., 
             var2 = ...,
             var3 = ...,
             ...)

# 編寫writeJSON函數(shù)
writeJSON <- function(xList, mainTag, fileOut){

    names(xList) = paste0(mainTag, ".", names(xList))
    NM  = names(xList)
    OUT = file(fileOut, "w")
    cat("{\n", file = OUT, append = FALSE, sep = "")

    for(i in 1:length(xList)){

        value = xList[[i]]
        if(i < length(xList))
            cat("\t\"", NM[i], "\":\"", value, "\",\n", file=OUT, append = TRUE, sep = "")
        else
            cat("\t\"", NM[i], "\":\"", value, "\"\n", file=OUT, append = TRUE, sep = "")
    }
    cat("}\n", file = OUT, append = TRUE, sep = "")

    close(OUT)
}

JSON = paste0("JSON/", Tag, ".json")
writeJSON(xList, "workflow_name", JSON)

Tag指的是數(shù)據(jù)樣本的Tag。

writeJSON函數(shù)可以寫到另外一個文件中顾复,然后再source調(diào)用比較方便班挖。

運行WDL腳本

不需要安裝,只需要用調(diào)用java包即可芯砸。

wget https://github.com/broadinstitute/cromwell/releases/download/47/cromwell-47.jar
java -jar cromwell-47.jar run test.wdl --inputs test.json 

遞交任務(wù)

通過使用qsub命令來對資源使用限量進(jìn)行設(shè)置萧芙,并重定向stderr和stdout。

cmd = "java -jar cromwell-47.jar run test.wdl --inputs test.json"
cmd = paste0("echo ", "\"", cmd, "\"")
cmd = paste(cmd, "| qsub -N", jobName)
cmd = paste(cmd, "-l h_cpu=720:00:00 -V -m n -cwd -pe smp", Ncpu)
cmd = paste0(cmd, " -l h_vmem=", Memory, "G")
cmd = paste(cmd, "-o", outFile, "-e", errFile)
systerm(cmd)

同樣可以寫成一個函數(shù)假丧,source調(diào)用双揪。

多樣本處理

以上講的是單個或單組樣本的workflow,但一般情況下包帚,會得到多個raw_data渔期,這樣就需要循環(huán)上面的workflow。寫個for循環(huán)即可渴邦,從1樣本的數(shù)量循環(huán)疯趟,提取每個樣本的Tag,并以此作為jobName和要保存的文件的文件夾名几莽。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末迅办,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子章蚣,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纤垂,死亡現(xiàn)場離奇詭異矾策,居然都是意外死亡,警方通過查閱死者的電腦和手機峭沦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門贾虽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吼鱼,你說我怎么就攤上這事蓬豁。” “怎么了菇肃?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵地粪,是天一觀的道長。 經(jīng)常有香客問我琐谤,道長蟆技,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任斗忌,我火速辦了婚禮质礼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘织阳。我一直安慰自己眶蕉,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布唧躲。 她就那樣靜靜地躺著造挽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惊窖。 梳的紋絲不亂的頭發(fā)上刽宪,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音界酒,去河邊找鬼圣拄。 笑死,一個胖子當(dāng)著我的面吹牛毁欣,可吹牛的內(nèi)容都是我干的庇谆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼凭疮,長吁一口氣:“原來是場噩夢啊……” “哼饭耳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起执解,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤寞肖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體新蟆,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡觅赊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了琼稻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吮螺。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖帕翻,靈堂內(nèi)的尸體忽然破棺而出鸠补,到底是詐尸還是另有隱情,我是刑警寧澤嘀掸,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布紫岩,位于F島的核電站,受9級特大地震影響横殴,放射性物質(zhì)發(fā)生泄漏被因。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一衫仑、第九天 我趴在偏房一處隱蔽的房頂上張望梨与。 院中可真熱鬧,春花似錦文狱、人聲如沸粥鞋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呻粹。三九已至,卻和暖如春苏研,著一層夾襖步出監(jiān)牢的瞬間等浊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工摹蘑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留筹燕,地道東北人。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓衅鹿,卻偏偏與公主長得像撒踪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子大渤,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容