<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Depth-First: Tag rjb</title>
    <link>http://depth-first.com/articles/tag/rjb</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Walking the Web of Chemical Informatics</description>
    <item>
      <title>JavaScript for Cheminformatics</title>
      <description>&lt;p&gt;&lt;a href="http://flickr.com/photos/jm999uk/244054409/"&gt;&lt;img src="http://depth-first.com/demo/20080715/rhino.jpg" align="right"&gt;&lt;/img&gt;&lt;/a&gt;Regular readers of this blog know that one of its recurring themes is the convergence of Web technologies and chemical information. Although several articles describe how &lt;a href="http://depth-first.com/articles/tag/ruby"&gt;Ruby&lt;/a&gt; and &lt;a href="http://depth-first.com/articles/tag/java"&gt;Java&lt;/a&gt; can be applied to cheminformatics, one language has never been featured: JavaScript. JavaScript is both the default language of the Web client, and a language of growing importance &lt;a href="http://depth-first.com/articles/2007/05/25/flex-rich-internet-applications-and-cheminformatics"&gt;elsewhere&lt;/a&gt;. This article, the first in a series, introduces JavaScript as a tool for creating rich, chemically-oriented Web applications.&lt;/p&gt;

&lt;h4&gt;Surely You Jest&lt;/h4&gt;

&lt;p&gt;If your last exposure to JavaScript was in the 1990s, a lot has changed for the better. Most importantly, performance has increased considerably, making possible JavaScript software of considerable complexity. A growing collection of well-crafted libraries such as &lt;a href="http://www.prototypejs.org/"&gt;Prototype&lt;/a&gt; and &lt;a href="http://script.aculo.us/"&gt;Scriptaculous&lt;/a&gt; now make it possible to focus precious developer effort at a higher level of abstraction. Although cross-browser compatibility continues to be an issue with browser-specific features, the JavaScript language itself is now remarkably stable and consistent across browsers and platforms.&lt;/p&gt;

&lt;p&gt;JavaScript will obviously never enjoy the performance of Java or C++, and it would be a mistake to assume otherwise. The key is to focus on what JavaScript can do that no other language or platform can. With this thought in mind, it's interesting to speculate on the role JavaScript could play in developing Web-based software for chemistry.&lt;/p&gt;

&lt;p&gt;For example, with essentially complete read-write access to the document object model (DOM) of sites on which they're active, tools based on JavaScript have great potential to enhance static content with content created either on a server or locally.&lt;/p&gt;

&lt;p&gt;As another example, consider the combination of JavaScript and an invisible Java applet. Java-JavaScript communication is possible in all browsers through &lt;a href="http://developer.mozilla.org/en/docs/LiveConnect"&gt;LiveConnect&lt;/a&gt;, which can be used to offload computation-intensive operations from JavaScript to an applet. In many ways, this approach to development on the client resembles the approach, discussed here many times, of using Java from Ruby through &lt;a href="http://depth-first.com/articles/tag/rjb"&gt;Ruby Java Bridge&lt;/a&gt; (RJB) or &lt;a href="http://depth-first.com/articles/tag/jruby"&gt;JRuby&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ultimately, JavaScript is the only programming language that allows cross-browser, client-side software to be written independently of a plugin. This may not sound like a big deal, but for many developers and organizations, Flash, Java, and other plugin technologies are &lt;a href="http://www.javaworld.com/javaworld/jw-05-2008/jw-05-applets.html?page=2"&gt;less than ideal&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;What's Known?&lt;/h4&gt;

&lt;p&gt;There are currently only scattered examples of the use of JavaScript in chemistry, an indication that either the field is ready for this idea, or that it will never work.&lt;/p&gt;

&lt;p&gt;Perhaps the two best-known examples of JavaScript applied to chemical informatics are the &lt;a href="http://depth-first.com/articles/2006/11/09/look-ma-no-applets"&gt;WebME&lt;/a&gt; and &lt;a href="http://pubchem.ncbi.nlm.nih.gov/edit/"&gt;PubChem&lt;/a&gt; chemical structure editors. Although remarkable accomplishments, both packages rely heavily on server back-ends for processing and analysis of chemical structures. The JavaScript code serves mainly to asynchronously pass low-level mouse events to the server, which then asynchronously passes a raster image back to the client. To an extent, the back and forth degrades the responsiveness of these tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blueobelisk.sourceforge.net/wiki/Main_Page"&gt;The Blue Obelisk&lt;/a&gt; maintains a Wiki page discussing some of the uses of &lt;a href="http://blueobelisk.sourceforge.net/wiki/Using_Javascript_and_Greasemonkey_for_Chemistry"&gt;Greasemonkey scripts in chemistry&lt;/a&gt;. Greasemonkey is a wonderful tool for augmenting existing Websites, and these scripts do some remarkable things, but they don't fall into the category of cross-browser, installation-free, general-purpose tools.&lt;/p&gt;

&lt;p&gt;Recently, &lt;a href="http://www.stolaf.edu/people/hansonr/"&gt;Robert Hanson&lt;/a&gt; discussed &lt;a href="http://chemapps.stolaf.edu/jmol/presentations/bcce19/hansonr-bcce19-ajax.ppt"&gt;on-demand Javascript&lt;/a&gt; as a potential tool for building chemistry-oriented Web applications. Although the proposal contains many important points, it has to my knowledge not been followed up with the release of code.&lt;/p&gt;

&lt;p&gt;An early compilation of resources can be found &lt;a href="http://www.ch.ic.ac.uk/java/"&gt;here&lt;/a&gt;, although all of the listed sites have since either disappeared or converted to other content.&lt;/p&gt;

&lt;p&gt;Poking around the Web, it's possible to find many examples of one-off chemistry tools created in JavaScript. For example, &lt;a href="http://chemistry.about.com/od/periodictables/l/bljavaperiodictable.htm"&gt;this page&lt;/a&gt; contains a JavaScript-enabled periodic table. Useful as tools like this may be, they're not general-purpose solutions designed to create a platform for further work.&lt;/p&gt;

&lt;h4&gt;What Would Be Most Valuable?&lt;/h4&gt;

&lt;p&gt;There are many cheminformatics tools that could be built in JavaScript. But to be of the greatest value, a tool should be usable in a variety of contexts. And it should serve as a platform on which more complex software can be built. Even more importantly, the tool should fix something that really is &lt;a href="http://depth-first.com/articles/tag/broken"&gt;broken&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We might begin by asking: what makes chemical information difficult to work with in the greatest number of cases?&lt;/p&gt;

&lt;p&gt;Since the earliest days of chemistry and computers, &lt;a href="http://depth-first.com/articles/2006/09/03/peculiarities-of-chemical-information"&gt;it has been clear&lt;/a&gt; that one of the distinguishing characteristics of chemical information is the central role played by chemical structures and the difficulty in accurately representing and processing them on machines.&lt;/p&gt;

&lt;p&gt;So, one answer to the question of what would be the most useful JavaScript tool for cheminformatics could be: a low-level cheminformatics toolkit that understands chemical structures and their associated graph operations.&lt;/p&gt;

&lt;p&gt;Another possibility: the handling of NMR, IR, UV, and mass spectra. &lt;a href="http://depth-first.com/articles/tag/jspecview"&gt;JSpecView&lt;/a&gt; is a good first choice, but it may be possible to build a pure JavaScript tool for interactively viewing and manipulating spectra, if a low-level toolkit for processing &lt;a href="http://old.iupac.org/standing/cpep/wp_jcamp_dx.html"&gt;JCAMP-DX&lt;/a&gt; were available.&lt;/p&gt;

&lt;p&gt;Would the performance and usability of such toolkits be high enough to make them a serious choice for use in chemistry-driven Web applications? What would the availability of such a toolkit enable that is currently difficult or impossible?&lt;/p&gt;

&lt;h4&gt;Conclusions&lt;/h4&gt;

&lt;p&gt;JavaScript is the default programming language of the Web client, offering a great deal to creators of chemically-oriented applications. One of the biggest barriers to using JavaScript for this purpose is the lack of key developer tools. Future articles will explore this idea.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Image Credit: &lt;a href="http://flickr.com/photos/jm999uk/"&gt;johnmuk&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 15 Jul 2008 08:32:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:212652a1-9a6e-4297-800e-bc62bc301bad</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2008/07/15/javascript-for-cheminformatics</link>
      <category>Tools</category>
      <category>java</category>
      <category>javascript</category>
      <category>toolkit</category>
      <category>platform</category>
      <category>applet</category>
      <category>jruby</category>
      <category>rjb</category>
      <category>client</category>
    </item>
    <item>
      <title>Easily Calculate TPSA Descriptors from SMILES Strings Using Ruby CDK</title>
      <description>&lt;p&gt;&lt;a href="http://ruby-lang.org"&gt;&lt;img src="http://depth-first.com/files/ruby_logo_new.gif" align="right" border="0"&gt;&lt;/img&gt;&lt;/a&gt;A D-F reader wrote in to ask how to calculate Topological Polar Surface Area (TPSA) using &lt;a href="http://depth-first.com/articles/tag/rcdk"&gt;Ruby CDK&lt;/a&gt;. TPSA is one of the most widely-used descriptors for predicting membrane permeability and from it other important ADME properties. This article shows how to calculate TPSA with Ruby using Ruby CDK.&lt;/p&gt;

