opentox-ruby 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,6 +17,7 @@ module OpenTox
17
17
  # this should come from opentox.owl
18
18
  OT.Compound => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
19
19
  OT.Feature => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
20
+ OT.Model => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
20
21
  OT.NominalFeature => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
21
22
  OT.NumericFeature => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
22
23
  OT.StringFeature => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
@@ -27,6 +28,8 @@ module OpenTox
27
28
  OT.Parameter => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
28
29
  OT.Task => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
29
30
  OTA.PatternMiningSupervised => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
31
+ OTA.ClassificationLazySingleTarget => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
32
+ OTA.RegressionLazySingleTarget => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
30
33
 
31
34
  #classes for validation
32
35
  OT.Validation => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
@@ -45,6 +48,10 @@ module OpenTox
45
48
  OT.values => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
46
49
  OT.algorithm => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
47
50
  OT.parameters => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
51
+ OT.featureDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
52
+ OT.dependentVariables => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
53
+ OT.predictedVariables => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
54
+ OT.paramValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
48
55
 
49
56
  #object props for validation#
50
57
  OT.model => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
@@ -103,6 +110,7 @@ module OpenTox
103
110
  OT.precision => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
104
111
  OT.areaUnderRoc => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
105
112
  OT.weightedAreaUnderRoc => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
113
+ OT.weightedAccuracy => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
106
114
  OT.fMeasure => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
107
115
  OT.percentIncorrect => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
108
116
  OT.validationType => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
@@ -126,7 +134,7 @@ module OpenTox
126
134
  OT.hasSource => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } ,
127
135
  OT.value => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } ,
128
136
  OT.paramScope => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } ,
129
- OT.paramValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } ,
137
+ #OT.paramValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } ,
130
138
  }
131
139
 
132
140
  @data_entries = {}
@@ -157,23 +165,16 @@ module OpenTox
157
165
  # Add a dataset
158
166
  # @param [String] uri Dataset URI
159
167
  def add_dataset(dataset)
160
-
161
168
  @dataset = dataset.uri
162
-
163
169
  @object[dataset.uri] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Dataset }] }
164
-
165
170
  add_metadata dataset.uri, dataset.metadata
166
-
167
171
  dataset.compounds.each { |compound| add_compound compound }
168
-
169
172
  dataset.features.each { |feature,metadata| add_feature feature,metadata }
170
-
171
173
  dataset.data_entries.each do |compound,entry|
172
174
  entry.each do |feature,values|
173
175
  values.each { |value| add_data_entry compound,feature,value }
174
176
  end
175
177
  end
176
-
177
178
  end
178
179
 
179
180
  # Add a algorithm
@@ -188,6 +189,14 @@ module OpenTox
188
189
  def add_model(uri,metadata)
189
190
  @object[uri] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Model }] }
190
191
  add_metadata uri, metadata
192
+ @object[metadata[OT.featureDataset]] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Dataset }] }
193
+ @object[metadata[OT.trainingDataset]] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Dataset }] }
194
+ @object[metadata[OT.dependentVariables]] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Feature }] }
195
+ metadata[OT.predictedVariables].each{|feature| @object[feature] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Feature }]}} #unless metadata[OT.predictedVariables].nil?
196
+ # TODO: add algorithms from parameters
197
+ @object["http://ot-dev.in-silico.ch/algorithm/fminer/bbrc"] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Algorithm }] }
198
+ @object["http://ot-dev.in-silico.ch/algorithm/fminer/last"] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Algorithm }] }
199
+ @object["http://ot-dev.in-silico.ch/algorithm/lazar"] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Algorithm }] }
191
200
  end
192
201
 
193
202
  # Add a task
@@ -272,7 +281,7 @@ module OpenTox
272
281
  @object[genid][name] = [{"type" => type(entry), "value" => entry }]
273
282
  end
274
283
  end
275
- elsif v.is_a? Array and u == RDF.type
284
+ elsif v.is_a? Array #and u == RDF.type
276
285
  @object[uri] = {} unless @object[uri]
277
286
  v.each do |value|
278
287
  @object[uri][u] = [] unless @object[uri][u]
@@ -354,7 +363,8 @@ module OpenTox
354
363
  # @return [text/plain] Object OWL-DL in RDF/XML format
355
364
  def to_rdfxml
