【问题标题】:Syntax for using config data in rules在规则中使用配置数据的语法
【发布时间】:2017-08-03 20:34:04
【问题描述】:

有没有什么地方可以完整描述snakemake规则中配置数据的使用?

在yaml文件的用户指南中有一个例子:

samples:
    A: data/samples/A.fastq
    B: data/samples/B.fastq

然后,它被用在这样的规则中:

bam=expand("sorted_reads/{sample}.bam", sample=config["samples"]),

上面的内容似乎将 {sample} 替换为“data/samples/A.fastq”,而不是像显然那样替换为“A”(和“B”等)。

在输出规则中使用配置数据的正确方法是什么,例如帮助形成输出文件名?此表单不起作用:

output: "{config.dataFolder}/{ID}/{ID}.yyy"

如果我在 yaml 文件中定义复杂的结构化数据,我正在寻找语法指导 - 我如何在蛇规则中使用它?什么时候使用 Python 语法,什么时候使用 SnakeMake 语法?

yaml 和 JSON 配置文件受到严重限制,因为它们不能使用文件中先前定义的值来定义新值,对吧?这也是设置配置参数时经常要做的事情。

使用配置文件有什么好处?为什么不直接使用 include: 一个包含一个 python 文件来定义参数?

一个有用的东西是一个参考手册,它彻底描述了 SnakeMake 的细节。当前的网站有点分散,需要一段时间才能找到您记得以前在其中看到过的东西。

【问题讨论】:

  • 为了克服 yaml 或 JSON 的限制,您可以从配置中读取内容,然后在蛇文件中(在规则之前),将 python 代码应用于从配置文件中读取的内容。

标签: python output config snakemake


【解决方案1】:

应该如何在“输出”规则中使用配置数据?我发现输出字符串不能包含 {config.} 值。但是,可以使用 Python 代码将它们包含在内,如下所示:

output: config["OutputDir"] + "/myfile.txt"

但是,这种方法不起作用(在输出:或输入:):

params: config=config
output: "{params.config[OutputDir]}/myfile.txt"

但是,它确实可以在“shell:”中工作:

params: config=config
output: config["OutputDir"] + "/myfile.txt"
shell: echo "OutputDir is {params.config[OutputDir]}" > {output}

请注意,shell cmd 中 [] 内的 OutputDir 周围没有引号。在字符串中扩展值的 {} 方法不使用引号引起的键。

配置数据可以按蛇文件方式或python方式定义吗?是的!

可以在使用“configfile”包含的 .yaml 文件中定义参数,也可以通过使用“include”包含的常规 Python 文件定义参数。后者是恕我直言,因为 .yaml 文件不允许定义引用以前的定义,除了最简单的配置文件之外,这在所有文件中都很常见。

使用yaml定义上面的“OutputDir”参数:

xxx.yaml:

OutputDir: DATA_DIR

蛇文件:

configfile: 'xxx.yaml'

使用 Python 定义它以与上述完全兼容:

xxx.py:

config['OutputDir'] = "DATA_DIR"

蛇文件:

include: 'xxx.py'

或者,在 Python 包含的配置文件中定义一个简单的变量“OutputDir”,然后在规则中使用它:

xxx.py:

OutputDir = "DATA_DIR"

蛇文件:

include: 'xxx.py'
rule:
    output: OutputDir + "/myfile.txt"

可以通过 .yaml 文件和 python 文件轻松定义和访问多嵌套字典和列表。示例:

MACBOOK> cat cfgtest.yaml
cfgtestYAML:

    A: 10
    B: [1, 2, 99]
    C:
        nst1: "hello"
        nst2: ["big", "world"]

MACBOOK> cat cfgtest.py
cfgtestPY = {

    'X': -2,
    'Y': range(4,7),
    'Z': {
        'nest1': "bye",
        'nest2': ["A", "list"]
        }
    }

MACBOOK> cat cfgtest
configfile: "cfgtest.yaml"
include: "cfgtest.py"