&lt;h4&gt;The Library&lt;/h4&gt;

&lt;p&gt;Our library consists of nothing more than a few method calls to manipulate the underlying &lt;a href="http://cdk.sf.net"&gt;CDK&lt;/a&gt; library. The &lt;tt&gt;tpsa_for&lt;/tt&gt; method accepts any SMILES string and returns the calculated TPSA:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rubygems&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require_gem&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rcdk&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rcdk/util&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;jrequire&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;org.openscience.cdk.qsar.descriptors.molecular.TPSADescriptor&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;TPSA&lt;/span&gt;
  &lt;span class="attribute"&gt;@@calc&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Org&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Openscience&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Cdk&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Qsar&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Descriptors&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Molecular&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;TPSADescriptor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;tpsa_for&lt;/span&gt; &lt;span class="ident"&gt;smiles&lt;/span&gt;
    &lt;span class="ident"&gt;mol&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;RCDK&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Util&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Lang&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;read_smiles&lt;/span&gt; &lt;span class="ident"&gt;smiles&lt;/span&gt;

    &lt;span class="attribute"&gt;@@calc&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;calculate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;mol&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;getValue&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;doubleValue&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;An Interactive Test&lt;/h4&gt;

&lt;p&gt;Saving the library to a file called &lt;strong&gt;tpsa.rb&lt;/strong&gt; lets us test it through interactive Ruby (irb):&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ irb
irb(main):001:0&gt; require 'tpsa'
./tpsa.rb:2:Warning: require_gem is obsolete.  Use gem instead.
/usr/local/lib/ruby/gems/1.8/gems/rcdk-0.3.0/lib/rcdk/java.rb:26:Warning: require_gem is obsolete.  Use gem instead.
=&gt; true
irb(main):002:0&gt; include TPSA
=&gt; Object
irb(main):003:0&gt; tpsa_for 'COCCc1ccc(OCC(O)CNC(C)C)cc1' # metoprolol
=&gt; 50.72
irb(main):004:0&gt; tpsa_for 'O=C3Nc1ccc(Cl)cc1C(c2ccccc2)=NC3O' # oxazepam
=&gt; 61.69
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The results we obtain for metoprolol and oxazepam are 50.72 and 61.69, respectively. These values compare well with those reported by Ertl et al. in the &lt;a href="http://dx.doi.org/10.1021/jm000942e"&gt;definitive paper on TPSA&lt;/a&gt; (50.7 and 61.7, respectively).&lt;/p&gt;

&lt;h4&gt;Conclusions&lt;/h4&gt;

&lt;p&gt;It doesn't take much Ruby to command a wide range of cheminformatics functionality - in this case TPSA calculations. But the fun doesn't stop there. The CDK, and by extension Ruby CDK, offer access to a &lt;a href="http://cheminfo.informatics.indiana.edu/~rguha/code/java/nightly/api/org/openscience/cdk/qsar/descriptors/molecular/package-frame.html"&gt;wide array of descriptor calculations&lt;/a&gt;, each of which follow the same basic pattern outlined here. All of it can be prototyped, debugged, and deployed through one of the most flexible programming languages currently available.&lt;/p&gt;</description>
      <pubDate>Wed, 19 Sep 2007 09:27:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:f9b7229e-0e55-4299-a5ce-4d035a424398</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2007/09/19/easily-calculate-tpsa-descriptors-from-smiles-strings-using-ruby-cdk</link>
      <category>Tools</category>
      <category>ruby</category>
      <category>rcdk</category>
      <category>rubycdk</category>
      <category>tpsa</category>
      <category>descriptor</category>
      <category>rjb</category>
    </item>
    <item>
      <title>A Molecular Language for Modern Chemistry: Reading FlexMol Documents with Octet</title>
      <description>&lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/0596004206?ie=UTF8&amp;amp;tag=depthfirst-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596004206"&gt;&lt;img border="0" src="http://depth-first.com/files/learning_xml.jpg" align="right"&gt;&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=depthfirst-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0596004206" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;An XML language is only as useful as the software tools that take advantage of it. &lt;a href="http://depth-first.com/articles/tag/flexmol"&gt;Previous articles&lt;/a&gt; have discussed how the XML language FlexMol can solve a variety of molecular representation problems ranging from the &lt;a href="http://depth-first.com/articles/2006/12/20/a-molecular-language-for-modern-chemistry-getting-started-with-flexmol"&gt;multiatom bonding of metallocenes&lt;/a&gt; to the &lt;a href="http://depth-first.com/articles/2006/12/20/a-molecular-language-for-modern-chemistry-getting-started-with-flexmol"&gt;axial chirality of biaryls&lt;/a&gt;. &lt;a href="http://depth-first.com/articles/2007/01/30/an-object-oriented-framework-for-molecular-representation-getting-started-with-octet"&gt;Octet&lt;/a&gt; is a framework written in Java that speaks FlexMol natively. In this article, I'll show how Octet can be used to read a sample FlexMol document.&lt;/p&gt;

&lt;h4&gt;Prerequisites&lt;/h4&gt;

&lt;p&gt;For this tutorial, you'll need &lt;a href="http://rubyforge.org/projects/rjb/"&gt;Ruby Java Bridge&lt;/a&gt; (RJB). Previous articles have discussed the installation and use of RJB on &lt;a href="http://depth-first.com/articles/2006/10/12/running-ruby-java-bridge-on-windows"&gt;Windows&lt;/a&gt; and &lt;a href="http://depth-first.com/articles/2006/08/26/scripting-java-libraries-with-ruby-java-bridge"&gt;Linux&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;A Sample Molecule&lt;/h4&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20070131/s_monolaterol.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://depth-first.com/articles/2007/01/25/a-molecular-language-for-modern-chemistry-flexmol-tetrahedral-chirality-and-monolaterol"&gt;recent article&lt;/a&gt; disused a FlexMol representation of the chiral natural product monolaterol. Using a slightly modified numbering system for this molecule (shown above), we can construct a &lt;a href="http://depth-first.com/demo/20070131/s_monolaterol.xml"&gt;complete FlexMol representation&lt;/a&gt;. In this case, we simply start numbering at index zero, subtracting one from every index in the previous example to match the zero-based indices used in Octet.&lt;/p&gt;

&lt;h4&gt;A Demonstration Package&lt;/h4&gt;

&lt;p&gt;To illustrate the process of reading a FlexMol document, I've prepared a small package (&lt;strong&gt;demo-20070131.tar.gz&lt;/strong&gt;) that can be &lt;a href="https://sourceforge.net/project/showfiles.php?group_id=96108&amp;amp;package_id=220177&amp;amp;release_id=482855"&gt;downloaded from SourceForge&lt;/a&gt;. In it, you'll find an Octet jarfile (&lt;strong&gt;octet-0.8.2.jar&lt;/strong&gt;), a FlexMol representation of monolaterol (&lt;strong&gt;s_monolaterol.xml&lt;/strong&gt;), a Ruby library (&lt;strong&gt;reader.rb&lt;/strong&gt;), and some Ruby test code (&lt;strong&gt;test.rb&lt;/strong&gt;). Inflate this archive and make it your working directory.&lt;/p&gt;

&lt;h4&gt;A Simple Test&lt;/h4&gt;

&lt;p&gt;The following sequence of commands will run the test included with the demonstration package:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ export CLASSPATH=./octet-0.8.2.jar
$ ruby test.rb
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;You should see several lines of output terminated with the line:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
The exact mass of monolaterol is 276.115029755.
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;You can get more hands-on experience with loading and processing the monolaterol FlexMol document using interactive Ruby (irb). For example:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ irb
irb(main):001:0&gt; require 'reader'
=&gt; true
irb(main):002:0&gt; r=Reader.new
=&gt; #&lt;Reader:0x2b9ab173a1f0 @xml_reader=#&lt;#&lt;Class:0x2b9ab1741680&gt;:0x2b9ab1736690&gt;, @handler=#&lt;#&lt;Class:0x2b9ab1741680&gt;:0x2b9ab1736e10&gt;, @builder=#&lt;#&lt;Class:0x2b9ab1741680&gt;:0x2b9ab1736b90&gt;&gt;
irb(main):003:0&gt; mol=r.read_file 's_monolaterol.xml'
=&gt; #&lt;#&lt;Class:0x2b9ab1741680&gt;:0x2b9ab172cd48&gt;
irb(main):004:0&gt; mol.countAtoms
=&gt; 21
irb(main):005:0&gt; mol.countBondingSystems
=&gt; 24
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Of course, this is just scratching the surface of what can be done once a FlexMol document has been loaded by Octet.&lt;/p&gt;

&lt;h4&gt;Conclusions&lt;/h4&gt;

&lt;p&gt;Octet makes it possible to convert FlexMol documents into Java object representations that can be accessed through Ruby. With an object representation, the possibilities are limitless. Some simple examples have been provided here. Future articles will illustrate more advanced uses.&lt;/p&gt;</description>
      <pubDate>Wed, 31 Jan 2007 14:56:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:ab1f670a-3c7e-407d-af0e-c4343d7082d2</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2007/01/31/a-molecular-language-for-modern-chemistry-reading-flexmol-documents-with-octet</link>
      <category>Tools</category>
      <category>flexmol</category>
      <category>octet</category>
      <category>ruby</category>
      <category>java</category>
      <category>rjb</category>
      <category>monolaterol</category>
      <category>xml</category>
    </item>
    <item>
      <title>Build a Rails Cheminformatics Application in Thirty Minutes</title>
      <description>&lt;p&gt;&lt;a href="http://www.rubyonrails.org/"&gt;&lt;img src="http://depth-first.com/files/rails_logo.png" align="right" border="0"&gt;&lt;/img&gt;&lt;/a&gt;A &lt;a href="http://depth-first.com/articles/2006/11/20/unchaining-chemistry-from-the-desktop"&gt;recent article&lt;/a&gt; highlighted the Web as a new cheminformatics platform. Advocacy is one thing, but a working, open, demo built with modern technologies is far more compelling. In the following tutorial we'll build a first-generation cheminformatics Web application using the &lt;a href="http://www.rubyonrails.org/"&gt;Ruby on Rails&lt;/a&gt; framework and 100% Open Source components. We'll just cover the essentials here - look for future articles to discuss the underlying technology in more detail.&lt;/p&gt;

&lt;h4&gt;The Problem&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://www.daylight.com/smiles/index.html"&gt;Simplified Molecular Input Line Entry System&lt;/a&gt; (SMILES) is one of the most compact and easy-to-learn molecular representation systems ever developed. Part of a larger family of molecular languages called &lt;a href="http://depth-first.com/articles/2006/08/18/107-years-of-line-formula-notations-1861-1968"&gt;line notations&lt;/a&gt;, SMILES strings are always written as a single line of ASCII text. This makes them perfect in situations calling for data entry; witness their use in a wide range of new free &lt;a href="http://depth-first.com/articles/2006/11/07/twelve-free-chemistry-databases"&gt;online chemistry databases&lt;/a&gt;. This system typically works by a chemist drawing a structure in a graphical editor, copying a SMILES string from the editor, and pasting this string into a search window in the database application.&lt;/p&gt;

&lt;p&gt;SMILES is a great language for computers, but not for chemists, who are trained to communicate through 2-D structure diagrams. Although SMILES strings can be decoded manually, this is a tedious and error-prone process, especially for SMILES encoding high degrees of branching and ring content. It's preferable for the computer to do this hard work for us, providing a perfectly laid-out 2-D structure diagram for use in debugging or inclusion in documents.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.daylight.com/daycgi/depict"&gt;Depict&lt;/a&gt; is a Web application originally developed by &lt;a href="http://www.daylight.com/"&gt;Daylight&lt;/a&gt; for the conversion of SMILES strings into 2-D structure diagrams. Type a SMILES string into the form, press enter, and get a raster image of the encoded molecule. Daylight's Depict does a good enough job, but you can't change the interface or output. You also can't take the software apart to see how it works. Wouldn't it be great if you could?&lt;/p&gt;

&lt;h4&gt;About This Tutorial Series&lt;/h4&gt;

&lt;p&gt;This tutorial is the first in a series describing how to build a Depict server using 100% &lt;a href="http://opensource.org"&gt;Open Source&lt;/a&gt; components. The application will accept a SMILES string in a Webpage text field, and then produce a 2-D structure diagram. It won't be designed for ease of use, appearance, or configurability - these improvements will be described in subsequent articles. When this application is finished, I'll deploy it on a Web server. At every step in this process, I'll provide enough detail for anyone to do the same.&lt;/p&gt;

&lt;p&gt;It won't be necessary to finish every step yourself before you can work with the finished product. Near the beginning of each installment will be be a "Download and Prerequisites" section containing a link to the complete source code. Simply download this code and run it to see what it does.&lt;/p&gt;

&lt;h4&gt;Download and Prerequisites&lt;/h4&gt;

&lt;p&gt;For this tutorial, you'll need &lt;a href="http://depth-first.com/articles/2006/10/30/agile-chemical-informatics-development-with-cdk-and-ruby-rcdk-0-3-0"&gt;Ruby CDK&lt;/a&gt; (RCDK). A recent article described the small amount of system configuration required for &lt;a href="http://depth-first.com/articles/2006/09/25/cdk-the-ruby-way-rcdk-0-2-0"&gt;RCDK on Linux&lt;/a&gt;. Another article showed how to install &lt;a href="http://depth-first.com/articles/2006/10/12/running-ruby-java-bridge-on-windows"&gt;RCDK on Windows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/0977616630?ie=UTF8&amp;amp;tag=depthfirst-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0977616630"&gt;&lt;img border="0" src="http://depth-first.com/demo/20061122/0977616630.01._AA_SCMZZZZZZZ_V36350687_.jpg" align="right"&gt;&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=depthfirst-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0977616630" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;In addition, you'll need to install &lt;a href="http://www.rubyonrails.org/down"&gt;Ruby on Rails&lt;/a&gt; - something that can be done through &lt;a href="http://docs.rubygems.org/"&gt;RubyGems&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The complete Depict application can be &lt;a href="http://depth-first.com/demo/20061121/depict.tar.gz"&gt;downloaded from this link&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;A Note on Ruby Java Bridge and AMD64 Linux Platforms&lt;/h4&gt;

&lt;p&gt;Our Depict application will use &lt;a href="http://rjb.rubyforge.org/"&gt;Ruby Java Bridge&lt;/a&gt; (RJB) as a Ruby interface to Java bytecode. Recently, &lt;a href="http://rubyforge.org/pipermail/rjb-users/2006-November/000008.html"&gt;a problem with RJB on AMD64-Linux&lt;/a&gt; was uncovered. This problem prevents third-party jarfiles from being loaded after Rails has been loaded.&lt;/p&gt;

&lt;p&gt;In practice, this means that the command to start the Rails server (Step 2) needs to be prefixed with an assignment of &lt;tt&gt;LD_PRELOAD&lt;/tt&gt;. You also need to make &lt;tt&gt;LD_LIBRARY_PATH&lt;/tt&gt; point to your native Java libraries. On my platform, which is AMD64-Linux running Sun's JVM, the commands are:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ export LD_LIBRARY_PATH=/usr/java/jdk1.5.0_09/jre/lib/amd64:/usr/java/jdk1.5.0_09/jre/lib/amd64/server
$ LD_PRELOAD=/usr/java/jdk1.5.0_09/jre/lib/amd64/libzip.so ruby script/server
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If you get an "Internal Error" due to an "unknown exception" while running Depict, chances are good that you've hit the same problem. Starting the Rails server as above should resolve it.&lt;/p&gt;

&lt;h4&gt;Step 1: Create the Application&lt;/h4&gt;

&lt;p&gt;Getting started with Rails is as simple as issuing the &lt;tt&gt;rails&lt;/tt&gt; command with the name of your application as an argument:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ rails depict
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Executing this command creates a complete Rails application template under the &lt;strong&gt;depict&lt;/strong&gt; subdirectory in your working directory. You build your application by editing the files and directories that were generated.&lt;/p&gt;

&lt;h4&gt;Step 2: Start the Server&lt;/h4&gt;

&lt;p&gt;You can start the Depict application by running the included server script:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ cd depict
$ ruby script/server
=&gt; Booting WEBrick...
=&gt; Rails application started on http://0.0.0.0:3000
=&gt; Ctrl-C to shutdown server; call with --help for options
[2006-11-18 10:17:08] INFO  WEBrick 1.3.1
[2006-11-18 10:17:08] INFO  ruby 1.8.5 (2006-08-25) [x86_64-linux-gnu]
[2006-11-18 10:17:08] INFO  WEBrick::HTTPServer#start: pid=4036 port=3000
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Let's see what Depict looks like so far. Point your browser to &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt;. You should see the following page:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061122/step_2.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You're now running Ruby on Rails.&lt;/p&gt;

&lt;h4&gt;Step 3: Create the SmilesController&lt;/h4&gt;

