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

如何避免Snakemake在expand返回空文件列表时执行无通配符聚合规则?

问题:Snakemake工作流中如何避免空输入规则执行?

我正在开发一个带有可选规则的Snakemake工作流,这些规则仅当制表符分隔的样本文件中存在可选元数据时才会执行。简单来说,原始样本数据可以先运行前十几条规则,后续步骤需要耗时收集的重复样本信息,而前十几条规则的输出能辅助这项收集工作。

我已经设置了分开的all规则来运行工作流的不同部分,但希望all规则能尽可能执行所有可运行的步骤:没有元数据时只运行前十几条规则,有元数据时则运行全部规则。

目前的实现大体可行,但存在一个问题:当元数据缺失时,一条无通配符的聚合规则会尝试在没有输入的情况下运行。该规则如下:

rule combine_idr_peaks:
    input:
        expand(
            "results/idr/{dataset}/merged.idr.narrowPeak",
            dataset=DATASETS,
        ),
    output:
        temp("results/idr/merged.idr.narrowPeak"),
    conda:
        "../envs/bedtools_coreutils.yml"
    shell:
        """
        cat {input:q} | \
        sortBed | \
        mergeBed > {output:q}
        """

当元数据缺失时,使用--printshellcmds参数查看命令,会得到如下内容:

cat  | sortBed | mergeBed > results/idr/merged.idr.narrowPeak

显然,工作流会挂起,因为cat命令在等待输入。
DATASETS变量由蛇形文件顶部的元数据填充,测试时故意缺失该可选元数据。

请问如何让Snakemake在输入为空时不执行该规则?


解决方案

方法1:动态控制all目标的输入列表

既然DATASETS是决定输入是否为空的核心变量,你可以在all规则中根据DATASETS是否为空,动态决定是否包含聚合规则的输出:

rule all:
    input:
        # 前十几条规则的固定输出
        "results/initial_step1.txt",
        "results/initial_step2.txt",
        # 仅当DATASETS非空时,才添加聚合规则的输出
        *([] if not DATASETS else ["results/idr/merged.idr.narrowPeak"])

当DATASETS为空时,all规则不会要求生成聚合文件,Snakemake也就不会触发combine_idr_peaks规则,从根源上避免了空输入问题。

方法2:在规则内添加输入有效性判断

如果需要保留规则定义,可以在shell脚本中添加条件判断,输入为空时直接创建空输出文件,避免cat命令挂起:

rule combine_idr_peaks:
    input:
        peaks=expand(
            "results/idr/{dataset}/merged.idr.narrowPeak",
            dataset=DATASETS,
        ),
    output:
        temp("results/idr/merged.idr.narrowPeak"),
    conda:
        "../envs/bedtools_coreutils.yml",
    params:
        has_input=lambda wildcards, input: len(input.peaks) > 0,
    shell:
        """
        if [[ {params.has_input} -eq 1 ]]; then
            cat {input.peaks:q} | sortBed | mergeBed > {output:q}
        else
            # 输入为空时创建空文件,满足Snakemake的输出要求
            touch {output:q}
        fi
        """

方法3:使用条件规则(Snakemake 7.0+)

如果你的Snakemake版本在7.0及以上,可直接用条件语句包裹规则,仅当DATASETS非空时才定义该规则:

if DATASETS:
    rule combine_idr_peaks:
        input:
            expand(
                "results/idr/{dataset}/merged.idr.narrowPeak",
                dataset=DATASETS,
            ),
        output:
            temp("results/idr/merged.idr.narrowPeak"),
        conda:
            "../envs/bedtools_coreutils.yml",
        shell:
            """
            cat {input:q} | sortBed | mergeBed > {output:q}
            """

这种方式最直观,DATASETS为空时规则不会被加载,自然不会被执行。


内容的提问来源于stack exchange,提问作者hepcat72

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:34:55