356
365
  Tempfile.open("owl-serializer"){|f| f.write(self.to_ntriples); @path = f.path}
357
- `rapper -i ntriples -f 'xmlns:ot="#{OT.uri}"' -f 'xmlns:dc="#{DC.uri}"' -f 'xmlns:rdf="#{RDF.uri}"' -f 'xmlns:owl="#{OWL.uri}"' -o rdfxml #{@path} 2>/dev/null`
366
+ # TODO: add base uri for ist services
367
+ `rapper -i ntriples -f 'xmlns:ot="#{OT.uri}"' -f 'xmlns:ota="#{OTA.uri}"' -f 'xmlns:dc="#{DC.uri}"' -f 'xmlns:rdf="#{RDF.uri}"' -f 'xmlns:owl="#{OWL.uri}"' -o rdfxml #{@path} 2>/dev/null`
358
368
  end
359
369
 
360
370
  # Convert to JSON as specified in http://n2.talis.com/wiki/RDF_JSON_Specification
@@ -373,6 +383,8 @@ module OpenTox
373
383
  XSD.boolean
374
384
  elsif value.is_a? Float
375
385
  XSD.float
386
+ elsif value.is_a? Integer
387
+ XSD.integer
376
388
  else
377
389
  XSD.string
378
390
  end
@@ -383,6 +395,8 @@ module OpenTox
383
395
  datatype = OT.NominalFeature
384
396
  elsif value.is_a? Float
385
397
  datatype = OT.NumericFeature
398
+ elsif value.is_a? Integer
399
+ datatype = OT.NumericFeature
386
400
  else
387
401
  datatype = OT.StringFeature
388
402
  end
@@ -38,6 +38,7 @@ module OpenTox
38
38
  task = Task.new(task_uri.chomp)
39
39
 
40
40
  # measure current memory consumption
41
+ =begin
41
42
  memory = `free -m|sed -n '2p'`.split
42
43
  free_memory = memory[3].to_i + memory[6].to_i # include cache
43
44
  if free_memory < 20 # require at least 200 M free memory
@@ -56,6 +57,7 @@ module OpenTox
56
57
  # return task
57
58
  # #raise "Server too busy to start a new task"
58
59
  #end
60
+ =end
59
61
 
60
62
  task_pid = Spork.spork(:logger => LOGGER) do
61
63
  LOGGER.debug "Task #{task.uri} started #{Time.now}"
@@ -167,6 +169,10 @@ module OpenTox
167
169
  @metadata[OT.hasStatus] == 'Running'
168
170
  end
169
171
 
172
+ def queued?
173
+ @metadata[OT.hasStatus] == 'Queued'
174
+ end
175
+
170
176
  def completed?
171
177
  @metadata[OT.hasStatus] == 'Completed'
172
178
  end
@@ -244,7 +250,7 @@ module OpenTox
244
250
 
245
251
  load_metadata # for extremely fast tasks
246
252
  check_state
247
- while self.running?
253
+ while self.running? or self.queued?
248
254
  sleep dur
249
255
  load_metadata
250
256
  # if another (sub)task is waiting for self, set progress accordingly
@@ -284,9 +290,10 @@ module OpenTox
284
290
  raise "illegal task state, task is completed, resultURI is no URI: '"+@metadata[OT.resultURI].to_s+
285
291
  "'" unless @metadata[OT.resultURI] and @metadata[OT.resultURI].to_s.uri? if completed?
286
292
  if @http_code == 202
287
- raise "#{@uri}: illegal task state, code is 202, but hasStatus is not Running: '"+@metadata[OT.hasStatus]+"'" unless running?
293
+ raise "#{@uri}: illegal task state, code is 202, but hasStatus is not Running or Queued: '"+@metadata[OT.hasStatus]+"'" unless running? or queued?
288
294
  elsif @http_code == 201
289
- raise "#{@uri}: illegal task state, code is 201, but hasStatus is not Completed: '"+@metadata[OT.hasStatus]+"'" unless completed?
295
+ # ignore hasStatus
296
+ # raise "#{@uri}: illegal task state, code is 201, but hasStatus is not Completed: '"+@metadata[OT.hasStatus]+"'" unless completed?
290
297
  raise "#{@uri}: illegal task state, code is 201, resultURI is no task-URI: '"+@metadata[OT.resultURI].to_s+
291
298
  "'" unless @metadata[OT.resultURI] and @metadata[OT.resultURI].to_s.uri?