&lt;p&gt;Rails adapts the Model-View-Controller application paradigm to the Web. It also automates many of the steps in building models, views, and controllers. Let's create a controller to handle the manipulation of SMILES strings:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ ruby script/generate controller Smiles
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/smiles
      exists  test/functional/
      create  app/controllers/smiles_controller.rb
      create  test/functional/smiles_controller_test.rb
      create  app/helpers/smiles_helper.rb
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Currently, &lt;tt&gt;SmilesController&lt;/tt&gt; is just a skeleton:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;SmilesController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's give &lt;tt&gt;SmilesController&lt;/tt&gt; the ability to accept a SMILES string as input by adding an &lt;tt&gt;input&lt;/tt&gt; method.&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;SmilesController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;input&lt;/span&gt;

  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Step 4: Create a Form&lt;/h4&gt;

&lt;p&gt;At this stage, pointing your browser to &lt;a href="http://localhost:3000/smiles/input"&gt;http://localhost:3000/smiles/input&lt;/a&gt; gives a screen containing an error message:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061122/step_4_1.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Rails is looking for view that doesn't exist, so let's create one. To your &lt;strong&gt;depict/app/views/smiles&lt;/strong&gt; directory, add the following file, called &lt;strong&gt;input.rhtml&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;html&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;head&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;&lt;span class="constant"&gt;Enter&lt;/span&gt; &lt;span class="ident"&gt;a&lt;/span&gt; &lt;span class="constant"&gt;SMILES&lt;/span&gt; &lt;span class="constant"&gt;String&lt;/span&gt;&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="regex"&gt;title&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;head&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;%=&lt;/span&gt;&lt;span class="string"&gt; form_tag :action&lt;/span&gt;&lt;span class="punct"&gt;=&amp;gt;'&lt;/span&gt;&lt;span class="string"&gt;depict&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="string"&gt;
      Enter a SMILES String: &amp;lt;br /&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;%=&lt;/span&gt;&lt;span class="string"&gt; text_field('smiles', 'value') %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;end_form_tag&lt;/span&gt; &lt;span class="punct"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="string"&gt;
  &amp;lt;/body&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="regex"&gt;html&amp;gt; &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This HTML view is an example of Ruby's templating mechanism, eRuby, which was discussed earlier in the context of &lt;a href="http://depth-first.com/articles/2006/11/15/diversity-oriented-chemical-informatics"&gt;converting SD files to HTML&lt;/a&gt;. In the template above, we've configured our form to invoke an action called &lt;tt&gt;depict&lt;/tt&gt; when submitted. This action does not yet exist, but will be created in Step 5 below.&lt;/p&gt;

&lt;p&gt;Now, pointing your browser to &lt;a href="http://localhost:3000/smiles/input"&gt;http://localhost:3000/smiles/input&lt;/a&gt; should give an input field:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061122/step_4_2.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Let's try it. Submitting the SMILES string for benzene gives the following error screen:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061122/step_4_3.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;We haven't defined the &lt;tt&gt;depict&lt;/tt&gt; action yet, a fact that Rails is communicating with this error message.&lt;/p&gt;

&lt;p&gt;Have you noticed how we haven't had to restart the Rails Web server as we've made changes? This is but one of the many conveniences that makes Rails such a productive platform.&lt;/p&gt;

&lt;h4&gt;Step 5: Add a Depict Action&lt;/h4&gt;

&lt;p&gt;We need a way to pass a SMILES string from the Web page text field in which it's entered to our application and back to another view. To do this we'll add a &lt;tt&gt;depict&lt;/tt&gt; method to &lt;strong&gt;depict/app/controllers/smiles_controller.rb&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;depict&lt;/span&gt;
  &lt;span class="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:smiles&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="symbol"&gt;:value&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Of course, our application still won't run properly because we haven't created a view for the new &lt;tt&gt;depict&lt;/tt&gt; method to use. Let's do this by adding the following file, named &lt;strong&gt;depict.rb&lt;/strong&gt; to the &lt;strong&gt;depict/app/views/smiles&lt;/strong&gt; directory:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;html&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;head&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;&lt;span class="constant"&gt;Depict&lt;/span&gt; &lt;span class="constant"&gt;SMILES&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;%=&lt;/span&gt;&lt;span class="string"&gt; @smiles %&amp;gt;&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;SMILES: &amp;lt;%&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="string"&gt;&amp;lt;/h1&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="regex"&gt;body&amp;gt;
&amp;lt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;html&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice how the instance variable &lt;tt&gt;@smiles&lt;/tt&gt; is available for use within the template.&lt;/p&gt;

&lt;p&gt;Let's have a look at Depict so far. Pointing your browser to &lt;a href="http://localhost:3000/smiles/input"&gt;http://localhost:3000/smiles/input&lt;/a&gt;, entering the SMILES string for benzene, and pressing return produces the page show below:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061122/step_5_1.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;So far, so good. We've been able to read user input from an HTML form and reprocess it into some simple HTML output. Now, lets render a 2-D molecular image to go with it.&lt;/p&gt;

&lt;h4&gt;Step 6: Generate the 2-D Image&lt;/h4&gt;

&lt;p&gt;We'll use a method called &lt;tt&gt;image_for&lt;/tt&gt;, which we'll define shortly. The file &lt;strong&gt;depict/app/views/smiles/depict&lt;/strong&gt; should look like this:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;html&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;head&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;title&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;&lt;span class="constant"&gt;Depict&lt;/span&gt; &lt;span class="constant"&gt;SMILES&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;%=&lt;/span&gt;&lt;span class="string"&gt; @smiles %&amp;gt;&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;SMILES:&amp;lt;%&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="string"&gt;&amp;lt;/h1&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="ident"&gt;img&lt;/span&gt; &lt;span class="ident"&gt;src&lt;/span&gt;&lt;span class="punct"&gt;=&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&amp;lt;%= url_for :action =&amp;gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ident"&gt;image_for&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;, :smiles =&amp;gt; @smiles %&amp;gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="regex"&gt;img&amp;gt;
  &amp;lt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="regex"&gt;html&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The added &lt;tt&gt;img&lt;/tt&gt; tag is a placeholder for now. It loads an image dynamically generated from the &lt;tt&gt;image_for&lt;/tt&gt; method, which we'll shortly add to &lt;tt&gt;SmilesController&lt;/tt&gt;. We pass the SMILES string as a parameter.&lt;/p&gt;

&lt;p&gt;The &lt;tt&gt;image_for&lt;/tt&gt; method does all of the real work in the Depict application. It accepts a SMILES string as a parameter, and produces a laid-out 2-D color molecular image as output. The method uses a variety of functionality contained in the Java API itself, and in Ruby CDK.&lt;/p&gt;

&lt;p&gt;In addition to an &lt;tt&gt;image_for&lt;/tt&gt; method, we'll need to add some accessory code to make it work. Edit &lt;strong&gt;depict/app/controllers/smiles_controller.rb&lt;/strong&gt; so that it looks like this:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# Load the RCDK library&lt;/span&gt;
&lt;span class="ident"&gt;require_gem&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rcdk&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rcdk/util&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="comment"&gt;# New jrequire calls.&lt;/span&gt;
&lt;span class="ident"&gt;jrequire&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;java.io.ByteArrayOutputStream&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;jrequire&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;net.sf.structure.cdk.util.ImageKit&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;jrequire&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;javax.imageio.ImageIO&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;SmilesController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;

  &lt;span class="comment"&gt;# Already defined.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;input&lt;/span&gt;

  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# Already defined.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;depict&lt;/span&gt;
    &lt;span class="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:smiles&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="symbol"&gt;:value&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# New method.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;image_for&lt;/span&gt;
    &lt;span class="ident"&gt;smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:smiles&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
    &lt;span class="ident"&gt;mol&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;RCDK&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Util&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Lang&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;read_smiles&lt;/span&gt; &lt;span class="ident"&gt;smiles&lt;/span&gt;
    &lt;span class="ident"&gt;mol&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;RCDK&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Util&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;XY&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;coordinate_molecule&lt;/span&gt; &lt;span class="ident"&gt;mol&lt;/span&gt;
    &lt;span class="ident"&gt;out&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;Java&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Io&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ByteArrayOutputStream&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
    &lt;span class="ident"&gt;image&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="constant"&gt;Net&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Sf&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Structure&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Cdk&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Util&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ImageKit&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;createRenderedImage&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;mol&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;300&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;300&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="constant"&gt;Javax&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Imageio&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ImageIO&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;write&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;image&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;png&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="ident"&gt;out&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="ident"&gt;send_data&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;out&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;toByteArray&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="symbol"&gt;:type&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;image/png&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="symbol"&gt;:disposition&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;inline&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="symbol"&gt;:filename&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;molecule.png&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let's test the application with a real-world example. The achiral SMILES string for &lt;a href="http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?cid=14950"&gt;Carmine&lt;/a&gt; is:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_smiles "&gt;CC1=C2C(=CC(=C1C(=O)O)O)C(=O)C3=C(C2=O)C(=C(C(=C3O)O)C4C(C(C(C(O4)CO)O)O)O)O&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Pointing your browser to &lt;a href="http://localhost:3000/smiles/input"&gt;http://localhost:3000/smiles/input&lt;/a&gt; and entering the above SMILES string produces a color 2-D image of the structure of the red food coloring:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061122/step_6_1.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;h4&gt;Conclusions&lt;/h4&gt;

