Class: OpenTox::Model::Lazar

Inherits:
Object
  • Object
show all
Includes:
Algorithm, OpenTox::Model
Defined in:
lib/model.rb

Overview

Lazy Structure Activity Relationship class

Instance Attribute Summary collapse

Attributes included from OpenTox

#metadata, #uri

Class Method Summary collapse

Instance Method Summary collapse

Methods included from OpenTox

#add_metadata, #load_metadata, sign_in, text_to_html, #to_rdfxml

Methods included from Algorithm

effect, gauss, get_cdk_descriptors, get_jl_descriptors, get_ob_descriptors, isnull_or_singular?, load_ds_csv, min_frequency, numeric?, pc_descriptors, sum_size, #to_rdfxml, zero_variance?

Constructor Details

#initialize(uri = nil) ⇒ Lazar

Returns a new instance of Lazar.



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/model.rb', line 107

def initialize(uri=nil)

  if uri
    super uri
  else
    super CONFIG[:services]["opentox-model"]
  end

  @metadata[OT.algorithm] = File.join(CONFIG[:services]["opentox-algorithm"],"lazar")

  @features = []
  @effects = {}
  @activities = {}
  @p_values = {}
  @fingerprints = {}
  @value_map = {}

  @feature_calculation_algorithm = "Substructure.match"
  @similarity_algorithm = "Similarity.tanimoto"
  @prediction_algorithm = "Neighbors.weighted_majority_vote"
  
end

Instance Attribute Details

#activitiesObject

Returns the value of attribute activities.



106
107
108
# File 'lib/model.rb', line 106

def activities
  @activities
end

#compoundObject

Returns the value of attribute compound.



106
107
108
# File 'lib/model.rb', line 106

def compound
  @compound
end

#compound_fingerprintsObject

Returns the value of attribute compound_fingerprints.



106
107
108
# File 'lib/model.rb', line 106

def compound_fingerprints
  @compound_fingerprints
end

#compoundsObject

Returns the value of attribute compounds.



106
107
108
# File 'lib/model.rb', line 106

def compounds
  @compounds
end

#effectsObject

Returns the value of attribute effects.



106
107
108
# File 'lib/model.rb', line 106

def effects
  @effects
end

#feature_calculation_algorithmObject

Returns the value of attribute feature_calculation_algorithm.



106
107
108
# File 'lib/model.rb', line 106

def feature_calculation_algorithm
  @feature_calculation_algorithm
end

#featuresObject

Returns the value of attribute features.



106
107
108
# File 'lib/model.rb', line 106

def features
  @features
end

#fingerprintsObject

Returns the value of attribute fingerprints.



106
107
108
# File 'lib/model.rb', line 106

def fingerprints
  @fingerprints
end

#neighborsObject

Returns the value of attribute neighbors.



106
107
108
# File 'lib/model.rb', line 106

def neighbors
  @neighbors
end

#p_valuesObject

Returns the value of attribute p_values.



106
107
108
# File 'lib/model.rb', line 106

def p_values
  @p_values
end

#prediction_algorithmObject

Returns the value of attribute prediction_algorithm.



106
107
108
# File 'lib/model.rb', line 106

def prediction_algorithm
  @prediction_algorithm
end

#prediction_datasetObject

Returns the value of attribute prediction_dataset.



106
107
108
# File 'lib/model.rb', line 106

def prediction_dataset
  @prediction_dataset
end

#similarity_algorithmObject

Returns the value of attribute similarity_algorithm.



106
107
108
# File 'lib/model.rb', line 106

def similarity_algorithm
  @similarity_algorithm
end

#subjectidObject

Returns the value of attribute subjectid.



106
107
108
# File 'lib/model.rb', line 106

def subjectid
  @subjectid
end

#value_mapObject

Returns the value of attribute value_map.



106
107
108
# File 'lib/model.rb', line 106

def value_map
  @value_map
end

Class Method Details

.all(subjectid = nil) ⇒ Array

Get URIs of all lazar models

Returns:

  • (Array)

    List of lazar model URIs



132
133
134
# File 'lib/model.rb', line 132

def self.all(subjectid=nil)
  RestClientWrapper.get(CONFIG[:services]["opentox-model"], :subjectid => subjectid).to_s.split("\n")
end

.create(params, waiting_task = nil) ⇒ OpenTox::Model::Lazar

Create a new lazar model

Parameters:

  • params (optional, Hash)

    Parameters for the lazar algorithm (OpenTox::Algorithm::Lazar)

Returns:



146
147
148
149
150
151
# File 'lib/model.rb', line 146

