opentox-ruby 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/task.rb CHANGED
@@ -2,41 +2,191 @@ $self_task=nil
2
2
 
3
3
  module OpenTox
4
4
 
5
+ # Class for handling asynchronous tasks
5
6
  class Task
7
+ include OpenTox
8
+ attr_accessor :http_code, :due_to_time
9
+
10
+ def initialize(uri=nil)
11
+ super uri
12
+ @metadata = {
13
+ DC.title => "",
14
+ DC.date => "",
15
+ OT.hasStatus => "Running",
16
+ OT.percentageCompleted => "0",
17
+ OT.resultURI => "",
18
+ DC.creator => "", # not mandatory according to API
19
+ DC.description => "", # not mandatory according to API
20
+ }
21
+ end
22
+
23
+ # Create a new task for the code in the block. Catches halts and exceptions and sets task state to error if necessary. The block has to return the URI of the created resource.
24
+ # @example
25
+ # task = OpenTox::Task.create do
26
+ # # this code will be executed as a task
27
+ # model = OpenTox::Algorithm.run(params) # this can be time consuming
28
+ # model.uri # Important: return URI of the created resource
29
+ # end
30
+ # task.status # returns "Running", because tasks are forked
31
+ # @param [String] title Task title
32
+ # @param [String] creator Task creator
33
+ # @return [OPenTox::Task] Task
34
+ def self.create( title=nil, creator=nil, max_duration=DEFAULT_TASK_MAX_DURATION, description=nil )
35
+
36
+ params = {:title=>title, :creator=>creator, :max_duration=>max_duration, :description=>description }
37
+ task_uri = RestClientWrapper.post(CONFIG[:services]["opentox-task"], params, nil, false).to_s
38
+ task = Task.new(task_uri.chomp)
39
+
40
+ # measure current memory consumption
41
+ memory = `free -m|sed -n '2p'`.split
42
+ free_memory = memory[3].to_i + memory[6].to_i # include cache
43
+ if free_memory < 20 # require at least 200 M free memory
44
+ LOGGER.warn "Cannot start task - not enough memory left (#{free_memory} M free)"
45
+ task.cancel
46
+ return task
47
+ #raise "Insufficient memory to start a new task"
48
+ end
49
+
50
+ cpu_load = `cat /proc/loadavg`.split(/\s+/)[0..2].collect{|c| c.to_f}
51
+ nr_cpu_cores = `cat /proc/cpuinfo |grep "cpu cores"|cut -d ":" -f2|tr -d " "`.split("\n").collect{|c| c.to_i}.inject{|sum,n| sum+n}
52
+ if cpu_load[0] > nr_cpu_cores and cpu_load[0] > cpu_load[1] and cpu_load[1] > cpu_load[2] # average CPU load of the last minute is high and CPU load is increasing
53
+ LOGGER.warn "Cannot start task - CPU load too high (#{cpu_load.join(", ")})"
54
+ task.cancel
55
+ return task
56
+ #raise "Server too busy to start a new task"
57
+ end
6
58
 
