27.08.2013 Views

Better Depictions with Ogham

Better Depictions with Ogham

Better Depictions with Ogham

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!