&lt;p&gt;Ruby on Rails is a fun and agile framework for rapid Web development. Although Depict isn't much to look at yet, it demonstrates many key Rails concepts. Several techniques could be used improve the application's look and usability. For example, we could use &lt;a href="http://www.ajaxian.com/"&gt;AJAX&lt;/a&gt; to depict SMILES strings as they are being typed - without the need to hit return. We could also provide options for changing image format, size, and color scheme. Future articles will describe these and other improvements.&lt;/p&gt;</description>
      <pubDate>Tue, 21 Nov 2006 15:06:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:28d193f3-f174-45ca-84f1-cac552672c29</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/11/21/build-a-rails-cheminformatics-application-in-thirty-minutes</link>
      <category>Tools</category>
      <category>webapplication</category>
      <category>web</category>
      <category>rails</category>
      <category>2d</category>
      <category>rcdk</category>
      <category>ruby</category>
      <category>rjb</category>
      <category>amd64</category>
    </item>
    <item>
      <title>Scripting Java with Ruby: Yet Another Java Bridge</title>
      <description>&lt;p&gt;&lt;img src="http://depth-first.com/files/ruby_logo_new.gif" align="right"&gt;&lt;/img&gt;New technologies attempting to compete with older technologies need to provide a clear upgrade path, if they are to succeed. A case in point is Ruby. Many Java developers' reaction to this language has less to do with its capabilities and more to do with previous investments in Java. What good is a new language if the special library X that you depend on needs to be rewritten from scratch?&lt;/p&gt;

&lt;p&gt;Previous articles, starting with &lt;a href="http://depth-first.com/articles/2006/08/26/scripting-java-libraries-with-ruby-java-bridge"&gt;this one&lt;/a&gt;, have discussed &lt;a href="http://rjb.rubyforge.org"&gt;Ruby Java Bridge&lt;/a&gt; (RJB) as a Java-Ruby integration tool. Two additional articles discussed RJB in the context of &lt;a href="http://depth-first.com/articles/2006/10/24/metaprogramming-with-ruby-mapping-java-packages-onto-ruby-modules"&gt;mapping Java packages onto Ruby modules&lt;/a&gt; and &lt;a href="http://depth-first.com/articles/2006/10/12/running-ruby-java-bridge-on-windows"&gt;Java-Ruby integration on Windows&lt;/a&gt;. RJB currently provides the mechanism whereby the full &lt;a href="http://cdk.sf.net"&gt;Chemistry Development Kit&lt;/a&gt; (CDK) API can be used in Ruby with &lt;a href="http://rubyforge.org/projects/rcdk"&gt;Ruby CDK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another option for Java-Ruby integration is &lt;a href="http://jruby.codehaus.org/"&gt;JRuby&lt;/a&gt;, a Java implementation of the Ruby interpreter. JRuby offers tight integration with the Java Virtual Machine, which will be ideal in many situations. In other situations, it will not be the best choice. For example, one of the advantages of RJB over JRuby is that the standard C-Ruby implementation can be used. This in turn offers, for example, full &lt;a href="http://www.rubyonrails.org/"&gt;Rails&lt;/a&gt; functionality and access to C extensions. A disadvantage of RJB is that, being written in C, it requires a working build toolchain for installation.&lt;/p&gt;

&lt;p&gt;I've seen &lt;a href="http://www.jaredrichardson.net/blog/2006/09/01/"&gt;one report&lt;/a&gt; of a Macintosh installation of RJB that failed. Without a Mac of my own, I can't confirm if this is indeed a problem. But this report also pointed me to a third approach to Ruby-Java integration, &lt;a href="http://www.cmt.phys.kyushu-u.ac.jp/~M.Sakurai/cgi-bin/fw/wiki.cgi?page=YAJB"&gt;Yet Another Java Bridge&lt;/a&gt; (YAJB). YAJB is different from both JRuby and RJB in that it extends the C implementation of Ruby with a Java bridge written in pure Java. In theory, it should run on any platform that both Ruby and Java run on.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.cmt.phys.kyushu-u.ac.jp/~M.Sakurai/java/ruby/yajb-0.8.1.tar.gz"&gt;YAJB-0.8.1&lt;/a&gt; installed on my system without a hitch. From the root directory of the distribution:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
# ruby setup.rb
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Using YAJB was straightforward. A Java &lt;tt&gt;Vector&lt;/tt&gt; instance could be instantiated and manipulated using familiar syntax:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;yajb/jbridge&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;JavaBridge&lt;/span&gt;

&lt;span class="ident"&gt;v&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;jnew&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;java.util.Vector&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;one&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
&lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;add&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;two&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
&lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;size&lt;/span&gt; &lt;span class="comment"&gt;# =&amp;gt; 2&lt;/span&gt;
&lt;span class="ident"&gt;v&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;elementAt&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="comment"&gt;# =&amp;gt; &amp;quot;two&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Good integration tools can make the difference between actually using new technologies and simply observing them. Java developers interested in using Ruby now have at least three good options to choose from: JRuby; RJB; and YAJB.&lt;/p&gt;</description>
      <pubDate>Wed, 25 Oct 2006 14:53:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:65a72a41-d6a6-4728-82b4-c93b9fed8421</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/10/25/scripting-java-with-ruby-yet-another-java-bridge</link>
      <category>Tools</category>
      <category>ruby</category>
      <category>java</category>
      <category>integration</category>
      <category>rjb</category>
      <category>jruby</category>
      <category>yajb</category>
    </item>
    <item>
      <title>Metaprogramming with Ruby: Mapping Java Packages Onto Ruby Modules</title>
      <description>&lt;p&gt;&lt;img src="http://depth-first.com/files/ruby_logo_new.gif" align="right"&gt;&lt;/img&gt;&lt;a href="http://www.vanderburg.org/Speaking/Stuff/oscon05.pdf"&gt;Metaprogramming&lt;/a&gt; lets you define new constructs in your programming language. In &lt;a href="http://www.journalhome.com/codecraft/9003/"&gt;safety languages&lt;/a&gt; like Java, metaprogramming is not a standard feature, although &lt;a href="http://www.csg.is.titech.ac.jp/~chiba/javassist/"&gt;it can be done&lt;/a&gt;. Not surprisingly, the reaction most Java developers have to metaprogramming typically ranges from "useless" to "catastrophic". I was once in that category. But in the words of Paul Graham, sometimes doing the right thing involves &lt;a href="http://www.paulgraham.com/progbot.html"&gt;"changing the language to suit the problem"&lt;/a&gt;. This is a powerful concept that, when used with care, can greatly reduce development time. The Ruby language is &lt;a href="http://ola-bini.blogspot.com/2006/09/ruby-metaprogramming-techniques.html"&gt;especially well-equipped&lt;/a&gt; for metaprogramming. This article will show a simple metaprogramming technique that extends Ruby so that Java packages are mapped onto to Ruby modules.&lt;/p&gt;

&lt;h4&gt;Prerequisites&lt;/h4&gt;

&lt;p&gt;This tutorial uses &lt;a href="http://rjb.rubyforge.org/"&gt;Ruby Java Bridge&lt;/a&gt; (RJB). RJB can be &lt;a href="http://depth-first.com/articles/2006/10/12/running-ruby-java-bridge-on-windows"&gt;installed&lt;/a&gt; either on Windows or Linux using the &lt;a href="http://rubygems.org/"&gt;RubyGems&lt;/a&gt; packaging mechanism.&lt;/p&gt;

&lt;h4&gt;Defining the Problem&lt;/h4&gt;

&lt;p&gt;The large amount of existing Java code makes RJB one of Ruby's most useful integration tools. RJB provides a lightweight mechanism for working with Java classes from Ruby, while simultaneously allowing for the use of C-extensions and everything else the C implementation of Ruby offers.&lt;/p&gt;

&lt;p&gt;Let's say you'd like to do image processing with Java's &lt;tt&gt;ImageIO&lt;/tt&gt; class. This could be accomplished with RJB via:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rubygems&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require_gem&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rjb&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rjb&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="attribute"&gt;@ImageIO&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Rjb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;javax.imageio.ImageIO&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="attribute"&gt;@ImageIO&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getReaderFormatNames&lt;/span&gt; &lt;span class="comment"&gt;# =&amp;gt; an array of format names&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, the instance variable &lt;tt&gt;ImageIO&lt;/tt&gt; holds a reference to the Java class of the same name. This isn't too bad, but can we do better?&lt;/p&gt;