7
- # due_to_time is only set in local tasks
8
- TASK_ATTRIBS = [ :uri, :date, :title, :creator, :description, :hasStatus, :percentageCompleted, :resultURI, :due_to_time ]
9
- TASK_ATTRIBS.each{ |a| attr_accessor(a) }
10
- attr_accessor :http_code
59
+
60
+ task_pid = Spork.spork(:logger => LOGGER) do
61
+ LOGGER.debug "Task #{task.uri} started #{Time.now}"
62
+ $self_task = task
63
+
64
+ begin
65
+ result = catch(:halt) do
66
+ yield task
67
+ end
68
+ # catching halt, set task state to error
69
+ if result && result.is_a?(Array) && result.size==2 && result[0]>202
70
+ LOGGER.error "task was halted: "+result.inspect
71
+ task.error(result[1])
72
+ return
73
+ end
74
+ LOGGER.debug "Task #{task.uri} done #{Time.now} -> "+result.to_s
75
+ task.completed(result)
76
+ rescue => ex
77
+ LOGGER.error "task failed: "+ex.message
78
+ LOGGER.error ": "+ex.backtrace.join("\n")
79
+ task.error(ex.message)
80
+ end
81
+ end
82
+ task.pid = task_pid
83
+ LOGGER.debug "Started task: "+task.uri.to_s
84
+ task
85
+ end
86
+
87
+ # Find a task for querying, status changes
88
+ # @param [String] uri Task URI
89
+ # @return [OpenTox::Task] Task object
90
+ def self.find(uri)
91
+ task = Task.new(uri)
92
+ task.load_metadata
93
+ task
94
+ end
95
+
96
+ # Get a list of all tasks
97
+ # @param [optional, String] uri URI of task service
98
+ # @return [text/uri-list] Task URIs
99
+ def self.all(uri=CONFIG[:services]["opentox-task"])
100
+ OpenTox.all uri
101
+ end
102
+
103
+ def self.from_yaml(yaml)
104
+ @metadata = YAML.load(yaml)
105
+ end
106
+
107
+ def self.from_rdfxml(rdfxml)
108
+ file = Tempfile.open("ot-rdfxml"){|f| f.write(rdfxml)}.path
109
+ parser = Parser::Owl::Generic.new file
110
+ @metadata = parser.load_metadata
111
+ end
112
+
113
+ def to_rdfxml
114
+ s = Serializer::Owl.new
115
+ s.add_task(@uri,@metadata)
116
+ s.to_rdfxml
117
+ end
118
+
119
+ def status
120
+ @metadata[OT.hasStatus]
121
+ end
122
+
123
+ def result_uri
124
+ @metadata[OT.resultURI]
125
+ end
126
+
127
+ def description
128
+ @metadata[DC.description]
129
+ end
11
130
 
12
- private
13
- def initialize(uri)
14
- @uri = uri.to_s.strip
131
+ def cancel
132
+ RestClientWrapper.put(File.join(@uri,'Cancelled'))
133
+ load_metadata
134
+ end
135
+
136
+ def completed(uri)
137
+ RestClientWrapper.put(File.join(@uri,'Completed'),{:resultURI => uri})
138
+ load_metadata
139
+ end
140
+
141
+ def error(description)
142
+ RestClientWrapper.put(File.join(@uri,'Error'),{:description => description.to_s[0..2000]})
143
+ load_metadata
15
144
  end
16
145
 
17
- # create is private now, use OpenTox::Task.as_task
18
- def self.create( params )
19
- task_uri = RestClientWrapper.post(@@config[:services]["opentox-task"], params, nil, false).to_s
20
- Task.find(task_uri.chomp)
146
+ def pid=(pid)
147
+ RestClientWrapper.put(File.join(@uri,'pid'), {:pid => pid})
21
148
  end
22
-
23
- public
24
- def self.find( uri, accept_header=nil )
25
- task = Task.new(uri)
26
- task.reload( accept_header )
27
- return task
149
+
150
+ def running?
151
+ @metadata[OT.hasStatus] == 'Running'
28
152
  end
153
+
154
+ def completed?
155
+ @metadata[OT.hasStatus] == 'Completed'
156
+ end
157
+
158
+ def error?
159
+ @metadata[OT.hasStatus] == 'Error'
160
+ end
161
+
162
+ def load_metadata
163
+ if (CONFIG[:yaml_hosts].include?(URI.parse(uri).host))
164
+ result = RestClientWrapper.get(@uri, {:accept => 'application/x-yaml'}, false)
165
+ @metadata = YAML.load result.to_s
166
+ @http_code = result.code
167
+ else
168
+ @metadata = Parser::Owl::Generic.new(@uri).load_metadata
169
+ @http_code = RestClientWrapper.get(uri, {:accept => 'application/rdf+xml'}, false).code
170
+ end
171
+ end
172
+
173
+ # create is private now, use OpenTox::Task.as_task
174
+ #def self.create( params )
175
+ #task_uri = RestClientWrapper.post(CONFIG[:services]["opentox-task"], params, nil, false).to_s
176
+ #Task.find(task_uri.chomp)
177
+ #end
29
178
 
179
+ =begin
30
180
  def self.from_data(data, content_type, code, base_uri)
31
181
  task = Task.new(nil)
32
182
  task.http_code = code
33
183
  task.reload_from_data(data, content_type, base_uri)
34
184
  return task
35
185
  end
36
-
186
+
37
187
  def reload( accept_header=nil )
