opentox-ruby 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/authorization.rb CHANGED
@@ -37,13 +37,15 @@ module OpenTox
37
37
 
38
38
  #Loads and sends Policyfile(XML) to open-sso server
39
39
  # @param [String] URI to create a policy for
40
- def send(uri)
40
+ def send(uri)
41
41
  xml = get_xml(uri)
42
42
  ret = false
43
- ret = Authorization.create_policy(xml, @subjectid)
43
+ ret = Authorization.create_policy(xml, @subjectid)
44
+ LOGGER.warn "Create policy on openSSO failed for URI: #{uri} subjectid: #{@subjectid}. Will try again." if !ret
45
+ ret = Authorization.create_policy(xml, @subjectid) if !ret
44
46
  LOGGER.debug "Policy send with subjectid: #{@subjectid}"
45
47
  LOGGER.warn "Not created Policy is: #{xml}" if !ret
46
- ret
48
+ ret
47
49
  end
48
50
 
49
51
  end
@@ -337,7 +339,7 @@ module OpenTox
337
339
  # @param [String] subjectid
338
340
  # @return [Boolean] true if access granted, else otherwise
339
341
  def self.authorized?(uri, request_method, subjectid)
340
- if CONFIG[:authorization][:free_request].include?(request_method)
342
+ if CONFIG[:authorization][:free_request].include?(request_method)
341
343
  #LOGGER.debug "authorized? >>true<< (request is free), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
342
344
  true
343
345
  elsif OpenTox::Authorization.free_uri?(uri, request_method)
@@ -360,7 +362,7 @@ module OpenTox
360
362
  false
361
363
  end
362
364
  end
363
-
365
+
364
366
  private
365
367
  def self.free_uri?(uri, request_method)
366
368
  if CONFIG[:authorization][:free_uris]
@@ -374,7 +376,7 @@ module OpenTox
374
376
  end
375
377
  return false
376
378
  end
377
-
379
+
378
380
  def self.authorize_exception?(uri, request_method)
379
381
  if CONFIG[:authorization][:authorize_exceptions]
380
382
  CONFIG[:authorization][:authorize_exceptions].each do |request_methods,uris|
@@ -387,6 +389,6 @@ module OpenTox
387
389
  end
388
390
  return false
389
391
  end
390
-
392
+
391
393
  end
392
- end
394
+ end
data/lib/compound.rb CHANGED
@@ -6,13 +6,15 @@ module OpenTox
6
6
  # Ruby wrapper for OpenTox Compound Webservices (http://opentox.org/dev/apis/api-1.2/structure).
7
7
  class Compound
8
8
 
9
+ include OpenTox
10
+
9
11
  attr_accessor :inchi, :uri
10
12
 
11
13
  # Create compound with optional uri
12
14
  # @example
13
- # compound = OpenTox::Compound.new("http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H"")
15
+ # compound = Compound.new("http://webservices.in-silico.ch/compound/InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H"")
14
16
  # @param [optional, String] uri Compound URI
15
- # @return [OpenTox::Compound] Compound
17
+ # @return [Compound] Compound
16
18
  def initialize(uri=nil)
17
19
  @uri = uri
18
20
  case @uri
@@ -36,9 +38,9 @@ module OpenTox
36
38
 
37
39
  # Create a compound from smiles string
38
40
  # @example
39
- # compound = OpenTox::Compound.from_smiles("c1ccccc1")
41
+ # compound = Compound.from_smiles("c1ccccc1")
40
42
  # @param [String] smiles Smiles string
41
- # @return [OpenTox::Compound] Compound
43
+ # @return [Compound] Compound
42
44
  def self.from_smiles(smiles)
43
45
  c = Compound.new
44
46
  c.inchi = Compound.smiles2inchi(smiles)
@@ -48,7 +50,7 @@ module OpenTox
48
50
 
49
51
  # Create a compound from inchi string
50
52
  # @param [String] smiles InChI string
51
- # @return [OpenTox::Compound] Compound
53
+ # @return [Compound] Compound
52
54
  def self.from_inchi(inchi)
53
55
  c = Compound.new
54
56
  c.inchi = inchi
@@ -58,7 +60,7 @@ module OpenTox
58
60
 