&lt;p&gt;Imagine a situation in which many Java classes need to be imported. This would lead to many variable assignments like the one above. The resulting duplications of Java class names and variable names &lt;a href="http://www.dcs.gla.ac.uk/~hcp/psd/lectures/badsmells.pdf"&gt;doesn't smell especially good&lt;/a&gt;, nor does it scale well. In addition, the large number of these variable assignments would add a lot of mental overhead when reading and writing the code.&lt;/p&gt;

&lt;p&gt;What we'd really like is if Ruby had a way for us to map a Java package/class hierarchy onto Ruby module/class hierarchy. We could then forget about the differences between Ruby and Java, and just get to work. For example:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#...&lt;/span&gt;

&lt;span class="ident"&gt;jrequire&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;javax.imageio.ImageIO&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="comment"&gt;#...&lt;/span&gt;

&lt;span class="constant"&gt;Javax&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Imageio&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ImageIO&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getReaderFormatNames&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;A Solution&lt;/h4&gt;

&lt;p&gt;Our solution will involve translating nested Java package/class constructs into nested Ruby module/class constructs at runtime. We'll need the ability to create new module hierarchies in running code, one of the problems metaprogramming solves. We'll also have to deal with capitalization: Java package names are all lowercase, but Ruby module names start with a capital letter. So &lt;tt&gt;java.lang.System&lt;/tt&gt; will become &lt;tt&gt;Java::Lang::System&lt;/tt&gt;. By mapping the Java package namespace onto the Ruby module namespace, we'll reduce the odds of creating a Ruby/Java class name collision, such as with &lt;tt&gt;java.lang.String&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;Let's create a small library to illustrate these points. The code will take advantage of Ruby's &lt;tt&gt;const_set&lt;/tt&gt; method, which allows new constants (and therefore new modules and classes) to be defined at runtime. Save the following code into a file called &lt;strong&gt;java.rb&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rubygems&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require_gem&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rjb&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rjb&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;Kernel&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;jrequire&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;qualified_class_name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;java_class&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Rjb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;import&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;qualified_class_name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;package_names&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;qualified_class_name&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;to_s&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;.&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
    &lt;span class="ident"&gt;java_class_name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;package_names&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;delete&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;package_names&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;last&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;new_module&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="keyword"&gt;class

    &lt;/span&gt;&lt;span class="class"&gt;package_names.each&lt;/span&gt; &lt;span class="ident"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;package_name&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;module_name&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;package_name&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;capitalize&lt;/span&gt;

      &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;!&lt;/span&gt;&lt;span class="ident"&gt;new_module&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;const_defined?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;module_name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="ident"&gt;new_module&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new_module&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;const_set&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;module_name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="constant"&gt;Module&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;else&lt;/span&gt;
        &lt;span class="ident"&gt;new_module&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;new_module&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;const_get&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;module_name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;false&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;new_module&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;const_defined?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;java_class_name&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="ident"&gt;new_module&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;const_set&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;java_class_name&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;java_class&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Usage&lt;/h4&gt;

&lt;p&gt;Using this library consists of &lt;tt&gt;requiring&lt;/tt&gt; it, applying the new &lt;tt&gt;jrequire&lt;/tt&gt; command, and manipulating the resulting class:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;java&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;jrequire&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;javax.imageio.ImageIO&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="constant"&gt;Javax&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Imageio&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ImageIO&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getReaderFormatNames&lt;/span&gt; &lt;span class="comment"&gt;# =&amp;gt; [&amp;quot;BMP&amp;quot;, &amp;quot;jpeg&amp;quot;, &amp;quot;bmp&amp;quot;, &amp;quot;wbmp&amp;quot;, &amp;quot;gif&amp;quot;, &amp;quot;JPG&amp;quot;, &amp;quot;png&amp;quot;, &amp;quot;jpg&amp;quot;, &amp;quot;WBMP&amp;quot;, &amp;quot;JPEG&amp;quot;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can eliminate the need to use the fully-qualified module name by adding an &lt;tt&gt;include&lt;/tt&gt; statement, just as you would with any other Ruby module:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;java&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;jrequire&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;javax.imageio.ImageIO&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;Javax&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Imageio&lt;/span&gt;

&lt;span class="constant"&gt;ImageIO&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getReaderFormatNames&lt;/span&gt; &lt;span class="comment"&gt;# =&amp;gt; [&amp;quot;BMP&amp;quot;, &amp;quot;jpeg&amp;quot;, &amp;quot;bmp&amp;quot;, &amp;quot;wbmp&amp;quot;, &amp;quot;gif&amp;quot;, &amp;quot;JPG&amp;quot;, &amp;quot;png&amp;quot;, &amp;quot;jpg&amp;quot;, &amp;quot;WBMP&amp;quot;, &amp;quot;JPEG&amp;quot;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;One Possible Variation&lt;/h4&gt;

&lt;p&gt;An interesting variation on the approach given here would be to override Ruby's &lt;tt&gt;require&lt;/tt&gt; method itself to accept fully-qualified Java class names. Then something even more Rubyesque could be used:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;java&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;javax/imageio/ImageIO&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="constant"&gt;Javax&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Imageio&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;ImageIO&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;getReaderFormatNames&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Other Examples of Ruby-Java Metaprogramming&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://ola-bini.blogspot.com/"&gt;Ola Bini&lt;/a&gt; has written an article on JRuby metaprogramming that takes &lt;a href="http://ola-bini.blogspot.com/2006/10/jruby-import.html"&gt;a slightly different approach&lt;/a&gt; than the one detailed here.&lt;/p&gt;

&lt;h4&gt;Conclusions&lt;/h4&gt;

&lt;p&gt;This tutorial has shown a simple and practical application of Ruby's built-in metaprogramming capabilities. The careful use of metaprogamming is a powerful way to reduce code complexity and build a more consistent programming environment. Look for more metaprogramming techniques to appear in future releases of the &lt;a href="http://depth-first.com/articles/2006/09/25/cdk-the-ruby-way-rcdk-0-2-0"&gt;Ruby CDK&lt;/a&gt; library.&lt;/p&gt;</description>
      <pubDate>Tue, 24 Oct 2006 14:11:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:db2201c3-26d3-462c-9b21-357888d87876</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/10/24/metaprogramming-with-ruby-mapping-java-packages-onto-ruby-modules</link>
      <category>Tools</category>
      <category>metaprogramming</category>
      <category>ruby</category>
      <category>java</category>
      <category>rjb</category>
    </item>
    <item>
      <title>Running Ruby Java Bridge on Windows</title>
      <description>&lt;p&gt;&lt;img src="http://depth-first.com/files/ruby_logo_new.gif" align="right"&gt;&lt;/img&gt;The &lt;a href="http://rjb.rubyforge.org/"&gt;Ruby Java Bridge&lt;/a&gt; (RJB) is one of the most useful Ruby integration packages available. For example, RJB enables the complete use of the Chemistry Development Kit (CDK) &lt;a href="http://depth-first.com/articles/2006/09/14/cdk-the-ruby-way"&gt;from within Ruby&lt;/a&gt;. Past articles have been written from a  unix-centric perspective. This article will show how Windows users can  join in the fun.&lt;/p&gt;

&lt;h4&gt;Prerequisites &lt;/h4&gt;

&lt;p&gt;The only software you'll need for this tutorial is &lt;a href="http://java.sun.com/javase/downloads/index.jsp"&gt;Sun's Java Development Kit&lt;/a&gt; (JDK).  RJB requires the JDK and won't work with Sun's Java Runtime Environment (JRE).&lt;/p&gt;

&lt;h4&gt;Install Ruby and RJB&lt;/h4&gt;

&lt;p&gt;The simplest way to get started with Ruby on Windows is to download and install the &lt;a href="http://rubyinstaller.rubyforge.org/wiki/wiki.pl"&gt;Ruby One-Click Installer&lt;/a&gt;. Be sure RubyGems support is enabled.&lt;/p&gt;

&lt;p&gt;Once Ruby is installed, RJB can then be installed by using the RubyGems packaging system (from a dos prompt - see below):&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
gem install rjb
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Choose the most recent Win32 version (1.0.2 at the time of this writing). This will automatically compile and install RJB on your system.&lt;/p&gt;

&lt;p&gt;If you'd like, now would be a good time to also install Ruby CDK (rcdk):&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
gem install rcdk
&lt;/pre&gt;
&lt;/div&gt;

&lt;h4&gt;Post-Install Configuration&lt;/h4&gt;

