snakemake 應(yīng)用介紹

接觸到一個(gè)生信分析項(xiàng)目碎罚,作者基于snakemake 串起了17個(gè)用python 腳本編寫的分析流程。自己在搭建的Linux 環(huán)境下纳像,測試了這些腳本荆烈。此文簡要介紹snakemake 的基礎(chǔ)知識(shí)和實(shí)際分析的細(xì)節(jié)。

snakemake 簡介

Snakemake工作流管理系統(tǒng)是一個(gè)用于創(chuàng)建可重復(fù)竟趾、可擴(kuò)展的數(shù)據(jù)分析的工具憔购。snakemake的工作流基于python語言來完成,具有可讀性強(qiáng)岔帽、能無縫地?cái)U(kuò)展到服務(wù)器玫鸟、集群、網(wǎng)格和云環(huán)境犀勒,而不需要修改工作流定義等特性屎飘。此外,Snakemake工作流可以包含所需軟件的描述贾费,這些軟件將自動(dòng)部署到任何執(zhí)行環(huán)境中钦购。

snakemake 的幾個(gè)特性

  • 可讀性強(qiáng):snakemake 通過制定每一條規(guī)則(rule)來定義每一個(gè)分析步驟,在規(guī)則中定義輸入(input)褂萧、輸出文件(output)押桃。不同規(guī)則的依賴性則自動(dòng)識(shí)別。
  • 分析流程的模塊化:可以將數(shù)據(jù)分析拆分成不同模塊导犹,通過腳本或shell 命令完成凉袱。
  • 可擴(kuò)展性:結(jié)合conda 環(huán)境和配置文件弯淘,可以輕松實(shí)現(xiàn)環(huán)境的導(dǎo)出,擴(kuò)展至其他環(huán)境下。

snakemake 語法基礎(chǔ)

安裝snakemake

建議通過conda 創(chuàng)建一個(gè)環(huán)境譬重,通過conda 完成安裝
https://snakemake.readthedocs.io/en/stable/getting_started/installation.html

創(chuàng)建 snakefile

rule bwa_map: # 定義規(guī)則名柳刮,也是分析的步驟名
    input: # 指定輸入文件尝抖,多個(gè)輸入文件伴嗡,以逗號(hào)分隔
        "data/genome.fa",
        "data/samples/A.fastq"
    output:  # 指定輸出文件
        "mapped_reads/A.bam"
    shell: # 運(yùn)行shell 命令,有多行命令時(shí),使用三引號(hào)纫骑。大括號(hào)實(shí)現(xiàn)自動(dòng)替換內(nèi)容
        "bwa mem {input} | samtools view -Sb - > {output}"

若文件夾不存在時(shí)蝎亚,snakemake 會(huì)自動(dòng)創(chuàng)建文件夾。

運(yùn)行 snakefile

當(dāng)所在環(huán)境已安裝snakemake 后先馆,且該目錄下存在snakefile发框,執(zhí)行snakemake --cores,該命令會(huì)自動(dòng)匹配snakefile文件煤墙,并運(yùn)行其中的規(guī)則梅惯。snakemake 采取自頂向下的方式執(zhí)行分析步驟,也會(huì)識(shí)別其中的依賴關(guān)系仿野。

snakemake 執(zhí)行過程中有一些常見的參數(shù)铣减,能為分析過程中提供一些便利。

-s  指定Snakefile脚作,
-n  不真正執(zhí)行葫哗,
-p   輸出要執(zhí)行的shell命令
-r  輸出每條rule執(zhí)行的原因,默認(rèn)FALSE
-j  指定運(yùn)行的核數(shù),若不指定球涛,則使用最大的核數(shù)
-f 重新運(yùn)行第一條rule或指定的rule
-F 重新運(yùn)行所有的rule劣针,不管是否已經(jīng)有輸出結(jié)果

snakemake 進(jìn)階實(shí)戰(zhàn)

聲明進(jìn)程數(shù)

rule samtools_sort:
    input:
        "mapped_reads/{sample}.bam"
    output:
        "sorted_reads/{sample}.bam"
    threads:
        56
    shell:
        "samtools sort -T sorted_reads/{wildcards.sample} "
        "-O bam {input} > {output}"

配置文件

配置文件可以用JSON或YAML語法進(jìn)行寫,然后用在snakemake 文件中聲明亿扁,configfile: "FilePath/config.yaml"捺典。需要使用cofigfile 的信息時(shí),通過config[鍵]來獲取从祝。

包括config.yaml 的snakefile 文件

configfile: "config.yaml"

rule bcftools_call:
    input:
        fa="data/genome.fa",
        bam=expand("sorted_reads/{sample}.bam", sample=config["samples"]), # config["samples"])
        bai=expand("sorted_reads/{sample}.bam.bai", sample=config["smaples"])
    output:
        "calls/all.vcf"
    shell:
       '''
samtools mpileup -g -f {input.fa} {input.bam} | 
bcftools call -mv - > {output}
       '''

config.yaml 文件內(nèi)容

samples:
    A: data/samples/A.fastq
    B: data/samples/B.fastq

基于snakemake 的snuupy 項(xiàng)目

https://github.com/ZhaiLab-SUSTech/snuupy/tree/master

該項(xiàng)目是一個(gè)對(duì)單細(xì)胞核測序數(shù)據(jù)的二代測序數(shù)據(jù)和三代測序數(shù)據(jù)的snakemake 的分析流程襟己,涉及17個(gè)python 腳本,完全通過python 完成各個(gè)分析步驟哄褒。

Job counts:
    count   jobs
    1   addGeneName
    1   addPolyATag
    1   addUnmappedBaseTag
    1   all
    1   barcodeAssignment
    1   generateIlluminaWindow
    1   generateMtx
    1   generateNanoporeWindow
    1   getMismatch
    1   getSpliceInfo
    1   minimapMappingPolished
    1   minimapMappingRaw
    1   parseIllumina
    1   polishReads
    1   polyAClusterDetected
    1   runCellRanger
    1   windowBlast
    17

snuupy snakemake 的部分內(nèi)容

configfile: "/public/home/liuzj/publicPipeline/snuupy/snakemake/config.yaml"
pipelineDir = config['pipelineDir']

# 對(duì)于包括多個(gè)規(guī)則的snakemake 文件,這一條rule all 是必須的煌张。這是一個(gè)特殊的規(guī)則呐赡,只有一個(gè)輸入文件,該文件是snakemake 分析流程的目標(biāo)文件骏融。
rule all:
    input:
        generateMtxFinished = f"{config['resultDir']}step16_generateMtx/generateMtxFinished.empty"  # f'***'python 語法链嘀,格式化字符輸出

rule parseIllumina:
    input:
        runCellRangerFinished = f"{config['resultDir']}step1_runCellRanger/runCellRangerFinished.empty"
    output:
        parseIlluminaResults = f"{config['resultDir']}step2_parseIllumina/parseIlluminaResults.index"
    params:
        genomeFai = config['genomeFai'],
        useBarcodeGz = f"{config['resultDir']}step1_runCellRanger/test/outs/filtered_feature_bc_matrix/barcodes.tsv.gz",
        useBarcode = f"{config['resultDir']}step1_runCellRanger/test/outs/filtered_feature_bc_matrix/barcodes.tsv",
        runCellRangerBam = f"{config['resultDir']}step1_runCellRanger/test/outs/possorted_genome_bam.bam",
        windowSize = 500,
        gpu = "0"

    threads:2
    shell:
        """
cd {pipelineDir}
gzip -d -c {params.useBarcodeGz} > {params.useBarcode} &&
python ./snuupy/snuupy.py parseIllumina --bam {params.runCellRangerBam} --barcode {params.useBarcode} --genome {params.genomeFai} --window {params.windowSize} --parsed {output.parseIlluminaResults}
        """

以上文件中shell 命令是通過python 的命令行參數(shù)輸入來完成的,這主要通過一個(gè)python 模塊click 來完成档玻。在snuupy 文件中定義parseIllumina 函數(shù)需要的參數(shù)怀泊,在命令行中的解析這些參數(shù),傳遞給執(zhí)行腳本误趴,完成分析步驟霹琼。

click 模塊主要包括兩個(gè)必要參數(shù):
@main.command("parseIllumina")
@click.option(***)

# snuupy.py
import click

@click.group()
def main():
    pass

@main.command("parseIllumina")
@click.option("--bam", "secondBam", help="cellranger result")
@click.option(
    "--barcode",
    "secondIndex",
    help="the filtered barcode list which is output by cellranger; format tsv NOT gz!!!",
)
@click.option("--genome", "genomeIndex", help="the fai format file")
@click.option(
    "--genomeCounts",
    "useColumn",
    default=5,
    type=int,
    show_default=True,
    help="chromosome counts",
)
@click.option("--window", "windowSize", type=int, default=500, help="window size")
@click.option("--parsed", "parsedIndex", help="the parsedIndex; end with .index")
def _parseIllumina(
    secondBam, secondIndex, genomeIndex, windowSize, parsedIndex, useColumn
):
    """
    \b
    parse Illumina bam file and generate Illumina index
    """
