Skip to content

Commit

Permalink
Merge branch 'local_blast'
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosp420 committed Jan 3, 2015
2 parents 970e61b + aa29005 commit 9b2cfbe
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 15 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ index:

coverage:
rm -rf htmlcov .coverage
coverage run --source voseq voseq/manage.py test -v 2 public_interface --settings=voseq.settings.base
coverage run --source voseq voseq/manage.py test -v 2 public_interface blast_local --settings=voseq.settings.base
coverage report -m
coverage html

test:
coverage run --source voseq voseq/manage.py test -v 2 public_interface --settings=voseq.settings.base
coverage run --source voseq voseq/manage.py test -v 2 public_interface blast_local --settings=voseq.settings.base
2 changes: 2 additions & 0 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ dataset==0.5.5
django-haystack==2.3.1
elasticsearch==1.2.0
coveralls==0.5
django-debug-toolbar==1.2.2
biopython==1.65
2 changes: 1 addition & 1 deletion test_db_dump.xml
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@
<field name="dateModification" xsi:nil="true" />
<field name="notes" xsi:nil="true" />
<field name="timestamp">2008-07-17 17:24:20</field>
<field name="id">4</field>
<field name="id">5</field>
<field name="genbank">1</field>
</row>
</table_data>
Expand Down
6 changes: 0 additions & 6 deletions voseq/Makefile

This file was deleted.

Empty file added voseq/blast_local/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions voseq/blast_local/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
Empty file.
3 changes: 3 additions & 0 deletions voseq/blast_local/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.db import models

# Create your models here.
57 changes: 57 additions & 0 deletions voseq/blast_local/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import glob
import os

from django.core.management import call_command
from django.test import TestCase
from django.conf import settings

from .utils import BLAST


class BlastLocalTest(TestCase):
def setUp(self):
args = []
opts = {'dumpfile': 'test_db_dump.xml'}
cmd = 'migrate_db'
call_command(cmd, *args, **opts)

blast_type = 'local'
voucher_code = 'CP100-10'
gene_code = 'COI'
self.blast = BLAST(blast_type, voucher_code, gene_code)
self.seq_file = ''

'''
def test_have_blast_db(self):
result = self.blast.have_blast_db()
self.assertEqual(False, result)
def test_have_blast_db_true(self):
self.blast.create_blast_db()
result = self.blast.have_blast_db()
self.assertEqual(True, result)
'''

def test_save_seqs_to_file(self):
self.blast.save_seqs_to_file()
self.seq_file = os.path.join(settings.BASE_DIR,
'..',
'blast_local',
'db',
'COI_seqs.fas',
)
result = os.path.isfile(self.seq_file)
self.assertTrue(result)

def test_create_blast_db(self):
self.blast.save_seqs_to_file()
self.blast.create_blast_db()
files = glob.glob(
os.path.join(settings.BASE_DIR,
'..',
'blast_local',
'db',
'COI_seqs.fas.n*')
)
self.assertTrue(len(files) > 0)
10 changes: 10 additions & 0 deletions voseq/blast_local/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.conf.urls import patterns
from django.conf.urls import url

from . import views


urlpatterns = patterns(
'',
url(r'^/(?P<voucher_code>.+)/(?P<gene_code>.+)/$', views.index, name='index'),
)
105 changes: 105 additions & 0 deletions voseq/blast_local/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import os
import re
import subprocess

from Bio.Blast.Applications import NcbiblastnCommandline
from Bio.Seq import Seq
from Bio import SeqIO
from Bio.SeqRecord import SeqRecord

from public_interface.models import Sequences


class BLAST(object):
"""
Class to handle duties related to local blast against sequences of one gene,
and full blast against all sequences in our database.
"""
def __init__(self, blast_type, voucher_code, gene_code):
"""
Type of blast to do: local, full, remote
:param blast_type: local, full, remote.
:param voucher_code:
:param gene_code:
"""
self.blast_type = blast_type
self.voucher_code = voucher_code
self.gene_code = gene_code
self.mask = True
self.cwd = os.path.dirname(__file__)

def have_blast_db(self):
"""
Finds out whether we already have a blast db with our sequences.
:return: True or False
"""
pass

def is_blast_db_up_to_date(self):
"""
Finds out whether our blast db contains all our sequences. In other
words, it finds out whether there are sequences in our postgres db with
time_created or time_edited more recent than our blast db files.
:return:
"""
pass

def save_seqs_to_file(self):
"""
Query sequences for each gene from our database and save them to local
disk.
Sets attribute `self.seq_file` containing necessary sequences from our
database.
"""
if self.blast_type == 'local':
self.seq_file = os.path.join(self.cwd,
'db',
self.gene_code + "_seqs.fas",
)
queryset = Sequences.objects.all().filter(gene_code=self.gene_code)

