You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:53:11