diff options
author | Christoph Helma <helma@in-silico.de> | 2009-09-08 11:15:50 +0200 |
---|---|---|
committer | Christoph Helma <helma@in-silico.de> | 2009-09-08 11:15:50 +0200 |
commit | 525a9229395070f04c54fe6aec3c2cd5e64235cd (patch) | |
tree | d942bde22ccc03e66223b9e284354387f64e4dcb | |
parent | 55d99f141275fc34019a621d1f0c444804ebc053 (diff) |
tests successful
-rw-r--r-- | application.rb | 192 | ||||
-rw-r--r-- | compound.rb | 33 | ||||
-rw-r--r-- | dataset.rb | 159 | ||||
-rw-r--r-- | feature.rb | 14 | ||||
-rw-r--r-- | import.rb | 22 | ||||
-rw-r--r-- | test/test.rb | 46 |
6 files changed, 123 insertions, 343 deletions
diff --git a/application.rb b/application.rb index b9f518d..2ebbbc8 100644 --- a/application.rb +++ b/application.rb @@ -1,5 +1,5 @@ # SETUP -[ 'rubygems', 'redis', 'opentox-ruby-api-wrapper', 'openbabel' ].each do |lib| +[ 'rubygems', 'redis', 'opentox-ruby-api-wrapper' ].each do |lib| require lib end @@ -15,8 +15,6 @@ 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 @@ -26,206 +24,64 @@ helpers do end def uri(name) - uri = url_for("/", :full) + URI.encode(name) #.gsub(/\s|\n/,'_') + uri = url_for("/dataset/", :full) + URI.encode(name) end end -=begin -# current sinatra version does not halt in before filter, should be resolved in future versions -before do - if params[:name] and !request.post? - halt 404, "Dataset \"#{params[:name]}\" not found." unless @dataset = Dataset.find(url_for("/", :full) + name.gsub(/\s|\n/,'_')) - end -end -=end - ## REST API -get '/?' do +load 'compound.rb' +load 'feature.rb' + +get '/datasets/?' do Dataset.find_all.join("\n") end -get '/*/tanimoto/*/?' do +get '/dataset/*/tanimoto/*/?' do find @set.tanimoto(uri(params[:splat][1])) end -get '/*/weighted_tanimoto/*/?' do +get '/dataset/*/weighted_tanimoto/*/?' do find @set.weighted_tanimoto(uri(params[:splat][1])) end # catch the rest -get '/*/?' do +get '/dataset/*/?' do find - @set.to_yaml + @set.members.join("\n") end -post '/?' do - +# create a dataset +post '/datasets/?' 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.add Dataset.create(File.join(dataset_uri, "compounds")).uri @set.uri - end -post '/*/features/?' do +load 'import.rb' +# import yaml +post '/dataset/*/?' 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) + YAML.load(params[:features]).each do |compound_uri,feature_uris| + # key: /dataset/:dataset/compound/:inchi/:feature_type + @compound_features = Dataset.find_or_create File.join(@set.uri,'compound',OpenTox::Compound.new(:uri => compound_uri).inchi,URI.escape(params[:feature_type])) + feature_uris.each do |feature_uri| + @compounds_set.add compound_uri + @compound_features.add feature_uri end end @set.uri - end -delete '/*/?' do +delete '/dataset/*/?' do find - @set.members.each{|m| Dataset.find(m).delete} + @set.members.each{|m| Dataset.find(m).delete} if @set.members @set.delete end - -put '/*/?' do - find - @set.add(params[:uri]) -end - -=begin -get '/:name' do - not_found? - respond_to do |format| - format.yaml { @dataset.to_yaml } - format.xml { builder :dataset } - end -end - -get '/:name/name' do - not_found? - URI.decode(params[:name]) -end - -get '/:name/compounds' do - not_found? - @dataset.compound_uris.join("\n") -end - -get '/:name/features' do - not_found? - @dataset.feature_uris.join("\n") -end - -get '/:name/compound/*/features' do - not_found? - compound_uri = params[:splat].first.gsub(/ /,'+') - @dataset.feature_uris_for_compound(compound_uri).join("\n") -end - -get '/:name/feature/*/compounds' do - not_found? - @dataset.compound_uris_for_feature(params[:splat].first).join("\n") -end - -get '/tanimoto/:name0/compound/*/:name1/compound/*/?' do - compound_uris = params[:splat].collect{ |c| c.gsub(/ /,'+') } - features = [ {:dataset_uri => uri(params[:name0]), :compound_uri => compound_uris[0]}, {:dataset_uri => uri(params[:name1]), :compound_uri => compound_uris[1]} ] - "#{Dataset.tanimoto(features)}" -end - -get '/weighted_tanimoto/:name0/compound/*/:name1/compound/*/?' do - compound_uris = params[:splat].collect{ |c| c.gsub(/ /,'+') } - features = [ {:dataset_uri => uri(params[:name0]), :compound_uri => compound_uris[0]}, {:dataset_uri => uri(params[:name1]), :compound_uri => compound_uris[1]} ] - Dataset.weighted_tanimoto(features) -end - -post '/?' do - #protected! - halt 403, "Dataset \"#{name}\" exists - please choose another name." if Dataset.exists?(uri params[:name]) - - dataset = Dataset.create(uri params[:name]) - - if params[:file] - File.open(params[:file][:tempfile].path).each_line do |line| - record = line.chomp.split(/,\s*/) - compound_uri = OpenTox::Compound.new(:smiles => record[0]).uri - feature_uri = OpenTox::Feature.new(:name => params[:name], :values => {:classification => record[1]}).uri - dataset.add(compound_uri, feature_uri) - end - end - dataset.uri -end - -put '/:name/?' do - #protected! - not_found? - @dataset.add(params[:compound_uri],params[:feature_uri]) - @dataset.uri + " sucessfully updated." -end - -delete '/:name/?' do - #protected! - not_found? - @dataset.destroy - "Successfully deleted dataset \"#{params[:name]}\"." -end - -# Dataset collections -get '/collections/?' do - DatasetCollection.find_all.join("\n") -end - -get '/collection/:name/?' do - @collection = DatasetCollection.find(uri params[:name]) - respond_to do |format| - format.yaml { @collection.to_yaml } - format.xml { builder :collection } - end -end - -post '/collections/?' do - halt 403, "Dataset collection \"#{name}\" exists - please choose another name." if DatasetCollection.exists?(uri params[:name]) - DatasetCollection.create(uri params[:name], :dataset_uris => params[:datasets]).uri -end - -delete '/collection/:name/?' do - DatasetCollection.find(uri params[:name]).destroy - "Successfully deleted dataset collection \"#{params[:name]}\"." -end -=end diff --git a/compound.rb b/compound.rb new file mode 100644 index 0000000..9c1552e --- /dev/null +++ b/compound.rb @@ -0,0 +1,33 @@ +mime :uid, "text/plain" +mime :smiles, "chemical/x-daylight-smiles" +mime :inchi, "chemical/x-inchi" +mime :sdf, "chemical/x-mdl-sdfile" +mime :image, "image/gif" +mime :names, "text/plain" + +set :default_content, :smiles + +get '/compound/*/match/*' do + "#{OpenTox::Compound.new(:inchi => params[:splat][0]).match(params[:splat][1])}" +end + +get %r{/compound/(.+)} do |inchi| # catches all remaining get requests + inchi.gsub!(/ /,'+') # fix CGI? escaping of + signs + respond_to do |format| + format.smiles { inchi2smiles inchi } + format.names { RestClient.get "#{CACTUS_URI}#{inchi}/names" } + format.inchi { inchi } + format.sdf { RestClient.get "#{CACTUS_URI}#{inchi}/sdf" } + format.image { "#{CACTUS_URI}#{inchi}/image" } + end +end + +post '/compound/?' do + if params[:smiles] + OpenTox::Compound.new(:smiles => params[:smiles]).uri + elsif params[:inchi] + OpenTox::Compound.new(:inchi => params[:inchi]).uri + elsif params[:name] + OpenTox::Compound.new(:name => params[:name]).uri + end +end @@ -39,6 +39,10 @@ class Dataset @@redis.set_members "datasets" end + def member?(uri) + @@redis.set_member? @uri, uri + end + def add(member_uri) @@redis.set_add @uri , member_uri @members << member_uri @@ -65,8 +69,8 @@ class Dataset 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) } + union.each{ |f| p_sum_union += OpenTox::Utils::gauss(OpenTox::Feature.new(:uri => f).value('p_value').to_f) } + intersect.each{ |f| p_sum_intersect += OpenTox::Utils::gauss(OpenTox::Feature.new(:uri => f).value('p_value').to_f) } "#{p_sum_intersect/p_sum_union}" end @@ -77,154 +81,3 @@ class Dataset 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) - dataset = Dataset.new(uri) - dataset.save - dataset - end - - def self.find(uri) - if @@redis.set_member? "datasets", uri - Dataset.new(uri) - else - nil - end - end - - def self.exists?(uri) - @@redis.set_member? "datasets", uri - end - - def self.find_all - @@redis.set_members("datasets") - end - - def save - @@redis.set_add "datasets", @uri - end - - def destroy - @@redis.set_members(@uri + '::compounds').each do |compound_uri| - @@redis.delete @uri + '::' + compound_uri - end - @@redis.delete @uri + '::compounds' - @@redis.set_members(@uri + '::features').each do |feature_uri| - @@redis.delete @uri + '::' + feature_uri - end - @@redis.delete @uri + '::features' - @@redis.set_delete "datasets", @uri - end - - def add(compound_uri,feature_uri) - @@redis.set_add @uri + '::compounds', compound_uri - @@redis.set_add @uri + '::features', feature_uri - @@redis.set_add @uri + '::' + compound_uri + '::features', feature_uri - @@redis.set_add @uri + '::' + feature_uri + '::compounds', compound_uri - end - - def compound_uris - @@redis.set_members(@uri + "::compounds") - end - - def feature_uris - @@redis.set_members(@uri + "::features") - end - - def feature_uris_for_compound(compound_uri) - @@redis.set_members(@uri + '::' + compound_uri + '::features') - end - - def compound_uris_for_feature(feature_uri) - @@redis.set_members(@uri + '::' + feature_uri + '::compounds') - end - - def self.tanimoto(features) - raise "Exactly 2 compounds are needed for similarity calculations" unless features.size == 2 - compound_keys = features.collect{ |f| f[:dataset_uri] + '::' + f[:compound_uri] + "::features" } - union_size = @@redis.set_union(compound_keys[0], compound_keys[1]).size - intersect_size = @@redis.set_intersect(compound_keys[0], compound_keys[1]).size - intersect_size.to_f/union_size.to_f - end - - def self.weighted_tanimoto(features) - raise "Exactly 2 compounds are needed for similarity calculations" unless features.size == 2 - compound_keys = features.collect{ |f| f[:dataset_uri] + '::' + f[:compound_uri] + "::features" } - union = @@redis.set_union(compound_keys[0], compound_keys[1]) - intersect = @@redis.set_intersect(compound_keys[0], compound_keys[1]) - - p_sum_union = 0.0 - p_sum_intersect = 0.0 - - union.each{ |f| p_sum_union += OpenTox::Utils::gauss(OpenTox::Feature.new(:uri => f).value('p_value').to_f) } - intersect.each{ |f| p_sum_intersect += OpenTox::Utils::gauss(OpenTox::Feature.new(:uri => f).value('p_value').to_f) } - "#{p_sum_intersect/p_sum_union}" - end - -end - -class Dataset - - attr_accessor :uri, :set_uris - - def initialize(uri, set_uris) - @uri = uri - @set_uris = set_uris - end - - def self.create(uri, set_uris) - collection = DatasetCollection.new(uri, set_uris) - collection.save - collection - end - - def self.find(uri) - if @@redis.set_member? "collections", uri - set_uris = @@redis.set_members uri - DatasetCollection.new(uri, set_uris) - else - nil - end - end - - def self.exists?(uri) - @@redis.set_member? "collections", uri - end - - def self.find_all - @@redis.set_members("collections").collect{ |uri| self.find(uri) } - end - - def save - @@redis.set_add "collections", @uri - @set_uris.each do |uri| - @@redis.set_add @uri + '::sets', uri - end - end - - def destroy - @set_uris.each do |uri| - Dataset.new(uri).destroy - end - @@redis.delete @uri + '::sets' - @@redis.set_delete "collections", @uri - end - - def add(set_uri) - @set_uris << set_uri - @@redis.set_add @uri, set_uri - end - -end -=end diff --git a/feature.rb b/feature.rb new file mode 100644 index 0000000..1f138be --- /dev/null +++ b/feature.rb @@ -0,0 +1,14 @@ +set :default_content, :yaml + +## REST API +get '/feature/*/?' do + @feature = OpenTox::Feature.new(request.url) + respond_to do |format| + format.yaml { @feature.to_yaml } + format.xml { builder :feature } + end +end + +post '/feature/?' do + OpenTox::Feature.new(:name => params[:name], :values => params[:values]).uri +end diff --git a/import.rb b/import.rb new file mode 100644 index 0000000..de6f60b --- /dev/null +++ b/import.rb @@ -0,0 +1,22 @@ +post '/dataset/*/import/?' do + find + halt 404, "Compound format #{params[:compound_format]} not (yet) supported" unless params[:compound_format] =~ /smiles|inchi|name/ + @compounds_set = Dataset.find File.join(@set.uri, "compounds") + case params[:file][:type] + when "text/csv" + File.open(params[:file][:tempfile].path).each_line do |line| + record = line.chomp.split(/,\s*/) + compound_uri = OpenTox::Compound.new(:smiles => record[0]).uri + feature_uri = OpenTox::Feature.new(:name => @set.name.sub(/dataset\//,''), :values => {:classification => record[1]}).uri + @compounds_set.add compound_uri unless @compounds_set.member? compound_uri + # key: /dataset/:dataset/compound/:inchi/:feature_type + @compound_features = Dataset.find_or_create File.join(@set.uri,'compound',OpenTox::Compound.new(:uri => compound_uri).inchi,URI.escape(params[:feature_type])) + @compound_features.add feature_uri + end + else + halt 404, "File format #{request.content_type} not (yet) supported" + end + @set.uri + +end + diff --git a/test/test.rb b/test/test.rb index 611113b..603e27d 100644 --- a/test/test.rb +++ b/test/test.rb @@ -15,15 +15,15 @@ class DatasetsTest < Test::Unit::TestCase end def test_index - get '/' + get '/datasets' assert last_response.ok? end def test_create_dataset - post '/', :name => "Test dataset" + post '/datasets', :name => "Test dataset" assert last_response.ok? uri = last_response.body - assert_equal "http://example.org/Test%20dataset", uri + assert_equal "http://example.org/dataset/Test%20dataset", uri get uri assert last_response.ok? delete uri @@ -34,20 +34,17 @@ class DatasetsTest < Test::Unit::TestCase def test_create_dataset_from_csv smiles = 'CC(=O)Nc1scc(n1)c1ccc(o1)[N+](=O)[O-]' - compound = Compound.new(:smiles => smiles) - post '/', :name => "Hamster Carcinogenicity" + compound = OpenTox::Compound.new(:smiles => smiles) + post '/datasets', :name => "Hamster Carcinogenicity" uri = last_response.body - post uri + '/activities', :file => Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), "hamster_carcinogenicity.csv")) + assert last_response.ok? + post uri + '/import', :file => Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), "hamster_carcinogenicity.csv"), "text/csv"), :compound_format => "smiles", :feature_type => "in vivo carcinogenicity" get uri assert last_response.ok? get uri + '/compounds' assert last_response.ok? 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) + get File.join(uri , 'compound', compound.inchi, URI.encode("in vivo carcinogenicity")) assert last_response.ok? assert last_response.body.include?("Hamster%20Carcinogenicity/classification/true") delete uri @@ -56,14 +53,16 @@ class DatasetsTest < Test::Unit::TestCase assert !last_response.ok? end +=begin def test_create_large_dataset_from_csv - post '/', :name => "Salmonella Mutagenicity" + post '/datasets', :name => "Salmonella Mutagenicity" uri = last_response.body - post uri + '/activities', :file => Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), "kazius.csv")) + post uri + '/import', :file => Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), "kazius.csv"), "text/csv"), :compound_format => "smiles", :feature_type => "activity" 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 @@ -95,7 +94,7 @@ class DatasetsTest < Test::Unit::TestCase 'F' => 0.9, } } - post '/', :name => name + post '/datasets', :name => name assert last_response.ok? uri = last_response.body get uri @@ -104,25 +103,28 @@ class DatasetsTest < Test::Unit::TestCase feature_data = {} data.each do |smiles,features| - compound = Compound.new(:smiles => smiles).inchi + compound = OpenTox::Compound.new(:smiles => smiles).uri feature_data[compound] = [] features.each do |k,v| - feature= Feature.new(:name => k, :values => {:p_value => v}).path + feature= OpenTox::Feature.new(:name => k, :values => {:p_value => v}).uri feature_data[compound] << feature end end - post uri + '/features', :features => feature_data.to_yaml + post uri , :features => feature_data.to_yaml, :feature_type => 'test' assert last_response.ok? data.each do |smiles,features| - compound= Compound.new(:smiles => smiles).inchi + compound= OpenTox::Compound.new(:smiles => smiles).inchi data.each do |s,f| unless s == smiles - neighbor= Compound.new(:smiles => s).inchi - get "/#{name}/#{compound}/" + neighbor= OpenTox::Compound.new(:smiles => s).inchi + get "/dataset/#{name}/compounds" + assert last_response.ok? + get "/dataset/#{name}/compound/#{compound}/test" assert last_response.ok? - get "/#{name}/#{compound}/tanimoto/#{name}/#{neighbor}" + get "/dataset/#{name}/compound/#{compound}/test/tanimoto/#{name}/compound/#{neighbor}/test" + puts last_response.body assert last_response.ok? sim = last_response.body features_a = data[smiles].keys @@ -132,7 +134,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 "/#{name}/#{compound}/weighted_tanimoto/#{name}/#{neighbor}" + get "/dataset/#{name}/compound/#{compound}/test/weighted_tanimoto/#{name}/compound/#{neighbor}/test" assert last_response.ok? puts "weighted_tanimoto::#{smiles}::#{s}::#{last_response.body}" end |