opentox-ruby 0.0.2 → 1.0.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.
data/lib/compound.rb CHANGED
@@ -68,6 +68,12 @@ module OpenTox
68
68
  c
69
69
  end
70
70
 
71
+ # Get InChI
72
+ # @return [String] InChI string
73
+ def to_inchi
74
+ @inchi
75
+ end
76
+
71
77
  # Get (canonical) smiles
72
78
  # @return [String] Smiles string
73
79
  def to_smiles
@@ -12,6 +12,7 @@ $stdout.sync = true
12
12
  $stderr.sync = true
13
13
  set :logging, false
14
14
  set :raise_errors, true
15
+ set :lock, true
15
16
 
16
17
  ['public','tmp'].each do |dir|
17
18
  FileUtils.mkdir_p dir unless File.exists?(dir)
data/lib/dataset.rb CHANGED
@@ -14,7 +14,7 @@ module OpenTox
14
14
  # dataset = OpenTox::Dataset.new("http:://webservices.in-silico/ch/dataset/1")
15
15
  # @param [optional, String] uri Dataset URI
16
16
  # @return [OpenTox::Dataset] Dataset object
17
- def initialize(uri=nil)
17
+ def initialize(uri=nil,subjectid=nil)
18
18
  super uri
19
19
  @features = {}
20
20
  @compounds = []
@@ -26,9 +26,9 @@ module OpenTox
26
26
  # dataset = OpenTox::Dataset.create
27
27
  # @param [optional, String] uri Dataset URI
28
28
  # @return [OpenTox::Dataset] Dataset object
29
- def self.create(uri=CONFIG[:services]["opentox-dataset"])
30
- dataset = Dataset.new
31
- dataset.save
29
+ def self.create(uri=CONFIG[:services]["opentox-dataset"], subjectid=nil)
30
+ dataset = Dataset.new(nil,subjectid)
31
+ dataset.save(subjectid)
32
32
  dataset
33
33
  end
34
34
 
@@ -38,29 +38,43 @@ module OpenTox
38
38
  # - you will have to set remaining metadata manually
39
39
  # @param [String] file CSV file path
40
40
  # @return [OpenTox::Dataset] Dataset object with CSV data
41
- def self.create_from_csv_file(file)
42
- dataset = Dataset.create
41
+ def self.create_from_csv_file(file, subjectid=nil)
42
+ dataset = Dataset.create(CONFIG[:services]["opentox-dataset"], subjectid)
43
43
  parser = Parser::Spreadsheets.new
44
44
  parser.dataset = dataset
45
45
  parser.load_csv(File.open(file).read)
46
- dataset.save
46
+ dataset.save(subjectid)
47
47
  dataset
48
48
  end
49
-
49
+
50
50
  # Find a dataset and load all data. This can be time consuming, use Dataset.new together with one of the load_* methods for a fine grained control over data loading.
51
51
  # @param [String] uri Dataset URI
52
52
  # @return [OpenTox::Dataset] Dataset object with all data
53
- def self.find(uri)
54
- dataset = Dataset.new(uri)
55
- dataset.load_all
53
+ def self.find(uri, subjectid=nil)
54
+ return nil unless uri
55
+ dataset = Dataset.new(uri, subjectid)
56
+ dataset.load_all(subjectid)
56
57
  dataset
57
58
  end
59
+
60
+ # replaces find as exist check, takes not as long, does NOT raise an un-authorized exception
61
+ # @param [String] uri Dataset URI
62
+ # @return [Boolean] true if dataset exists and user has get rights, false else
63
+ def self.exist?(uri, subjectid=nil)
64
+ return false unless uri
65
+ dataset = Dataset.new(uri, subjectid)
66
+ begin
67
+ dataset.load_metadata( subjectid ).size > 0
68
+ rescue
69
+ false
70
+ end
71
+ end
58
72
 
59
73
  # Get all datasets from a service
60
74
  # @param [optional,String] uri URI of the dataset service, defaults to service specified in configuration
61
75
  # @return [Array] Array of dataset object without data (use one of the load_* methods to pull data from the server)
62
- def self.all(uri=CONFIG[:services]["opentox-dataset"])
63
- RestClientWrapper.get(uri,:accept => "text/uri-list").to_s.each_line.collect{|u| Dataset.new(u)}
76
+ def self.all(uri=CONFIG[:services]["opentox-dataset"], subjectid=nil)
77
+ RestClientWrapper.get(uri,{:accept => "text/uri-list",:subjectid => subjectid}).to_s.each_line.collect{|u| Dataset.new(u, subjectid)}
64
78
  end
