我想使用一个函数来轻松设置输出日志文件名。
我尝试了以下功能
# output_path=simulations/sim1/model/test.out
# idx=2 == add <x> after 2nd element
# x=logs
# returns= simulations/sim1/logs/model/test.out
def get_xpath(wildcards,x,idx):
outbase=wildcards.output[0]
return str('/'.join(outbase.split('/')[:idx])+"/"+x+"/"+'/'.join(outbase.split('/')[idx:]))
rule testme:
...
log: lambda wildcards: get_xpath(wildcards,"logs",2),
但它给出了以下 AttributeError
'function' object has no attribute 'get_wildcard_names'
我也尝试过使用 lambda:
rule testme:
...
log: lambda wildcards, output: output[0].split('.')[0],
这给出了同样的错误。我在 Snakemake 文档中找不到任何实现此目的的示例,所以我不确定这是否可能。有什么想法吗?
谢谢!
这只是一个 hack,但一种方法是将其放入
params
指令中。好处是如果规则失败,这条不会被删除:
rule abc:
params: log = lambda wildcards: get_xpath(wildcards,"logs",2),
...
当然,可执行文件(shell/run/script)内的引用必须调整为
params.log
而不是 log
。
这是一个解决方法。
如果不手动复制,您仍然无法获取输出文件名,但您可以使用一个函数,通过使用规则名称作为变量来更轻松地命名日志文件。可以通过使用某些通配符或提供输出文件名的硬拷贝来改进它。尽管将规则名称设置为变量会限制某些功能,例如通过名称直接调用规则。
def logfile(rule_name,wildcards=None,output=None):
return f"{config['dataset_id']}/logs/{rule_name}.log"
ruleid="get_fasta_per_locus"
rule ruleid:
input:
output:
log:
lambda wildcards: logfile(ruleid)
我目前的解决方法:
def get_output_log(wildcards, output):
out=output[0].split('/')
if len(out) < 4:
raise ValueError("Output path must have at least 4 components")
out.insert(2, "logs")
# create the directory if it does not exist
out = [x.format(**wildcards) for x in out]
os.makedirs('/'.join(out[:-1]), exist_ok=True)
return '/'.join(out)
用途:
rule xx:
input: ...
output: ...
params:
log=lambda wildcards, output: get_output_log(wildcards, output),
shell:
"""
command &> {params.log}
"""