考虑这个蛇文件:
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}"
当运行时,测试.txt和测试.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'
但是,如果 test.dat 存在,则运行正常。 为什么?
我本来希望参数在蛇制作准备好运行规则"a"之前不会被评估。 相反,它必须在运行规则"a"之前的 DAG 阶段调用上面的参数函数 rdf()。 然而,以下工作,即使在测试时.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}"
这意味着参数被计算两次,一次在 DAG 阶段,一次在规则执行阶段。 为什么?
这对我来说是一个问题。 我需要能够从规则的输入文件中读取数据,为要执行的程序制定参数。 该命令不接收输入文件名本身,而是获取从输入文件的内容派生的参数。 我可以像上面一样处理它,但这似乎很笨拙,我想知道是否有错误或我错过了什么?
我遇到了同样的问题。就我而言,我可以通过让函数在非现有文件上运行时返回占位符默认值来规避这个问题。
例如,我有一个规则,需要提前知道它的某些输入文件的行数。因此,我使用了:
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
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}"
在试运行中,将放置占位符-1
,使试运行成功完成,而在非试运行中,该函数将返回适当的值。