Better Depictions with Ogham
Better Depictions with Ogham
Better Depictions with Ogham
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
CUP XI. Santa Fe<br />
Bob Tolbert<br />
VP, Development<br />
April 19, 2010
• Current version<br />
– Single pixel lines <strong>with</strong> BMP output<br />
– Poor fonts<br />
– Decent coordinate generation<br />
– Core API in ints not floats<br />
• <strong>Ogham</strong> 2.0 plans<br />
• Using native graphics in Python, Java, .Net<br />
CUP XI. Santa Fe<br />
<strong>Ogham</strong><br />
April 19, 2010
• Replace OEDepictView <strong>with</strong> OEMolView<br />
– More straightforward access to atom and bond properties<br />
• Replace OEDepictBase <strong>with</strong> OEImageBase<br />
– Replace int <strong>with</strong> float API<br />
• OEPen for user-defined line properties<br />
– Including width<br />
<strong>Ogham</strong> 2.0<br />
• Older classes will stay around for backward compatibility<br />
CUP XI. Santa Fe<br />
April 19, 2010
• Much work on layout algorithm to remove clashes<br />
– Send us your clashing structure<br />
• Many new built-in ring templates<br />
• Working “aligned” depictions<br />
– Current version has severe limitations<br />
– Can’t align to part of a ring system<br />
• User-defined templates<br />
CUP XI. Santa Fe<br />
<strong>Ogham</strong> 2.0<br />
April 19, 2010
• C++ - Qt<br />
– <strong>Depictions</strong> in VIDA<br />
• Python – PyCairo<br />
– mol2png web service<br />
• Java – Graphics2D<br />
– Mol2Img.java<br />
• .Net – System.Drawing.Drawing2D<br />
CUP XI. Santa Fe<br />
Using Native Graphics<br />
April 19, 2010
• Cairo – LGPL library for low-level 2D graphics<br />
– Part of GTK/GNOME project<br />
• PyCairo – Python wrapper for Cairo<br />
– Usually installable via yum or apt-get on Linux<br />
– Installation a bit of a pain on Windows<br />
CUP XI. Santa Fe<br />
PyCairo<br />
April 19, 2010
import cairo<br />
from openeye.oechem import *<br />
from openeye.oedepict import *<br />
class OECairoImage(OEDepictBase):<br />
def __init__(self, ctx, w, h):<br />
CUP XI. Santa Fe<br />
OEDepictBase.__init__(self)<br />
self.context = ctx<br />
Derive new class from OEDepictBase<br />
self.context.set_line_cap(cairo.LINE_CAP_ROUND)<br />
self.context.select_font_face("monospace",<br />
cairo.FONT_SLANT_NORMAL,<br />
cairo.FONT_WEIGHT_BOLD)<br />
ctx is a PyCairo context<br />
Set some default style information<br />
April 19, 2010
def DrawLine(self, x1, y1, x2, y2, c):<br />
self.SetColor(c)<br />
self.context.move_to(x1, y1)<br />
self.context.line_to(x2, y2)<br />
self.context.stroke()<br />
def DrawString(self, x, y, str, c):<br />
self.SetFont()<br />
self.SetColor(c)<br />
self.context.move_to(x,y-self.offset)<br />
self.context.show_text(str)<br />
Overload as many methods as you can for the best native performance<br />
CUP XI. Santa Fe<br />
Add some overloads<br />
April 19, 2010
import cairo<br />
from openeye.oechem import *<br />
from openeye.oedepict import *<br />
from OECairoImage import OECairoImage<br />
. . .<br />
def main(args, interfaceData):<br />
. . .<br />
WIDTH = itf.GetInt("-w")<br />
HEIGHT = itf.GetInt("-h")<br />
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,WIDTH,HEIGHT)<br />
ctx = cairo.Context (surface)<br />
img = OECairoImage(ctx, WIDTH, HEIGHT)<br />
CUP XI. Santa Fe<br />
mol2png.py<br />
Declare a PyCairo image and then pass to OECairoImage ctor<br />
April 19, 2010
view = OEDepictView()<br />
…set up OEDepictView options<br />
# set some atoms to be selected by SMARTS<br />
setSelected(mol, SMARTS)<br />
view.SetMolecule(mol)<br />
# render the image<br />
view.RenderImage(img)<br />
# draw transparent selection on top<br />
drawSelected(view, ctx, (0.0,1.0,0.0,0.3))<br />
CUP XI. Santa Fe<br />
mol2png.py (part 2)<br />
RGBA color<br />
To draw directly to the context<br />
To access molecule information and view coordinates<br />
April 19, 2010
def setSelected(mol, smarts):<br />
if smarts:<br />
pat=OESubSearch()<br />
selectedAtoms=set()<br />
bondedAtoms=set()<br />
if not pat.Init(smarts):<br />
CUP XI. Santa Fe<br />
print "Invalid smarts: \"%s\""%smarts<br />
return<br />
for match in pat.Match(mol):<br />
for a in match.GetTargetAtoms():<br />
selectedAtoms.add(a)<br />
a.SetBoolData("atom_selected", True)<br />
for match in pat.Match(mol):<br />
for b in match.GetTargetBonds():<br />
b.SetBoolData("selected",True)<br />
bondedAtoms.add(b.GetBgn())<br />
bondedAtoms.add(b.GetEnd())<br />
selectedAtoms -= bondedAtoms<br />
for a in selectedAtoms:<br />
a.SetBoolData("selected", True)<br />
setSelected<br />
April 19, 2010
def drawSelected(view, ctx, rgb):<br />
ctx.push_group()<br />
ctx.set_source_rgba(rgb[0], rgb[1], rgb[2], 1.0)<br />
for bond in view.GetMolecule().GetBonds():<br />
if bond.HasData("selected"):<br />
a1 = bond.GetBgn()<br />
astyle1 = view.AStyle(a1.GetIdx())<br />
a2 = bond.GetEnd()<br />
astyle2 = view.AStyle(a2.GetIdx())<br />
if astyle1.hidden or astyle2.hidden:<br />
continue<br />
xyz1 = view.GetViewCoords(view.GetMolecule(), a1)<br />
drawSelected<br />
xyz2 = view.GetViewCoords(view.GetMolecule(), a2)<br />
ctx.set_line_width(view.GetFontSize()*SELECTION_WIDTH_SCALE)<br />
ctx.move_to(xyz1[0], xyz1[1])<br />
ctx.line_to(xyz2[0], xyz2[1])<br />
ctx.stroke()<br />
ctx.pop_group_to_source()<br />
ctx.paint_<strong>with</strong>_alpha(rgb[3])<br />
Draw transparent – alpha < 1.0<br />
CUP XI. Santa Fe<br />
Loop over the selected bonds<br />
Draw a wide line<br />
April 19, 2010
class Root(object):<br />
def depict(self, *args, **kwargs):<br />
cherrypy.response.headers['Content-Type'] = "image/png"<br />
return depictWeb(kwargs)<br />
depict.exposed=True<br />
def main():<br />
root=Root()<br />
cherrypy.quickstart(root)<br />
Uses CherryPy web service<br />
Start a server and expose “depict” as a REST URL.<br />
CUP XI. Santa Fe<br />
mol2png_server.py<br />
April 19, 2010
def depictWeb(query):<br />
. . . .<br />
import cStringIO<br />
buffer = cStringIO.StringIO()<br />
surface.write_to_png(buffer)<br />
png_string=buffer.getvalue()<br />
buffer.close()<br />
return [png_string]<br />
mol2png_server.py (part 2)<br />
Draw to PyCairo surface, write to buffer in memory, return as PNG.<br />
CUP XI. Santa Fe<br />
April 19, 2010
CUP XI. Santa Fe<br />
mol2png_server demo<br />
April 19, 2010
public class OEJavaMolDepiction extends OEDepictBase {<br />
protected Graphics2D g2;<br />
public OEJavaMolDepiction(Graphics g, int w, int h) {<br />
g2 = (Graphics2D) g;<br />
}<br />
CUP XI. Santa Fe<br />
width = w;<br />
height = h;<br />
Java2DMolDepiction -<br />
derives from OEDepictBase<br />
contains Java Graphics2D object<br />
OEJavaMolDepiction.java<br />
April 19, 2010
BufferedImage bi = new BufferedImage(w, h,<br />
BufferedImage.TYPE_INT_RGB);<br />
Graphics2D g2 = bi.createGraphics();<br />
OEJavaMolDepiction img = new OEJavaMolDepiction(g2, w, h);<br />
Draw(img, w, h);<br />
WriteImage(outputfile, bi);<br />
CUP XI. Santa Fe<br />
Mol2Img.java<br />
April 19, 2010
For more information, please contact us.<br />
business@eyesopen.com<br />
support@eyesopen.com<br />
www.eyesopen.com<br />
505-473-7385<br />
CUP XI. Santa Fe<br />
April 19, 2010