Merge pull request #12 from navanchauhan/rdkit-api

added Molecule Properties and Alerts
This commit is contained in:
Navan Chauhan 2020-10-17 18:24:47 +05:30 committed by GitHub
commit db5234cb8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 184 additions and 4 deletions

View File

@ -14,3 +14,14 @@ 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

View File

@ -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

View File

@ -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>

View File

@ -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 %}

View File

@ -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()
@ -427,3 +472,46 @@ 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