def self.create(params, waiting_task=nil )
  subjectid = params[:subjectid]
  lazar_algorithm = OpenTox::Algorithm::Generic.new File.join( CONFIG[:services]["opentox-algorithm"],"lazar")
  model_uri = lazar_algorithm.run(params, waiting_task)
  OpenTox::Model::Lazar.find(model_uri, subjectid)      
end

.find(uri, subjectid = nil) ⇒ OpenTox::Model::Lazar

Find a lazar model

Parameters:

Returns:



139
140
141
# File 'lib/model.rb', line 139

def self.find(uri, subjectid=nil)
  OpenTox::Model::Lazar.from_json RestClientWrapper.get(uri,{:accept => 'application/json', :subjectid => subjectid})
end

.from_json(json) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/model.rb', line 153

def self.from_json(json)
  hash = Yajl::Parser.parse(json)
  #LOGGER.debug hash.to_yaml
  lazar = OpenTox::Model::Lazar.new
  #hash.each { |k,v| eval("lazar.#{k} = #{v}") }
  lazar.uri = hash["uri"] if hash["uri"]
  lazar. = hash["metadata"] if hash["metadata"]
  lazar.compound = hash["compound"] if hash["compound"]
  lazar.prediction_dataset = hash["prediction_dataset"] if hash["prediction_dataset"]
  lazar.features = hash["features"] if hash["features"]
  lazar.effects = hash["effects"] if hash["effects"]
  lazar.activities = hash["activities"] if hash["activities"]
  lazar.p_values = hash["p_values"] if hash["p_values"]
  lazar.fingerprints = hash["fingerprints"] if hash["fingerprints"]
  lazar.feature_calculation_algorithm = hash["feature_calculation_algorithm"] if hash["feature_calculation_algorithm"]
  lazar.similarity_algorithm = hash["similarity_algorithm"] if hash["similarity_algorithm"]
  lazar.prediction_algorithm = hash["prediction_algorithm"] if hash["prediction_algorithm"]
  lazar.subjectid = hash["subjectid"] if hash["subjectid"]
  lazar.value_map = hash["value_map"] if hash["value_map"]
  lazar.compounds = hash["compounds"] if hash["compounds"]

  lazar
end

Instance Method Details

#database_activity(subjectid) ⇒ Boolean

Find database activities and store them in @prediction_dataset

Returns:

  • (Boolean)

    true if compound has databasse activities, false if not



386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/model.rb', line 386

def database_activity(subjectid)
  if @activities[@compound.uri]
    if OpenTox::Feature.find([OT.dependentVariables], subjectid).feature_type == "classification"
      @activities[@compound.uri].each { |act| @prediction_dataset.add @compound.uri, @metadata[OT.dependentVariables], @value_map[act.to_s] }
    else
      @activities[@compound.uri].each { |act| @prediction_dataset.add @compound.uri, @metadata[OT.dependentVariables], act }
    end
    @prediction_dataset.(OT.hasSource => @metadata[OT.trainingDataset])
    @prediction_dataset.save(subjectid)
    true
  else
    false
  end
end

#delete(subjectid) ⇒ Object

Delete model at model service



436
437
438
# File 'lib/model.rb', line 436

def delete(subjectid)
  RestClientWrapper.delete(@uri, :subjectid => subjectid) unless @uri == CONFIG[:services]["opentox-model"]
end

#parameter(param) ⇒ String

Get a parameter value

Parameters:

  • param (String)

    Parameter name

Returns:

  • (String)

    Parameter value



196
197
198
# File 'lib/model.rb', line 196

def parameter(param)
  @metadata[OT.parameters].collect{|p| p[OT.paramValue] if p[DC.title] == param}.compact.first
end

#predict(compound_uri, verbose = false, subjectid = nil) ⇒ OpenTox::Dataset

Predict a compound

Parameters:

  • compound_uri (String)

    Compound URI

  • verbose (optinal, Boolean) (defaults to: false)

    Verbose prediction (output includes neighbors and features)

Returns:



237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/model.rb', line 237

