将 snakefile 修改为 运行 一个工作流程的多次迭代

Modify snakefile to run multiple iterations of one workflow

我有一个带有单个 Snakefile 和单个配置文件的 Snakemake 工作流程。在我的 Snakefile 中,我指定了一个不按顺序编号的作业(例如 210,215)。对于我可以指定的每个作业,配置文件都有一个对应的条目,其中包含有关该特定作业的信息(参数包括年份、子作业数量、文件前缀等,所有这些都存储为字符串)。在规则中,为了构造输入和输出,我使用 config[job]["year"] 等语句为每个作业提供正确的字符串。

我的工作流程的一个简化示例,希望能展示我如何使用配置文件中的信息:

# SNAKEFILE
job=210
rule all:
    input:
        expand(config["outputdir"]+"/"+config[job]["prefix"]+"_test_"+config[job]["year"]+config[job]["originID"]+"_{sample}.root",sample=config[job]["samples"])
...other rules...
rule filter_2:
    input:
        config["outputdir"]+"/filter-1-applied/{sj}/"+config[job]["prefix"]+"_test_"+config[job]["year"]+config[job]["originID"]+"_{sample}.root"
    output:
        config["outputdir"]+"/filter-2-applied/{sj}/"+config[job]["prefix"]+"_test_"+config[job]["year"]+config[job]["originID"]+"_{sample}.root"
    shell:
        "(bash scripts/filter-2.sh {input} {output}) 2> {log}"
...other rules...

CONFIG.YAML
outputdir="/home/ghl/outputs"
210:                                                                                                                                                                                                               
    prefix: "Real"
    year: "2016"
    origindir: "/home/ghl/files/210"
    subjobs: 2653
    originID: "_abc123"
    samples: ["type1_v1","type1_v2","type2_v1","type2_v2"]

当我有少量工作时这很好,但现在我有 ~80 到 运行,有些即使在我可以访问的批量提交系统上提交也需要几个小时,它每次手动 运行 需要很长时间,等待,更改 'job' 属性,然后再次 运行。我想做的是能够从这个 Snakefile 的单个 运行 中 运行 多个作业(例如 210 和 215)。

在 python 中,我会将所有内容都包含在一个循环中,例如:

for job in [1,3,...,210,215]:
    <run single job workflow>
print("Done!")

我正在尝试在我的 Snakefile 中做同样的事情。我已经尝试将 job=jobs 放入 'rule all' 的输入中,就像我对示例所做的那样,并定义 jobs=[210,215],或者将输入更改为 returns 相应文件名的函数从工作列表中,但 运行 都涉及与 'job' 不再是脚本中的 python 变量但现在是通配符这一事实相关的问题,我不清楚我应该如何为 config[job]["year"] :
之类的东西提供通配符 config[{job}]["year"]config["{job}"] 不起作用(具体来说,他们给出 NameError 或 KeyError)。

有没有办法实现这一点(理想情况下无需完全重写)?按照我提到的内容进行修改(或者以某种方式 运行 从单独的 snakefile 中修改此工作流程?)将是理想的,我想这可能只需替换 config[job] 的所有实例即可实现使用 并更改 'rule all' 的输入以包含工作编号列表...

提前致谢!

如果其他人想知道我是如何解决这个问题的,它需要重写一些东西,并且相当广泛地使用 lambda 函数,此外,所有文件现在都以他们的工作编号为前缀(我有一个 bash 在 snakemake 之外运行的脚本来删除它们)。我敢肯定,其中大部分超出了要求,但对我来说已经足够好了。

我在配置中指定了一个作业列表:jobs: [j210,j215](j 前缀是必需的,因为如果 snakemake 将它们解释为整数而不是字符串,则会出现关键错误,原因我不太明白)

我添加了一个额外的 make_final 规则,该规则仅取决于作业,并修改了所有规则(并且还使用了很多通配符约束,您对它们的需求可能会有所不同)。这使得 job 成为通配符,因此 config[job] 可以在 inputparams 中使用 lambda 函数访问:config[wildcards.job]

rule all:
    input:
       expand("completed/{job}.log",job=config["jobs"])

rule make_final:
    # this input is just my final file from the chain of rules. Awkward syntax as requires a list expansion - each source job produces 4 output files
    input:
        lambda wildcards : [(config["outputdir"]+"/{job}_"+config[wildcards.job]["prefix"]+"_test_"+config[wildcards.job]["year"]+config[wildcards.job]["originID"]+"_"+foobar+".root") for foobar in config[wildcards.job]["samples"]],
    output:
        "completed/{job}.log"
    shell:
        "touch {output}"

并且修改了之前的规则,例如像这样:

rule filter_2_mc:
    input:
        # this new approach allows neater/more natural phrasing here, rather than
        # using lots of config[job]["blah"] statements
        config["outputdir"]+"/filter-1-applied/{sj}/{job}_{prefix}_test_{year}{originID}_{sample}.root"
    output:
        config["outputdir"]+"/filter-2-applied/{sj}/{job}_{prefix}_test_{year}{originID}_{sample}.root"                                                                                                                       
    shell:
        "bash scripts/filter-2-new.sh {input} {output}"

一些规则的输入需要 lambda 函数:或参数:如果需要指定配置[wildcards.job]中的任何内容。

(如果不允许回答我自己的问题并将其标记为正确答案,我也深表歉意)