# Is it possible to do alignment within Python? Check variants against reference?

I'm currently adding a few SNPs randomly into a FASTA within python using BioPython. In the following example from BioPython, I add an SNV at location "5"

http://biopython.org/DIST/docs/api/Bio.Seq.MutableSeq-class.html

from Bio.Seq import MutableSeq
from Bio.Alphabet import generic_dna
my_seq = MutableSeq("ACTCGTCGTCG", generic_dna)
my_seq[5] = "A"
print(my_seq)
## outputs ACTCGACGTCG


In my case, I'm using the reference hg38 as the input FASTA to manipulate.

After randomly inserting these SNPs, I would like to find a region whereby there are no SNPs within (let's say) +/- 50Kb, or the next nearest thing.

Is it possible to align the FASTA with variants against the reference within python? Otherwise, is there a quick way to check the variant FASTA against the reference FASTA, finding a region with no variants? What would be an efficient way to execute this task?

• If you are making the random mutations why not just keep track of the mutated locations to locate the regions of interest. There is no need to do an alignment if you know where the mutations are since you induced the mutations Sep 14 '17 at 1:32
• Yes, the obvious approach would be to simply keep track of what regions you have modified. Aligning the entire genome to itself just to find a few SNPs is possible, but much, much harder than just keeping track of your changes. Please edit your question and explain why you don't just want to track them yourself. Also, it would be helpful if you could show your actual code instead of the example given in the documentation. Sep 14 '17 at 7:48
• @Bioathlete In that case, let's say I keep track of the changes I make. I could reserve a region whereby I make no changes in this region of course. Given a list of mutations though in a bed-list format within Python (let's say, using a pandas DataFrame, how would you calculate a region with no mutations?) Sep 14 '17 at 14:34
• I would sort the entries by chr and position and then just compare the current position with the next position to see if it is above the threshold of interest (50kb in your example). Sep 14 '17 at 17:31
• @ShanZhengYang please edit your question so it asks what you are actually trying to do. If you have a bed file of regions, it's a completely different proposition. Please show us your code, explain what exactly you need to do going forwards and we'll see if we can help. Sep 15 '17 at 7:45

As others have said, doing whole-genome (or even whole-chromosome) alignments is the wrong solution. Simply track where you're creating SNVs. If you wrote your SNV locations to a sorted BED file you could use something like the following:

#!/usr/bin/env python
minWidth = 100000  # Only report regions of >=100kb
last = [None, None]
for line in open("some bed file"):
cols = line.strip().split()
if cols[0] != last[0]:
if int(cols[2]) >= minWidth:
print("{}:1-{}".format(cols[0], cols[2]))
else:
if int(cols[2]) - last[1] >= minWidth
print("{}:{}-{}".format(cols[0], last[1], cols[2]))
last = [cols[0], int(cols[2])]


This will miss the last part of each chromosome/contig, since it doesn't know how long they are, but you should be able to figure out how to handle that. The memory requirements of this are trivially small.

I suspect there's also a bedtools or bedops command that will directly give you the distance to the next downstream region. One could alternatively parse that (it's all the above code is doing, but using bedtools or bedops would produce more validated results than a quickly thrown together script).

If you store the positions of your random SNPs in a sort-bed sorted BED file, you can filter with BEDOPS bedmap:

$bedmap --count --echo --range 50000 --delim '\t' SNPs.bed | awk '$1==1' | cut -f2- > SNPs.filtered.bed


The file SNPs.filtered.bed will only contain those elements from SNPs.bed which do not overlap within 50kb.

Or you can use BEDOPS bedops and closest-features to do the same thing, but the logic isn't nearly as pretty:

$bedops --everything --range 0:50000 test.bed | closest-features --dist test.bed - | awk -v FS='|' '{ if ($NR > 50000) { print \$1; } }' > SNPs.filtered.bed


The result is the same as with the bedmap pipeline. IMO, the bedmap approach is cleaner.

Once you have SNPs.filtered.bed, you could convert it to FASTA via samtools faidx and bed2faidx.pl or similar. Then you have FASTA upon which you can apply your random perturbations.