65
79
 
66
80
  # Load YAML representation into the dataset
@@ -71,16 +85,21 @@ module OpenTox
71
85
  end
72
86
 
73
87
  def load_rdfxml(rdfxml)
74
- load_rdfxml_file Tempfile.open("ot-rdfxml"){|f| f.write(rdfxml)}.path
88
+ raise "rdfxml data is empty" if rdfxml.to_s.size==0
89
+ file = Tempfile.new("ot-rdfxml")
90
+ file.puts rdfxml
91
+ file.close
92
+ load_rdfxml_file file
93
+ file.delete
75
94
  end
76
95
 
77
96
  # Load RDF/XML representation from a file
78
97
  # @param [String] file File with RDF/XML representation of the dataset
79
98
  # @return [OpenTox::Dataset] Dataset object with RDF/XML data
80
- def load_rdfxml_file(file)
81
- parser = Parser::Owl::Dataset.new @uri
99
+ def load_rdfxml_file(file, subjectid=nil)
100
+ parser = Parser::Owl::Dataset.new @uri, subjectid
82
101
  parser.uri = file.path
83
- copy parser.load_uri
102
+ copy parser.load_uri(subjectid)
84
103
  end
85
104
 
86
105
  # Load CSV string (format specification: http://toxcreate.org/help)
@@ -89,8 +108,8 @@ module OpenTox
89
108
  # - you will have to set remaining metadata manually
90
109
  # @param [String] csv CSV representation of the dataset
91
110
  # @return [OpenTox::Dataset] Dataset object with CSV data
92
- def load_csv(csv)
93
- save unless @uri # get a uri for creating features
111
+ def load_csv(csv, subjectid=nil)
112
+ save(subjectid) unless @uri # get a uri for creating features
94
113
  parser = Parser::Spreadsheets.new
95
114
  parser.dataset = self
96
115
  parser.load_csv(csv)
@@ -102,8 +121,8 @@ module OpenTox
102
121
  # - you will have to set remaining metadata manually
103
122
  # @param [Excel] book Excel workbook object (created with roo gem)
104
123
  # @return [OpenTox::Dataset] Dataset object with Excel data
105
- def load_spreadsheet(book)
106
- save unless @uri # get a uri for creating features
124
+ def load_spreadsheet(book, subjectid=nil)
125
+ save(subjectid) unless @uri # get a uri for creating features
107
126
  parser = Parser::Spreadsheets.new
108
127
  parser.dataset = self
109
128
  parser.load_spreadsheet(book)
@@ -111,26 +130,26 @@ module OpenTox
111
130
 
112
131
  # Load and return only metadata of a Dataset object
113
132
  # @return [Hash] Metadata of the dataset
114
- def load_metadata
115
- add_metadata Parser::Owl::Dataset.new(@uri).load_metadata
133
+ def load_metadata(subjectid=nil)
134
+ add_metadata Parser::Owl::Dataset.new(@uri, subjectid).load_metadata(subjectid)
116
135
  self.uri = @uri if @uri # keep uri
117
136
  @metadata
118
137
  end
119
138
 
120
139
  # Load all data (metadata, data_entries, compounds and features) from URI
121
- def load_all
140
+ def load_all(subjectid=nil)
122
141
  if (CONFIG[:yaml_hosts].include?(URI.parse(@uri).host))
123
- copy YAML.load(RestClientWrapper.get(@uri, :accept => "application/x-yaml"))
142
+ copy YAML.load(RestClientWrapper.get(@uri, {:accept => "application/x-yaml", :subjectid => subjectid}))
124
143
  else
125
- parser = Parser::Owl::Dataset.new(@uri)
126
- copy parser.load_uri
144
+ parser = Parser::Owl::Dataset.new(@uri, subjectid)
145
+ copy parser.load_uri(subjectid)
127
146
  end
128
147
  end
129
148
 
130
149
  # Load and return only compound URIs from the dataset service
131
150
  # @return [Array] Compound URIs in the dataset
132
- def load_compounds
133
- RestClientWrapper.get(File.join(uri,"compounds"),:accept=> "text/uri-list").to_s.each_line do |compound_uri|
151
+ def load_compounds(subjectid=nil)
152
+ RestClientWrapper.get(File.join(uri,"compounds"),{:accept=> "text/uri-list", :subjectid => subjectid}).to_s.each_line do |compound_uri|
134
153
  @compounds << compound_uri.chomp
135
154
  end
136
155
  @compounds.uniq!
@@ -138,9 +157,9 @@ module OpenTox
138
157
 
139
158
  # Load and return only features from the dataset service
