3

Can anybody help me understand if it is possible to access sample details from a config.yml file when the sample names are not written in the snakemake workflow? This is so I can re-use the workflow for different projects and only adjust the config file. Let me give you an example:

I have four samples that belong together and should be analyzed together. They are called sample1-4. Every sample comes with some more information but to keep it simple here lets say its just a name tag such as S1, S2, etc.

My config.yml file could look like this:

samples: ["sample1","sample2","sample3","sample4"]

sample1:
  tag: "S1"
sample2:
  tag: "S2"
sample3:
  tag: "S3"
sample4:
  tag: "S4"

And here is an example of the snakefile that we use:

configfile: "config.yaml"

rule final: 
  input: expand("{sample}.txt", sample=config["samples"])

rule rule1:
  output:  "{sample}.txt"
  params:  tag=config["{sample}"]["tag"]
  shell:   """
           touch {output}
           echo {params.tag} > {output}

What rule1 is trying to do is create a file named after each sample as saved in the samples variable in the config file. So far no problem. Then, I would like to print the sample tag into that file. As the code is written above, running snakemake will fail because config["{sample}"] will literally look for the {sample} variable in the config file which doesn't exist because instead I need it to be replaced with the current sample that the rule is run for, e.g. sample1.

Does anybody know if this is somehow possible to do, and if yes, how I could do it?

Ideally I'd like to compress the information even more (see below) but that's further down the road.

samples:
    sample1:
        tag: "S1"
    sample2:
        tag: "S2"
    sample3:
        tag: "S3"
    sample4:
        tag: "S4"
fakechek
  • 239
  • 2
  • 14
  • 1
    Snakemake won't replace curly braces statements in any part of the Snakefile. Only in shell commands and input/output/params given as plain strings. In your case, you need to write `tag=lambda wildcards: config[wildcards.sample]["tag"]`. – Johannes Köster Jan 10 '18 at 08:37
  • Excellent, thank you! – fakechek Jan 10 '18 at 10:19

2 Answers2

5

I would suggest using a tab-delimited file in order to store samples information.

sample.tab:

Sample     Tag      
1          S1   
2          S2

You could store the path to this file in the config file, and read it in your Snakefile.

config.yaml:

sample_file: "sample.tab"

Snakefile:

configfile: "config.yaml"

sample_file = config["sample_file"]

samples = read_table(sample_file)['Sample']
tags    = read_table(sample_file)['Tag']

This way your can re-use your workflow for any number of samples, with any number of columns.

Apart from that, in Snakemake usually you can escape curly brackets by doubling them, maybe you could try that.

Good luck!

rioualen
  • 948
  • 8
  • 17
  • 3
    Yes, a separate sample sheet is the more scalable way. Note that you can read it in a one-liner via pandas: `pd.read_table(config["samples"])`. See https://github.com/snakemake-workflows/rna-seq-star-deseq2 for an example. – Johannes Köster Jan 10 '18 at 08:35
  • Good point about separating sample and config information. For now I have barely any settings saved in the config file but as I extend the workflow I'm sure it will become more obvious to separate those things. – fakechek Jan 10 '18 at 10:20
3

In the params section, you need to provide a function of wildcards. The following modification of your workflow seems to work:

configfile: "config.yaml"

rule final: 
    input: expand("{sample}.txt", sample=config["samples"])

rule rule1:
    output:
        "{sample}.txt"
    params:
        tag = lambda wildcards: config[wildcards.sample]["tag"]
    shell:
        """
        touch {output}
        echo {params.tag} > {output}
        """
bli
  • 7,549
  • 7
  • 48
  • 94