Snakemake params函数是否在输入文件存在之前进行评估?

ted*_*oal 6 parameters snakemake

考虑一下这个蛇文件:

def rdf(fn):
    f = open(fn, "rt")
    t = f.readlines()
    f.close()
    return t

rule a:
    output: "test.txt"
    input: "test.dat"
    params: X=lambda wildcards, input, output, threads, resources: rdf(input[0])
    message: "X is {params.X}"
    shell: "cp {input} {output}"

rule b:
    output: "test.dat"
    shell: "echo 'hello world' >{output}"
Run Code Online (Sandbox Code Playgroud)

当运行并且test.txt和test.dat都不存在时,会出现此错误:

InputFunctionException in line 7 of /Users/tedtoal/Documents/BioinformaticsConsulting/Mars/Cacao/Pipeline/SnakeMake/t2:
FileNotFoundError: [Errno 2] No such file or directory: 'test.dat'
Run Code Online (Sandbox Code Playgroud)

但是,如果test.dat存在,则可以正常运行。为什么?

我希望在snakemake准备运行规则'a'之前不对参数进行评估。相反,它必须在DAG阶段中在运行规则“ a”之前调用上述params函数rdf()。但是,即使最初不存在test.dat,也可以进行以下操作:

import os

def rdf(fn):
    if not os.path.exists(fn): return ""
    f = open(fn, "rt")
    t = f.readlines()
    f.close()
    return t

rule a:
    output: "test.txt"
    input: "test.dat"
    params: X=lambda wildcards, input, output, threads, resources: rdf(input[0])
    message: "X is {params.X}"
    shell: "cp {input} {output}"

rule b:
    output: "test.dat"
    shell: "echo 'hello world' >{output}"
Run Code Online (Sandbox Code Playgroud)

这意味着对参数进行了两次评估,一次在DAG阶段,一次在规则执行阶段。为什么?

这对我来说是个问题。我需要能够从输入文件中读取数据到规则,以便为要执行的程序制定参数。该命令本身不接收输入文件名,而是获取从输入文件的内容派生的参数。我可以按照上面的方法处理,但这似乎很笨拙,我想知道是否存在错误或缺少某些内容?

Sch*_*lar 2

我遇到过同样的问题。就我而言,我可以通过让函数在不存在的文件上运行时返回默认占位符来规避该问题。

例如,我有一条规则需要提前知道某些输入文件的行数。因此,我使用了:

def count_lines(bed):
    # This is neccessary, because in a dry-run, snakemake will evaluate the 'params' 
    # directive in the (potentiall non-existing) input files. 
    if not Path(bed).exists():
        return -1

    total = 0
    with open(bed) as f:
        for line in f:
            total += 1
    return total
Run Code Online (Sandbox Code Playgroud)
rule subsample_background:
    input:        
        one = "raw/{A}/file.txt",
        two = "raw/{B}/file.txt"
    output:
        "processed/some_output.txt"
    params:
        n = lambda wildcards, input: count_lines(input.one)

    shell:
        "run.sh -n {params.n} {input.B} > {output}"
Run Code Online (Sandbox Code Playgroud)

在空运行中,-1将放置一个占位符,允许空运行成功“完成”,而在非空运行中,函数将返回适当的值。