140
159
  # @return [Hash] Features of the dataset
141
- def load_features
142
- parser = Parser::Owl::Dataset.new(@uri)
143
- @features = parser.load_features
160
+ def load_features(subjectid=nil)
161
+ parser = Parser::Owl::Dataset.new(@uri, subjectid)
162
+ @features = parser.load_features(subjectid)
144
163
  @features
145
164
  end
146
165
 
@@ -218,7 +237,7 @@ module OpenTox
218
237
  @features[feature] = {} unless @features[feature]
219
238
  @data_entries[compound] = {} unless @data_entries[compound]
220
239
  @data_entries[compound][feature] = [] unless @data_entries[compound][feature]
221
- @data_entries[compound][feature] << value
240
+ @data_entries[compound][feature] << value if value!=nil
222
241
  end
223
242
 
224
243
  # Add/modify metadata, existing entries will be overwritten
@@ -242,34 +261,70 @@ module OpenTox
242
261
  def add_feature_metadata(feature,metadata)
243
262
  metadata.each { |k,v| @features[feature][k] = v }
244
263
  end
264
+
265
+ # Add a new compound
266
+ # @param [String] compound Compound URI
267
+ def add_compound (compound)
268
+ @compounds << compound unless @compounds.include? compound
269
+ end
270
+
271
+ # Creates a new dataset, by splitting the current dataset, i.e. using only a subset of compounds and features
272
+ # @param [Array] compounds List of compound URIs
273
+ # @param [Array] features List of feature URIs
274
+ # @param [Hash] metadata Hash containing the metadata for the new dataset
275
+ # @param [String] subjectid
276
+ # @return [OpenTox::Dataset] newly created dataset, already saved
277
+ def split( compounds, features, metadata, subjectid=nil)
278
+ LOGGER.debug "split dataset using "+compounds.size.to_s+"/"+@compounds.size.to_s+" compounds"
279
+ raise "no new compounds selected" unless compounds and compounds.size>0
280
+ dataset = OpenTox::Dataset.create(CONFIG[:services]["opentox-dataset"],subjectid)
281
+ if features.size==0
282
+ compounds.each{ |c| dataset.add_compound(c) }
283
+ else
284
+ compounds.each do |c|
285
+ features.each do |f|
286
+ unless @data_entries[c][f]
287
+ dataset.add(c,f,nil)
288
+ else
289
+ @data_entries[c][f].each do |v|
290
+ dataset.add(c,f,v)
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end
296
+ dataset.add_metadata(metadata)
297
+ dataset.save(subjectid)
298
+ dataset
299
+ end
245
300
 
246
301
  # Save dataset at the dataset service
247
302
  # - creates a new dataset if uri is not set
248
303
  # - overwrites dataset if uri exists
249
304
  # @return [String] Dataset URI
250
- def save
305
+ def save(subjectid=nil)
251
306
  # TODO: rewrite feature URI's ??
252
307
  @compounds.uniq!
253
308
  if @uri
254
309
  if (CONFIG[:yaml_hosts].include?(URI.parse(@uri).host))
255
- RestClientWrapper.post(@uri,{:content_type => "application/x-yaml"},self.to_yaml)
310
+ RestClientWrapper.post(@uri,self.to_yaml,{:content_type => "application/x-yaml", :subjectid => subjectid})
256
311
  else
257
312
  File.open("ot-post-file.rdf","w+") { |f| f.write(self.to_rdfxml); @path = f.path }
258
- task_uri = RestClient.post(@uri, {:file => File.new(@path)},{:accept => "text/uri-list"}).to_s.chomp
313
+ task_uri = RestClient.post(@uri, {:file => File.new(@path)},{:accept => "text/uri-list" , :subjectid => subjectid}).to_s.chomp
259
314
  #task_uri = `curl -X POST -H "Accept:text/uri-list" -F "file=@#{@path};type=application/rdf+xml" http://apps.ideaconsult.net:8080/ambit2/dataset`
260
315
  Task.find(task_uri).wait_for_completion
261
- self.uri = RestClientWrapper.get(task_uri,:accept => 'text/uri-list')
316
+ self.uri = RestClientWrapper.get(task_uri,{:accept => 'text/uri-list', :subjectid => subjectid})
262
317
  end
263
318
  else
264
319
  # create dataset if uri is empty
265
- self.uri = RestClientWrapper.post(CONFIG[:services]["opentox-dataset"],{}).to_s.chomp
320
+ self.uri = RestClientWrapper.post(CONFIG[:services]["opentox-dataset"],{:subjectid => subjectid}).to_s.chomp
266
321
  end
