Search code examples
snakemake

snakemake if else statement within rule input


With snakemake, I would like to have a different input (including a wildcard) within a rule according to a boolean

I've tried :

rule quantify:
    input:
        if trimmed_fastq:
            forward = path_trimmed_fastq + "/{sample}_R1_val_1.fq.gz",
            rev = path_trimmed_fastq + "/{sample}_R2_val_2.fq.gz"
        else:
            forward = fastq_path + "/{sample}_R1.fastq.gz",
            rev = fastq_path + "/{sample}_R2.fastq.gz"

But it gives me an "invalid syntax" error, I think it doesn't like if else statement in input, anyone has an idea how to fix this?

I know I could have two different "quantify" and "quantify_trimmed" rules with if else statement around them, but I'm wondering if there is a more elegant solution.

Thank you for your help


Solution

  • Indeed, you cannot have an if..else statement inside an input. Instead, a function can be used to achieve what you want:

    def getInputFilesForQuantify(wildcards):
        files = dict()
        if(trimmed_fastq):
            files["forward"] = os.path.join(path_trimmed_fastq,wildcards.sample,"_R1_val_1.fq.gz")
            files["rev"] = os.path.join(path_trimmed_fastq,wildcards.sample,"_R2_val_2.fq.gz")
        else:
            files["forward"] = os.path.join(fastq_path,wildcards.sample,"_R1.fastq.gz")
            files["rev"] = os.path.join(fastq_path,wildcards.sample,"_R2.fastq.gz")
        return files
    
    rule quantify:
        input: unpack(getInputFilesForQuantify)
        output: ....
    

    Note:

    • wildcards are passed to the parameters of the function.
    • unpack is here used because you're returning a dictionnary if naming of your inputs are needed. Otherwise, a simple list of files is returned.