我正在尝试创建 snakemake 规则,该规则接收我的 fastq 文件的输入并在输出中为每个
fastq
文件返回一个 .sam 文件。
我有这样一个文件:
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”列中输入,并在输出中使用这样的路径:
"ALIGNEMENT/{sm}/{id}.sam"
其中 {sm} 和 { id} 是我的 file.txt 的 SM 和 ID 列
我还想为每个文件启动一个规则。
如果有人可以帮助我谢谢你
我正在尝试创建 snakemake 规则,该规则接收我的 fastq 文件的输入并在输出中为每个 fastq 文件返回一个 .sam 文件。
从上面看来,在我看来,您想将
zip
添加到规则expand
中的all
功能。使用 zip,您可以在输入列表中显示通配符,如果没有它,您将获得{id}
和{sm}
的所有组合。
然后要获取规则
alignment
中的输入fastq文件,您需要查询信息数据框以获取给定id
对应的FILE。您可以使用 lambda 函数或编写专用函数作为输入来执行此操作。
这是我的看法:
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}
"""
简而言之:您不需要 Snakemake。这不是一个很好的工具选择,因为它解决了与你所拥有的相反的问题。
你描述的问题是:有一个输入文件名列表并知道过程,你想循环处理它们。只需使用纯 Python,读取文件名列表,遍历名称并使用为每个输入创建输出的命令调用 shell。使用 Python 或您选择的任何其他脚本语言。
Snakemake 是解决相反目标的强大工具。起点是您要创建的目标。下一步是定义如何创建目标的规则。最后一步是提供成为依赖树叶子的 INPUT 文件,并运行管道。
解决你的问题的一种更像蛇蝎的方法可能如下所示。首先你定义你想要得到什么(注意
zip
参数):
rule all:
input:
sam_file = expand("ALIGNEMENT/{sm}/{id}.sam", zip, sm=info_df["SM"], id=info_df["ID"])
然后您可以定义一个规则来创建每个 sam 文件。请注意,
{fastq}
被替换为字典,该字典提供从 (sm, id)
对到 fastq 值的映射:
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 作为任务的错误工具。