<?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 depict</title>
    <link>http://depth-first.com/articles/tag/depict</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Walking the Web of Chemical Informatics</description>
    <item>
      <title>From InChI to Image with Ruby Open Babel and 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;Like SMILES, InChI is a line notation that can be used to encode and store chemical information relatively efficiently. Although there are a number of scenarios where this strategy is used, what many of them have in common is the need to eventually convert an InChI into a human-readable form. In most cases, this form will be a 2D chemical structure. This article will show how a small Ruby library can convert InChI strings into color PNG images with the help of &lt;a href="http://depth-first.com/articles/tag/rubyopenbabel"&gt;Ruby Open Babel&lt;/a&gt; and &lt;a href="http://depth-first.com/articles/tag/rcdk"&gt;Ruby CDK&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Our library accepts an InChI as input and produces a scaled PNG image as output. It re-uses part of a &lt;a href="http://depth-first.com/articles/2007/06/25/interconvert-almost-any-smiles-and-inchi-with-ruby-open-babel"&gt;previously-discussed&lt;/a&gt; library for the interconversion of SMILES and InChI.&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&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;openbabel&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="keyword"&gt;module &lt;/span&gt;&lt;span class="module"&gt;InChI&lt;/span&gt;
  &lt;span class="attribute"&gt;@@to_smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;OpenBabel&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;OBConversion&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;@@to_smiles&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;set_in_and_out_formats&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;smi&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;inchi_to_png&lt;/span&gt; &lt;span class="ident"&gt;inchi&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;path_to_png&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;width&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;height&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;inchi_to_smiles&lt;/span&gt; &lt;span class="ident"&gt;inchi&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;Image&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;smiles_to_png&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;path_to_png&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;width&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;height&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;inchi_to_smiles&lt;/span&gt; &lt;span class="ident"&gt;inchi&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;OpenBabel&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;OBMol&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;@@to_smiles&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;read_string&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;inchi&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="keyword"&gt;or&lt;/span&gt; &lt;span class="keyword"&gt;raise&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Can't parse InChI: &lt;span class="expr"&gt;#{inchi}&lt;/span&gt;.&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
      &lt;span class="attribute"&gt;@@to_smiles&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;write_string&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;strip&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;Testing&lt;/h4&gt;

Our library can be tested by saving it to a file called &lt;strong&gt;inchi.rb&lt;/strong&gt; and using interactive Ruby (the warning can safely be ignored for now):

&lt;div class="console"&gt;
&lt;pre&gt;
$ irb
irb(main):001:0&gt; require 'inchi'
./inchi.rb:3: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.
i=&gt; true
irb(main):002:0&gt; include InChI
=&gt; Object
irb(main):003:0&gt; inchi='InChI=1/C23H27FN4O2/c1-15-18(23(29)28-10-3-2-4-21(28)25-15)9-13-27-11-7-16(8-12-27)22-19-6-5-17(24)14-20(19)30-26-22/h5-6,14,16H,2-4,7-13H2,1H3' #risperidone
=&gt; "InChI=1/C23H27FN4O2/c1-15-18(23(29)28-10-3-2-4-21(28)25-15)9-13-27-11-7-16(8-12-27)22-19-6-5-17(24)14-20(19)30-26-22/h5-6,14,16H,2-4,7-13H2,1H3"
irb(main):004:0&gt; inchi_to_png inchi, 'risperidone.png', 300, 300
=&gt; nil
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This code produces the following image:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href="http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?cid=5073"&gt;&lt;img src="http://depth-first.com/demo/20070906/risperidone.png"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Our library can also be used on more complicated molecules, for example Brevetoxin:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ irb
irb(main):001:0&gt; require 'inchi'
./inchi.rb:3: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 InChI
=&gt; Object
irb(main):003:0&gt; inchi='InChI=1/C49H70O13/c1-26-17-36-39(22-45(52)58-36)57-44-21-38-40(62-48(44,4)23-26)18-28(3)46-35(55-38)11-7-6-10-31-32(59-46)12-8-14-34-33(54-31)13-9-15-43-49(5,61-34)24-42-37(56-43)20-41-47(60-42)30(51)19-29(53-41)16-27(2)25-50/h6-8,14,25-26,28-44,46-47,51H,2,9-13,15-24H2,1,3-5H3/b7-6-,14-8-' #brevetoxin a
=&gt; "InChI=1/C49H70O13/c1-26-17-36-39(22-45(52)58-36)57-44-21-38-40(62-48(44,4)23-26)18-28(3)46-35(55-38)11-7-6-10-31-32(59-46)12-8-14-34-33(54-31)13-9-15-43-49(5,61-34)24-42-37(56-43)20-41-47(60-42)30(51)19-29(53-41)16-27(2)25-50/h6-8,14,25-26,28-44,46-47,51H,2,9-13,15-24H2,1,3-5H3/b7-6-,14-8-"
irb(main):004:0&gt; inchi_to_png inchi, 'brevetoxin.png', 300, 200
=&gt; nil
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This produces the following image:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;a href="http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?cid=6437089"&gt;&lt;img src="http://depth-first.com/demo/20070906/brevetoxin.png"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;&lt;/p&gt;

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

&lt;p&gt;While our library could certainly be improved, it solves what otherwise would be a very difficult problem conveniently. Areas for further work include error handling and improving the appearance of the images (the latter is the aim of &lt;a href="http://depth-first.com/articles/tag/firefly"&gt;Firefly&lt;/a&gt;). Despite the fact that three programming languages are used (Ruby, C++, and Java), this complexity is neatly encapsulated behind a simple Ruby interface.&lt;/p&gt;</description>
      <pubDate>Thu, 06 Sep 2007 08:25:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:242847bf-aa4f-474d-979f-7b73ed072a28</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2007/09/06/from-inchi-to-image-with-ruby-open-babel-and-ruby-cdk</link>
      <category>Tools</category>
      <category>ruby</category>
      <category>rubycdk</category>
      <category>rcdk</category>
      <category>rubyopenbabel</category>
      <category>depict</category>
      <category>inchi</category>
      <category>sdg</category>
    </item>
    <item>
      <title>Anatomy of a Cheminformatics Web Application: Ajaxifying Depict</title>
      <description>&lt;p&gt;&lt;a href="http://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;The &lt;a href="http://depth-first.com/articles/2006/11/27/anatomy-of-a-cheminformatics-web-application-beautifying-depict"&gt;previous tutorial in this series&lt;/a&gt; showed some techniques for improving the appearance and usability of a simple cheminformatics Web application. That application, Depict, rendered color images of 2-D molecular structures when given a SMILES string. Still, something is missing. Wouldn't it be better if the application responded to individual keystrokes in the input field, rather than waiting for the user to hit the return key? In this tutorial, we'll see how to quickly accomplish this effect with a technology called "Ajax."&lt;/p&gt;

&lt;h4&gt;Downloads 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;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 Rails application that this tutorial starts with can be downloaded from &lt;a href="http://depth-first.com/demo/20061127/depict-20061127.tar.gz"&gt;this link&lt;/a&gt;. If you'd rather start working directly with the version of Depict produced by applying the changes outlined in this tutorial, the full source code can be downloaded from &lt;a href="http://depth-first.com/demo/20061204/depict-20061204.tar.gz"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you'll be running Depict on an AMD64 Linux system, you'll need to prepend your invocation of &lt;tt&gt;script/server&lt;/tt&gt; with &lt;tt&gt;LD_PRELOAD&lt;/tt&gt;. For example, on my system running Sun's JVM, the full command looks like:&lt;/p&gt;

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

&lt;h4&gt;A Brief Introduction to Ajax&lt;/h4&gt;

&lt;p&gt;When stripped down to its essentials, &lt;a href="http://ajaxian.com/"&gt;Ajax&lt;/a&gt; is nothing more than an asynchronous communication channel between Web browsers and Web servers. In the pre-Ajax model of client-server Web interactions, a browser would make a request to a server and then wait until getting a server response, which would take the form of a complete Web page. In the Ajax model, a browser makes a request to a server, continuing to function while the server generates a response, which takes the form of a small section of the page that gets replaced. For this reason, Ajax-enabled Web sites are far more application-like than the document-centric sites that preceded them.&lt;/p&gt;

&lt;h4&gt;Ajax Support in Rails&lt;/h4&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/20061127/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;Ajax is implemented in JavaScript using the &lt;tt&gt;HTMLHttpRequest&lt;/tt&gt; object, although working at this level can require a lot of code to do anything meaningful. Fortunately, Rails and other Web application frameworks provide high-level interfaces to Ajax. In Rails, Ajax support takes the form of a variety of helper methods, one of which we'll use in this tutorial: &lt;tt&gt;observe_field&lt;/tt&gt;. This method, an instance of the &lt;a href="http://en.wikipedia.org/wiki/Observer_pattern"&gt;Observer Pattern&lt;/a&gt;, assigns an Observer to monitor input activity in a text field.&lt;/p&gt;

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

&lt;p&gt;We'd like Depict to provide immediate feedback by rendering a SMILES string as it is keyed into the input field. If the partial SMILES string is valid, it will be rendered, otherwise, an error image will be rendered. At no point will the user need to press the return key to see an image of the SMILES string they are typing.&lt;/p&gt;

&lt;h4&gt;Step 1: Ajaxify the View&lt;/h4&gt;