38
188
  unless accept_header
39
- if (@@config[:yaml_hosts].include?(URI.parse(uri).host))
189
+ if (CONFIG[:yaml_hosts].include?(URI.parse(uri).host))
40
190
  accept_header = "application/x-yaml"
41
191
  else
42
192
  accept_header = 'application/rdf+xml'
@@ -64,113 +214,46 @@ module OpenTox
64
214
  end
65
215
  raise "uri is null after loading" unless @uri and @uri.to_s.strip.size>0
66
216
  end
67
-
68
- def cancel
69
- RestClientWrapper.put(File.join(@uri,'Cancelled'))
70
- reload
71
- end
72
-
73
- def completed(uri)
74
- RestClientWrapper.put(File.join(@uri,'Completed'),{:resultURI => uri})
75
- reload
76
- end
77
-
78
- def error(description)
79
- RestClientWrapper.put(File.join(@uri,'Error'),{:description => description.to_s[0..2000]})
80
- reload
81
- end
82
-
83
- def pid=(pid)
84
- RestClientWrapper.put(File.join(@uri,'pid'), {:pid => pid})
85
- end
86
-
87
- def running?
88
- @hasStatus.to_s == 'Running'
89
- end
90
-
91
- def completed?
92
- @hasStatus.to_s == 'Completed'
93
- end
94
-
95
- def error?
96
- @hasStatus.to_s == 'Error'
97
- end
217
+ =end
98
218
 
99
219
  # waits for a task, unless time exceeds or state is no longer running
100
220
  def wait_for_completion(dur=0.3)
101
221
 
102
- if (@uri.match(@@config[:services]["opentox-task"]))
103
- due_to_time = (@due_to_time.is_a?(Time) ? @due_to_time : Time.parse(@due_to_time))
104
- running_time = due_to_time - (@date.is_a?(Time) ? @date : Time.parse(@date))
105
- else
106
- # the date of the external task cannot be trusted, offest to local time might be to big
107
- due_to_time = Time.new + EXTERNAL_TASK_MAX_DURATION
108
- running_time = EXTERNAL_TASK_MAX_DURATION
109
- end
222
+ due_to_time = Time.new + DEFAULT_TASK_MAX_DURATION
110
223
  LOGGER.debug "start waiting for task "+@uri.to_s+" at: "+Time.new.to_s+", waiting at least until "+due_to_time.to_s
111
224
 
225
+ load_metadata # for extremely fast tasks
226
+ check_state
112
227
  while self.running?
113
228
  sleep dur
114
- reload
229
+ load_metadata
115
230
  check_state
116
231
  if (Time.new > due_to_time)
117
- raise "max wait time exceeded ("+running_time.to_s+"sec), task: '"+@uri.to_s+"'"
232
+ raise "max wait time exceeded ("+DEFAULT_TASK_MAX_DURATION.to_s+"sec), task: '"+@uri.to_s+"'"
118
233
  end
119
234
  end
120
235
 
121
- LOGGER.debug "Task '"+@hasStatus+"': "+@uri.to_s+", Result: "+@resultURI.to_s
236
+ LOGGER.debug "Task '"+@metadata[OT.hasStatus]+"': "+@uri.to_s+", Result: "+@metadata[OT.resultURI].to_s
122
237
  end
123
238
 
239
+ private
124
240
  def check_state
125
241
  begin
126
- raise "illegal task state, task is completed, resultURI is no URI: '"+@resultURI.to_s+
127
- "'" unless @resultURI and Utils.is_uri?(@resultURI) if completed?
242
+ raise "illegal task state, task is completed, resultURI is no URI: '"+@metadata[OT.resultURI].to_s+
243
+ "'" unless @metadata[OT.resultURI] and @metadata[OT.resultURI].to_s.uri? if completed?
128
244
 
129
245
  if @http_code == 202
130
- raise "illegal task state, code is 202, but hasStatus is not Running: '"+@hasStatus+"'" unless running?
246
+ raise "#{@uri}: illegal task state, code is 202, but hasStatus is not Running: '"+@metadata[OT.hasStatus]+"'" unless running?
131
247
  elsif @http_code == 201
