opentox-ruby 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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