Using SVGs in IPython Notebooks

Sometimes I like working directly with SVGs in order to generate images from code. I like using the IPython Notebook for this because of the instant feedback. Here is an example for creating and viewing a small SVG within the IPython Notebook.

First, import this stuff.

import xml.etree.ElementTree as ET
from IPython.display import SVG

These next functions will create (mostly) equilateral triangles. The 0.866 term is roughly equivalent to sqrt(3)/2, which is the height of a unit side equilateral triangle, or the second-longest side of a 30-60-90 triangle with a hypotenuse equal to one, because trigonometry.

Caveat: these function definitions are pretty arbitrary, I wasn’t planning on using them in a blog post.

def addTriangle( svg, points, fill="gray" ):
    pts = [ str(pt[0])+","+str(pt[1]) for pt in points ]
    pts = " ".join( pts )
    attrib = dict()
    attrib["points"] = pts
    attrib["fill"] = fill
    ET.SubElement( svg, "polygon", attrib )
    return svg

def upTriangle( top=(0,0), side=1 ):
    bottomR = ( top[0]+side/2.0, top[1]+side*0.866 )
    bottomL = ( top[0]-side/2.0, top[1]+side*0.866 )
    return [ top, bottomR, bottomL ]

def dnTriangle( top=(0,0), side=1 ):
    topR = ( top[0]+side/2.0, top[1] )
    topL = ( top[0]-side/2.0, top[1] )
    down = ( top[0], top[1]+side*0.866 )
    return [ down, topR, topL ]

Finally, some code to actually draw something:

width, height = 40, 40
attrib = { 'width':str(width), 'height':str(height) }
svg = ET.Element( 'svg', attrib=attrib )
svg = addTriangle( svg, upTriangle( top=(10,0), side=20 ), "#ff0000" ) # red
svg = addTriangle( svg, dnTriangle( top=(20,0), side=20 ), "#ff9900" ) # orange
svg = addTriangle( svg, upTriangle( top=(30,0), side=20 ), "#ffff00" ) # yellow
svg = addTriangle( svg, dnTriangle( top=(10,20*0.866), side=20 ), "#9900ff" ) # purple
svg = addTriangle( svg, upTriangle( top=(20,20*0.866), side=20 ), "#0000ff" ) # blue
svg = addTriangle( svg, dnTriangle( top=(30,20*0.866), side=20 ), "#33cc33" ) # green
SVG( ET.tostring( svg ) )

This should produce the following SVG:

P.S. This also works with the IJupyter project.