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"


from Bio.Seq import MutableSeq
from Bio.Alphabet import generic_dna
my_seq = MutableSeq("ACTCGTCGTCG", generic_dna)
my_seq[5] = "A"
## 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?

  • 2
    $\begingroup$ 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 $\endgroup$
    – Bioathlete
    Sep 14, 2017 at 1:32
  • 1
    $\begingroup$ 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. $\endgroup$
    – terdon
    Sep 14, 2017 at 7:48
  • $\begingroup$ @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?) $\endgroup$ Sep 14, 2017 at 14:34
  • 1
    $\begingroup$ 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). $\endgroup$
    – Bioathlete
    Sep 14, 2017 at 17:31
  • 2
    $\begingroup$ @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. $\endgroup$
    – terdon
    Sep 15, 2017 at 7:45

2 Answers 2


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]))
        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.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.