rule:
    output: 'cfgtest.txt'
    params: YAML=config["cfgtestYAML"], PY=cfgtestPY
    shell:
        """
        echo "params.YAML[A]: {params.YAML[A]}"             >{output}
        echo "params.YAML[B]: {params.YAML[B]}"             >>{output}
        echo "params.YAML[B][2]: {params.YAML[B][2]}"       >>{output}
        echo "params.YAML[C]: {params.YAML[C]}"             >>{output}
        echo "params.YAML[C][nst1]: {params.YAML[C][nst1]}" >>{output}
        echo "params.YAML[C][nst2]: {params.YAML[C][nst2]}" >>{output}
        echo "params.YAML[C][nst2][1]: {params.YAML[C][nst2][1]}" >>{output}

        echo "" >>{output}

        echo "params.PY[X]: {params.PY[X]}"                 >>{output}
        echo "params.PY[Y]: {params.PY[Y]}"                 >>{output}
        echo "params.PY[Y][2]: {params.PY[Y][2]}"           >>{output}
        echo "params.PY[Z]: {params.PY[Z]}"                 >>{output}
        echo "params.PY[Z][nest1]: {params.PY[Z][nest1]}"     >>{output}
        echo "params.PY[Z][nest2]: {params.PY[Z][nest2]}"     >>{output}
        echo "params.PY[Z][nest2][1]: {params.PY[Z][nest2][1]}" >>{output}
        """

MACBOOK> snakemake -s cfgtest
Provided cores: 1
Rules claiming more threads will be scaled down.
Job counts:
    count   jobs
    1   1
    1

rule 1:
    output: cfgtest.txt
    jobid: 0

Finished job 0.
1 of 1 steps (100%) done

MACBOOK> cat cfgtest.txt
params.YAML[A]: 10
params.YAML[B]: 1 2 99
params.YAML[B][2]: 99
params.YAML[C]: {'nst1': 'hello', 'nst2': ['big', 'world']}
params.YAML[C][nst1]: hello
params.YAML[C][nst2]: big world
params.YAML[C][nst2][1]: world

params.PY[X]: -2
params.PY[Y]: range(4, 7)
params.PY[Y][2]: 6
params.PY[Z]: {'nest1': 'bye', 'nest2': ['A', 'list']}
params.PY[Z][nest1]: bye
params.PY[Z][nest2]: A list
params.PY[Z][nest2][1]: list

【讨论】:

  • 有趣的是,“params”的一级成员可以用“.”访问或“[]”,但所有后续级别必须使用“[]”。例如。 “params.PY[X]”和“params[PY][X]”是一样的,但是“params.PY.X”不起作用。
  • 上述帖子中的方法 2 不起作用。 input, output, params, ... 中的大括号用于表示通配符。相比之下,shell 指令或扩展函数中的大括号用于格式化字符串,与 python 方法 str.format 完全一样。
【解决方案2】:

YAML 配置

这与 YAML 文件的嵌套有关,请参阅示例 here

config["samples"] 请求将返回“A”和“B”。我是我的头我认为它返回一个列表,但我对变量类型并不积极。

使用此处列出的配置文件: https://snakemake.readthedocs.io/en/latest/tutorial/advanced.html

您可以链接到以下 YAML 配置文件,采用 YAML 格式。

settings/config.yaml:

samples:
    A
    B

settings/config.yaml:

sampleID:
    123
    124
    125
baseDIR:
    data

使用 YAML 配置访问的结果调用

蛇文件:

configfile: "settings/config.yaml"

rule all:
    input:
        expand("{baseDIR}/{ID}.bam", baseDIR=config["baseDIR"], ID=config["sampleID"]),


rule fastq2bam:
    input:
        expand("{{baseDIR}}/{{ID}}.{readDirection}.fastq", readDirection=['1','2'])
    output:
        "{baseDIR}/{ID}.bam"
        #Note different number of {}, 1 for wildcards not in expand.
        #Equivalent line with 'useless' expand call would be:
        #expand("{{baseDIR}}/{{ID}}.bam")

    shell:
    """
    bwa mem {input[0]} {input[1]} > {output}
    """

虚拟示例,只是试图举例说明不同字符串和配置变量的使用。我在 fastq2bam 规则中使用通配符。通常,我只使用配置变量在我的规则“全部”中进行设置,如果可能,这是最佳实践。我不能说 shell 调用是否真的适用于 bwa mem,但我想你明白我的意思了。

可以看到更大版本的 Snakefile here

配置文件设置好后,要引用其中的任何内容,请使用“config”。它可用于根据需要深入访问 YAML。在这里,我将降低 3 个假设级别,如下所示:

hypothetical_var = config["yamlVarLvl1"]["yamlVarLvl2"]["yamlVarLvl3"]

等于(我对打字不持肯定态度,我认为它会转换为字符串)

 hypothetical_var = ['124', '125', '126', '127', '128', '129']

