Snakemake 在规则中使用不同的通配符

Snakemake use different wildcards in a rule

提问人:Théo Durand 提问时间:5/4/2023 最后编辑:applesomthingThéo Durand 更新时间:5/6/2023 访问量:133

问:

我正在尝试创建 snakemake 规则,该规则接受输入我的 fastq 文件并在输出中为每个文件返回一个 .sam 文件。fastq

我有一个这样的文件:

FILE    TYPE    SM    LB    ID    PU          PL
xfgh.fastq.gz  Single      IND1  IND1  IND1  Platform    Illumina
IND2.fastq.gz     Single  IND2  IND2  IND2  Platform    Illumina
zfgv.fastq.gz  Single      IND3  IND3  IND3  Platform    Illumina 
IND4_P1.fastq.gz  Single      IND4  IND4  IND4  Platform    Illumina

所以我做了类似的事情。
我用熊猫打开我的数据帧:

pd.read_csv("info_file.txt")我库存了一个列文件SM和ID

我创建我的规则:

rule all:
    input:
        sam_file = expand("ALIGNEMENT/{sm}/{id}.sam", sm = info_df["SM"], id = info_df["ID"])

rule alignement:
    input:
          fastq_files = "PATH/TO/{fastq}"
    output:
          sam_file = "ALIGNEMENT/{sm}/{id}.sam"

我知道输入和输出需要具有相同的通配符,但是是否存在一种方法可以从file.txt的“FILES”列中输入,并在输出中输入这样的路径:其中 {sm} 和 {id} 是我file.txt的 SM 和 ID 列"ALIGNEMENT/{sm}/{id}.sam"

我还想为每个文件启动一个规则。

如果有人能帮我,谢谢

python-3.x 通配符 snakemake fastq

评论

0赞 euronion 5/4/2023
查看 中的参数空间探索功能。你会发现它正是为此目的而制作的。snakemake
0赞 dariober 5/5/2023
@euronion也许我应该习惯参数空间。不过,乍一看,我发现它很不透明。
0赞 euronion 5/5/2023
@dariober 是的,入门有点棘手。一旦你尝试了一两个简单的示例工作流程,它就不会变得更容易了。但是,您将有一两个示例工作流来构建未来的参数空间;-)

答:

0赞 Dmitry Kuzminov 5/5/2023 #1

简而言之:你不需要 Snakemake。这不是一个好的工具选择,因为它解决了与您拥有的问题相反的问题。

您描述的问题是:有一个输入文件名列表并知道过程,您希望在循环中处理它们。只需使用纯 Python,读取文件名列表,遍历名称,然后使用为每个输入创建输出的命令调用 shell。使用 Python 或您选择的任何其他脚本语言。

Snakemake 是一个强大的工具,可以解决相反的目标。起点是您要创建的目标。下一步是定义如何创建目标的规则。最后一步是提供 INPUT 文件,这些文件将成为依赖项树的叶子,并运行管道。

解决您的问题的一种稍微多一点的 Snakemake-tonic 方法可能如下所示。首先,定义要获取的内容(注意参数):zip

rule all:
    input:
        sam_file = expand("ALIGNEMENT/{sm}/{id}.sam", zip, sm=info_df["SM"], id=info_df["ID"])

然后,您可以定义创建每个 sam 文件的规则。请注意,它被替换为一个字典,该字典提供从 到 fastq 值对的映射:{fastq}(sm, id)

rule create_sam:
    input:
        lambda wildcards: f"PATH/TO/{mapping[(wildcards.sm, wildcards.id)]}"
    output:
        sam_file = "ALIGNEMENT/{sm}/{id}.sam"

最后,您需要从 csv 文件中创建一个字典作为全局对象。不是错误问题的最佳解决方案。mapping

更新:尽管@dariober提供了一个解决问题的有效答案,但我坚持认为在这种情况下没有必要使用 Snakemake。Snakemake 提供的所有好处都丢失了,同时存在不必要的复杂性。作为替代解决方案,我提供了一个简单的单一规则管道,没有讨厌的 lambda。

rule keep_it_simple_stupid:
    script:
        with open("info_file.txt") as f:
            next(f)
            for row in f:
                filename, _, sm, _, id, _, _ = row.split('\t')
                shell(f"do whatever you want with {filename}, {sm}, and {id}")

此规则的主体是纯准系统 Python。如果它是 Snakemake 更惯用的更大管道的一部分,那么将其包装到 Snakemake 规则中可能是有意义的。但如果不是 - 应避免将 Snakemake 作为完成任务的错误工具。

评论

0赞 Théo Durand 5/5/2023
感谢您的回答,但是创建映射字典作为全局对象是什么意思?我只需要这样做:mapping = {} ??而且我真的不明白我的输入如何包含没有FILES列的文件名,你能解释一下吗?
1赞 dariober 5/5/2023 #2

我正在尝试创建 snakemake 规则,该规则接受输入我的 fastq 文件并在输出中为每个 fastq 文件返回一个 .sam 文件。

从上面看来,您想添加到规则中的函数中。使用 zip 可以配对出现在输入列表中的通配符,如果没有它,您将获得 和 的所有组合。zipexpandall{id}{sm}

然后要获取规则中的输入fastq文件,则需要查询info数据帧,得到给定的FILE。您可以使用 lambda 函数或编写专用函数作为输入来执行此操作。alignmentid

以下是我的看法:

import pandas as pd

info_df = pd.read_csv("info_file.txt", sep='\t') 

rule all:
    input:
        expand("ALIGNEMENT/{sm}/{id}.sam", zip, sm = info_df["SM"], id = info_df["ID"])

rule alignement:
    input:
        fastq_files=lambda wc: info_df[info_df['ID'] == wc.id]['FILE'],
    output:
        sam_file = "ALIGNEMENT/{sm}/{id}.sam"
    shell:
        r"""
        echo {input.fastq_files} > {output.sam_file}
        """