59
61
  # Create a compound from sdf string
60
62
  # @param [String] smiles SDF string
61
- # @return [OpenTox::Compound] Compound
63
+ # @return [Compound] Compound
62
64
  def self.from_sdf(sdf)
63
65
  c = Compound.new
64
66
  c.inchi = Compound.sdf2inchi(sdf)
@@ -68,9 +70,9 @@ module OpenTox
68
70
 
69
71
  # Create a compound from name. Relies on an external service for name lookups.
70
72
  # @example
71
- # compound = OpenTox::Compound.from_name("Benzene")
73
+ # compound = Compound.from_name("Benzene")
72
74
  # @param [String] name name can be also an InChI/InChiKey, CAS number, etc
73
- # @return [OpenTox::Compound] Compound
75
+ # @return [Compound] Compound
74
76
  def self.from_name(name)
75
77
  c = Compound.new
76
78
  # paranoid URI encoding to keep SMILES charges and brackets
@@ -131,7 +133,7 @@ module OpenTox
131
133
 
132
134
  # Match a smarts string
133
135
  # @example
134
- # compound = OpenTox::Compound.from_name("Benzene")
136
+ # compound = Compound.from_name("Benzene")
135
137
  # compound.match?("cN") # returns false
136
138
  # @param [String] smarts Smarts string
137
139
  def match?(smarts)
@@ -146,7 +148,7 @@ module OpenTox
146
148
 
147
149
  # Match an array of smarts strings, returns array with matching smarts
148
150
  # @example
149
- # compound = OpenTox::Compound.from_name("Benzene")
151
+ # compound = Compound.from_name("Benzene")
150
152
  # compound.match(['cc','cN']) # returns ['cc']
151
153
  # @param [Array] smarts_array Array with Smarts strings
152
154
  # @return [Array] Array with matching Smarts strings
@@ -166,7 +168,7 @@ module OpenTox
166
168
 
167
169
  # Match_hits an array of smarts strings, returns hash with matching smarts as key and number of non-unique hits as value
168
170
  # @example
169
- # compound = OpenTox::Compound.from_name("Benzene")
171
+ # compound = Compound.from_name("Benzene")
170
172
  # compound.match(['cc','cN']) # returns ['cc']
171
173
  # @param [Array] smarts_array Array with Smarts strings
172
174
  # @return [Hash] Hash with matching smarts as key and number of non-unique hits as value
@@ -191,6 +193,40 @@ module OpenTox
191
193
  return smarts_hits
192
194
  #smarts_array.collect { |s| s if match?(s)}.compact
193
195
  end
196
+
197
+ # Lookup numerical values, returns hash with feature name as key and value as value
198
+ # @param [Array] Array of feature names
199
+ # @param [String] Feature dataset uri
200
+ # @return [Hash] Hash with feature name as key and value as value
201
+ def lookup(feature_array,feature_dataset_uri,pc_type,subjectid=nil)
202
+ ds = OpenTox::Dataset.find(feature_dataset_uri,subjectid)
203
+ #entry = ds.data_entries[self.uri]
204
+ entry = nil
205
+ ds.data_entries.each { |c_uri, values|
206
+ if c_uri.split('/compound/').last == self.to_inchi
207
+ entry = ds.data_entries[self.uri]
208
+ break
209
+ end
210
+ }
211
+ LOGGER.debug "#{entry.size} entries in feature ds for query." unless entry.nil?
212
+
213
+ if entry.nil?
214
+ uri, smiles_to_inchi = OpenTox::Algorithm.get_pc_descriptors({:compounds => [self.uri], :pc_type => pc_type})
215
+ uri = OpenTox::Algorithm.load_ds_csv(uri, smiles_to_inchi, subjectid)
216
+ ds = OpenTox::Dataset.find(uri,subjectid)
217
+ entry = ds.data_entries[self.uri]
218
+ ds.delete(subjectid)
219
+ end
220
+ features = entry.keys
221
+ features.each { |feature|
222
+ new_feature = File.join(feature_dataset_uri, "feature", feature.split("/").last)
223
+ entry[new_feature] = entry[feature].flatten.first.to_f # see algorithm/lazar.rb:182, to_f because feature type detection doesn't work w 1 entry
224
+ entry.delete(feature) unless feature == new_feature # e.g. when loading from ambit
225
+ }
226
+ #res = feature_array.collect {|v| entry[v]}
227
+ #LOGGER.debug "----- am #{entry.to_yaml}"
228
+ entry
229
+ end
194
230
 
