【问题标题】:Handling equivalent file extensions in Snakemake在 Snakemake 中处理等效的文件扩展名
【发布时间】:2019-06-04 02:35:06
【问题描述】:

基本上,我想知道在snakemake 中推荐的处理等效文件扩展名的方法是什么。例如,假设我有一个规则来计算 fasta 文件中的条目数。该规则可能看起来像....

rule count_entries:
    input:
        ["{some}.fasta"]
    output:
        ["{some}.entry_count"]
    shell:
        'grep -c ">" {input[0]} > {output[0]}'

这很好用。但是如果我希望这条规则也允许“{some}.fa”作为输入呢?

有什么干净的方法可以做到这一点吗?

编辑:

这是我对第一个建议解决方案的最佳猜测。这可能可以转换为更高阶的函数以更通用,但这是我理解的基本思想。我认为这个想法并不真正适合任何一般用例,因为它在“构建 DAG”阶段不与其他规则合作。

import os

def handle_ext(wcs):
    base = wcs["base"]
    for file_ext in [".fasta", ".fa"]:
        if(os.path.exists(base + file_ext)):
            return [base + file_ext]

rule count_entries:
    input:
        handle_ext
    output:
        ["{base}.entry_count"]
    shell:
        'grep -c ">" {input[0]} > {output[0]}'

EDIT2:这是我认为目前最好的解决方案...

count_entries_cmd = 'grep -c ">" {input} > {output}'
count_entries_output = "{some}.entry_count"

rule count_entries_fasta:
    input:
        "{some}.fasta"
    output:
        count_entries_output
    shell:
        count_entries_cmd

rule count_entries_fa:
    input:
        "{some}.fa"
    output:
        count_entries_output
    shell:
        count_entries_cmd

【问题讨论】:

  • 只使用 python 函数可能是最好的解决方案。我不相信snakemake对此有任何内置解决方案。
  • 使用function as input files查看此内容。
  • 查看我在 OP 中的编辑以获取适合此用例的示例。它仍然看起来很丑陋和尴尬。此外,它并不能很好地与其他规则一起使用,或者根本不能真正使用,因为它只知道文件存在后 .fasta 是否是正确的输入。

标签: python shell snakemake


【解决方案1】:

我注意到的一件事是,您试图在输入和输出部分中指定文件列表,但实际上您的规则采用单个文件并生成另一个文件。 我建议你一个简单的解决方案,为不同的扩展指定两个单独的规则:

rule count_entries_fasta:
    input:
        "{some}.fasta"
    output:
        "{some}.entry_count"
    shell:
        'grep -c ">" {input} > {output}'

rule count_entries_fa:
    input:
        "{some}.fa"
    output:
        "{some}.entry_count"
    shell:
        'grep -c ">" {input} > {output}'

除非您将具有相同 {some} 名称和不同扩展名的文件保存在同一个文件夹中(我希望您不要这样做),否则这些规则并不含糊。

【讨论】:

  • 这似乎是最好的解决方案。我唯一的保留是它包含很多重复的代码。这可以通过将输出和 shell 字符串作为变量提取并仅在规则定义中使用这些变量来在某种程度上以明显的方式进行简化。理想情况下,可以生成这些规则,而不需要手动复制代码,但我不确定这是否可行。规则可以由函数生成吗?如果有怎么办?
  • @NolanHartwick 您不需要复制代码。例如,您可以使 shell 内容成为一个单独的函数。剩下的只是表达你想法的最少代码:获取输出,将其与输入匹配。
  • 规则定义本身就是重复代码。这可能是不可避免的,这意味着这种解决方案不能很好地推广到更多文件类型。拥有相同规则的两个版本看起来并不算太糟糕。如果有四个,或者在潜在的极端情况下更多,看起来会更糟。在这些(我承认很少见)情况下,如果可以通过函数调用或其他方式创建规则,那就太好了,这样您就可以指定基本规则和一组等效输入,然后创建所有需要的规则。不过我认为这是不可能的。
【解决方案2】:

一种可能的解决方案是只允许原始规则将 .fasta 文件作为输入,但允许将 .fa 文件重命名为该规则。例如,

rule fa_to_fasta:
    input:
        "{some}.fa"
    output:
        temp("{some}.fasta")
    shell:
        """
        cp {input} {output}
        """

显然,这样做的缺点是制作文件的临时副本。此外,如果foo.fafoo.fasta 都提供了(不是通过复制),那么foo.fasta 将默默地覆盖foo.fa,即使它们不同。

【讨论】:

  • 即使这样不好,这种情况也经常发生,可能有不同的方法来创建同一个文件。您总是可以明确地解决歧义。无论如何,移动源文件是更糟糕的解决方案。
  • 此外,如果文件夹中有 fastafa 文件,则没有歧义。真正的歧义是当您同时拥有两者时,在这种情况下更改文件名也不起作用。
  • @DmitryKuzminov 虽然我承认 Snakemake 只会在两种潜在输入都存在的情况下引发歧义异常,但我正在考虑的歧义是正式的歧义为了获得可重复的管道,必须避免。实际上,Snakemake 规则定义了从输出文件到一组输入文件的映射。如果每个输出文件都有一个可确定的偏序集,那么整个管道是明确的。仅仅因为 Snakemake 不测试正式的可重复性并不意味着不应该瞄准它。
  • 首先,Snakemake 允许您使用 ruleorder 语句明确地解决歧义。当 Snakemake 无法决定它应该使用哪个规则(从而产生AmbiguousRuleException)时,如果存在真正的歧义,这将起作用。但是在 fasta/fa ​​的示例中,除非存在名称完全相同但扩展名不同的文件(我认为这是一个更严重的逻辑问题,然后只是有歧义),否则没有歧义。但在这种情况下移动文件也无济于事。
  • @DmitryKuzminov 好点。我现在看到如果有两个具有相同基数的文件,实际上会想要触发歧义异常,因为它会警告用户他们的输入存在真正的逻辑问题。在我建议的解决方案中,即使两者之间存在真正的区别,它也会默默地忽略 .fa 文件。感谢您的意见!
猜你喜欢
  • 1970-01-01
  • 2011-03-14
  • 1970-01-01
  • 2012-06-17
  • 2015-05-28
  • 2021-04-11
  • 2018-08-02
  • 1970-01-01
  • 2011-10-11
相关资源
最近更新 更多