Snakemake rule for analysis where a single result file is produced for diff parameters, and parameter is coming from another rule output content

Viewed 64

I have the following basic snakemake setup:

rule step1:
    """
    The output will contain a list of GENEs in a txt file.
    """

    input: "input1.txt"

    output: "output1.txt"

    shell:
        """
        analysis1.R {input} {output}
        """

rule step2:
    """
    Analysis step2.
    """

    input: "input2.txt"

    output: "output2.txt"

    shell:
        """
        analysis2.py {input} {output}
        """

rule step3:
    """
    GENE should be coming from the step1 output file, with a GENE name on each
    line.
    """

    input: rules.step2.output

    output: "output3-GENE.txt"

    shell:
        """
        analysis3.py -i {input} -o {output} -p GENE
        """

I produce a file with a list of genes (parameters) in step1 for step3 and another file in step2. What I would like to do is run step3 as many times as lines I have in output1.txt where the content of the line is a parameter for step3, and it should also be part of the output file name, but I can't wrap my head around it. Any ideas? Thanks for the help!

1 Answers

You can use checkpoints.

If you know the list of files that your step3 file shall generate, you may define an aggregate rule:

rule aggregate:
    input:
        # List of files that step3 needs to generate

That would allow you to run the rule step3 as many times as is needed.

The tricky part is to define the list of these files. That shall be the function of the result of the rule step1:

def aggregate_input(wildcards):
    with checkpoints.rile1.get().output[0].open() as f:
        return f.readlines()

rule aggregate:
    input:
        aggregate_input

In this case the rule step1 shall become a checkpoint:

checkpoint step1:
    """
    The output will contain a list of GENEs in a txt file.
    """

    input: "input1.txt"

    output: "output1.txt"

    shell:
        """
        analysis1.R {input} {output}
        """

In my example I've simplified the function aggregate_input to return just the lines of the output of step1. If you need a more complex function, you may design your own one.

Related