&lt;p&gt;You'll need to make sure your system's &lt;tt&gt;JAVA_HOME&lt;/tt&gt; environment variable points to your JDK installation. If you're running Windows XP, a convenient way to do so is to use Start-&gt;Control Panel-&gt;(Switch to Classic View)-&gt;System-&gt;Advanced Tab-&gt;Environment Variables. Add a new variable called &lt;tt&gt;JAVA_HOME&lt;/tt&gt; with the path to the JDK installation as a value. On my system, this path is &lt;strong&gt;C:\Program Files\Java\JDK1.5.0_09&lt;/strong&gt;. Simply installing JDK does not set your system's &lt;tt&gt;JAVA_HOME&lt;/tt&gt; environment variable.&lt;/p&gt;

&lt;h4&gt;Testing RJB&lt;/h4&gt;

&lt;p&gt;You can verify that RJB is installed and working as described in &lt;a href="http://depth-first.com/articles/2006/08/26/scripting-java-libraries-with-ruby-java-bridge"&gt;my previous article on RJB&lt;/a&gt;. A command line prompt can be obtained in Windows XP through Start-&gt;Run followed by typing &lt;strong&gt;command.com&lt;/strong&gt; and enter. The screenshot below shows RJB working via IRB:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061012/ruby_rjb.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;h4&gt;Summing Up&lt;/h4&gt;

&lt;p&gt;Using Ruby and RJB on Windows is not that much different than doing so on unix. With this background, future articles will return to the theme of Ruby's role in chemical informatics software integration.&lt;/p&gt;</description>
      <pubDate>Thu, 12 Oct 2006 14:19:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:28ac1cb3-eb01-438a-8eab-e1f5661e8839</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/10/12/running-ruby-java-bridge-on-windows</link>
      <category>Tools</category>
      <category>windows</category>
      <category>ruby</category>
      <category>rcdk</category>
      <category>rjb</category>
    </item>
    <item>
      <title>Hacking NMRShiftDB</title>
      <description>&lt;p&gt;&lt;img src="http://depth-first.com/files/nmrshift-logo.gif" align="right"&gt;&lt;/img&gt;&lt;a href="http://nmrshiftdb.org"&gt;NMRShiftDB&lt;/a&gt; is an open web database of peer-reviewed NMR chemical shifts compiled by volunteers. As of this writing, it contains 22,429 measured spectra from 18,986 structures, and reports 927 registered users. The &lt;a href="http://sourceforge.net/projects/nmrshiftdb/"&gt;database code&lt;/a&gt; itself is open source.&lt;/p&gt;

&lt;p&gt;Although NMRShiftDB has a web interface, its architecture is designed to simplify writing programs that use it. A &lt;a href="http://depth-first.com/articles/2006/08/30/hacking-pubchem-with-ruby"&gt;previous article&lt;/a&gt; showed how a working &lt;a href="http://pubchem.ncbi.nlm.nih.gov/"&gt;PubChem&lt;/a&gt; API could be written with just a few lines of Ruby. This time, I'll show how the same thing can be done for NMRShiftDB.&lt;/p&gt;

&lt;h4&gt;Ingredients&lt;/h4&gt;

&lt;p&gt;This tutorial uses Arton's excellent &lt;a href="http://rjb.rubyforge.org/"&gt;Ruby Java Bridge&lt;/a&gt;, the installation and use of which has been &lt;a href="http://depth-first.com/articles/2006/08/26/scripting-java-libraries-with-ruby-java-bridge"&gt;previously discussed&lt;/a&gt;. Also used is Ruby's InChI interface, &lt;a href="http://rubyforge.org/projects/rino"&gt;Rino&lt;/a&gt;, for which installation instructions are &lt;a href="http://depth-first.com/articles/2006/08/17/ruby-and-inchi-the-rino-library"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Create a working directory called &lt;strong&gt;nmr&lt;/strong&gt;. Into this directory, copy &lt;strong&gt;cdk-20060714.jar&lt;/strong&gt;, which can be &lt;a href="http://prdownloads.sourceforge.net/cdk/cdk-20060714.jar?download"&gt;downloaded here&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Code&lt;/h4&gt;

&lt;p&gt;Create a file called &lt;strong&gt;nmr.rb&lt;/strong&gt; containing the following Ruby code:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;net/http&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;smi2inchi&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="comment"&gt;# A very simple NMRShiftDB Web API.&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;NMRFetcher&lt;/span&gt;

  &lt;span class="comment"&gt;# Creates a &amp;lt;tt&amp;gt;Translator&amp;lt;/tt&amp;gt; instance.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;
    &lt;span class="attribute"&gt;@translator&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Translator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# Returns an XML record, as a string, for the molecule&lt;/span&gt;
  &lt;span class="comment"&gt;# with SMILES matching &amp;lt;tt&amp;gt;smiles&amp;lt;/tt&amp;gt; and spectrum type&lt;/span&gt;
  &lt;span class="comment"&gt;# matching &amp;lt;tt&amp;gt;spectrumtype&amp;lt;/tt&amp;gt; (13C, 1H, 15N and 31P).&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;get_record&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;smiles&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;spectrumtype&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;body&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;
    &lt;span class="ident"&gt;inchi&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;smi2inchi&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;smiles&lt;/span&gt;&lt;span class="punct"&gt;)).&lt;/span&gt;&lt;span class="ident"&gt;gsub&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;InChI=&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;inchi=&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
    &lt;span class="ident"&gt;path&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/NmrshiftdbServlet?nmrshiftdbaction=exportcmlbyinchi&amp;amp;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;inchi&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&amp;amp;spectrumtype=&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;spectrumtype&lt;/span&gt;

    &lt;span class="constant"&gt;Net&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;HTTP&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;start&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;nmrshiftdb.ice.mpg.de&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;http&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
      &lt;span class="ident"&gt;response&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;http&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;get&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;path&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="ident"&gt;body&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;response&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="punct"&gt;!&lt;/span&gt;&lt;span class="ident"&gt;valid_record?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
      &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;body&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;private&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;valid_record?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="punct"&gt;!&lt;/span&gt;&lt;span class="ident"&gt;body&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;eql?&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;No such molecule or spectrum&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;smi2inchi&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;smiles&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@translator&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;translate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;smiles&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The magic in the above code is nothing more than a simple HTTP request sent to &lt;tt&gt;nmrshiftdb.ice.mpg.de&lt;/tt&gt;, contained in the &lt;tt&gt;get_record&lt;/tt&gt; method. This request encodes an InChI identifier, which is generated from the SMILES string passed as an argument. We also specify a spectrum type.&lt;/p&gt;

&lt;p&gt;Now create a file called &lt;strong&gt;smi2inchi.rb&lt;/strong&gt;, containing the following Ruby code:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="constant"&gt;ENV&lt;/span&gt;&lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;CLASSPATH&lt;/span&gt;&lt;span class="punct"&gt;']&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;./cdk-20060714.jar&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rubygems&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require_gem&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rjb&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require_gem&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rino&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rjb&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="constant"&gt;StringWriter&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Rjb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;java.io.StringWriter&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="constant"&gt;SmilesParser&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Rjb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;org.openscience.cdk.smiles.SmilesParser&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="constant"&gt;MDLWriter&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Rjb&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="ident"&gt;import&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;org.openscience.cdk.io.MDLWriter&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="comment"&gt;# Converts a SMILES string into an InChI identifier using&lt;/span&gt;
&lt;span class="comment"&gt;# the CDK Library (Java) and the Rino Library (Ruby/C).&lt;/span&gt;
&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;Translator&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;initialize&lt;/span&gt;
    &lt;span class="attribute"&gt;@smiles_parser&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;SmilesParser&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
    &lt;span class="attribute"&gt;@mdl_writer&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;MDLWriter&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
    &lt;span class="attribute"&gt;@mol2inchi&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Rino&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;MolfileReader&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# Returns an InChI identifier from the specified SMILES string.&lt;/span&gt;
  &lt;span class="comment"&gt;# Uses the CDK classes SmilesParser and MDLWriter to generate&lt;/span&gt;
  &lt;span class="comment"&gt;# a molfile from a SMILES string. Then this molfile is&lt;/span&gt;
  &lt;span class="comment"&gt;# parsed by Rino::MolfileReader.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;translate&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;smiles&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;mol&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="attribute"&gt;@smiles_parser&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;parseSmiles&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;smiles&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="ident"&gt;sw&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;StringWriter&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;

    &lt;span class="attribute"&gt;@mdl_writer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;setWriter&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sw&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="attribute"&gt;@mdl_writer&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;write&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;mol&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="attribute"&gt;@mol2inchi&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;read&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;sw&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;toString&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The description and use of this code was discussed in &lt;a href="http://depth-first.com/articles/2006/08/26/from-smiles-to-inchi-rino-cdk-and-java-ruby-bridge"&gt;a recent article&lt;/a&gt; on generating InChI identifiers from SMILES strings.&lt;/p&gt;

