首页 > 解决方案 > 包括子蛇文件并生成它们的输出

问题描述

问题

问题是当我将include其他子 Snakefiles 放入主 Snakefile 时,永远不会生成子 Snakefiles 的输出。如果这有帮助,我认为这在管道中有可选的“分支”——有时我的客户想要特定分支的输出,而客户却不想要。我希望能够选择何时执行这些可选分支。我的蛇形版本是5.13.0.

理想的解决方案

我想要include子 Snakefile,并生成这些子 Snakefile 的输出。以下是我的设想:

配置.yaml

module2: "yes"

蛇文件('主'蛇文件)

# working dir
workdir: "path/to/dir/test"
configfile: "code/config.yaml"

# core rules. These rules are always run. 
include: "code/head.py"

if config["module2"] == "yes":
    include: "code/module2/Snakefile"

rule all:
    input:
        "data/output_head.txt"

如果我的客户要求,例如可以在哪里module2生成特定图表。

请注意,即使主 Snakefile 的规则所有输入都没有改变,我想生成code/module2/Snakefile子 Snakefile 的输出。每个文件内容都显示在下一节中。

我的(错误)方法

可重现的例子

├── Snakefile
├── code
│   ├── config.yaml
│   ├── head.py
│   └── module2
│       ├── Snakefile
│       └── tail.py
├── data
└── inputs
    └── test_input.txt

Snakefile(“主”蛇文件创建核心工作流输出)

# working dir
workdir: "path/to/dir/test"
configfile: "code/config.yaml"

# core rules
include: "code/head.py"

# module 2 rules
include: "code/module2/Snakefile"

# core output
rule all:
    input:
        "data/output_head.txt"

test_input.txt

1
2
3
4
5
6
7
8
9
10

代码/head.py

rule head:
    input:
        "inputs/test_input.txt"
    output:
        "data/output_head.txt"
    shell:
        "head -3 {input} > {output} " # we expect 1 2 3 in output_head.txt

code/module2/Snakefile('subordinate'snakefile 创建可选的模块 2 输出文件)

include: "tail.py"

rule all:
    input:
        "data/output_tail.txt"

代码/module2/tail.py

rule tail:
        input:
                "inputs/test_input.txt"
        output:
                "data/output_tail.txt"
        shell:
                "tail -3 {input} > {output} " # we expect 8 9 10 in output_tail.txt

我遇到的实际错误是:

CreateRuleException in line 12 of path/to/dir/test/Snakefile:
The name all is already used by another rule

我相信这是因为子 Snakefilerule all与主 Snakefile 的rule all.

可重现的例子

最后我查看了模块化页面,在include它下面说:

默认目标规则(通常称为 all-rule)不受包含影响。即,它始终是您的 Snakefile 中的第一条规则,无论您在第一条规则之上有多少包含。

如果我翻译对了,它可以改写为:“将 Snakefiles 包含到您的主 Snakefile 中不会添加新的输出文件,因为这是由主 Snakefile 确定的。”

如果这是真的,那么如果我没有得到它们的输出文件,那么包含子 Snakefile 的意义何在?

结论

将管道设置为有条件include的子 Snakefile 并生成其输出文件的最佳方法是什么?也许我正在阅读非常错误的文档。如果我是,请赐教。

标签: pythonincludesnakemake

解决方案


不确定它是否是最好的,但这是我的解决方案。在配置中,我让用户指定要包括哪些“分支”:

# config.yaml
main:
    subworkflows:
        - workflow1
        - workflow2

主 Snakefile 使用此配置条目来包含具有匹配名称的其他蛇文件。另请注意,如果名称不存在,并且每个子工作流的配置文件已加载并与一些额外的脚本合并,我会进行额外的检查。

# Snakefile
subworkflows = config['main']['subworkflows']
for subw in subworkflows:
    sub_path = 'subworkflows/{}.snake'.format(subw)
    sub_config = 'subworkflows/{}.yaml'.format(subw)
    if not os.path.exists(sub_path):
        continue

    subw_outputs_dict[subw] = []

    if os.path.exists(sub_config):
        configfile: sub_config
        paths = join_config_paths(paths, config['path'])

    include: sub_path

    if len(subw_outputs_dict[subw]) == 0:
        continue

    subw_outputs.extend(subw_outputs_dict[subw])

rule all:
    input:
        subw_outputs

每个子模块将其最终输出构建到 subw_outputs_dict 中,作为每个部分的规则。

# workflow1.snake
if "subw_outputs_dict" in locals() and "ids" in locals():
    subw_outputs_dict['workflow1'] = expand(paths['my_output'], id=ids)

总结一下:

  • config.yaml 控制运行的内容
  • Snakefile 包括请求的工作流并将它们加入到规则所有文件的单个列表中
  • 每个子工作流在全局字典中定义一组规则及其输出。

这是受到另一个我不记得的项目的启发,但对我来说效果很好。我会对其他人的所作所为感兴趣。我敢打赌,有一种更流畅的方式来使用子工作流,但我发现其中的内容更容易思考和调试。


推荐阅读