From 5127847aa91af7add1cd15f39ae3c037365eb610 Mon Sep 17 00:00:00 2001 From: rautenberg Date: Thu, 24 Jan 2013 11:42:42 +0100 Subject: remove some rescue blocks from A&A --- lib/authorization.rb | 70 +++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/lib/authorization.rb b/lib/authorization.rb index 1fe5c51..95d6c46 100644 --- a/lib/authorization.rb +++ b/lib/authorization.rb @@ -77,7 +77,7 @@ module OpenTox begin out = RestClientWrapper.post("#{AA}/auth/logout",:subjectid => subjectid) return true unless is_token_valid(subjectid) - rescue + rescue #openSSO throws 500 if token is invalid return false end return false @@ -88,12 +88,8 @@ module OpenTox # @return [Boolean, nil] returns true, false or nil (if authorization-request fails). def self.authorize(uri, action, subjectid) return true if !AA - #begin return true if RestClientWrapper.post("#{AA}/auth/authorize",{:uri => uri, :action => action, :subjectid => subjectid})== "boolean=true\n" return false - #rescue - # return nil - #end end #Checks if a token is a valid token @@ -103,7 +99,7 @@ module OpenTox return true if !AA begin return true if RestClientWrapper.post("#{AA}/auth/isTokenValid",:tokenid => subjectid) == "boolean=true\n" - rescue #do rescue because openSSO throws 401 + rescue #do rescue because openSSO throws 401 if token invalid return false end return false @@ -113,23 +109,23 @@ module OpenTox # @param [String]subjectid requires subjectid # @return [Array, nil] returns an Array of policy names or nil if request fails def self.list_policies(subjectid) - begin + #begin out = RestClientWrapper.get("#{AA}/pol",nil,:subjectid => subjectid) return out.split("\n") - rescue - return nil - end + #rescue + # return nil + #end end #Returns a policy in xml-format # @param [String, String]policy,subjectid # @return [String] XML of the policy def self.list_policy(policy, subjectid) - begin + #begin return RestClientWrapper.get("#{AA}/pol",nil,{:subjectid => subjectid,:id => policy}) - rescue - return nil - end + #rescue + # return nil + #end end # Lists policies alongside with affected uris @@ -157,11 +153,11 @@ module OpenTox # @param [String, String]uri,subjectid # return [String, nil]owner,nil returns owner of the URI def self.get_uri_owner(uri, subjectid) - begin - return RestClientWrapper.get("#{AA}/pol",nil,{:subjectid => subjectid, :uri => uri}).sub("\n","") - rescue - return nil - end + #begin + return RestClientWrapper.get("#{AA}/pol",nil,{:subjectid => subjectid, :uri => uri}).sub("\n","") + #rescue + # return nil + #end end #Returns true or false if owner (who created the first policy) of an URI @@ -184,7 +180,7 @@ module OpenTox # @param [String, String]uri,subjectid # return [Array, nil] returns an Array of policy names or nil if request fails def self.list_uri_policies(uri, subjectid) - begin + #begin out = RestClientWrapper.get("#{AA}/pol",nil,{:uri => uri, :polnames => true, :subjectid => subjectid}) policies = []; notfirstline = false out.split("\n").each do |line| @@ -192,56 +188,56 @@ module OpenTox notfirstline = true end return policies - rescue - return nil - end + #rescue + # return nil + #end end #Sends a policy in xml-format to opensso server. Requires policy-xml and token. # @param [String, String]policyxml,subjectid # return [Boolean] returns true if policy is created def self.create_policy(policy, subjectid) - begin + #begin $logger.debug "OpenTox::Authorization.create_policy policy: #{policy[168,43]} with token:" + subjectid.to_s + " length: " + subjectid.length.to_s return true if RestClientWrapper.post("#{AA}/Pol/opensso-pol",policy, {:subjectid => subjectid, :content_type => "application/xml"}) - rescue + #rescue return false - end + #end end #Deletes a policy # @param [String, String]policyname,subjectid # @return [Boolean,nil] def self.delete_policy(policy, subjectid) - begin + #begin $logger.debug "OpenTox::Authorization.delete_policy policy: #{policy} with token: #{subjectid}" return true if RestClientWrapper.delete("#{AA}/pol",nil, {:subjectid => subjectid, :id => policy}) - rescue + #rescue return nil - end + #end end #Returns array of the LDAP-Groups of an user # @param [String]subjectid # @return [Array] gives array of LDAP groups of a user def self.list_user_groups(user, subjectid) - begin + #begin out = RestClientWrapper.post("#{AA}/opensso/identity/read", {:name => user, :admin => subjectid, :attributes_names => "group"}) grps = [] out.split("\n").each do |line| grps << line.sub("identitydetails.group=","") if line.include?("identitydetails.group=") end return grps - rescue - [] - end + #rescue + # [] + #end end #Returns the owner (user id) of a token # @param [String]subjectid # @return [String]user def self.get_user(subjectid) - begin + #begin out = RestClientWrapper.post("#{AA}/opensso/identity/attributes", {:subjectid => subjectid, :attributes_names => "uid"}) user = ""; check = false out.split("\n").each do |line| @@ -252,9 +248,9 @@ module OpenTox check = true if line.include?("userdetails.attribute.name=uid") end return user - rescue - nil - end + #rescue + # nil + #end end #Send default policy with Authorization::Helper class -- cgit v1.2.3 From 2d094d61663c36004915b5e124ba2001364392ac Mon Sep 17 00:00:00 2001 From: rautenberg Date: Thu, 24 Jan 2013 13:05:05 +0100 Subject: one step back --- lib/authorization.rb | 70 +++++++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/lib/authorization.rb b/lib/authorization.rb index 95d6c46..1fe5c51 100644 --- a/lib/authorization.rb +++ b/lib/authorization.rb @@ -77,7 +77,7 @@ module OpenTox begin out = RestClientWrapper.post("#{AA}/auth/logout",:subjectid => subjectid) return true unless is_token_valid(subjectid) - rescue #openSSO throws 500 if token is invalid + rescue return false end return false @@ -88,8 +88,12 @@ module OpenTox # @return [Boolean, nil] returns true, false or nil (if authorization-request fails). def self.authorize(uri, action, subjectid) return true if !AA + #begin return true if RestClientWrapper.post("#{AA}/auth/authorize",{:uri => uri, :action => action, :subjectid => subjectid})== "boolean=true\n" return false + #rescue + # return nil + #end end #Checks if a token is a valid token @@ -99,7 +103,7 @@ module OpenTox return true if !AA begin return true if RestClientWrapper.post("#{AA}/auth/isTokenValid",:tokenid => subjectid) == "boolean=true\n" - rescue #do rescue because openSSO throws 401 if token invalid + rescue #do rescue because openSSO throws 401 return false end return false @@ -109,23 +113,23 @@ module OpenTox # @param [String]subjectid requires subjectid # @return [Array, nil] returns an Array of policy names or nil if request fails def self.list_policies(subjectid) - #begin + begin out = RestClientWrapper.get("#{AA}/pol",nil,:subjectid => subjectid) return out.split("\n") - #rescue - # return nil - #end + rescue + return nil + end end #Returns a policy in xml-format # @param [String, String]policy,subjectid # @return [String] XML of the policy def self.list_policy(policy, subjectid) - #begin + begin return RestClientWrapper.get("#{AA}/pol",nil,{:subjectid => subjectid,:id => policy}) - #rescue - # return nil - #end + rescue + return nil + end end # Lists policies alongside with affected uris @@ -153,11 +157,11 @@ module OpenTox # @param [String, String]uri,subjectid # return [String, nil]owner,nil returns owner of the URI def self.get_uri_owner(uri, subjectid) - #begin - return RestClientWrapper.get("#{AA}/pol",nil,{:subjectid => subjectid, :uri => uri}).sub("\n","") - #rescue - # return nil - #end + begin + return RestClientWrapper.get("#{AA}/pol",nil,{:subjectid => subjectid, :uri => uri}).sub("\n","") + rescue + return nil + end end #Returns true or false if owner (who created the first policy) of an URI @@ -180,7 +184,7 @@ module OpenTox # @param [String, String]uri,subjectid # return [Array, nil] returns an Array of policy names or nil if request fails def self.list_uri_policies(uri, subjectid) - #begin + begin out = RestClientWrapper.get("#{AA}/pol",nil,{:uri => uri, :polnames => true, :subjectid => subjectid}) policies = []; notfirstline = false out.split("\n").each do |line| @@ -188,56 +192,56 @@ module OpenTox notfirstline = true end return policies - #rescue - # return nil - #end + rescue + return nil + end end #Sends a policy in xml-format to opensso server. Requires policy-xml and token. # @param [String, String]policyxml,subjectid # return [Boolean] returns true if policy is created def self.create_policy(policy, subjectid) - #begin + begin $logger.debug "OpenTox::Authorization.create_policy policy: #{policy[168,43]} with token:" + subjectid.to_s + " length: " + subjectid.length.to_s return true if RestClientWrapper.post("#{AA}/Pol/opensso-pol",policy, {:subjectid => subjectid, :content_type => "application/xml"}) - #rescue + rescue return false - #end + end end #Deletes a policy # @param [String, String]policyname,subjectid # @return [Boolean,nil] def self.delete_policy(policy, subjectid) - #begin + begin $logger.debug "OpenTox::Authorization.delete_policy policy: #{policy} with token: #{subjectid}" return true if RestClientWrapper.delete("#{AA}/pol",nil, {:subjectid => subjectid, :id => policy}) - #rescue + rescue return nil - #end + end end #Returns array of the LDAP-Groups of an user # @param [String]subjectid # @return [Array] gives array of LDAP groups of a user def self.list_user_groups(user, subjectid) - #begin + begin out = RestClientWrapper.post("#{AA}/opensso/identity/read", {:name => user, :admin => subjectid, :attributes_names => "group"}) grps = [] out.split("\n").each do |line| grps << line.sub("identitydetails.group=","") if line.include?("identitydetails.group=") end return grps - #rescue - # [] - #end + rescue + [] + end end #Returns the owner (user id) of a token # @param [String]subjectid # @return [String]user def self.get_user(subjectid) - #begin + begin out = RestClientWrapper.post("#{AA}/opensso/identity/attributes", {:subjectid => subjectid, :attributes_names => "uid"}) user = ""; check = false out.split("\n").each do |line| @@ -248,9 +252,9 @@ module OpenTox check = true if line.include?("userdetails.attribute.name=uid") end return user - #rescue - # nil - #end + rescue + nil + end end #Send default policy with Authorization::Helper class -- cgit v1.2.3 From 54b833546cea44e03eca3183ad4a37b9f30651a1 Mon Sep 17 00:00:00 2001 From: mguetlein Date: Mon, 4 Feb 2013 14:07:28 +0100 Subject: add validation, some debug messages, small adjustments --- lib/opentox-client.rb | 3 +- lib/opentox.rb | 4 + lib/rest-client-wrapper.rb | 8 +- lib/utils/shims/dataset.rb | 98 +++++++++++++ lib/utils/shims/feature.rb | 2 +- lib/utils/shims/model.rb | 40 +++++ lib/utils/shims/task.rb | 40 +++++ lib/validation.rb | 356 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 546 insertions(+), 5 deletions(-) create mode 100644 lib/utils/shims/model.rb create mode 100644 lib/validation.rb diff --git a/lib/opentox-client.rb b/lib/opentox-client.rb index ac7f4e6..65a9177 100644 --- a/lib/opentox-client.rb +++ b/lib/opentox-client.rb @@ -37,7 +37,8 @@ FALSE_REGEXP = /^(false|inactive|0|0.0|low tox|deactivating|non-carcinogen|non-m "dataset.rb", "model.rb", "algorithm.rb", - "4store.rb" + "4store.rb", + "validation.rb" ].each{ |f| require File.join(File.dirname(__FILE__),f) } Dir["#{File.dirname(__FILE__)}/utils/shims/*.rb"].each { |f| require f } # Shims for legacy code diff --git a/lib/opentox.rb b/lib/opentox.rb index 0f29c30..f125c30 100644 --- a/lib/opentox.rb +++ b/lib/opentox.rb @@ -115,6 +115,10 @@ module OpenTox end def wait_for_task uri + OpenTox.wait_for_task uri + end + + def self.wait_for_task uri if URI.task?(uri) t = OpenTox::Task.new uri t.wait diff --git a/lib/rest-client-wrapper.rb b/lib/rest-client-wrapper.rb index 1258339..0d1c56b 100644 --- a/lib/rest-client-wrapper.rb +++ b/lib/rest-client-wrapper.rb @@ -13,13 +13,13 @@ module OpenTox # @return [RestClient::Response] REST call response [:head,:get,:post,:put,:delete].each do |method| - define_singleton_method method do |uri,payload={},headers={}| + define_singleton_method method do |uri,payload={},headers={},waiting_task=nil| - # check input + # check input + bad_request_error "Headers are not a hash: #{headers.inspect}", uri unless headers==nil or headers.is_a?(Hash) @subjectid = headers[:subjectid] ? headers[:subjectid] : nil bad_request_error "Invalid URI: '#{uri}'", uri unless URI.valid? uri #resource_not_found_error "URI '#{uri}' not found.", uri unless URI.accessible?(uri, @subjectid) unless URI.ssl?(uri) - bad_request_error "Headers are not a hash: #{headers.inspect}", uri unless headers==nil or headers.is_a?(Hash) # make sure that no header parameters are set in the payload [:accept,:content_type,:subjectid].each do |header| if defined? $aa || URI(uri).host == URI($aa[:uri]).host @@ -36,6 +36,8 @@ module OpenTox args[:payload] = payload headers.each{ |k,v| headers.delete(k) if v==nil } if headers #remove keys with empty values, as this can cause problems args[:headers] = headers + + $logger.debug "POST #{uri} #{payload.inspect}" if method.to_s=="post" && payload.is_a?(Hash) @request = RestClient::Request.new(args) # ignore error codes from Task services (may return error codes >= 400 according to API, which causes exceptions in RestClient and RDF::Reader) diff --git a/lib/utils/shims/dataset.rb b/lib/utils/shims/dataset.rb index 912510c..f72ff1b 100644 --- a/lib/utils/shims/dataset.rb +++ b/lib/utils/shims/dataset.rb @@ -21,7 +21,104 @@ module OpenTox ds.get ds end + + def self.exist?(uri, subjectid=nil) + ds = OpenTox::Dataset.new uri, subjectid + begin + ds.get_metadata + true + rescue + false + end + end + + def split( compound_indices, feats, metadata, subjectid=nil) + + raise "Dataset.split : pls give compounds as indices" if compound_indices.size==0 or !compound_indices[0].is_a?(Fixnum) + raise "Dataset.split : pls give features as feature objects (given: #{feats})" if feats!=nil and feats.size>0 and !feats[0].is_a?(OpenTox::Feature) + $logger.debug "split dataset using "+compound_indices.size.to_s+"/"+@compounds.size.to_s+" compounds" + + dataset = OpenTox::Dataset.new(nil, subjectid) + dataset.metadata = metadata + dataset.features = (feats ? feats : self.features) + compound_indices.each do |c_idx| + dataset << [ self.compounds[c_idx] ] + dataset.features.each_with_index.collect{|f,f_idx| self.data_entries[c_idx][f_idx]} + end + #compound_indices.each do |c_idx| + # c = @compounds[c_idx] + # dataset.add_compound(c) + # if @data_entries[c] + # features.each do |f| + # if @data_entries[c][f] + # dataset.add_data_entry c,f,@data_entries[c][f][entry_index(c_idx)] + # else + # dataset.add_data_entry c,f,nil + # end + # end + # end + # end + + dataset.put subjectid + dataset + end + + + # maps a compound-index from another dataset to a compound-index from this dataset + # mapping works as follows: + # (compound c is the compound identified by the compound-index of the other dataset) + # * c occurs only once in this dataset? map compound-index of other dataset to index in this dataset + # * c occurs >1 in this dataset? + # ** number of occurences is equal in both datasets? assume order is preserved(!) and map accordingly + # ** number of occurences is not equal in both datasets? cannot map, raise error + # @param [OpenTox::Dataset] dataset that should be mapped to this dataset (fully loaded) + # @param [Fixnum] compound_index, corresponding to dataset + def compound_index( dataset, compound_index ) + unless defined?(@index_map) and @index_map[dataset.uri] + map = {} + dataset.compounds.collect{|c| c.uri}.uniq.each do |compound| + self_indices = compound_indices(compound) + next unless self_indices + dataset_indices = dataset.compound_indices(compound) + if self_indices.size==1 + dataset_indices.size.times do |i| + map[dataset_indices[i]] = self_indices[0] + end + elsif self_indices.size==dataset_indices.size + # we do assume that the order is preseverd! + dataset_indices.size.times do |i| + map[dataset_indices[i]] = self_indices[i] + end + else + raise "cannot map compound #{compound} from dataset #{dataset.uri} to dataset #{uri}, "+ + "compound occurs #{dataset_indices.size} times and #{self_indices.size} times" + end + end + @index_map = {} unless defined?(@index_map) + @index_map[dataset.uri] = map + end + @index_map[dataset.uri][compound_index] + end + + def compound_indices( compound ) + unless defined?(@cmp_indices) and @cmp_indices.has_key?(compound) + @cmp_indices = {} + @compounds.size.times do |i| + c = @compounds[i].uri + if @cmp_indices[c]==nil + @cmp_indices[c] = [i] + else + @cmp_indices[c] = @cmp_indices[c]+[i] + end + end + end + @cmp_indices[compound] + end + + def data_entry_value(compound_index, feature_uri) + build_feature_positions unless @feature_positions + @data_entries[compound_index][@feature_positions[feature_uri]] + end ### Index Structures @@ -30,6 +127,7 @@ module OpenTox # @return [Hash] A hash with keys 1...feature.training_classes.size and values training classes def value_map(feature) training_classes = feature.accept_values + raise "no accept values for feature #{feature.uri} in dataset #{uri}" unless training_classes training_classes.each_index.inject({}) { |h,idx| h[idx+1]=training_classes[idx]; h } end diff --git a/lib/utils/shims/feature.rb b/lib/utils/shims/feature.rb index f49bb39..9afa5c2 100644 --- a/lib/utils/shims/feature.rb +++ b/lib/utils/shims/feature.rb @@ -66,7 +66,7 @@ module OpenTox bad_request_error "rdf type of feature '#{@uri}' not set" unless self[RDF.type] if self[RDF.type].include?(OT.NominalFeature) "classification" - elsif [RDF.type].to_a.flatten.include?(OT.NumericFeature) + elsif self[RDF.type].include?(OT.NumericFeature) "regression" else "unknown" diff --git a/lib/utils/shims/model.rb b/lib/utils/shims/model.rb new file mode 100644 index 0000000..26a82c4 --- /dev/null +++ b/lib/utils/shims/model.rb @@ -0,0 +1,40 @@ + + +module OpenTox + + # Shims for the Task class + class Model + + def feature_type(subjectid=nil) + unless @feature_type + get unless metadata[OT.dependentVariables.to_s] + raise "cannot determine feature type, dependent variable missing" unless metadata[OT.dependentVariables.to_s] + @feature_type = OpenTox::Feature.find( metadata[OT.dependentVariables.to_s][0], subjectid ).feature_type + end + @feature_type + end + + def predicted_variable(subjectid=nil) + load_predicted_variables(subjectid) unless defined? @predicted_var + @predicted_var + end + + def predicted_confidence(subjectid=nil) + load_predicted_variables(subjectid) unless defined? @predicted_conf + @predicted_conf + end + + private + def load_predicted_variables(subjectid=nil) + metadata[OT.predictedVariables.to_s].each do |f| + feat = OpenTox::Feature.find( f, subjectid ) + if feat.title =~ /confidence/ + @predicted_conf = f + else + @predicted_var = f unless @predicted_var + end + end + end + + end +end \ No newline at end of file diff --git a/lib/utils/shims/task.rb b/lib/utils/shims/task.rb index cb73e72..7ac8a7d 100644 --- a/lib/utils/shims/task.rb +++ b/lib/utils/shims/task.rb @@ -11,12 +11,52 @@ module OpenTox # Shims for the Task class class Task + def self.run(description, creator, subjectid=nil) + create($task[:uri],subjectid,{ RDF::DC.description => description, RDF::DC.creator => creator},&Proc.new) + end + # Check status of a task # @return [String] Status def status self[RDF::OT.hasStatus] end + + def code + RestClientWrapper.head(@uri).code + end end end + + +module OpenTox + + class SubTask + + def initialize(task, min, max) + #TODO add subtask code + end + + def self.create(task, min, max) + if task + SubTask.new(task, min, max) + else + nil + end + end + + def waiting_for(task_uri) + #TODO add subtask code + end + + def progress(pct) + #TODO add subtask code + end + + def running?() + #TODO add subtask code + end + end + +end \ No newline at end of file diff --git a/lib/validation.rb b/lib/validation.rb new file mode 100644 index 0000000..47f74d7 --- /dev/null +++ b/lib/validation.rb @@ -0,0 +1,356 @@ +require "yaml" + +module OldOpenTox + attr_accessor :metadata, :uri + + def initialize(uri=nil) + @metadata = {} + self.uri = uri if uri + end + + # loads metadata via yaml + def load_metadata( subjectid=nil ) + yaml = OpenTox::RestClientWrapper.get(uri,nil,{:subjectid => subjectid, :accept => "application/x-yaml"}) + #puts uri + #puts yaml + @metadata = YAML.load(yaml) + end +end + +module OpenTox + + class Validation + include OldOpenTox + + # find validation, raises error if not found + # @param [String] uri + # @param [String,optional] subjectid + # @return [OpenTox::Validation] + def self.find( uri, subjectid=nil ) + val = Validation.new(uri) + val.load_metadata( subjectid ) + val + end + + # returns a filtered list of validation uris + # @param [Hash,optional] params, validation-params to filter the uris (could be model, training_dataset, ..) + # @return [Array] + def self.list( params={} ) + filter_string = "" + params.each do |k,v| + filter_string += (filter_string.length==0 ? "?" : "&") + v = v.to_s.gsub(/;/, "%3b") if v.to_s =~ /;/ + filter_string += k.to_s+"="+v.to_s + end + (OpenTox::RestClientWrapper.get($validation[:uri]+filter_string).split("\n")) + end + + # creates a training test split validation, waits until it finishes, may take some time + # @param [Hash] params (required:algorithm_uri,dataset_uri,prediction_feature, optional:algorithm_params,split_ratio(0.67),random_seed(1)) + # @param [String,optional] subjectid + # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly + # @return [OpenTox::Validation] + def self.create_training_test_split( params, subjectid=nil, waiting_task=nil ) + params[:subjectid] = subjectid if subjectid + uri = OpenTox::RestClientWrapper.post( File.join($validation[:uri],"training_test_split"), + params,{:content_type => "text/uri-list"},waiting_task ) + Validation.new(OpenTox.wait_for_task(uri)) + end + + # creates a training test validation, waits until it finishes, may take some time + # @param [Hash] params (required:algorithm_uri,training_dataset_uri,prediction_feature,test_dataset_uri,optional:algorithm_params) + # @param [String,optional] subjectid + # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly + # @return [OpenTox::Validation] + def self.create_training_test_validation( params, subjectid=nil, waiting_task=nil ) + params[:subjectid] = subjectid if subjectid + uri = OpenTox::RestClientWrapper.post( File.join($validation[:uri],"training_test_validation"), + params,{:content_type => "text/uri-list"},waiting_task ) + Validation.new(OpenTox.wait_for_task(uri)) + end + + # creates a bootstrapping validation, waits until it finishes, may take some time + # @param [Hash] params (required:algorithm_uri,dataset_uri,prediction_feature, optional:algorithm_params,random_seed(1)) + # @param [String,optional] subjectid + # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly + # @return [OpenTox::Validation] + def self.create_bootstrapping_validation( params, subjectid=nil, waiting_task=nil ) + params[:subjectid] = subjectid if subjectid + uri = OpenTox::RestClientWrapper.post( File.join($validation[:uri],"bootstrapping"), + params,{:content_type => "text/uri-list"},waiting_task ) + Validation.new(OpenTox.wait_for_task(uri)) + end + + # looks for report for this validation, creates a report if no report is found + # @param [String,optional] subjectid + # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly + # @return [String] report uri + def find_or_create_report( subjectid=nil, waiting_task=nil ) + @report = ValidationReport.find_for_validation(@uri, subjectid) unless @report + @report = ValidationReport.create(@uri, {}, subjectid, waiting_task) unless @report + @report.uri + end + + # creates a validation object from crossvaldiation statistics, raise error if not found + # (as crossvaldiation statistics are returned as an average valdidation over all folds) + # @param [String] crossvalidation uri + # @param [String,optional] subjectid + # @return [OpenTox::Validation] + def self.from_cv_statistics( crossvalidation_uri, subjectid=nil ) + find( File.join(crossvalidation_uri, 'statistics'),subjectid ) + end + + # returns confusion matrix as array, predicted values are in rows + # example: + # [[nil,"active","moderate","inactive"],["active",1,3,99],["moderate",4,2,8],["inactive",3,8,6]] + # -> 99 inactive compounds have been predicted as active + def confusion_matrix + raise "no classification statistics, probably a regression valdiation" unless @metadata[OT.classificationStatistics] + matrix = @metadata[OT.classificationStatistics][OT.confusionMatrix][OT.confusionMatrixCell] + values = matrix.collect{|cell| cell[OT.confusionMatrixPredicted]}.uniq + table = [[nil]+values] + values.each do |c| + table << [c] + values.each do |r| + matrix.each do |cell| + if cell[OT.confusionMatrixPredicted]==c and cell[OT.confusionMatrixActual]==r + table[-1] << cell[OT.confusionMatrixValue].to_f + break + end + end + end + end + table + end + + # returns probability-distribution for a given prediction + # it takes all predictions into account that have a confidence value that is >= confidence and that have the same predicted value + # (minimum 12 predictions with the hightest confidence are selected (even if the confidence is lower than the given param) + # + # @param [Float] confidence value (between 0 and 1) + # @param [String] predicted value + # @param [String,optional] subjectid + # @return [Hash] see example + # + # Example 1: + # validation.probabilities(0.3,"active") + # -> {:min_confidence=>0.32, :num_predictions=>20, :probs=>{"active"=>0.7, "moderate"=>0.25 "inactive"=>0.05}} + # there have been 20 "active" predictions with confidence >= 0.3, 70 percent of them beeing correct + # + # Example 2: + # validation.probabilities(0.8,"active") + # -> {:min_confidence=>0.45, :num_predictions=>12, :probs=>{"active"=>0.9, "moderate"=>0.1 "inactive"=>0}} + # the given confidence value was to high (i.e. <12 predictions with confidence value >= 0.8) + # the top 12 "active" predictions have a min_confidence of 0.45, 90 percent of them beeing correct + # + def probabilities( confidence, prediction, subjectid=nil ) + YAML.load(OpenTox::RestClientWrapper.get(@uri+"/probabilities?prediction="+prediction.to_s+"&confidence="+confidence.to_s,nil, + {:subjectid => subjectid, :accept => "application/x-yaml"})) + end + end + + class Crossvalidation + include OldOpenTox + + attr_reader :report + + # find crossvalidation, raises error if not found + # @param [String] uri + # @param [String,optional] subjectid + # @return [OpenTox::Crossvalidation] + def self.find( uri, subjectid=nil ) + cv = Crossvalidation.new(uri) + cv.load_metadata( subjectid ) + cv + end + + # returns a filtered list of crossvalidation uris + # @param [Hash,optional] params, crossvalidation-params to filter the uris (could be algorithm, dataset, ..) + # @return [Array] + def self.list( params={} ) + filter_string = "" + params.each do |k,v| + filter_string += (filter_string.length==0 ? "?" : "&") + v = v.to_s.gsub(/;/, "%3b") if v.to_s =~ /;/ + filter_string += k.to_s+"="+v.to_s + end + (OpenTox::RestClientWrapper.get(File.join($validation[:uri],"crossvalidation")+filter_string).split("\n")) + end + + # creates a crossvalidations, waits until it finishes, may take some time + # @param [Hash] params (required:algorithm_uri,dataset_uri,prediction_feature, optional:algorithm_params,num_folds(10),random_seed(1),stratified(false)) + # @param [String,optional] subjectid + # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly + # @return [OpenTox::Crossvalidation] + def self.create( params, subjectid=nil, waiting_task=nil ) + params[:subjectid] = subjectid if subjectid + uri = OpenTox::RestClientWrapper.post( File.join($validation[:uri],"crossvalidation"), + params,{:content_type => "text/uri-list"},waiting_task ) + Crossvalidation.new(OpenTox.wait_for_task(uri)) + end + + # looks for report for this crossvalidation, creates a report if no report is found + # @param [String,optional] subjectid + # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly + # @return [String] report uri + def find_or_create_report( subjectid=nil, waiting_task=nil ) + @report = CrossvalidationReport.find_for_crossvalidation(@uri, subjectid) unless @report + @report = CrossvalidationReport.create(@uri, subjectid, waiting_task) unless @report + @report.uri + end + + # loads metadata via yaml from crossvalidation object + # fields (like for example the validations) can be acces via validation.metadata[OT.validation] + def load_metadata( subjectid=nil ) + @metadata = YAML.load(OpenTox::RestClientWrapper.get(uri,nil,{:subjectid => subjectid, :accept => "application/x-yaml"})) + end + + # returns a Validation object containing the statistics of the crossavlidation + def statistics( subjectid=nil ) + Validation.from_cv_statistics( @uri, subjectid ) + end + + # documentation see OpenTox::Validation.probabilities + def probabilities( confidence, prediction, subjectid=nil ) + YAML.load(OpenTox::RestClientWrapper.get(@uri+"/statistics/probabilities?prediction="+prediction.to_s+"&confidence="+confidence.to_s,nil, + {:subjectid => subjectid, :accept => "application/x-yaml"})) + end + + end + + class ValidationReport + include OldOpenTox + + # finds ValidationReport via uri, raises error if not found + # @param [String] uri + # @param [String,optional] subjectid + # @return [OpenTox::ValidationReport] + def self.find( uri, subjectid=nil ) + OpenTox::RestClientWrapper.get(uri,nil,{:subjectid => subjectid}) + rep = ValidationReport.new(uri) + rep.load_metadata( subjectid ) + rep + end + + # finds ValidationReport for a particular validation + # @param [String] crossvalidation uri + # @param [String,optional] subjectid + # @return [OpenTox::ValidationReport] nil if no report found + def self.find_for_validation( validation_uri, subjectid=nil ) + uris = RestClientWrapper.get(File.join($validation[:uri], + "/report/validation?validation="+validation_uri),nil,{:subjectid => subjectid}).chomp.split("\n") + uris.size==0 ? nil : ValidationReport.new(uris[-1]) + end + + # creates a validation report via validation + # @param [String] validation uri + # @param [Hash] params addiditonal possible + # (min_confidence, params={}, min_num_predictions, max_num_predictions) + # @param [String,optional] subjectid + # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly + # @return [OpenTox::ValidationReport] + def self.create( validation_uri, params={}, subjectid=nil, waiting_task=nil ) + params = {} if params==nil + raise OpenTox::BadRequestError.new "params is no hash" unless params.is_a?(Hash) + params[:validation_uris] = validation_uri + params[:subjectid] = subjectid + uri = RestClientWrapper.post(File.join($validation[:uri],"/report/validation"), + params, {}, waiting_task ) + ValidationReport.new(OpenTox.wait_for_task(uri)) + end + + end + + class CrossvalidationReport + include OldOpenTox + + # finds CrossvalidationReport via uri, raises error if not found + # @param [String] uri + # @param [String,optional] subjectid + # @return [OpenTox::CrossvalidationReport] + def self.find( uri, subjectid=nil ) + OpenTox::RestClientWrapper.get(uri,nil,{:subjectid => subjectid}) + rep = CrossvalidationReport.new(uri) + rep.load_metadata( subjectid ) + rep + end + + # finds CrossvalidationReport for a particular crossvalidation + # @param [String] crossvalidation uri + # @param [String,optional] subjectid + # @return [OpenTox::CrossvalidationReport] nil if no report found + def self.find_for_crossvalidation( crossvalidation_uri, subjectid=nil ) + uris = RestClientWrapper.get(File.join($validation[:uri], + "/report/crossvalidation?crossvalidation="+crossvalidation_uri),nil,{:subjectid => subjectid}).chomp.split("\n") + uris.size==0 ? nil : CrossvalidationReport.new(uris[-1]) + end + + # creates a crossvalidation report via crossvalidation + # @param [String] crossvalidation uri + # @param [String,optional] subjectid + # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly + # @return [OpenTox::CrossvalidationReport] + def self.create( crossvalidation_uri, subjectid=nil, waiting_task=nil ) + uri = RestClientWrapper.post(File.join($validation[:uri],"/report/crossvalidation"), + { :validation_uris => crossvalidation_uri, :subjectid => subjectid }, {}, waiting_task ) + CrossvalidationReport.new(OpenTox.wait_for_task(uri)) + end + end + + + class AlgorithmComparisonReport + include OldOpenTox + + # finds AlgorithmComparisonReport via uri, raises error if not found + # @param [String] uri + # @param [String,optional] subjectid + # @return [OpenTox::CrossvalidationReport] + def self.find( uri, subjectid=nil ) + OpenTox::RestClientWrapper.get(uri,nil,{:subjectid => subjectid}) + rep = AlgorithmComparisonReport.new(uri) + rep.load_metadata( subjectid ) + rep + end + + # finds AlgorithmComparisonReport for a particular crossvalidation + # @param [String] crossvalidation uri + # @param [String,optional] subjectid + # @return [OpenTox::AlgorithmComparisonReport] nil if no report found + def self.find_for_crossvalidation( crossvalidation_uri, subjectid=nil ) + uris = RestClientWrapper.get(File.join($validation[:uri], + "/report/algorithm_comparison?crossvalidation="+crossvalidation_uri),nil,{:subjectid => subjectid}).chomp.split("\n") + uris.size==0 ? nil : AlgorithmComparisonReport.new(uris[-1]) + end + + # creates a algorithm comparison report via crossvalidation uris + # @param [Hash] crossvalidation uri_hash, see example + # @param [Hash] params addiditonal possible + # (ttest_significance, ttest_attributes, min_confidence, min_num_predictions, max_num_predictions) + # @param [String,optional] subjectid + # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly + # @return [OpenTox::AlgorithmComparisonReport] + # example for hash: + # { :lazar-bbrc => [ http://host/validation/crossvalidation/x1, http://host/validation/crossvalidation/x2 ], + # :lazar-last => [ http://host/validation/crossvalidation/xy, http://host/validation/crossvalidation/xy ] } + def self.create( crossvalidation_uri_hash, params={}, subjectid=nil, waiting_task=nil ) + identifier = [] + validation_uris = [] + crossvalidation_uri_hash.each do |id, uris| + uris.each do |uri| + identifier << id + validation_uris << uri + end + end + params = {} if params==nil + raise OpenTox::BadRequestError.new "params is no hash" unless params.is_a?(Hash) + params[:validation_uris] = validation_uris.join(",") + params[:identifier] = identifier.join(",") + params[:subjectid] = subjectid + uri = RestClientWrapper.post(File.join($validation[:uri],"/report/algorithm_comparison"), + params, {}, waiting_task ) + AlgorithmComparisonReport.new(OpenTox.wait_for_task(uri)) + end + end + +end + -- cgit v1.2.3 From 01856c1edf64ca1f33e2c3c99e539f48d3d19dda Mon Sep 17 00:00:00 2001 From: mguetlein Date: Mon, 4 Feb 2013 17:39:56 +0100 Subject: add pending fix to log non-runtime-errors --- lib/task.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/task.rb b/lib/task.rb index 23e6e9e..315dc18 100644 --- a/lib/task.rb +++ b/lib/task.rb @@ -18,7 +18,16 @@ module OpenTox begin result_uri = yield task.completed result_uri - rescue + rescue + unless $!.is_a?(RuntimeError) # PENDING: only runtime Errors are logged when raised + cut_index = $!.backtrace.find_index{|line| line.match /gems\/sinatra/} + msg = "\nTask ERROR\n"+ + "task description: #{params[RDF::DC.description]}\n"+ + "task uri: #{$!.class.to_s}\n"+ + "error msg: #{$!.message}\n"+ + "error backtrace:\n#{$!.backtrace[0..cut_index].join("\n")}\n" + $logger.error msg + end if $!.respond_to? :to_ntriples RestClientWrapper.put(File.join(task.uri,'Error'),:errorReport => $!.to_ntriples,:content_type => 'text/plain') else -- cgit v1.2.3 From cadc92f526a04dd270134bade08d053f4b099923 Mon Sep 17 00:00:00 2001 From: mguetlein Date: Mon, 4 Feb 2013 18:24:24 +0100 Subject: add delete method for validations --- lib/validation.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/validation.rb b/lib/validation.rb index 47f74d7..5c91f7c 100644 --- a/lib/validation.rb +++ b/lib/validation.rb @@ -15,6 +15,10 @@ module OldOpenTox #puts yaml @metadata = YAML.load(yaml) end + + def delete (subjectid=nil) + OpenTox::RestClientWrapper.delete(@uri.to_s,nil,{:subjectid => subjectid}) + end end module OpenTox -- cgit v1.2.3 From f1a6d9f9d5bc73d757e0864d998c95f10ebeecbb Mon Sep 17 00:00:00 2001 From: rautenberg Date: Thu, 7 Feb 2013 11:55:53 +0100 Subject: add regex filter for URL authentification --- lib/authorization.rb | 2 +- lib/rest-client-wrapper.rb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/authorization.rb b/lib/authorization.rb index 1fe5c51..8eefc63 100644 --- a/lib/authorization.rb +++ b/lib/authorization.rb @@ -12,7 +12,7 @@ module OpenTox #Helper Class to create and send default policies out of xml templates #@example Creating a default policy to a URI - # aa=OpenTox::Authorization::AA.new(tok) + # aa=OpenTox::Authorization::Helper.new(tok) # xml=aa.get_xml('http://uri....') # OpenTox::Authorization.create_policy(xml,tok) diff --git a/lib/rest-client-wrapper.rb b/lib/rest-client-wrapper.rb index 1258339..79a65d9 100644 --- a/lib/rest-client-wrapper.rb +++ b/lib/rest-client-wrapper.rb @@ -45,7 +45,8 @@ module OpenTox elsif response.code >= 400 and !URI.task?(uri) message = response.to_s parameters = request.args - parameters[:headers][:subjectid] = "REMOVED" if parameters[:headers] and parameters[:headers][:subjectid] + parameters[:headers][:subjectid] = "REMOVED" if parameters[:headers] and parameters[:headers][:subjectid] + parameters[:url] = parameters[:url].gsub(/(http|https|)\:\/\/[a-zA-Z0-9\-]+\:[a-zA-Z0-9]+\@/, "REMOVED@") if parameters[:url] message += "\nREST parameters:\n#{parameters.inspect}" error = known_errors.collect{|e| e if e[:code] == response.code}.compact.first Object.method(error[:method]).call message, uri # call error method -- cgit v1.2.3