267
322
  @uri
268
323
  end
269
324
 
270
325
  # Delete dataset at the dataset service
271
- def delete
272
- RestClientWrapper.delete @uri
326
+ def delete(subjectid=nil)
327
+ RestClientWrapper.delete(@uri, :subjectid => subjectid)
273
328
  end
274
329
 
275
330
  private
@@ -293,9 +348,9 @@ module OpenTox
293
348
  # Find a prediction dataset and load all data.
294
349
  # @param [String] uri Prediction dataset URI
295
350
  # @return [OpenTox::Dataset] Prediction dataset object with all data
296
- def self.find(uri)
297
- prediction = LazarPrediction.new(uri)
298
- prediction.load_all
351
+ def self.find(uri, subjectid=nil)
352
+ prediction = LazarPrediction.new(uri, subjectid)
353
+ prediction.load_all(subjectid)
299
354
  prediction
300
355
  end
301
356
 
data/lib/environment.rb CHANGED
@@ -23,22 +23,8 @@ else
23
23
  end
24
24
 
25
25
  # database
26
- if CONFIG[:database]
27
- ['dm-core', 'dm-serializer', 'dm-timestamps', 'dm-types', 'dm-migrations', 'dm-validations' ].each{|lib| require lib }
28
- case CONFIG[:database][:adapter]
29
- when /sqlite/i
30
- db_dir = File.join(basedir, "db")
31
- FileUtils.mkdir_p db_dir
32
- DataMapper::setup(:default, "sqlite3://#{db_dir}/opentox.sqlite3")
33
- else
34
- DataMapper.setup(:default, {
35
- :adapter => CONFIG[:database][:adapter],
36
- :database => CONFIG[:database][:database],
37
- :username => CONFIG[:database][:username],
38
- :password => CONFIG[:database][:password],
39
- :host => CONFIG[:database][:host]})
40
- end
41
- end
26
+ `redis-server /opt/redis/redis.conf` unless File.exists? "/var/run/redis.pid"
27
+ Ohm.connect :thread_safe => true
42
28
 
43
29
  # load mail settings for error messages
44
30
  load File.join config_dir,"mail.rb" if File.exists?(File.join config_dir,"mail.rb")
@@ -54,8 +40,8 @@ else
54
40
  end
55
41
 
56
42
  # Regular expressions for parsing classification data
57
- TRUE_REGEXP = /^(true|active|1|1.0)$/i
58
- FALSE_REGEXP = /^(false|inactive|0|0.0)$/i
43
+ TRUE_REGEXP = /^(true|active|1|1.0|tox)$/i
44
+ FALSE_REGEXP = /^(false|inactive|0|0.0|low tox)$/i
59
45
 
60
46
  # Task durations
61
47
  DEFAULT_TASK_MAX_DURATION = 36000
@@ -83,6 +69,11 @@ class OwlNamespace
83
69
 
84
70
  end
85
71
 
72
+ AA_SERVER = CONFIG[:authorization] ? (CONFIG[:authorization][:server] ? CONFIG[:authorization][:server] : nil) : nil
73
+ CONFIG[:authorization][:authenticate_request] = [""] unless CONFIG[:authorization][:authenticate_request]
74
+ CONFIG[:authorization][:authorize_request] = [""] unless CONFIG[:authorization][:authorize_request]
75
+ CONFIG[:authorization][:free_request] = [""] unless CONFIG[:authorization][:free_request]
76
+
86
77
  RDF = OwlNamespace.new 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
87
78
  OWL = OwlNamespace.new 'http://www.w3.org/2002/07/owl#'
88
79
  DC = OwlNamespace.new 'http://purl.org/dc/elements/1.1/'
