Skip to content

Instantly share code, notes, and snippets.

@sunhwan
Last active January 29, 2021 19:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sunhwan/85e9833534d7a2746423978a8c196dcd to your computer and use it in GitHub Desktop.
Save sunhwan/85e9833534d7a2746423978a8c196dcd to your computer and use it in GitHub Desktop.
import argparse
import re
import base64
from io import BytesIO
import cairosvg
from rdkit import Chem
from rdkit.Chem import AllChem
from rdkit.Chem.Draw import rdMolDraw2D
from rdkit.Chem.Draw.MolDrawing import MolDrawing, DrawingOptions #Only needed if modifying defaults
DrawingOptions.atomLabelFontSize = 55
DrawingOptions.dotsPerAngstrom = 100
DrawingOptions.bondLineWidth = 2.0
def sdf_to_html(mols, fields, use_js, add_smiles=False):
atoms_prop = re.compile(r'atom\.[a-z]?prop\.')
rows = []
nl = "\n"
for i, m in enumerate(mols):
_m = Chem.RemoveHs(m)
AllChem.Compute2DCoords(_m)
if i == 0:
# print header
keys = m.GetPropsAsDict().keys()
# add 'mol' at the front to print molecular structure first
# also remove atom.prop.XXX
keys = ['mol'] + [k for k in keys if not atoms_prop.match(k)]
if fields != 'all':
keys = [k for k in keys if k == 'mol' or k in fields.split(',')]
cols = []
props = m.GetPropsAsDict()
# always print entry number and mol name
cols.append(f"<th>No</th>")
cols.append(f"<th>Name</th>")
if add_smiles:
cols.append(f"<th>SMILES</th>")
for k in keys:
cols.append(f'<th>{k}</th>')
row = f"""<thead><tr>{nl.join(cols)}</tr></thead>"""
rows.append(row)
cols = []
# always print entry number and mol name
cols.append(f"<td>{i+1}</td>")
cols.append(f"<td>{m.GetProp('_Name')}</td>")
if add_smiles:
cols.append(f"<td>{Chem.MolToSmiles(m)}</td>")
props = m.GetPropsAsDict()
for k in keys:
if k == 'mol':
drawer = rdMolDraw2D.MolDraw2DSVG(300, 200)
drawer.DrawMolecule(_m)
drawer.FinishDrawing()
svg = drawer.GetDrawingText()
cols.append(f"""<td>{svg}</td>""")
else:
cols.append(f'<td>{props.get(k, "")}</td>')
row = f"""<tr>{nl.join(cols)}</tr>"""
rows.append(row)
header = ""
footer = ""
if use_js:
header = """
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.css">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.js"></script>
"""
footer = """
<script>
$(document).ready( function () {
$('#table').DataTable({
paging: false
});
} );
</script>
"""
table = f"""
{header}
<table id="table">{nl.join(rows)}</table>
{footer}
"""
return table
def main():
parser = argparse.ArgumentParser(description='Process SDF file into a HTML table')
parser.add_argument('sdfile', help='SDF file')
parser.add_argument('--fields', default="all", help='fields to print')
parser.add_argument('--smiles', action="store_true", help='add SMILES field')
parser.add_argument('--js', default=True, help='fields to print')
args = parser.parse_args()
sdfile = args.sdfile
mols = Chem.SDMolSupplier(sdfile, removeHs=False)
html = sdf_to_html(mols, args.fields, args.js, args.smiles)
print(html)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment