Search code examples
snakemake

How do I interpolate wildcards into a shell command?


I'm trying to build a Snakemake pipeline, but I'm confused why filename wildcards work for input and output, but not for shell. For example, the following works fine:

samplelist=[ "aa_S1", "bb_S2"]

rule all:
    input: expand("{sample}.out", sample=samplelist)

rule align:
    input: "{sample}.txt"
    output: "{sample}.out"
    shell: "touch {output}"

But let's say that the command I use for shell actually derives from a string I give it, so I can't name the output file directly in the shell command. Then how can I use my filename wildcard (here {sample}) in the shell command?

For example, the following doesn't work:

samplelist=[ "aa_S1", "bb_S2"]

rule all:
    input: expand("{sample}.out", sample=samplelist)

rule align:
    input: "{sample}.txt"
    output: "{sample}.out"
    shell: "touch {sample}.out"

It gives me the following error:

RuleException in line 6 of Snakefile:
NameError: The name 'sample' is unknown in this context. Please make sure
  that you defined that variable. Also note that braces not used for variable
  access have to be escaped by repeating them, i.e. {{print $1}}

How can I work around this?



(Or if you really want to see some real life code, here is what I'm working with):

samplelist=[ "aa_S1", "bb_S2"]

rule all:
    input: expand("{sample}_aligned.sam", sample=samplelist)

rule align:
    input: "{sample}_R1_001.trimmed.fastq.gz",
           "{sample}_R2_001.trimmed.fastq.gz"
    output: "{sample}_aligned.sam"
    threads: 4
    shell: "STAR --outFileNamePrefix {sample}_aligned  --readFilesIn {input[0]} {input[1]} --readFilesCommand zcat --runMode alignReads --runThreadN {threads} --genomeDir /path/to/StarIndex"

But the error message is basically the same. For shell, I can use {input}, {output}, and {threads}, but not {sample}.

I did look at Snakemake: How do I use a function that takes in a wildcard and returns a value?, but that seems to be focused on generating input file names. My issue deals with interpolation of the filename wildcard into the shell command.


Solution

  • Wildcards are available via {wildcards.XXXX}. source

    rule align:
        input: "{sample}.txt"
        output: "{sample}.out"
        shell: "touch {wildcards.sample}.out"