195
231
 
196
232
  # Get URI of compound image with highlighted fragments
data/lib/dataset.rb CHANGED
@@ -288,7 +288,7 @@ module OpenTox
288
288
 
289
289
  # Insert a statement (compound_uri,feature_uri,value)
290
290
  # @example Insert a statement (compound_uri,feature_uri,value)
291
- # dataset.add "http://webservices.in-silico.ch/compound/InChI=1S/C6Cl6/c7-1-2(8)4(10)6(12)5(11)3(1)9", "http://webservices.in-silico.ch/dataset/1/feature/hamster_carcinogenicity", true
291
+ # dataset.add "http://webservices.in-silico.ch/compound/InChI=1S/C6Cl6/c7-1-2(8)4(10)6(12)5(11)3(1)9", "http://webservices.in-silico.ch/dataset/1/feature/hamster_carcinogenicity", 1
292
292
  # @param [String] compound Compound URI
293
293
  # @param [String] feature Compound URI
294
294
  # @param [Boolean,Float] value Feature value
@@ -315,6 +315,16 @@ module OpenTox
315
315
  @features[feature] = metadata
316
316
  end
317
317
 
318
+ # Complete feature values by adding zeroes
319
+ def complete_data_entries
320
+ all_features = @features.keys
321
+ @data_entries.each { |c, e|
322
+ (Set.new(all_features.collect)).subtract(Set.new e.keys).to_a.each { |f|
323
+ self.add(c,f,0)
324
+ }
325
+ }
326
+ end
327
+
318
328
  # Add/modify metadata for a feature
319
329
  # @param [String] feature Feature URI
320
330
  # @param [Hash] metadata Hash with feature metadata
@@ -363,7 +373,45 @@ module OpenTox
363
373
  dataset.save(subjectid)
364
374
  dataset
365
375
  end
366
-
376
+
377
+ # merges two dataset into a new dataset (by default uses all compounds and features)
378
+ # precondition: both datasets are fully loaded
379
+ # @param [OpenTox::Dataset] dataset1 to merge
380
+ # @param [OpenTox::Dataset] dataset2 to merge
381
+ # @param [Hash] metadata
382
+ # @param [optional,String] subjectid
383
+ # @param [optional,Array] features1, if specified only this features of dataset1 are used
384
+ # @param [optional,Array] features2, if specified only this features of dataset2 are used
385
+ # @param [optional,Array] compounds1, if specified only this compounds of dataset1 are used
386
+ # @param [optional,Array] compounds2, if specified only this compounds of dataset2 are used
387
+ # example: if you want no features from dataset2, give empty array as features2
388
+ def self.merge( dataset1, dataset2, metadata, subjectid=nil, features1=nil, features2=nil, compounds1=nil, compounds2=nil )
389
+ features1 = dataset1.features.keys unless features1
390
+ features2 = dataset2.features.keys unless features2
391
+ compounds1 = dataset1.compounds unless compounds1
392
+ compounds2 = dataset2.compounds unless compounds2
393
+ data_combined = OpenTox::Dataset.create(CONFIG[:services]["opentox-dataset"],subjectid)
394
+ LOGGER.debug("merging datasets #{dataset1.uri} and #{dataset2.uri} to #{data_combined.uri}")
395
+ [[dataset1, features1, compounds1], [dataset2, features2, compounds2]].each do |dataset,features,compounds|
396
+ compounds.each{|c| data_combined.add_compound(c)}
397
+ features.each do |f|
398
+ m = dataset.features[f]
399
+ m[OT.hasSource] = dataset.uri unless m[OT.hasSource]
400
+ data_combined.add_feature(f,m)
401
+ compounds.each do |c|
402
+ dataset.data_entries[c][f].each do |v|
403
+ data_combined.add(c,f,v)
404
+ end if dataset.data_entries[c] and dataset.data_entries[c][f]
405
+ end
406
+ end
407
+ end
408
+ metadata = {} unless metadata
409
+ metadata[OT.hasSource] = "Merge from #{dataset1.uri} and #{dataset2.uri}" unless metadata[OT.hasSource]
410
+ data_combined.add_metadata(metadata)
411
+ data_combined.save(subjectid)
412
+ data_combined
413
+ end
414
+
367
415
  # Save dataset at the dataset service