132
- raise "illegal task state, code is 201, but hasStatus is not Completed: '"+@hasStatus+"'" unless completed?
133
- raise "illegal task state, code is 201, resultURI is no task-URI: '"+@resultURI.to_s+
134
- "'" unless @resultURI and Utils.task_uri?(@resultURI)
248
+ raise "#{@uri}: illegal task state, code is 201, but hasStatus is not Completed: '"+@metadata[OT.hasStatus]+"'" unless completed?
249
+ raise "#{@uri}: illegal task state, code is 201, resultURI is no task-URI: '"+@metadata[OT.resultURI].to_s+
250
+ "'" unless @metadata[OT.resultURI] and @metadata[OT.resultURI].to_s.uri?
135
251
  end
136
252
  rescue => ex
137
253
  RestClientWrapper.raise_uri_error(ex.message, @uri)
138
254
  end
139
255
  end
140
-
141
- # returns the task uri
142
- # catches halts and exceptions, task state is set to error then
143
- def self.as_task( title, creator, max_duration=DEFAULT_TASK_MAX_DURATION, description=nil )
144
- #return yield nil
145
-
146
- params = {:title=>title, :creator=>creator, :max_duration=>max_duration, :description=>description }
147
- task = OpenTox::Task.create(params)
148
- task_pid = Spork.spork(:logger => LOGGER) do
149
- LOGGER.debug "Task #{task.uri} started #{Time.now}"
150
- $self_task = task
151
-
152
- begin
153
- result = catch(:halt) do
154
- yield task
155
- end
156
- # catching halt, set task state to error
157
- if result && result.is_a?(Array) && result.size==2 && result[0]>202
158
- LOGGER.error "task was halted: "+result.inspect
159
- task.error(result[1])
160
- return
161
- end
162
- LOGGER.debug "Task #{task.uri} done #{Time.now} -> "+result.to_s
163
- task.completed(result)
164
- rescue => ex
165
- LOGGER.error "task failed: "+ex.message
166
- LOGGER.error ": "+ex.backtrace.join("\n")
167
- task.error(ex.message)
168
- end
169
- end
170
- task.pid = task_pid
171
- LOGGER.debug "Started task: "+task.uri.to_s
172
- task.uri
173
- end
256
+
174
257
  end
175
258
 
176
259
  end
data/lib/validation.rb CHANGED
@@ -1,20 +1,70 @@
1
1
  module OpenTox
2
2
  class Validation
3
+ include OpenTox
3
4
 
4
- attr_accessor :uri
5
-
6
- def initialize(params)
7
- @uri = OpenTox::RestClientWrapper.post(File.join(@@config[:services]["opentox-validation"],"/crossvalidation"),params,nil,false)
8
- end
5
+ attr_accessor :report_uri, :qmrf_report_uri
9
6
 
10
- def self.crossvalidation(params)
11
- params[:uri] = File.join(@@config[:services]['opentox-validation'], "crossvalidation")
7
+ def self.create_crossvalidation(params)
8
+ params[:uri] = File.join(CONFIG[:services]['opentox-validation'], "crossvalidation")
12
9
  params[:num_folds] = 10 unless params[:num_folds]
13
10
  params[:random_seed] = 2 unless params[:random_seed]
14
11
  params[:stratified] = false unless params[:stratified]
15
- OpenTox::Validation.new(params)
12
+ uri = OpenTox::RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/crossvalidation"),params,nil,false)
13
+ OpenTox::Validation.new(uri)
16
14
  end
17
15
 
