You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Snakemake按染色体拆分文件后无法识别输入/输出文件的问题

嘿,这个问题我太熟了——在Snakemake里处理动态生成的文件(比如按染色体拆分BAM这种没法提前知道输出数量的场景)确实容易踩坑,不过咱们用checkpoint功能就能完美解决!下面给你一步步的具体方案:

核心思路

Snakemake的checkpoint专门用来处理规则生成未知数量输出的情况。我们先通过checkpoint执行BAM拆分,再用自定义函数收集拆分后的文件,让后续的变异检测和VCF合并规则能自动识别这些动态生成的输入输出。

具体实现步骤

1. 用Checkpoint拆分BAM文件

先写一个checkpoint规则,把拆分后的BAM统一放到单独目录里,方便后续收集:

checkpoint split_bam:
    input:
        "sample.bam"
    output:
        directory("split_bams")  # 创建目录存放拆分后的BAM
    shell:
        """
        mkdir -p split_bams
        # bamtools split会自动在-out指定的前缀后加上染色体名和.bam后缀
        bamtools split -in {input} --reference -out split_bams/sample.REF_
        """

2. 编写函数收集拆分后的BAM

接下来写一个辅助函数,从checkpoint的输出目录里收集所有拆分后的BAM文件,并提取对应的染色体名称:

import os
import glob

def get_split_bams(wildcards):
    # 获取checkpoint的输出目录
    checkpoint_dir = checkpoints.split_bam.get_output(wildcards)[0]
    # 遍历目录下所有BAM文件,提取染色体名
    bam_files = glob.glob(os.path.join(checkpoint_dir, "*.bam"))
    chroms = [os.path.basename(f).replace("sample.REF_", "").replace(".bam", "") for f in bam_files]
    # 返回所有拆分BAM的路径列表
    return expand("split_bams/sample.REF_{chrom}.bam", chrom=chroms)

3. 变异检测规则

现在可以针对每个拆分后的BAM文件写变异检测规则,用wildcard匹配染色体:

rule call_variants:
    input:
        lambda wildcards: f"split_bams/sample.REF_{wildcards.chrom}.bam"
    output:
        "split_vcfs/sample.REF_{chrom}.vcf"
    shell:
        """
        mkdir -p split_vcfs
        # 替换成你实际使用的变异检测命令,比如FreeBayes、GATK等
        freebayes -f reference.fasta {input} > {output}
        """

记得把freebayes -f reference.fasta {input} > {output}换成你真实的变异检测命令哦。

4. 合并VCF文件

最后写合并规则,收集所有拆分后的VCF文件,用vcf-concat合并:

def get_split_vcfs(wildcards):
    # 收集所有拆分后的VCF文件
    vcf_files = glob.glob("split_vcfs/*.vcf")
    chroms = [os.path.basename(f).replace("sample.REF_", "").replace(".vcf", "") for f in vcf_files]
    return expand("split_vcfs/sample.REF_{chrom}.vcf", chrom=chroms)

rule merge_vcfs:
    input:
        get_split_vcfs
    output:
        "sample.vcf"
    shell:
        """
        vcf-concat {input} > {output}
        """

可选方案:提前提取染色体列表

如果你不想用checkpoint,也可以先写一个规则提取BAM里的染色体列表,再基于这个列表生成所有输入输出:

rule get_chromosomes:
    input:
        "sample.bam"
    output:
        "chroms.txt"
    shell:
        """
        # 用samtools提取染色体名,过滤掉未比对的序列(*)
        samtools idxstats {input} | cut -f1 | grep -v '*' > {output}
        """

# 读取染色体列表
CHROMS = open("chroms.txt").read().splitlines()

rule split_bam:
    input:
        "sample.bam"
    output:
        expand("sample.REF_{chrom}.bam", chrom=CHROMS)
    shell:
        """
        bamtools split -in {input} --reference
        """

# 后续的call_variants和merge_vcfs规则可以直接用CHROMS变量来生成输入输出

不过这个方案的缺点是,如果BAM文件更新了,需要手动重新运行get_chromosomes规则,而checkpoint的方式更灵活,能自动适配BAM的变化。

这样处理后,Snakemake就能自动识别所有动态生成的文件,再也不会报unknown output/input files的错误啦!

内容的提问来源于stack exchange,提问作者Wouter De Coster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:18:31