368
416
  # - creates a new dataset if uri is not set
369
417
  # - overwrites dataset if uri exists
data/lib/environment.rb CHANGED
@@ -24,7 +24,11 @@ end
24
24
 
25
25
  # database
26
26
  #`redis-server /opt/redis/redis.conf` unless File.exists? "/var/run/redis.pid" # removed by AM
27
- Ohm.connect :thread_safe => true
27
+ ohm_port=6379
28
+ if !CONFIG[:ohm_port].nil?
29
+ ohm_port=CONFIG[:ohm_port].to_i
30
+ end
31
+ Ohm.connect(:thread_safe => true, :port => ohm_port)
28
32
 
29
33
  # load mail settings for error messages
30
34
  #load File.join config_dir,"mail.rb" if File.exists?(File.join config_dir,"mail.rb")
@@ -87,4 +91,5 @@ DC = OwlNamespace.new 'http://purl.org/dc/elements/1.1/'
87
91
  OT = OwlNamespace.new 'http://www.opentox.org/api/1.1#'
88
92
  OTA = OwlNamespace.new 'http://www.opentox.org/algorithmTypes.owl#'
89
93
  XSD = OwlNamespace.new 'http://www.w3.org/2001/XMLSchema#'
94
+ #BO = OwlNamespace.new 'http://www.blueobelisk.org/ontologies/chemoinformatics-algorithms/#'
90
95
 
data/lib/model.rb CHANGED
@@ -102,8 +102,8 @@ module OpenTox
102
102
  include Algorithm
103
103
  include Model
104
104
 
105
- attr_accessor :compound, :prediction_dataset, :features, :effects, :activities, :p_values, :fingerprints, :feature_calculation_algorithm, :similarity_algorithm, :prediction_algorithm, :min_sim, :subjectid, :prop_kernel, :value_map, :nr_hits, :transform, :conf_stdev, :prediction_min_max
106
105
 
106
+ attr_accessor :compound, :prediction_dataset, :features, :effects, :activities, :p_values, :fingerprints, :feature_calculation_algorithm, :similarity_algorithm, :prediction_algorithm, :subjectid, :value_map, :compound_fingerprints, :feature_calculation_algorithm, :neighbors
107
107
  def initialize(uri=nil)
108
108
 
109
109
  if uri
@@ -120,18 +120,11 @@ module OpenTox
120
120
  @p_values = {}
121
121
  @fingerprints = {}
122
122
  @value_map = {}
123
- @prediction_min_max = []
124
123
 
125
124
  @feature_calculation_algorithm = "Substructure.match"
126
125
  @similarity_algorithm = "Similarity.tanimoto"
127
126
  @prediction_algorithm = "Neighbors.weighted_majority_vote"
128
127
 
129
- @nr_hits = false
130
- @min_sim = 0.3
131
- @prop_kernel = false
132
- @transform = { "class" => "NOP" }
133
- @conf_stdev = false
134
-
135
128
  end
136
129
 
137
130
  # Get URIs of all lazar models
@@ -174,19 +167,14 @@ module OpenTox
174
167
  lazar.feature_calculation_algorithm = hash["feature_calculation_algorithm"] if hash["feature_calculation_algorithm"]
175
168
  lazar.similarity_algorithm = hash["similarity_algorithm"] if hash["similarity_algorithm"]
176
169
  lazar.prediction_algorithm = hash["prediction_algorithm"] if hash["prediction_algorithm"]
177
- lazar.min_sim = hash["min_sim"] if hash["min_sim"]
178
170
  lazar.subjectid = hash["subjectid"] if hash["subjectid"]
179
- lazar.prop_kernel = hash["prop_kernel"] if hash["prop_kernel"]
180
171
  lazar.value_map = hash["value_map"] if hash["value_map"]
