04 June 2009

Fun with SVG: NCBI/pubchem+XSLT= SVG

Just for fun. I've played with the compounds stored in NCBI/Pubchem and I've created a XSLT stylesheet transforming the pubchem/xml format into a SVG figure.
The XSLT stylesheet is available here:

This xml format was new to me, so feel free to tell me if I've missed something...

Here are two examples:
The stylesheet takes a few optional arguments:
  • scale :=scale factor
  • show-bounds := (true/false)
  • xradius := scale factor for atoms


xsltproc --stringparam scale 30 --stringparam xradius 2 --stringparam show-bounds false src/xsl/pubchem2svg.xsl CID_16204538.xml > file.svg

A few points about how it works

First we need to collect the min/max values of each x/y/z coordinate. For example for max-x, we get an ordered list of all the X coordinates and we get the first item.
<xsl:variable name="max-x">
<xsl:for-each select="$x_array/c:PC-Conformer_x_E">
<xsl:sort select="." data-type="number" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="."/>

Then we loop over the index for each atom and we call the template xyz
<xsl:comment>BEGIN ATOMS</xsl:comment>
<xsl:element name="svg:g">
<xsl:call-template name="xyz">
<xsl:with-param name="index" select="1"/>
<xsl:comment>END ATOMS</xsl:comment>

For each index-th atom, the template xyz create a SVG figure for the atom. A call to the templates coord-x and coord-y returns the coordinates (x/y) of this element on the SVG panel.
<xsl:element name="svg:use">
<xsl:attribute name="xlink:href">#atom<xsl:choose>
<xsl:when test="$s='o' or $s='c' or $s='h'"><xsl:value-of select="$s"/></xsl:when>
<xsl:attribute name="x"><xsl:call-template name="coord-x"><xsl:with-param name="index" select="$index"/></xsl:call-template></xsl:attribute>
<xsl:attribute name="y"><xsl:call-template name="coord-y"><xsl:with-param name="index" select="$index"/></xsl:call-template></xsl:attribute>
<xsl:attribute name="title"><xsl:value-of select="$s"/><xsl:text> </xsl:text><xsl:value-of select="$index"/></xsl:attribute>

The template coord-x itself align the coordinate of the atom according to the scale and the width of the SVG panel:
<xsl:template name="coord-x">
<xsl:param name="index"/>
<xsl:variable name="x" select="$x_array/c:PC-Conformer_x_E[$index]"/>
<xsl:value-of select="$margin + ($x - $min-x) * $scale"/>

That's it.


PS: See also the post I wrote one year ago NCBI Blast+ XSLT => XHTML + SVG .


fred said...

Very nice! You could use it to draw fractals...

NamC's blog said...

Hi~ good man. I did it in my macbook. That's great~! Thank you for your post.

Noel O'Boyle said...

FYI, this post has inspired a new feature in Open Babel. See:
http://forums.openbabel.org/SVG-quot-3D-quot-depictions-and-BountySource-td4658815.html and links therein.