How to use the expand function in Snakemake to make permutations or combinations of a list

Viewed 187

probably a very basic question in Snakemake but I couldn't find the answer so far. Say I have a list of samples

SAMPLES = ["A", "B", "C"]

A typical expand command would look like:

expand("{sample}.txt", sample=SAMPLES)

But I would like to get combinations (or even permutations) of the same samples list.

Doing:

expand("{sample}-{sample}.txt", sample=SAMPLES)

would give you

 A-A.txt, A-B.txt, A-C.txt, B-A.txt, B-B.txt, B-C.txt, C-A.txt, C-B.txt, C-C.txt

Instead I want:

A-B.txt, A-C.txt, B-C.txt

In the Snakemake documentation for the expand function they say:

"Per default, expand uses the python itertools function product that yields all combinations of the provided wildcard values. However by inserting a second positional argument this can be replaced by any combinatoric function, e.g. zip"

However, I cannot just replace product with the itertools.combinations function because, as far as I can tell from the source code of expand, you can't give the r (length of the output tuples) argument to expand. Doing

import itertools
expand("{sample}-{sample}.txt", itertools.combinations, sample=SAMPLES)

Returns an error of 'list' object cannot be interpreted as an integer. But it works with itertools.product.

I guess I could create two lists outside of the rules with itertools.combinations before calling expand, but I was hoping for an elegant way of doing it from the Snakemake community.

Thanks!

1 Answers

Maybe it can be done within expand but I think it would be easier to generate the list of interest without it. E.g.:

SAMPLES = ["A", "B", "C"]

combs = []
for x in itertools.combinations(SAMPLES, 2):
    combs.append('%s-%s.txt' %(x[0], x[1]))

print(combs)                                                                                                                                                                                                                                                                      
['A-B.txt', 'A-C.txt', 'B-C.txt']

Now use combs wherever you would have used expand(...). Consider that expand is just a convenience function that returns a list but you don't have to necessarily use it

Related