181
- lazar.nr_hits = hash["nr_hits"] if hash["nr_hits"]
182
- lazar.transform = hash["transform"] if hash["transform"]
183
- lazar.conf_stdev = hash["conf_stdev"] if hash["conf_stdev"]
184
- lazar.prediction_min_max = hash["prediction_min_max"] if hash["prediction_min_max"]
172
+
185
173
  lazar
186
174
  end
187
175
 
188
176
  def to_json
189
- Yajl::Encoder.encode({:uri => @uri,:metadata => @metadata, :compound => @compound, :prediction_dataset => @prediction_dataset, :features => @features, :effects => @effects, :activities => @activities, :p_values => @p_values, :fingerprints => @fingerprints, :feature_calculation_algorithm => @feature_calculation_algorithm, :similarity_algorithm => @similarity_algorithm, :prediction_algorithm => @prediction_algorithm, :min_sim => @min_sim, :subjectid => @subjectid, :prop_kernel => @prop_kernel, :value_map => @value_map, :nr_hits => @nr_hits, :transform => @transform, :conf_stdev => @conf_stdev, :prediction_min_max => @prediction_min_max})
177
+ Yajl::Encoder.encode({:uri => @uri,:metadata => @metadata, :compound => @compound, :prediction_dataset => @prediction_dataset, :features => @features, :effects => @effects, :activities => @activities, :p_values => @p_values, :fingerprints => @fingerprints, :feature_calculation_algorithm => @feature_calculation_algorithm, :similarity_algorithm => @similarity_algorithm, :prediction_algorithm => @prediction_algorithm, :subjectid => @subjectid, :value_map => @value_map})
190
178
  end
191
179
 
192
180
  def run( params, accept_header=nil, waiting_task=nil )
@@ -230,8 +218,11 @@ module OpenTox
230
218
  predict(compound_uri,false,subjectid)
231
219
  count += 1
232
220
  waiting_task.progress( count/d.compounds.size.to_f*100.0 ) if waiting_task
233
- rescue => ex
234
- LOGGER.warn "prediction for compound "+compound_uri.to_s+" failed: "+ex.message+" subjectid: #{subjectid}"
221
+ rescue => e
222
+ LOGGER.warn "prediction for compound "+compound_uri.to_s+" failed: "+e.message+" subjectid: #{subjectid}"
223
+ #LOGGER.debug "#{e.class}: #{e.message}"
224
+ #LOGGER.debug "Backtrace:\n\t#{e.backtrace.join("\n\t")}"
225
+
235
226
  end
236
227
  end
237
228
  #@prediction_dataset.save(subjectid)
@@ -246,7 +237,6 @@ module OpenTox
246
237
 
247
238
  @compound = Compound.new compound_uri
248
239
  features = {}
249
-
250
240
  #LOGGER.debug self.to_yaml
251
241
  unless @prediction_dataset
252
242
  @prediction_dataset = Dataset.create(CONFIG[:services]["opentox-dataset"], subjectid)
@@ -257,29 +247,42 @@ module OpenTox
257
247
  OT.parameters => [{DC.title => "compound_uri", OT.paramValue => compound_uri}]
258
248
  } )
259
249
  end
260
-
261
250
  if OpenTox::Feature.find(metadata[OT.dependentVariables], subjectid).feature_type == "regression"
262
251
  all_activities = []
263
252
  all_activities = @activities.values.flatten.collect! { |i| i.to_f }
264
- @prediction_min_max[0] = (all_activities.to_scale.min/2)
265
- @prediction_min_max[1] = (all_activities.to_scale.max*2)
266
253
  end
267
-
268
254
  unless database_activity(subjectid) # adds database activity to @prediction_dataset
255
+ # Calculation of needed values for query compound
256
+ @compound_features = eval("#{@feature_calculation_algorithm}({
257
+ :compound => @compound,
258
+ :features => @features,
259
+ :feature_dataset_uri => @metadata[OT.featureDataset],
260
+ :pc_type => self.parameter(\"pc_type\"),
261
+ :subjectid => subjectid
262
+ })")
263
+ # Adding fingerprint of query compound with features and values(p_value*nr_hits)
264
+ @compound_fingerprints = {}
265
+ @compound_features.each do |feature, value| # value is nil if "Substructure.match"
266
+ if @feature_calculation_algorithm == "Substructure.match_hits"
267
+ @compound_fingerprints[feature] = @p_values[feature] * value
268
+ elsif @feature_calculation_algorithm == "Substructure.match"
269
+ @compound_fingerprints[feature] = @p_values[feature]
270
+ elsif @feature_calculation_algorithm == "Substructure.lookup"
271
+ @compound_fingerprints[feature] = value
272
+ end
273
+ end
269
274
 