16
+ def create_report
17
+ @report_uri = RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/report/crossvalidation"), :validation_uris => @uri).to_s
18
+ @report_uri
19
+ end
20
+
21
+ def create_qmrf_report
22
+ @qmrf_report_uri = RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/reach_report/qmrf"), :model_uri => @uri).to_s
23
+ @qmrf_report_uri
24
+ end
25
+
26
+ def summary(type)
27
+ v = YAML.load RestClientWrappper.get(File.join(@uri, 'statistics'),:accept => "application/x-yaml").to_s
28
+
29
+ case type
30
+ when "classification"
31
+ tp=0; tn=0; fp=0; fn=0; n=0
32
+ v[:classification_statistics][:confusion_matrix][:confusion_matrix_cell].each do |cell|
33
+ if cell[:confusion_matrix_predicted] == "true" and cell[:confusion_matrix_actual] == "true"
34
+ tp = cell[:confusion_matrix_value]
35
+ n += tp
36
+ elsif cell[:confusion_matrix_predicted] == "false" and cell[:confusion_matrix_actual] == "false"
37
+ tn = cell[:confusion_matrix_value]
38
+ n += tn
39
+ elsif cell[:confusion_matrix_predicted] == "false" and cell[:confusion_matrix_actual] == "true"
40
+ fn = cell[:confusion_matrix_value]
41
+ n += fn
42
+ elsif cell[:confusion_matrix_predicted] == "true" and cell[:confusion_matrix_actual] == "false"
43
+ fp = cell[:confusion_matrix_value]
44
+ n += fp
45
+ end
46
+ end
47
+ {
48
+ :nr_predictions => n,
49
+ :true_positives => tp,
50
+ :false_positives => fp,
51
+ :true_negatives => tn,
52
+ :false_negatives => fn,
53
+ :correct_predictions => 100*(tp+tn).to_f/n,
54
+ :weighted_area_under_roc => v[:classification_statistics][:weighted_area_under_roc].to_f,
55
+ :sensitivity => tp.to_f/(tp+fn),
56
+ :specificity => tn.to_f/(tn+fp),
57
+ }
58
+ when "regression"
59
+ {
60
+ :nr_predictions => v[:num_instances] - v[:num_unpredicted],
61
+ :r_square => v[:regression_statistics][:r_square],
62
+ :root_mean_squared_error => v[:regression_statistics][:root_mean_squared_error],
63
+ :mean_absolute_error => v[:regression_statistics][:mean_absolute_error],
64
+ }
65
+ end
66
+ end
67
+
18
68
  end
19
69
  end
20
70
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opentox-ruby
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Christoph Helma, Martin Guetlein, Andreas Maunz, Micha Rautenberg, David Vorgrimmler
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-24 00:00:00 +01:00
18
+ date: 2010-11-30 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -201,7 +201,7 @@ dependencies:
201
201
  type: :runtime
202
202
  version_requirements: *id013
203
203
  - !ruby/object:Gem::Dependency
204
- name: tmail
204
+ name: yajl-ruby
205
205
  prerelease: false
206
206
  requirement: &id014 !ruby/object:Gem::Requirement
207
207
  none: false
@@ -215,7 +215,7 @@ dependencies:
215
215
  type: :runtime
216
216
  version_requirements: *id014
217
217
  - !ruby/object:Gem::Dependency
218
- name: rinruby
218
+ name: tmail
219
219
  prerelease: false
220
220
  requirement: &id015 !ruby/object:Gem::Requirement
221
221
  none: false
@@ -229,7 +229,7 @@ dependencies:
229
229
  type: :runtime
230
230
  version_requirements: *id015
231
231
  - !ruby/object:Gem::Dependency
232
- name: rjb
232
+ name: rinruby
233
233
  prerelease: false
234
234
  requirement: &id016 !ruby/object:Gem::Requirement
235
235
  none: false
@@ -243,21 +243,21 @@ dependencies:
243
243
  type: :runtime
244
244
  version_requirements: *id016
245
245
  - !ruby/object:Gem::Dependency
246
- name: dm-core
246
+ name: rjb
247
247
  prerelease: false
248
248
  requirement: &id017 !ruby/object:Gem::Requirement
249
249
  none: false
250
250
  requirements:
251
251
  - - ">="
252
252
  - !ruby/object:Gem::Version
253
- hash: 1
253
+ hash: 3
254
254
  segments:
255
- - 1
256
- version: "1"
255
+ - 0
256
+ version: "0"
257
257
  type: :runtime
258
258
  version_requirements: *id017
259
259
  - !ruby/object:Gem::Dependency
260
- name: dm-serializer
260
+ name: dm-core
261
261
  prerelease: false
262
262
  requirement: &id018 !ruby/object:Gem::Requirement
263
263
  none: false
@@ -271,7 +271,7 @@ dependencies:
271
271
  type: :runtime
272
272
  version_requirements: *id018
273
273
  - !ruby/object:Gem::Dependency
274
- name: dm-timestamps
274
+ name: dm-serializer
275
275
  prerelease: false
276
276
  requirement: &id019 !ruby/object:Gem::Requirement