&lt;p&gt;Before using the code we've just created you'll need to set the &lt;tt&gt;LD_LIBRARY_PATH&lt;/tt&gt; (or equivalent) to point to the native Java libraries. On Linux with Sun's JDK, this is done from the command line with:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ export LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/i386:$LD_LIBRARY_PATH
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Using the &lt;tt&gt;NMRFetcher&lt;/tt&gt; class is just a matter of creating an instance, and invoking &lt;tt&gt;get_record&lt;/tt&gt; with the desired SMILES string and spectrum type (1H, 13C). Doing so returns a CML document containing the structure of the compound and its spectrum. If no record matches, the method returns &lt;tt&gt;nil&lt;/tt&gt;. The code below give an example in which the CML output is pretty-printed using the wonderful Ruby API for XML, &lt;a href="http://www.germane-software.com/software/rexml/"&gt;REXML&lt;/a&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;rexml/document&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;nmr&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;nmr&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;NMRFetcher&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;
&lt;span class="ident"&gt;smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;c1ccccc1&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="comment"&gt;#benzene, to keep things simple&lt;/span&gt;
&lt;span class="ident"&gt;type&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;13C&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;record&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;nmr&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;get_record&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;smiles&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;type&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;record&lt;/span&gt; &lt;span class="comment"&gt;#pretty-print the CML record using REXML&lt;/span&gt;
  &lt;span class="ident"&gt;file&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;result.xml&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;w&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;

  &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;REXML&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Document&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;record&lt;/span&gt;&lt;span class="punct"&gt;)).&lt;/span&gt;&lt;span class="ident"&gt;write&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;file&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

  &lt;span class="ident"&gt;file&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;close&lt;/span&gt;
&lt;span class="keyword"&gt;else&lt;/span&gt; &lt;span class="comment"&gt;#write an error&lt;/span&gt;
  &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;open&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;result.error&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;w&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;file&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="ident"&gt;file&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;No record of SMILES: &lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="punct"&gt;+&lt;/span&gt; &lt;span class="ident"&gt;smiles&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

The above code can be put into a file (&lt;strong&gt;test.rb&lt;/strong&gt;) and run:

&lt;div class="console"&gt;
&lt;pre&gt;
$ ruby test.rb
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Alternatively, it can be entered interactively and played with using irb:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ irb
irb(main):001:0&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;h4&gt;Output&lt;/h4&gt;

&lt;p&gt;The program produces the following &lt;a href="http://www.xml-cml.org/"&gt;Chemical Markup Language&lt;/a&gt; output in a file called &lt;strong&gt;result.xml&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_xml "&gt;&lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;cml&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;molecule&lt;/span&gt; &lt;span class="attribute"&gt;title&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;Benzene&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;nmrshiftdb7901&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/schema/cml2/core&lt;/span&gt;&lt;span class="punct"&gt;'&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;atomArray&lt;/span&gt; &lt;span class="attribute"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/schema&lt;/span&gt;&lt;span class="punct"&gt;'&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;atom&lt;/span&gt; &lt;span class="attribute"&gt;elementType&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;C&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;y2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0.7625&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;x2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;-1.4063&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a1&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;formalCharge&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;hydrogenCount&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;atom&lt;/span&gt; &lt;span class="attribute"&gt;elementType&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;C&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;y2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0.35&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;x2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;-2.1207&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a2&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;formalCharge&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;hydrogenCount&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;atom&lt;/span&gt; &lt;span class="attribute"&gt;elementType&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;C&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;y2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;-0.475&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;x2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;-2.1207&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a3&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;formalCharge&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;hydrogenCount&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;atom&lt;/span&gt; &lt;span class="attribute"&gt;elementType&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;C&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;y2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;-0.8875&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;x2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;-1.4063&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a4&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;formalCharge&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;hydrogenCount&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;atom&lt;/span&gt; &lt;span class="attribute"&gt;elementType&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;C&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;y2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;-0.475&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;x2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;-0.6918&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a5&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;formalCharge&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;hydrogenCount&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;atom&lt;/span&gt; &lt;span class="attribute"&gt;elementType&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;C&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;y2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0.35&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;x2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;-0.6918&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a6&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;formalCharge&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;hydrogenCount&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;0&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;atomArray&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;bondArray&lt;/span&gt; &lt;span class="attribute"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/schema&lt;/span&gt;&lt;span class="punct"&gt;'&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;bond&lt;/span&gt; &lt;span class="attribute"&gt;atomRefs2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a1 a2&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;order&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;S&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;b1&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;bond&lt;/span&gt; &lt;span class="attribute"&gt;atomRefs2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a2 a3&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;order&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;D&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;b2&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;bond&lt;/span&gt; &lt;span class="attribute"&gt;atomRefs2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a3 a4&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;order&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;S&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;b3&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;bond&lt;/span&gt; &lt;span class="attribute"&gt;atomRefs2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a4 a5&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;order&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;D&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;b4&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;bond&lt;/span&gt; &lt;span class="attribute"&gt;atomRefs2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a5 a6&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;order&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;S&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;b5&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;bond&lt;/span&gt; &lt;span class="attribute"&gt;atomRefs2&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a1 a6&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;order&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;D&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;b6&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;bondArray&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;molecule&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;spectrum&lt;/span&gt; &lt;span class="attribute"&gt;moleculeRef&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;nmrshiftdb7901&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="namespace"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="attribute"&gt;cml&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/dict/cml&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="namespace"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="attribute"&gt;cmlDict&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/dict/cmlDict&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="namespace"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="attribute"&gt;siUnits&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/units/siUnits&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;type&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;NMR&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="namespace"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="attribute"&gt;macie&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/dict/macie&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="namespace"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="attribute"&gt;units&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/units/units&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;nmrshiftdb15502&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="namespace"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="attribute"&gt;subst&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/dict/substDict&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="namespace"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;&lt;span class="attribute"&gt;nmr&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.nmrshiftdb.org/dict&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/schema/cml2/spect&lt;/span&gt;&lt;span class="punct"&gt;'&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;conditionList&lt;/span&gt; &lt;span class="attribute"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/schema&lt;/span&gt;&lt;span class="punct"&gt;'&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;scalar&lt;/span&gt; &lt;span class="attribute"&gt;dataType&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;xsd:string&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;units&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;siUnits:k&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;dictRef&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;cml:temp&lt;/span&gt;&lt;span class="punct"&gt;'&amp;gt;&lt;/span&gt;298&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;scalar&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;scalar&lt;/span&gt; &lt;span class="attribute"&gt;dataType&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;xsd:string&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;units&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;siUnits:hertz&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;dictRef&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;cml:field&lt;/span&gt;&lt;span class="punct"&gt;'&amp;gt;&lt;/span&gt;Unreported&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;scalar&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;conditionList&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;metadataList&lt;/span&gt; &lt;span class="attribute"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/schema&lt;/span&gt;&lt;span class="punct"&gt;'&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;metadata&lt;/span&gt; &lt;span class="attribute"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;nmr:OBSERVENUCLEUS&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;content&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;13C&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;metadataList&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;peakList&lt;/span&gt; &lt;span class="attribute"&gt;xmlns&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;http://www.xml-cml.org/schema&lt;/span&gt;&lt;span class="punct"&gt;'&amp;gt;&lt;/span&gt;
      &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt;&lt;span class="tag"&gt;peak&lt;/span&gt; &lt;span class="attribute"&gt;xUnits&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;units:ppm&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;peakShape&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;sharp&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;xValue&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;128.5&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;p0&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="attribute"&gt;atomRefs&lt;/span&gt;&lt;span class="punct"&gt;='&lt;/span&gt;&lt;span class="string"&gt;a1 a2 a3 a4 a5 a6&lt;/span&gt;&lt;span class="punct"&gt;'/&amp;gt;&lt;/span&gt;
    &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;peakList&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;spectrum&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="tag"&gt;cml&lt;/span&gt;&lt;span class="punct"&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The kind of output produced by NMRFetcher and NMRShiftDB could be used in a variety of ways. Notice, near the bottom of the document, how peak assignments are made relative the the atom labels in the &lt;tt&gt;molecule&lt;/tt&gt; declaration. It should be possible, for example, to create interactive 2-D structure diagrams from this document in which a user mouses over an atom and gets a C-13 chemical shift.&lt;/p&gt;

&lt;p&gt;NMRShiftDB is a valuable and free online resource for NMR spectroscopy. Programatically mixing its capabilities with free software and other online services offers numerous opportunities to build innovative chemical informatics systems.&lt;/p&gt;</description>
      <pubDate>Mon, 04 Sep 2006 13:28:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:4db46312-f5b9-4369-b9bc-d949f28b61c5</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/09/04/hacking-nmrshiftdb</link>
      <category>Databases</category>
      <category>nmrshiftdb</category>
      <category>cml</category>
      <category>rjb</category>
      <category>inchi</category>
      <category>smiles</category>
    </item>
  </channel>
</rss>