292
299
  end
@@ -1,12 +1,12 @@
1
1
 
2
- OT_LOGO = "http://opentox.informatik.uni-freiburg.de/ot-logo.png"
2
+ OT_LOGO = File.join(CONFIG[:services]["opentox-validation"],"resources/ot-logo.png")
3
3
 
4
4
  class String
5
5
 
6
6
  # encloses URI in text with with link tag
7
7
  # @return [String] new text with marked links
8
8
  def link_urls
9
- self.gsub(/(?i)http(s?):\/\/[^\r\n\s']*/, '<a href=\0>\0</a>')
9
+ self.gsub(/(?i)http(s?):\/\/[^\r\n\s']*/, '<a href="\0">\0</a>')
10
10
  end
11
11
  end
12
12
 
@@ -15,98 +15,123 @@ module OpenTox
15
15
  # produces a html page for making web services browser friendly
16
16
  # format of text (=string params) is preserved (e.g. line breaks)
17
17
  # urls are marked as links
18
- # @example post params:
19
- # [ [ [:mandatory_param_1], [:mandatory_param_2], [:optional_param,"default_value"] ],
20
- # [ [:alteranative_mandatory_param_1], [:alteranative_mandatory_param_2] ]
21
- # ]
18
+ #
22
19
  # @param [String] text this is the actual content,
23
20
  # @param [optional,String] related_links info on related resources
24
21
  # @param [optional,String] description general info
25
- # @param [optional,Array] post_params, array of arrays containing info on POST operation, see example
22
+ # @param [optional,Array] post_command, infos for the post operation, object defined below
26
23
  # @return [String] html page
27
- def self.text_to_html( text, subjectid=nil, related_links=nil, description=nil, post_params=nil )
24
+ def self.text_to_html( text, subjectid=nil, related_links=nil, description=nil, post_command=nil )
28
25
 
29
26
  # TODO add title as parameter
30
27
  title = nil #$sinatra.url_for($sinatra.request.env['PATH_INFO'], :full) if $sinatra
31
28
  html = "<html>"
32
29
  html += "<title>"+title+"</title>" if title
33
- html += "<img src="+OT_LOGO+"><body>"
30
+ html += "<img src=\""+OT_LOGO+"\"><\/img><body>"
34
31
 
35
32
  if AA_SERVER
36
33
  user = OpenTox::Authorization.get_user(subjectid) if subjectid
37
34
  html += "<pre><p align=\"right\">"
38
35
  unless user
39
- html += "You are currently not logged in to "+$url_provider.url_for("",:full)+
40
- ", <a href="+$url_provider.url_for("/login",:full)+">login</a>"
36
+ html += "You are currently not signed in to "+$url_provider.url_for("",:full)+
37
+ ", <a href="+$url_provider.url_for("/sign_in",:full)+">sign in</a>"
41
38
  else
42
- html += "You are logged in as '#{user}' to "+$url_provider.url_for("",:full)+
43
- ", <a href="+$url_provider.url_for("/logout",:full)+">logout</a>"
39
+ html += "You are signed in as '#{user}' to "+$url_provider.url_for("",:full)+
40
+ ", <a href="+$url_provider.url_for("/sign_out",:full)+">sign out</a>"
44
41
  end
45
42
  html += " </p></pre>"
46
43
  end
47
44
 
48
45
  html += "<h3>Description</h3><pre><p>"+description.link_urls+"</p></pre>" if description
49
46
  html += "<h3>Related links</h3><pre><p>"+related_links.link_urls+"</p></pre>" if related_links
50
- if post_params
51
- html += "<h3>POST parameters</h3>"
52
- count = 0
53
- post_params.each do |p|
54
- html += "<pre><p>alternatively:</p></pre>" if count > 0
55
- html += "<pre><p><table><thead><tr><th>param</th><th>default_value</th></tr></thead>"
56
- p.each do |k,v|
57
- html += "<tr><th>"+k.to_s+"</th><th>"+(v!=nil ? v.to_s : "<i>mandatory</i>")+"</th></tr>"
58
- end
59
- html += "</table></p></pre>"
60
- count += 1
61
- end
47
+ if post_command
48
+ raise "not a post command" unless post_command.is_a?(OpenTox::PostCommand)
49
+ html += "<h3>POST command</h3>"
50
+ html += post_command.to_html
62
51
  end
63
- html += "<h3>Content</h3>" if description || related_links
52
+ html += "<h3>Content</h3>" if description || related_links || post_command
64
53
  html += "<pre><p style=\"padding:15px; border:10px solid \#5D308A\">"
65
54
  html += text.link_urls
66
- html += "</p></pre></body><html>"
55
+ html += "</p></pre></body></html>"
67
56
  html
68
57
  end
69
58
 
70
- def self.login( msg=nil )
59
+ def self.sign_in( msg=nil )
71
60
  html = "<html><title>Login</title><img src="+OT_LOGO+"><body>"
72
- html += "<form method='POST' action='"+$url_provider.url_for("/login",:full)+"'>"
61
+ html += "<form method='POST' action='"+$url_provider.url_for("/sign_in",:full)+"'>"
73
62
  html += "<pre><p style=\"padding:15px; border:10px solid \#5D308A\">"
74
63
  html += msg+"\n\n" if msg
75
- html += "Please login to "+$url_provider.url_for("",:full)+"\n\n"
64
+ html += "Please sign in to "+$url_provider.url_for("",:full)+"\n\n"
76
65
  html += "<table border=0>"
77
66
  html += "<tr><td>user:</td><td><input type='text' name='user' size='15' /></td></tr>"+
78
67
  "<tr><td>password:</td><td><input type='password' name='password' size='15' /></td></tr>"+
79
68
  #"<input type=hidden name=back_to value="+back_to.to_s+">"+
80
- "<tr><td><input type='submit' value='Login' /></td></tr>"
81
- html += "</table></p></pre></form></body><html>"
69
+ "<tr><td><input type='submit' value='Sign in' /></td></tr>"
70
+ html += "</table></p></pre></form></body></html>"
82
71
  html
83
72
  end
73
+
74
+ class PostAttribute
75
+ attr_accessor :name, :is_mandatory, :default, :description
76
+
77
+ def initialize(name, is_mandatory=true, default=nil, description=nil)
78
+ @name = name
79
+ @is_mandatory = is_mandatory
80
+ @default = default
81
+ @description = description
82
+ end
83
+ end
84
+
85
+ class PostCommand
86
+ attr_accessor :attributes, :uri, :name
87
+
88
+ def initialize( uri, name="Send" )
89
+ @uri = uri
90
+ @name = name
91
+ @attributes = []
92
+ end
93
+
94
+ def to_html
95
+ html = "<form method='POST' action='"+@uri.to_s+"'>"
96
+ html << "<pre><p>"
97
+ html << "<table border=0>"
98
+ #html << "<tr><td colspan='3'><i><sup>Mandatory params are marked with *.</sup></i></td></tr>"
99
+ attributes.each do |a|
100
+ mandatory_string = a.is_mandatory ? "*" : ""
101
+ html << "<tr><td>"+a.name.to_s+":"+mandatory_string+"</td>"
102
+ html << "<td><input type='text' name='"+a.name.to_s+
103
+ "' size='50' value='"+a.default.to_s+"'/></td>"
104
+ html << "<td><i><sup>"+a.description.to_s+"</sup></i></td></tr>"
105
+ end
106
+ html << "<tr><td colspan='3'><input type='submit' value='"+@name.to_s+"' /></td></tr>"
107
+ html << "</table></p></pre></form>"
108
+ html
109
+ end
110
+ end
84
111
  end
85
112
 
86
- =begin
87
- get '/logout/?' do
113
+ get '/sign_out/?' do
88
114
  response.set_cookie("subjectid",{:value=>nil})
89
115
  content_type "text/html"
90
- content = "Sucessfully logged out from "+$url_provider.url_for("",:full)
116
+ content = "Sucessfully signed out from "+$url_provider.url_for("",:full)
91
117
  OpenTox.text_to_html(content)
92
118
  end
93
119
 
94
- get '/login/?' do
120
+ get '/sign_in/?' do
95
121
  content_type "text/html"
96
- OpenTox.login
122
+ OpenTox.sign_in
97
123
  end
98
124
 
99
- post '/login/?' do
125
+ post '/sign_in/?' do
100
126
  subjectid = OpenTox::Authorization.authenticate(params[:user], params[:password])
101
127
  if (subjectid)
102
128
  response.set_cookie("subjectid",{:value=>subjectid})
103
129
  content_type "text/html"
104
- content = "Sucessfully logged in as '"+params[:user]+"' to "+$url_provider.url_for("",:full)
130
+ content = "Sucessfully signed in as '"+params[:user]+"' to "+$url_provider.url_for("",:full)
105
131
  OpenTox.text_to_html(content,subjectid)
106
132
  else
107
133
  content_type "text/html"
108
- OpenTox.login("Login failed, please try again")
134
+ OpenTox.sign_in("Login failed, please try again")
109
135
  end
110
136
  end
111
- =end
112
137
 
@@ -36,6 +36,30 @@ module OpenTox
36
36
  Validation.new(uri)
37
37
  end
38
38
 
39
+ # creates a training test validation, waits until it finishes, may take some time
40
+ # @param [Hash] params (required:algorithm_uri,training_dataset_uri,prediction_feature,test_dataset_uri,optional:algorithm_params)
41
+ # @param [String,optional] subjectid
42
+ # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
43
+ # @return [OpenTox::Validation]
44
+ def self.create_training_test_validation( params, subjectid=nil, waiting_task=nil )
45
+ params[:subjectid] = subjectid if subjectid
46
+ uri = OpenTox::RestClientWrapper.post( File.join(CONFIG[:services]["opentox-validation"],"training_test_validation"),
47
+ params,{:content_type => "text/uri-list"},waiting_task )
48
+ Validation.new(uri)
49
+ end
50
+
51
+ # creates a bootstrapping validation, waits until it finishes, may take some time
52
+ # @param [Hash] params (required:algorithm_uri,dataset_uri,prediction_feature, optional:algorithm_params,random_seed(1))
53
+ # @param [String,optional] subjectid
54
+ # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
55
+ # @return [OpenTox::Validation]
56
+ def self.create_bootstrapping_validation( params, subjectid=nil, waiting_task=nil )
57
+ params[:subjectid] = subjectid if subjectid
58
+ uri = OpenTox::RestClientWrapper.post( File.join(CONFIG[:services]["opentox-validation"],"bootstrapping"),
59
+ params,{:content_type => "text/uri-list"},waiting_task )
60
+ Validation.new(uri)
61
+ end
62
+
39
63
  # looks for report for this validation, creates a report if no report is found
40
64
  # @param [String,optional] subjectid
41
65
  # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
@@ -61,34 +85,27 @@ module OpenTox
61
85
  @metadata = YAML.load(OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid, :accept => "application/x-yaml"}))
62
86
  end
63
87
 
64
- # PENDING: creates summary as used for ToxCreate
65
- def summary
66
- if @metadata[OT.classificationStatistics]
67
- res = {
68
- :nr_predictions => @metadata[OT.numInstances] - @metadata[OT.numUnpredicted],
69
- :correct_predictions => @metadata[OT.classificationStatistics][OT.percentCorrect],
70
- :weighted_area_under_roc => @metadata[OT.classificationStatistics][OT.weightedAreaUnderRoc],
71
- }
72
- @metadata[OT.classificationStatistics][OT.classValueStatistics].each do |s|
73
- if s[OT.classValue].to_s=="true"
74
- res[:true_positives] = s[OT.numTruePositives]
75
- res[:false_positives] = s[OT.numFalsePositives]
76
- res[:true_negatives] = s[OT.numTrueNegatives]
77
- res[:false_negatives] = s[OT.numFalseNegatives]
78
- res[:sensitivity] = s[OT.truePositiveRate]
79
- res[:specificity] = s[OT.trueNegativeRate]
80
- break
88
+ # returns confusion matrix as array, predicted values are in rows
89
+ # example:
90
+ # [[nil,"active","moderate","inactive"],["active",1,3,99],["moderate",4,2,8],["inactive",3,8,6]]
91
+ # -> 99 inactive compounds have been predicted as active
92
+ def confusion_matrix
93
+ raise "no classification statistics, probably a regression valdiation" unless @metadata[OT.classificationStatistics]
94
+ matrix = @metadata[OT.classificationStatistics][OT.confusionMatrix][OT.confusionMatrixCell]
95
+ values = matrix.collect{|cell| cell[OT.confusionMatrixPredicted]}.uniq
96
+ table = [[nil]+values]
97
+ values.each do |c|
98
+ table << [c]
99
+ values.each do |r|
100
+ matrix.each do |cell|
101
+ if cell[OT.confusionMatrixPredicted]==c and cell[OT.confusionMatrixActual]==r
102
+ table[-1] << cell[OT.confusionMatrixValue].to_f
103
+ break
104
+ end
81
105
  end
82
106
  end
83
- res
84
- elsif @metadata[OT.regressionStatistics]
85
- {
86
- :nr_predictions => @metadata[OT.numInstances] - @metadata[OT.numUnpredicted],
87
- :r_square => @metadata[OT.regressionStatistics][OT.rSquare],
88
- :root_mean_squared_error => @metadata[OT.regressionStatistics][OT.rootMeanSquaredError],
89
- :mean_absolute_error => @metadata[OT.regressionStatistics][OT.meanAbsoluteError],
90
- }
91
107
  end
108
+ table
92
109
  end
93
110
  end
94
111
 
@@ -147,9 +164,9 @@ module OpenTox
147
164
  @metadata = YAML.load(OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid, :accept => "application/x-yaml"}))