277
277
  none: false
@@ -285,7 +285,7 @@ dependencies:
285
285
  type: :runtime
286
286
  version_requirements: *id019
287
287
  - !ruby/object:Gem::Dependency
288
- name: dm-types
288
+ name: dm-timestamps
289
289
  prerelease: false
290
290
  requirement: &id020 !ruby/object:Gem::Requirement
291
291
  none: false
@@ -299,7 +299,7 @@ dependencies:
299
299
  type: :runtime
300
300
  version_requirements: *id020
301
301
  - !ruby/object:Gem::Dependency
302
- name: dm-migrations
302
+ name: dm-types
303
303
  prerelease: false
304
304
  requirement: &id021 !ruby/object:Gem::Requirement
305
305
  none: false
@@ -313,7 +313,7 @@ dependencies:
313
313
  type: :runtime
314
314
  version_requirements: *id021
315
315
  - !ruby/object:Gem::Dependency
316
- name: dm-mysql-adapter
316
+ name: dm-migrations
317
317
  prerelease: false
318
318
  requirement: &id022 !ruby/object:Gem::Requirement
319
319
  none: false
@@ -327,7 +327,7 @@ dependencies:
327
327
  type: :runtime
328
328
  version_requirements: *id022
329
329
  - !ruby/object:Gem::Dependency
330
- name: dm-validations
330
+ name: dm-mysql-adapter
331
331
  prerelease: false
332
332
  requirement: &id023 !ruby/object:Gem::Requirement
333
333
  none: false
@@ -341,9 +341,23 @@ dependencies:
341
341
  type: :runtime
342
342
  version_requirements: *id023
343
343
  - !ruby/object:Gem::Dependency
344
- name: haml
344
+ name: dm-validations
345
345
  prerelease: false
346
346
  requirement: &id024 !ruby/object:Gem::Requirement
347
+ none: false
348
+ requirements:
349
+ - - ">="
350
+ - !ruby/object:Gem::Version
351
+ hash: 1
352
+ segments:
353
+ - 1
354
+ version: "1"
355
+ type: :runtime
356
+ version_requirements: *id024
357
+ - !ruby/object:Gem::Dependency
358
+ name: haml
359
+ prerelease: false
360
+ requirement: &id025 !ruby/object:Gem::Requirement
347
361
  none: false
348
362
  requirements:
349
363
  - - ">="
@@ -353,11 +367,11 @@ dependencies:
353
367
  - 3
354
368
  version: "3"
355
369
  type: :runtime
356
- version_requirements: *id024
370
+ version_requirements: *id025
357
371
  - !ruby/object:Gem::Dependency
358
372
  name: jeweler
359
373
  prerelease: false
360
- requirement: &id025 !ruby/object:Gem::Requirement
374
+ requirement: &id026 !ruby/object:Gem::Requirement
361
375
  none: false
362
376
  requirements:
363
377
  - - ">="
@@ -367,7 +381,7 @@ dependencies:
367
381
  - 0
368
382
  version: "0"
369
383
  type: :development
370
- version_requirements: *id025
384
+ version_requirements: *id026
371
385
  description: Ruby wrapper for the OpenTox REST API (http://www.opentox.org)
372
386
  email: helma@in-silico.ch
373
387
  executables:
@@ -390,17 +404,22 @@ files:
390
404
  - lib/config/config_ru.rb
391
405
  - lib/dataset.rb
392
406
  - lib/environment.rb
407
+ - lib/feature.rb
393
408
  - lib/helper.rb
394
409
  - lib/model.rb
410
+ - lib/opentox-ruby.rb
395
411
  - lib/opentox.owl
412
+ - lib/opentox.rb
396
413
  - lib/overwrite.rb
414
+ - lib/parser.rb
397
415
  - lib/rest_client_wrapper.rb
416
+ - lib/serializer.rb
398
417
  - lib/spork.rb
399
418
  - lib/task.rb
400
419
  - lib/templates/config.yaml
401
420
  - lib/validation.rb
402
421
  has_rdoc: true
403
- homepage: http://github.com/helma/opentox-ruby-api-wrapper
422
+ homepage: http://github.com/helma/opentox-ruby
404
423
  licenses: []
405
424
 
406
425
  post_install_message: