Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional execution of one rule or another depending on the arguments given to a snakemake pipeline

Tags:

snakemake

I am creating a snakemake pipeline where I have, in some point, to filter my results. But there are two kind of filters that I could apply, so I would like to give it as an argument when launching the pipelin and then, depending on the argument, I would like to apply a rule or another.

As an example:

snakemake --snakefile my_pipeline.sm --config filter=${1}

where filter can be Hard or Soft

my_pipeline.sm is conformed by 4 rules:

rule A:
    input:
          A.bam
    outpu:
          A.vcf
    shell:
          "do.something"

rule B:
    input:
         A.vcf
    output:
         A.hard_filtered.vcf
    shell:
         "do.something"

rule C:
    input:
         A.vcf
    output:
         A.soft_filtered.vcf
    shell:
         "do.something"

rule D:
    input:
         A.*_filtered.vcf
    output:
         A.annotated.vcf
    shell:
         "do.something"

Is there anyway to execute rule B if filter argument is Hard, while executing rule C if filter argument is Soft; instead of performing a conditional clausule in the shell command of a unique rule? I didn't find this information in snakemake manual.

like image 605
Jeni Avatar asked Sep 03 '25 16:09

Jeni


1 Answers

Snakemake has a feature called ruleorder. That allows you to disambiguate rules. For example in your code (which wouldn't work, but let's assume that it is corrected) you have two equal branches to get the target file done:

  • A.bam -> A.vcf -> A.hard_filtered.vcf -> A.annotated.vcf
  • A.bam -> A.vcf -> A.soft_filtered.vcf -> A.annotated.vcf

Snakemake will complain that it doesn't know which branch to prefer. That could be fixed by:

ruleorder: rule1 > rule2

Now Snakemake will always prefer rule1 to the rule2.

You may define two different orderings based on the configuration (that comes either from file or from command line). Below is my simplified code sample.

configfile: "config.yml"

if config["filtering"] == "soft":
    ruleorder: annotate_soft > annotate_hard
else:
    ruleorder: annotate_hard > annotate_soft

rule all:
    input:
        "A.annotated.vcf"

rule hard:
    input:
        "A.vcf"
    output:
        "A.hard_filtered.vcf"
    shell:
        "echo 'hard' > {output}"

rule soft:
    input:
        "A.vcf"
    output:
        "A.soft_filtered.vcf"
    shell:
        "echo 'soft' > {output}"

rule annotate_hard:
    input:
        "A.hard_filtered.vcf"
    output:
        "A.annotated.vcf"
    shell:
        "cp {input} {output}"

rule annotate_soft:
    input:
        "A.soft_filtered.vcf"
    output:
        "A.annotated.vcf"
    shell:
        "cp {input} {output}"
like image 55
Dmitry Kuzminov Avatar answered Sep 05 '25 16:09

Dmitry Kuzminov