diff --git a/ippisite/ippidb/admin.py b/ippisite/ippidb/admin.py index 3b32cd020b9245306579d28bf9379a49357f6f86..bfa448254966b23ddfe8b14c7ad97bdcfe6b53b4 100644 --- a/ippisite/ippidb/admin.py +++ b/ippisite/ippidb/admin.py @@ -2,44 +2,56 @@ from django.contrib import admin from .models import * from django.apps import apps + @admin.register(Bibliography) class BibliographyAdmin(admin.ModelAdmin): - list_display = ('authors_list', 'title', 'journal_name', 'biblio_year', 'id_source') + list_display = ('authors_list', 'title', + 'journal_name', 'biblio_year', 'id_source') + @admin.register(Protein) class ProteinAdmin(admin.ModelAdmin): list_display = ('uniprot_id', 'recommended_name_long') + @admin.register(Taxonomy) class TaxonomyAdmin(admin.ModelAdmin): list_display = ('taxonomy_id', 'name') + @admin.register(Domain) class DomainAdmin(admin.ModelAdmin): list_display = ('pfam_acc', 'pfam_id', 'pfam_description', 'domain_family') + @admin.register(ProteinDomainBoundComplex) class ProteinDomainBoundComplexAdmin(admin.ModelAdmin): list_display = ('protein', 'domain', 'ppc_copy_nb', 'ppp_copy_nb_per_p') - list_display_links = ('protein', 'domain', 'ppc_copy_nb', 'ppp_copy_nb_per_p') + list_display_links = ( + 'protein', 'domain', 'ppc_copy_nb', 'ppp_copy_nb_per_p') + @admin.register(ProteinDomainPartnerComplex) class ProteinDomainPartnerComplexAdmin(admin.ModelAdmin): list_display = ('protein', 'domain', 'ppc_copy_nb') list_display_links = ('protein', 'domain', 'ppc_copy_nb') + @admin.register(Symmetry) class Symmetry(admin.ModelAdmin): list_display = ('code', 'description') + @admin.register(MDDRCompoundImport) class MDDRCompoundImport(admin.ModelAdmin): list_display = ('mddr_name', 'dvpmt_phase', 'canonical_smile') + @admin.register(Compound) class Compound(admin.ModelAdmin): list_display = ('iupac_name', 'common_name', 'canonical_smile') + @admin.register(TestActivityDescription) class TextActivityDescription(admin.ModelAdmin): list_display = ('test_name', 'test_type', 'test_modulation_type') @@ -57,5 +69,3 @@ admin.site.site_title = admin.site.site_header admin.site.index_header = 'iPPI-DB administration' admin.site.index_title = admin.site.index_header - - diff --git a/ippisite/ippidb/forms.py b/ippisite/ippidb/forms.py index 35e35581ff2815478e57e133ee20f36a18b6b60b..168c54a42c30ce9551c0090b11614469f6f929bd 100644 --- a/ippisite/ippidb/forms.py +++ b/ippisite/ippidb/forms.py @@ -1,4 +1,4 @@ -from django.forms import ModelForm,modelformset_factory,formset_factory +from django.forms import ModelForm, modelformset_factory, formset_factory from django import forms from django.db import models from django.core.exceptions import ValidationError @@ -7,84 +7,102 @@ from django.core.validators import RegexValidator from .models import Bibliography, Protein, ProteinDomainComplex, Ppi, PpiComplex from .ws import pdb_entry_exists + class IdForm(ModelForm): + class Meta: model = Bibliography - fields = ['source','id_source'] + fields = ['source', 'id_source'] widgets = { - 'source' : forms.RadioSelect, + 'source': forms.RadioSelect, 'id_source': forms.TextInput(attrs={'placeholder': 'ID'}), } + class BibliographyForm(ModelForm): + class Meta: model = Bibliography exclude = ['authors_list', 'biblio_year'] widgets = { - 'source': forms.TextInput(attrs={'readonly':'readonly','class':'readonly'}), - 'id_source': forms.TextInput(attrs={'readonly':'readonly', 'class':'readonly'}), - 'title': forms.TextInput(attrs={'readonly':'readonly', 'class':'readonly'}), - 'journal_name': forms.TextInput(attrs={'readonly':'readonly', 'class':'readonly'}), + 'source': forms.TextInput(attrs={'readonly': 'readonly', 'class': 'readonly'}), + 'id_source': forms.TextInput(attrs={'readonly': 'readonly', 'class': 'readonly'}), + 'title': forms.TextInput(attrs={'readonly': 'readonly', 'class': 'readonly'}), + 'journal_name': forms.TextInput(attrs={'readonly': 'readonly', 'class': 'readonly'}), } + def validate_pdb_exists(value): if not(pdb_entry_exists(value)): - raise ValidationError('PDB entry not found: %(value)s', params={'value': value}, code='invalid') + raise ValidationError( + 'PDB entry not found: %(value)s', params={'value': value}, code='invalid') + class PDBForm(forms.Form): - pdb_id = forms.CharField(label="PDB ID",max_length=4, widget=forms.TextInput(attrs={'placeholder': 'e.g 4HHB', 'required':'required'}), required=True, validators=[ - RegexValidator('^[0-9][a-zA-Z0-9]{3}$', message='PDB ID must be 1 numeric + 3 alphanumeric characters'), + pdb_id = forms.CharField(label="PDB ID", max_length=4, widget=forms.TextInput(attrs={'placeholder': 'e.g 4HHB', 'required': 'required'}), required=True, validators=[ + RegexValidator( + '^[0-9][a-zA-Z0-9]{3}$', message='PDB ID must be 1 numeric + 3 alphanumeric characters'), validate_pdb_exists - ]) + ]) PDBFormSet = formset_factory(PDBForm) -formset=PDBFormSet() +formset = PDBFormSet() + class ProteinForm(ModelForm): - class Meta: - model = Protein - exclude = ['recommended_name_long', 'short_name'] - widgets = { - 'uniprot_id' : forms.TextInput(attrs={'readonly':'readonly','class':'readonly'}), - 'gene_name' : forms.TextInput(attrs={'readonly':'readonly','class':'readonly'}), - 'entry_name' : forms.TextInput(attrs={'readonly':'readonly','class':'readonly'}), - 'organism': forms.TextInput(attrs={'readonly':'readonly','class':'readonly'}), + + class Meta: + model = Protein + exclude = ['recommended_name_long', 'short_name'] + widgets = { + 'uniprot_id': forms.TextInput(attrs={'readonly': 'readonly', 'class': 'readonly'}), + 'gene_name': forms.TextInput(attrs={'readonly': 'readonly', 'class': 'readonly'}), + 'entry_name': forms.TextInput(attrs={'readonly': 'readonly', 'class': 'readonly'}), + 'organism': forms.TextInput(attrs={'readonly': 'readonly', 'class': 'readonly'}), } -ProteinFormSet = modelformset_factory(Protein, exclude=('recommended_name_long', 'short_name'), extra=0) +ProteinFormSet = modelformset_factory( + Protein, exclude=('recommended_name_long', 'short_name'), extra=0) TYPE_CHOICES = ( - ('Hetero2merAB','Inhib_Hetero 2-mer AB'), - ('Homo2merA2','Inhib_Homo 2-mer A2'), - ('custom', 'Inhib_Custom your own'), - ('Hetero2merAB','Stab_Hetero 2-mer AB'), - ('Homo2merA2','Stab_Homo 2-mer A2'), - ('HomoLike2mer','Stab_Homo-Like 2-mer A2'), - ('Homo3merA3','Stab_Homo 3-mer A3'), - ('Homo3merA2','Stab_Homo 3-mer A3 inhibited A2-dimer'), - ('Homo4merA4','Stab_Homo 4-mer A4'), - ('RingHomo3mer','Stab_Ring-Like 3-mer A3'), - ('RingHomo5mer','Stab_Ring-Like 5-mer A5'), - ('custom', 'Stab_Custom your own'), - ) + ('Hetero2merAB', 'Inhib_Hetero 2-mer AB'), + ('Homo2merA2', 'Inhib_Homo 2-mer A2'), + ('custom', 'Inhib_Custom your own'), + ('Hetero2merAB', 'Stab_Hetero 2-mer AB'), + ('Homo2merA2', 'Stab_Homo 2-mer A2'), + ('HomoLike2mer', 'Stab_Homo-Like 2-mer A2'), + ('Homo3merA3', 'Stab_Homo 3-mer A3'), + ('Homo3merA2', 'Stab_Homo 3-mer A3 inhibited A2-dimer'), + ('Homo4merA4', 'Stab_Homo 4-mer A4'), + ('RingHomo3mer', 'Stab_Ring-Like 3-mer A3'), + ('RingHomo5mer', 'Stab_Ring-Like 5-mer A5'), + ('custom', 'Stab_Custom your own'), +) + class ProteinDomainComplexTypeForm(forms.Form): complexType = forms.ChoiceField( widget=forms.RadioSelect, choices=TYPE_CHOICES, - ) + ) + class ProteinDomainComplexForm(ModelForm): - class Meta: - model = ProteinDomainComplex - fields = ['protein', 'domain', 'ppc_copy_nb'] + + class Meta: + model = ProteinDomainComplex + fields = ['protein', 'domain', 'ppc_copy_nb'] + class PpiForm(ModelForm): - class Meta: - model = Ppi - fields = ['pdb_id', 'symmetry'] + + class Meta: + model = Ppi + fields = ['pdb_id', 'symmetry'] + class PpiComplexForm(ModelForm): - class Meta: - model = PpiComplex - fields = ['complex', 'cc_nb'] + + class Meta: + model = PpiComplex + fields = ['complex', 'cc_nb'] diff --git a/ippisite/ippidb/gx.py b/ippisite/ippidb/gx.py index 999004b40da1e46bc72936289d7868cab616e6d9..e74a84da2adaba230ab1e07674cf13ea346ccda5 100644 --- a/ippisite/ippidb/gx.py +++ b/ippisite/ippidb/gx.py @@ -2,14 +2,17 @@ from bioblend.galaxy import GalaxyInstance from bioblend.galaxy.tools.inputs import inputs workflow_id = 'dad6103ff71ca4fe' -galaxy_url = 'https://galaxy-dev.web.pasteur.fr' +galaxy_url = 'https://galaxy-dev.web.pasteur.fr' api_key = '21c2ce387688b1a785040762f7c9c331' + def run_workflow_and_get_results(input_file): gi = GalaxyInstance(galaxy_url, key=api_key) gi.verify = False history_id = gi.histories.create_history("ippidb_history")['id'] - dataset_id = gi.tools.upload_file(input_file, history_id)['outputs'][0]['id'] - inputs = {'0':{'id':dataset_id, 'src': 'hda' }} - workflow_run = gi.workflows.invoke_workflow(workflow_id, inputs=inputs, history_id=history_id) - print(workflow_run) + dataset_id = gi.tools.upload_file( + input_file, history_id)['outputs'][0]['id'] + inputs = {'0': {'id': dataset_id, 'src': 'hda'}} + workflow_run = gi.workflows.invoke_workflow( + workflow_id, inputs=inputs, history_id=history_id) + print(workflow_run) diff --git a/ippisite/ippidb/management/commands/import_v1_data.py b/ippisite/ippidb/management/commands/import_v1_data.py index 41c0a5b771eb30f32cd79eef46de39a74b9e26d6..533a9d6dd8140c86081619cbd63de8571b93b3c8 100644 --- a/ippisite/ippidb/management/commands/import_v1_data.py +++ b/ippisite/ippidb/management/commands/import_v1_data.py @@ -9,6 +9,7 @@ from ippidb.models import Bibliography, Protein, Taxonomy, MolecularFunction, \ Domain, ProteinDomainBoundComplex, ProteinDomainPartnerComplex, Symmetry, Ppi, PpiComplex, Disease, \ Compound, MDDRCompoundImport, MDDRActivityClass, TestActivityDescription, CellLine + class MyConverter(mysql.connector.conversion.MySQLConverter): def row_to_python(self, row, fields): @@ -21,6 +22,7 @@ class MyConverter(mysql.connector.conversion.MySQLConverter): return[to_unicode(col) for col in row] + class Command(BaseCommand): help = "Import data from the local v1 database" @@ -90,37 +92,43 @@ class Command(BaseCommand): help='Stop on fail', ) - def handle(self, *args, **options): - conn = mysql.connector.connect(converter_class=MyConverter, host="localhost", user="root", password="ippidb", database="ippidb") + conn = mysql.connector.connect( + converter_class=MyConverter, host="localhost", user="root", password="ippidb", database="ippidb") cursor = conn.cursor() if options['bibliographies']: cursor.execute("""SELECT * FROM biblio""") rows = cursor.fetchall() Bibliography.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed bibliography table')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed bibliography table')) for row in rows: try: b = Bibliography() - if row[1]=='article': + if row[1] == 'article': b.source = 'PM' else: b.source = 'PT' b.id_source = row[2] b.save(autofill=True) except Exception as e: - self.stdout.write(self.style.ERROR('Failed inserting {}'.format(row[2]))) + self.stdout.write( + self.style.ERROR('Failed inserting {}'.format(row[2]))) else: - self.stdout.write(self.style.SUCCESS('Successfully inserted {}'.format(row[2]))) + self.stdout.write( + self.style.SUCCESS('Successfully inserted {}'.format(row[2]))) if options['proteins']: cursor.execute("""SELECT * FROM protein""") rows = cursor.fetchall() Protein.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed protein table')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed protein table')) Taxonomy.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed taxonomy table')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed taxonomy table')) MolecularFunction.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed molecular function table')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed molecular function table')) for row in rows: try: p = Protein() @@ -130,16 +138,20 @@ class Command(BaseCommand): if options['stoponfail']: import traceback self.stderr.write(traceback.format_exc()) - raise CommandError('Failed inserting {} {}'.format(row[1], row[2])) + raise CommandError( + 'Failed inserting {} {}'.format(row[1], row[2])) else: - self.stdout.write(self.style.ERROR('Failed inserting {} {}'.format(row[1], row[2]))) + self.stdout.write( + self.style.ERROR('Failed inserting {} {}'.format(row[1], row[2]))) else: - self.stdout.write(self.style.SUCCESS('Successfully inserted {} {}'.format(row[1], row[2]))) + self.stdout.write( + self.style.SUCCESS('Successfully inserted {} {}'.format(row[1], row[2]))) if options['domains']: cursor.execute("""SELECT * FROM domain""") rows = cursor.fetchall() Domain.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed domain table')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed domain table')) for row in rows: try: p = Domain() @@ -150,16 +162,20 @@ class Command(BaseCommand): if options['stoponfail']: import traceback self.stderr.write(traceback.format_exc()) - raise CommandError('Failed inserting {} {}'.format(row[1], row[2])) + raise CommandError( + 'Failed inserting {} {}'.format(row[1], row[2])) else: - self.stdout.write(self.style.ERROR('Failed inserting {} {}'.format(row[1], row[2]))) + self.stdout.write( + self.style.ERROR('Failed inserting {} {}'.format(row[1], row[2]))) else: - self.stdout.write(self.style.SUCCESS('Successfully inserted {} {}'.format(row[1], row[2]))) + self.stdout.write( + self.style.SUCCESS('Successfully inserted {} {}'.format(row[1], row[2]))) if options['symmetries']: Symmetry.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed symmetries table')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed symmetries table')) rows = [ - ['AS', 'asymmetric'], + ['AS', 'asymmetric'], ['C2', 'C2 symmetry'], ['D2', 'D2 symmetry'], ['C3', 'C3 symmetry'], @@ -179,15 +195,18 @@ class Command(BaseCommand): if options['stoponfail']: import traceback self.stderr.write(traceback.format_exc()) - raise CommandError('Failed inserting {} {}'.format(row[0], row[1])) + raise CommandError( + 'Failed inserting {} {}'.format(row[0], row[1])) else: - self.stdout.write(self.style.ERROR('Failed inserting {} {}'.format(row[0], row[1]))) + self.stdout.write( + self.style.ERROR('Failed inserting {} {}'.format(row[0], row[1]))) else: - self.stdout.write(self.style.SUCCESS('Successfully inserted {} {}'.format(row[0], row[1]))) + self.stdout.write( + self.style.SUCCESS('Successfully inserted {} {}'.format(row[0], row[1]))) if options['ppi']: sql_request_string = ''' select distinct protein.NumUniprot, domain.PfamNumAccession, complexe.NbCopy, cmpdAction.IDComplexeBound, bindingSiteEvidence.CodePDB, 'part1', ppi.IDPPI, disease.Disease from bindingSite inner join ppi on (bindingSite.IDBindingSite=ppi.IDBindingSite1) inner join complexe on (ppi.IDComplexe1=complexe.IDComplexe) left outer join cmpdAction on (complexe.IDComplexe=cmpdAction.IDComplexeBound) inner join protein on (bindingSite.IDProtein=protein.IDProtein) inner join domain on (bindingSite.IDDomain=domain.IDDomain) inner join disease on (disease.IDPPI=ppi.IDPPI) left outer join bindingSiteEvidence on (ppi.IDPPI=bindingSiteEvidence.IDPPI) -union +union select distinct protein.NumUniprot, domain.PfamNumAccession , complexe.NbCopy, cmpdAction.IDComplexeBound, null, 'part2', ppi.IDPPI, disease.Disease from bindingSite inner join ppi on (bindingSite.IDBindingSite=ppi.IDBindingSite2) inner join complexe on (ppi.IDComplexe2=complexe.IDComplexe) left outer join cmpdAction on (complexe.IDComplexe=cmpdAction.IDComplexeBound) inner join protein on (bindingSite.IDProtein=protein.IDProtein) inner join domain on (bindingSite.IDDomain=domain.IDDomain) inner join disease on (disease.IDPPI=ppi.IDPPI)''' cursor.execute(sql_request_string) rows = cursor.fetchall() @@ -196,21 +215,23 @@ select distinct protein.NumUniprot, domain.PfamNumAccession , complexe.NbCopy, Disease.objects.all().delete() Ppi.objects.all().delete() PpiComplex.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed protein domain complex, PPI, and disease tables')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed protein domain complex, PPI, and disease tables')) ppi_ids_mapping = {} for row in rows: try: # create or retrieve Ppi object - if row[5]=='part1': + if row[5] == 'part1': ppi = Ppi() - disease, created = Disease.objects.get_or_create(name=row[7]) + disease, created = Disease.objects.get_or_create( + name=row[7]) ppi.pdb_id = row[4] ppi.pockets_nb = 1 ppi.symmetry = Symmetry.objects.get(code='AS') ppi.save() ppi.diseases.add(disease) ppi.save() - ppi_ids_mapping[row[6]]=ppi.id + ppi_ids_mapping[row[6]] = ppi.id else: ppi = Ppi.objects.get(id=ppi_ids_mapping[row[6]]) # create a complex @@ -236,20 +257,25 @@ select distinct protein.NumUniprot, domain.PfamNumAccession , complexe.NbCopy, if options['stoponfail']: import traceback self.stderr.write(traceback.format_exc()) - raise CommandError('Failed inserting {} {}'.format(row[0], row[1])) + raise CommandError( + 'Failed inserting {} {}'.format(row[0], row[1])) else: - self.stdout.write(self.style.ERROR('Failed inserting {} {}'.format(row[0], row[1]))) + self.stdout.write( + self.style.ERROR('Failed inserting {} {}'.format(row[0], row[1]))) else: - self.stdout.write(self.style.SUCCESS('Successfully inserted {} {}'.format(row[0], row[1]))) + self.stdout.write( + self.style.SUCCESS('Successfully inserted {} {}'.format(row[0], row[1]))) cursor.execute("""SELECT * FROM testActivityDescription""") rows = cursor.fetchall() TestActivityDescription.objects.all().delete() CellLine.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed test activity descriptions table and cell lines table')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed test activity descriptions table and cell lines table')) for row in rows: try: tad = TestActivityDescription() - cursor.execute("""select IDSource from biblio where IDBiblio={}""".format(row[2])) + cursor.execute( + """select IDSource from biblio where IDBiblio={}""".format(row[2])) biblio_row = cursor.fetchone() biblio = Bibliography.objects.get(id_source=biblio_row[0]) tad.biblio = biblio @@ -259,21 +285,26 @@ select distinct protein.NumUniprot, domain.PfamNumAccession , complexe.NbCopy, tad.test_modulation_type = row[8][0] tad.nb_active_compounds = row[9] if row[16] is not None: - tad.cell_line, created = CellLine.objects.get_or_create(name=row[16]) + tad.cell_line, created = CellLine.objects.get_or_create( + name=row[16]) tad.save() except Exception as e: if options['stoponfail']: import traceback self.stderr.write(traceback.format_exc()) - raise CommandError('Failed inserting {} {}'.format(row[1], row[2])) + raise CommandError( + 'Failed inserting {} {}'.format(row[1], row[2])) else: - self.stdout.write(self.style.ERROR('Failed inserting {} {}'.format(row[1], row[2]))) + self.stdout.write( + self.style.ERROR('Failed inserting {} {}'.format(row[1], row[2]))) else: - self.stdout.write(self.style.SUCCESS('Successfully inserted {}'.format(row[2]))) + self.stdout.write( + self.style.SUCCESS('Successfully inserted {}'.format(row[2]))) if options['mddr']: MDDRCompoundImport.objects.all().delete() MDDRActivityClass.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed MDDR Compound and Activity class tables')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed MDDR Compound and Activity class tables')) for sdf_file in glob.glob('/home/hmenager/iPPIDB/mddr20151_2d.sdf/*.sdf'): for item in readfile("sdf", sdf_file): try: @@ -284,86 +315,97 @@ select distinct protein.NumUniprot, domain.PfamNumAccession , complexe.NbCopy, m.db_import_date = timezone.now() m.save() for activity_class_name in item.data['ACTIV_CLASS'].split(','): - activity_class, created = MDDRActivityClass.objects.get_or_create(name=activity_class_name) + activity_class, created = MDDRActivityClass.objects.get_or_create( + name=activity_class_name) m.activity_classes.add(activity_class) m.save() except Exception as e: if options['stoponfail']: import traceback self.stderr.write(traceback.format_exc()) - raise CommandError('Failed inserting {}'.format(str(item))) + raise CommandError( + 'Failed inserting {}'.format(str(item))) else: - self.stdout.write(self.style.ERROR('Failed inserting {}'.format(str(item)))) + self.stdout.write( + self.style.ERROR('Failed inserting {}'.format(str(item)))) else: - self.stdout.write(self.style.SUCCESS('Successfully inserted {} {}'.format(item.data['MOLNAME'], str(item)))) + self.stdout.write( + self.style.SUCCESS('Successfully inserted {} {}'.format(item.data['MOLNAME'], str(item)))) if options['compound']: cursor.execute("""SELECT * FROM compound""") rows = cursor.fetchall() Compound.objects.all().delete() - self.stdout.write(self.style.SUCCESS('Successfully flushed compound table')) + self.stdout.write( + self.style.SUCCESS('Successfully flushed compound table')) for row in rows: try: compound = Compound() compound.canonical_smile = row[1] - compound.is_macrocycle = (row[4]=='Y') + compound.is_macrocycle = (row[4] == 'Y') compound.aromatic_ratio = row[5] compound.balaban_index = row[6] - compound.fsp3 = row[7] #Csp3Ratio - compound.gc_molar_refractivity=row[10] #GCMolarRefractivity - compound.log_d = row[13] #LogD - compound.a_log_p = row[14] #ALogP - compound.mean_atom_vol_vdw = row[15] #MeanAtomVolVdW - compound.molecular_weight = row[16] #MolecularWeight - compound.nb_acceptor_h = row[17] #NbAcceptorH - compound.nb_aliphatic_amines = row[18] #NbAliphaticsAmines - compound.nb_aromatic_bonds = row[19] #NbAromaticBonds - compound.nb_aromatic_ether = row[20] #NbAromaticsEther - compound.nb_aromatic_sssr = row[21] #NbAromaticsSSSR - compound.nb_atom = row[22] #NbAtom - compound.nb_atom_non_h = row[23] #NbAtomNonH - compound.nb_benzene_like_rings = row[24] #NbBenzLikeRings - compound.nb_bonds = row[25] #NbBonds - compound.nb_bonds_non_h = row[26] #NbBondsNonH - compound.nb_br = row[27] #NbBr - compound.nb_c = row[28] #NbC - compound.nb_chiral_centers = row[29] #NbChiralCenters - compound.nb_circuits = row[30] #NbCircuits - compound.nb_cl = row[31] #NbCl - compound.nb_csp2 = row[32] #NbCsp2 - compound.nb_csp3 = row[33] #NbCsp3 - compound.nb_donor_h = row[34] #NbDonorH - compound.nb_double_bonds = row[35] #NbDoubleBonds - compound.nb_f = row[36] #NbF - compound.nb_i = row[37] #NbI - compound.nb_multiple_bonds = row[38] #NbMultBonds - compound.nb_n = row[39] #NbN - compound.nb_o = row[40] #NbO - compound.nb_rings = row[41] #NbRings - compound.nb_rotatable_bonds = row[42] #NbRotatableBonds - compound.randic_index = row[44] #RandicIndex - compound.rdf070m = row[45] #RDF070m - compound.rotatable_bond_fraction = row[46] #RotatableBondFraction - compound.sum_atom_polar = row[47] #SumAtomPolar - compound.sum_atom_vol_vdw = row[48] #SumAtomVolVdW - compound.tpsa = row[51] #TPSA - compound.ui = row[52] #Ui - compound.wiener_index = row[54] #WienerIndex - if row[55]!='N': - compound.common_name = row[55] #CmpdNameSh - compound.pubchem_id = row[56] #IdPubchem - if row[57]!='N': - compound.chemspider_id = row[57] #IdPubchem + compound.fsp3 = row[7] # Csp3Ratio + compound.gc_molar_refractivity = row[ + 10] # GCMolarRefractivity + compound.log_d = row[13] # LogD + compound.a_log_p = row[14] # ALogP + compound.mean_atom_vol_vdw = row[15] # MeanAtomVolVdW + compound.molecular_weight = row[16] # MolecularWeight + compound.nb_acceptor_h = row[17] # NbAcceptorH + compound.nb_aliphatic_amines = row[ + 18] # NbAliphaticsAmines + compound.nb_aromatic_bonds = row[19] # NbAromaticBonds + compound.nb_aromatic_ether = row[20] # NbAromaticsEther + compound.nb_aromatic_sssr = row[21] # NbAromaticsSSSR + compound.nb_atom = row[22] # NbAtom + compound.nb_atom_non_h = row[23] # NbAtomNonH + compound.nb_benzene_like_rings = row[24] # NbBenzLikeRings + compound.nb_bonds = row[25] # NbBonds + compound.nb_bonds_non_h = row[26] # NbBondsNonH + compound.nb_br = row[27] # NbBr + compound.nb_c = row[28] # NbC + compound.nb_chiral_centers = row[29] # NbChiralCenters + compound.nb_circuits = row[30] # NbCircuits + compound.nb_cl = row[31] # NbCl + compound.nb_csp2 = row[32] # NbCsp2 + compound.nb_csp3 = row[33] # NbCsp3 + compound.nb_donor_h = row[34] # NbDonorH + compound.nb_double_bonds = row[35] # NbDoubleBonds + compound.nb_f = row[36] # NbF + compound.nb_i = row[37] # NbI + compound.nb_multiple_bonds = row[38] # NbMultBonds + compound.nb_n = row[39] # NbN + compound.nb_o = row[40] # NbO + compound.nb_rings = row[41] # NbRings + compound.nb_rotatable_bonds = row[42] # NbRotatableBonds + compound.randic_index = row[44] # RandicIndex + compound.rdf070m = row[45] # RDF070m + compound.rotatable_bond_fraction = row[ + 46] # RotatableBondFraction + compound.sum_atom_polar = row[47] # SumAtomPolar + compound.sum_atom_vol_vdw = row[48] # SumAtomVolVdW + compound.tpsa = row[51] # TPSA + compound.ui = row[52] # Ui + compound.wiener_index = row[54] # WienerIndex + if row[55] != 'N': + compound.common_name = row[55] # CmpdNameSh + compound.pubchem_id = row[56] # IdPubchem + if row[57] != 'N': + compound.chemspider_id = row[57] # IdPubchem compound.chembl_id = row[58] compound.iupac_name = row[59] - #compound.mddr_compound = row[60] - #FIXME lookup MDDR to get the right ID + # compound.mddr_compound = row[60] + # FIXME lookup MDDR to get the right ID compound.save() except Exception as e: if options['stoponfail']: import traceback self.stderr.write(traceback.format_exc()) - raise CommandError('Failed inserting {} {}'.format(row[1], row[2])) + raise CommandError( + 'Failed inserting {} {}'.format(row[1], row[2])) else: - self.stdout.write(self.style.ERROR('Failed inserting {} {}'.format(row[1], row[2]))) + self.stdout.write( + self.style.ERROR('Failed inserting {} {}'.format(row[1], row[2]))) else: - self.stdout.write(self.style.SUCCESS('Successfully inserted {} {}'.format(row[1], row[2]))) + self.stdout.write( + self.style.SUCCESS('Successfully inserted {} {}'.format(row[1], row[2]))) diff --git a/ippisite/ippidb/models.py b/ippisite/ippidb/models.py index 4456cfa2ba1916a3542f799f48c12fd9cc9fde64..4daa47324126d647e9d2abc93a7b2d5b033e9f74 100644 --- a/ippisite/ippidb/models.py +++ b/ippisite/ippidb/models.py @@ -4,7 +4,9 @@ from django.db import models from .ws import get_pubmed_info, get_epo_info, get_uniprot_info, get_taxonomy_info, get_go_info, get_pfam_info + class AutoFillableModel(models.Model): + """ AutoFillableModel makes it possible to automatically fill model fields from external sources in the autofill() method @@ -24,6 +26,7 @@ class AutoFillableModel(models.Model): class Bibliography(AutoFillableModel): + """ Bibliography data table """ @@ -32,7 +35,8 @@ class Bibliography(AutoFillableModel): ('PT', 'Patent'), ('DO', 'DOI ID') ) - source = models.CharField('Bibliographic type', max_length=2, choices=SOURCES, default='PM') + source = models.CharField( + 'Bibliographic type', max_length=2, choices=SOURCES, default='PM') id_source = models.CharField('Bibliographic ID', max_length=25) title = models.CharField('Title', max_length=300) journal_name = models.CharField('Journal name', max_length=50, null=True) @@ -43,7 +47,8 @@ class Bibliography(AutoFillableModel): in_vitro = models.BooleanField('in vitro study', default=False) in_vivo = models.BooleanField('in vivo study', default=False) in_cellulo = models.BooleanField('in cellulo study', default=False) - pharmacokinetic = models.BooleanField('pharmacokinetic study', default=False) + pharmacokinetic = models.BooleanField( + 'pharmacokinetic study', default=False) xray = models.BooleanField('X-Ray data', default=False) def autofill(self): @@ -64,7 +69,8 @@ class Bibliography(AutoFillableModel): class Taxonomy(AutoFillableModel): - taxonomy_id = models.DecimalField('NCBI TaxID', unique=True, max_digits=9, decimal_places=0) + taxonomy_id = models.DecimalField( + 'NCBI TaxID', unique=True, max_digits=9, decimal_places=0) name = models.CharField('Organism name', max_length=200) def autofill(self): @@ -77,8 +83,10 @@ class Taxonomy(AutoFillableModel): class Meta: verbose_name_plural = "taxonomies" + class MolecularFunction(AutoFillableModel): - go_id = models.CharField('Gene Ontology ID', unique=True, max_length=10) # GO term id format: 'GO:0000000' + go_id = models.CharField('Gene Ontology ID', unique=True, max_length=10) + # GO term id format: 'GO:0000000' description = models.CharField('description', max_length=500) def autofill(self): @@ -88,9 +96,11 @@ class MolecularFunction(AutoFillableModel): def __str__(self): return self.description + class Protein(AutoFillableModel): uniprot_id = models.CharField('Uniprot ID', unique=True, max_length=10) - recommended_name_long = models.CharField('Uniprot Recommended Name (long)', max_length=75) + recommended_name_long = models.CharField( + 'Uniprot Recommended Name (long)', max_length=75) short_name = models.CharField('Short name', max_length=50) gene_name = models.CharField('Gene name', unique=True, max_length=30) entry_name = models.CharField('Entry name', max_length=30) @@ -122,11 +132,14 @@ class Protein(AutoFillableModel): def __str__(self): return '{} ({})'.format(self.uniprot_id, self.recommended_name_long) + class Domain(AutoFillableModel): - pfam_acc = models.CharField('Pfam Accession', max_length=10, unique=True) - pfam_id = models.CharField('Pfam Family Identifier', max_length=20) + pfam_acc = models.CharField('Pfam Accession', max_length=10, unique=True) + pfam_id = models.CharField('Pfam Family Identifier', max_length=20) pfam_description = models.CharField('Pfam Description', max_length=100) - domain_family = models.CharField('Domain family', max_length=25) #TODO: what is this field? check database contents + domain_family = models.CharField('Domain family', max_length=25) + # TODO: what is this field? check database + # contents def autofill(self): info = get_pfam_info(self.pfam_acc) @@ -136,26 +149,34 @@ class Domain(AutoFillableModel): def __str__(self): return '{} ({}-{})'.format(self.pfam_acc, self.pfam_id, self.pfam_description) + class ProteinDomainComplex(models.Model): protein = models.ForeignKey('Protein') domain = models.ForeignKey('Domain') - ppc_copy_nb = models.IntegerField('Number of copies of the protein in the complex') - + ppc_copy_nb = models.IntegerField( + 'Number of copies of the protein in the complex') + class Meta: verbose_name_plural = "complexes" def __str__(self): return '{}-{}'.format(self.protein_id, self.domain_id) + class ProteinDomainBoundComplex(ProteinDomainComplex): - ppp_copy_nb_per_p = models.IntegerField('Number of copies of the protein in the pocket') + ppp_copy_nb_per_p = models.IntegerField( + 'Number of copies of the protein in the pocket') + class Meta: verbose_name_plural = "bound complexes" - + + class ProteinDomainPartnerComplex(ProteinDomainComplex): + class Meta: verbose_name_plural = "partner complexes" + class Symmetry(models.Model): code = models.CharField('Symmetry code', max_length=2) description = models.CharField('Description', max_length=300) @@ -168,14 +189,17 @@ class Symmetry(models.Model): class Disease(models.Model): - name = models.CharField('Disease', max_length=30, unique=True) # is there any database/nomenclature for diseases? + name = models.CharField('Disease', max_length=30, unique=True) + # is there any database/nomenclature for diseases? def __str__(self): return self.name + class Ppi(models.Model): pdb_id = models.CharField('PDB ID', max_length=4, null=True) - pockets_nb = models.IntegerField('Total number of pockets in the complex', default=1) + pockets_nb = models.IntegerField( + 'Total number of pockets in the complex', default=1) symmetry = models.ForeignKey(Symmetry) diseases = models.ManyToManyField(Disease) @@ -192,14 +216,15 @@ class Ppi(models.Model): """ return bound ppi complexes belonging to this ppi """ - #this is the less efficient query ever seen, FIXME + # this is the less efficient query ever seen, FIXME return PpiComplex.objects.filter(ppi=self, complex__in=ProteinDomainBoundComplex.objects.all()) class PpiComplex(models.Model): ppi = models.ForeignKey(Ppi) complex = models.ForeignKey(ProteinDomainComplex) - cc_nb = models.IntegerField('Number of copies of the complex in the PPI', default=1) + cc_nb = models.IntegerField( + 'Number of copies of the complex in the PPI', default=1) class Meta: verbose_name_plural = "Ppi complexes" @@ -209,60 +234,83 @@ class PpiComplex(models.Model): class Compound(models.Model): - canonical_smile = models.CharField('Canonical Smile', unique=True, max_length=500) - is_macrocycle = models.BooleanField('Contains one or more macrocycles') - aromatic_ratio = models.DecimalField('Aromatic ratio', max_digits=3, decimal_places=2) - balaban_index = models.DecimalField('Balaban index', max_digits=3, decimal_places=2) + canonical_smile = models.CharField( + 'Canonical Smile', unique=True, max_length=500) + is_macrocycle = models.BooleanField('Contains one or more macrocycles') + aromatic_ratio = models.DecimalField( + 'Aromatic ratio', max_digits=3, decimal_places=2) + balaban_index = models.DecimalField( + 'Balaban index', max_digits=3, decimal_places=2) fsp3 = models.DecimalField('Fsp3', max_digits=3, decimal_places=2) - gc_molar_refractivity = models.DecimalField('GC Molar Refractivity', max_digits=5, decimal_places=2) - log_d = models.DecimalField('LogD (Partition coefficient octanol-1/water, with pKa information)', max_digits=4, decimal_places=2) - a_log_p = models.DecimalField('ALogP (Partition coefficient octanol-1/water)', max_digits=4, decimal_places=2) - mean_atom_vol_vdw = models.DecimalField('Mean atom volume computed with VdW radii', max_digits=4, decimal_places=2) - molecular_weight = models.DecimalField('Molecular weight', max_digits=6, decimal_places=2) + gc_molar_refractivity = models.DecimalField( + 'GC Molar Refractivity', max_digits=5, decimal_places=2) + log_d = models.DecimalField( + 'LogD (Partition coefficient octanol-1/water, with pKa information)', max_digits=4, decimal_places=2) + a_log_p = models.DecimalField( + 'ALogP (Partition coefficient octanol-1/water)', max_digits=4, decimal_places=2) + mean_atom_vol_vdw = models.DecimalField( + 'Mean atom volume computed with VdW radii', max_digits=4, decimal_places=2) + molecular_weight = models.DecimalField( + 'Molecular weight', max_digits=6, decimal_places=2) nb_acceptor_h = models.IntegerField('Number of hydrogen bond acceptors') nb_aliphatic_amines = models.IntegerField('Number of aliphatics amines') nb_aromatic_bonds = models.IntegerField('Number of aromatic bonds') nb_aromatic_ether = models.IntegerField('Number of aromatic ethers') - nb_aromatic_sssr = models.IntegerField('Number of aromatic Smallest Set of System Rings (SSSR)') - nb_atom = models.IntegerField('Number of atoms') - nb_atom_non_h = models.IntegerField('Number of non hydrogen atoms') + nb_aromatic_sssr = models.IntegerField( + 'Number of aromatic Smallest Set of System Rings (SSSR)') + nb_atom = models.IntegerField('Number of atoms') + nb_atom_non_h = models.IntegerField('Number of non hydrogen atoms') nb_benzene_like_rings = models.IntegerField('Number of benzene-like rings') nb_bonds = models.IntegerField('Number of bonds') - nb_bonds_non_h = models.IntegerField('Number of bonds not involving a hydrogen') - nb_br = models.IntegerField('Number of Bromine atoms') - nb_c = models.IntegerField('Number of Carbon atoms') - nb_chiral_centers = models.IntegerField('Number of chiral centers') - nb_circuits = models.IntegerField('Number of circuits') - nb_cl = models.IntegerField('Number of Chlorine atoms') - nb_csp2 = models.IntegerField('Number of sp2-hybridized carbon atoms') - nb_csp3 = models.IntegerField('Number of sp3-hybridized carbon atoms') - nb_donor_h = models.IntegerField('Number of hydrogen bond donors') - nb_double_bonds = models.IntegerField('Number of double bonds') - nb_f = models.IntegerField('Number of fluorine atoms') - nb_i = models.IntegerField('Number of iodine atoms') - nb_multiple_bonds = models.IntegerField('Number of multiple bonds') + nb_bonds_non_h = models.IntegerField( + 'Number of bonds not involving a hydrogen') + nb_br = models.IntegerField('Number of Bromine atoms') + nb_c = models.IntegerField('Number of Carbon atoms') + nb_chiral_centers = models.IntegerField('Number of chiral centers') + nb_circuits = models.IntegerField('Number of circuits') + nb_cl = models.IntegerField('Number of Chlorine atoms') + nb_csp2 = models.IntegerField('Number of sp2-hybridized carbon atoms') + nb_csp3 = models.IntegerField('Number of sp3-hybridized carbon atoms') + nb_donor_h = models.IntegerField('Number of hydrogen bond donors') + nb_double_bonds = models.IntegerField('Number of double bonds') + nb_f = models.IntegerField('Number of fluorine atoms') + nb_i = models.IntegerField('Number of iodine atoms') + nb_multiple_bonds = models.IntegerField('Number of multiple bonds') nb_n = models.IntegerField('Number of nitrogen atoms') - nb_o = models.IntegerField('Number of oxygen atoms') - nb_rings = models.IntegerField('Number of rings') - nb_rotatable_bonds = models.IntegerField('Number of rotatable bonds') - randic_index = models.DecimalField('Randic index', max_digits=4, decimal_places=2) - rdf070m = models.DecimalField('RDF070m, radial distribution function weighted by the atomic masses at 7Å', max_digits=5, decimal_places=2) - rotatable_bond_fraction = models.DecimalField('Fraction of rotatable bonds', max_digits=3, decimal_places=2) - sum_atom_polar = models.DecimalField('Sum of atomic polarizabilities', max_digits=5, decimal_places=2) - sum_atom_vol_vdw = models.DecimalField('Sum of atom volumes computed with VdW radii', max_digits=6, decimal_places=2) - tpsa = models.DecimalField('Topological Polar Surface Area (TPSA)', max_digits=5, decimal_places=2) - ui = models.DecimalField('Unsaturation index', max_digits=4, decimal_places=2) - wiener_index = models.IntegerField('Wiener index') - common_name = models.CharField('Common name', unique=True, max_length=20, blank=True, null=True) - pubchem_id = models.CharField('Pubchem ID', max_length=10, blank=True, null=True) - chemspider_id = models.CharField('Chemspider ID', unique=True, max_length=10, blank=True, null=True) - chembl_id = models.CharField('Chembl ID', max_length=30, blank=True, null=True) - iupac_name = models.CharField('IUPAC name', max_length=255, blank=True, null=True) - mddr_compound = models.ForeignKey('MDDRCompoundImport', blank=True, null=True) + nb_o = models.IntegerField('Number of oxygen atoms') + nb_rings = models.IntegerField('Number of rings') + nb_rotatable_bonds = models.IntegerField('Number of rotatable bonds') + randic_index = models.DecimalField( + 'Randic index', max_digits=4, decimal_places=2) + rdf070m = models.DecimalField( + 'RDF070m, radial distribution function weighted by the atomic masses at 7Å', max_digits=5, decimal_places=2) + rotatable_bond_fraction = models.DecimalField( + 'Fraction of rotatable bonds', max_digits=3, decimal_places=2) + sum_atom_polar = models.DecimalField( + 'Sum of atomic polarizabilities', max_digits=5, decimal_places=2) + sum_atom_vol_vdw = models.DecimalField( + 'Sum of atom volumes computed with VdW radii', max_digits=6, decimal_places=2) + tpsa = models.DecimalField( + 'Topological Polar Surface Area (TPSA)', max_digits=5, decimal_places=2) + ui = models.DecimalField( + 'Unsaturation index', max_digits=4, decimal_places=2) + wiener_index = models.IntegerField('Wiener index') + common_name = models.CharField( + 'Common name', unique=True, max_length=20, blank=True, null=True) + pubchem_id = models.CharField( + 'Pubchem ID', max_length=10, blank=True, null=True) + chemspider_id = models.CharField( + 'Chemspider ID', unique=True, max_length=10, blank=True, null=True) + chembl_id = models.CharField( + 'Chembl ID', max_length=30, blank=True, null=True) + iupac_name = models.CharField( + 'IUPAC name', max_length=255, blank=True, null=True) + mddr_compound = models.ForeignKey( + 'MDDRCompoundImport', blank=True, null=True) class MDDRActivityClass(models.Model): - name = models.CharField('Activity Class', max_length=100, unique=True) + name = models.CharField('Activity Class', max_length=100, unique=True) class Meta: verbose_name_plural = "MDDR activity classes" @@ -270,58 +318,67 @@ class MDDRActivityClass(models.Model): def __str__(self): return self.name + class MDDRCompoundImport(models.Model): MDDR_DEVELOPMENT_PHASES = ( - ('Biological Testing',''), - ('Preclinical',''), - ('Phase III',''), - ('Phase II',''), - ('Phase I/II',''), - ('Phase I',''), - ('Launched',''), - ('Pre-Registered',''), - ('Not Applicable',''), - ('Discontinued',''), - ('Clinical',''), - ('Withdrawn',''), - ('Registered',''), - ('Not Determined',''), - ('Phase II/III',''), - ('IND Filed',''), + ('Biological Testing', ''), + ('Preclinical', ''), + ('Phase III', ''), + ('Phase II', ''), + ('Phase I/II', ''), + ('Phase I', ''), + ('Launched', ''), + ('Pre-Registered', ''), + ('Not Applicable', ''), + ('Discontinued', ''), + ('Clinical', ''), + ('Withdrawn', ''), + ('Registered', ''), + ('Not Determined', ''), + ('Phase II/III', ''), + ('IND Filed', ''), ) - mddr_name = models.CharField('MDDR name', max_length=40) - dvpmt_phase = models.CharField('Development phase', max_length=20, choices=MDDR_DEVELOPMENT_PHASES) - canonical_smile = models.CharField('Canonical Smile', max_length=500, blank=True, null=True) - #TODO index this table on canonical_smile - db_import_date = models.DateTimeField('MDDR release year/month') + mddr_name = models.CharField('MDDR name', max_length=40) + dvpmt_phase = models.CharField( + 'Development phase', max_length=20, choices=MDDR_DEVELOPMENT_PHASES) + canonical_smile = models.CharField( + 'Canonical Smile', max_length=500, blank=True, null=True) + # TODO index this table on canonical_smile + db_import_date = models.DateTimeField('MDDR release year/month') activity_classes = models.ManyToManyField(MDDRActivityClass) class Meta: # over multiple releases of the MDDR database, the same compound can evolve in its development phase - # the same compound can have different names and development phases in the same MDDR release + # the same compound can have different names and development phases in + # the same MDDR release unique_together = (('mddr_name', 'dvpmt_phase', 'canonical_smile'),) verbose_name_plural = "MDDR compound imports" def __str__(self): return "{}, {}".format(self.mddr_name, self.dvpmt_phase) + class MDDRSimilarity(models.Model): - canonical_smile_ippidb = models.CharField('Canonical Smile for IPPIDB compound', max_length=500, unique=True, blank=True, null=True) - canonical_smile_mddr = models.CharField('Canonical Smile for MDDR Compound', max_length=500, unique=True, blank=True, null=True) - tanimoto = models.DecimalField('Tanimoto', max_digits=6, decimal_places=5) + canonical_smile_ippidb = models.CharField( + 'Canonical Smile for IPPIDB compound', max_length=500, unique=True, blank=True, null=True) + canonical_smile_mddr = models.CharField( + 'Canonical Smile for MDDR Compound', max_length=500, unique=True, blank=True, null=True) + tanimoto = models.DecimalField('Tanimoto', max_digits=6, decimal_places=5) class Meta: unique_together = (('canonical_smile_ippidb', 'canonical_smile_mddr'),) verbose_name_plural = "MDDR similarities" + class CellLine(models.Model): name = models.CharField('Name', max_length=50, unique=True) def __str__(self): return self.name + class TestActivityDescription(models.Model): TEST_TYPES = ( ('BIOCH', 'Biochemical assay'), @@ -333,11 +390,13 @@ class TestActivityDescription(models.Model): ('S', 'Stabilization') ) biblio = models.ForeignKey(Bibliography) - ppi = models.ForeignKey(Ppi, blank=True, null=True) - test_name = models.CharField('Test name', max_length=100) + ppi = models.ForeignKey(Ppi, blank=True, null=True) + test_name = models.CharField('Test name', max_length=100) test_type = models.CharField('Test type', max_length=5, choices=TEST_TYPES) - test_modulation_type = models.CharField('Test modulation type', max_length=1, choices=TEST_MODULATION_TYPES) - nb_active_compounds = models.IntegerField('Total number of active compounds') + test_modulation_type = models.CharField( + 'Test modulation type', max_length=1, choices=TEST_MODULATION_TYPES) + nb_active_compounds = models.IntegerField( + 'Total number of active compounds') cell_line = models.ForeignKey(CellLine, blank=True, null=True) def get_complexes(self): @@ -345,11 +404,12 @@ class TestActivityDescription(models.Model): get the complexes tested for this PPI depends on the modulation type """ - if self.test_modulation_type=='I': + if self.test_modulation_type == 'I': return self.ppi.get_ppi_complexes() else: return self.ppi.get_ppi_bound_complexes() + class CompoundActivityResult(models.Model): MODULATION_TYPES = ( ('B', 'Binding'), @@ -357,34 +417,42 @@ class CompoundActivityResult(models.Model): ('S', 'Stabilization') ) ACTIVITY_TYPES = ( - ('pIC50','pIC50 (half maximal inhibitory concentration, -log10)'), - ('pEC50','pEC50 (half maximal effective concentration, -log10)'), - ('pKd','pKd (dissociation constant, -log10)'), - ('pKi','pKi (inhibition constant, -log10)'), + ('pIC50', 'pIC50 (half maximal inhibitory concentration, -log10)'), + ('pEC50', 'pEC50 (half maximal effective concentration, -log10)'), + ('pKd', 'pKd (dissociation constant, -log10)'), + ('pKi', 'pKi (inhibition constant, -log10)'), ) - compound = models.ForeignKey(Compound) - test_activity_description = models.ForeignKey(TestActivityDescription) - activity_type = models.CharField('Activity type', max_length=5, choices=ACTIVITY_TYPES) - activity = models.DecimalField('Activity', max_digits=12, decimal_places=10) - modulation_type = models.CharField('Modulation type', max_length=1, choices=MODULATION_TYPES) + compound = models.ForeignKey(Compound) + test_activity_description = models.ForeignKey(TestActivityDescription) + activity_type = models.CharField( + 'Activity type', max_length=5, choices=ACTIVITY_TYPES) + activity = models.DecimalField( + 'Activity', max_digits=12, decimal_places=10) + modulation_type = models.CharField( + 'Modulation type', max_length=1, choices=MODULATION_TYPES) class Meta: - unique_together = (('compound', 'test_activity_description', 'activity_type'),) + unique_together = ( + ('compound', 'test_activity_description', 'activity_type'),) + class TestCytotoxDescription(models.Model): - biblio = models.ForeignKey(Bibliography) - test_name = models.CharField('Cytotoxicity test name', max_length=100) + biblio = models.ForeignKey(Bibliography) + test_name = models.CharField('Cytotoxicity test name', max_length=100) cell_line = models.ForeignKey(CellLine) - compound_concentration = models.DecimalField('Compound concentration in μM', max_digits=7, decimal_places=3, blank=True, null=True) + compound_concentration = models.DecimalField( + 'Compound concentration in μM', max_digits=7, decimal_places=3, blank=True, null=True) + class CompoundCytotoxicityResult(models.Model): - compound = models.ForeignKey(Compound) + compound = models.ForeignKey(Compound) test_cytotoxicity_description = models.ForeignKey(TestCytotoxDescription) toxicity = models.BooleanField('Toxicity', default=False) class Meta: unique_together = (('compound', 'test_cytotoxicity_description'),) + class TestPKDescription(models.Model): ADMINISTRATION_MODES = ( ('IV', ''), @@ -392,24 +460,33 @@ class TestPKDescription(models.Model): ('IP', ''), ('SL', 'SL') ) - biblio = models.ForeignKey(Bibliography) - test_name = models.CharField('Pharmacokinetic test name', max_length=100) + biblio = models.ForeignKey(Bibliography) + test_name = models.CharField('Pharmacokinetic test name', max_length=100) organism = models.ForeignKey(Taxonomy) - administration_mode = models.CharField('Administration mode', max_length=2, choices=ADMINISTRATION_MODES,blank=True, null=True) - dose = models.DecimalField('Dose in mg/kg', max_digits=7, decimal_places=4, blank=True, null=True) - dose_interval = models.IntegerField('Dose interval, in hours', blank=True, null=True) + administration_mode = models.CharField( + 'Administration mode', max_length=2, choices=ADMINISTRATION_MODES, blank=True, null=True) + dose = models.DecimalField( + 'Dose in mg/kg', max_digits=7, decimal_places=4, blank=True, null=True) + dose_interval = models.IntegerField( + 'Dose interval, in hours', blank=True, null=True) + class CompoundPKResult(models.Model): - compound = models.ForeignKey(Compound) + compound = models.ForeignKey(Compound) test_pk_description = models.ForeignKey(TestPKDescription) tolerated = models.NullBooleanField('Tolerated', null=True) - auc = models.IntegerField('Area under curve (ng.mL-1.hr)', blank=True, null=True) - clearance = models.DecimalField('Clearance (mL/hr)', max_digits=7, decimal_places=3, blank=True, null=True) - cmax = models.DecimalField('Maximal concentration (ng/mL)', max_digits=7, decimal_places=3, blank=True, null=True) - oral_bioavailability = models.IntegerField('Oral Bioavailability (%F)', blank=True, null=True) - t_demi = models.IntegerField('t½', blank=True, null=True) - t_max = models.IntegerField('tmax', blank=True, null=True) - voldistribution = models.DecimalField('Volume distribution (Vd)', max_digits=5, decimal_places=2, blank=True, null=True) + auc = models.IntegerField( + 'Area under curve (ng.mL-1.hr)', blank=True, null=True) + clearance = models.DecimalField( + 'Clearance (mL/hr)', max_digits=7, decimal_places=3, blank=True, null=True) + cmax = models.DecimalField( + 'Maximal concentration (ng/mL)', max_digits=7, decimal_places=3, blank=True, null=True) + oral_bioavailability = models.IntegerField( + 'Oral Bioavailability (%F)', blank=True, null=True) + t_demi = models.IntegerField('t½', blank=True, null=True) + t_max = models.IntegerField('tmax', blank=True, null=True) + voldistribution = models.DecimalField( + 'Volume distribution (Vd)', max_digits=5, decimal_places=2, blank=True, null=True) class Meta: unique_together = (('compound', 'test_pk_description'),) @@ -420,11 +497,13 @@ class CompoundAction(models.Model): ('O', 'Orthosteric'), ('A', 'Allosteric') ) - compound = models.ForeignKey(Compound) - activation_mode = models.CharField('Activation mode', max_length=1, choices=ACTIVATION_MODES) + compound = models.ForeignKey(Compound) + activation_mode = models.CharField( + 'Activation mode', max_length=1, choices=ACTIVATION_MODES) ppi = models.ForeignKey(Ppi) pdb_id = models.CharField('PDB ID', max_length=4) - nb_copy_compounds = models.IntegerField('Number of copies for the compound') + nb_copy_compounds = models.IntegerField( + 'Number of copies for the compound') class Meta: unique_together = (('ppi', 'compound', 'activation_mode', 'pdb_id'),) @@ -436,10 +515,12 @@ class CompoundAction(models.Model): """ return self.ppi.get_ppi_bound_complexes() + class RefCompoundBiblio(models.Model): - compound = models.ForeignKey(Compound) - bibliography = models.ForeignKey(Bibliography) - compound_name = models.CharField('Compound name in the publication', max_length=50) + compound = models.ForeignKey(Compound) + bibliography = models.ForeignKey(Bibliography) + compound_name = models.CharField( + 'Compound name in the publication', max_length=50) class Meta: unique_together = (('compound', 'bibliography'),) diff --git a/ippisite/ippidb/urls.py b/ippisite/ippidb/urls.py index 377643bea8062f91dab63debefe8169df3f69c85..3cfaacf9b49cf01e977c2512c7f71a14c894d5be 100644 --- a/ippisite/ippidb/urls.py +++ b/ippisite/ippidb/urls.py @@ -1,10 +1,10 @@ -from django.conf.urls import include,url +from django.conf.urls import include, url from . import views -from ippidb.forms import IdForm, BibliographyForm,PDBForm,ProteinDomainComplexTypeForm,ProteinDomainComplexForm,PpiForm -from ippidb.views import IppiWizard,FORMS +from ippidb.forms import IdForm, BibliographyForm, PDBForm, ProteinDomainComplexTypeForm, ProteinDomainComplexForm, PpiForm +from ippidb.views import IppiWizard, FORMS ippidb_wizard = IppiWizard.as_view(FORMS, - url_name='ippidb_step') + url_name='ippidb_step') urlpatterns = [ @@ -12,14 +12,17 @@ urlpatterns = [ url(r'^about$', views.about, name='about'), url(r'^about/general/$', views.general, name='general'), url(r'^about/pharmacology/$', views.pharmacology, name='pharmacology'), - url(r'^about/physicochemistry/$', views.physicochemistry, name='physicochemistry'), - url(r'^about/drug-candidate/$', views.drugCandidate, name='drug-candidate'), + url(r'^about/physicochemistry/$', + views.physicochemistry, name='physicochemistry'), + url(r'^about/drug-candidate/$', + views.drugCandidate, name='drug-candidate'), url(r'^query$', views.query, name='query'), url(r'^query/pharma/$', views.pharma, name='pharma'), url(r'^query/chemical/$', views.chemical, name='chemical'), url(r'^tutorials$', views.tutorials, name='tutorials'), - url(r'^admin-session$', views.adminSession, name='admin-session'), - url(r'^admin-session/add/(?P<step>.+)/$', ippidb_wizard, name='ippidb_step'), + url(r'^admin-session$', views.adminSession, name='admin-session'), + url(r'^admin-session/add/(?P<step>.+)/$', + ippidb_wizard, name='ippidb_step'), url(r'^admin-session/add/$', ippidb_wizard, name='ippidb'), ] diff --git a/ippisite/ippidb/views.py b/ippisite/ippidb/views.py index ddc731043ce42c509474af7d007d9facf6ff21c0..6994beb62beb3b90abc79aa5b93d344a138f8e0c 100644 --- a/ippisite/ippidb/views.py +++ b/ippisite/ippidb/views.py @@ -2,50 +2,62 @@ import ippidb from django.shortcuts import render from django.http import HttpResponseRedirect -from formtools.wizard.views import SessionWizardView,NamedUrlSessionWizardView +from formtools.wizard.views import SessionWizardView, NamedUrlSessionWizardView from .forms import IdForm, BibliographyForm, PDBForm, ProteinForm, ProteinDomainComplexTypeForm, ProteinDomainComplexForm, PpiForm, ProteinFormSet, PDBFormSet from .models import Protein, Bibliography from .ws import get_pdb_uniprot_mapping + def index(request): return render(request, 'index.html') + def about(request): return render(request, 'about.html') + def general(request): return render(request, 'general.html') + def pharmacology(request): return render(request, 'pharmacology.html') + def physicochemistry(request): return render(request, 'physicochemistry.html') + def drugCandidate(request): return render(request, 'drug-candidate.html') + def query(request): return render(request, 'query.html') + def pharma(request): return render(request, 'pharma.html') + def chemical(request): return render(request, 'chemical.html') + def tutorials(request): return render(request, 'tutorials.html') + def adminSession(request): return render(request, 'admin-session.html') FORMS = [("IdForm", ippidb.forms.IdForm), ("BibliographyForm", ippidb.forms.BibliographyForm), ("PDBForm", ippidb.forms.PDBFormSet), - ("ProteinForm",ippidb.forms.ProteinFormSet), - ("ProteinDomainComplexTypeForm", ippidb.forms.ProteinDomainComplexTypeForm), + ("ProteinForm", ippidb.forms.ProteinFormSet), + ("ProteinDomainComplexTypeForm", + ippidb.forms.ProteinDomainComplexTypeForm), ("ProteinDomainComplexForm", ippidb.forms.ProteinDomainComplexForm), ("PpiForm", ippidb.forms.PpiForm)] @@ -53,19 +65,21 @@ TEMPLATES = {"IdForm": "IdForm.html", "BibliographyForm": "BibliographyForm.html", "PDBForm": "PDBForm.html", "ProteinForm": "ProteinForm.html", - "ProteinDomainComplexTypeForm":"ProteinDomainComplexTypeForm.html", + "ProteinDomainComplexTypeForm": "ProteinDomainComplexTypeForm.html", "ProteinDomainComplexForm": "ProteinDomainComplexForm.html", "PpiForm": "PpiForm.html"} + class IppiWizard(NamedUrlSessionWizardView): + def get_template_names(self): return [TEMPLATES[self.steps.current]] def get_form_instance(self, step): - if self.steps.current=='BibliographyForm': + if self.steps.current == 'BibliographyForm': pk = self.storage.get_step_data('IdForm').get('pk') return Bibliography.objects.get(pk=pk) - if self.steps.current=='ProteinForm': + if self.steps.current == 'ProteinForm': pks = self.storage.get_step_data('PDBForm').get('pks') return Protein.objects.filter(id__in=pks) @@ -76,12 +90,12 @@ class IppiWizard(NamedUrlSessionWizardView): when appropriate """ data = super(IppiWizard, self).process_step(form).copy() - if self.steps.current=='IdForm': + if self.steps.current == 'IdForm': form.instance.autofill() if self.steps.current in ['IdForm', 'Bibliography']: form.instance.save() data['pk'] = form.instance.id - if self.steps.current=='PDBForm': + if self.steps.current == 'PDBForm': pdb_ids = [form['pdb_id'] for form in form.cleaned_data] uniprot_ids = [] protein_ids = [] @@ -103,4 +117,3 @@ class IppiWizard(NamedUrlSessionWizardView): return render(self.request, '/admin-session/add.html', { 'form_data': [form.cleaned_data for form in form_list], }) - diff --git a/ippisite/ippidb/ws.py b/ippisite/ippidb/ws.py index ad6fd40ee8fd118cc998ffa40465371673ad9faf..fa72b16dcb9373f28a123eb17169bcc5baba15c5 100644 --- a/ippisite/ippidb/ws.py +++ b/ippisite/ippidb/ws.py @@ -3,12 +3,15 @@ from bioservices.uniprot import UniProt import xml.etree.ElementTree as ET import requests + def get_pubmed_info(pmid): eu = EUtils() r = eu.EFetch('pubmed', pmid, retmode='dict', rettype='abstract') - article = r['PubmedArticleSet']['PubmedArticle']['MedlineCitation']['Article'] + article = r['PubmedArticleSet'][ + 'PubmedArticle']['MedlineCitation']['Article'] title = article['ArticleTitle'] - authors_list = [a['LastName']+ ' ' + a['Initials'] for a in article['AuthorList']['Author']] + authors_list = [a['LastName'] + ' ' + a['Initials'] + for a in article['AuthorList']['Author']] authors = ', '.join(authors_list) journal_name = article['Journal']['Title'] biblio_date = article['Journal']['JournalIssue']['PubDate'] @@ -16,60 +19,76 @@ def get_pubmed_info(pmid): biblio_year = biblio_date['Year'] else: biblio_year = biblio_date['MedlineDate'][0:3] - return {'title':title, - 'journal_name':journal_name, - 'biblio_year':biblio_year, + return {'title': title, + 'journal_name': journal_name, + 'biblio_year': biblio_year, 'authors_list': authors} + def get_epo_info(patent_number): - resp = requests.get('http://ops.epo.org/3.1/rest-services/published-data/publication/docdb/{}/biblio.json'.format(patent_number)) + resp = requests.get( + 'http://ops.epo.org/3.1/rest-services/published-data/publication/docdb/{}/biblio.json'.format(patent_number)) data = resp.json() - exchange_doc = data['ops:world-patent-data']['exchange-documents']['exchange-document'] + exchange_doc = data['ops:world-patent-data'][ + 'exchange-documents']['exchange-document'] if isinstance(exchange_doc, list): exchange_doc = exchange_doc[0] - title = [el['$'] for el in exchange_doc['bibliographic-data']['invention-title'] if el['@lang']=='en'] - authors = [i['inventor-name']['name']['$'] for i in exchange_doc['bibliographic-data']['parties']['inventors']['inventor'] if i['@data-format']=='original'] - biblio_year = [el['date']['$'][:4] for el in exchange_doc['bibliographic-data']['publication-reference']['document-id'] if el['@document-id-type']=='epodoc'][0] + title = [el['$'] + for el in exchange_doc['bibliographic-data']['invention-title'] if el['@lang'] == 'en'] + authors = [i['inventor-name']['name']['$'] + for i in exchange_doc['bibliographic-data']['parties']['inventors']['inventor'] if i['@data-format'] == 'original'] + biblio_year = [el['date']['$'][:4] + for el in exchange_doc['bibliographic-data']['publication-reference']['document-id'] if el['@document-id-type'] == 'epodoc'][0] return {'title': title, 'journal_name': None, 'biblio_year': biblio_year, 'authors_list': authors} + def get_uniprot_info(uniprot_id): uniprot_client = UniProt() - ns = {'u':'http://uniprot.org/uniprot'} + ns = {'u': 'http://uniprot.org/uniprot'} resp = uniprot_client.retrieve(uniprot_id) - recommended_name = resp.root.findall('u:entry/u:protein/u:recommendedName/u:fullName', ns)[0].text - organism = resp.root.findall('u:entry/u:organism/u:dbReference[@type="NCBI Taxonomy"]', ns)[0].attrib['id'] - gene = resp.root.findall('u:entry/u:gene/u:name[@type="primary"]', ns)[0].text + recommended_name = resp.root.findall( + 'u:entry/u:protein/u:recommendedName/u:fullName', ns)[0].text + organism = resp.root.findall( + 'u:entry/u:organism/u:dbReference[@type="NCBI Taxonomy"]', ns)[0].attrib['id'] + gene = resp.root.findall( + 'u:entry/u:gene/u:name[@type="primary"]', ns)[0].text entry_name = resp.root.findall('u:entry/u:name', ns)[0].text go_els = resp.root.findall('u:entry/u:dbReference[@type="GO"]', ns) molecular_functions = [] for go_el in go_els: - term_property_value = go_el.findall('u:property[@type="term"]', ns)[0].attrib['value'] - if term_property_value[0:2]=='F:': - molecular_functions.append('GO_'+go_el.attrib['id'][3:]) + term_property_value = go_el.findall( + 'u:property[@type="term"]', ns)[0].attrib['value'] + if term_property_value[0:2] == 'F:': + molecular_functions.append('GO_' + go_el.attrib['id'][3:]) return {'recommended_name': recommended_name, 'organism': int(organism), 'gene': gene, 'entry_name': entry_name, 'molecular_functions': molecular_functions - } + } + def get_go_info(go_id): - resp = requests.get('https://www.ebi.ac.uk/ols/api/ontologies/go/terms/http%253A%252F%252Fpurl.obolibrary.org%252Fobo%252F{}'.format(go_id)) + resp = requests.get( + 'https://www.ebi.ac.uk/ols/api/ontologies/go/terms/http%253A%252F%252Fpurl.obolibrary.org%252Fobo%252F{}'.format(go_id)) data = resp.json() label = data['label'] return {'label': label} + def get_taxonomy_info(taxonomy_id): eu = EUtils() r = eu.EFetch('taxonomy', taxonomy_id, retmode='dict') scientific_name = r['TaxaSet']['Taxon']['ScientificName'] return {'scientific_name': scientific_name} + def get_pfam_info(pfam_acc): - resp = requests.get('http://pfam.xfam.org/family/{}?output=xml'.format(pfam_acc)) + resp = requests.get( + 'http://pfam.xfam.org/family/{}?output=xml'.format(pfam_acc)) root = ET.fromstring(resp.text) ns = {'pfam': 'http://pfam.xfam.org/'} entry = root.findall('pfam:entry', ns)[0] @@ -79,14 +98,18 @@ def get_pfam_info(pfam_acc): return {'id': pfam_id, 'description': description} + def get_pdb_uniprot_mapping(pdb_id): - resp = requests.get('https://www.ebi.ac.uk/pdbe/api/mappings/uniprot/{}'.format(pdb_id.lower())) + resp = requests.get( + 'https://www.ebi.ac.uk/pdbe/api/mappings/uniprot/{}'.format(pdb_id.lower())) uniprot_ids = list(resp.json()[pdb_id]['UniProt'].keys()) return uniprot_ids + def pdb_entry_exists(pdb_id): """ test if a PDB entry exists using EBI web services """ - resp = requests.get('https://www.ebi.ac.uk/pdbe/api/pdb/entry/summary/{}'.format(pdb_id.lower())) + resp = requests.get( + 'https://www.ebi.ac.uk/pdbe/api/pdb/entry/summary/{}'.format(pdb_id.lower())) # EBI sends back either a 404 or an empty json if the PDB does not exist if not(resp.ok): return False