diff --git a/ippisite/ippidb/models.py b/ippisite/ippidb/models.py index 41d9fcfe7c4d7fd3d1e7885ee478bbb100508ab0..7358a3cd45761d861a60f19dddc0c6f9416bb211 100644 --- a/ippisite/ippidb/models.py +++ b/ippisite/ippidb/models.py @@ -37,9 +37,9 @@ class AutoFillableModel(models.Model): class Bibliography(AutoFillableModel): - """ - Bibliography data table + Bibliography references + (publications or patents) """ SOURCES = ( ('PM', 'PubMed ID'), @@ -63,6 +63,10 @@ class Bibliography(AutoFillableModel): xray = models.BooleanField('X-Ray data', default=False) def autofill(self): + """ + fetch information from external services + (Pubmed or Google patents) + """ if self.source == 'PM': info = get_pubmed_info(self.id_source) else: @@ -80,11 +84,19 @@ class Bibliography(AutoFillableModel): class Taxonomy(AutoFillableModel): + """ + Taxonomy IDs (from NCBI Taxonomy) + and the corresponding human-readable name + """ 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): + """ + fetch information from external services + (NCBI Entrez) + """ info = get_taxonomy_info(self.taxonomy_id) self.name = info['scientific_name'] @@ -96,11 +108,19 @@ class Taxonomy(AutoFillableModel): class MolecularFunction(AutoFillableModel): + """ + Molecular functions (from Gene Ontology) + and the corresponding human-readable description + """ 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): + """ + fetch information from external services + (EBI OLS) + """ info = get_go_info(self.go_id) self.description = info['label'] @@ -113,6 +133,10 @@ class MolecularFunction(AutoFillableModel): class Protein(AutoFillableModel): + """ + Protein information (from Uniprot) + and the corresponding human-readable name + """ uniprot_id = models.CharField('Uniprot ID', unique=True, max_length=10) recommended_name_long = models.CharField( 'Uniprot Recommended Name (long)', max_length=75) @@ -123,6 +147,10 @@ class Protein(AutoFillableModel): molecular_functions = models.ManyToManyField(MolecularFunction) def autofill(self): + """ + fetch information from external services + (Uniprot) and create Taxonomy/Molecular Functions if needed + """ info = get_uniprot_info(self.uniprot_id) self.recommended_name_long = info['recommended_name'] self.gene_name = info['gene'] @@ -150,6 +178,9 @@ class Protein(AutoFillableModel): class Domain(AutoFillableModel): + """ + Domain (i.e. Protein domain) information (from PFAM) + """ 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) @@ -158,6 +189,10 @@ class Domain(AutoFillableModel): # contents def autofill(self): + """ + fetch information from external services + (PFAM) + """ info = get_pfam_info(self.pfam_acc) self.pfam_id = info['id'] self.pfam_description = info['description'] @@ -171,6 +206,9 @@ class Domain(AutoFillableModel): class ProteinDomainComplex(models.Model): + """ + Protein-Domain association + """ protein = models.ForeignKey('Protein', models.CASCADE) domain = models.ForeignKey('Domain', models.CASCADE) ppc_copy_nb = models.IntegerField( @@ -187,6 +225,9 @@ class ProteinDomainComplex(models.Model): class ProteinDomainBoundComplex(ProteinDomainComplex): + """ + Protein-Domain association with a "bound complex" role + """ ppp_copy_nb_per_p = models.IntegerField( 'Number of copies of the protein in the pocket') @@ -195,12 +236,18 @@ class ProteinDomainBoundComplex(ProteinDomainComplex): class ProteinDomainPartnerComplex(ProteinDomainComplex): + """ + Protein-Domain association with a "partner complex" role + """ class Meta: verbose_name_plural = "partner complexes" class Symmetry(models.Model): + """ + Symmetry of a PPI + """ code = models.CharField('Symmetry code', max_length=2) description = models.CharField('Description', max_length=300) @@ -219,6 +266,9 @@ class Disease(models.Model): return self.name class PpiFamily(models.Model): + """ + PPI Family + """ name = models.CharField('Name', max_length=30, unique=True) class Meta: @@ -229,6 +279,9 @@ class PpiFamily(models.Model): class Ppi(AutoFillableModel): + """ + PPI + """ pdb_id = models.CharField('PDB ID', max_length=4, null=True, blank=True) pockets_nb = models.IntegerField( 'Total number of pockets in the complex', default=1) @@ -266,6 +319,9 @@ class Ppi(AutoFillableModel): class PpiComplex(models.Model): + """ + PPI Complex + """ ppi = models.ForeignKey(Ppi, models.CASCADE) complex = models.ForeignKey(ProteinDomainComplex, models.CASCADE) cc_nb = models.IntegerField( @@ -279,6 +335,10 @@ class PpiComplex(models.Model): class CompoundManager(models.Manager): + """ + CompoundManager adds automatically a number of annotations to the results + of the database query, used for filters and compound card + """ def get_queryset(self): qs = super().get_queryset() @@ -344,6 +404,9 @@ class CompoundManager(models.Manager): return qs class Compound(AutoFillableModel): + """ + Chemical compound + """ objects = CompoundManager() canonical_smile = models.TextField( 'Canonical Smile', unique=True) @@ -546,6 +609,10 @@ class CompoundTanimoto(models.Model): ('canonical_smiles', 'fingerprint', 'compound')) def create_tanimoto(smiles_query, fingerprint): + """ + Compute the Tanimoto similarity between a given SMILES and the compounds + then insert the results in CompoundTanimoto + """ if CompoundTanimoto.objects.filter(canonical_smiles=smiles_query, fingerprint=fingerprint).count()==0: smiles_dict = {c.id:c.canonical_smile for c in Compound.objects.all()} fingerprinter = FingerPrinter(fingerprint) @@ -558,16 +625,27 @@ def create_tanimoto(smiles_query, fingerprint): CompoundTanimoto.objects.bulk_create(cts) class PcaBiplotData(models.Model): + """ + PCA biplot data + the table contains all the data as one JSON text in one row + """ pca_biplot_data = models.TextField( 'PCA biplot JSON data', blank=True, null=True) class LeLleBiplotData(models.Model): + """ + LE-LLE biplot data + the table contains all the data as one JSON text in one row + """ le_lle_biplot_data = models.TextField( 'LE-LLE biplot JSON data', blank=True, null=True) class CellLine(models.Model): + """ + Cell lines + """ name = models.CharField('Name', max_length=50, unique=True) def __str__(self): @@ -575,6 +653,9 @@ class CellLine(models.Model): class TestActivityDescription(models.Model): + """ + Activity test descriptions + """ TEST_TYPES = ( ('BIOCH', 'Biochemical assay'), ('CELL', 'Cellular assay') @@ -630,6 +711,9 @@ class TestActivityDescription(models.Model): class CompoundActivityResult(models.Model): + """ + Activity test results on a compound + """ MODULATION_TYPES = ( ('I', 'Inhibition'), ('S', 'Stabilization') @@ -664,6 +748,9 @@ class CompoundActivityResult(models.Model): class TestCytotoxDescription(models.Model): + """ + Cytotoxicity test descriptions + """ biblio = models.ForeignKey(Bibliography, models.CASCADE) test_name = models.CharField('Cytotoxicity test name', max_length=100) cell_line = models.ForeignKey(CellLine, models.CASCADE) @@ -672,6 +759,9 @@ class TestCytotoxDescription(models.Model): class CompoundCytotoxicityResult(models.Model): + """ + Cytotoxicity test results on a compound + """ compound = models.ForeignKey(Compound, models.CASCADE) test_cytotoxicity_description = models.ForeignKey( TestCytotoxDescription, models.CASCADE) @@ -685,6 +775,9 @@ class CompoundCytotoxicityResult(models.Model): class TestPKDescription(models.Model): + """ + Pharmacokinetic test descriptions + """ ADMINISTRATION_MODES = ( ('IV', ''), ('PO', ''), @@ -705,6 +798,9 @@ class TestPKDescription(models.Model): class CompoundPKResult(models.Model): + """ + Pharmacokinetic test results on a compound + """ compound = models.ForeignKey(Compound, models.CASCADE) test_pk_description = models.ForeignKey(TestPKDescription, models.CASCADE) tolerated = models.NullBooleanField('Tolerated', null=True) @@ -729,6 +825,9 @@ class CompoundPKResult(models.Model): class CompoundAction(models.Model): + """ + Compound action + """ ACTIVATION_MODES = ( ('O', 'Orthosteric'), ('A', 'Allosteric'), @@ -756,6 +855,9 @@ class CompoundAction(models.Model): return 'Action of {} on {}'.format(self.compound, self.ppi) class RefCompoundBiblio(models.Model): + """ + Compound-Bibliographic reference association + """ compound = models.ForeignKey(Compound, models.CASCADE) bibliography = models.ForeignKey(Bibliography, models.CASCADE) compound_name = models.CharField( @@ -765,6 +867,9 @@ class RefCompoundBiblio(models.Model): unique_together = (('compound', 'bibliography'),) class DrugBankCompound(models.Model): + """ + Drugbank compound + """ id = models.TextField( 'Drugbank ID', unique=True, primary_key=True) common_name = models.TextField('Common name') @@ -772,6 +877,9 @@ class DrugBankCompound(models.Model): 'Canonical SMILES') class DrugbankCompoundTanimoto(models.Model): + """ + Drugbank compound-compound tanimoto similarity + """ compound = models.ForeignKey(Compound, models.CASCADE) drugbank_compound = models.ForeignKey(DrugBankCompound, models.CASCADE) tanimoto = models.DecimalField( diff --git a/ippisite/ippidb/tests.py b/ippisite/ippidb/tests.py index ea1a73f8f5e0e528db4402582841222a6a73d883..5fc938e61a76b2964a8eeab772b14e58a057d1e0 100644 --- a/ippisite/ippidb/tests.py +++ b/ippisite/ippidb/tests.py @@ -47,6 +47,9 @@ class SmiInchi(TestCase): class FingerPrinterTestCase(TestCase): + """ + Test FingerPrinter class + """ def setUp(self): self.fingerprinter = FingerPrinter("FP4") diff --git a/ippisite/ippidb/views/compound_query.py b/ippisite/ippidb/views/compound_query.py index da4d49859816b2500fe42cfef89766d1d1a02ad7..4462b28a8f4013923238cdd07cfeba54792099d2 100644 --- a/ippisite/ippidb/views/compound_query.py +++ b/ippisite/ippidb/views/compound_query.py @@ -381,6 +381,9 @@ class TrueListFilterHandler(object): class CompoundListView(ListView): + """ + Compounds list view + """ model = Compound template_name = "compound_list.html" @@ -515,6 +518,9 @@ class CompoundDetailView(DetailView): return context class CompoundCardBDCHEMRedirectView(RedirectView): + """ + redirection of BD-CHEM-issued URLs + """ def get_redirect_url(self, *args, **kwargs): kwargs['compound_id'] = str(int(kwargs['compound_id'])) @@ -522,6 +528,9 @@ class CompoundCardBDCHEMRedirectView(RedirectView): def convert_mol2smi(request): + """ + convert MOL2 file to SMILES + """ mol_string = request.GET.get('molString') smiles_string = mol2smi(mol_string) resp = {'smiles': smiles_string} @@ -529,6 +538,10 @@ def convert_mol2smi(request): def convert_smi2mol(request): + """ + convert SMILES file to MOL2 + (and generate 2D coordinates) + """ smi_string = request.GET.get('smiString') mol_string = smi2mol(smi_string) resp = {'mol': mol_string}