OEViz - A Simple Depiction Web Service
Problem
You want to generate OEDepict images from SMILES using your web browser. This examples works in Python 2 & 3.
Ingredients
|
Difficulty Level
Solution
Flask is a web microframework for Python. It allows you to create a web server with ease. Using Flask and OEDepict TK we can generate images based on input from a web page. This simple example has a single web page built using Bootstrap and JavaScript to update the image after every keystroke. From within Flask we generate images like you normally do with Python.
Usage:
The code for this example is on GitHub, as it requires multiple files. You must clone the code from https://github.com/oess/python-cookbook-simple-oeviz/. Learn more about GitHub here. From the command line run:
prompt > git clone https://github.com/oess/python-cookbook-simple-oeviz/
After cloning you should create a Python virtualenv environment which includes the OpenEye Python Toolkit and Flask. Flask can be installed with pip install flask. Finally start the Flask web server:
(myvirtualenv) prompt > python simpe-oeviz.py
Now visit http://127.0.0.1:5000 with your browser and enter a SMILES string to visualize it.
Discussion
OERenderMolecule writes a file, this is not required on a web server, as writing and then reading the file adds an unnecessary step. Instead you build your image up then write it to a string using OEWriteImageToString then return this directly to the browser with a MIME type and it will render the file for you.
There are two main functions in simple-oeviz.py
. The first is depict()
which tells Flask that when someone requests
the route of the website, /
, to render the template oeviz.html
. You can find this file in the templates directory, it is
HTML, CSS and JavaScript.
@app.route('/')
def depict():
""" Return a simple HTML file """
return render_template('oeviz.html')
depict_smiles()
is where OEDepict TK comes in. When /smiles/<smiles>/
is requested by the browser Flask will call
this function. It passes the value of smiles as a variable where OESmilesToMol will attempt to parse the value. If it
is a valid SMILES strings we depict the molecule, if it is not we place an error message on the OEImage we have already
created. Finally we return this to the browser with MIME information so it knows the data should be treated as an SVG
image. You will notice the SMILES string is wrapped with an unquote
, this is to escape URL encodings for example #
will become %23
, which is not valid SMILES notation.
@app.route('/smiles/<smiles>/')
def depict_smiles(smiles):
""" OEChem and OEDepict image generation """
# Image to draw on
image = OEImage(400, 400)
# Process SMILES
mol = OEGraphMol()
parsed = OESmilesToMol(mol, str(unquote(smiles)))
if parsed:
# Create image of molecule
OEPrepareDepiction(mol)
OERenderMolecule(image, mol)
else:
# Create error image
font = OEFont(OEFontFamily_Helvetica, OEFontStyle_Default, 20,
OEAlignment_Center, OERed)
image.DrawText(OE2DPoint(image.GetWidth()/2.0, image.GetHeight()/2.0),
'Your SMILES is not valid', font)
img_content = OEWriteImageToString('svg', image)
return Response(img_content, mimetype='image/svg+xml')
We use JavaScript, static/oeviz.js
, to listen to the keystrokes in the text box. After each keystroke it sends the
contents to the SMILES API and returns the response to the img tag in the HTML, which displays the image to the user,
either a valid molecule or an error message.
See also in Flask manual
Theory
API
flask.Flask class
render_template class
Response class
See also in OEDepict TK manual
Theory
Molecule depiction section
API
OEImage class
OE2DMolDisplayOptions class
OE2DMolDisplay class
OERenderMolecule function
OEPrepareDepiction function
OEWriteImageToString function