&lt;p&gt;Let's start by adding an observer to Depict's input field. These changes will occur to the SMILES View, contained in &lt;strong&gt;depict/app/views/smiles/depict.rhtml&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Depict&amp;lt;/title&amp;gt;
    &amp;lt;%= stylesheet_link_tag &amp;quot;default&amp;quot;, :media =&amp;gt; &amp;quot;all&amp;quot; %&amp;gt;

    &amp;lt;!-- Nothing works without this line. --&amp;gt;
    &amp;lt;%= javascript_include_tag :defaults %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Depict a SMILES String&amp;lt;/h1&amp;gt;

    &amp;lt;!-- New id attribute needed by Ajax --&amp;gt;
    &amp;lt;div class=&amp;quot;image&amp;quot; id=&amp;quot;results&amp;quot; &amp;gt;
      &amp;lt;img src=&amp;quot;&amp;lt;%= image_for_smiles :smiles =&amp;gt; @smiles %&amp;gt;&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;
      &amp;lt;div class=&amp;quot;smiles&amp;quot;&amp;gt;
      &amp;lt;%= form_tag :action=&amp;gt;'depict' %&amp;gt;
        &amp;lt;label&amp;gt;SMILES: &amp;lt;/label&amp;gt;

        &amp;lt;!-- Ajaxified text field. --&amp;gt;
        &amp;lt;!-- We turn off autocomplete to simplfify the interface. --&amp;gt;
        &amp;lt;%= text_field_tag :smiles, @smiles, {:autocomplete =&amp;gt; &amp;quot;off&amp;quot;} %&amp;gt;
        &amp;lt;%= observe_field( :smiles,
                           :frequency =&amp;gt; 0.5,
                           :update    =&amp;gt; :results,
                           :url       =&amp;gt; { :action =&amp;gt; :ajax_depict } ) %&amp;gt;
      &amp;lt;%= end_form_tag %&amp;gt;
      &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;

  &amp;lt;div class=&amp;quot;about&amp;quot;&amp;gt;
    &amp;lt;!-- Update the URL to point to the new Depth-First article --&amp;gt;
    &amp;lt;a href=&amp;quot;http://depth-first.com/articles/2006/12/04/anatomy-of-a-cheminformatics-web-application-ajaxifying-depict&amp;quot;&amp;gt;About this Application&amp;lt;/a&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code introduces three key elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;tt&gt;javascript_include_tag&lt;/tt&gt; method is called, which is surprisingly easy to forget to do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The original &lt;tt&gt;text_field&lt;/tt&gt; method call is replaced by &lt;tt&gt;text_field_tag&lt;/tt&gt; to simplify coding. We disable browser-based autocompletion by setting the &lt;tt&gt;autocomplete&lt;/tt&gt; attribute to &lt;tt&gt;off&lt;/tt&gt;. This removes a feature unlikely to ever be used, and leads to a more streamlined interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;tt&gt;observe_field&lt;/tt&gt; method is called, linking activity in the text field to an Ajax action, &lt;tt&gt;ajax_depict&lt;/tt&gt;, that will update the image area. To accomplish this, we assign the &lt;tt&gt;div&lt;/tt&gt; containing our image the id "results."&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Making these changes and refreshing the browser window gives a screen like the one below:&lt;/p&gt;

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

&lt;p&gt;Although the client side of the Ajax communication channel is working, the server side is not. Let's fix that.&lt;/p&gt;

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

&lt;p&gt;Depict needs an Action and View that will be invoked in response to keyboard events in the SMILES input box. To do this, first add a new &lt;tt&gt;ajax_depict&lt;/tt&gt; method to &lt;tt&gt;SmilesController&lt;/tt&gt;, the source for which is found in &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;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;depict&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&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="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&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;else&lt;/span&gt;
      &lt;span class="attribute"&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;&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;def &lt;/span&gt;&lt;span class="method"&gt;image_for&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:bytes&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;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:bytes&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;&lt;span class="expr"&gt;#{flash[:smiles]}&lt;/span&gt;.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;span class="comment"&gt;# The new ajax_depict method.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;ajax_depict&lt;/span&gt;
    &lt;span class="attribute"&gt;@smiles&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;raw_post&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;Making the above changes and refreshing your browser should give an error message:&lt;/p&gt;

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

&lt;p&gt;The new &lt;tt&gt;ajax_depict&lt;/tt&gt; method is being called, but no associated template exits. This template contains the HTML that will be inserted into the &lt;tt&gt;div&lt;/tt&gt; with the &lt;tt&gt;results&lt;/tt&gt; id attribute that we set up in Step 1. We can resolve the error we're getting by simply creating a new file (&lt;strong&gt;depict/app/views/smiles/ajax_depict.rhtml&lt;/strong&gt;) containing the following partial template:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;img src=&amp;quot;&amp;lt;%= image_for_smiles :smiles =&amp;gt; @smiles %&amp;gt;&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, refreshing your browser should produce a screen like that shown below. We have now Ajaxified Depict, but we're not quite done yet.&lt;/p&gt;

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

&lt;h4&gt;Step 3: Update the Cascading Style Sheet&lt;/h4&gt;

&lt;p&gt;As you type a SMILES string into the input window, you may have noticed the input box being repositioned toward the top of the application window just prior to the display of a new image. This is due to the image area being resized to zero height as the new image is generated.&lt;/p&gt;

&lt;p&gt;Fortunately, the fix is simple; we'll just specify that the image area must be 400 pixels high, whether an image is being displayed or not. This is done by editing the &lt;tt&gt;image&lt;/tt&gt; selector in the CSS file at &lt;strong&gt;depict/public/stylesheets/default.css&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;.image {
    margin-left: auto;
    margin-right: auto;
    width: 400px;
    /* Keeps the input box from moving during image refresh.*/
    height: 400px;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Refreshing the Depict window should now give a statically-positioned SMILES input field.&lt;/p&gt;

&lt;h4&gt;Step 4: Backward Compatibility&lt;/h4&gt;

&lt;p&gt;As it stands, if the user presses the return key, they will see the "Enter SMILES Below" message. This is due to the change in the way SMILES strings are transmitted into the application. To fix this problem, we simply change the way that &lt;tt&gt;SmilesController&lt;/tt&gt; assigns the &lt;tt&gt;smiles&lt;/tt&gt; instance variable (&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="comment"&gt;# Uses new input method.&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&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="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&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="keyword"&gt;else&lt;/span&gt;
    &lt;span class="attribute"&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;&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;Making this change produces an interface that will render the correct image whether the return key is typed or not. If JavaScript is disabled, Depict will work exactly the same way as it did in the non-Ajax version.&lt;/p&gt;

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

&lt;p&gt;Ajax makes the Web more attractive than ever as an application development platform. In this tutorial, we've seen how using Rails made it very easy to give Depict the feel of an interactive SMILES depiction tool using Ajax. But a few details remain before we're ready to deploy this application on a Web server for the public to use. For example, we need to take server load and network latency into account, and we need to make sure Depict works well on all major browsers. The next articles in this series will address these issues.&lt;/p&gt;</description>
      <pubDate>Mon, 04 Dec 2006 15:06:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:04460726-dd5b-40ce-aeb8-1b8f055932a8</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/12/04/anatomy-of-a-cheminformatics-web-application-ajaxifying-depict</link>
      <category>Tools</category>
      <category>depict</category>
      <category>rails</category>
      <category>cheminformatics</category>
      <category>2d</category>
      <category>integration</category>
      <category>ajax</category>
    </item>
    <item>
      <title>Anatomy of a Cheminformatics Web Application: Beautifying Depict</title>
      <description>&lt;p&gt;&lt;a href="http://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;&lt;a href="http://depth-first.com/articles/2006/11/21/build-a-rails-cheminformatics-application-in-thirty-minutes"&gt;A recent article&lt;/a&gt; outlined the steps for building a &lt;a href="http://rubyonrails.org"&gt;Rails&lt;/a&gt; Web application that renders &lt;a href="http://www.daylight.com/smiles/index.html"&gt;SMILES&lt;/a&gt; strings as 2-D molecular images. Although this application, Depict, performed its stated purpose, it was neither much to look at nor as easy to use as it could be. In this tutorial, we'll give Depict a face-lift and make it more user-friendly.&lt;/p&gt;

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

&lt;p&gt;As it now stands, Depict accepts a SMILES string as input, and then renders a new Web page containing a 2-D molecular image. We'd like to make it easier to enter multiple SMILES strings by combining data entry and image display into the same Web page. We'd also like to make the application as a whole look better by using &lt;a href="http://www.w3.org/Style/CSS/"&gt;Cascading Style Sheets&lt;/a&gt; and other UI enhancements.&lt;/p&gt;

&lt;h4&gt;Download and Prerequisites&lt;/h4&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/20061127/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;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;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 Rails application that this tutorial starts with can be downloaded from &lt;a href="http://depth-first.com/demo/20061121/depict.tar.gz"&gt;this link&lt;/a&gt;. If you'd rather work with the version of Depict produced by applying the changes outlined in this tutorial, the full source code can be downloaded from &lt;a href="http://depth-first.com/demo/20061127/depict-20061127.tar.gz"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Step 1: Consolidate Actions&lt;/h4&gt;

&lt;p&gt;Our first version of Depict defined three &lt;tt&gt;SmilesController&lt;/tt&gt; actions: &lt;tt&gt;input&lt;/tt&gt;; &lt;tt&gt;depict&lt;/tt&gt;; and &lt;tt&gt;image_for&lt;/tt&gt;. Because we want to show the molecular image on the same page on which SMILES input happens, we'll consolidate &lt;tt&gt;input&lt;/tt&gt; and &lt;tt&gt;depict&lt;/tt&gt; into a single action.&lt;/p&gt;

&lt;p&gt;To do this, we'll edit &lt;strong&gt;depict/app/controllers/smiles_controller.rb&lt;/strong&gt; by removing the &lt;tt&gt;input&lt;/tt&gt; method and rewriting the &lt;tt&gt;depict&lt;/tt&gt; and &lt;tt&gt;image_for&lt;/tt&gt; methods:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&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;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;# Consolidated depict method.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;depict&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&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="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&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;else&lt;/span&gt;
      &lt;span class="attribute"&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;&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;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="ident"&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="comment"&gt;# Just return if we can't get a SMILES string.&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;smiles&lt;/span&gt;
      &lt;span class="keyword"&gt;return&lt;/span&gt;
    &lt;span class="keyword"&gt;end&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;We need to check whether the SMILES in &lt;tt&gt;image_for&lt;/tt&gt; is &lt;tt&gt;nil&lt;/tt&gt; because when the application is first lanched, no SMILES string is defined. By checking for this condition and exiting if found, our application can gracefully start up and respond to a blank input field.&lt;/p&gt;

&lt;p&gt;We no longer need a View for the &lt;tt&gt;input&lt;/tt&gt; action, the functionality of which we'll be moving into the View for our new &lt;tt&gt;depict&lt;/tt&gt; action. Delete &lt;strong&gt;depict/app/views/smiles/input.rhtml&lt;/strong&gt;, and edit &lt;strong&gt;depict/app/view/smiles/depict.rhtml&lt;/strong&gt; so that is looks like the following:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Depict&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Depict a SMILES String&amp;lt;/h1&amp;gt;
    &amp;lt;img src=&amp;quot;&amp;lt;%= url_for :action =&amp;gt; &amp;quot;image_for&amp;quot;, :smiles =&amp;gt; @smiles %&amp;gt;&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&amp;lt;br /&amp;gt;

    &amp;lt;%= form_tag :action=&amp;gt;'depict' %&amp;gt;
      &amp;lt;label&amp;gt;SMILES: &amp;lt;/label&amp;gt;
      &amp;lt;%= text_field('smiles', 'value', :value =&amp;gt; @smiles) %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= end_form_tag %&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This new template is simply a combination of the two previous templates. Pointing your browser to &lt;a href="http://localhost:3000/smiles/depict"&gt;http://localhost:3000/smiles/depict&lt;/a&gt; and entering a valid SMILES string should give a screen similar to the one below:&lt;/p&gt;

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

&lt;h4&gt;Step 2: Add a Helper for Serving Images&lt;/h4&gt;

&lt;p&gt;If a blank or invalid SMILES is entered, we'd like to give feedback by loading an image that reflects this condition. The user is expecting to see an image anyway, so we may as well put our error message there. To do so, we need to first re-think our &lt;tt&gt;image_for&lt;/tt&gt; action.&lt;/p&gt;

&lt;p&gt;Currently, &lt;tt&gt;image_for&lt;/tt&gt; tries to generate an image from any string of characters. When it fails, no image is produced, giving rise to the familar "broken image" icon below:&lt;/p&gt;

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

&lt;p&gt;We could add some conditional logic in our view that would detect an invalid or empty SMILES string. However, for several reasons such co-mingling of application code and HTML is generally considered a Bad Thing. Fortunately, Rails offers just what we need: Helpers. A helper is code contained in a module that is automatically included in a view.&lt;/p&gt;

&lt;p&gt;Each Rails Controller comes complete with an associated Helper. Our SmilesHelper was already created and wired together for us when we created the &lt;tt&gt;SmilesController&lt;/tt&gt;. All we need to do is to add our own Helper methods.&lt;/p&gt;

&lt;p&gt;We're going to add a method called &lt;tt&gt;image_for_smiles&lt;/tt&gt; that will return a URL to an image based on a SMILES string. It needs to handle three possible types of string input:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Blank SMILES: Returns a static URL to an image on our server indicating no SMILES string has been entered. We'll discuss where to put this image in Step 5.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Invalid SMILES: Returns a static URL to an image on our server indicating an invalid SMILES. We'll add this in Step 5.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Valid SMILES: Returns a dynamic URL that will generate a 2-D molecular image on the fly from binary data generated in the same manner as our current &lt;tt&gt;image_for&lt;/tt&gt; action.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's add the functionality we need to our &lt;tt&gt;SmilesHelper&lt;/tt&gt;, which is contained in the file &lt;strong&gt;depict/app/helpers/smiles_helper.rb&lt;/strong&gt;:&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;module &lt;/span&gt;&lt;span class="module"&gt;SmilesHelper&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;image_for_smiles&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;param&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;param&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="keyword"&gt;if&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;eql?&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="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/images/blank.png&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

    &lt;span class="ident"&gt;render&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;def &lt;/span&gt;&lt;span class="method"&gt;render&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;begin&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;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;400&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="number"&gt;400&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="keyword"&gt;rescue&lt;/span&gt;
      &lt;span class="keyword"&gt;return&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;/images/invalid.png&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="keyword"&gt;end&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="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;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:bytes&lt;/span&gt;&lt;span class="punct"&gt;]&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="ident"&gt;flash&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="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;smiles&lt;/span&gt;

    &lt;span class="ident"&gt;url_for&lt;/span&gt; &lt;span class="symbol"&gt;:action&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;image_for&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="symbol"&gt;:id&lt;/span&gt; &lt;span class="punct"&gt;=&amp;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;

&lt;p&gt;Here, we introduce another Rails element - the flash. The flash provides temporary storage for data that needs to be passed from one Action to another. In the &lt;tt&gt;render&lt;/tt&gt; method, we're storing the byte array created by Ruby CDK in the flash so that it can be sent into Depict's image window as dynamically-generated content.&lt;/p&gt;

&lt;p&gt;If successful, the &lt;tt&gt;render&lt;/tt&gt; method returns a URL of the form:&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;http://localhost:3000/smiles/image_for/SMILES&lt;/tt&gt;&lt;/p&gt;

&lt;p&gt;where &lt;tt&gt;SMILES&lt;/tt&gt; is the escaped form of the user-specified SMILES string. If two images are served with exactly the same URL, some browsers (e.g., Konqueror) will assume they represent the same image and will re-use the image in their cache. So, we append the SMILES string to the URL as a way to get these browsers to refresh Depict's image area.&lt;/p&gt;

&lt;h4&gt;Step 3: Invoke the New &lt;tt&gt;image_for_smiles&lt;/tt&gt; Method&lt;/h4&gt;

&lt;p&gt;We've added a new &lt;tt&gt;image_for_smiles&lt;/tt&gt; method as a Helper, but Depict isn't yet using it. Let's change that by modifying the way that our image URL is generated in &lt;strong&gt;depict/app/views/smiles/depict.rhtml&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Depict&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Depict a SMILES String&amp;lt;/h1&amp;gt;
    &amp;lt;img src=&amp;quot;&amp;lt;%= image_for_smiles :smiles =&amp;gt; @smiles %&amp;gt;&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&amp;lt;br /&amp;gt;

    &amp;lt;%= form_tag :action=&amp;gt;'depict' %&amp;gt;
      &amp;lt;label&amp;gt;SMILES: &amp;lt;/label&amp;gt;
      &amp;lt;%= text_field('smiles', 'value', :value =&amp;gt; @smiles) %&amp;gt;&amp;lt;br /&amp;gt;
    &amp;lt;%= end_form_tag %&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Step 4: Simplify &lt;tt&gt;SmilesController&lt;/tt&gt;&lt;/h4&gt;

&lt;p&gt;We're now no longer using &lt;tt&gt;SmilesController&lt;/tt&gt; (&lt;strong&gt;depict/app/controllers/smiles_controller.rb&lt;/strong&gt;) to perform the bulk of the work related to 2-D image generation. Let's update our Controller to reflect these changes:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;# No libraries need to be loaded now.&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;# Consolidated depict method.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;depict&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&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="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&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;else&lt;/span&gt;
      &lt;span class="attribute"&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;&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="comment"&gt;# Consolidated image_for 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="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:bytes&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;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:bytes&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;&lt;span class="expr"&gt;#{flash[:smiles]}&lt;/span&gt;.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;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice how much simpler the &lt;tt&gt;image_for&lt;/tt&gt; method now is. The byte array saved in Rails' flash (introduced in Step 2) is simply sent out as a PNG image to any receiver requesting it.&lt;/p&gt;

&lt;p&gt;Our application, when provided with a valid SMILES string, now looks like the image below.&lt;/p&gt;

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

&lt;h4&gt;Step 5: Add Static Images&lt;/h4&gt;

&lt;p&gt;We'd like to have Depict render an appropriate image in those cases where a molecular image can not be rendered. In fact, Depict is already configured to do so - all we need to do is add the images themselves.&lt;/p&gt;

&lt;p&gt;Where do we put these images? Rails creates several directories when an application template is produced. One of these is called &lt;strong&gt;public&lt;/strong&gt;. This directory in turn contains an &lt;strong&gt;images&lt;/strong&gt; subdirectory. Currently, &lt;strong&gt;depict/public/images&lt;/strong&gt; only contains the Rails logo. It is this directory into which static images are designed to go. Let's add these two images to &lt;strong&gt;depict/public/images&lt;/strong&gt;: &lt;a href="http://depth-first.com/demo/20061127/blank.png"&gt;blank.png&lt;/a&gt; and &lt;a href="http://depth-first.com/demo/20061127/invalid.png"&gt;invalid.png&lt;/a&gt;. You could, of course, create your own custom 400x400 pixel images for this purpose.&lt;/p&gt;

&lt;p&gt;Deleting any SMILES input from Depict now should generate the screen shown below.&lt;/p&gt;

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

&lt;p&gt;Not exactly subtle, but it gets the message across. A similar screen results by entering an invalid SMILES string, such as "hello".&lt;/p&gt;

&lt;h4&gt;Step 6: Create and Use a Cascading Style Sheet&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/0596527411?ie=UTF8&amp;amp;tag=depthfirst-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0596527411"&gt;&lt;img border="0" src="http://depth-first.com/demo/20061127/0596527411.01._AA_SCMZZZZZZZ_V37012485_.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=0596527411" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;We'd like to have fine-grained control over the appearance of our application through a single file - a job ideally suited for Cascading Style Sheets (CSS). Where do CSS files live in a Rails application? Along with the &lt;strong&gt;images&lt;/strong&gt; directory described above, Rails also creates a &lt;strong&gt;public/stylesheets&lt;/strong&gt; directory when an application template is generated. This is where custom style sheets can be placed. Create a CSS file called &lt;strong&gt;default.css&lt;/strong&gt; in this directory containing the following definitions:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;h1 {
    text-align: center;
    font-size: 30pt;
    background: #993333;
    color: white;
}

.image {
    margin-left: auto;
    margin-right: auto;
    width: 400px;
}

.smiles {
    margin-left: auto;
    margin-right: auto;
    width: 400px;
}

.smiles input {
    width: 100%;
    font-size: 18pt;
    text-align: center;
    border: solid #993333;
    border-width: 2px 2px 2px 2px;
}

.smiles label {
    background: #993333;
    color: white;
    padding: 4px;
    font: sans-serif;
    font-weight: bold;
}

.about {
    text-align: center;
    font-size: 16pt;
}

a:link,  a:visited { color: #930; }
a:hover, a:active {color: #FFFFFF; background: #993333;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, we need to tell Rails where to find the above CSS. Open up &lt;strong&gt;depict/app/views/smiles/depict.rhtml&lt;/strong&gt; and add the following eRuby line inside the &lt;tt&gt;head&lt;/tt&gt; tags:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;%= stylesheet_link_tag &amp;quot;default&amp;quot;, :media =&amp;gt; &amp;quot;all&amp;quot; %&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That's all there is to it. Reloading Depict should give a screen similar to the one below.&lt;/p&gt;

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

&lt;h4&gt;Step 7: Clean Up the View&lt;/h4&gt;

&lt;p&gt;You may have noticed that the style sheet added in the previous step defines some features we're not currently using. Let's update Depict's View (&lt;strong&gt;depict/app/views/depict.rhtml&lt;/strong&gt;) to reflect the changes to our CSS:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Depict&amp;lt;/title&amp;gt;
    &amp;lt;%= stylesheet_link_tag &amp;quot;default&amp;quot;, :media =&amp;gt; &amp;quot;all&amp;quot; %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Depict a SMILES String&amp;lt;/h1&amp;gt;
    &amp;lt;div class=&amp;quot;image&amp;quot;&amp;gt;
      &amp;lt;img src=&amp;quot;&amp;lt;%= image_for_smiles :smiles =&amp;gt; @smiles %&amp;gt;&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;
      &amp;lt;div class=&amp;quot;smiles&amp;quot;&amp;gt;
      &amp;lt;%= form_tag :action=&amp;gt;'depict' %&amp;gt;
        &amp;lt;label&amp;gt;SMILES: &amp;lt;/label&amp;gt;
        &amp;lt;%= text_field('smiles', 'value', :align=&amp;gt;'center', :value =&amp;gt; @smiles) %&amp;gt;&amp;lt;br /&amp;gt;
      &amp;lt;%= end_form_tag %&amp;gt;
      &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;

  &amp;lt;div class=&amp;quot;about&amp;quot;&amp;gt;
    &amp;lt;a href=&amp;quot;http://depth-first.com/articles/2006/11/27/anatomy-of-a-cheminformatics-web-application-beautifying-depict&amp;quot;&amp;gt;About this Application&amp;lt;/a&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The changes here consist of grouping related HTML elements together into &lt;tt&gt;div&lt;/tt&gt; blocks and adding a link to the article you're reading at the bottom of the article. The interaction of the above code and the style sheet we created in Step 6 produces a screen, such as the one below, when a valid SMILES string is entered.&lt;/p&gt;

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

&lt;h4&gt;Summary&lt;/h4&gt;

&lt;p&gt;Even if you haven't followed along through this tutorial, it should be apparent that Rails is a powerful tool for the agile development of Web applications. Although we haven't used any sophisticated techniques, we now have a working Depict server with a simple, logical Web interface that does something useful.&lt;/p&gt;

&lt;p&gt;But we're not quite done with Depict yet. Currently, you need to hit the return key to get a 2-D rendering. Wouldn't it be better if the application automatically updated the image as a SMILES string is typed? If you're thinking "Ajax", you're right on target.&lt;/p&gt;</description>
      <pubDate>Mon, 27 Nov 2006 15:05:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:7cdb3872-ba13-4b71-94d0-c5ed397b9405</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/11/27/anatomy-of-a-cheminformatics-web-application-beautifying-depict</link>
      <category>Tools</category>
      <category>rails</category>
      <category>ruby</category>
      <category>application</category>
      <category>depict</category>
      <category>smiles</category>
      <category>2d</category>
    </item>
    <item>
      <title>Looking at InChIs</title>
      <description>&lt;p&gt;InChI identifiers can be viewed both as unique molecular keys and as a language encoding molecular structure. With the right software, it is possible to decode any InChI to arrive at a human-readable molecular structure. This tutorial will show how to convert InChI identifiers into 2-D molecular renderings using open source tools.&lt;/p&gt;

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

&lt;p&gt;The InChI to 2-D image conversion process requires two pieces of software:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://depth-first.com/articles/2006/09/19/decoding-inchis-with-rino"&gt;Rino&lt;/a&gt; decodes InChI identifiers into molfiles. The resulting atomic coordinates are set to zero.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="http://depth-first.com/articles/2006/09/25/cdk-the-ruby-way-rcdk-0-2-0"&gt;RCDK&lt;/a&gt; assigns coordinates to the molfile produced by Rino, and renders the result.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Bring on the Code&lt;/h4&gt;

&lt;p&gt;The following Ruby code illustrates how the InChI for the pesticide fipronil (Regent) can be translated into a PNG image:&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;rino&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;util&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;InChI=1/C12H4Cl2F6N4OS/c13-5-1-4(11(15,16)17)2-6(14)8(5)24-10(22)9(7(3-21)23-24)26(25)12(18,19)20/h1-2H,22H2&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt; &lt;span class="comment"&gt;#fipronil&lt;/span&gt;
&lt;span class="ident"&gt;reader&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;InChIReader&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;molfile1&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;reader&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;inchi&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="comment"&gt;# lacks 2-D atomic coordinates&lt;/span&gt;
&lt;span class="ident"&gt;molfile2&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_molfile&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;molfile1&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="comment"&gt;# has 2-D atomic coordinates&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;Image&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;molfile_to_png&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;molfile2&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;fipronil.png&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="number"&gt;350&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Running this code produces the image &lt;strong&gt;fipronil.png&lt;/strong&gt; in your working directory:&lt;/p&gt;

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

&lt;h4&gt;Limitations&lt;/h4&gt;

&lt;p&gt;The technique illustrated here is subject to the same limitations as the underlying software. For Rino, this means that stereochemistry is ignored. For RCDK, this means that implicit hydrogen atoms, isotopes, and charges are omitted, and that layout of macrocycles and other complex ring systems may not subjectively appear very refined.&lt;/p&gt;

&lt;h4&gt;Other Software that Does This&lt;/h4&gt;

&lt;p&gt;To my knowledge, only one other Open Source package, &lt;a href="http://bkchem.zirael.org/inchi_en.html"&gt;BKChem&lt;/a&gt;, is capable of rendering InChIs as described here. BKChem's underlying InChI translation and depiction software, OASA, can also be &lt;a href="http://inchi.info/converter_en.html"&gt;accessed online&lt;/a&gt;. For comparison, OASA produces the following image for for the fipronil InChI:&lt;/p&gt;

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

&lt;p&gt;The &lt;a href="http://pubchem.ncbi.nlm.nih.gov/edit/"&gt;PubChem editor&lt;/a&gt; can also translate and render InChIs, but no source code appears to be available. PubChem's InChI translation and rendering output for fipronil is:&lt;/p&gt;

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

&lt;p&gt;&lt;a href="http://cdk.sf.net"&gt;The Chemistry Development Kit&lt;/a&gt;, on which RCDK is based, was recently upgraded to support reading InChI identifiers. For some time, CDK has been able to generate 2-D atomic coordinates.&lt;/p&gt;

&lt;p&gt;More information on InChI software can be found at Beda Kosata's &lt;a href="http://inchi.info/index.html"&gt;InChI.info&lt;/a&gt; site.&lt;/p&gt;

&lt;h4&gt;The Final Word&lt;/h4&gt;

&lt;p&gt;Within certain limitations, it is quite feasible to programatically obtain a 2-D molecular image for any InChI identifier. Combining this capability with other chemical informatics software and services offers numerous possibilities to use InChI in innovative ways.&lt;/p&gt;</description>
      <pubDate>Tue, 26 Sep 2006 14:35:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:a6f32cae-5226-4b4d-9ab6-6ecd0a788c40</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/09/26/looking-at-inchis</link>
      <category>Graphics</category>
      <category>inchi</category>
      <category>rcdk</category>
      <category>rino</category>
      <category>depict</category>
      <category>2d</category>
      <category>ruby</category>
    </item>
  </channel>
</rss>
