考虑这个snakefile:
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}"
运行时,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'
但是,如果test.dat存在,它运行正常。为什么呢?
我原本预计,在snakemake准备好运行规则之前,不能对params进行评估。' a。相反,它必须在运行规则'之前在DAG阶段调用上面的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}"
这意味着params被评估两次,一次在DAG阶段,一次在规则执行阶段。为什么呢?
对我来说这是个问题。我需要能够将输入文件中的数据读取到规则中,以便为要执行的程序制定参数。该命令本身不接收输入文件名,而是从输入文件的内容中获取参数。我可以像上面那样处理它,但这看起来很糟糕,我想知道是否有错误或我错过了什么?
答案 0 :(得分:0)
我有同样的问题。就我而言,我可以通过在不存在的文件上运行时让该函数返回默认的占位符来解决问题。
例如,我有一条规则需要提前知道某些输入文件的行数。因此,我使用了:
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
,使空运行成功“完成”,而在非空运行中,该函数将返回适当的值。