summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/opentox-client.rb3
-rw-r--r--lib/opentox.rb4
-rw-r--r--lib/rest-client-wrapper.rb8
-rw-r--r--lib/utils/shims/dataset.rb98
-rw-r--r--lib/utils/shims/feature.rb2
-rw-r--r--lib/utils/shims/model.rb40
-rw-r--r--lib/utils/shims/task.rb40
-rw-r--r--lib/validation.rb356
8 files changed, 546 insertions, 5 deletions
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
+