148
165
  end
149
166
 
150
- # PENDING: creates summary as used for ToxCreate
151
- def summary( subjectid=nil )
152
- Validation.from_cv_statistics( @uri, subjectid ).summary
167
+ # returns a Validation object containing the statistics of the crossavlidation
168
+ def statistics( subjectid=nil )
169
+ Validation.from_cv_statistics( @uri, subjectid )
153
170
  end
154
171
  end
155
172
 
@@ -198,7 +215,6 @@ module OpenTox
198
215
  # @param [String,optional] subjectid
199
216
  # @return [OpenTox::CrossvalidationReport]
200
217
  def self.find( uri, subjectid=nil )
201
- # PENDING load report data?
202
218
  OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid})
203
219
  rep = CrossvalidationReport.new(uri)
204
220
  rep.load_metadata( subjectid )
@@ -227,6 +243,54 @@ module OpenTox
227
243
  end
228
244
  end
229
245
 
246
+
247
+ class AlgorithmComparisonReport
248
+ include OpenTox
249
+
250
+ # finds AlgorithmComparisonReport via uri, raises error if not found
251
+ # @param [String] uri
252
+ # @param [String,optional] subjectid
253
+ # @return [OpenTox::CrossvalidationReport]
254
+ def self.find( uri, subjectid=nil )
255
+ OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid})
256
+ rep = AlgorithmComparisonReport.new(uri)
257
+ rep.load_metadata( subjectid )
258
+ rep
259
+ end
260
+
261
+ # finds AlgorithmComparisonReport for a particular crossvalidation
262
+ # @param [String] crossvalidation uri
263
+ # @param [String,optional] subjectid
264
+ # @return [OpenTox::AlgorithmComparisonReport] nil if no report found
265
+ def self.find_for_crossvalidation( crossvalidation_uri, subjectid=nil )
266
+ uris = RestClientWrapper.get(File.join(CONFIG[:services]["opentox-validation"],
267
+ "/report/algorithm_comparison?crossvalidation="+crossvalidation_uri), {:subjectid => subjectid}).chomp.split("\n")
268
+ uris.size==0 ? nil : AlgorithmComparisonReport.new(uris[-1])
269
+ end
270
+
271
+ # creates a crossvalidation report via crossvalidation
272
+ # @param [Hash] crossvalidation uri_hash, see example
273
+ # @param [String,optional] subjectid
274
+ # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
275
+ # @return [OpenTox::AlgorithmComparisonReport]
276
+ # example for hash:
277
+ # { :lazar-bbrc => [ http://host/validation/crossvalidation/x1, http://host/validation/crossvalidation/x2 ],
278
+ # :lazar-last => [ http://host/validation/crossvalidation/xy, http://host/validation/crossvalidation/xy ] }
279
+ def self.create( crossvalidation_uri_hash, subjectid=nil, waiting_task=nil )
280
+ identifier = []
281
+ validation_uris = []
282
+ crossvalidation_uri_hash.each do |id, uris|
283
+ uris.each do |uri|
284
+ identifier << id
285
+ validation_uris << uri
286
+ end
287
+ end
288
+ uri = RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/report/algorithm_comparison"),
289
+ { :validation_uris => validation_uris.join(","), :identifier => identifier.join(","), :subjectid => subjectid }, {}, waiting_task )
290
+ AlgorithmComparisonReport.new(uri)
291
+ end
292
+ end
293
+
230
294
  class QMRFReport
231
295
  include OpenTox
232
296