data/lib/error.rb ADDED
@@ -0,0 +1,99 @@
1
+
2
+ # adding additional fields to Exception class to format errors according to OT-API
3
+ class Exception
4
+ attr_accessor :errorCause
5
+ def http_code; 500; end
6
+ end
7
+
8
+ module OpenTox
9
+
10
+ class BadRequestError < RuntimeError
11
+ def http_code; 400; end
12
+ end
13
+
14
+ class NotAuthorizedError < RuntimeError
15
+ def http_code; 401; end
16
+ end
17
+
18
+ class NotFoundError < RuntimeError
19
+ def http_code; 404; end
20
+ end
21
+
22
+ class ServiceUnavailableError < RuntimeError
23
+ def http_code; 503; end
24
+ end
25
+
26
+ class RestCallError < RuntimeError
27
+ attr_accessor :rest_params
28
+ def http_code; 502; end
29
+ end
30
+
31
+ class ErrorReport
32
+
33
+ # TODO replace params with URIs (errorCause -> OT.errorCause)
34
+ attr_reader :message, :actor, :errorCause, :http_code, :errorDetails, :errorType
35
+
36
+ private
37
+ def initialize( http_code, erroType, message, actor, errorCause, rest_params=nil, backtrace=nil )
38
+ @http_code = http_code
39
+ @errorType = erroType
40
+ @message = message
41
+ @actor = actor
42
+ @errorCause = errorCause
43
+ @rest_params = rest_params
44
+ @backtrace = backtrace
45
+ end
46
+
47
+ public
48
+ # creates a error report object, from an ruby-exception object
49
+ # @param [Exception] error
50
+ # @param [String] actor, URI of the call that cause the error
51
+ def self.create( error, actor )
52
+ rest_params = error.rest_params if error.is_a?(OpenTox::RestCallError) and error.rest_params
53
+ backtrace = error.backtrace.short_backtrace if CONFIG[:backtrace]
54
+ ErrorReport.new( error.http_code, error.class.to_s, error.message, actor, error.errorCause, rest_params, backtrace )
55
+ end
56
+
57
+ def self.from_rdf(rdf)
58
+ metadata = OpenTox::Parser::Owl.from_rdf( rdf, OT.ErrorReport ).metadata
59
+ ErrorReport.new(metadata[OT.statusCode], metadata[OT.errorCode], metadata[OT.message], metadata[OT.actor], metadata[OT.errorCause])
60
+ end
61
+
62
+ # overwrite sorting to make easier readable
63
+ def to_yaml_properties
64
+ p = super
65
+ p = ( p - ["@backtrace"]) + ["@backtrace"] if @backtrace
66
+ p = ( p - ["@errorCause"]) + ["@errorCause"] if @errorCause
67
+ p
68
+ end
69
+
70
+ def rdf_content()
71
+ c = {
72
+ RDF.type => OT.ErrorReport,
73
+ OT.statusCode => @http_code,
74
+ OT.message => @message,
75
+ OT.actor => @actor,
76
+ OT.errorCode => @errorType,
77
+ }
78
+ c[OT.errorCause] = @errorCause.rdf_content if @errorCause
79
+ c
80
+ end
81
+
82
+ def to_rdfxml
83
+ s = Serializer::Owl.new
84
+ s.add_resource(CONFIG[:services]["opentox-task"]+"/tmpId/ErrorReport/tmpId", OT.errorReport, rdf_content)
85
+ s.to_rdfxml
86
+ end
87
+ end
88
+ end
89
+
90
+ class Array
91
+ def short_backtrace
92
+ short = []
93
+ each do |c|
94
+ break if c =~ /sinatra\/base/
95
+ short << c
96
+ end
97
+ short.join("\n")
98
+ end
99
+ end
data/lib/feature.rb CHANGED
@@ -2,14 +2,42 @@ module OpenTox
2
2
  class Feature
3
3
  include OpenTox
4
4
 
5
- def self.find(uri)
5
+ def self.find(uri, subjectid=nil)
6
+ return nil unless uri
6
7
  feature = Feature.new uri
7
8
  if (CONFIG[:yaml_hosts].include?(URI.parse(uri).host))
8
- feature.add_metadata YAML.load(RestClientWrapper.get(uri,:accept => "application/x-yaml"))
9
+ feature.add_metadata YAML.load(RestClientWrapper.get(uri,{:accept => "application/x-yaml", :subjectid => subjectid}))
9
10
  else
10
11
  feature.add_metadata Parser::Owl::Dataset.new(uri).load_metadata
11
12
  end
12
13
  feature
13
14
  end
15
+
16
+ # provides domain (possible target values) of classification feature
17
+ # @return [Array] list with possible target values
18
+ def domain
19
+ if metadata[OT.acceptValue]
20
+ raise "accept value found, remove hack and implement correctly"
21
+ else
22
+ if @uri=~/feature\/26221/ || @uri=~/feature\/221726/
23
+ return ["mutagen" , "nonmutagen"]
24
+ end
25
+ return [true, false]
26
+ end
27
+ end
28
+
29
+ # provides feature type, possible types are "regression" or "classification"
30
+ # @return [String] feature type, unknown if OT.isA property is unknown/ not set
31
+ def feature_type
32
+ case metadata[OT.isA]
33
+ when /NominalFeature/
34
+ "classification"
35
+ when /NumericFeature/
36
+ "regression"
37
+ else
38
+ "unknown"
39
+ end
40
+ end
41
+
14
42
  end
15
43
  end