def predict(compound_uri,verbose=false,subjectid=nil)

  @compound = Compound.new compound_uri
  features = {}

  #LOGGER.debug self.to_yaml
  unless @prediction_dataset
    @prediction_dataset = Dataset.create(CONFIG[:services]["opentox-dataset"], subjectid)
    @prediction_dataset.( {
      OT.hasSource => @uri,
      DC.creator => @uri,
      DC.title => URI.decode(File.basename( @metadata[OT.dependentVariables] )),
      OT.parameters => [{DC.title => "compound_uri", OT.paramValue => compound_uri}]
    } )
  end

  unless database_activity(subjectid) # adds database activity to @prediction_dataset

    # Calculation of needed values for query compound
    @compound_features = eval("#{@feature_calculation_algorithm}({
                              :compound => @compound, 
                              :features => @features, 
                              :feature_dataset_uri => @metadata[OT.featureDataset],
                              :pc_type => self.parameter(\"pc_type\"),
                              :lib => self.parameter(\"lib\"),
                              :subjectid => subjectid
                              })")
    
    # Adding fingerprint of query compound with features and values(p_value*nr_hits)
    @compound_fingerprints = {}
    @compound_features.each do |feature, value| # value is nil if "Substructure.match"
      if @feature_calculation_algorithm == "Substructure.match_hits" 
        @compound_fingerprints[feature] = @p_values[feature] * value
      elsif @feature_calculation_algorithm == "Substructure.match"
        @compound_fingerprints[feature] = @p_values[feature]
      elsif @feature_calculation_algorithm == "Substructure.lookup"
        @compound_fingerprints[feature] = value
      end
    end

    # Transform model data to machine learning scheme (tables of data)
    mtf = OpenTox::Algorithm::Transform::ModelTransformer.new(self)
    mtf.transform

    # Make a prediction
    prediction = eval("#{@prediction_algorithm}( { :props => mtf.props,
                                                    :acts => mtf.acts,
                                                    :sims => mtf.sims,
                                                    :value_map => @value_map,
                                                    :min_train_performance => self.parameter(\"min_train_performance\")
                                                  } ) ")

    value_feature_uri = File.join( @uri, "predicted", "value")
    confidence_feature_uri = File.join( @uri, "predicted", "confidence")

    @prediction_dataset.[OT.dependentVariables] = @metadata[OT.dependentVariables] unless @prediction_dataset.[OT.dependentVariables] 
    @prediction_dataset.[OT.predictedVariables] = [value_feature_uri, confidence_feature_uri] unless @prediction_dataset.[OT.predictedVariables] 

    if OpenTox::Feature.find([OT.dependentVariables], subjectid).feature_type == "classification"
      @prediction_dataset.add @compound.uri, value_feature_uri, @value_map[prediction[:prediction].to_s]
    else
      @prediction_dataset.add @compound.uri, value_feature_uri, prediction[:prediction]
    end
    @prediction_dataset.add @compound.uri, confidence_feature_uri, prediction[:confidence]
    @prediction_dataset.features[value_feature_uri][DC.title] = @prediction_dataset.[DC.title]
    @prediction_dataset.features[confidence_feature_uri][DC.title] = "Confidence"

    if verbose
      if @feature_calculation_algorithm == "Substructure.match"
        f = 0
        @compound_features.each do |feature|
          feature_uri = File.join( @prediction_dataset.uri, "feature", "descriptor", f.to_s)
          features[feature] = feature_uri
          @prediction_dataset.add_feature(feature_uri, {
            RDF.type => [OT.Substructure],
            OT.smarts => feature,
            OT.pValue => @p_values[feature],
            OT.effect => @effects[feature]
          })
          @prediction_dataset.add @compound.uri, feature_uri, true
          f+=1
        end
      elsif @feature_calculation_algorithm == "Substructure.lookup"
        f = 0
        @compound_features.each do |feature, value|
          features[feature] = feature
          @prediction_dataset.add_feature(feature, {
            RDF.type => [OT.NumericFeature]
          })
          @prediction_dataset.add @compound.uri, feature, value
          f+=1
        end
      else
        @compound_features.each do |feature|
          features[feature] = feature
          @prediction_dataset.add @compound.uri, feature, true
        end
      end
      n = 0
      @neighbors.each do |neighbor|
        neighbor_uri = File.join( @prediction_dataset.uri, "feature", "neighbor", n.to_s )
        @prediction_dataset.add_feature(neighbor_uri, {
          OT.compound => neighbor[:compound],
          OT.similarity => neighbor[:similarity],
          OT.measuredActivity => neighbor[:activity],
          RDF.type => [OT.Neighbor]
        })
        @prediction_dataset.add @compound.uri, neighbor_uri, true
        f = 0 unless f
        neighbor[:features].each do |feature|
          if @feature_calculation_algorithm == "Substructure.match"
            feature_uri = File.join( @prediction_dataset.uri, "feature", "descriptor", f.to_s) unless feature_uri = features[feature]
          else
            feature_uri = feature
          end
          if @feature_calculation_algorithm == "Substructure.lookup"
            @prediction_dataset.add neighbor[:compound], feature_uri, @fingerprints[neighbor[:compound]][feature_uri]
          else
            @prediction_dataset.add neighbor[:compound], feature_uri, true
          end

          unless features.has_key? feature
            features[feature] = feature_uri
            if @feature_calculation_algorithm == "Substructure.lookup"
              @prediction_dataset.add_feature(feature_uri, {
                RDF.type => [OT.NumericFeature]
              })
            else
              @prediction_dataset.add_feature(feature_uri, {
                RDF.type => [OT.Substructure],
                OT.smarts => feature,
                OT.pValue => @p_values[feature],
                OT.effect => @effects[feature]
              })
            end
            f+=1
          end
        end
        n+=1
      end
    end
  end

  @prediction_dataset.save(subjectid)
  @prediction_dataset
end

#predict_dataset(dataset_uri, subjectid = nil, waiting_task = nil) ⇒ OpenTox::Dataset

Predict a dataset

Parameters:

  • dataset_uri (String)

    Dataset URI

  • (optional, subjectid)
  • waiting_task (optional, OpenTox::Task) (defaults to: nil)

    (can be a OpenTox::Subtask as well), progress is updated accordingly

Returns:



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/model.rb', line 205

def predict_dataset(dataset_uri, subjectid=nil, waiting_task=nil)

  @prediction_dataset = Dataset.create(CONFIG[:services]["opentox-dataset"], subjectid)
  @prediction_dataset.({
    OT.hasSource => @uri,
    DC.creator => @uri,
    DC.title => URI.decode(File.basename( @metadata[OT.dependentVariables] )),
    OT.parameters => [{DC.title => "dataset_uri", OT.paramValue => dataset_uri}]
  })
  d = Dataset.new(dataset_uri,subjectid)
  d.load_compounds(subjectid)
  count = 0
  d.compounds.each do |compound_uri|
    begin
      predict(compound_uri,false,subjectid)
      count += 1
      waiting_task.progress( count/d.compounds.size.to_f*100.0 ) if waiting_task
    rescue => e
      LOGGER.warn "prediction for compound "+compound_uri.to_s+" failed: "+e.message+" subjectid: #{subjectid}"
      #LOGGER.debug "#{e.class}: #{e.message}"
      #LOGGER.debug "Backtrace:\n\t#{e.backtrace.join("\n\t")}"

    end
  end
  #@prediction_dataset.save(subjectid)
  @prediction_dataset
end

#prediction_confidence_featureObject



418
419
420
421
422
423
424
425
426
427
428
# File 'lib/model.rb', line 418

def prediction_confidence_feature
  dependent_uri = @metadata[OT.dependentVariables].first
  feature = OpenTox::Feature.new File.join( @uri, "predicted", "confidence")
  feature.( {
    RDF.type => OT.ModelPrediction,
    OT.hasSource => @uri,
    DC.creator => @uri,
    DC.title => "#{URI.decode(File.basename( dependent_uri ))} confidence"
  })
  feature
end

#prediction_featuresObject



401
402
403
# File 'lib/model.rb', line 401

def prediction_features
  [prediction_value_feature,prediction_confidence_feature]
end

#prediction_value_featureObject



405
406
407
408
409
410
411
412
413
414
415
416
# File 'lib/model.rb', line 405

def prediction_value_feature
  dependent_uri = @metadata[OT.dependentVariables].first
  feature = OpenTox::Feature.new File.join( @uri, "predicted", "value")
  feature.( {
    RDF.type => OT.ModelPrediction,
    OT.hasSource => @uri,
    DC.creator => @uri,
    DC.title => URI.decode(File.basename( dependent_uri )),
    OWL.sameAs => dependent_uri
  })
  feature
end

#run(params, accept_header = nil, waiting_task = nil) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
# File 'lib/model.rb', line 181

def run( params, accept_header=nil, waiting_task=nil )
unless accept_header
  if CONFIG[:json_hosts].include?(URI.parse(@uri).host)
    accept_header = 'application/json' 
  else
    accept_header = 'application/rdf+xml'
  end
end
LOGGER.info "running model "+@uri.to_s+", params: "+params.inspect+", accept: "+accept_header.to_s
RestClientWrapper.post(@uri,params,{:accept => accept_header},waiting_task).to_s
end

#save(subjectid) ⇒ Object

Save model at model service



431
432
433
# File 'lib/model.rb', line 431

def save(subjectid)
  self.uri = RestClientWrapper.post(@uri,self.to_json,{:content_type =>  "application/json", :subjectid => subjectid})
end

#to_jsonObject



177
178
179
# File 'lib/model.rb', line 177

def to_json
  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, :compounds => @compounds})
end