270
- neighbors
271
- prediction = eval("#{@prediction_algorithm} ( { :neighbors => @neighbors,
272
- :compound => @compound,
273
- :features => @features,
274
- :p_values => @p_values,
275
- :fingerprints => @fingerprints,
276
- :similarity_algorithm => @similarity_algorithm,
277
- :prop_kernel => @prop_kernel,
275
+ # Transform model data to machine learning scheme (tables of data)
276
+ mtf = OpenTox::Algorithm::Transform::ModelTransformer.new(self)
277
+ mtf.transform
278
+
279
+ # Make a prediction
280
+ prediction = eval("#{@prediction_algorithm}( { :props => mtf.props,
281
+ :acts => mtf.acts,
282
+ :sims => mtf.sims,
278
283
  :value_map => @value_map,
279
- :nr_hits => @nr_hits,
280
- :conf_stdev => @conf_stdev,
281
- :prediction_min_max => @prediction_min_max,
282
- :transform => @transform } ) ")
284
+ :min_train_performance => self.parameter(\"min_train_performance\")
285
+ } ) ")
283
286
 
284
287
  value_feature_uri = File.join( @uri, "predicted", "value")
285
288
  confidence_feature_uri = File.join( @uri, "predicted", "confidence")
@@ -355,44 +358,6 @@ module OpenTox
355
358
  @prediction_dataset
356
359
  end
357
360
 
358
-
359
-
360
- # Find neighbors and store them as object variable, access all compounds for that.
361
- def neighbors
362
- @compound_features = eval("#{@feature_calculation_algorithm}(@compound,@features)") if @feature_calculation_algorithm
363
- @neighbors = []
364
- @fingerprints.keys.each do |training_compound| # AM: access all compounds
365
- add_neighbor @fingerprints[training_compound].keys, training_compound
366
- end
367
- end
368
-
369
- # Adds a neighbor to @neighbors if it passes the similarity threshold.
370
- def add_neighbor(training_features, training_compound)
371
- compound_features_hits = {}
372
- training_compound_features_hits = {}
373
- if @nr_hits
374
- compound_features_hits = @compound.match_hits(@compound_features)
375
- training_compound_features_hits = @fingerprints[training_compound]
376
- #LOGGER.debug "dv ------------ training_compound_features_hits:#{training_compound_features_hits.class} #{training_compound_features_hits}"
377
- end
378
- params = {}
379
- params[:nr_hits] = @nr_hits
380
- params[:compound_features_hits] = compound_features_hits
381
- params[:training_compound_features_hits] = training_compound_features_hits
382
-
383
- sim = eval("#{@similarity_algorithm}(training_features, @compound_features, @p_values, params)")
384
- if sim > @min_sim
385
- @activities[training_compound].each do |act|
386
- @neighbors << {
387
- :compound => training_compound,
388
- :similarity => sim,
389
- :features => training_features,
390
- :activity => act
391
- }
392
- end
393
- end
394
- end
395
-
396
361
  # Find database activities and store them in @prediction_dataset
397
362
  # @return [Boolean] true if compound has databasse activities, false if not
398
363
  def database_activity(subjectid)
data/lib/opentox-ruby.rb CHANGED
@@ -9,6 +9,6 @@ rescue LoadError
9
9
  end
10
10
 
11
11
  ['opentox', 'compound','dataset', 'parser','serializer', 'algorithm','model','task','validation','feature',
12
- 'rest_client_wrapper', 'authorization', 'policy', 'helper', 'to-html', 'ontology' ].each do |lib|
12
+ 'rest_client_wrapper', 'authorization', 'policy', 'helper', 'to-html', 'ontology', 'r-util' ].each do |lib|
13
13
  require lib
14
14
  end