summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgebele <gebele@in-silico.ch>2016-12-07 12:07:13 +0000
committergebele <gebele@in-silico.ch>2016-12-07 12:07:13 +0000
commit55bf06381a42c9bb1e1e991e990f5d6e90c8e33e (patch)
tree44044577e36e00485aa5d73531d9d56747e5b742
parentb65956f3b250b4f10fe93b7d35924d21538cd6f5 (diff)
rebuild code for public release;prepared to work with lazar v1.0.0;reintroduced compound details
-rw-r--r--VERSION2
-rw-r--r--application.rb27
-rw-r--r--config.ru2
-rw-r--r--helper.rb215
-rw-r--r--views/details.haml6
-rw-r--r--views/layout.haml37
-rw-r--r--views/neighbors.haml4
-rw-r--r--views/predict.haml12
-rw-r--r--views/prediction.haml22
9 files changed, 82 insertions, 245 deletions
diff --git a/VERSION b/VERSION
index ec63514..9084fa2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-9
+1.1.0
diff --git a/application.rb b/application.rb
index eefd833..4eb4a36 100644
--- a/application.rb
+++ b/application.rb
@@ -24,19 +24,33 @@ get '/?' do
end
get '/predict/?' do
- @models = OpenTox::Model::Prediction.all
+ @models = OpenTox::Model::Validation.all
@models = @models.delete_if{|m| m.model.name =~ /\b(Net cell association)\b/}
@endpoints = @models.collect{|m| m.endpoint}.sort.uniq
@models.count <= 0 ? (haml :info) : (haml :predict)
end
get '/predict/modeldetails/:model' do
- model = OpenTox::Model::Prediction.find params[:model]
+ model = OpenTox::Model::Validation.find params[:model]
crossvalidations = OpenTox::Validation::RepeatedCrossValidation.find(model.repeated_crossvalidation_id).crossvalidations
return haml :model_details, :layout=> false, :locals => {:model => model, :crossvalidations => crossvalidations}
end
+# get individual compound details
+get '/prediction/:neighbor/details/?' do
+ @compound = OpenTox::Compound.find params[:neighbor]
+ @smiles = @compound.smiles
+ begin
+ @names = @compound.names.nil? ? "No names for this compound available." : @compound.names
+ rescue
+ @names = "No names for this compound available."
+ end
+ @inchi = @compound.inchi.gsub("InChI=", "")
+
+ haml :details, :layout => false
+end
+
get '/jme_help/?' do
File.read(File.join('views','jme_help.html'))
end
@@ -121,7 +135,7 @@ post '/predict/?' do
@compounds.each do |compound|
@batch[compound] = []
params[:selection].keys.each do |model_id|
- model = Model::Prediction.find model_id
+ model = OpenTox::Model::Validation.find model_id
prediction = model.predict(compound)
@batch[compound] << [model, prediction]
end
@@ -148,7 +162,7 @@ post '/predict/?' do
@models = []
@predictions = []
params[:selection].keys.each do |model_id|
- model = Model::Prediction.find model_id
+ model = OpenTox::Model::Validation.find model_id
@models << model
@predictions << model.predict(@compound)
end
@@ -156,6 +170,11 @@ post '/predict/?' do
end
end
+get '/license' do
+ @license = RDiscount.new(File.read("LICENSE.md")).to_html
+ haml :license, :layout => false
+end
+
get '/style.css' do
headers 'Content-Type' => 'text/css; charset=utf-8'
scss :style
diff --git a/config.ru b/config.ru
index 8f9daf5..ad609be 100644
--- a/config.ru
+++ b/config.ru
@@ -1,4 +1,4 @@
-ENV["LAZAR_ENV"] = "production"
+ENV["LAZAR_ENV"] = "development"#"production"
require 'bundler'
Bundler.require
require File.expand_path './application.rb'
diff --git a/helper.rb b/helper.rb
index caa1923..54dbd5e 100644
--- a/helper.rb
+++ b/helper.rb
@@ -1,218 +1,3 @@
helpers do
-
- def is_authorized(uri, action)
- if OpenTox::Authorization.server && session[:subjectid] != nil
- return OpenTox::Authorization.authorized?(uri, action, session[:subjectid])
- else
- return true
- end
- return false
- end
-
- def is_aluist
- OpenTox::Authorization.list_user_groups(session[:username], session[:subjectid]).include?("aluist")
- end
-
- def hide_link(destination)
- @link_id = 0 unless @link_id
- @link_id += 1
- haml :js_link, :locals => {:name => "hide", :destination => destination, :method => "hide"}, :layout => false
- end
-
- def toggle_link(destination,name)
- @link_id = 0 unless @link_id
- @link_id += 1
- haml :js_link, :locals => {:name => name, :destination => destination, :method => "toggle"}, :layout => false
- end
-
- def sort(descriptors,value_map)
- features = {:activating => [], :deactivating => [], :pc_features => []}
- if descriptors.kind_of?(Array)
- descriptors.each do |d|
- if !value_map.empty?
- features[:activating] << {:smarts => d[OT.smarts],:p_value => d[OT.pValue]} if d[OT.effect] == 2
- features[:deactivating] << {:smarts => d[OT.smarts],:p_value => d[OT.pValue]} if d[OT.effect] == 1
- else
- if d[OT.effect] =~ TRUE_REGEXP
- features[:activating] << {:smarts => d[OT.smarts],:p_value => d[OT.pValue]}
- elsif d[OT.effect] =~ FALSE_REGEXP
- features[:deactivating] << {:smarts => d[OT.smarts],:p_value => d[OT.pValue]}
- end
- end
- end
- else
- descriptors.each do |d,v|
- features[:pc_features] << {:feature => d, :value => v}
- end
- end
- features
- end
-
- def compound_image(compound,descriptors,value_map)
- haml :compound_image, :locals => {:compound => compound, :features => sort(descriptors,value_map)}, :layout => false
- end
- def activity_markup(activity,value_map)
- if value_map and !value_map.empty?
- if value_map.size == 2
- activity = value_map.index(activity) if value_map.has_value? activity
- if activity.to_i == 2
- haml ".active #{value_map[activity]}", :layout => false
- elsif activity.to_i == 1
- haml ".inactive #{value_map[activity]}", :layout => false
- else
- haml ".other #{activity.to_s}", :layout => false
- end
- else
- haml ".other #{activity.to_s}", :layout => false
- end
- elsif OpenTox::Algorithm::numeric? activity
- haml ".other #{sprintf('%.03g', activity.to_f)}", :layout => false
- else
- haml ".other #{activity.to_s}", :layout => false
- end
-=begin
- case activity.class.to_s
- when /Float/
- haml ".other #{sprintf('%.03g', activity)}", :layout => false
- when /String/
- case activity
- when "true"
- haml ".active active", :layout => false
- when "false"
- haml ".inactive inactive", :layout => false
- else
- haml ".other #{activity.to_s}", :layout => false
- end
- else
- if activity #true
- haml ".active active", :layout => false
- elsif !activity # false
- haml ".inactive inactive", :layout => false
- else
- haml ".other #{activity.to_s}", :layout => false
- end
- end
-=end
- end
-
- def neighbors_navigation
- @page = 0 unless @page
- haml :neighbors_navigation, :layout => false
- end
-
- def models_navigation
- @page = 0 unless @page
- haml :models_navigation, :layout => false
- end
-
- def models_navigation_bottom
- @page = 0 unless @page
- haml :models_navigation_bottom, :layout => false
- end
-
- def endpoint_option_list(max_time=3600)
- out = ""
- tmpfile = File.join(TMP_DIR, 'endpoint_option_list')
- if File.exists? tmpfile
- if Time.now-File.mtime(tmpfile) <= max_time
- f = File.open(tmpfile, 'r+')
- f.each{|line| out << line}
- return out
- else
- File.unlink(tmpfile)
- end
- end
- result = endpoint_selection()
- if result.lines.count > 3
- f = File.new(tmpfile,'w')
- f.print result
- f.close
- end
- result
- end
-
- def endpoint_level(endpoint="Endpoints", level=1)
- results = OpenTox::Ontology::Echa.echa_endpoints(endpoint) rescue results = []
- out = ""
- out += "<ul id='list_#{endpoint}' class='endpoint level_#{level}'>\n" if results.size > 0
- results.each do |result|
- r = result.split(',')
- endpointname = CGI.escape(r.first.split("#").last).gsub(".","")
- title = r[1..r.size-1].to_s
- out += " <li class='level_#{level}'><input type='radio' name='endpoint' value='#{result}' id='#{endpointname}' class='endpoint_list' /><label for='#{endpointname}' id='label_#{endpointname}'>#{title.gsub("\"","")}</label>\n"
- out += endpoint_level(endpointname, level + 1)
- out += "</li>\n"
- end
- out += "</ul>\n" if results.size > 0
- return out
- end
-
- def endpoint_selection()
- out = "<span id='endpoint_label'></span><input type='button' id='endpoint_list_button' value='Select endpoint' /> \n
- <div id='div_endpoint'>\n"
- out += "<b>Please select:</b>\n"
- out += endpoint_level
- js = ""
- out += "</div>\n"
- return out
- end
-
- def logmmol_to_mg(value ,mw)
- mg = round_to((10**(-1.0*round_to(value.to_f, 2))*(mw.to_f*1000)),4)
- return mg
- end
-
- def logmg_to_mg(value)
- mg = round_to(10**round_to(value.to_f, 2),4)
- return mg
- end
-
- def ptd50_to_td50(value ,mw)
- td50 = round_to((10**(-1.0*round_to(value.to_f, 2))*(mw.to_f*1000)),4)
- return td50
- end
-
- def round_to(value, deci)
- rounded = (value.to_f*(10**deci)).round / (10**deci).to_f
- return rounded
- end
-
- def calc_mw(compound_uri)
- ds = OpenTox::Dataset.new()
- ds.save(@subjectid)
- ds.add_compound(compound_uri)
- ds.save(@subjectid)
- mw_algorithm_uri = File.join(CONFIG[:services]["opentox-algorithm"],"pc/MW")
- mw_uri = OpenTox::RestClientWrapper.post(mw_algorithm_uri, {:dataset_uri=>ds.uri})
- ds.delete(@subjectid)
- mw_ds = OpenTox::Dataset.find(mw_uri, @subjectid)
- mw = mw_ds.data_entries[compound_uri][mw_uri.to_s + "/feature/MW"].first.to_f
- mw_ds.delete(@subjectid)
- return mw
- end
-
- def transform(value, compound_uri, name, haml)
- prediction_trans = nil
- model_name = name.to_s.downcase
- if model_name.include? "ptd50"
- mw = calc_mw(compound_uri)
- td50 = ptd50_to_td50(value, mw)
- prediction_trans = "TD50: #{td50}"
- elsif model_name.include? "loael"
- if model_name.include? "mol"
- mw = calc_mw(compound_uri)
- mg = logmmol_to_mg(value, mw)
- prediction_trans = "mg/kg bw/day: #{mg}"
- elsif model_name.include? "mg"
- mg = logmg_to_mg(value)
- prediction_trans = "mg/kg bw/day: #{mg}"
- end
- end
- if haml == true
- haml ".other #{prediction_trans.to_s}", :layout => false
- else
- return prediction_trans
- end
- end
end
diff --git a/views/details.haml b/views/details.haml
index bb8250d..be4948a 100644
--- a/views/details.haml
+++ b/views/details.haml
@@ -1,8 +1,12 @@
+:javascript
+ $(document).ready(function(){
+ addExternalLinks();
+ });
%div.modal-body{:style=>"padding:10px;"}
%button.close{ :type=>" button", data: { dismiss:"modal"}} &times;
%h3
Names and synonyms:
- %img.img-responsive{:src=>"#{@compound.uri}/image", :alt=>"Compound image not available", :width=>"300px", :heigth=>"300px", :style=>"float:left;"}
+ %p= @compound.svg
%p
%b="SMILES:"
%p= @smiles
diff --git a/views/layout.haml b/views/layout.haml
index 5ed63e8..62a224b 100644
--- a/views/layout.haml
+++ b/views/layout.haml
@@ -29,11 +29,30 @@
%h1.media-heading
lazar toxicity predictions
%div.col-md-2
- %h5
+ %h1.media-heading
%small
- [version: #{@version}]
+ %a{:href=>"https://nano-lazar.in-silico.ch", :rel=>"external"} nano-lazar
%div.container-fluid
+ %topline
+ %div.row
+ %div.col-md-8
+ Problems, bugs, ideas for improvements ? Please report at our
+ %a{:href => 'https://github.com/opentox/lazar-gui/issues', :rel => "external"} issue tracker
+ or send us an email.
+ %a{ :href=>"mailto:info@in-silico.ch", :target=>"_top"}
+ %img.share{:src=>"/images/Email.png"}
+ [version: #{@version}]
+ %div.col-md-2
+ %div.col-md-2
+ %a{:href=>"https://twitter.com/intent/tweet?source=http%3A%2F%2Flazar.in-silico.ch&text=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Tweet"}
+ %img.share{:src=>"/images/Twitter.png"}
+ %a{:href=>"https://plus.google.com/share?url=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Share on Google+"}
+ %img.share{:src=>"/images/Google+.png"}
+ %a{:href=>"http://www.linkedin.com/shareArticle?mini=true&url=http%3A%2F%2Flazar.in-silico.ch&title=&summary=&source=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Share on LinkedIn"}
+ %img.share{:src=>"/images/LinkedIn.png"}
+ %a{:href=>"https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Flazar.in-silico.ch&title=&summary=&source=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Share on Facebook"}
+ %img.share{:src=>"/images/Facebook.png"}
:javascript
$(document).ready(function(){
$("#back-top").hide();
@@ -57,7 +76,19 @@
%p.text-muted
&copy;
%a{:href => 'http://www.in-silico.ch', :rel => "external"} <i style="font-family: serife">in silico</i> toxicology gmbh 2004 - #{Time.now.year.to_s}
-
+ |
+ %a{:href => to("/license"), :rel => "external"} GPL3 License
+ %supporters.col-md-12
+ %p Financial support by
+ %a{:href=>"http://www.bfr.bund.de/de/start.html", :rel=>"external"}
+ %img{:src=>"/images/bfr_logo.gif"}
+ %a{:href=>"http://www.opentox.org/", :rel=>"external"}
+ %img{:src=>"/images/ot_logo.png"}
+ %a{:href=>"https://enanomapper.net/", :rel=>"external"}
+ %img{:src=>"/images/enm_logo.png"}
+ %a{:href=>"https://www.researchgate.net/institution/Nestle_SA/department/Nestle_Research_Center", :rel=>"external"}
+ %img{:src=>"/images/nestec.jpg"}
+
#back-top{:style => "z-index:100;position:fixed;bottom:1%;right:1%;"}
%a{:href => "", :style=>"text:decoration:none;color:#ccc;"}
diff --git a/views/neighbors.haml b/views/neighbors.haml
index 32b8389..a608c4d 100644
--- a/views/neighbors.haml
+++ b/views/neighbors.haml
@@ -81,8 +81,8 @@
/ Compound
- c = Compound.find(neighbor)
%td{:style =>"vertical-align:middle;padding-left:1em;width:50%;"}
- /%a.btn.btn-link{:href => "#details#{j+1}", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(neighbor["_id"])}/details"), :id=>"link#{j+1}#{count}"}}
- %p= c.svg
+ %a.btn.btn-link{:href => "#details#{j+1}", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(c.id.to_s)}/details"), :id=>"link#{j+1}#{count}"}}
+ = c.svg
%p= c.smiles
/ Measured Activity
diff --git a/views/predict.haml b/views/predict.haml
index 9a7d0d4..b7a4087 100644
--- a/views/predict.haml
+++ b/views/predict.haml
@@ -125,12 +125,12 @@
%br
%input{:type => 'text', :name => 'identifier', :id => 'identifier', :size => '60'}
%p
- %label{:for=>"fileselect"}
- or upload a CSV file for batch predictions
- %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"File format", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"auto", html:"true", content:"One column with compounds and keyword SMILES or InChI in the first row."}}
- %br
- %span.btn.btn-default.btn-file
- %input{:type=>"file", :name=> "fileselect", :id=>"fileselect", :accept=>"text/csv"}
+ -#%label{:for=>"fileselect"}
+ or upload a CSV file for batch predictions (disabled in public version)
+ -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"File format", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"auto", html:"true", content:"One column with compounds and keyword SMILES or InChI in the first row."}}
+ -#%br
+ -#%span.btn.btn-default.btn-file
+ %input{:type=>"file", :name=> "fileselect", :id=>"fileselect", :accept=>"text/csv", :disabled=>"disabled"}
%fieldset#middle.well
%h2 2. Select one or more endpoints
diff --git a/views/prediction.haml b/views/prediction.haml
index b090be5..362f006 100644
--- a/views/prediction.haml
+++ b/views/prediction.haml
@@ -1,10 +1,3 @@
-:javascript
- $(document).ready(function(){
- $('[data-toggle="popover"]').popover();
- $('.modal').on('hidden.bs.modal', function () {
- $(this).removeData('bs.modal');
- });
- });
%div.well
%a.btn.btn-warning{:href => to('/predict')}
%i.glyphicon.glyphicon-menu-left
@@ -16,7 +9,8 @@
%tbody
%tr
%td{:id=>"compound", :style=>"vertical-align:top;"}
- %p= @compound.svg
+ %a.btn.btn-link{:href => "#details0", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@compound.id.to_s)}/details"), :id=>"link01"}}
+ = @compound.svg
%p= @compound.smiles
- @model_types = {}
- @dbhit = {}
@@ -57,7 +51,7 @@
%p
%b Prediction:
/ prediction popover
- -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Prediction", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"<p>lazar searches the training dataset for similar compounds (neighbors) and calculates the prediction from their experimental activities.<p><b>Classification:</b></br>Majority vote of neighbor activities weighted by similarity.<p><b>Regression:</b></br>Prediction from a local partial least squares regression model with neighbor activities weighted by similarity.<p><a href=\"http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract\", target=\"_blank\"> Original publication</a>."}}
+ %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Prediction", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"<p>lazar searches the training dataset for similar compounds (neighbors) and calculates the prediction from their experimental activities.<p><b>Classification:</b></br>Majority vote of neighbor activities weighted by similarity.<p><b>Regression:</b></br>Prediction from a local partial least squares regression model with neighbor activities weighted by similarity.<p><a href=\"http://www.frontiersin.org/Journal/10.3389/fphar.2013.00038/abstract\", target=\"_blank\"> Original publication</a>."}}
%br
= (type == "Regression") ? "#{prediction[:value].delog10} (#{unit})</br>#{@compound.mmol_to_mg(prediction[:value].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:value]
@@ -67,20 +61,20 @@
%b 95% Prediction interval:
- interval = (prediction[:prediction_interval].nil? ? nil : prediction[:prediction_interval])
/ prediction interval popover
- -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Prediction intervall", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"An estimate of prediction uncertainty. The \"real\" value should be with 95% probability within the prediction interval."}}
+ %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Prediction intervall", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"An estimate of prediction uncertainty. The \"real\" value should be with 95% probability within the prediction interval."}}
%br
= interval.nil? ? "--" : "#{interval[1].delog10} - #{interval[0].delog10} (#{unit})"
%br
= "#{@compound.mmol_to_mg(interval[1].delog10)} - #{@compound.mmol_to_mg(interval[0].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" if !prediction[:prediction_interval].nil?
- else
%b Probability:
+ / probability popover
+ %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Confidence", :tabindex=>"0", data: {trigger:"focus", 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."}}
- unless prediction[:probabilities].nil?
%br
= "#{prediction[:probabilities].keys[0]}: #{prediction[:probabilities].values[0]}"
%br
= "#{prediction[:probabilities].keys[1]}: #{prediction[:probabilities].values[1]}"
- / probability popover
- -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Confidence", :tabindex=>"0", data: {trigger:"focus", 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."}}
/ show warnings
%p
@@ -94,4 +88,8 @@
/ always show the neighbors table, message is given there
= haml :neighbors, :layout => false, :model_type => @model_types, :dbhit => @dbhit
+
+%div.modal.fade{:id=>"details0", :role=>"dialog"}
+ %div.modal-dialog.modal-lg
+ %div.modal-content