Snakemake多通配符实现:从目录结构读取输入文件
问题描述
我想要构建一个可处理多输入文件、调用各类工具生成目标结果的Snakemake流程。我的input/目录结构如下:
- organism_A - gene_1 - seq_1.fasta - seq_2.fasta - gene_2 - seq_3.fasta - organism_B - gene_1 - seq_4.fasta - seq_5.fasta - seq_6.fasta - gene_3 - seq_7.fasta
目前我的方案仅使用一个{sequence}通配符,对应input/目录中文件的完整相对路径(例如input/organism_A/gene_1/seq_1.fasta)。这个方案在单一规则下运行正常,但添加更多规则时,很难精准指定输入与输出。
我认为基于input/目录中的文件结构创建{organism}、{gene}和{sequence}三个通配符是可行的,这样能方便维护输出名称,解决上述问题。请问是否可以基于input/目录中的文件实现这种多通配符的方案?
附当前代码:
import os # Get a list of all .fasta files in the input directory and its subdirectories def get_input_files(directory): input_files = [] for root, _, files in os.walk(directory): for file in files: if not file.startswith('.') and file.endswith('.fasta'): # Get the relative path by stripping the "input/" prefix relative_path = os.path.relpath(os.path.join(root, file), directory) input_files.append(relative_path) return input_files input_files = get_input_files("input") rule all: input: expand("output/{sequence}", sequence=input_files) rule run_script: input: sequence=lambda wildcards: f"input/{wildcards.sequence}" output: directory("output/{sequence}") shell: r""" my scipt which will produce files in output directory """
解决方案
完全可以实现多通配符方案,核心是解析输入文件路径,拆分出organism、gene、sequence三个维度的信息,再用这些信息构建Snakemake的通配符规则。具体实现步骤如下:
1. 解析输入路径,提取多维度元数据
修改原有的文件获取函数,不再只返回完整路径,而是返回包含三个维度信息的字典列表,方便后续生成通配符目标:
import os from pathlib import Path def get_input_metadata(directory): metadata = [] for root, _, files in os.walk(directory): for file in files: if not file.startswith('.') and file.endswith('.fasta'): # 用Path对象拆分路径层级 rel_path = Path(os.path.relpath(os.path.join(root, file), directory)) organism = rel_path.parts[0] gene = rel_path.parts[1] sequence = rel_path.stem # 自动去掉.fasta后缀 metadata.append({ "organism": organism, "gene": gene, "sequence": sequence }) return metadata input_metadata = get_input_metadata("input")
2. 用多通配符定义最终目标(rule all)
基于提取的元数据,用三个通配符构建输出路径,保持和输入对应的层级结构,逻辑更清晰:
rule all: input: # 按元数据展开所有目标路径 expand( "output/{organism}/{gene}/{sequence}_results", zip, **{k: [d[k] for d in input_metadata] for k in ["organism", "gene", "sequence"]} )
3. 重写处理规则,关联多通配符输入输出
现在每个规则都能精准获取三个维度的信息,输入输出路径更直观,也便于后续扩展新规则:
rule run_script: input: fasta="input/{organism}/{gene}/{sequence}.fasta" output: directory("output/{organism}/{gene}/{sequence}_results") shell: r""" mkdir -p {output} # 可直接使用通配符变量传递参数 my_script --input {input.fasta} --output {output} --organism {wildcards.organism} """
4. 扩展规则的优势示例
当需要添加预处理等新规则时,多通配符能让依赖关系一目了然:
# 新增预处理规则 rule preprocess_seq: input: fasta="input/{organism}/{gene}/{sequence}.fasta" output: processed="output/{organism}/{gene}/{sequence}_processed.fasta" shell: r""" preprocess_tool {input.fasta} > {output.processed} """ # 主规则依赖预处理结果 rule run_script: input: processed_fasta=rules.preprocess_seq.output.processed output: directory("output/{organism}/{gene}/{sequence}_results") shell: r""" mkdir -p {output} my_script --input {input.processed_fasta} --output {output} """
这种方式彻底解决了单一通配符带来的路径模糊问题,让整个流程逻辑更清晰,便于维护和扩展。
内容的提问来源于stack exchange,提问作者amk
相关产品推荐
相关产品推荐

