From 55d99f141275fc34019a621d1f0c444804ebc053 Mon Sep 17 00:00:00 2001 From: Christoph Helma Date: Thu, 3 Sep 2009 14:12:28 +0200 Subject: compound and feature services integrated --- application.rb | 95 ++++++++++++++++++++++++++++++++++++++++++++++-- dataset.rb | 86 ++++++++++++++++++++++++++++++++++++++++++- test/test.rb | 113 +++++++++++++++++++-------------------------------------- 3 files changed, 213 insertions(+), 81 deletions(-) diff --git a/application.rb b/application.rb index a23b52a..b9f518d 100644 --- a/application.rb +++ b/application.rb @@ -1,5 +1,5 @@ # SETUP -[ 'rubygems', 'redis', 'opentox-ruby-api-wrapper' ].each do |lib| +[ 'rubygems', 'redis', 'opentox-ruby-api-wrapper', 'openbabel' ].each do |lib| require lib end @@ -15,15 +15,18 @@ end set :default_content, :yaml load File.join(File.dirname(__FILE__), 'dataset.rb') +load File.join(File.dirname(__FILE__), 'compound.rb') +load File.join(File.dirname(__FILE__), 'feature.rb') helpers do - def not_found? - halt 404, "Dataset \"#{params[:name]}\" not found." unless @dataset = Dataset.find(uri(params[:name])) + def find + uri = uri(params[:splat].first) + halt 404, "Dataset \"#{uri}\" not found." unless @set = Dataset.find(uri) end def uri(name) - uri = url_for("/", :full) + name.gsub(/\s|\n/,'_') + uri = url_for("/", :full) + URI.encode(name) #.gsub(/\s|\n/,'_') end end @@ -43,6 +46,89 @@ get '/?' do Dataset.find_all.join("\n") end +get '/*/tanimoto/*/?' do + find + @set.tanimoto(uri(params[:splat][1])) +end + +get '/*/weighted_tanimoto/*/?' do + find + @set.weighted_tanimoto(uri(params[:splat][1])) +end + +# catch the rest +get '/*/?' do + find + @set.to_yaml +end + +post '/?' do + + dataset_uri = uri(params[:name]) + halt 403, "Dataset \"#{dataset_uri}\" exists." if Dataset.find(dataset_uri) + + @set = Dataset.create(dataset_uri) + @compounds_set = Dataset.create File.join(dataset_uri, "compounds") + #@activities_set = Dataset.create File.join(dataset_uri, "activities") + #@features_set = Dataset.create File.join(dataset_uri, "features") + @set.add(@compounds_set.uri) + #@set.add(@activities_set.uri) + #@set.add(@features_set.uri) + @set.uri + +end + +post '/*/activities/?' do + + find + @compounds_set = Dataset.find File.join(@set.uri, "compounds") + #@activities_set = Dataset.find File.join(@set.uri, "activities") + File.open(params[:file][:tempfile].path).each_line do |line| + record = line.chomp.split(/,\s*/) + inchi = Compound.new(:smiles => record[0]).inchi + feature = Feature.new(:name => @set.name, :values => {:classification => record[1]}) + @compound_activities = Dataset.find_or_create File.join(@set.uri, inchi) + #@activity_compounds = Dataset.find_or_create File.join(@set.uri, feature.path) + @compounds_set.add(inchi) + #@activities_set.add(feature.path) + @compound_activities.add(feature.path) + #@activity_compounds.add(inchi) + end + @set.uri + +end + +post '/*/features/?' do + + find + @compounds_set = Dataset.find File.join(@set.uri, "compounds") + #@features_set = Dataset.find File.join(@set.uri, "features") + YAML.load(params[:features]).each do |inchi,features| + @compound_features = Dataset.find_or_create File.join(@set.uri, inchi) + features.each do |feature| + #@feature_compounds = Dataset.find_or_create File.join(@set.uri, feature) + @compounds_set.add(inchi) + #@features_set.add(feature) + @compound_features.add(feature) + #@feature_compounds.add(inchi) + end + end + @set.uri + +end + +delete '/*/?' do + find + @set.members.each{|m| Dataset.find(m).delete} + @set.delete +end + +put '/*/?' do + find + @set.add(params[:uri]) +end + +=begin get '/:name' do not_found? respond_to do |format| @@ -142,3 +228,4 @@ delete '/collection/:name/?' do DatasetCollection.find(uri params[:name]).destroy "Successfully deleted dataset collection \"#{params[:name]}\"." end +=end diff --git a/dataset.rb b/dataset.rb index 00872b9..25adf86 100644 --- a/dataset.rb +++ b/dataset.rb @@ -1,11 +1,92 @@ class Dataset - #include OpenTox::Utils + include OpenTox::Utils + attr_reader :uri, :name, :members + + def initialize(uri) + @uri = uri + begin + @name = URI.split(uri)[5] + rescue + puts "Bad URI #{uri}" + end + @members = @@redis.set_members(uri) + end + + def self.create(uri) + @@redis.set_add "datasets", uri + Dataset.new(uri) + end + + def self.find(uri) + if @@redis.set_member? "datasets", uri + Dataset.new(uri) + else + nil + end + end + + def self.find_or_create(uri) + dataset = Dataset.create(uri) unless dataset = Dataset.find(uri) + dataset + end + + def self.find_all_keys + @@redis.keys "*" + end + + def self.find_all + @@redis.set_members "datasets" + end + + def add(member_uri) + @@redis.set_add @uri , member_uri + @members << member_uri + end + + def union(set_uri) + @@redis.set_union(@uri,set_uri) + end + + def intersection(set_uri) + @@redis.set_intersect(@uri,set_uri) + end + + def tanimoto(set_uri) + union_size = @@redis.set_union(@uri,set_uri).size + intersect_size = @@redis.set_intersect(@uri,set_uri).size + "#{intersect_size.to_f/union_size.to_f}" + end + + def weighted_tanimoto(set_uri) + union = @@redis.set_union(@uri,set_uri) + intersect = @@redis.set_intersect(@uri,set_uri) + + p_sum_union = 0.0 + p_sum_intersect = 0.0 + + union.each{ |f| p_sum_union += OpenTox::Utils::gauss(Feature.value(f,'p_value').to_f) } + intersect.each{ |f| p_sum_intersect += OpenTox::Utils::gauss(Feature.value(f,'p_value').to_f) } + "#{p_sum_intersect/p_sum_union}" + end + + def delete + @@redis.delete @uri + @@redis.set_delete "datasets", @uri + end + +end + +=begin +class Dataset + + include OpenTox::Utils attr_reader :uri, :name def initialize(uri) @name = File.basename(uri) @uri = uri + @members = [] end def self.create(uri) @@ -93,7 +174,7 @@ class Dataset end -class Set +class Dataset attr_accessor :uri, :set_uris @@ -146,3 +227,4 @@ class Set end end +=end diff --git a/test/test.rb b/test/test.rb index 65959bf..611113b 100644 --- a/test/test.rb +++ b/test/test.rb @@ -1,12 +1,14 @@ require 'application' require 'test/unit' require 'rack/test' +require 'ruby-prof' set :environment, :test @@redis.flush_db class DatasetsTest < Test::Unit::TestCase include Rack::Test::Methods + #include RubyProf::Test def app Sinatra::Application @@ -20,72 +22,32 @@ class DatasetsTest < Test::Unit::TestCase def test_create_dataset post '/', :name => "Test dataset" assert last_response.ok? - uri = last_response.body.chomp - assert_equal "http://example.org/Test_dataset", uri - get uri - assert last_response.ok? - delete "/Test_dataset" - assert last_response.ok? - get "/Test_dataset" - assert !last_response.ok? - end - - def test_create_dataset_and_insert_data - name = "Test dataset" - compounds = { - '[O-][N+](=O)C/C=C\C(=O)Cc1cc(C#N)ccc1' => 'true', - 'F[B-](F)(F)F.[Na+]' => 'false', - 'N#[N+]C1=CC=CC=C1.F[B-](F)(F)F' => 'false' - } - post '/', :name => name - assert last_response.ok? - uri = last_response.body.chomp + uri = last_response.body + assert_equal "http://example.org/Test%20dataset", uri get uri assert last_response.ok? - assert last_response.body.include?("Test_dataset") - - compounds.each do |smiles,activity| - - compound_uri = OpenTox::Compound.new(:smiles => smiles).uri - feature_uri = OpenTox::Feature.new(:name => name, :values => {:classification => activity}).uri - put uri, :compound_uri => compound_uri, :feature_uri => feature_uri - - assert last_response.ok? - get uri + '/compounds' - assert last_response.ok? - assert last_response.body.include?(compound_uri) - get uri + '/features' - assert last_response.ok? - assert last_response.body.include?(activity) - assert last_response.body.include?(feature_uri) - get uri + '/compound/' + compound_uri + '/features' - assert last_response.ok? - assert last_response.body.include?(activity) - assert_equal feature_uri, last_response.body - end - get uri + '/compounds' - #puts last_response.body delete uri assert last_response.ok? - get "/Test_dataset" + get uri assert !last_response.ok? end def test_create_dataset_from_csv smiles = 'CC(=O)Nc1scc(n1)c1ccc(o1)[N+](=O)[O-]' - compound_uri = OpenTox::Compound.new(:smiles => smiles).uri - post '/', :name => "Hamster Carcinogenicity", :file => Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), "hamster_carcinogenicity.csv")) + compound = Compound.new(:smiles => smiles) + post '/', :name => "Hamster Carcinogenicity" uri = last_response.body + post uri + '/activities', :file => Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), "hamster_carcinogenicity.csv")) get uri assert last_response.ok? get uri + '/compounds' assert last_response.ok? - assert last_response.body.include?(compound_uri) - get uri + '/features' - assert last_response.ok? - assert last_response.body.include?("Hamster%20Carcinogenicity/classification/true") - assert last_response.body.include?("Hamster%20Carcinogenicity/classification/false") - get uri + '/compound/' + compound_uri + '/features' + assert last_response.body.include?(compound.inchi) + #get uri + '/activities' + #assert last_response.ok? + #assert last_response.body.include?("Hamster%20Carcinogenicity/classification/true") + #assert last_response.body.include?("Hamster%20Carcinogenicity/classification/false") + get File.join(uri ,compound.inchi) assert last_response.ok? assert last_response.body.include?("Hamster%20Carcinogenicity/classification/true") delete uri @@ -94,20 +56,21 @@ class DatasetsTest < Test::Unit::TestCase assert !last_response.ok? end -=begin def test_create_large_dataset_from_csv - post '/', :name => "Salmonella Mutagenicity", :file => Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), "kazius.csv")) + post '/', :name => "Salmonella Mutagenicity" + uri = last_response.body + post uri + '/activities', :file => Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), "kazius.csv")) uri = last_response.body get uri assert last_response.ok? end -=end def test_tanimoto_similarity #@feature_set = OpenTox::Algorithms::Fminer.new :dataset_uri => @dataset name = "Similarity test dataset" data = { - '[O-][N+](=O)C/C=C\C(=O)Cc1cc(C#N)ccc1' => + 'c1ccccc1' => + #'[O-][N+](=O)C/C=C\C(=O)Cc1cc(C#N)ccc1' => { 'A' => 1.0, 'B' => 0.9, @@ -115,7 +78,8 @@ class DatasetsTest < Test::Unit::TestCase 'D' => 0.7, 'E' => 0.5 }, - 'F[B-](F)(F)F.[Na+]' => + 'CCCNN' => + #'F[B-](F)(F)F.[Na+]' => { 'F' => 0.9, 'B' => 0.9, @@ -123,7 +87,8 @@ class DatasetsTest < Test::Unit::TestCase 'D' => 0.7, 'E' => 0.5 }, - 'N#[N+]C1=CC=CC=C1.F[B-](F)(F)F' => + 'C1CO1' => + #'N#[N+]C1=CC=CC=C1.F[B-](F)(F)F' => { 'A' => 1.0, 'B' => 0.9, @@ -135,24 +100,29 @@ class DatasetsTest < Test::Unit::TestCase uri = last_response.body get uri assert last_response.ok? - get uri + '/name' - name = last_response.body + name = URI.encode(name) + feature_data = {} data.each do |smiles,features| - compound_uri = OpenTox::Compound.new(:smiles => smiles).uri + compound = Compound.new(:smiles => smiles).inchi + feature_data[compound] = [] features.each do |k,v| - feature_uri = OpenTox::Feature.new(:name => k, :values => {:p_value => v}).uri - put uri, :compound_uri => compound_uri, :feature_uri => feature_uri - assert last_response.ok? + feature= Feature.new(:name => k, :values => {:p_value => v}).path + feature_data[compound] << feature end end + post uri + '/features', :features => feature_data.to_yaml + assert last_response.ok? + data.each do |smiles,features| - compound_uri = OpenTox::Compound.new(:smiles => smiles).uri + compound= Compound.new(:smiles => smiles).inchi data.each do |s,f| unless s == smiles - neighbor_uri = OpenTox::Compound.new(:smiles => s).uri - get "/tanimoto/#{name}/compound/#{compound_uri}/#{name}/compound/#{neighbor_uri}" + neighbor= Compound.new(:smiles => s).inchi + get "/#{name}/#{compound}/" + assert last_response.ok? + get "/#{name}/#{compound}/tanimoto/#{name}/#{neighbor}" assert last_response.ok? sim = last_response.body features_a = data[smiles].keys @@ -162,7 +132,7 @@ class DatasetsTest < Test::Unit::TestCase mysim = intersect.size.to_f/union.size.to_f assert_equal sim, mysim.to_s puts "tanimoto::#{smiles}::#{s}::#{last_response.body}" - get "/weighted_tanimoto/#{name}/compound/#{compound_uri}/#{name}/compound/#{neighbor_uri}" + get "/#{name}/#{compound}/weighted_tanimoto/#{name}/#{neighbor}" assert last_response.ok? puts "weighted_tanimoto::#{smiles}::#{s}::#{last_response.body}" end @@ -171,11 +141,4 @@ class DatasetsTest < Test::Unit::TestCase end -=begin - def test_unauthorized_create - post '/', :name => "Test dataset" - assert !last_response.ok? - end -=end - end -- cgit v1.2.3