Skip to content

Commit

Permalink
Merge pull request #229 from carlosp420/overview_table
Browse files Browse the repository at this point in the history
Overview table
  • Loading branch information
carlosp420 committed Jun 18, 2015
2 parents 99f549b + 2901e4d commit 13aa990
Show file tree
Hide file tree
Showing 30 changed files with 904 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ voseq/create_dataset/dataset_files/*txt

# avoid including migrations files
voseq/public_interface/migrations/*
voseq/overview_table/migrations/*
voseq/stats/migrations/*

# avoid including doc files for modules
Expand Down
1 change: 1 addition & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ HISTORY
pre-release v2.0.0-alpha-4 (2015-xx-xx)
+++++++++++++++++++++++++++++++++++++++

- **Interactive overview table** to browse taxa and the genes sequenced for them.
- **Easy instalation** and deployment using Vagrant virtual machines. Install
and configure VoSeq and all its dependencies with the command ``vagrant up``.

Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ test:
rm -rf htmlcov .coverage
coverage run --source voseq voseq/manage.py test -v 2 blast_local blast_local_full blast_ncbi blast_new \
core create_dataset genbank_fasta public_interface stats view_genes genbank_fasta gene_table \
voucher_table gbif \
voucher_table gbif overview_table \
--settings=voseq.settings.testing

travis_test:
Expand All @@ -73,5 +73,5 @@ travis_test:
rm -rf htmlcov .coverage
coverage run --source voseq voseq/manage.py test -v 2 blast_local blast_local_full blast_ncbi blast_new \
core create_dataset genbank_fasta public_interface stats view_genes genbank_fasta gene_table \
voucher_table gbif \
voucher_table gbif overview_table \
--settings=voseq.settings.travis
Empty file.
Empty file.
16 changes: 16 additions & 0 deletions voseq/overview_table/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from django.db import models


class OverviewTable(models.Model):
"""Bulk create does not work on inherited models so we need to create a new
one.
"""
sequence_string = models.TextField(help_text="HTML string of cells with length of"
"sequences for each gene.")
o_code = models.CharField(max_length=300)
orden = models.TextField(blank=True)
superfamily = models.TextField(blank=True)
family = models.TextField(blank=True)
subfamily = models.TextField(blank=True)
genus = models.TextField(blank=True)
species = models.TextField(blank=True)
151 changes: 151 additions & 0 deletions voseq/overview_table/templates/overview_table/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
{% extends 'public_interface/base.html' %}

{% block title %}
VoSeq | Overview table
{% endblock title %}

{% load staticfiles %}
{% block additional_css %}
<link rel="stylesheet" type="text/css" href="{% static 'css/dataTables.bootstrap.css' %}">
{% endblock additional_css %}

{% block content %}
<div class="explorer-container">
<div class="container">
<h3>Interactive overview table:</h3>


<div class="container">
<div class="row">

<div class="col-xs-12 col-sm-12 col-md-11 col-lg-12">


<table class="table table-condensed table-striped small_fonts">
{% for i in genes %}
{% if forloop.counter == 1 %}
<tr>
{% endif %}
<td>
<input type="checkbox" class="toggle-vis" data-column="{{ forloop.counter|add:6 }}">
{{ i.gene_code }}
</input>
</td>

{% if forloop.counter|divisibleby:"4" %}
</tr>
{% endif %}

{% endfor %}
</tr>
</table>

<table id="datatable" class="display table table-striped table-hover" width="100%">
<thead>
<tr>
<th>Code</th>
<th>Order</th>
<th>Superfamily</th>
<th>Family</th>
<th>Subfamily</th>
<th>Genus</th>
<th>Species</th>
{% for i in genes %}
<th class="genes">{{ i.gene_code }}</th>
{% endfor %}
</thead>
<tbody>

{% for item in data %}
<tr>
<td><a href="/p/{{ item.o_code }}/">{{ item.o_code }}</a></td>
<td>{{ item.orden }}</td>
<td>{{ item.superfamily }}</td>
<td>{{ item.family }}</td>
<td>{{ item.subfamily }}</td>
<td>{{ item.genus }}</td>
<td>{{ item.species }}</td>
{{ item.sequence_string|safe }}
</tr>
{% endfor %}

</tbody>
</table>


</div><!-- col -->

</div><!-- row -->

<div class="row"><!-- pagination -->
{% if data.has_previous or data.has_next %}
<nav class="text-center">
<ul class="pagination">
{% if data.has_previous %}
<li>
<a href="?page={{ data.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% endif %}

{% for i in page_range %}
{% if i > data.number|add:"-10" and i < data.number|add:"10" %}
{% if data.number == i %}
<li class="active">
{% else %}
<li>
{% endif %}
<a href="?{{ url_encoded_query }}&amp;page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endfor %}

{% if data.has_next %}
<li>
<a href="?page={{ data.next_page_number }}" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
</div><!-- pagination -->
</div><!-- container -->


</div>
</div>
{% endblock content %}


{% block additional_javascript_footer %}
<script type="text/javascript" charset="utf8" src="{% static 'js/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" charset="utf8" src="{% static 'js/dataTables.bootstrap.min.js' %}"></script>
<script>
$(document).ready( function () {
var table = $('#datatable').DataTable(
{
"paging": false,
"scrollY": 600,
"info": false
}
);

table.columns( '.genes' ).visible(false, false);
table.columns.adjust().draw(false);

$('input.toggle-vis').on('click', function(e) {
e.preventDefault();

// Get the column API object
var column = table.column( $(this).attr('data-column') );

// Toggle the visibility
column.visible( ! column.visible() );
});
});
</script>

{% endblock additional_javascript_footer %}
33 changes: 33 additions & 0 deletions voseq/overview_table/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from django.test import TestCase
from django.core.management import call_command
from django.test import Client

from overview_table.utils import OverviewTableMaker


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

def test_utils(self):
o = OverviewTableMaker()
expected = 3
result = len(o.items)
self.assertEqual(expected, result)


class TestViews(TestCase):
def test_index_view(self):
args = []
opts = {'dumpfile': 'test_db_dump.xml', 'verbosity': 0}
cmd = 'migrate_db'
call_command(cmd, *args, **opts)
call_command('create_stats')

c = Client()
response = c.get('/view_table/')
self.assertEqual(200, response.status_code)
10 changes: 10 additions & 0 deletions voseq/overview_table/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'^/$', views.index, name='index'),
)
47 changes: 47 additions & 0 deletions voseq/overview_table/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from public_interface.models import Genes
from public_interface.models import Sequences
from public_interface.models import Vouchers


class OverviewTableMaker(object):
def __init__(self):
self.genes = Genes.objects.all().order_by('gene_code').values('gene_code')
self.items = self.get_vouchers_with_sequences()

def get_vouchers_with_sequences(self):
unique_vouchers = self.get_unique()
sequences = Sequences.objects.all().values('code', 'gene_code', 'total_number_bp')
sequences = self.convert_to_dict(sequences)

for voucher in unique_vouchers:
code = voucher['code']
voucher['sequence_string'] = self.build_sequence_string(sequences[code])

return unique_vouchers

def get_unique(self):
v = Vouchers.objects.all().filter(sequences__code__isnull=False).values('code', 'orden', 'superfamily', 'family',
'subfamily', 'genus', 'species').distinct()
return v

def convert_to_dict(self, sequences):
new_seqs = {}
for i in sequences:
code = i['code']
if code not in new_seqs:
new_seqs[code] = {}
del i['code']
new_seqs[code][i['gene_code']] = i['total_number_bp']
return new_seqs

def build_sequence_string(self, sequences):
my_string = []
for gene in self.genes:
gene_code = gene['gene_code']
try:
my_string.append(str(sequences[gene_code]))
except KeyError:
my_string.append('')

my_string = '<td>' + '</td><td>'.join(my_string) + '</td>'
return my_string
37 changes: 37 additions & 0 deletions voseq/overview_table/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render

from core.utils import get_version_stats
from core.utils import get_username
from public_interface.models import Genes
from overview_table.models import OverviewTable


def index(request):
version, stats = get_version_stats()
username = get_username(request)

genes = Genes.objects.all().order_by('gene_code')
vouchers = OverviewTable.objects.all()

paginator = Paginator(vouchers, 100)

page = request.GET.get('page')
try:
vouchers_for_page = paginator.page(page)
except PageNotAnInteger:
vouchers_for_page = paginator.page(1)
except EmptyPage:
vouchers_for_page = paginator.page(paginator.num_pages)

return render(request,
'overview_table/index.html',
{
'username': username,
'version': version,
'stats': stats,
'data': vouchers_for_page,
'genes': genes,
'page_range': paginator.page_range,
},
)
7 changes: 3 additions & 4 deletions voseq/public_interface/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ class Vouchers(models.Model):
(LOST, 'lost'),
(UNKNOWN, 'unknown'),
)
code = models.TextField(unique=True, primary_key=True, help_text="Voucher code.")
code = models.CharField(max_length=300, unique=True, primary_key=True, help_text="Voucher code.")
orden = models.TextField(blank=True)
superfamily = models.TextField(blank=True)
family = models.TextField(blank=True)
Expand Down Expand Up @@ -173,7 +173,7 @@ class Sequences(models.Model):
time_edited = models.DateTimeField(auto_now=True, null=True, blank=True)
notes = models.TextField(blank=True)
genbank = models.BooleanField()
# total_number_bp = models.IntegerField(blank=True, null=True)
total_number_bp = models.IntegerField(blank=True, null=True)
number_ambiguous_bp = models.IntegerField(blank=True, null=True)

class Meta:
Expand All @@ -183,8 +183,7 @@ def save(self, *args, **kwargs):
ambiguous_seq_length = self.sequences.count('?') + self.sequences.count('-')
ambiguous_seq_length += self.sequences.count('N') + self.sequences.count('n')
self.number_ambiguous_bp = ambiguous_seq_length
# TODO save length of sequence string as *total_number_bp*
# self.total_number_bp = len(self.sequences)
self.total_number_bp = len(str(self.sequences))
super(Sequences, self).save(*args, **kwargs)

def __str__(self):
Expand Down

0 comments on commit 13aa990

Please sign in to comment.