diff --git a/docker-compose.yml b/docker-compose.yml index 756d6fe..9cda14d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -40,4 +40,4 @@ networks: front-tier: driver: bridge back-tier: - driver: bridge + driver: bridge \ No newline at end of file diff --git a/pgd/settings.py b/pgd/settings.py index 95fc97d..7108b18 100644 --- a/pgd/settings.py +++ b/pgd/settings.py @@ -4,9 +4,10 @@ import os PROJECT_ROOT = os.path.dirname(os.path.abspath(os.path.dirname(__file__))) -DEBUG = config('DEBUG', default=False, cast=bool) +DEBUG = True TEMPLATE_DEBUG = DEBUG + ADMINS = ( # ('Your Name', 'your_email@domain.com'), ) @@ -122,6 +123,7 @@ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', + 'django_pdb.middleware.PdbMiddleware', ) ROOT_URLCONF = config('ROOT_URLCONF', default='pgd.urls') @@ -130,11 +132,12 @@ WSGI_APPLICATION = 'pgd.wsgi.application' TEMPLATE_DIRS = ( - '%s/templates' % DOC_ROOT + '%s/templates' % DOC_ROOT, ) INSTALLED_APPS = ( 'django.contrib.auth', + 'django_pdb', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', @@ -175,6 +178,7 @@ } } +DJANGO_SETTINGS_MODULE = 'pgd.settings' # PGD Specific settings QUERY_LIMIT = config('QUERY_LIMIT', default=50000000, cast=int) SEGMENT_SIZE = config('SEGMENT_SIZE', default=10, cast=int) diff --git a/pgd/urls.py b/pgd/urls.py index 49f4789..f00229e 100755 --- a/pgd/urls.py +++ b/pgd/urls.py @@ -5,6 +5,8 @@ from django.core.urlresolvers import reverse_lazy from views import ReferencesView, ContactUsView, NewsView, WelcomeView admin.autodiscover() +import pgd_search.urls +import pgd_core.urls #from pgd import VERSION #from pgd_splicer.models import pdb_select_settings @@ -20,9 +22,9 @@ # Uncomment the next line to enable the admin: #(r'^admin/', include(admin.site.urls)), - url(r'^search/', include('pgd_search.urls'), name='pgd_search'), + url(r'^search/', include(pgd_search.urls), name='pgd_search'), - url(r'^accounts/', include('pgd_core.urls')), + url(r'^accounts/', include(pgd_core.urls)), # Static pages: (r'^references/$', ReferencesView.as_view()), diff --git a/pgd/wsgi.py b/pgd/wsgi.py index 1e4ba31..25bef95 100644 --- a/pgd/wsgi.py +++ b/pgd/wsgi.py @@ -14,9 +14,12 @@ """ import os +import sys +from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pgd.settings") +#os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pgd.settings") +os.environ['DJANGO_SETTINGS_MODULE'] = 'pgd.settings' # This application object is used by any WSGI server configured to use this # file. This includes Django's development server, if the WSGI_APPLICATION # setting points here. diff --git a/pgd_search/plot/ConfDistFuncs.py b/pgd_search/plot/ConfDistFuncs.py index b040ea5..557bf7f 100644 --- a/pgd_search/plot/ConfDistFuncs.py +++ b/pgd_search/plot/ConfDistFuncs.py @@ -9,15 +9,16 @@ from django.db import connections from django.db.backends.mysql.compiler import SQLCompiler -from django.db.models import Count, Avg, StdDev +from django.db.models import Count, Avg, StdDev, FloatField from pgd_constants import * from pgd_core.models import * from pgd_search.models import * -from pgd_search.statistics.aggregates import DirectionalAvg, DirectionalStdDev, BinSort +from pgd_search.statistics.aggregates import DirectionalAvg, DirectionalStdDev, BinSort, PGDAggregate, BinSortSQL from pgd_splicer.sidechain import sidechain_length_relationship_list, sidechain_angle_relationship_list from svg import * +import sys ANGLES = ('ome', 'phi', 'psi', 'chi1','chi2','chi3','chi4','chi5','zeta') NON_FIELDS = ('Observations', 'all') @@ -311,7 +312,7 @@ def query_bins(self): annotations[avg] = Avg(field[1]) annotations[stddev] = StdDev(field[1]) annotated_query = querySet.annotate(**annotations) - + # sort and group by bins using an aggregate function that calculates # bin index based on bin size (in field units ie. degrees) and bin count. # @@ -324,14 +325,24 @@ def query_bins(self): # XXX in Django 1.2+ aggregates were changed to require connection and # SQLCompiler objects to generate sql. We must initialize this all # manually to be able to grab the SQL for just our aggregate. + sortx = BinSort(self.xTextString, offset=x, bincount=xbin, max=x1) sorty = BinSort(self.yTextString, offset=y, bincount=ybin, max=y1) + annotated_query.annotate(x=sortx, y=sorty) cn = connections['default'] qn = SQLCompiler(annotated_query.query, cn, 'default').quote_name_unless_alias - sortx_sql = sortx.aggregate.as_sql(qn, cn)[0] - sorty_sql = sorty.aggregate.as_sql(qn, cn)[0] + + #Hack : Using the BinSortSQL class directly instead of BinSort + #this overrides l:329 and l:330 + sortx = BinSortSQL(('pgd_core_residue', 'psi'), offset=x, bincount=xbin, max=x1) + sorty = BinSortSQL(('pgd_core_residue', 'phi'), offset=y, bincount=ybin, max=y1) + + sortx_sql = sortx.as_sql(qn, cn)[0] + sorty_sql = sorty.as_sql(qn, cn)[0] + + annotated_query = annotated_query.extra(select={'x':sortx_sql, 'y':sorty_sql}) annotated_query = annotated_query.order_by('x','y') diff --git a/pgd_search/plot/PlotForm.py b/pgd_search/plot/PlotForm.py index aa66e35..2fc5df2 100644 --- a/pgd_search/plot/PlotForm.py +++ b/pgd_search/plot/PlotForm.py @@ -3,7 +3,7 @@ from pgd_search.views import RESIDUE_INDEXES #choice for occurence of property -ATTRIBUTE_CHOICES = [ +ATTRIBUTE_CHOICES = ( ("Observations",'Observations'), ("L1",u'C-1N'), ("L2",u'NCα'), @@ -28,10 +28,10 @@ ("psi",u'ψ'), ('zeta',u'ζ'), #('h_bond_energy','H Bond'), - ] + ) # choices for properties mapped to axis -PROPERTY_CHOICES = [ +PROPERTY_CHOICES = ( ("L1",u'C-1N'), ("L2",u'NCα'), ("L3",u'CαCβ'), @@ -55,7 +55,7 @@ ("psi",u'ψ'), ('zeta',u'ζ'), #('h_bond_energy','H Bond'), - ] + ) PROPERTY_CHOICES_DICT = {} @@ -63,42 +63,42 @@ PROPERTY_CHOICES_DICT[prop] = label -BACKGROUND_CHOICES = [ +BACKGROUND_CHOICES = ( ('#ffffff','White'), ('#000000','Black'), ('#666666','Gray'), ('#222222','Dark Gray'), (None,'Transparent'), -] +) -GRAPH_CHOICES = [ +GRAPH_CHOICES = ( ('#222222','Dark Gray'), ('#666666','Gray'), ('#000000','Black'), ('#ffffff','White'), (None,'Transparent'), -] +) -TEXT_CHOICES = [ +TEXT_CHOICES = ( ('#000000','Black'), ('#ffffff','White'), ('#666666','Gray'), ('#222222','Dark Gray'), -] +) -HUE_CHOICES = [ +HUE_CHOICES = ( ('green','Green'), ('blue','Blue'), ('red','Red'), ('black','Black/White'), -] +) -HASH_CHOICES = [ +HASH_CHOICES = ( ('#666666','Gray'), ('#222222','Dark Gray'), ('#000000','Black'), ('#ffffff','White'), -] +) """ @@ -147,11 +147,11 @@ class PlotForm(forms.Form): widget=forms.TextInput(attrs={'size':4})) #custom plot properties - background_color= forms.ChoiceField(choices=BACKGROUND_CHOICES) - graph_color = forms.ChoiceField(choices=GRAPH_CHOICES) - text_color = forms.ChoiceField(choices=TEXT_CHOICES) + background_color= forms.ChoiceField(required=False, choices=BACKGROUND_CHOICES) + graph_color = forms.ChoiceField(required=False, choices=GRAPH_CHOICES) + text_color = forms.ChoiceField(required=False, choices=TEXT_CHOICES) plot_hue = forms.ChoiceField(choices=HUE_CHOICES) - hash_color = forms.ChoiceField(choices=HASH_CHOICES) + hash_color = forms.ChoiceField(required=False, choices=HASH_CHOICES) height = forms.IntegerField(initial=470, widget=forms.TextInput(attrs={'size':4})) width = forms.IntegerField(initial=560, @@ -165,4 +165,10 @@ def clean(self): data['attribute'] = data['attribute'].replace('-','_') except KeyError: pass + if not data['graph_color'] : + data['graph_color'] = '#222222' + if not data['hash_color'] : + data['hash_color'] = '#666666' + if not data['text_color'] : + data['text_color'] = '#000000' return data diff --git a/pgd_search/plot/views.py b/pgd_search/plot/views.py index 2c1d612..afffc33 100644 --- a/pgd_search/plot/views.py +++ b/pgd_search/plot/views.py @@ -6,13 +6,13 @@ from django.conf import settings from django.shortcuts import render_to_response import json - from PlotForm import PlotForm, ATTRIBUTE_CHOICES, PROPERTY_CHOICES from ConfDistFuncs import * from pgd_constants import AA_CHOICES from pgd_search.views import settings_processor from pgd_splicer.sidechain import sidechain_string_dict + AA_CHOICES = [aa[1].upper() for aa in filter(lambda x: x[1].upper() in sidechain_string_dict, AA_CHOICES)] def drawGraph(request, height=470, width=560, xStart=None, yStart=None, xEnd=None, yEnd=None, attribute='Observations', xProperty='phi', yProperty='psi', reference=None, sigmaVal=3, residue_attribute=None, residue_xproperty=None, residue_yproperty=None, xBin=None, yBin=None, background_color='#ffffff',graph_color='#222222',text_color='#000000', hue='green', hash_color='666666'): @@ -74,15 +74,12 @@ def drawGraph(request, height=470, width=560, xStart=None, yStart=None, xEnd=Non text_color, hash_color ) - svg = cdp.Plot() except Exception, e: - print 'exception', e import traceback, sys exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() print "*** print_tb:" traceback.print_tb(exceptionTraceback, limit=10, file=sys.stdout) - raise e return (svg, xStart, xEnd, xBin, yStart, yEnd, yBin) diff --git a/pgd_search/search/views.py b/pgd_search/search/views.py index 5b3005e..9fa88f9 100644 --- a/pgd_search/search/views.py +++ b/pgd_search/search/views.py @@ -1,12 +1,11 @@ import math import re import pickle - from django.http import HttpResponse, HttpResponseRedirect from django.template import RequestContext from django.shortcuts import render_to_response, redirect from django.conf import settings -from django.forms.util import ErrorList +from django.forms.utils import ErrorList from django.core.paginator import Paginator, InvalidPage, EmptyPage import json from datetime import datetime @@ -24,7 +23,6 @@ json_sidechain_angles_lookup = json.dumps(bond_angles_string_dict) - def search(request): """ Handler for search form. @@ -43,10 +41,10 @@ def search(request): #at least for now limit the size of the result set count = search_object.querySet().count() if count > settings.QUERY_LIMIT: - form._errors['Result Size'] = ErrorList(['Your query returned more than 20,000 records, refine your search']) + form.error['Result Size'] = ErrorList(['Your query returned more than 20,000 records, refine your search']) elif count == 0 and False: - form._errors['Result Size'] = ErrorList(['Your query returned no results']) + form.error['Result Size'] = ErrorList(['Your query returned no results']) else: #store search in session diff --git a/pgd_search/statistics/aggregates.py b/pgd_search/statistics/aggregates.py index 2a0b40b..ac31b1a 100644 --- a/pgd_search/statistics/aggregates.py +++ b/pgd_search/statistics/aggregates.py @@ -6,6 +6,7 @@ class PGDAggregate(Aggregate): Modified to allow Aggregate functions outside of the Django module """ + def add_to_query(self, query, alias, col, source, is_summary): """Add the aggregate to the nominated query. @@ -24,13 +25,15 @@ def add_to_query(self, query, alias, col, source, is_summary): * is_summary is a boolean that is set True if the aggregate is a summary value rather than an annotation. """ + self.queryObj = query klass = globals()['%sSQL' % self.name] aggregate = klass(col, source=source, is_summary=is_summary, **self.extra) - + # Validate that the backend has a fully supported, correct # implementation of this aggregate + self.aggr = aggregate query.aggregates[alias] = aggregate - self.aggregate = aggregate + class DirectionalStdDev(PGDAggregate): @@ -63,3 +66,4 @@ class BinSort(PGDAggregate): class BinSortSQL(SQLAggregate): sql_function = '' sql_template = '%(function)sFLOOR((IF(%(field)s<%(offset).16f,360,0)+%(field)s-%(offset).16f)/%(bincount).16f)-IF(%(field)s=%(max).16f,1,0)' + \ No newline at end of file diff --git a/pgd_splicer/ProcessPDBTask.py b/pgd_splicer/ProcessPDBTask.py index 5191e9d..a9c8bfc 100755 --- a/pgd_splicer/ProcessPDBTask.py +++ b/pgd_splicer/ProcessPDBTask.py @@ -32,6 +32,7 @@ from Bio.PDB import calc_angle as pdb_calc_angle from Bio.PDB import calc_dihedral as pdb_calc_dihedral from django.db import transaction +import django from tools import localfile @@ -47,6 +48,7 @@ from pgd_splicer.chi import CHI_MAP, CHI_CORRECTIONS_TESTS, CHI_CORRECTIONS from pgd_splicer.sidechain import bond_angles, bond_lengths +django.setup() def NO_VALUE(field): """ @@ -215,7 +217,7 @@ def process_pdb(pdb): """ Process an individual pdb file """ - + transaction.set_autocommit(False) # create a copy of the data. This dict will have a large amount of data # added to it as the protein is processed. This prevents memory leaks # due to the original dict having a reference held outside this method. @@ -249,8 +251,10 @@ def process_pdb(pdb): protein.rfactor = float(data['rfactor']) protein.rfree = float(data['rfree']) protein.pdb_date = data['pdb_date'] - protein.save() + with transaction.atomic(): + protein.save() + transaction.commit() # 3) Get/Create Chains and save values chains = {} for chaincode, residues in data['chains'].items(): @@ -264,9 +268,10 @@ def process_pdb(pdb): chain.id = chainId chain.protein = protein chain.code = chaincode - chain.save() + with transaction.atomic(): + chain.save() - protein.chains.add(chain) + protein.chains.add(chain) #create dictionary of chains for quick access chains[chaincode] = chain @@ -305,17 +310,20 @@ def process_pdb(pdb): except: sidechain = klass() sidechain.__dict__.update(residue_props['sidechain']) - sidechain.save() + with transaction.atomic(): + sidechain.save() residue.__setattr__(name, sidechain) # 4e) save - residue.save() - chain.residues.add(residue) + with transaction.atomic(): + residue.save() + chain.residues.add(residue) # 4f) Update old_residue.next if "prev" in residue_props: old_residue.next = residue - old_residue.save() + with transaction.atomic(): + old_residue.save() old_residue = residue diff --git a/requirements.txt b/requirements.txt index 325a360..3935d30 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ biopython -django-registration-redux==1.1 -django==1.6 +django-registration-redux +django==1.8 +django-pdb selenium mysql-python numpy