summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Helma <helma@in-silico.ch>2015-08-27 20:25:16 +0200
committerChristoph Helma <helma@in-silico.ch>2015-08-27 20:25:16 +0200
commit7dcae58f3af869b4c58e6091cee099acff113ad2 (patch)
tree1c9d16803d26ae663539a1721a63e4999b941323
parent46166d66c458eb9d922f0c6c4958654a761a7529 (diff)
Initial GUI for Nestec models
-rw-r--r--Gemfile10
-rw-r--r--application.rb87
-rw-r--r--lazar-gui.gemspec12
-rw-r--r--views/neighbors.haml150
-rw-r--r--views/predict.haml111
-rw-r--r--views/prediction.haml127
6 files changed, 133 insertions, 364 deletions
diff --git a/Gemfile b/Gemfile
index 1b83cff..736527c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,12 +3,4 @@ gemspec
gem "sinatra"
gem "haml"
gem "sass"
-gem "opentox-server", :path => "../opentox-server"
-gem "opentox-client", :path => "../opentox-client"
-gem "opentox-algorithm", :path => "../algorithm"
-gem "opentox-compound", :path => "../compound"
-gem "opentox-dataset", :path => "../dataset"
-gem "opentox-feature", :path => "../feature"
-gem "opentox-model", :path => "../model"
-gem "opentox-task", :path => "../task"
-gem "opentox-validation", :path => "../validation"
+gem "lazar", :path => "../lazar"
diff --git a/application.rb b/application.rb
index cff08a2..9b105a4 100644
--- a/application.rb
+++ b/application.rb
@@ -1,16 +1,12 @@
require_relative 'helper.rb'
-require File.join(ENV["HOME"],".opentox","config","lazar-gui.rb") # until added to ot-tools
+include OpenTox
+#require File.join(ENV["HOME"],".opentox","config","lazar-gui.rb") # until added to ot-tools
# DG: workaround for https://github.com/sinatra/sinatra/issues/808
# Date: 18/11/2013
set :protection, :except => :path_traversal
helpers do
- # models must be edited with RDF.type => (RDF::OT.PredictionModel, EchaEndpoint)
- @@models = []
- models = `curl -k GET -H accept:text/uri-list #{$model[:uri]}`.split("\n")
- .collect{|m| model = OpenTox::Model::Lazar.find m; @@models << model if model.type.flatten.to_s =~ /PredictionModel/}
-
class Numeric
def percent_of(n)
self.to_f / n.to_f * 100.0
@@ -24,11 +20,9 @@ get '/?' do
end
get '/predict/?' do
- # sort models by endpoint alphabetically
- $size = 0
- @models = @@models.sort!{|a, b| a.type.select{|e| e =~ /endpoint/i} <=> b.type.select{|e| e =~ /endpoint/i}}
- @endpoints = @@models.collect{|e| e.type.select{|e| e =~ /endpoint/i}}.sort!.uniq
- @models.size <= 0 ? (haml :info) : (haml :predict)
+ @models = OpenTox::Model::Prediction.all
+ @endpoints = @models.collect{|m| m.endpoint}.sort.uniq
+ @models.count <= 0 ? (haml :info) : (haml :predict)
end
get '/jme_help/?' do
@@ -202,68 +196,23 @@ end
post '/predict/?' do
# validate identifier input
- task = OpenTox::Task.run("Validate SMILES string.") do
- # transfered input
- @identifier = params[:identifier]
-
+ # transfered input
+ @identifier = params[:identifier]
+ begin
# get compound from SMILES
- @compound = OpenTox::Compound.from_smiles @identifier.to_s
-
- # validate SMILES by converting to INCHI
- inchi = @compound.inchi
- end#smiles
- # necessary to wait for task
- task.wait
- # case task fails return message smiles invalid
- # case task completed go ahead
- case task[RDF::OT.hasStatus]
- when "Error"
+ @compound = Compound.from_smiles @identifier#.to_s
+ rescue
@error_report = "Attention, '#{params[:identifier]}' is not a valid SMILES string."
haml :error
- when "Completed"
- @identifier = params[:identifier]
- @compound = OpenTox::Compound.from_smiles @identifier.to_s
- # init arrays
- @prediction_models = []
- @predictions = []
- @model_type = []
- # get selected models
- # compare selected model by uri
- params[:selection].each do |model|
- # selected model = model[0]
- # compare selected with all models
- @@models.each do |m|
- @prediction_models << m if m.uri == model[0]
- end
- end
- # predict with selected models
- # one prediction in 'pa' array = OpenTox::Dataset
- # all collected predictions in '@predictions' array
- # add task for progressBar
- total = @prediction_models.size
- toptask = OpenTox::Task.find params[:task_uri]
- toptask.metadata
- toptask[RDF::OT.hasStatus] = "Running"
- toptask[RDF::OT.percentageCompleted] = "10"
- toptask.put
- @prediction_models.each_with_index do |m, idx|
- idx = idx+1
- # define type (classification|regression)
- m.type.join =~ /classification/i ? (@model_type << "classification") : (@model_type << "regression")
-
- # predict against compound
- @prediction_uri = m.run :compound_uri => "#{@compound.uri}"
- $logger.debug "prediction dataset:\t#{@prediction_uri}\n"
-
- prediction = OpenTox::Dataset.new @prediction_uri
- pa = []
- pa << prediction
- @predictions << pa
- toptask[RDF::OT.percentageCompleted] = idx.percent_of(total).round(1)
- toptask.put
- end
- haml :prediction
end
+ @models = []
+ @predictions = []
+ params[:selection].keys.each do |model_id|
+ model = Model::Prediction.find model_id
+ @models << model
+ @predictions << model.predict(@compound)
+ end
+ haml :prediction
end
get '/style.css' do
diff --git a/lazar-gui.gemspec b/lazar-gui.gemspec
index 8b07ab2..dd852a0 100644
--- a/lazar-gui.gemspec
+++ b/lazar-gui.gemspec
@@ -15,18 +15,10 @@ Gem::Specification.new do |s|
s.files = `git ls-files`.split("\n")
s.required_ruby_version = '>= 1.9.2'
- s.add_runtime_dependency "opentox-server"
- s.add_runtime_dependency "opentox-client"
- s.add_runtime_dependency "opentox-algorithm"
- s.add_runtime_dependency "opentox-compound"
- s.add_runtime_dependency "opentox-dataset"
- s.add_runtime_dependency "opentox-feature"
- s.add_runtime_dependency "opentox-model"
- s.add_runtime_dependency "opentox-task"
- s.add_runtime_dependency "opentox-validation"
+ #s.add_runtime_dependency "opentox-server"
+ s.add_runtime_dependency "lazar"
s.add_runtime_dependency "sinatra"
s.add_runtime_dependency "haml"
s.add_runtime_dependency "sass"
s.add_runtime_dependency "unicorn"
- s.post_install_message = "Please configure your service in ~/.opentox/config/lazar-gui.rb"
end
diff --git a/views/neighbors.haml b/views/neighbors.haml
index 22dff56..9f60e7c 100644
--- a/views/neighbors.haml
+++ b/views/neighbors.haml
@@ -4,110 +4,74 @@
/ display preordered in table view ;
%div.results{:style=>"display:none"}
- - count_m = 0
%h3 Neighbors:
/ tabs div
#tabs
%ul.nav.nav-tabs.nav-justified{:id=>"neighborTabs", :role=>"tablist"}
/ each model a tab head ;
- - @prediction_models.each do |m|
- - count_m += 1
- - m_title = m.title.split("_").last(2)[0]
+ - @models.each_with_index do |model,i|
%li
- %a{:href => "#results_#{count_m}", :id => "linkTab#{count_m}", data: {toggle:"tab"}}
- = m_title
- - count_rs = 0
+ %a{:href => "#results_#{i+1}", :id => "linkTab#{i+1}", data: {toggle:"tab"}}
+ = "#{model.endpoint} (#{model.species})"
%div.tab-content
/ unpack to single arrays
- - @predictions.each do |pa|
+ - @predictions.each_with_index do |prediction,j|
/ pass model type for significant fragments view
- - @type = @model_type[count_rs]
- - count_rs += 1
- #results.tab-pane.fade{:id=>"#{count_rs}"}
- - pa.each do |p|
- / prepare dataset for neighbors table ;
- / delete first array which contains prediction ;
- / following arrays are the neighbor predictions ;
- - @model_uri = p.metadata[RDF::OT.hasSource][0]
- - p.data_entries.shift
- - p.compounds.shift
-
- / call the tablesorter plugin ;
- / presort by similarity ;
- :javascript
- $(document).ready(function(){
- $("table##{count_rs}").tablesorter({
- debug: false,
- //table: 'ui-widget ui-widget-content ui-corner-all',
- //header: 'ui-widget-header ui-corner-all ui-state-default',
- theme: "bootstrap",
- //widthFixed: true,
- //hover: 'ui-state-hover',
- //even: 'ui-widget-content',
- //odd: 'ui-state-default',
- headerTemplate: '{content} {icon}',
- widgets: ['zebra', 'columns', 'uitheme'],
- headers: {0: {sorter: false}, 3: {sorter: false}},
- sortList: [[2,1]]
- });
+ #results.tab-pane.fade{:id=>"#{j+1}"}
+ / prepare dataset for neighbors table ;
+ / delete first array which contains prediction ;
+ / following arrays are the neighbor predictions ;
+ / call the tablesorter plugin ;
+ / presort by similarity ;
+ :javascript
+ $(document).ready(function(){
+ $("table##{j+1}").tablesorter({
+ debug: false,
+ theme: "bootstrap",
+ headerTemplate: '{content} {icon}',
+ widgets: ['zebra', 'columns', 'uitheme'],
+ headers: {0: {sorter: false}, 3: {sorter: false}},
+ sortList: [[2,1]]
});
- - $logger.debug "neighbors compounds:\t#{p.data_entries[0]}\n"
- - if p.data_entries[0][2] != nil && p.data_entries[0].size != 3
- -#%h2= "Neighbors: "
-
- %div.table-responsive
- %table.tablesorter{:id=>"#{count_rs}", :style=>"border-style: solid;"}
- %thead
- %tr
- %th{:style =>"vertical-align:middle;"}
- Compound
- %th{:style =>"vertical-align:middle;"}
- Measured Activity
- %th{:style =>"vertical-align:middle;"}
- Similarity
- %th{:style =>"vertical-align:middle;"}
- Supporting Information
- %info
- %tr
- %td
- %td{:style=>"font-size:x-small;padding:0px;"}
- %a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Measured Activity", data: {toggle:"popover", placement:"auto", html:"true", content:"Experimental result(s) from the training dataset."}, :style=>"z-index:auto+10;"}
- %td{:style=>"font-size:x-small;padding:0px;"}
- %a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Similarity", data: {toggle:"popover", placement:"auto", html:"true", content:"LAZAR calculates activity specific similarities based on the presence of statistically significant fragments. This procedure will <ul><li>consider only those parts of a chemical structure that are relevant for a particular endpoint</li><li>ignore inert parts of the structure</li><li>lead to different similarities, depending on the toxic endpoint Similarities of 1 may be encountered even for structurally dissimilar compounds, because inert parts are ignored.</li></ul>"}, :style=>"z-index:auto+10;"}
- %tbody
- - count = 0
- - p.compounds.each do |neighbor_compound|
- / prevent conversion of nil
- - c = p.data_entries[count][2] != nil ? p.data_entries[count][2] : ''
- - case c
- - when /(false|true|inactive|active)/i
- - c = c
- - else
- /- c = Array.new
- - c = p.data_entries[count][2].to_f.round(3)
- %tr
- %td{:style =>"vertical-align:middle;padding-left:1em;"}
- %a.btn.btn-link{:href => "#details#{count_rs}", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(neighbor_compound.uri)}/details"), :id=>"link#{count_rs}#{count}"}}
- %img.blind{:src=>"#{neighbor_compound.uri}/image", :alt=>"no image", :onError=>"this.onerror=null;", :title=>"#{neighbor_compound.smiles}", :width=>"150px"}
- %td{:style =>"vertical-align:middle;padding-left:1em;"}
- - if c.class == String
- = c
- - else
- = c
- %td{:style =>"vertical-align:middle;padding-left:1em;"}
- = p.data_entries[count][3] != nil ? p.data_entries[count][3].round(3) : "Not enough similar compounds in training dataset."
- %td{:style =>"vertical-align:middle;padding-left:1em;"}
- - if @type =~ /classification/i
- - if p.data_entries[count][3] != nil
- %a.btn.btn-default{:href => "#details#{count_rs}", :id=>"link#{count_rs}#{count}sf", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@type}/#{CGI.escape(neighbor_compound.uri)}/significant_fragments")}} Significant Fragments
- - if @type =~ /regression/i
- - if p.data_entries[count][3] != nil
- %a.btn.btn-default{:href => "#details#{count_rs}", :id=>"link#{count_rs}#{count}sf", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@type}/#{CGI.escape(neighbor_compound.uri)}/significant_fragments")}} Descriptors
- - count += 1
- - else
- %span.btn.btn-default.disabled Not enough similar compounds in training dataset
+ });
+ - if prediction[:neighbors].size > 0
+
+ %div.table-responsive
+ %table.tablesorter{:id=>"#{j+1}", :style=>"border-style: solid;"}
+ %thead
+ %tr
+ %th{:style =>"vertical-align:middle;"}
+ Compound
+ %th{:style =>"vertical-align:middle;"}
+ Measured Activity
+ %th{:style =>"vertical-align:middle;"}
+ Similarity
+ / %th{:style =>"vertical-align:middle;"}
+ / Supporting Information
+ %info
+ %tr
+ %td
+ %td{:style=>"font-size:x-small;padding:0px;"}
+ %a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Measured Activity", data: {toggle:"popover", placement:"auto", html:"true", content:"Experimental result(s) from the training dataset."}, :style=>"z-index:auto+10;"}
+ %td{:style=>"font-size:x-small;padding:0px;"}
+ %a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Similarity", data: {toggle:"popover", placement:"auto", html:"true", content:"LAZAR calculates activity specific similarities based on the presence of statistically significant fragments. This procedure will <ul><li>consider only those parts of a chemical structure that are relevant for a particular endpoint</li><li>ignore inert parts of the structure</li><li>lead to different similarities, depending on the toxic endpoint Similarities of 1 may be encountered even for structurally dissimilar compounds, because inert parts are ignored.</li></ul>"}, :style=>"z-index:auto+10;"}
+ / %td
+ %tbody
+ - prediction[:neighbors].each_with_index do |neighbor,count|
+ %tr
+ %td{:style =>"vertical-align:middle;padding-left:1em;"}
+ %a.btn.btn-link{:href => "#details#{j+1}", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(neighbor[0].to_s)}/details"), :id=>"link#{j+1}#{count}"}}
+ = Compound.find(neighbor[0]).svg
+ %td{:style =>"vertical-align:middle;padding-left:1em;"}
+ = neighbor[2].collect{|n| '%.2e' % n}.join ", "
+ %td{:style =>"vertical-align:middle;padding-left:1em;"}
+ / TODO differentiate between no neighbors found and compound found in dataset, display neighbors for compounds in dataset?
+ = neighbor[1] != nil ? neighbor[1] : "Not enough similar compounds in training dataset."
- %div.modal.fade{:id=>"details#{count_rs}", :role=>"dialog"}
+ - else
+ %span.btn.btn-default.disabled Not enough similar compounds in training dataset
+
+ %div.modal.fade{:id=>"details#{j+1}", :role=>"dialog"}
%div.modal-dialog.modal-lg
%div.modal-content
diff --git a/views/predict.haml b/views/predict.haml
index bd430a6..118c4d4 100644
--- a/views/predict.haml
+++ b/views/predict.haml
@@ -1,35 +1,6 @@
%link{ :href=>"/jsme/jsa.css", :rel=>"stylesheet"}
%script{:src=>"/jsme/jsme.nocache.js"}
:javascript
- function callTask(url) {
- var result="";
- $.ajax({
- url: url,
- async: false,
- success:function(data) {
- var response = data.match(/Completed\s.*\./)[0];
- var arr = response.split(" ");
- result = arr[1].replace(/"/g, "");
- }
- });
- return result;
- };
- // form function
- function progress($element, url) {
- $element.width("2%");
- $element.show();
- var timer = setInterval(function(){
- var percent = callTask(url);
- if(percent == 100.0){
- var next = percent;
- clearInterval(timer);
- }
- else {
- var next = percent;
- }
- $element.width(next+"%");
- }, 3000);
- };
function checksmiles () {
if (document.form.identifier.value == "") {
alert("Please draw or insert a chemical structure.");
@@ -48,7 +19,6 @@
});
if (checked == false){
alert("Please select an endpoint.");
- $('.progress-bar').hide();
return false;
};
return true;
@@ -67,8 +37,6 @@
};
// init task for progress
-- task_uri = OpenTox::Task.task_uri
-- OpenTox::Task.run("Predict compound.", "#{$lazar[:uri]}", task_uri)do;end
// whole site content needs to be in one form. Input and checkboxes are proofed by js functions.
%form{:name => "form", :action => to('/predict'), :method => "post", :enctype => "multipart/form-data", :onsubmit => "return !!(checksmiles() & checkboxes())" }
@@ -102,74 +70,14 @@
});
#models
- - @detail_count = 0
- @endpoints.each do |endpoint|
%div
- %b= endpoint[0].split("#").last.gsub("_", " ").gsub(/\"|\]/, "")+" :"
- - @models.each do |model|
- - if endpoint == model.type.select{|e| e =~ /Endpoint/}
- - model_title = model.title.split("_").last(2)[0]
- - model_t = model.title.gsub("_", " ")
- - @detail_count +=1
- %div{:id => model_title}
- %input{:type => "checkbox", :name => "selection[#{model.uri}]", :id => "selection[#{model_title}]", :value => true, :disabled => false}
- %label{:for => "selection[#{model_title}]"}
- = model_t
- %a.btn.btn-default.btn-xs{:href=>"#details", :id => "linkDetails#{model_title}", :title=>"#{model_title} details", :style=>"font-size:small;"}
- Details | Validation
-
- :javascript
- $("a#linkDetails#{model_title}").click(function () {
- $("#details_#{@detail_count}").toggle();
- //document.location = document.location + "#" + "details";
- });
- #details{:id => "#{@detail_count}", :style => "display:none;"}
- %div.panel{:style=>"padding:0.5em;"}
- %div.row
- %div.col-md-6
- %h3 Model Details:
- %p
- Algorithm: LAZAR
- - model.type.to_s =~ /regression/i ? type = "regression" : type = "classification"
- - @model_type = type
- %p
- = "Type: "+type
- - training_dataset = OpenTox::Dataset.new "#{model[RDF::OT.trainingDataset]}"
- - training_compounds = training_dataset.compounds.size.to_s
- %p
- Training compounds:
- = training_compounds
- %p
- Descriptors:
- - if type == "regression"
- %a{:href=>"https://services.in-silico.ch/algorithm/descriptor/physchem/list", :title=>"link opens in new window.", :target=>"_blank"} Physico-chemical (PC) properties
- - else
- %a{:href=>"http://www.maunz.de/libfminer2-bbrc-doc/", :title=>"link opens in new window.", :target=>"_blank"} Fminer backbone refinement classes
- %p
- Model:
- %a.btn{:href=>"#{to("/predict/#{CGI.escape(model.uri)}")}", :title=>"download"}
- rdf
- %span.glyphicon.glyphicon-download-alt
- %p
- Feature Dataset:
- %a.btn{:href=>"#{to("/predict/#{CGI.escape(model[RDF::OT.featureDataset])}")}", :title=>"download"}
- rdf
- %span.glyphicon.glyphicon-download-alt
- -#%a{:href=>"#{to("/predict/#{CGI.escape(model[RDF::OT.featureDataset])}")}/sdf", :title=>"download"} sdf
- %p
- Training Dataset:
- %a.btn{:href=>"#{to("/predict/#{CGI.escape(model[RDF::OT.trainingDataset])}")}", :title=>"link opens in new window."}
- rdf
- %span.glyphicon.glyphicon-download-alt
- -#%a{:href=>"#{to("/predict/#{CGI.escape(model[RDF::OT.trainingDataset])}/sdf")}", :title=>"link opens in new window."} sdf
- - unless model.metadata[RDF::OT.crossValidation].nil?
- %div.col-md-6
- %h3 Validation:
- %a.btn.btn-info.btn-xs{:href => "#{model.metadata[RDF::OT.crossValidation][0]}", :title=>"link opens in new window.", :target=>"_blank"}
- Detailed report link
- %p
- - @cv = OpenTox::Validation.find "#{model.metadata[RDF::OT.crossValidation][0]+"/statistics"}"
- = haml :validation, :layout => false, :validation => @cv, :model_type => @model_type
+ %b= endpoint
+ - @models.select{|m| m.endpoint == endpoint}.each do |model|
+ %div{:id => model.id}
+ %input{:type => "checkbox", :name => "selection[#{model.id}]", :id => "selection[#{model.id}]", :value => true, :disabled => false}
+ %label{:for => "selection[#{model.id}]"}
+ = model.species
%p
@@ -179,9 +87,4 @@
%h2
3. Predict
%div.col-md-10
- %input.btn.btn-warning.h2{ :type => "submit", :id => "submit", :value=>">>", :onclick => "(progress($('.progress-bar'),'#{task_uri}') & getsmiles())"}
- %input{:type => "hidden", :name => "task_uri", :value => "#{task_uri}"}
- %div.row
- %div.col-md-12
- %div.progress
- %div.progress-bar.progress-bar-striped.active{:role=>"progressbar", aria: { valuemin: 0, valuemax: 100}, :style=>"width:0;"}
+ %input.btn.btn-warning.h2{ :type => "submit", :id => "submit", :value=>">>", :onclick => "getsmiles()"}
diff --git a/views/prediction.haml b/views/prediction.haml
index dfc11fc..91f7024 100644
--- a/views/prediction.haml
+++ b/views/prediction.haml
@@ -18,89 +18,58 @@
%tbody
%tr
%td{:id=>"compound", :style=>"vertical-align:top;"}
- %a.btn.btn-link{:href => "#detailsTop", :id=>"linkCompound", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@compound.uri)}/details")}}
- %img.img-responsive{:src=>"#{@compound.uri}/image", :alt=>"no image", :title=>"#{@compound.smiles}", :width=>"150", :height=>"150"}
- - count=0
- - @predictions.each do |pa|
- / unpack to single array/prediction
- / if p.data_entries array[0].size == 3 -> database hit
- / change 'result' if database hit
- / change 'confidence' if database hit
- - pa.each do |p|
- / prevent conversion of nil
- /- $logger.debug "data entries in prediction array:\t#{p.data_entries}\n"
- - database_hit = 0
- - if p.data_entries[0].size == 3
- - database_hit = 1
- - c = p.data_entries[0][0] != nil ? p.data_entries[0][0] : ''
- - case c
- - when /(false|true|inactive|active)/i
- - c = c
- - else
- /- c = Array.new
- - c = (p.data_entries[0][0].class == Float) ? p.data_entries[0][0].round(3) : (p.data_entries[0][0] != nil ? p.data_entries[0][0] : "no prediction")
- %td{:style=>"vertical-align:top;"}
- %b{:class => "title"}
- = @prediction_models[count].title.gsub("_", " ")
- - @model_uri = @prediction_models[count].uri
+ %a.btn.btn-link{:href => "#detailsTop", :id=>"linkCompound", data: { toggle: "modal", remote: to("/prediction/#{@compound.id.to_s}/details")}}
+ / %img.img-responsive{:src=>"#{@compound.id}/image", :alt=>"no image", :title=>"#{@compound.smiles}", :width=>"150", :height=>"150"}
+ = @compound.svg
+ - @predictions.each_with_index do |prediction,i|
+ %td{:style=>"vertical-align:top;"}
+ %b{:class => "title"}
+ = "#{@models[i].endpoint.gsub('_', ' ')} (#{@models[i].species})"
+ %p
+ - if prediction[:confidence] == "measured"
+ %p
+ / TODO fix scientific notation from database
+ %b Measured activity:
+ = prediction[:value].numeric? ? "#{prediction[:value].round(3)} (#{@models[i].unit})" : prediction[:value]
+ %p Compound is part of the training dataset
+ - elsif prediction[:neighbors].size > 0
%p
/ model type (classification|regression)
%b Type:
- = @model_type[count]
+ = @models[i].model.class.to_s.match("Classification") ? "Classification" : "Regression"
+ %br
+ %b Prediction:
+ / TODO scientific notation
+ = prediction[:value].numeric? ? "#{'%.2e' % prediction[:value]} #{@models[i].unit}" : prediction[:value]
+ / TODO update description
+ %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Prediction", data: {toggle:"popover", placement:"left", html:"true", content:"LAZAR calculates searches the training dataset for similar compounds (neighbors) and calculates the prediction from their measured activities. LAZAR calculates predictions using <ul><li>a majority vote (weighted by compound similarity) for<br /><b>classification</b> (<a href='http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract', target='_blank'>original publication</a>) </li><li>a local QSAR model based on neighbors for<br /><b>regression</b> (<a href='http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract', target='_blank'</h>original publication</a>) </li></ul>Please keep in mind that predictions are based on the measured activities of neighbors."}}
+ %br
+ / TODO probability
+ %b Confidence:
+ = prediction[:confidence].round(3)
+ %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Confidence", data: {toggle:"popover", placement:"left", html:"true", content:"Indicates the applicability domain of a model. Predictions with a high confidence can be expected to be more reliable than predictions with low confidence. Confidence values may take any value between 0 and 1. For most models confidence > 0.025 is a sensible (hard) cutoff to distinguish between reliable and unreliable predictions."}}
+ %p
+ /TODO add tooltip for significant ftagments and descriptors
+ / - if @model_type[i] =~ /classification/i && (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0)
+ / Significant fragments:
+ / %a.btn.btn-default.btn-sm{:id=>"linkSigFragments", :href => "#detailsTop", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[i]}/#{CGI.escape(@compound.uri)}/fingerprints")}} Significant fragments
+ / - if @model_type[i] =~ /regression/i && (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0)
+ / Descriptors
+ / %a.btn.btn-default.btn-sm{:id=>"linkDescriptors", :href => "#detailsTop", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[i]}/#{CGI.escape(@compound.uri)}/fingerprints")}} Descriptors
+ / %p
+ %a.btn.btn-default.btn-sm{:href=> "#tabs", :id=>"link#{i+1}"}
+ Neighbors
+ :javascript
+ $("a#link#{i}").click(function () {
+ $(".results").show();
+ //document.getElementById('tabs').focus();
+ $('#neighborTabs a[href="#results_#{i+1}"]').tab('show');
+ //$("#tabs").tabs({ active: "#{i}" });
+ });
+ %p
+ - else
%p
- - unless database_hit > 0
- %b Result:
- %b
- - if c.class == String
- - result = (c != '' ? c : "No prediction result.")
- = result
- - else
- - result = (c != '' ? c.round(3) : "No prediction result.")
- = result
- - confidence = (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0) ? p.data_entries[0][1].round(2) : "--"
- %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Result", data: {toggle:"popover", placement:"left", html:"true", content:"LAZAR calculates searches the training dataset for similar compounds (neighbors) and calculates the prediction from their measured activities. LAZAR calculates predictions using <ul><li>a majority vote (weighted by compound similarity) for<br /><b>classification</b> (<a href='http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract', target='_blank'>original publication</a>) </li><li>a local QSAR model based on neighbors for<br /><b>regression</b> (<a href='http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract', target='_blank'</h>original publication</a>) </li></ul>Please keep in mind that predictions are based on the measured activities of neighbors."}}
- - @cv = OpenTox::Validation.find @prediction_models[count].metadata[RDF::OT.crossValidation][0]+"/statistics" #unless @prediction_models[count].title.include?("Mutagenicity")
- - unless @model_type[count] == "regression"
- %br
- %b
- = "Probability: "
- - unless result == "No prediction result." or confidence == "--"
- - prob = @cv.probabilities( confidence, result )[:probs][result]*100
- = "#{prob.round(1)} %"
- %p
- %b Confidence:
- = confidence
- %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Confidence", data: {toggle:"popover", placement:"left", html:"true", content:"Indicates the applicability domain of a model. Predictions with a high confidence can be expected to be more reliable than predictions with low confidence. Confidence values may take any value between 0 and 1. For most models confidence > 0.025 is a sensible (hard) cutoff to distinguish between reliable and unreliable predictions."}}
- %p
- /TODO add tooltip for significant ftagments and descriptors
- - if @model_type[count] =~ /classification/i && (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0)
- / Significant fragments:
- %a.btn.btn-default.btn-sm{:id=>"linkSigFragments", :href => "#detailsTop", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[count]}/#{CGI.escape(@compound.uri)}/fingerprints")}} Significant fragments
- - if @model_type[count] =~ /regression/i && (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0)
- / Descriptors
- %a.btn.btn-default.btn-sm{:id=>"linkDescriptors", :href => "#detailsTop", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[count]}/#{CGI.escape(@compound.uri)}/fingerprints")}} Descriptors
- %p
- - if c != ''
- %a.btn.btn-default.btn-sm{:href=> "#tabs", :id=>"link#{count}"}
- Neighbors
- :javascript
- $("a#link#{count}").click(function () {
- $(".results").show();
- //document.getElementById('tabs').focus();
- $('#neighborTabs a[href="#results_#{count+1}"]').tab('show');
- //$("#tabs").tabs({ active: "#{count}" });
- });
- %p
- - count+=1
- - else # database hit
- %b Database hit:
- %br Compound found in training dataset
- %p
- %b Measured activity:
- = p.data_entries[0][2]
- %p
-
- - count+=1
+ Not enough similar compounds in training dataset.
/ always show the neighbors table, message is given there
= haml :neighbors, :layout => false, :model_type => @model_type