biocore/scikit-bio — pull request #224 by ElBrogrammer (2014-03-26 16:09:45+00:00)
Title: Add method to expand degeneracies

Added a method `NucleotideSequence.nondegenerates()` that generates all possible nondegenerate sequences.

This is similar to PyCogent's `cogent.seqsim.sequence_generators.SequenceGenerator`, but has a different interface and implementation. It is much simpler than `SequenceGenerator`, as it doesn't have the ability to slice into the possible generated sequences, index them, generate a subset, query the total number of possible seqs, etc.

I chose to go with this simpler functionality as degeneracy expansion is only used in QIIME's split_libraries.py. It only expects some sort of generator, so a native Python `generator` seemed appropriate here.

I did some light performance testing and this version is slightly faster than the one in PyCogent. The implementation is also much simpler and it yields rich `NucleotideSequence` objects.

Other differences between this version and PyCogent's `SequenceGenerator`:

- the empty sequence (`NucleotideSequence('')`) yields the empty sequence. PyCogent didn't yield anything in this case. The new behavior seems more consistent to me because the empty sequence is a valid sequence without degeneracies, so we should yield the original (empty) sequence.
- there is no implicit/explicit ordering to the generated sequences, because we're using `set`s to store degenerate characters. PyCogent used a string to store degenerate characters, so ordering was guaranteed. For our use-cases, I don't think ordering matters.
- this version supports sequences with mixed-case and gap characters. This would have resulted in a `KeyError` in PyCogent.