diff options
author | Martin Gütlein <martin.guetlein@gmail.com> | 2010-03-24 10:21:37 +0100 |
---|---|---|
committer | Martin Gütlein <martin.guetlein@gmail.com> | 2010-03-24 10:21:37 +0100 |
commit | 7c6b9a46e012a3e541f63d245c344e5876d7da5e (patch) | |
tree | 8fac33200a981bf965b6f7917409418a050c84a2 /lib | |
parent | 54d1c336501dd34785ca29a3393a9fd347097482 (diff) | |
parent | 95f6ca7e8c02daea41ae00b85807cae245142092 (diff) |
resolved conflicts
Diffstat (limited to 'lib')
-rw-r--r-- | lib/algorithm.rb | 43 | ||||
-rw-r--r-- | lib/dataset.rb | 74 | ||||
-rw-r--r-- | lib/model.rb | 71 | ||||
-rw-r--r-- | lib/opentox-ruby-api-wrapper.rb | 2 | ||||
-rw-r--r-- | lib/owl.rb | 230 | ||||
-rw-r--r-- | lib/task.rb | 36 | ||||
-rw-r--r-- | lib/validation.rb | 21 |
7 files changed, 262 insertions, 215 deletions
diff --git a/lib/algorithm.rb b/lib/algorithm.rb index 2a781d8..8083db2 100644 --- a/lib/algorithm.rb +++ b/lib/algorithm.rb @@ -1,51 +1,32 @@ +LOGGER.progname = File.expand_path(__FILE__) + module OpenTox module Algorithm class Fminer - include Owl - - def initialize - super - self.uri = File.join(@@config[:services]["opentox-algorithm"],'fminer') - self.title = "fminer" - self.source = "http://github.com/amaunz/libfminer" - self.parameters = { - "Dataset URI" => { :scope => "mandatory", :value => "dataset_uri" }, - "Feature URI for dependent variable" => { :scope => "mandatory", :value => "feature_uri" } - } - end def self.create_feature_dataset(params) LOGGER.debug File.basename(__FILE__) + ": creating feature dataset" resource = RestClient::Resource.new(params[:feature_generation_uri], :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) resource.post :dataset_uri => params[:dataset_uri], :feature_uri => params[:feature_uri] end + + def self.uri + File.join(@@config[:services]["opentox-algorithm"], "fminer") + end end class Lazar - include Owl - - def initialize - super - self.uri = File.join(@@config[:services]["opentox-algorithm"],'lazar') - self.title = "lazar" - self.source = "http://github.com/helma/opentox-algorithm" - self.parameters = { - "Dataset URI" => - { :scope => "mandatory", :value => "dataset_uri" }, - "Feature URI for dependent variable" => - { :scope => "mandatory", :value => "feature_uri" }, - "Feature generation URI" => - { :scope => "mandatory", :value => "feature_generation_uri" } - } - end def self.create_model(params) LOGGER.debug params LOGGER.debug File.basename(__FILE__) + ": creating model" - #@uri = RestClient.post File.join(@@config[:services]["opentox-algorithm"], "lazar"), :dataset_uri => params[:dataset_uri], :feature_uri => params[:feature_uri], :feature_generation_uri => File.join(@@config[:services]["opentox-algorithm"], "fminer") - resource = RestClient::Resource.new(File.join(@@config[:services]["opentox-algorithm"], "lazar"), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - @uri = resource.post :dataset_uri => params[:dataset_uri], :feature_uri => params[:feature_uri], :feature_generation_uri => File.join(@@config[:services]["opentox-algorithm"], "fminer") + resource = RestClient::Resource.new(File.join(@@config[:services]["opentox-algorithm"], "lazar"), :user => @@users[:users].keys[0], :password => @@users[:users].values[0], :content_type => "application/x-yaml") + @uri = resource.post(:dataset_uri => params[:dataset_uri], :feature_uri => params[:feature_uri], :feature_generation_uri => File.join(@@config[:services]["opentox-algorithm"], "fminer")).chomp + end + + def self.uri + File.join(@@config[:services]["opentox-algorithm"], "lazar") end end diff --git a/lib/dataset.rb b/lib/dataset.rb index 2d49829..f416921 100644 --- a/lib/dataset.rb +++ b/lib/dataset.rb @@ -1,12 +1,47 @@ +LOGGER.progname = File.expand_path(__FILE__) + module OpenTox class Dataset - include Owl + + attr_accessor :uri, :title, :source, :identifier, :data, :features, :compounds def initialize - super + @data = {} + @features = [] + @compounds = [] + end + + def self.find(uri) + if uri.match(/webservices.in-silico.ch|localhost/) # try to get YAML first + YAML.load RestClient.get(uri, :accept => 'application/x-yaml').to_s + else # get default rdf+xml + owl = OpenTox::Owl.from_uri(uri) + @title = owl.title + @source = owl.source + @identifier = owl.identifier.sub(/^\[/,'').sub(/\]$/,'') + @uri = @identifier + @data = owl.data + halt 404, "Dataset #{uri} empty!" if @data.empty? + @data.each do |compound,features| + @compounds << compound + features.each do |f,v| + @features << f + end + end + @compounds.uniq! + @features.uniq! + end end + + def save + @features.uniq! + @compounds.uniq! + RestClient::Resource.new(@@config[:services]["opentox-dataset"], :user => @@users[:users].keys[0], :password => @@users[:users].values[0]).post(self.to_yaml, :content_type => "application/x-yaml").chomp.to_s + end + +=begin # create/add to entry from uris or Redland::Resources def add(compound,feature,value) compound = self.find_or_create_compound compound unless compound.class == Redland::Resource @@ -85,6 +120,7 @@ module OpenTox resource = RestClient::Resource.new(@@config[:services]["opentox-dataset"], :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) uri = resource.post data, :content_type => content_type dataset = Dataset.new +<<<<<<< HEAD dataset.read uri.to_s dataset end @@ -96,6 +132,9 @@ module OpenTox #LOGGER.debug data #data = RestClient.get(uri, :accept => 'application/rdf+xml') # unclear why this does not work for complex uris, Dataset.find works from irb dataset.rdf = data +======= + dataset.read uri.chomp.to_s +>>>>>>> helma/development dataset end @@ -107,6 +146,7 @@ module OpenTox features end +<<<<<<< HEAD def data data = {} @model.subjects(RDF['type'], OT['DataEntry']).each do |data_entry| @@ -158,6 +198,8 @@ module OpenTox end data end +======= +>>>>>>> helma/development def compounds compounds = [] @@ -173,35 +215,13 @@ module OpenTox resource.delete end - def save - LOGGER.debug "Saving dataset" - #task_uri = RestClient.post(@@config[:services]["opentox-dataset"], self.rdf, :content_type => "application/rdf+xml").to_s - task_uri = RestClient::Resource.new(@@config[:services]["opentox-dataset"], :user => @@users[:users].keys[0], :password => @@users[:users].values[0]).post(self.rdf, :content_type => "application/rdf+xml").to_s - task = OpenTox::Task.find(task_uri) - LOGGER.debug "Waiting for task #{task_uri}" - task.wait_for_completion - LOGGER.debug "Dataset task #{task_uri} completed" - if task.failed? - LOGGER.error "Saving dataset failed" - task.failed - exit - end - task.resource + def to_owl end - def to_yaml - { - :uri => self.uri, - :opentox_class => self.owl_class, - :title => self.title, - :source => self.source, - :identifier => self.identifier, - :compounds => self.compounds.collect{|c| c.to_s.to_s.sub(/^\[(.*)\]$/,'\1')}, - :features => self.features.collect{|f| f.to_s }, - :data => self.data - }.to_yaml + def from_owl end +=end end end diff --git a/lib/model.rb b/lib/model.rb index b4ef86c..8877b84 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -1,44 +1,47 @@ module OpenTox module Model + + class Generic + + attr_accessor :predicted_variables, :independent_variables, :dependent_variables, :activity_dataset_uri, :feature_dataset_uri, :effects, :activities, :p_values, :fingerprints, :features, :algorithm + + def self.find(uri) + owl = OpenTox::Owl.from_uri(uri) + @title = owl.title + @source = owl.source + @identifier = owl.identifier.sub(/^\[/,'').sub(/\]$/,'') + @uri = @identifier + @algorithm = owl.algorithm + @dependent_variables = owl.dependentVariables + @independent_variables = owl.independentVariables + @predicted_variables = owl.predictedVariables + end + + end - class Lazar - include Owl - - PREDICTION_FEATURE_MODIFIER = "_lazar_prediction" + class Lazar < Generic - # Create a new prediction model from a dataset def initialize - super - self.source = "http://github.com/helma/opentox-model" - self.algorithm = File.join(@@config[:services]["opentox-algorithm"],"lazar") - self.independentVariables = File.join(@@config[:services]["opentox-algorithm"],"fminer#BBRC_representative") # TODO read this from dataset + @source = "http://github.com/helma/opentox-model" + @algorithm = File.join(@@config[:services]["opentox-algorithm"],"lazar") + #@independent_variables = File.join(@@config[:services]["opentox-algorithm"],"fminer#BBRC_representative") + @features = [] + @effects = {} + @activities = {} + @p_values = {} + @fingerprints = {} end - def self.from_yaml(yaml) - yaml = YAML.load yaml - lazar = Lazar.new - lazar.title = "lazar model for #{yaml[:endpoint]}" - lazar.parameters = { - "Dataset URI" => { :scope => "mandatory", :value => "dataset_uri=#{yaml[:activity_dataset]}" }, - "Feature URI for dependent variable" => { :scope => "mandatory", :value => "feature_uri=#{yaml[:endpoint]}" }, - "Feature generation URI" => { :scope => "mandatory", :value => "feature_generation_uri=#{File.join(@@config[:services]["opentox-algorithm"],"fminer")}"} #TODO write to yaml - } - lazar.algorithm = File.join(@@config[:services]["opentox-algorithm"],"lazar") - lazar.trainingDataset = yaml[:activity_dataset] - lazar.dependentVariables = yaml[:endpoint] - lazar.predictedVariables = yaml[:endpoint] + PREDICTION_FEATURE_MODIFIER - lazar + def save + @features.uniq! + resource = RestClient::Resource.new(@@config[:services]["opentox-model"], :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) + resource.post(self.to_yaml, :content_type => "application/x-yaml").chomp.to_s end def self.find_all - RestClient.get(@@config[:services]["opentox-model"]).split("\n") + RestClient.get(@@config[:services]["opentox-model"]).chomp.split("\n") end - - def self.find(uri) - yaml = RestClient.get(uri, :accept => "application/x-yaml") - OpenTox::Model::Lazar.from_yaml(yaml) - end - +=begin # Predict a compound def predict(compound) @@ -48,12 +51,12 @@ module OpenTox end def self.base_uri - @@config[:services]["opentox-model"] + File.join @@config[:services]["opentox-model"],'lazar' end def self.create(data) resource = RestClient::Resource.new(@@config[:services]["opentox-model"], :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - resource.post(data, :content_type => "application/x-yaml").to_s + resource.post(data, :content_type => "application/x-yaml").chomp.to_s end def delete @@ -103,8 +106,8 @@ module OpenTox me = @model.subject(RDF['type'],OT[self.owl_class]) @model.add me, OT['predictedVariables'], Redland::Uri.new(predictedVariables) # untyped individual comes from this line, why?? @model.add Redland::Uri.new(predictedVariables), RDF['type'], OT['Feature'] - end - + end +=end end end end diff --git a/lib/opentox-ruby-api-wrapper.rb b/lib/opentox-ruby-api-wrapper.rb index 03838e8..849043c 100644 --- a/lib/opentox-ruby-api-wrapper.rb +++ b/lib/opentox-ruby-api-wrapper.rb @@ -8,6 +8,6 @@ rescue LoadError puts "Please install Openbabel with 'rake openbabel:install' in the compound component" end -['owl', 'compound','dataset','algorithm','model','task','utils','authorization'].each do |lib| +['owl', 'compound','dataset','algorithm','model','task','validation','utils','authorization'].each do |lib| require lib end @@ -1,101 +1,55 @@ module OpenTox - module Owl + class Owl - attr_reader :uri + attr_accessor :uri, :ot_class, :model def initialize - @model = Redland::Model.new Redland::MemoryStore.new - @parser = Redland::Parser.new - @serializer = Redland::Serializer.ntriples - - # read OT Ontology - #@parser.parse_into_model(@model,"http://opentox.org/data/documents/development/RDF%20files/OpenToxOntology/at_download/file") - #@parser.parse_string_into_model(@model,File.read(File.join(File.dirname(__FILE__),"opentox.owl")),'/') - # reate an anonymous resource for metadata - # this has to be rewritten with an URI as soon as the resource has been saved at an definitive location - tmp = @model.create_resource - @model.add tmp, RDF['type'], OT[self.owl_class] - end - - def uri=(uri) - @uri = uri - uri = Redland::Uri.new(uri) - # rewrite uri - @model.subjects(RDF['type'],OT[self.owl_class]).each do |me| - @model.delete(me,RDF['type'],OT[self.owl_class]) - @model.add(uri,RDF['type'],OT[self.owl_class]) - id = @model.object(me, DC['identifier']) - @model.delete me, DC['identifier'], id - # find/replace metadata - @model.find(me, nil, nil) do |s,p,o| - @model.delete s,p,o - @model.add uri,p,o - end - @model.add uri, DC['identifier'], @uri - end end - def title - # I have no idea, why 2 subjects are returned - # iterating over all subjects leads to memory allocation problems - # SPARQL queries also do not work - #me = @model.subjects(RDF['type'],OT[self.owl_class])[1] - me = @model.subject(RDF['type'],OT[self.owl_class]) - @model.object(me, DC['title']).to_s + def self.create(ot_class,uri) + owl = OpenTox::Owl.new + owl.ot_class = ot_class + owl.uri = Redland::Uri.new(uri.chomp) + owl.model.add owl.uri, RDF['type'], OT[owl.ot_class] + owl.model.add owl.uri, DC['identifier'], owl.uri + owl end - def title=(title) - me = @model.subject(RDF['type'],OT[self.owl_class]) + def self.from_uri(uri) + owl = OpenTox::Owl.new + parser = Redland::Parser.new begin - t = @model.object(me, DC['title']) - @model.delete me, DC['title'], t - rescue + parser.parse_into_model(owl.model,uri) + rescue => e + raise "Error parsing #{uri}: #{e.message + e.backtrace}" end - @model.add me, DC['title'], title - end - - def source - me = @model.subject(RDF['type'],OT[self.owl_class]) - @model.object(me, DC['source']).to_s unless me.nil? - end - - def source=(source) - me = @model.subject(RDF['type'],OT[self.owl_class]) - begin - t = @model.object(me, DC['source']) - @model.delete me, DC['source'], t - rescue - end - @model.add me, DC['source'], source - end - - def identifier - me = @model.subject(RDF['type'],OT[self.owl_class]) - @model.object(me, DC['identifier']).to_s unless me.nil? - end - - def owl_class - self.class.to_s.sub(/^OpenTox::/,'').sub(/::.*$/,'') - end - - def read(uri) - @parser.parse_into_model(@model,uri) - @uri = uri - end - - def rdf=(rdf) - @uri = '/' unless @uri - @parser.parse_string_into_model(@model,rdf,@uri) + owl.uri = Redland::Uri.new(uri.chomp) + owl end def rdf @model.to_string end - def to_ntriples - @serializer.model_to_string(Redland::Uri.new(@uri), @model) + def method_missing(name, *args) + methods = ['title', 'source', 'identifier', 'algorithm', 'independentVariables', 'dependentVariables', 'predictedVariables', 'date','trainingDataset' ] + if methods.include? name.to_s.sub(/=/,'') + if /=/ =~ name.to_s # setter + name = name.to_s.sub(/=/,'') + begin # delete existing entry + t = @model.object(@uri, DC[name]) + @model.delete @uri, DC[name], t + rescue + end + @model.add @uri, DC[name], args.first + else # getter + @model.object(@uri, DC[name.to_s]).to_s + end + else + raise "Method '#{name.to_s}' not found." + end end def parameters=(params) @@ -108,26 +62,110 @@ module OpenTox end end -=begin - def create_owl_statement(name,value) - r = @model.create_resource - dc_class = DC[name.gsub(/^[a-z]/) { |a| a.upcase }] # capitalize only the first letter - #puts "DC:" + name.gsub(/^[a-z]/) { |a| a.upcase } - @model.add dc_class, RDF['type'], OWL["Class"] - @model.add r, RDF['type'], dc_class - @model.add r, DC[name], value + def add_data_entries(compound_uri,features) + # add compound + compound = @model.subject(DC["identifier"], compound_uri) + if compound.nil? + compound = @model.create_resource(compound_uri) + @model.add compound, RDF['type'], OT["Compound"] + @model.add compound, DC["identifier"], compound_uri + end + features.each do |f| + f.each do |feature_uri,value| + # add feature + feature = find_or_create_feature feature_uri + if value.class.to_s == 'Hash' + # create tuple + tuple = @model.create_resource + @model.add tuple, RDF['type'], OT["Tuple"] + @model.add tuple, OT['feature'], feature + value.each do |uri,v| + f = find_or_create_feature uri + complex_value = @model.create_resource + @model.add tuple, OT['complexValue'], complex_value + @model.add complex_value, RDF['type'], OT["FeatureValue"] + @model.add complex_value, OT['feature'], f + @model.add complex_value, OT['value'], v.to_s + end + # add data entry + data_entry = @model.subject OT['compound'], compound + if data_entry.nil? + data_entry = @model.create_resource + @model.add @uri, OT['dataEntry'], data_entry + @model.add data_entry, RDF['type'], OT["DataEntry"] + @model.add data_entry, OT['compound'], compound + end + @model.add data_entry, OT['values'], tuple + else + data_entry = @model.subject OT['compound'], compound + if data_entry.nil? + data_entry = @model.create_resource + @model.add @uri, OT['dataEntry'], data_entry + @model.add data_entry, RDF['type'], OT["DataEntry"] + @model.add data_entry, OT['compound'], compound + end + values = @model.create_resource + @model.add data_entry, OT['values'], values + @model.add values, RDF['type'], OT['FeatureValue'] + @model.add values, OT['feature'], feature + @model.add values, OT['value'], value.to_s + end + end + end + end + + def find_or_create_feature(feature_uri) + feature = @model.subject(DC["identifier"], feature_uri) + if feature.nil? + feature = @model.create_resource(feature_uri) + @model.add feature, RDF['type'], OT["Feature"] + @model.add feature, DC["identifier"], feature_uri + @model.add feature, DC["title"], File.basename(feature_uri).split(/#/)[1] + @model.add feature, DC['source'], feature_uri + end + feature end - def method_missing(name, *args) - # create magic setter methods - if /=/ =~ name.to_s - create_owl_statement name.to_s.sub(/=/,''), args.first - else - raise "No method #{name}" + def data + data = {} + @model.subjects(RDF['type'], OT['DataEntry']).each do |data_entry| + compound_node = @model.object(data_entry, OT['compound']) + compound_uri = @model.object(compound_node, DC['identifier']).to_s + @model.find(data_entry, OT['values'], nil) do |s,p,values| + feature_node = @model.object values, OT['feature'] + feature_uri = @model.object(feature_node, DC['identifier']).to_s.sub(/\^\^.*$/,'') # remove XML datatype + type = @model.object(values, RDF['type']) + if type == OT['FeatureValue'] + value = @model.object(values, OT['value']).to_s + case value.to_s + when TRUE_REGEXP # defined in environment.rb + value = true + when FALSE_REGEXP # defined in environment.rb + value = false + else + LOGGER.warn compound_uri + " has value '" + value.to_s + "' for feature " + feature_uri + value = nil + end + data[compound_uri] = [] unless data[compound_uri] + data[compound_uri] << {feature_uri => value} unless value.nil? + elsif type == OT['Tuple'] + entry = {} + data[compound_uri] = [] unless data[compound_uri] + #data[compound_uri][feature_uri] = [] unless data[compound_uri][feature_uri] + @model.find(values, OT['complexValue'],nil) do |s,p,complex_value| + name_node = @model.object complex_value, OT['feature'] + name = @model.object(name_node, DC['title']).to_s + value = @model.object(complex_value, OT['value']).to_s + v = value.sub(/\^\^.*$/,'') # remove XML datatype + v = v.to_f if v.match(/^[\.|\d]+$/) # guess numeric datatype + entry[name] = v + end + data[compound_uri] << {feature_uri => entry} unless entry.empty? + end + end end + data end -=end end - end diff --git a/lib/task.rb b/lib/task.rb index c5cddf7..5591a34 100644 --- a/lib/task.rb +++ b/lib/task.rb @@ -1,3 +1,5 @@ +LOGGER.progname = File.expand_path(__FILE__) + module OpenTox class Task @@ -5,16 +7,13 @@ module OpenTox attr_accessor :uri def initialize(uri) - #super() - @uri = uri + @uri = uri.chomp end def self.create - #uri = RestClient.post @@config[:services]["opentox-task"], {} resource = RestClient::Resource.new(@@config[:services]["opentox-task"], :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) - #uri = resource.post(nil) - uri = resource.post({}) - Task.new(uri) + uri = resource.post({}).chomp + Task.new(uri.chomp) end def self.find(uri) @@ -26,7 +25,7 @@ module OpenTox end def self.all - task_uris = RestClient.get(@@config[:services]["opentox-task"]).split(/\n/) + task_uris = RestClient.get(@@config[:services]["opentox-task"]).chomp.split(/\n/) task_uris.collect{|uri| Task.new(uri)} end @@ -53,7 +52,7 @@ module OpenTox end def cancel - resource = RestClient::Resource.new(@File.join(@uri,'cancelled'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) + resource = RestClient::Resource.new(File.join(@uri,'cancelled'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) resource.put({}) end @@ -62,23 +61,8 @@ module OpenTox resource.put :resource => uri end -=begin - def started - RestClient.put File.join(@uri,'started'), {} - end - - def cancel - RestClient.put File.join(@uri,'cancelled'), {} - end - - def completed(uri) - RestClient.put File.join(@uri,'completed'), :resource => uri - end - -=end def failed - #RestClient.put File.join(@uri,'failed'), {} - resource = RestClient::Resource.new(@File.join(@uri,'failed'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) + resource = RestClient::Resource.new(File.join(@uri,'failed'), :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) resource.put({}) end @@ -102,9 +86,9 @@ module OpenTox self.status.to_s == 'failed' end - def wait_for_completion + def wait_for_completion(dur=0.1) until self.completed? or self.failed? - sleep 1 + sleep dur end end diff --git a/lib/validation.rb b/lib/validation.rb new file mode 100644 index 0000000..6fd5704 --- /dev/null +++ b/lib/validation.rb @@ -0,0 +1,21 @@ +module OpenTox + class Validation + + attr_accessor :uri + + def initialize(params) + resource = RestClient::Resource.new(params[:uri], :user => @@users[:users].keys[0], :password => @@users[:users].values[0]) + @uri = resource.post(params).to_s + end + + def self.crossvalidation(params) + params[:uri] = File.join(@@config[:services]['opentox-validation'], "crossvalidation") + params[:num_folds] = 10 unless params[:num_folds] + params[:random_seed] = 2 unless params[:random_seed] + params[:stratified] = false unless params[:stratified] + OpenTox::Validation.new(params) + end + + end +end + |