my_records = []
for i in queryset:
id = i.code_id + '|' + i.gene_code
seq = self.strip_question_marks(i.sequences)
seq_record = SeqRecord(Seq(seq),
id=id)
my_records.append(seq_record)
SeqIO.write(my_records, self.seq_file, "fasta")

def strip_question_marks(self, seq):
seq = re.sub('^\?+', '', seq)
seq = re.sub('\?+$', '', seq)
return seq

def create_blast_db(self):
"""
Creates a BLAST database from our sequences file in FASTA format.
Optionally eliminates low-complexity regions from the sequences.
:return:
"""
if self.mask is True:
command = 'dustmasker -in ' + self.seq_file + ' -infmt fasta '
command += '-outfmt maskinfo_asn1_bin -out ' + self.seq_file + '_dust.asnb'
subprocess.check_output(command, shell=True) # identifying low-complexity regions.

command = 'makeblastdb -in ' + self.seq_file + ' -input_type fasta -dbtype nucl '
command += '-mask_data ' + self.seq_file + '_dust.asnb '
command += '-out ' + self.seq_file + ' -title "Whole Genome without low-complexity regions"'
print("creating database...")
subprocess.check_output(command, shell=True) # Overwriting the genome file.
else:
command = 'makeblastdb -in ' + self.seq_file + ' -input_type fasta -dbtype nucl '
command += '-out ' + self.seq_file + ' -title "Whole Genome unmasked"'
print("creating database...")
subprocess.check_output(command, shell=True)

def do_blast(self):
blastn_cline = NcbiblastnCommandline(query=self.query, db=self.db,
evalue=0.001, outfmt=5, out="opuntia.xml")
blastn_cline()
7 changes: 7 additions & 0 deletions voseq/blast_local/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@


from django.shortcuts import render


def index(request, voucher_code, gene_code):
return render(request, 'public_interface/base.html')
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ <h3 class="panel-title"><b>Sequence Information</b></h3>
<td><b>Lab.</b></td>
<td><b>Accession</b></td>
<td><b>local Blast</b></td>
<td><b>ncbi Blast</b></td>
<td><b>NCBI Blast</b></td>
</tr>
{% for item in sequences %}
<tr>
Expand All @@ -283,6 +283,12 @@ <h3 class="panel-title"><b>Sequence Information</b></h3>
<td>{{ item.ambiguous_seq_length }}</td>
<td>{{ item.labPerson }}</td>
<td><a href="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Search&db=nucleotide&term={{ item.accession }}[accn]&doptcmdl=GenBank">{{ item.accession }}</a></td>
<td class="text-center">
<a href="/blast_local/{{ voucher.code }}/{{ item.gene_code }}/"><i class="fa fa-bomb"></i></a>
&nbsp;&nbsp;
<i class="fa fa-database"></i>
</td>
<td class="text-center"><i class="fa fa-bomb"></i></td>
</tr>
{% endfor %}
</table>
Expand Down
3 changes: 2 additions & 1 deletion voseq/voseq/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

# my apps
'public_interface',
'blast_local',
)

MIDDLEWARE_CLASSES = (
Expand Down Expand Up @@ -98,7 +99,7 @@

STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
BASE_DIR,
)

# Get your API key from here:
Expand Down
7 changes: 3 additions & 4 deletions voseq/voseq/settings/local.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import json
import os

from unipath import Path
from django.core.exceptions import ImproperlyConfigured

from .base import *
Expand All @@ -10,8 +8,7 @@
DEBUG = True
TEMPLATE_DEBUG = True

BASE_DIR = Path(__file__).absolute().ancestor(3)
SECRETS_FILE = os.path.join(BASE_DIR.ancestor(1), 'config.json')
SECRETS_FILE = os.path.join(BASE_DIR, '..', '..', 'config.json')

with open(SECRETS_FILE) as f:
secrets = json.loads(f.read())
Expand All @@ -38,3 +35,5 @@ def get_secret(setting, secrets=secrets):
'PORT': get_secret('DB_PORT'),
}
}

INSTALLED_APPS += ('debug_toolbar',)
1 change: 1 addition & 0 deletions voseq/voseq/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

urlpatterns = patterns(
'',
url(r'^blast_local', include('blast_local.urls', namespace='blast_local')),
url(r'^', include('public_interface.urls', namespace='public_interace')),
# Examples:
# url(r'^blog/', include('blog.urls')),
Expand Down

0 comments on commit 9b2cfbe

Please sign in to comment.