added Molecule Properties and Alerts
This commit is contained in:
parent
16316fa24c
commit
426d6e460b
11
app/misc.ini
11
app/misc.ini
|
@ -14,3 +14,14 @@ 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.
|
||||
|
||||
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' }}">
|
||||
<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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
88
app/views.py
88
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()
|
||||
|
@ -427,3 +472,46 @@ def page_not_found(error):
|
|||
|
||||
if __name__ == '__main__':
|
||||
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