opentox-ruby-api-wrapper 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +674 -0
- data/README.rdoc +23 -0
- data/Rakefile +64 -0
- data/VERSION +1 -0
- data/lib/algorithm.rb +37 -0
- data/lib/compound.rb +67 -0
- data/lib/dataset.rb +94 -0
- data/lib/environment.rb +33 -0
- data/lib/feature.rb +48 -0
- data/lib/helper.rb +26 -0
- data/lib/model.rb +71 -0
- data/lib/opentox-ruby-api-wrapper.rb +13 -0
- data/lib/opentox.rb +27 -0
- data/lib/spork.rb +81 -0
- data/lib/task.rb +55 -0
- data/lib/tasks/opentox.rb +135 -0
- data/lib/tasks/redis.rb +125 -0
- data/lib/templates/config.ru +23 -0
- data/lib/templates/config.yaml +10 -0
- data/lib/utils.rb +9 -0
- metadata +84 -0
data/README.rdoc
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
= opentox-ruby-api-wrapper
|
2
|
+
|
3
|
+
Ruby wrapper for the OpenTox REST API (http://www.opentox.org)
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
Run the following if you haven't already:
|
8
|
+
|
9
|
+
gem sources -a http://gems.github.com
|
10
|
+
|
11
|
+
Install the gem:
|
12
|
+
|
13
|
+
sudo gem install helma-opentox-ruby-api-wrapper
|
14
|
+
|
15
|
+
== Usage
|
16
|
+
|
17
|
+
- set the environment variables OPENTOX_COMPOUNDS, OPENTOX_FEATURES, OPENTOX_DATASETS, OPENTOX_FMINER to the base URI of the OpenTox REST webservices
|
18
|
+
- require 'opentox-ruby-api-wrapper' in your ruby application
|
19
|
+
- consult the rdoc API documentation for details
|
20
|
+
|
21
|
+
== Copyright
|
22
|
+
|
23
|
+
Copyright (c) 2009 Christoph Helma. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "opentox-ruby-api-wrapper"
|
8
|
+
gem.summary = %Q{Ruby wrapper for the OpenTox REST API}
|
9
|
+
gem.description = %Q{Ruby wrapper for the OpenTox REST API (http://www.opentox.org)}
|
10
|
+
gem.email = "helma@in-silico.ch"
|
11
|
+
gem.homepage = "http://github.com/helma/opentox-ruby-api-wrapper"
|
12
|
+
gem.authors = ["Christoph Helma"]
|
13
|
+
gem.add_dependency "technoweenie-rest-client"
|
14
|
+
gem.add_dependency "sinatra"
|
15
|
+
gem.add_dependency "rack"
|
16
|
+
gem.add_dependency "rack-contrib"
|
17
|
+
gem.add_dependency "thin"
|
18
|
+
gem.add_dependency "cucumber"
|
19
|
+
gem.add_dependency "ezmobius-redis-rb"
|
20
|
+
gem.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*", 'lib/jeweler/templates/.gitignore']
|
21
|
+
gem.files.include %w(lib/tasks/opentox.rb, lib/tasks/redis.rb, lib/environment.rb, lib/algorithm.rb, lib/compound.rb, lib/dataset.rb, lib/feature.rb, lib/model.rb, lib/utils.rb, lib/templates/*)
|
22
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
23
|
+
end
|
24
|
+
rescue LoadError
|
25
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/*_test.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
require 'rcov/rcovtask'
|
37
|
+
Rcov::RcovTask.new do |test|
|
38
|
+
test.libs << 'test'
|
39
|
+
test.pattern = 'test/**/*_test.rb'
|
40
|
+
test.verbose = true
|
41
|
+
end
|
42
|
+
rescue LoadError
|
43
|
+
task :rcov do
|
44
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
task :test => :check_dependencies
|
49
|
+
|
50
|
+
task :default => :test
|
51
|
+
|
52
|
+
require 'rake/rdoctask'
|
53
|
+
Rake::RDocTask.new do |rdoc|
|
54
|
+
if File.exist?('VERSION')
|
55
|
+
version = File.read('VERSION')
|
56
|
+
else
|
57
|
+
version = ""
|
58
|
+
end
|
59
|
+
|
60
|
+
rdoc.rdoc_dir = 'rdoc'
|
61
|
+
rdoc.title = "opentox-ruby-api-wrapper #{version}"
|
62
|
+
rdoc.rdoc_files.include('README*')
|
63
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
64
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.1.0
|
data/lib/algorithm.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module OpenTox
|
2
|
+
module Algorithm
|
3
|
+
|
4
|
+
class Fminer < OpenTox
|
5
|
+
# Create a new dataset with BBRC features
|
6
|
+
def self.create(params)
|
7
|
+
puts params[:dataset_uri]
|
8
|
+
uri = RestClient.post File.join(@@config[:services]["opentox-algorithm"],'fminer'), :dataset_uri => params[:dataset_uri]
|
9
|
+
print "fminer finsihed "
|
10
|
+
puts uri
|
11
|
+
uri
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Similarity < OpenTox
|
16
|
+
|
17
|
+
def self.tanimoto(dataset1,compound1,dataset2,compound2)
|
18
|
+
RestClient.get File.join(@@config[:services]["opentox-algorithm"], 'tanimoto/dataset',dataset1.name,compound1.inchi,'dataset',dataset2.name,compound2.inchi)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.weighted_tanimoto(dataset1,compound1,dataset2,compound2)
|
22
|
+
# URI.escape does not work here
|
23
|
+
uri = File.join(@@config[:services]["opentox-algorithm"], 'weighted_tanimoto/dataset',CGI.escape(dataset1.name),'compound',CGI.escape(compound1.inchi),'dataset',CGI.escape(dataset2.name),'compound',CGI.escape(compound2.inchi))
|
24
|
+
RestClient.get uri
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class Lazar < OpenTox
|
30
|
+
# Create a new prediction model from a dataset
|
31
|
+
def self.create(params)
|
32
|
+
RestClient.post File.join(@@config[:services]["opentox-algorithm"],"lazar_classification"), params
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
data/lib/compound.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module OpenTox
|
2
|
+
|
3
|
+
# uri: /compound/:inchi
|
4
|
+
class Compound < OpenTox
|
5
|
+
|
6
|
+
attr_reader :inchi
|
7
|
+
|
8
|
+
# Initialize with <tt>:uri => uri</tt>, <tt>:smiles => smiles</tt> or <tt>:name => name</tt> (name can be also an InChI/InChiKey, CAS number, etc)
|
9
|
+
def initialize(params)
|
10
|
+
@@cactus_uri="http://cactus.nci.nih.gov/chemical/structure/"
|
11
|
+
if params[:smiles]
|
12
|
+
@inchi = smiles2inchi(params[:smiles])
|
13
|
+
@uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi))
|
14
|
+
elsif params[:inchi]
|
15
|
+
@inchi = params[:inchi]
|
16
|
+
@uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi))
|
17
|
+
elsif params[:name]
|
18
|
+
@inchi = RestClient.get "#{@@cactus_uri}#{params[:name]}/stdinchi"
|
19
|
+
@uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi))
|
20
|
+
elsif params[:uri]
|
21
|
+
@inchi = params[:uri].sub(/^.*InChI/, 'InChI')
|
22
|
+
@uri = params[:uri]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the (canonical) smiles
|
27
|
+
def smiles
|
28
|
+
obconversion(@inchi,'inchi','can')
|
29
|
+
end
|
30
|
+
|
31
|
+
def sdf
|
32
|
+
obconversion(@inchi,'inchi','sdf')
|
33
|
+
end
|
34
|
+
|
35
|
+
# Matchs a smarts string
|
36
|
+
def match?(smarts)
|
37
|
+
obconversion = OpenBabel::OBConversion.new
|
38
|
+
obmol = OpenBabel::OBMol.new
|
39
|
+
obconversion.set_in_format('inchi')
|
40
|
+
obconversion.read_string(obmol,@inchi)
|
41
|
+
smarts_pattern = OpenBabel::OBSmartsPattern.new
|
42
|
+
smarts_pattern.init(smarts)
|
43
|
+
smarts_pattern.match(obmol)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Match an array of smarts features, returns matching features
|
47
|
+
def match(smarts_dataset)
|
48
|
+
smarts_dataset.all_features.collect{ |uri| uri if self.match?(Feature.new(:uri => uri).name) }.compact
|
49
|
+
end
|
50
|
+
|
51
|
+
def smiles2inchi(smiles)
|
52
|
+
obconversion(smiles,'smi','inchi')
|
53
|
+
end
|
54
|
+
|
55
|
+
def smiles2cansmi(smiles)
|
56
|
+
obconversion(smiles,'smi','can')
|
57
|
+
end
|
58
|
+
|
59
|
+
def obconversion(identifier,input_format,output_format)
|
60
|
+
obconversion = OpenBabel::OBConversion.new
|
61
|
+
obmol = OpenBabel::OBMol.new
|
62
|
+
obconversion.set_in_and_out_formats input_format, output_format
|
63
|
+
obconversion.read_string obmol, identifier
|
64
|
+
obconversion.write_string(obmol).gsub(/\s/,'').chomp
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/dataset.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module OpenTox
|
2
|
+
|
3
|
+
# key: /datasets
|
4
|
+
# set: dataset uris
|
5
|
+
# key: /dataset/:dataset/compounds
|
6
|
+
# set: compound uris
|
7
|
+
# key: /dataset/:dataset/compound/:inchi
|
8
|
+
# set: feature uris
|
9
|
+
class Dataset < OpenTox
|
10
|
+
|
11
|
+
# Initialize with <tt>:uri => uri</tt> or <tt>:name => name</tt> (creates a new dataset)
|
12
|
+
def initialize(uri)
|
13
|
+
super(uri)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.create(params)
|
17
|
+
uri = RestClient.post @@config[:services]["opentox-dataset"], :name => params[:name]
|
18
|
+
Dataset.new(uri.to_s)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.find(params)
|
22
|
+
begin
|
23
|
+
if params[:name]
|
24
|
+
uri = File.join(@@config[:services]["opentox-dataset"], URI.encode(params[:name]))
|
25
|
+
elsif params[:uri]
|
26
|
+
uri = params[:uri]
|
27
|
+
end
|
28
|
+
RestClient.get uri # check if the resource is available
|
29
|
+
Dataset.new(uri) if uri
|
30
|
+
rescue
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.find_or_create(params)
|
36
|
+
self.create(params) unless self.find(params)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.base_uri
|
40
|
+
@@config[:services]["opentox-dataset"]
|
41
|
+
end
|
42
|
+
|
43
|
+
def import(params)
|
44
|
+
if params[:csv]
|
45
|
+
# RestClient seems not to work for file uploads
|
46
|
+
#RestClient.post @uri + '/import', :compound_format => params[:compound_format], :content_type => "text/csv", :file => File.new(params[:csv])
|
47
|
+
`curl -X POST -F "file=@#{params[:csv]};type=text/csv" -F compound_format=#{params[:compound_format]} #{@uri + '/import'}`
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def add(features)
|
52
|
+
RestClient.put @uri, :features => features
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get all compounds from a dataset
|
56
|
+
def compound_uris
|
57
|
+
RestClient.get(File.join(@uri, 'compounds')).split("\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
def compounds
|
61
|
+
compound_uris.collect{|uri| Compound.new(:uri => uri)}
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get all features for a compound
|
65
|
+
def feature_uris(compound)
|
66
|
+
uri = File.join(@uri, 'compound', CGI.escape(compound.inchi)) # URI.encode does not work here
|
67
|
+
RestClient.get(uri).split("\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
# Get all features for a compound
|
71
|
+
def features(compound)
|
72
|
+
feature_uris(compound).collect{|uri| Feature.new(:uri => uri)}
|
73
|
+
end
|
74
|
+
|
75
|
+
def all_features
|
76
|
+
RestClient.get(File.join(@uri, 'features')).split("\n")
|
77
|
+
end
|
78
|
+
|
79
|
+
# Delete a dataset
|
80
|
+
def delete
|
81
|
+
RestClient.delete @uri
|
82
|
+
end
|
83
|
+
|
84
|
+
def tanimoto(dataset)
|
85
|
+
RestClient.get(File.join(@uri,'tanimoto',dataset.path))
|
86
|
+
end
|
87
|
+
|
88
|
+
def weighted_tanimoto(dataset)
|
89
|
+
RestClient.get(File.join(@uri,'weighted_tanimoto',dataset.path))
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
data/lib/environment.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# set default environment
|
2
|
+
ENV['RACK_ENV'] = 'test' unless ENV['RACK_ENV']
|
3
|
+
|
4
|
+
# load configuration
|
5
|
+
basedir = File.join(ENV['HOME'], ".opentox")
|
6
|
+
config_dir = File.join(basedir, "config")
|
7
|
+
@@tmp_dir = File.join(basedir, "tmp")
|
8
|
+
config_file = File.join(config_dir, "#{ENV['RACK_ENV']}.yaml")
|
9
|
+
|
10
|
+
if File.exist?(config_file)
|
11
|
+
@@config = YAML.load_file(config_file)
|
12
|
+
else
|
13
|
+
FileUtils.mkdir_p config_dir
|
14
|
+
FileUtils.mkdir_p @@tmp_dir
|
15
|
+
FileUtils.cp(File.join(File.dirname(__FILE__), 'templates/config.yaml'), config_file)
|
16
|
+
puts "Please edit #{config_file} and restart your application."
|
17
|
+
exit
|
18
|
+
end
|
19
|
+
|
20
|
+
# configure redis database
|
21
|
+
begin
|
22
|
+
case ENV['RACK_ENV']
|
23
|
+
when 'production'
|
24
|
+
@@redis = Redis.new :db => 0
|
25
|
+
when 'development'
|
26
|
+
@@redis = Redis.new :db => 1
|
27
|
+
when 'test'
|
28
|
+
@@redis = Redis.new :db => 2
|
29
|
+
@@redis.flush_db
|
30
|
+
end
|
31
|
+
rescue
|
32
|
+
puts "Redis database not running, please start it with 'rake redis:start'."
|
33
|
+
end
|
data/lib/feature.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
module OpenTox
|
2
|
+
|
3
|
+
# uri: /feature/:name/:property_name/:property_value/...
|
4
|
+
class Feature < OpenTox
|
5
|
+
|
6
|
+
attr_accessor :name, :values
|
7
|
+
|
8
|
+
def initialize(params)
|
9
|
+
if params[:uri]
|
10
|
+
@uri = params[:uri]
|
11
|
+
items = URI.split(@uri)[5].split(/\//)
|
12
|
+
@name = items[1]
|
13
|
+
@values = {}
|
14
|
+
i = 2
|
15
|
+
while i < items.size
|
16
|
+
@values[items[i]] = items[i+1]
|
17
|
+
i += 2
|
18
|
+
end
|
19
|
+
else
|
20
|
+
@name = params[:name]
|
21
|
+
@values = {}
|
22
|
+
params.each do |k,v|
|
23
|
+
@values[k] = v unless k.to_s == 'name'
|
24
|
+
end
|
25
|
+
@uri = File.join(@@config[:services]["opentox-feature"],path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def values_path
|
30
|
+
path = ''
|
31
|
+
@values.each do |k,v|
|
32
|
+
path = File.join path, URI.encode(k.to_s), URI.encode(v.to_s)
|
33
|
+
end
|
34
|
+
path
|
35
|
+
end
|
36
|
+
|
37
|
+
def path
|
38
|
+
File.join(URI.encode(@name),values_path)
|
39
|
+
end
|
40
|
+
|
41
|
+
def value(property)
|
42
|
+
items = @uri.split(/\//)
|
43
|
+
i = items.index(property)
|
44
|
+
items[i+1]
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
data/lib/helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
helpers do
|
2
|
+
|
3
|
+
# Authentification
|
4
|
+
def protected!
|
5
|
+
response['WWW-Authenticate'] = %(Basic realm="Testing HTTP Auth") and \
|
6
|
+
throw(:halt, [401, "Not authorized\n"]) and \
|
7
|
+
return unless authorized?
|
8
|
+
end
|
9
|
+
|
10
|
+
def authorized?
|
11
|
+
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
12
|
+
@auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == ['api', API_KEY]
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
=begin
|
17
|
+
def xml(object)
|
18
|
+
builder do |xml|
|
19
|
+
xml.instruct!
|
20
|
+
object.to_xml
|
21
|
+
end
|
22
|
+
end
|
23
|
+
=end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
data/lib/model.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
module OpenTox
|
2
|
+
|
3
|
+
module Model
|
4
|
+
|
5
|
+
class LazarClassification < OpenTox
|
6
|
+
|
7
|
+
# Create a new prediction model from a dataset
|
8
|
+
def initialize(uri)
|
9
|
+
super(uri)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create(params)
|
13
|
+
uri = RestClient.post File.join(@@config[:services]["opentox-model"], 'lazar_classification'), params
|
14
|
+
puts "URI: " + uri
|
15
|
+
LazarClassification.new(uri.to_s)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.find(name)
|
19
|
+
uri = RestClient.get File.join(@@config[:services]["opentox-model"], 'lazar_classification', URI.encode(params[:name]))
|
20
|
+
LazarClassification.new(uri)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.find_all
|
24
|
+
RestClient.get File.join(@@config[:services]["opentox-model"], 'lazar_classification')#.split("\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
# Predict a compound
|
28
|
+
def predict(compound)
|
29
|
+
LazarPrediction.new(:uri => RestClient.post(@uri, :compound_uri => compound.uri))
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.base_uri
|
33
|
+
@@config[:services]["opentox-model"]
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
module Prediction
|
41
|
+
|
42
|
+
module Classification
|
43
|
+
|
44
|
+
class Lazar < OpenTox
|
45
|
+
|
46
|
+
def initialize(params)
|
47
|
+
super(params[:uri])
|
48
|
+
end
|
49
|
+
|
50
|
+
def classification
|
51
|
+
YAML.load(RestClient.get @uri)[:classification]
|
52
|
+
end
|
53
|
+
|
54
|
+
def confidence
|
55
|
+
YAML.load(RestClient.get @uri)[:confidence]
|
56
|
+
end
|
57
|
+
|
58
|
+
def neighbors
|
59
|
+
RestClient.get @uri + '/neighbors'
|
60
|
+
end
|
61
|
+
|
62
|
+
def features
|
63
|
+
RestClient.get @uri + '/features'
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|