aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNavan Chauhan <navanchauhan@gmail.com>2020-10-17 18:22:35 +0530
committerNavan Chauhan <navanchauhan@gmail.com>2020-10-17 18:22:35 +0530
commit426d6e460b36690e8fbbc0d09ad34e7bacade61a (patch)
tree4c9d293e68bd106c4c53eb06e76c634d585beb8c
parent16316fa24cbc9b66a1dbcf9fd8e18506c35d7b91 (diff)
added Molecule Properties and Alerts
-rw-r--r--app/misc.ini13
-rw-r--r--app/templates/base.html9
-rw-r--r--app/templates/home.html10
-rw-r--r--app/templates/mol-characteristics.html66
-rw-r--r--app/views.py90
5 files changed, 184 insertions, 4 deletions
diff --git a/app/misc.ini b/app/misc.ini
index c474556..9587e56 100644
--- a/app/misc.ini
+++ b/app/misc.ini
@@ -13,4 +13,15 @@ DB02 = Unknown Hostname, failed to connect to the database.
CW01 = Looks like an invalid PDB ID
-PC00 = Could not find any compound on PubChem matching the query. \ No newline at end of file
+PC00 = Could not find any compound on PubChem matching the query.
+
+RD00 = Failed to import RDKit.
+RD01 = Could not convert SMILES to molecule, please check the SMILES
+
+[ALERT_SMARTS]
+ESTER = [#6][CX3](=O)[OX2H0][#6]
+ANILINE = [NX3][$(C=C),$(cc)]
+
+[ALERT_DESCRIPTION]
+ESTER = The given compound contains Ester. For more details read the paper.
+ANILINE = None \ No newline at end of file
diff --git a/app/templates/base.html b/app/templates/base.html
index e4ae447..0936f80 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -29,6 +29,15 @@
<li class="{{ 'nav-item active' if active_page == 'about' else 'nav-item' }}">
<a class="nav-link" href="{{ url_for('about') }}">About</a>
</li>
+ <li class="{{ 'nav-item dropdown active' if active_page == 'analyse' else 'nav-item dropdown' }}">
+ <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ Analyse
+ </a>
+ <div class="dropdown-menu" aria-labelledby="navbarDropdown">
+ <a class="dropdown-item" href="{{ url_for('propalert') }}">Property and Alerts</a>
+ <a class="dropdown-item" href="#">Druggability</a>
+ </div>
+ </li>
<li class="{{ 'nav-item dropdown active' if active_page == 'dock' else 'nav-item dropdown' }}">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dock and Report
diff --git a/app/templates/home.html b/app/templates/home.html
index 7e0e352..d67cac7 100644
--- a/app/templates/home.html
+++ b/app/templates/home.html
@@ -5,7 +5,7 @@
<h2>Curie Web Demo</h2>
<p>Curie-Web is a part of The Curie Project which aims to make the process of Computer-Aided Drug Design as fast as possible.</p>
<p>The following are the currently active modules</p>
- <h3>Docking</h3>
+ <h3>Dock and Generate Reports</h3>
<ul>
<li><a href="{{ url_for('dock_manual') }}">Dock and Report (Manual)</a> - You can enter your AutoDock Vina configuration, upload the PDBQT files and it will perform the molecular docking and generate a PDF with proper visualisations and protein-interaction profillings (Using PLIP) </li>
<li><a href="{{ url_for('dock_automatic') }}">Dock and Report (Automatic)</a> - You just enter in the PDB Code, target compound's SMILES structure and name, it will automatically find a binding location and then perform docking and report generation</li>
@@ -16,13 +16,19 @@
<li><a href="{{ url_for('generate') }}">Generate</a> - You can use this to generate completely new compounds</li>
</ul>
- <h3>Researching</h3>
+ <h3>Research</h3>
<ul>
<li><a href="{{ url_for('pubmed') }}">PubMed Search</a> - Handy PubMed search with direct download links</li>
<li><a href="{{url_for('pubchem')}}">PubChem Search</a> - Get Compound SMILES</li>
<li>Qrious App - You can enter a question for a set of papers (e.g. ChemRxiv preprints) and it uses AI to answer it for each individual paper based on their abstract</li>
</ul>
+ <h3>Analyse</h3>
+ <ul>
+ <li><a href="{{ url_for('propalert') }}">Chemical Properties and Alerts</a> - Find Chemical properties and check structure for alerts.</li>
+ <li><a href="#">Druggability</a> - Classify druggability of a compound using a ML Model.</li>
+ </ul>
+
<h3>Misc.</h3>
<ul>
<li>API - <a href="/docs">Swagger UI</a> or <a href="/redoc">ReDoc</a> - API access for the server</li>
diff --git a/app/templates/mol-characteristics.html b/app/templates/mol-characteristics.html
new file mode 100644
index 0000000..c7fc945
--- /dev/null
+++ b/app/templates/mol-characteristics.html
@@ -0,0 +1,66 @@
+{% extends 'base.html' %}
+{% set active_page = "analyse" %}
+{% block main %}
+ <h1>Chemical Properties and Alerts</h1>
+ <form action="{{ url_for('propalert') }}" method="post" enctype="multipart/form-data">
+ {% include 'flash_messages.html' %}
+ {{ form.csrf_token }}
+ <div class="form-row">
+ {{ form.query.label }}
+ {{ form.query(class="form-control")}}
+ </div>
+ <!--<div class="form-row">
+ {\{ form.modelSelection.label }}
+ {\{ form.modelSelection(class="form-control")}}
+ </div>-->
+ <br>
+ <div class="form-row">
+ <button type="submit" class="btn btn-primary">Search</button>
+ </div>
+ </form>
+
+ {% if complete %}
+ <br>
+ <h3>Properties</h3>
+
+ <table class="table table-dark">
+ <thead>
+ <tr>
+ <th scope="col">Property</th>
+ <th scope="col">Value</th>
+ </tr>
+ </thead>
+ {% for x in prop %}
+ <tbody>
+ <tr>
+ <th scope="row">{{x}}</th>
+ <td>{{prop[x]}}</td>
+ </tr>
+ </tbody>
+ {% endfor %}
+ </table>
+
+ {% if perfect %}
+ <h3>No alerts for the given compound.</h3>
+ {% endif %}
+
+ <div class="card-deck row-cols-2">
+ {% for x in range(result|length) %}
+
+ <div class="card" style="width: 18rem;">
+ <div class="card-img-top">
+ {{result[x]["SVG"] | safe }}
+ </div>
+ <div class="card-body">
+ <h5 class="card-title">{{result[x]["Name"]}}</h5>
+ <p class="card-text">{{result[x]["Description"]}}</p>
+ <a href="#" class="btn btn-primary">Read Paper</a>
+ </div>
+ </div>
+ {% endfor %}
+ </div>
+ {% endif %}
+
+
+
+{% endblock %} \ No newline at end of file
diff --git a/app/views.py b/app/views.py
index 47a37ac..bf2d401 100644
--- a/app/views.py
+++ b/app/views.py
@@ -17,6 +17,8 @@ import subprocess
import mysql.connector as con
from mysql.connector.errors import InterfaceError,DatabaseError
+
+
import requests
import logging
@@ -31,6 +33,8 @@ import configparser
misc = configparser.ConfigParser()
misc.read('app/misc.ini')
errors = misc['ERRORS']
+AlertSMARTS = misc['ALERT_SMARTS']
+AlertDescription = misc['ALERT_DESCRIPTION']
base = os.getcwd()
@@ -121,6 +125,47 @@ def pubchem():
return render_template('search-pubchem.html',result=search,form=form)
return render_template('search-pubchem.html',form=form)
+@app.route('/Properties',methods=['GET','POST'])
+def propalert():
+ form = PyMedSearch()
+
+ if request.method == 'POST' and form.validate_on_submit():
+ q = form.query.data
+ result = []
+ perfect = False
+ complete = False
+
+ try:
+ from rdkit import Chem
+ except ImportError:
+ return render_template('error.html',code="RD00",description=errors["RD00"])
+
+ if Chem.MolFromSmiles(q.strip()) is None:
+ print("invalid smiles")
+ return render_template('error.html',code="RD01",description=errors["RD01"])
+
+ for alert in AlertSMARTS:
+ print("Checking",alert,AlertSMARTS[alert])
+ records = {}
+ records['Name'] = alert
+ try:
+ records['SVG'] = get_svg(q,AlertSMARTS[alert])
+ except:
+ continue
+ records['Description'] = AlertDescription[alert]
+ result.append(records)
+
+ prop = get_prop(q)
+ print(prop)
+
+ complete = True
+
+ if len(result) == 0:
+ perfect = True
+
+ return render_template('mol-characteristics.html',complete=complete,result=result,form=form,perfect=perfect,prop=prop)
+ return render_template('mol-characteristics.html',form=form)
+
@app.route('/Status',methods=['GET','POST'])
def status():
taskStatusForm = statusForm()
@@ -426,4 +471,47 @@ def page_not_found(error):
if __name__ == '__main__':
- app.run(debug=True, host="0.0.0.0", port="8080") \ No newline at end of file
+ app.run(debug=True, host="0.0.0.0", port="8080")
+
+def get_svg(base,pattern):
+ try:
+ from rdkit.Chem.Draw import rdMolDraw2D
+ from rdkit import Chem
+ except:
+ return None # Need to add logic
+
+ mol = Chem.MolFromSmiles(base)
+ patt = Chem.MolFromSmarts(pattern)
+ hit_ats = list(mol.GetSubstructMatch(patt))
+ hit_bonds = []
+ for bond in patt.GetBonds():
+ aid1 = hit_ats[bond.GetBeginAtomIdx()]
+ aid2 = hit_ats[bond.GetEndAtomIdx()]
+ hit_bonds.append(mol.GetBondBetweenAtoms(aid1,aid2).GetIdx())
+ d = rdMolDraw2D.MolDraw2DSVG(500, 500)
+ rdMolDraw2D.PrepareAndDrawMolecule(d, mol, highlightAtoms=hit_ats, highlightBonds=hit_bonds)
+ return d.GetDrawingText().replace("width='500' height='500'","").replace("width='500px' height='500px'","")
+
+def get_prop(base):
+ try:
+ from rdkit import Chem
+ from rdkit.Chem import Crippen
+ from rdkit.Chem import Descriptors
+ from rdkit.Chem import rdMolDescriptors
+ from rdkit.Chem import Lipinski
+ except:
+ return None # Need to add logic
+ result = {}
+
+ mol = Chem.MolFromSmiles(base)
+ result["cLogP"] = Crippen.MolLogP(mol)
+ result["Molecular Weight"] = Descriptors.MolWt(mol)
+ result["TPSA"] = rdMolDescriptors.CalcTPSA(mol)
+ result["Hydrogen Bond Acceptors"] = Lipinski.NumHAcceptors(mol)
+ result["Hydrogen Bond Donors"] = Lipinski.NumHDonors(mol)
+ result["Rotable Bonds"] = Lipinski.NumRotatableBonds(mol)
+ result["Fraction SP3"] = Lipinski.FractionCSP3(mol)
+
+
+ return result
+