3、Snakemake基本概念:规则、输入输出文件、通配符、运行方式(本地/集群),Snakefile结构

各位好,我是老周。今天咱们聊聊Snakemake的几个核心概念。说白了,你只要能搞懂规则、通配符、输入输出文件这三样,流水线的基本骨架就搭起来了。

我最初用Snakemake时,以为规则名随便写就行。结果项目一复杂,自己都看不懂。后来养成了按功能命名的习惯——规则名就是文档,省得写注释。

Snakemake 核心概念关系图 Snakefile 规则 (Rule) input / output 通配符 {wildcard} 本地运行 集群提交 核心逻辑 Snakefile 定义规则 → 规则通过 input/output 和通配符匹配文件 → 根据运行方式(本地或集群)执行对应 shell 命令或脚本

3.1 规则:流水线的执行单元

规则就是Snakemake的最小执行单元。每个规则描述一件事——比如对某个样本做质控、比对或变异检测。

一个标准规则长这样:

rule fastqc:
    input:
        "data/sample1.fastq"
    output:
        "results/sample1_fastqc.html"
    shell:
        "fastqc {input} -o results/"

我个人习惯用缩进来区分规则块。input指定原材料,output指定产物,shell写实际运行的命令。这三个字段一出来,规则的三要素就齐了。

规则名(比如这里的fastqc)可以随便取,但我建议用动词开头。我踩过坑——项目里取了个step1,一个月后回来看完全不知道它干了什么。

命名建议:规则名用 动词_对象 格式,比如 run_fastqc、align_bwa,一看就知道在做什么。

3.2 输入输出文件:流水线的物料清单

input和output定义了文件的依赖关系。Snakemake会自动检查output是否已存在,如果缺了某个文件,它就向上回溯,找生成它的规则。

你看这段代码:

rule bwa_mem:
    input:
        ref="genome/hg38.fa",
        fq1="data/sample1_R1.fastq",
        fq2="data/sample1_R2.fastq"
    output:
        "results/sample1.sam"
    shell:
        "bwa mem {input.ref} {input.fq1} {input.fq2} > {output}"

这里用了命名输入,把每个文件都起了别名。项目一大,你就能体会到这样做的价值——我在处理8个样本时,就靠这些别名避免了顺序混淆。

3.3 通配符:让规则动起来

通配符是Snakemake的灵魂。没有通配符,你得为每个样本写一条规则。有了通配符,一条规则就能覆盖所有样本。

来个例子:

rule fastqc:
    input:
        "data/{sample}.fastq"
    output:
        "results/{sample}_fastqc.html"
    shell:
        "fastqc {input} -o results/"

{sample}就是通配符。你运行snakemake results/sample1_fastqc.html,Snakemake会自动把{sample}替换成sample1。

通配符可以组合使用。比如data/{sample}_{lane}.fastq,能同时匹配sample1_L001、sample1_L002等。

避坑:通配符必须能在output里唯一确定。如果两个规则用同样的通配符产生同样的output,Snakemake会报歧义错误。我曾被这个坑了整整一个下午。
通配符模式 匹配示例 用途场景
{sample} sample1, NA12878, HCC1395 按样本名处理
{lane} L001, L002, L003 按测序lane拆分
{chr} chr1, chrX, chr22 按染色体分任务
{run_id} run20240301, run20240302 按批次处理

3.4 两种运行方式:本地和集群

Snakemake默认在本地运行,按顺序或按你指定的线程数并行处理。

本地运行命令很简单:

snakemake -j 4

-j 4表示同时跑4个任务。小项目用这个足够了。

但质控项目往往涉及上百个样本,本地跑太慢。这时候就需要集群模式。Snakemake支持SLURM、SGE、LSF等主流调度系统。

比如对接SLURM:

snakemake --cluster "sbatch -t 01:00:00 -c 4 --mem=8G" -j 20

这个命令的意思是:每个任务提交到SLURM,申请1小时、4核、8G内存,最多同时提交20个任务。

个人经验:集群模式下,-j控制的是同时提交的任务数,不是用多少核。我刚开始总搞混,导致集群负载过高被管理员约谈。

3.5 Snakefile结构:流水线的设计图纸

Snakefile是Snakemake的入口文件。它定义了所有规则和全局配置。一个标准的Snakefile结构大概是:

# 1. 全局配置
SAMPLE_IDS = ["sample1", "sample2", "sample3"]
DATA_DIR = "data"
RESULTS_DIR = "results"

# 2. 默认规则(运行 snakemake 时的默认目标)
rule all:
    input:
        expand("{results}/{sample}_fastqc.html",
               results=RESULTS_DIR, sample=SAMPLE_IDS)

# 3. 具体规则
rule fastqc:
    input:
        "{data}/{sample}.fastq"
    output:
        "{results}/{sample}_fastqc.html"
    shell:
        "fastqc {input} -o {results}/"

这里有个关键点:rule all没有实际任务,它只声明了最终结果。Snakemake看到rule all缺少什么文件,就会自动去执行相关规则来生成。

我常用的Snakefile结构分四层:

  • 配置层:定义样本列表、路径、参数
  • all规则层:声明最终产出
  • 业务规则层:质控、比对、排序、变异检测等
  • 辅助函数层:提取公共逻辑

这种分层的好处是——修改样本列表时,只需要动配置层,规则完全不变。

小技巧:Snakefile本质上是Python代码。所以你可以用glob.glob()动态获取输入文件,用os.path.basename()处理路径,甚至引入pandas读取样本表——这些我都实际用过,写起来很顺手。

好了,Snakemake的这几个核心概念就讲到这里。规则定义执行逻辑,通配符让规则批量生效,输入输出串联起流水线的上下游,本地和集群两种模式适配不同的计算环境。Snakefile就像一张蓝图,把这些要素组织成清晰的结构。下一回咱们聊聊配置文件的使用——怎么用YAML或JSON管理样本信息,让流水线更加灵活。