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

Snakemake如何根据wildcard值选择执行对应规则?

解决Snakemake中物种分支执行及公共预处理重复问题

针对你遇到的问题,核心是要让公共预处理规则prepare_data仅在处理mouse或human时触发一次,同时避免其他物种的规则无意义地调用它。以下是几种可行的实现方案:

方案1:分组通配符+条件依赖(推荐)

通过明确拆分目标集,让mouse/human的处理规则依赖prepare_data,其他物种的规则直接独立执行。

步骤1:定义规则与依赖

# 限制species通配符的合法取值
wildcard_constraints:
    species=r"mouse|human|(?!mouse|human)\w+"

# 公共预处理规则:无通配符,确保仅执行一次
rule prepare_data:
    output:
        "data/processed/ready_flag.txt"
    shell:
        """
        # 这里编写公共预处理逻辑,如下载公共参考、初始化配置等
        echo "Preprocessing done" > {output}
        """

# mouse/human专属处理规则:依赖prepare_data
rule process_mouse_human:
    input:
        prep="data/processed/ready_flag.txt",
        raw_data="data/raw/{species}.fastq"
    output:
        "data/processed/{species}.bam"
    shell:
        """
        # 编写mouse/human特有的处理流程,比如比对到特定参考基因组
        samtools view -Sb {input.raw_data} > {output}
        """

# 其他物种处理规则:不依赖prepare_data
rule process_other_animals:
    input:
        raw_data="data/raw/{species}.fastq"
    output:
        "data/processed/{species}.bam"
    shell:
        """
        # 编写其他物种的专属处理逻辑
        custom_animal_pipeline {input.raw_data} -o {output}
        """

步骤2:拆分目标集合

# 定义所有需要处理的物种列表
all_species = ["mouse", "human", "rat", "dog", "cat"]

# 拆分mouse/human和其他物种的目标文件
mh_targets = expand("data/processed/{species}.bam", species=["mouse", "human"])
animal_targets = expand("data/processed/{species}.bam", species=[s for s in all_species if s not in ["mouse", "human"]])

# 总目标规则
rule all:
    input:
        mh_targets,
        animal_targets

运行时,Snakemake会自动识别:mouse/human的目标需要先执行prepare_data,再执行process_mouse_human;其他物种直接执行process_other_animals,不会触发prepare_data。

方案2:动态生成规则

如果需要为每个物种生成独立规则,可通过Python循环动态创建,精准控制依赖关系:

all_species = ["mouse", "human", "rat", "dog"]

rule prepare_data:
    output:
        "data/processed/ready_flag.txt"
    shell:
        "echo 'Preprocessing done' > {output}"

# 为mouse/human生成带prepare_data依赖的规则
for sp in ["mouse", "human"]:
    rule:
        name = f"process_{sp}"
        input:
            prep="data/processed/ready_flag.txt",
            raw=f"data/raw/{sp}.fastq"
        output:
            f"data/processed/{sp}.bam"
        shell:
            f"samtools view -Sb {input.raw} > {output}"

# 为其他物种生成无依赖的规则
for sp in [s for s in all_species if s not in ["mouse", "human"]]:
    rule:
        name = f"process_{sp}"
        input:
            raw=f"data/raw/{sp}.fastq"
        output:
            f"data/processed/{sp}.bam"
        shell:
            f"custom_animal_pipeline {input.raw} -o {output}"

rule all:
    input:
        expand("data/processed/{species}.bam", species=all_species)

这种方式适合每个物种的处理逻辑差异较大的场景,同时保证prepare_data仅被mouse/human的规则调用一次。

方案3:Checkpoint(适用于动态预处理输出)

如果prepare_data的输出是动态生成的(比如根据后续需求生成不同文件),可以用Checkpoint确保它仅执行一次:

checkpoint prepare_data:
    output:
        directory("data/processed/prep_output")
    shell:
        """
        mkdir -p {output}
        echo 'Preprocessing done' > {output}/ready.txt
        # 其他动态预处理步骤
        """

# 定义函数获取预处理输出,确保Checkpoint完成后才继续
def get_prep_input(wildcards):
    prep_dir = checkpoints.prepare_data.get_output()[0]
    return f"{prep_dir}/ready.txt"

rule process_mouse_human:
    input:
        prep=get_prep_input,
        raw_data="data/raw/{species}.fastq"
    output:
        "data/processed/{species}.bam"
    shell:
        "samtools view -Sb {input.raw_data} > {output}"

rule process_other_animals:
    input:
        raw_data="data/raw/{species}.fastq"
    output:
        "data/processed/{species}.bam"
    shell:
        "custom_animal_pipeline {input.raw_data} -o {output}"

rule all:
    input:
        expand("data/processed/{species}.bam", species=["mouse", "human", "rat", "dog"])

Checkpoint会在所有依赖它的规则执行前完成,且仅执行一次,适合复杂的动态预处理场景。


内容的提问来源于stack exchange,提问作者dariober

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 06:18:24