From c1b22b7f77436fab48749e9ddc5de29cef2de7fc Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Mon, 20 Aug 2012 12:31:39 +0200 Subject: initial opentox-server version --- .gitignore | 6 +- Gemfile | 4 ++ VERSION | 1 + application.rb | 176 +++++++++++++++++++----------------------------------- compound.gemspec | 25 ++++++++ config.ru | 11 ++-- public/robots.txt | 2 - 7 files changed, 101 insertions(+), 124 deletions(-) create mode 100644 Gemfile create mode 100644 VERSION create mode 100644 compound.gemspec delete mode 100644 public/robots.txt diff --git a/.gitignore b/.gitignore index 8300cb2..4040c6c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ -tmp/* -log/* +*.gem +.bundle +Gemfile.lock +pkg/* diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..2142a18 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source :gemcutter +gemspec +gem "opentox-server", :path => "../opentox-server" +gem "opentox-client", :path => "../opentox-client" diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..8c5ba87 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +5.0.0pre1 diff --git a/application.rb b/application.rb index fe04547..b59f484 100644 --- a/application.rb +++ b/application.rb @@ -1,124 +1,72 @@ -# Java environment -ENV["JAVA_HOME"] = "/usr/lib/jvm/java-6-sun" unless ENV["JAVA_HOME"] -java_dir = File.join File.expand_path(File.dirname(__FILE__)),"java" -cdk = File.join java_dir, "cdk-1.3.5.jar" -jchempaint = File.join java_dir, "cdk-jchempaint-15.jar" -ENV["CLASSPATH"] = "#{ENV["CLASSPATH"]}:#{java_dir}:#{cdk}:#{jchempaint}" +require 'openbabel' +module OpenTox + class Application < Service -require 'rubygems' -require 'rjb' -gem "opentox-ruby", "~> 3" -require 'opentox-ruby' + FORMATS = { + "chemical/x-daylight-smiles" => "smi", + "chemical/x-inchi" => "inchi", + #"chemical/x-inchikey" => "inchikey", + # OpenBabel segfaults randomly durng inchikey calculation + "chemical/x-mdl-sdfile" => "sdf", + "chemical/x-mdl-molfile" => "sdf", + "image/png" => 'png', + } -before do - @inchi = URI.unescape request.env['REQUEST_URI'].sub(/^\//,'').sub(/.*compound\//,'').sub(/\/smarts.*$/,'').sub(/\/image/,'').sub(/\?.*$/,'') # hack to avoid sinatra's URI/CGI unescaping, splitting, ..." - puts @inchi -end - -# Display activating (red) and deactivating (green) substructures. Overlaps betwen activating and deactivating structures are marked in yellow. -# @example -# curl http://webservices.in-silico.ch/compound/compound/InChI=1S/C6H5NO2/c8-7(9)6-4-2-1-3-5-6/h1-5H/smarts/activating/cN/ccN/deactivating/cc" > img.png -# @return [image/png] Image with highlighted substructures -get %r{/(.+)/smarts/activating/(.*)/deactivating/(.*)$} do |inchi,activating,deactivating| - smiles = OpenTox::Compound.from_inchi(@inchi).to_smiles - activating = activating.to_s.split(/\//).collect{|s| s.gsub(/"/,'')} - deactivating = deactivating.to_s.split(/\//).collect{|s| s.gsub(/"/,'')} - content_type "image/png" - attachment "#{smiles}.png" - begin - Rjb.load(nil,["-Xmx64m"])# avoid JVM memory allocation problems - s = Rjb::import('Structure').new(smiles,150) - s.match_deactivating(deactivating) - s.match_activating(activating) - s.show - rescue => e - LOGGER.warn e.message - end -end + helpers do + # Convert identifier from OpenBabel input_format to OpenBabel output_format + def obconversion(identifier,input_format,output_format) + obconversion = OpenBabel::OBConversion.new + obmol = OpenBabel::OBMol.new + obconversion.set_in_and_out_formats input_format, output_format + obconversion.read_string obmol, identifier + case output_format + when /smi|can|inchi/ + obconversion.write_string(obmol).gsub(/\s/,'').chomp + else + obconversion.write_string(obmol) + end + end + end -def png_from_smiles(smiles) - begin - Rjb.load(nil,["-Xmx64m","-Djava.awt.headless=true"])# avoid JVM memory allocation problems - Rjb::import('Structure').new(smiles,150).show - rescue - LOGGER.warn e.message - end -end + before do + @inchi = URI.unescape request.env['REQUEST_URI'].sub(/^\//,'').sub(/.*compound\//,'').sub(/\/smarts.*$/,'').sub(/\/image/,'').sub(/\?.*$/,'') # hack to avoid sinatra's URI/CGI unescaping, splitting, ..." + end -# Get png image -# @return [image/png] Image data -get %r{/(.+)/image} do |inchi| # catches all remaining get requests - smiles = OpenTox::Compound.from_inchi(@inchi).to_smiles - content_type "image/png" - attachment "#{smiles}.png" - png_from_smiles(smiles) -end + get "/compound/?" do + not_implemented_error "Object listing not implemented, because compounds are not stored at the server.", to("/compound") + end -# Get compound representation -# @param [optinal, HEADER] Accept one of `chemical/x-daylight-smiles, chemical/x-inchi, chemical/x-mdl-sdfile, chemical/x-mdl-molfile, text/plain, image/gif, image/png`, defaults to chemical/x-daylight-smiles -# @example Get smiles -# curl http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H -# @example Get all known names -# curl -H "Accept:text/plain" http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H -# @return [chemical/x-daylight-smiles, chemical/x-inchi, chemical/x-mdl-sdfile, chemical/x-mdl-molfile, text/plain, image/gif, image/png] Compound representation -get %r{/(.+)} do |inchi| # catches all remaining get requests - #inchi = URI.unescape request.env['REQUEST_URI'].sub(/^\//,'').sub(/.*compound\//,'') # hack to avoid sinatra's URI/CGI unescaping, splitting, ..." - case request.env['HTTP_ACCEPT'] - when "*/*" - response['Content-Type'] = "chemical/x-daylight-smiles" - OpenTox::Compound.from_inchi(@inchi).to_smiles - when "chemical/x-daylight-smiles" - response['Content-Type'] = "chemical/x-daylight-smiles" - OpenTox::Compound.from_inchi(@inchi).to_smiles - when "chemical/x-inchi" - response['Content-Type'] = "chemical/x-inchi" - @inchi - when "chemical/x-mdl-sdfile" - response['Content-Type'] = "chemical/x-mdl-sdfile" - OpenTox::Compound.from_inchi(@inchi).to_sdf - when "image/gif" - response['Content-Type'] = "image/gif" - OpenTox::Compound.from_inchi(@inchi).to_gif - when "image/png" - response['Content-Type'] = "image/png" - png_from_smiles(OpenTox::Compound.from_inchi(@inchi).to_smiles) - when "text/plain" - response['Content-Type'] = "text/plain" - uri = File.join @@cactus_uri,@inchi,"names" - RestClient.get(uri).body - else - raise OpenTox::BadRequestError.new "Unsupported MIME type '#{request.env['HTTP_ACCEPT']}'" - end -end + get %r{/compound/(.+)/image} do |inchi| # catches all remaining get requests + obconversion @inchi, "inchi", "png" + end -# Create a new compound URI (compounds are not saved at the compound service) -# @param [HEADER] Content-type one of `chemical/x-daylight-smiles, chemical/x-inchi, chemical/x-mdl-sdfile, chemical/x-mdl-molfile, text/plain` -# @example Create compound from Smiles string -# curl -X POST -H "Content-type:chemical/x-daylight-smiles" --data "c1ccccc1" http://webservices.in-silico.ch/compound -# @example Create compound from name, uses an external lookup service and should work also with trade names, CAS numbers, ... -# curl -X POST -H "Content-type:text/plain" --data "Benzene" http://webservices.in-silico.ch/compound -# @param [BODY] - string with identifier/data in selected Content-type -# @return [text/uri-list] compound URI -post '/?' do + # Get compound representation + # @param [optinal, HEADER] Accept one of `chemical/x-daylight-smiles, chemical/x-inchi, chemical/x-mdl-sdfile, chemical/x-mdl-molfile, text/plain, image/gif, image/png`, defaults to chemical/x-daylight-smiles + # @example Get smiles + # curl http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H + # @example Get all known names + # curl -H "Accept:text/plain" http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H + # @return [chemical/x-daylight-smiles, chemical/x-inchi, chemical/x-mdl-sdfile, chemical/x-mdl-molfile, text/plain, image/gif, image/png] Compound representation + get %r{/compound/(.+)} do |inchi| # catches all remaining get requests + bad_request_error "Unsupported MIME type '#{@accept}.", uri unless FORMATS.keys.include? @accept + return @inchi if @accept == "chemical/x-inchi" + obconversion @inchi, "inchi", FORMATS[@accept] + end - input = request.env["rack.input"].read - response['Content-Type'] = 'text/uri-list' - begin - case request.content_type - when /chemical\/x-daylight-smiles/ - OpenTox::Compound.from_smiles(input).uri + "\n" - when /chemical\/x-inchi/ - OpenTox::Compound.from_inchi(input).uri + "\n" - when /chemical\/x-mdl-sdfile|chemical\/x-mdl-molfile/ - OpenTox::Compound.from_sdf(input).uri + "\n" - when /text\/plain/ - OpenTox::Compound.from_name(input).uri + "\n" - else - status 400 - "Unsupported MIME type '#{request.content_type}'" + # Create a new compound URI (compounds are not saved at the compound service) + # @param [HEADER] Content-type one of `chemical/x-daylight-smiles, chemical/x-inchi, chemical/x-mdl-sdfile, chemical/x-mdl-molfile, text/plain` + # @example Create compound from Smiles string + # curl -X POST -H "Content-type:chemical/x-daylight-smiles" --data "c1ccccc1" http://webservices.in-silico.ch/compound + # @example Create compound from name, uses an external lookup service and should work also with trade names, CAS numbers, ... + # curl -X POST -H "Content-type:text/plain" --data "Benzene" http://webservices.in-silico.ch/compound + # @param [BODY] - string with identifier/data in selected Content-type + # @return [text/uri-list] compound URI + post '/compound/?' do + response['Content-Type'] = 'text/uri-list' + bad_request_error "Unsupported MIME type '#{@content_type}.", uri unless FORMATS.keys.include? @content_type + return to(File.join("/compound",@body)) if @content_type == "chemical/x-inchi" + to(File.join("compound",obconversion(@body, FORMATS[@content_type], "inchi"))) end - rescue - status 400 - "Cannot process request '#{input}' for content type '#{request.content_type}'" + end end diff --git a/compound.gemspec b/compound.gemspec new file mode 100644 index 0000000..0d0e9d2 --- /dev/null +++ b/compound.gemspec @@ -0,0 +1,25 @@ +# -*- encoding: utf-8 -*- +$:.push File.expand_path("../lib", __FILE__) + +Gem::Specification.new do |s| + s.name = "opentox-compound" + s.version = File.read("./VERSION") + s.authors = ["Christoph Helma"] + s.email = ["helma@in-silico.ch"] + s.homepage = "http://github.com/OpenTox/compound" + s.summary = %q{Toxbank compound service} + s.description = %q{Toxbank compound service} + s.license = 'GPL-3' + + s.rubyforge_project = "task" + + s.files = `git ls-files`.split("\n") + s.required_ruby_version = '>= 1.9.2' + + # specify any dependencies here; for example: + s.add_runtime_dependency "opentox-server", "#{VERSION}" + s.add_runtime_dependency "rjb" + s.add_runtime_dependency "openbabel" + s.post_install_message = "Please configure your service in ~/.opentox/config/compound.rb" +end + diff --git a/config.ru b/config.ru index a1aab0d..41e7811 100644 --- a/config.ru +++ b/config.ru @@ -1,6 +1,5 @@ -require 'rubygems' -require 'opentox-ruby' -require 'config/config_ru' -run Sinatra::Application -set :raise_errors, false -set :show_exceptions, false \ No newline at end of file +SERVICE = "compound" +require 'bundler' +Bundler.require +require './application.rb' +run OpenTox::Application diff --git a/public/robots.txt b/public/robots.txt deleted file mode 100644 index 1f53798..0000000 --- a/public/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: / -- cgit v1.2.3