如果 YAML 是:

yamlVarLvl1:
    yamlVarLvl2:
        yamlVarLvl3:
            '124'
            '125'
            '126'
            '127'
            '128'
            '129'

代码组织

Python 和 Snakemake 代码大部分可以在某些地方交错。我建议不要这样做,因为它会使代码难以维护。由用户决定如何实现这一点。例如,使用 run 或 shell 指令会改变访问变量的方式。

YAML 和 JSON 文件是首选的配置变量文件,因为我相信它们为变量的编辑和命令行界面覆盖提供了一些支持。如果它是使用外部导入的 python 变量实现的,这将不会那么干净。它也帮助我的大脑,知道 python 文件做事,YAML 文件存储东西。

YAML 始终是一个外部文件,但是...

  1. 如果您使用的是单个 Snakefile,请将支持的 python 放在顶部?
  2. 如果您使用的是多文件系统,请考虑将支持的 python 脚本外部化。

教程

我认为完美的小插图很难设计。我正在尝试向我的团队介绍 Snakemake,我有超过 40 页的个人书面文档,我提供了三个 1 小时以上的演示文稿和 PowerPoint 幻灯片,我几乎阅读了整个 ReadTheDocs.io Snakemake 手册,我只是最近完成了其他resources的列表,但是,我还在学习呢!

旁注,我发现这个tutorial 也很好。

这是否提供了足够的上下文?

【讨论】:

  • 感谢您的信息。我把很多问题合二为一,因为我每 90 分钟只能发布一个问题。您没有回答的一个问题是,配置数据应如何在“输出”规则中使用?我发现这行得通:
  • 别担心,我也理解您正在尽力而为,我感谢您将此讨论从 Google 网上论坛转移到此处。对配置文件的输入和输出访问是相同的。输入和输出指令之间的唯一区别是输入指令可以使用输入函数,而我不相信有任何能力将函数放入输出中。
  • 或许值得一提的是,无论使用 YAML 还是 JSON,Snakemake 都会简单地将相应的配置文件读入 Python 字典,该字典可作为 config 全局访问。读取通过标准库的json 模块或pyyaml 库进行。这里没什么特别的。这也意味着整数和浮点数被正确转换,如果你没有在配置文件中给它们加上引号,它们在结果字典中就是正确的整数或浮点数。
【解决方案3】:

有没有什么地方可以完整描述snakemake规则中配置数据的使用?

您可以在配置文件中放入的内容没有限制,只要它可以解析为 python 对象即可。基本上,“你的想象力就是极限”。

在输出规则中使用配置数据的正确方法是什么,例如帮助形成输出文件名?

我从规则之外的配置中提取东西,用普通的 python。

我会这样做,而不是 output: "{config.dataFolder}/{ID}/{ID}.yyy"

data_folder = config.dataFolder

rule name_of_the_rule:
    output:unction
        os.path.join(data_folder, "{ID}", "{ID}.yyy")

我猜你所尝试的,当有来自通配符和其他东西的混合时,snakemake 在格式化字符串时会遇到问题。但也许以下在 python 3.6 中有效,使用formatted string litterals:output: f"{config.dataFolder}/{ID}/{ID}.yyy"。我没查过。

如果我在 yaml 文件中定义复杂的结构化数据,我正在寻找语法指导 - 我如何在蛇规则中使用它?什么时候使用 Python 语法,什么时候使用 SnakeMake 语法?

在蛇形文件中,我通常会在规则之前读取配置文件以提取配置信息。这本质上是纯 python,只是为了方便起见,Snakemake 直接提供了一个 config 对象。您可能只使用 config = json.load("config.json")config = yaml.load("config.yaml") 的普通标准 python。

在蛇文件中,在规则之外,你可以在 python 中做任何你想做的计算。这可以在读取配置之前以及之后。您可以定义可在规则中使用的函数(例如生成规则的输入),计算将用作通配符的事物列表。我认为唯一需要在使用它的规则之前定义一个对象。

Snakemake 语法似乎主要是描述规则的一种手段。在规则的run 部分中,您可以使用任何您想要的python,知道您可以访问wildcards 对象来帮助您。规则的输入和输出是文件路径列表,你可以使用python来构建它们。

【讨论】:

    猜你喜欢
    • 2018-10-21
    • 2016-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-28
    • 1970-01-01
    相关资源
    最近更新 更多