Snakemake中如何限制通配符仅展开有效组合?
当然可以!你当前遇到的问题是因为全局定义的SAMPLE列表没有和GROUP关联,导致Snakemake展开了所有group和sample的笛卡尔积(比如group1和sample3这种不存在的组合)。要解决这个问题,核心是建立每个group对应的专属sample列表,然后让Snakemake基于这个映射来生成任务。
步骤1:构建Group-Sample关联映射
首先替换你原来的GROUP和SAMPLE定义,用一个字典来存储每个group对应的有效samples:
import os from glob import glob # 定义基础目录 base_dir = "directory" # 构建group到对应samples的字典 group_samples = {} for group_dir in glob(os.path.join(base_dir, "*")): if os.path.isdir(group_dir): group_name = os.path.basename(group_dir) # 获取该group下的所有sample文件,根据你的文件名格式调整后缀处理逻辑 sample_list = [ os.path.splitext(os.path.splitext(fn)[0])[0] # 去掉.fastq.gz后缀 for fn in glob(os.path.join(group_dir, "*.fastq.gz")) ] group_samples[group_name] = sample_list
这个字典会准确记录每个group下存在的sample,比如group_samples["group1"]就是["sample1", "sample2"],完全不会混入其他group的sample。
步骤2:用expand生成有效任务目标
接下来,在rule all中使用Snakemake的expand函数,结合上面的映射来生成所有需要处理的有效文件:
rule all: input: # Group级别的任务输出 expand("other_directory/{group}/{group}_contig_file.fasta", group=group_samples.keys()), # Sample级别的任务输出:仅展开每个group对应的有效sample expand( "other_directory/{group}/{group}{sample}.bam", group=group_samples.keys(), sample=lambda wildcards: group_samples[wildcards.group] )
这里的关键是sample=lambda wildcards: group_samples[wildcards.group]——它会针对每个{group}通配符,动态获取该group下的sample列表,而不是使用全局的sample列表,这样就完全避免了无效组合。
步骤3:调整规则(可选优化)
你原来的规则可以直接复用,不过可以稍微优化一下路径的可读性:
rule group_task: input: group_dir=os.path.join(base_dir, "{group}") output: "other_directory/{group}/{group}_contig_file.fasta" # 替换成你的group处理逻辑 shell: """ # 示例:从group目录生成contig文件 your_group_command {input.group_dir} > {output} """ rule sample_per_group_task: input: sample_reads=os.path.join(base_dir, "{group}/{sample}.fastq.gz"), group_contigs="other_directory/{group}/{group}_contig_file.fasta" output: "other_directory/{group}/{group}{sample}.bam" # 替换成你的sample处理逻辑 shell: """ # 示例:将sample reads比对到group contigs your_alignment_tool -i {input.sample_reads} -r {input.group_contigs} -o {output} """
为什么这个方法有效?
通过提前构建group和sample的关联映射,Snakemake在解析任务时只会处理实际存在的组合,不会生成像group1/sample3.fastq.gz这种不存在的输入文件。同时,这种方法也保持了Snakemake的并行化能力——每个group下的sample任务仍然可以并行运行,完全符合你的需求。
内容的提问来源于stack exchange,提问作者EisenRa

