From 281a0bade2ca1d1bb040c54704650b69f6da24a5 Mon Sep 17 00:00:00 2001 From: mguetlein Date: Mon, 7 Feb 2011 15:35:53 +0100 Subject: .find method raises error if opentox-object not found, extending validation.rb --- lib/algorithm.rb | 11 ++--- lib/model.rb | 11 ++--- lib/task.rb | 1 + lib/validation.rb | 144 +++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 108 insertions(+), 59 deletions(-) (limited to 'lib') diff --git a/lib/algorithm.rb b/lib/algorithm.rb index bfa9860..af8dfaf 100644 --- a/lib/algorithm.rb +++ b/lib/algorithm.rb @@ -31,18 +31,15 @@ module OpenTox class Generic include Algorithm - # Find Generic Opentox Algorithm via URI, and loads metadata + # Find Generic Opentox Algorithm via URI, and loads metadata, could raise NotFound/NotAuthorized error # @param [String] uri Algorithm URI - # @return [OpenTox::Algorithm::Generic] Algorithm instance, nil if alogrithm was not found + # @return [OpenTox::Algorithm::Generic] Algorithm instance def self.find(uri, subjectid=nil) return nil unless uri alg = Generic.new(uri) alg.load_metadata( subjectid ) - if alg.metadata==nil or alg.metadata.size==0 - nil - else - alg - end + raise "cannot load algorithm metadata" if alg.metadata==nil or alg.metadata.size==0 + alg end end diff --git a/lib/model.rb b/lib/model.rb index 7cf52ad..ae793e8 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -24,18 +24,15 @@ module OpenTox class Generic include Model - # Find Generic Opentox Model via URI, and loads metadata + # Find Generic Opentox Model via URI, and loads metadata, could raise NotFound/NotAuthorized error # @param [String] uri Model URI - # @return [OpenTox::Model::Generic] Model instance, nil if model was not found + # @return [OpenTox::Model::Generic] Model instance def self.find(uri,subjectid=nil) return nil unless uri model = Generic.new(uri) model.load_metadata(subjectid) - if model.metadata==nil or model.metadata.size==0 - nil - else - model - end + raise "could not load model metadata" if model.metadata==nil or model.metadata.size==0 + model end # provides feature type, possible types are "regression" or "classification" diff --git a/lib/task.rb b/lib/task.rb index 9c52299..73d880e 100644 --- a/lib/task.rb +++ b/lib/task.rb @@ -80,6 +80,7 @@ module OpenTox return nil unless uri task = Task.new(uri) task.load_metadata + raise "could not load task metadata" if task.metadata==nil or task.metadata.size==0 task end diff --git a/lib/validation.rb b/lib/validation.rb index c256d1d..f0c5297 100644 --- a/lib/validation.rb +++ b/lib/validation.rb @@ -1,4 +1,63 @@ module OpenTox + class Validation + include OpenTox + + # 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 + + # 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 + + # loads metadata via yaml from validation object + # fields (like for example the validated model) can be acces via validation.metadata[OT.model] + def load_metadata( subjectid=nil ) + @metadata = YAML.load(OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid, :accept => "application/x-yaml"})) + end + + # PENDING: creates summary as used for ToxCreate + def summary + if @metadata[OT.classificationStatistics] + res = { + :nr_predictions => @metadata[OT.numInstances] - @metadata[OT.numUnpredicted], + :correct_predictions => @metadata[OT.classificationStatistics][OT.percentCorrect], + :weighted_area_under_roc => @metadata[OT.classificationStatistics][OT.weightedAreaUnderRoc], + } + @metadata[OT.classificationStatistics][OT.classValueStatistics].each do |s| + if s[OT.classValue].to_s=="true" + res[:true_positives] = s[OT.numTruePositives] + res[:false_positives] = s[OT.numFalsePositives] + res[:true_negatives] = s[OT.numTrueNegatives] + res[:false_negatives] = s[OT.numFalseNegatives] + res[:sensitivity] = s[OT.truePositiveRate] + res[:specificity] = s[OT.falsePositiveRate] + break + end + end + res + elsif @metadata[OT.regressionStatistics] + { + :nr_predictions => @metadata[OT.numInstances] - @metadata[OT.numUnpredicted], + :r_square => @metadata[OT.regressionStatistics][OT.rSquare], + :root_mean_squared_error => @metadata[OT.regressionStatistics][OT.rootMeanSquaredError], + :mean_absolute_error => @metadata[OT.regressionStatistics][OT.meanAbsoluteError], + } + end + end + end + class Crossvalidation include OpenTox @@ -9,9 +68,9 @@ module OpenTox # @param [String,optional] subjectid # @return [OpenTox::Crossvalidation] def self.find( uri, subjectid=nil ) - # PENDING load crossvalidation data? - OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid}) - Crossvalidation.new(uri) + cv = Crossvalidation.new(uri) + cv.load_metadata( subjectid ) + cv end # creates a crossvalidations, waits until it finishes, may take some time @@ -31,42 +90,37 @@ module OpenTox # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly # @return [OpenTox::CrossvalidationReport] def find_or_create_report( subjectid=nil, waiting_task=nil ) - @report = CrossvalidationReport.find_for_crossvalidation(self, subjectid) unless @report - @report = CrossvalidationReport.create(self, subjectid, waiting_task) unless @report + @report = CrossvalidationReport.find_for_crossvalidation(@uri, subjectid) unless @report + @report = CrossvalidationReport.create(@uri, subjectid, waiting_task) unless @report @report 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,{:subjectid => subjectid, :accept => "application/x-yaml"})) + end + # PENDING: creates summary as used for ToxCreate def summary( subjectid=nil ) - v = YAML.load RestClientWrapper.get(File.join(@uri, 'statistics'),{:accept => "application/x-yaml", :subjectid => subjectid}).to_s - if v[OT.classificationStatistics] - res = { - :nr_predictions => v[OT.numInstances] - v[OT.numUnpredicted], - :correct_predictions => v[OT.classificationStatistics][OT.percentCorrect], - :weighted_area_under_roc => v[OT.classificationStatistics][OT.weightedAreaUnderRoc], - } - v[OT.classificationStatistics][OT.classValueStatistics].each do |s| - if s[OT.classValue].to_s=="true" - res[:true_positives] = s[OT.numTruePositives] - res[:false_positives] = s[OT.numFalsePositives] - res[:true_negatives] = s[OT.numTrueNegatives] - res[:false_negatives] = s[OT.numFalseNegatives] - res[:sensitivity] = s[OT.truePositiveRate] - res[:specificity] = s[OT.falsePositiveRate] - break - end - end - res - elsif v[OT.regressionStatistics] - { - :nr_predictions => v[OT.numInstances] - v[OT.numUnpredicted], - :r_square => v[OT.regressionStatistics][OT.rSquare], - :root_mean_squared_error => v[OT.regressionStatistics][OT.rootMeanSquaredError], - :mean_absolute_error => v[OT.regressionStatistics][OT.meanAbsoluteError], - } - end + Validation.from_cv_statistics( @uri, subjectid ).summary end end + + class ValidationReport + include OpenTox + + # 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(CONFIG[:services]["opentox-validation"], + "/report/validation?validation="+validation_uri), {:subjectid => subjectid}).chomp.split("\n") + uris.size==0 ? nil : ValidationReport.new(uris[-1]) + end + + end class CrossvalidationReport include OpenTox @@ -82,23 +136,23 @@ module OpenTox end # finds CrossvalidationReport for a particular crossvalidation - # @param [OpenTox::Crossvalidation] + # @param [String] crossvalidation uri # @param [String,optional] subjectid # @return [OpenTox::CrossvalidationReport] nil if no report found - def self.find_for_crossvalidation( crossvalidation, subjectid=nil ) + def self.find_for_crossvalidation( crossvalidation_uri, subjectid=nil ) uris = RestClientWrapper.get(File.join(CONFIG[:services]["opentox-validation"], - "/report/crossvalidation?crossvalidation="+crossvalidation.uri), {:subjectid => subjectid}).chomp.split("\n") + "/report/crossvalidation?crossvalidation="+crossvalidation_uri), {:subjectid => subjectid}).chomp.split("\n") uris.size==0 ? nil : CrossvalidationReport.new(uris[-1]) end # creates a crossvalidation report via crossvalidation - # @param [OpenTox::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, subjectid=nil, waiting_task=nil ) + def self.create( crossvalidation_uri, subjectid=nil, waiting_task=nil ) uri = RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/report/crossvalidation"), - { :validation_uris => crossvalidation.uri, :subjectid => subjectid }, {}, waiting_task ) + { :validation_uris => crossvalidation_uri, :subjectid => subjectid }, {}, waiting_task ) CrossvalidationReport.new(uri) end end @@ -117,23 +171,23 @@ module OpenTox end # finds QMRF report for a particular model - # @param [OpenTox::Crossvalidation] + # @param [String] model_uri # @param [String,optional] subjectid # @return [OpenTox::QMRFReport] nil if no report found - def self.find_for_model( model, subjectid=nil ) + def self.find_for_model( model_uri, subjectid=nil ) uris = RestClientWrapper.get(File.join(CONFIG[:services]["opentox-validation"], - "/reach_report/qmrf?model="+model.uri), {:subjectid => subjectid}).chomp.split("\n") + "/reach_report/qmrf?model="+model_uri), {:subjectid => subjectid}).chomp.split("\n") uris.size==0 ? nil : QMRFReport.new(uris[-1]) end # creates a qmrf report via model - # @param [OpenTox::Model] + # @param [String] model_uri # @param [String,optional] subjectid # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly # @return [OpenTox::QMRFReport] - def self.create( model, subjectid=nil, waiting_task=nil ) + def self.create( model_uri, subjectid=nil, waiting_task=nil ) uri = RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/reach_report/qmrf"), - { :model_uri => model.uri, :subjectid => subjectid }, {}, waiting_task ) + { :model_uri => model_uri, :subjectid => subjectid }, {}, waiting_task ) QMRFReport.new(uri) end end -- cgit v1.2.3