我正在尝试使用snakemake来自动化我们迄今为止手工完成的一些事情。 我有一个问题,我想调用一个具有许多可能的输出文件的脚本。一个最小的非工作示例是这样的:
rule all:
input:
expand("{year}.txt", year=["15","16","17"]),
rule make_file:
output:
"{year}.txt",
run:
year_list = wildcards.year
shell("python make_txt.py --year {year_list}")
其中 make_txt.py 只是:
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument('--year', nargs='*')
args = parser.parse_args()
for year in args.year:
with open(f"{year}.txt",'w') as f:
pass
此脚本可以将列表作为参数,然后生成多个文件,每个通配符一个文件。但它也可以获取一个列表,然后一次运行完成所有操作。我想要的是snakemake只调用一次make_file并执行
python make_txt.py --year 15 16 17
。我需要这个,因为我使用的实际代码是以循环通配符的方式编写的,并且在此之前需要进行大量设置,因此逐个运行作业会浪费大量时间。
我尝试在参数中运行某种解析,我认为这可能是正确的方法。我有什么遗漏的吗? 这个问题几乎也是我想要的。 从那里实施解决方案我的蛇文件是:
years = ["15","16","17"]
rule all:
input:
expand("{year}.txt", year=years),
rule make_file:
output:
expand("{year}.txt",year=years),
params:
years = years,
shell:
"python make_txt.py --year {params.years}"
调用规则全部现在可以正确运行创建三个文件的单个作业。然而,我失去了使用通配符的能力,我仍然非常想做。我的真实代码有很多参数,并且像这样“硬编码”它们,每次我想要输出文件的不同子集时,我都需要更改蛇文件,而不是仅仅通过通配符调整目标。 理想的情况是提供一个列表作为通配符,有点像
snakemake [16,17,18].txt
然后将被解释为 wildcards.year = 15 16 17
。有什么办法可以实现这个功能吗?
我认为你不能用文件来做到这一点,但也许可以使用 config 选项或文件:
# config.yaml
years:
- 15
- 16
- 17
# Snakefile
configfile: "config.yaml"
if isinstance(config['years'], list):
years = config['years']
else:
years = config['years'].split(',')
rule all:
input:
expand("{year}.txt", year=years),
rule make_file:
output:
expand("{year}.txt",year=years),
params:
years = years,
shell:
"python make_txt.py --year {params.years}"
然后您可以通过调整 config.yaml 内容或使用
snakemake --config years=10,11,12
来自定义执行。
传入文件名的问题在于,snakemake 将文件视为特殊文件,并且没有任何语法可以说明“此规则将创建您需要的所有年份”而不更改另一个变量。您可以使用检查点,但最终您需要说明规则将生成什么,并且使用配置变量是最简单的界面。