Merge pull request #12 from navanchauhan/rdkit-api
added Molecule Properties and Alerts
This commit is contained in:
commit
db5234cb8b
13
app/misc.ini
13
app/misc.ini
|
@ -13,4 +13,15 @@ DB02 = Unknown Hostname, failed to connect to the database.
|
||||||
|
|
||||||
CW01 = Looks like an invalid PDB ID
|
CW01 = Looks like an invalid PDB ID
|
||||||
|
|
||||||
PC00 = Could not find any compound on PubChem matching the query.
|
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
|
|
@ -29,6 +29,15 @@
|
||||||
<li class="{{ 'nav-item active' if active_page == 'about' else 'nav-item' }}">
|
<li class="{{ 'nav-item active' if active_page == 'about' else 'nav-item' }}">
|
||||||
<a class="nav-link" href="{{ url_for('about') }}">About</a>
|
<a class="nav-link" href="{{ url_for('about') }}">About</a>
|
||||||
</li>
|
</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' }}">
|
<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">
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
Dock and Report
|
Dock and Report
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<h2>Curie Web Demo</h2>
|
<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>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>
|
<p>The following are the currently active modules</p>
|
||||||
<h3>Docking</h3>
|
<h3>Dock and Generate Reports</h3>
|
||||||
<ul>
|
<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_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>
|
<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>
|
<li><a href="{{ url_for('generate') }}">Generate</a> - You can use this to generate completely new compounds</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h3>Researching</h3>
|
<h3>Research</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ url_for('pubmed') }}">PubMed Search</a> - Handy PubMed search with direct download links</li>
|
<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><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>
|
<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>
|
</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>
|
<h3>Misc.</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>API - <a href="/docs">Swagger UI</a> or <a href="/redoc">ReDoc</a> - API access for the server</li>
|
<li>API - <a href="/docs">Swagger UI</a> or <a href="/redoc">ReDoc</a> - API access for the server</li>
|
||||||
|
|
|
@ -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 %}
|
90
app/views.py
90
app/views.py
|
@ -17,6 +17,8 @@ import subprocess
|
||||||
import mysql.connector as con
|
import mysql.connector as con
|
||||||
from mysql.connector.errors import InterfaceError,DatabaseError
|
from mysql.connector.errors import InterfaceError,DatabaseError
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
@ -31,6 +33,8 @@ import configparser
|
||||||
misc = configparser.ConfigParser()
|
misc = configparser.ConfigParser()
|
||||||
misc.read('app/misc.ini')
|
misc.read('app/misc.ini')
|
||||||
errors = misc['ERRORS']
|
errors = misc['ERRORS']
|
||||||
|
AlertSMARTS = misc['ALERT_SMARTS']
|
||||||
|
AlertDescription = misc['ALERT_DESCRIPTION']
|
||||||
|
|
||||||
base = os.getcwd()
|
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',result=search,form=form)
|
||||||
return render_template('search-pubchem.html',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'])
|
@app.route('/Status',methods=['GET','POST'])
|
||||||
def status():
|
def status():
|
||||||
taskStatusForm = statusForm()
|
taskStatusForm = statusForm()
|
||||||
|
@ -426,4 +471,47 @@ def page_not_found(error):
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(debug=True, host="0.0.0.0", port="8080")
|
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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue