snakemake:未检测到不明确的规则?

snakemake: Ambiguous rule not detected?

以下 Snakefile 失败 AmbiguousRuleException:

library_id = ['S1']
run_id = ['R1']

samples = dict(zip(library_id, run_id))

rule all:
    input:
        expand('{library_id}.bam', library_id= library_id),

rule bwa:
    output:
        '{run_id}.bam',

rule merge_bam:
    input:
        lambda wc: '%s.bam' % samples[wc.library_id],
    output:
        '{library_id}.bam',

给出:


    AmbiguousRuleException:
    Rules bwa and merge_bam are ambiguous for the file S1.bam.
    Consider starting rule output with a unique prefix, constrain your wildcards, or use the ruleorder directive.
    Wildcards:
        bwa: run_id=S1
        merge_bam: library_id=S1
    Expected input files:
        bwa: 
        merge_bam: R1.bamExpected output files:
        bwa: S1.bam
        merge_bam: S1.bam

这是预料之中的,没关系。但是,如果 library_idrun_id 具有 相同的 值,则不会检测到歧义并且仅执行第一条规则:

library_id = ['S1']
run_id = ['S1'] # Same as library_id!

samples = dict(zip(library_id, run_id))

rule all:
    input:
        expand('{library_id}.bam', library_id= library_id),

rule bwa:
    output:
        '{run_id}.bam',

rule merge_bam:
    input:
        lambda wc: '%s.bam' % samples[wc.library_id],
    output:
        '{library_id}.bam',

干-运行执行:

Job counts:
    count   jobs
    1   all
    1   bwa
    2

[Mon Aug 23 11:27:39 2021]
localrule bwa:
    output: S1.bam
    jobid: 1
    wildcards: run_id=S1

[Mon Aug 23 11:27:39 2021]
localrule all:
    input: S1.bam
    jobid: 0

Job counts:
    count   jobs
    1   all
    1   bwa
    2
This was a dry-run (flag -n). The order of jobs does not reflect the order of execution.

这是一个错误还是我遗漏了什么?第二个例子应该像第一个一样给出 AmbiguousRuleException,而且更明显。

这是 snakemake 6.4.1

TL;DR

Snakemake 执行一些循环检查,并在 DAG 创建期间删除具有相同输入和输出文件的作业。在您的工作案例中,merge_bam 规则中的作业具有相同的 input/output 文件 (S1.bam),因此在 DAG 中不考虑它,并且在满足all 规则。

详情

Snakemake 从最终的目标文件开始(在本例中为 S1.bam)并向后工作以查找可以执行以从现有输入文件创建目标文件的参数化规则(作业)。为此,它递归调用 snakemake/dag.py::DAG.update()snakemake/dag.py::DAG.update_() 从初始目标文件构建 DAG。 DAG.update()following check 将作业从考虑中删除,如果它们产生与输入所需的相同的输出文件:

if file in job.input:
    cycles.append(job)
    continue

例如如果目标文件也是候选作业的输入文件,则跳过该候选作业。

在您的工作案例中,merge_bam 规则中的作业被视为生成 all 规则请求的 S1.bam 文件的候选对象。但是,merge_bam 作业还请求 S1.bam 作为它自己的输入,因此它无法通过上述循环检查。因此,它不被视为 all 规则请求的 S1.bam 文件的生产者,只留下 bwa 作业。

在例外情况下,merge_bam 规则输出 S1.bam 但要求 R1.bam 作为输入,因此它通过了循环检查并被视为 [= 的潜在生产者all 规则请求的 12=] 文件。由于 merge_bambwa 都可以产生 S1.bam(并且没有定义规则顺序),因此抛出 AmbiguousRuleException

结论

循环 DAG 和模糊规则的混合导致了这种不直观的行为。 Snakemake 的目的不是找出所有可能的规则歧义,所以我不一定会说这是一个错误。