Commit 19aa824d authored by Hervé  MENAGER's avatar Hervé MENAGER
Browse files

refactor annotations to compound queryset to the model level

this is mainly to be used in compounds list, but will ultimately be
useful everywhere


Former-commit-id: 720068133a0e7c7f5d9bd562d77467ab70d0c477
parent 74a9218e
......@@ -6,8 +6,11 @@ from __future__ import unicode_literals
import operator
from django.db import models
from django.db.models import Max
from django.conf import settings
from django.db.models import Max, Min, Count, F, Q
from django.db.models.functions import Cast
from django.db.models import FloatField
from .utils import FingerPrinter, smi2inchi, smi2inchikey
from .ws import get_pubmed_info, get_google_patent_info, get_uniprot_info, get_taxonomy_info, get_go_info, get_pfam_info
......@@ -268,7 +271,22 @@ class PpiComplex(models.Model):
return 'PPI {}, Complex {} ({})'.format(self.ppi, self.complex, self.cc_nb)
class CompoundManager(models.Manager):
def get_queryset(self):
qs = super().get_queryset()
# with number of publications
qs = qs.annotate(pubs=Count('refcompoundbiblio', distinct=True))
# with best activity
qs = qs.annotate(best_activity=Max('compoundactivityresult__activity'))
# with LE
qs = qs.annotate(le=Cast(1.37 * Max('compoundactivityresult__activity') / F('nb_atom_non_h'),FloatField()))
# with LLE
qs = qs.annotate(lle=Cast(Max('compoundactivityresult__activity') - F('a_log_p'),FloatField()))
return qs
class Compound(AutoFillableModel):
objects = CompoundManager()
canonical_smile = models.TextField(
'Canonical Smile', unique=True)
is_macrocycle = models.BooleanField('Contains one or more macrocycles')
......@@ -454,26 +472,6 @@ class Compound(AutoFillableModel):
return None
return self.compoundactivityresult_set.filter(activity=best_pXC50_activity)[0]
@property
def le(self):
"""
LE: Ligand Efficiency
"""
best_pXC50_activity = self.best_pXC50_activity
if best_pXC50_activity is None:
return None
return (1.37 * float(best_pXC50_activity))/self.nb_atom_non_h
@property
def lle(self):
"""
LLE: Lipophilic Efficiency
"""
best_pXC50_activity = self.best_pXC50_activity
if best_pXC50_activity is None:
return None
return float(best_pXC50_activity - self.a_log_p)
@property
def best_pXC50_activity_ppi_name(self):
"""
......
......@@ -63,9 +63,9 @@
Activity and Efficiencies
</button>
<div class="dropdown-menu" aria-labelledby="aeMenuButton">
{% include "modal_open_button.html" with label="Best Activity" param_name="qs_ba" %}
{% include "modal_open_button.html" with label="LE" param_name="qs_le" %}
{% include "modal_open_button.html" with label="LLE" param_name="qs_lle" %}
{% include "modal_open_button.html" with label="Best Activity" param_name="best_activity" %}
{% include "modal_open_button.html" with label="LE" param_name="le" %}
{% include "modal_open_button.html" with label="LLE" param_name="lle" %}
</div>
</div>
<div class="dropdown btn-group" style="display: inline-flex;">
......@@ -125,7 +125,7 @@
<div class="m-2 d-flex justify-content-between">
<span>{{ paginator.count }} compounds</span>
{% if selected_family or selected_ppi or selected_disease or selected_taxonomy or selected_boundcomplex or molecular_weight or a_log_p or nb_donor_h or nb_acceptor_h or tpsa or nb_rotatable_bonds or nb_aromatic_sssr or nb_chiral_centers or fsp3 or pubs or similar_to or qs_ba or qs_le or qs_lle %}
{% if selected_family or selected_ppi or selected_disease or selected_taxonomy or selected_boundcomplex or molecular_weight or a_log_p or nb_donor_h or nb_acceptor_h or tpsa or nb_rotatable_bonds or nb_aromatic_sssr or nb_chiral_centers or fsp3 or pubs or similar_to or best_activity or le or lle %}
<span>
&nbsp;-&nbsp;filters:&nbsp;
{% if selected_family %}
......@@ -183,14 +183,14 @@
{% if similar_to %}
{% include "similarity_badge.html" with param_name="similar_to" param_value=similar_to_query param_label="Similar to " %}
{% endif %}
{% if qs_ba %}
{% include "slider_badge.html" with param_name="qs_ba" param_value_min=qs_ba_value_min param_value_max=qs_ba_value_max param_label="Best Act." %}
{% if best_activity %}
{% include "slider_badge.html" with param_name="best_activity" param_value_min=best_activity_value_min param_value_max=best_activity_value_max param_label="Best Act." %}
{% endif %}
{% if qs_le %}
{% include "slider_badge.html" with param_name="qs_le" param_value_min=qs_le_value_min param_value_max=qs_le_value_max param_label="LE" %}
{% if le %}
{% include "slider_badge.html" with param_name="le" param_value_min=le_value_min param_value_max=le_value_max param_label="LE" %}
{% endif %}
{% if qs_lle %}
{% include "slider_badge.html" with param_name="qs_lle" param_value_min=qs_lle_value_min param_value_max=qs_lle_value_max param_label="LLE" %}
{% if lle %}
{% include "slider_badge.html" with param_name="lle" param_value_min=lle_value_min param_value_max=lle_value_max param_label="LLE" %}
{% endif %}
</span>
{% endif %}
......@@ -261,8 +261,8 @@
{% include "slider_modal.html" with label="FSP3" param_name="fsp3" param_min=fsp3_min param_max=fsp3_max param_value=fsp3 param_value_min=fsp3_value_min param_value_max=fsp3_value_max step='0.1' param_label='Select a cutoff value for the FSP3 of the compounds to be selected'%}
{% include "slider_modal.html" with label="Publications" param_name="pubs" param_min=pubs_min param_max=pubs_max param_value=pubs param_value_min=pubs_value_min param_value_max=pubs_value_max step='1' param_label='Select a cutoff value for the number of publications mentioning the compounds to be selected'%}
{% include "marvinjs_modal.html" with smiles=similar_to_query fingerprint=similar_to_fingerprint %}
{% include "slider_modal.html" with label="Best Activiry" param_name="qs_ba" param_min=qs_ba_min param_max=qs_ba_max param_value=qs_ba param_value_min=qs_ba_value_min param_value_max=qs_ba_value_max step='1' param_label='Select a cutoff value for the best activity of the compounds to be selected'%}
{% include "slider_modal.html" with label="LE" param_name="qs_le" param_min=qs_le_min param_max=qs_le_max param_value=qs_le param_value_min=qs_le_value_min param_value_max=qs_le_value_max step='0.1' param_label='Select a cutoff value for the LE of the compounds to be selected'%}
{% include "slider_modal.html" with label="LLE" param_name="qs_lle" param_min=qs_lle_min param_max=qs_lle_max param_value=qs_lle param_value_min=qs_lle_value_min param_value_max=qs_lle_value_max step='1' param_label='Select a cutoff value for the LLE of the compounds to be selected'%}
{% include "slider_modal.html" with label="Best Activiry" param_name="best_activity" param_min=best_activity_min param_max=best_activity_max param_value=best_activity param_value_min=best_activity_value_min param_value_max=best_activity_value_max step='1' param_label='Select a cutoff value for the best activity of the compounds to be selected'%}
{% include "slider_modal.html" with label="LE" param_name="le" param_min=le_min param_max=le_max param_value=le param_value_min=le_value_min param_value_max=le_value_max step='0.1' param_label='Select a cutoff value for the LE of the compounds to be selected'%}
{% include "slider_modal.html" with label="LLE" param_name="lle" param_min=lle_min param_max=lle_max param_value=lle param_value_min=lle_value_min param_value_max=lle_value_max step='1' param_label='Select a cutoff value for the LLE of the compounds to be selected'%}
{% endblock %}
......@@ -20,7 +20,7 @@
{% include "compound_t_colhead.html" with col_id="nb_chiral_centers" col_name="R/S" col_title="Number of chiral centers" %}
{% include "compound_t_colhead.html" with col_id="le" col_name="LE" col_title="Ligand Efficiency" %}
{% include "compound_t_colhead.html" with col_id="lle" col_name="LLE" col_title="Lipophilic Efficiency" %}
{% include "compound_t_colhead.html" with col_id="qs_ba" col_name="Best Activity" col_title="Best pXC50 Activity" %}
{% include "compound_t_colhead.html" with col_id="best_activity" col_name="Best Activity" col_title="Best pXC50 Activity" %}
<button type="button" class="btn btn-primary float-right" style="width: inherit!important" data-toggle="modal" data-target="#selectColumns">
<i class="fa fa-columns" title="customize columns"></i>
</button>
......@@ -84,8 +84,8 @@
{% if "lle" in fields %}
<td scope="col">{{ compound.lle|floatformat:2 }}</td>
{% endif %}
{% if "qs_ba" in fields %}
<td scope="col">{{ compound.qs_ba|floatformat:2 }}</td>
{% if "best_activity" in fields %}
<td scope="col">{{ compound.best_activity|floatformat:2 }}</td>
{% endif %}
</tr>
{% endfor %}
......@@ -155,7 +155,7 @@
<label><input type="checkbox" name="field" value="lle" class="mr-1" {% if 'lle' in fields %}checked="checked"{% endif %} />Lipophilic Efficiency</label>
</div>
<div class="row">
<label><input type="checkbox" name="field" value="qs_ba" class="mr-1" {% if 'qs_ba' in fields %}checked="checked"{% endif %} />Best pXC50 Activity</label>
<label><input type="checkbox" name="field" value="best_activity" class="mr-1" {% if 'best_activity' in fields %}checked="checked"{% endif %} />Best pXC50 Activity</label>
</div>
</div>
<div class="modal-footer">
......
......@@ -279,19 +279,6 @@ class CompoundRangeFilterHandler(object):
queryset = queryset.filter(**filter_dict)
# max and min value are the max and min for
qs = Compound.objects
# annotate
# with number of publications
if self.parameter_name == 'pubs':
qs = qs.annotate(pubs=Count('refcompoundbiblio', distinct=True))
# with best activity
elif self.parameter_name == 'qs_ba':
qs = qs.annotate(qs_ba=Max('compoundactivityresult__activity'))
# with LE
elif self.parameter_name == 'qs_le':
qs = qs.annotate(qs_le=Cast(1.37 * Max('compoundactivityresult__activity') / F('nb_atom_non_h'),FloatField()))
# with LLE
elif self.parameter_name == 'qs_lle':
qs = qs.annotate(qs_lle=Cast(Max('compoundactivityresult__activity') - F('a_log_p'),FloatField()))
self.filter_context[self.parameter_name+'_max'] = self.get_max(qs)
self.filter_context[self.parameter_name+'_min'] = self.get_min(qs)
return queryset
......@@ -344,7 +331,7 @@ class CompoundListView(ListView):
table_view_default_fields = ['id', 'canonical_smiles', 'common_name', 'molecular_weight', 'a_log_p', 'compound_action_ligand_ids', 'pubs']
sort_by_option_ids = ['id', 'molecular_weight', 'a_log_p', 'nb_aromatic_sssr', 'nb_chiral_centers', 'pubs', 'qs_le', 'qs_lle', 'qs_ba']
sort_by_option_ids = ['id', 'molecular_weight', 'a_log_p', 'nb_aromatic_sssr', 'nb_chiral_centers', 'pubs', 'le', 'lle', 'best_activity']
def get_ordering(self):
# sort by options
......@@ -353,11 +340,11 @@ class CompoundListView(ListView):
for sort_by_option_id in self.sort_by_option_ids:
if sort_by_option_id == 'pubs':
name = 'Number of publications'
elif sort_by_option_id == 'qs_le':
elif sort_by_option_id == 'le':
name = 'Ligand Efficiency'
elif sort_by_option_id == 'qs_lle':
elif sort_by_option_id == 'lle':
name = 'Lipophilic Efficiency'
elif sort_by_option_id == 'qs_ba':
elif sort_by_option_id == 'best_activity':
name = 'Best Activity'
else:
name = compound_fields.get(sort_by_option_id)
......@@ -397,15 +384,6 @@ class CompoundListView(ListView):
self.filter_context = {}
# get queryset
qs = super().get_queryset()
# annotate
# with number of publications
qs = qs.annotate(pubs=Count('refcompoundbiblio', distinct=True))
# with best activity
qs = qs.annotate(qs_ba=Max('compoundactivityresult__activity'))
# with LE
qs = qs.annotate(qs_le=Cast(1.37 * Max('compoundactivityresult__activity') / F('nb_atom_non_h'),FloatField()))
# with LLE
qs = qs.annotate(qs_lle=Cast(Max('compoundactivityresult__activity') - F('a_log_p'),FloatField()))
# add filters
cfhs = [\
CompoundListFilterHandler(PpiFamily, 'compoundaction__ppi__family', 'ppi__compoundaction__compound', 'family', self.filter_context, self.request.GET),
......@@ -423,9 +401,9 @@ class CompoundListView(ListView):
CompoundRangeFilterHandler('nb_chiral_centers', self.filter_context, self.request.GET),
CompoundRangeFilterHandler('fsp3', self.filter_context, self.request.GET, 0.1),
CompoundRangeFilterHandler('pubs', self.filter_context, self.request.GET),
CompoundRangeFilterHandler('qs_ba', self.filter_context, self.request.GET),
CompoundRangeFilterHandler('qs_le', self.filter_context, self.request.GET, 0.1),
CompoundRangeFilterHandler('qs_lle', self.filter_context, self.request.GET),
CompoundRangeFilterHandler('best_activity', self.filter_context, self.request.GET),
CompoundRangeFilterHandler('le', self.filter_context, self.request.GET, 0.1),
CompoundRangeFilterHandler('lle', self.filter_context, self.request.GET),
ExistsFilterHandler('pubchem_id', self.filter_context, self.request.GET),
ExistsFilterHandler('chemspider_id', self.filter_context, self.request.GET),
ExistsFilterHandler('chembl_id', self.filter_context, self.request.GET),
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment