A recent article 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 Ruby on Rails 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.
Simplified Molecular Input Line Entry System (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 line notations, 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 online chemistry databases. 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.
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.
Depict is a Web application originally developed by Daylight 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?
About This Tutorial Series
This tutorial is the first in a series describing how to build a Depict server using 100% Open Source 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.
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.
Download and Prerequisites
The complete Depict application can be downloaded from this link.
A Note on Ruby Java Bridge and AMD64 Linux Platforms
Our Depict application will use Ruby Java Bridge (RJB) as a Ruby interface to Java bytecode. Recently, a problem with RJB on AMD64-Linux was uncovered. This problem prevents third-party jarfiles from being loaded after Rails has been loaded.
In practice, this means that the command to start the Rails server (Step 2) needs to be prefixed with an assignment of
LD_PRELOAD. You also need to make
LD_LIBRARY_PATH point to your native Java libraries. On my platform, which is AMD64-Linux running Sun's JVM, the commands are:
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
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.
Step 1: Create the Application
Getting started with Rails is as simple as issuing the
rails command with the name of your application as an argument:
Executing this command creates a complete Rails application template under the depict subdirectory in your working directory. You build your application by editing the files and directories that were generated.
Step 2: Start the Server
You can start the Depict application by running the included server script:
$ cd depict $ ruby script/server => Booting WEBrick... => Rails application started on http://0.0.0.0:3000 => 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
Let's see what Depict looks like so far. Point your browser to http://localhost:3000. You should see the following page:
Congratulations! You're now running Ruby on Rails.
Step 3: Create the SmilesController
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:
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
SmilesController is just a skeleton:
class SmilesController < ApplicationController end
SmilesController the ability to accept a SMILES string as input by adding an
class SmilesController < ApplicationController def input end end
Step 4: Create a Form
At this stage, pointing your browser to http://localhost:3000/smiles/input gives a screen containing an error message:
Rails is looking for view that doesn't exist, so let's create one. To your depict/app/views/smiles directory, add the following file, called input.rhtml:
<html> <head> <title>Enter a SMILES String</title> </head> <body> <%= form_tag :action=>'depict' %> Enter a SMILES String: <br /> <%= text_field('smiles', 'value') %><br /> <%= end_form_tag %> </body> </html>
This HTML view is an example of Ruby's templating mechanism, eRuby, which was discussed earlier in the context of converting SD files to HTML. In the template above, we've configured our form to invoke an action called
depict when submitted. This action does not yet exist, but will be created in Step 5 below.
Now, pointing your browser to http://localhost:3000/smiles/input should give an input field:
Let's try it. Submitting the SMILES string for benzene gives the following error screen:
We haven't defined the
depict action yet, a fact that Rails is communicating with this error message.
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.
Step 5: Add a Depict Action
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
depict method to depict/app/controllers/smiles_controller.rb:
def depict @smiles = @params[:smiles][:value] end
Of course, our application still won't run properly because we haven't created a view for the new
depict method to use. Let's do this by adding the following file, named depict.rb to the depict/app/views/smiles directory:
<html> <head> <title>Depict SMILES: <%= @smiles %></title> </head> <body> <h1>SMILES: <%= @smiles %></h1> </body> </html>
Notice how the instance variable
@smiles is available for use within the template.
Let's have a look at Depict so far. Pointing your browser to http://localhost:3000/smiles/input, entering the SMILES string for benzene, and pressing return produces the page show below:
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.
Step 6: Generate the 2-D Image
We'll use a method called
image_for, which we'll define shortly. The file depict/app/views/smiles/depict should look like this:
<html> <head> <title>Depict SMILES: <%= @smiles %></title> </head> <body> <h1>SMILES:<%= @smiles %></h1> <img src="<%= url_for :action => "image_for", :smiles => @smiles %>"></img> </body> </html>
img tag is a placeholder for now. It loads an image dynamically generated from the
image_for method, which we'll shortly add to
SmilesController. We pass the SMILES string as a parameter.
image_for 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.
In addition to an
image_for method, we'll need to add some accessory code to make it work. Edit depict/app/controllers/smiles_controller.rb so that it looks like this:
# Load the RCDK library require_gem 'rcdk' require 'rcdk/util' # New jrequire calls. jrequire 'java.io.ByteArrayOutputStream' jrequire 'net.sf.structure.cdk.util.ImageKit' jrequire 'javax.imageio.ImageIO' class SmilesController < ApplicationController # Already defined. def input end # Already defined. def depict @smiles = @params[:smiles][:value] end # New method. def image_for smiles = @params[:smiles] mol = RCDK::Util::Lang.read_smiles smiles mol = RCDK::Util::XY::coordinate_molecule mol out=Java::Io::ByteArrayOutputStream.new image=Net::Sf::Structure::Cdk::Util::ImageKit.createRenderedImage(mol, 300, 300) Javax::Imageio::ImageIO.write(image, "png", out) send_data(out.toByteArray, :type => "image/png", :disposition => "inline", :filename => "molecule.png") end end
Let's test the application with a real-world example. The achiral SMILES string for Carmine is:
Pointing your browser to http://localhost:3000/smiles/input and entering the above SMILES string produces a color 2-D image of the structure of the red food coloring:
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 AJAX 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.