3、Snakemake基本概念:规则、输入输出文件、通配符、运行方式(本地/集群),Snakefile结构
各位好,我是老周。今天咱们聊聊Snakemake的几个核心概念。说白了,你只要能搞懂规则、通配符、输入输出文件这三样,流水线的基本骨架就搭起来了。
我最初用Snakemake时,以为规则名随便写就行。结果项目一复杂,自己都看不懂。后来养成了按功能命名的习惯——规则名就是文档,省得写注释。
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等。
| 通配符模式 | 匹配示例 | 用途场景 |
|---|---|---|
| {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规则层:声明最终产出
- 业务规则层:质控、比对、排序、变异检测等
- 辅助函数层:提取公共逻辑
这种分层的好处是——修改样本列表时,只需要动配置层,规则完全不变。
glob.glob()动态获取输入文件,用os.path.basename()处理路径,甚至引入pandas读取样本表——这些我都实际用过,写起来很顺手。
好了,Snakemake的这几个核心概念就讲到这里。规则定义执行逻辑,通配符让规则批量生效,输入输出串联起流水线的上下游,本地和集群两种模式适配不同的计算环境。Snakefile就像一张蓝图,把这些要素组织成清晰的结构。下一回咱们聊聊配置文件的使用——怎么用YAML或JSON管理样本信息,让流水线更加灵活。