## 導(dǎo)入實(shí)際分析腳本
    from scripts.parseIllumina import parseIllumina

    parseIllumina(
        secondBam, secondIndex, genomeIndex, windowSize, parsedIndex, useColumn
    )

配置文件部分內(nèi)容
配置文件中也可以包括yaml 文件。

pipelineDir:
  '/public/home/liuzj/publicPipeline/snuupy/'
resultDir:
  '/public/home/liuzj/publicPipeline/snuupy/example/snakemakeResults/'

#inpuf files
rawNanoporeFa:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/nanopore.fa'
nanoporeWorkspace:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/workspace'
nanoporeSeqSummary:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/nanoporeSeqSummary.txt'

#genome files
geneAnnoBed:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/ref/annoFile/gene.bed'
geneAnnoRepreBed:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/ref/annoFile/araport11.representative.gene_model.bed'
geneNot12Bed:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/ref/annoFile/geneNotBed12.bed'
genomeFa:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/ref/annoFile/genome.fa'
genomeFai:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/ref/annoFile/genome.fa.fai'
usedIntron:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/ref/annoFile/select_intron_by_Cyto.id.txt'

#softwares path
minimap2Path:
  '/public/home/liuzj/softwares/anaconda3/bin/minimap2'
picardPath:
  '/public/home/liuzj/softwares/picard/picard.jar'
seqkitPath:

#cellranger configs
runCellRangerConfig:
  '/public/home/liuzj/publicPipeline/snuupy/removeExonRegion/cellRangerParameter.yaml'

#reads path
illuminaFastqs:
  '/public/home/liuzj/publicPipeline/snuupy/example/00_data/illuminaFastq/'

總結(jié)

在snuupy 項(xiàng)目中,一個(gè)分析步驟涉及多個(gè)輸入文件枣申,使用snakemake 流程具有獨(dú)特的優(yōu)勢(shì)售葡。而且分析過程中,多處涉及同一個(gè)分析工具忠藤,將其寫入配置文件挟伙,也是簡化輸入的方式。

因?yàn)樯婕暗胶芏鄠€(gè)分析步驟模孩,先將命令打印出來尖阔,再對(duì)個(gè)別步驟單獨(dú)測試,或者直接運(yùn)行特定snakemake rule榨咐,是比較好的測試思路介却。


參考
snakemake 官方文檔
使用Snakemake搭建分析流程
snakemake 使用筆記
https://github.com/ZhaiLab-SUSTech/snuupy/tree/master
Python Click 模塊

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市祭芦,隨后出現(xiàn)的幾起案子筷笨,更是在濱河造成了極大的恐慌,老刑警劉巖龟劲,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胃夏,死亡現(xiàn)場離奇詭異,居然都是意外死亡昌跌,警方通過查閱死者的電腦和手機(jī)仰禀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蚕愤,“玉大人答恶,你說我怎么就攤上這事∑加眨” “怎么了悬嗓?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長裕坊。 經(jīng)常有香客問我包竹,道長,這世上最難降的妖魔是什么籍凝? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任周瞎,我火速辦了婚禮,結(jié)果婚禮上饵蒂,老公的妹妹穿的比我還像新娘声诸。我一直安慰自己,他們只是感情好退盯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布彼乌。 她就那樣靜靜地躺著泻肯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪囤攀。 梳的紋絲不亂的頭發(fā)上软免,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天,我揣著相機(jī)與錄音焚挠,去河邊找鬼膏萧。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蝌衔,可吹牛的內(nèi)容都是我干的榛泛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼噩斟,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼曹锨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起剃允,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤沛简,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后斥废,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體椒楣,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年牡肉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捧灰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡统锤,死狀恐怖毛俏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饲窿,我是刑警寧澤煌寇,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站逾雄,受9級(jí)特大地震影響阀溶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嘲驾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一淌哟、第九天 我趴在偏房一處隱蔽的房頂上張望迹卢。 院中可真熱鬧辽故,春花似錦、人聲如沸腐碱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喂走,卻和暖如春殃饿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芋肠。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國打工乎芳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帖池。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓奈惑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親睡汹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肴甸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

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