summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgebele <gebele@in-silico.ch>2016-10-12 13:45:37 +0000
committergebele <gebele@in-silico.ch>2016-10-12 13:45:37 +0000
commit4b8e18a19f375b8d4c12621ec8f8f9ee305d11fa (patch)
tree6f11df8a79fc0c1b7a74e3adcc6a35ae157f4033
parentf4ec6a9bc42a1d6d3a2f136ddf50f3589a57c21b (diff)
stage save for transmission
-rw-r--r--Gemfile1
-rw-r--r--application.rb121
-rw-r--r--config.ru6
-rw-r--r--views/predict.haml52
-rw-r--r--views/prediction.haml25
5 files changed, 167 insertions, 38 deletions
diff --git a/Gemfile b/Gemfile
index a33d28e..7692587 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,7 @@
source "https://rubygems.org"
gemspec
gem "lazar", :path => "../lazar"
+gem "qsar-report", :path => "../qsar-report"
gem "sinatra"
gem 'sinatra-reloader', '~> 1.0'
gem "haml"
diff --git a/application.rb b/application.rb
index 29c1aca..a702d9a 100644
--- a/application.rb
+++ b/application.rb
@@ -1,9 +1,11 @@
+require 'qsar-report'
require 'rdiscount'
$ambit_search = "http://data.enanomapper.net/substance?type=name&search="
$npo_search = "http://bioportal.bioontology.org/search?q=%s&ontologies=NPO&include_properties=false&include_views=false&includeObsolete=false&require_definition=false&exact_match=false&categories="
+
configure :development do
- $logger = Logger.new(STDOUT)
+ #$logger = Logger.new(STDOUT)
end
before do
@@ -13,27 +15,111 @@ end
get '/?' do
redirect to('/predict')
end
-=begin
-get '/qsar-report/:id' do
+#=begin
+get '/qmrf-report/:id' do
+ prediction_model = OpenTox::Model::NanoPrediction.find(params[:id])
+ if prediction_model
+ model = prediction_model.model
+ model_type = "regression"
+ report = OpenTox::QMRFReport.new
+ if File.directory?("#{File.dirname(__FILE__)}/../../lazar")
+ lazar_commit = `cd #{File.dirname(__FILE__)}/../../lazar; git rev-parse HEAD`.strip
+ lazar_commit = "https://github.com/opentox/lazar/tree/#{lazar_commit}"
+ else
+ lazar_commit = "https://github.com/opentox/lazar/releases/tag/v#{Gem.loaded_specs["lazar"].version}"
+ end
+ report.value "QSAR_title", "Model for #{prediction_model.species} #{prediction_model.endpoint}"
+ report.change_catalog :software_catalog, :firstsoftware, {:name => "nano-lazar", :description => "nano-lazar toxicity predictions", :number => "1", :url => "https://nano-lazar.in-silico.ch", :contact => "helma@in-silico.ch"}
+ report.ref_catalog :QSAR_software, :software_catalog, :firstsoftware
+ report.value "qmrf_date", "#{Time.now.strftime('%d %B %Y')}"
+ report.change_catalog :authors_catalog, :firstauthor, {:name => "Christoph Helma", :affiliation => "in silico toxicology gmbh", :contact => "Rastatterstrasse 41, CH-4057 Basel, Switzerland", :email => "helma@in-silico.ch", :number => "1", :url => "http://in-silico.ch"}
+ report.ref_catalog :qmrf_authors, :authors_catalog, :firstauthor
+ report.change_catalog :authors_catalog, :modelauthor, {:name => "Christoph Helma", :affiliation => "in silico toxicology gmbh", :contact => "Contact Address", :email => "Contact Email", :number => "1", :url => "Web Page"}
+ report.ref_catalog :model_authors, :authors_catalog, :modelauthor
+ report.value "model_date", "#{Time.parse(model.created_at.to_s).strftime('%Y')}"
+ report.change_catalog :publications_catalog, :publications_catalog_1, {:title => "Rautenberg, Gebele and Helma (2013), Validation of read across predictions for nanoparticle toxicities ", :url => "in preparation"}
+ report.ref_catalog :references, :publications_catalog, :publications_catalog_1
+ report.value "model_species", prediction_model.species
+ report.change_catalog :endpoints_catalog, :endpoints_catalog_1, {:name => prediction_model.endpoint, :group => ""}
+ report.ref_catalog :model_endpoint, :endpoints_catalog, :endpoints_catalog_1
+ report.value "endpoint_units", "#{prediction_model.unit}"
+ report.value "algorithm_type", "#{model.class.to_s.gsub('OpenTox::Model::Lazar','')}"
+ #TODO add more
+ report.change_catalog :algorithms_catalog, :algorithms_catalog_1, {:definition => "see Helma 2016 and lazar.in-silico.ch, submitted version: #{lazar_commit}", :description => "Neighbor algorithm: #{model.neighbor_algorithm.gsub('_',' ').titleize}#{(model.neighbor_algorithm_parameters[:min_sim] ? ' with similarity > ' + model.neighbor_algorithm_parameters[:min_sim].to_s : '')}"}
+ report.ref_catalog :algorithm_explicit, :algorithms_catalog, :algorithms_catalog_1
+ report.change_catalog :algorithms_catalog, :algorithms_catalog_3, {:definition => "see Helma 2016 and lazar.in-silico.ch, submitted version: #{lazar_commit}", :description => "modified k-nearest neighbor #{model_type}"}
+ report.ref_catalog :algorithm_explicit, :algorithms_catalog, :algorithms_catalog_3
+ if model.prediction_algorithm_parameters
+ pred_algorithm_params = (model.prediction_algorithm_parameters[:method] == "rf" ? "random forest" : model.prediction_algorithm_parameters[:method])
+ end
+ report.change_catalog :algorithms_catalog, :algorithms_catalog_2, {:definition => "see Helma 2016 and lazar.in-silico.ch, submitted version: #{lazar_commit}", :description => "Prediction algorithm: #{model.prediction_algorithm.gsub('OpenTox::Algorithm::','').gsub('_',' ').gsub('.', ' with ')} #{(pred_algorithm_params ? pred_algorithm_params : '')}"}
+ report.ref_catalog :algorithm_explicit, :algorithms_catalog, :algorithms_catalog_2
+
+ # Descriptors in the model 4.3
+ if model.neighbor_algorithm_parameters[:type]
+ report.change_catalog :descriptors_catalog, :descriptors_catalog_1, {:description => "", :name => "#{model.neighbor_algorithm_parameters[:type]}", :publication_ref => "", :units => ""}
+ report.ref_catalog :algorithms_descriptors, :descriptors_catalog, :descriptors_catalog_1
+ end
+
+ # Descriptor selection 4.4
+ report.value "descriptors_selection", "#{model.feature_selection_algorithm.gsub('_',' ')} #{model.feature_selection_algorithm_parameters.collect{|k,v| k.to_s + ': ' + v.to_s}.join(', ')}" if model.feature_selection_algorithm
+ response['Content-Type'] = "application/xml"
+
+ return report.to_xml
+ else
+ bad_request_error "model with id: #{params[:id]} does not exist."
+ end
end
-=end
+#=end
get '/predict/?' do
+ # temporarily outstanding
+ nos = %w(S40.CIT
+ S40.MES
+ S40.MUTA
+ S40.cPEG5K-SH
+ S40.DDT@DOTAP
+ S40.MAA
+ S40.PLL-SH
+ S40.mPEG5K-SH
+ S40.MBA
+ S40.PVA
+ S40.LA
+ S40.AUT
+ S40.HDA
+ S40.SA
+ S40.nPEG5K-SH
+ S40.MHDA
+ )
@prediction_models = []
prediction_models = OpenTox::Model::NanoPrediction.all
prediction_models.each{|m| m.model[:feature_selection_algorithm_parameters]["category"] == "P-CHEM" ? @prediction_models[0] = m : @prediction_models[1] = m}
+ # define type (pc or pcp)
@prediction_models.each_with_index{|m,idx| idx == 0 ? m[:pc_model] = true : m[:pcp_model] = true}
-
# collect nanoparticles by training dataset (Ag + Au)
dataset = OpenTox::Dataset.find_by(:name=> "Protein Corona Fingerprinting Predicts the Cellular Interaction of Gold and Silver Nanoparticles")
- nanoparticles = dataset.nanoparticles
- # select physchem_parameters by relevant_features out of each model
- @@pc_relevant_features = @prediction_models[0].model.relevant_features.collect{|id, v| OpenTox::Feature.find(id)}
- @@pcp_relevant_features = @prediction_models[1].model.relevant_features.collect{|id, v| OpenTox::Feature.find(id)}
+ # temporarily delete silver
+ nanoparticles = dataset.nanoparticles#.delete_if{|n| !nos.include?(n.name)}
+
+ # select physchem_parameters by relevant_features out of each model; use @@ for global usage (prediction.haml)
+ @pc_relevant_features = @prediction_models[0].model.relevant_features.collect{|id, v| OpenTox::Feature.find(id)}
+ @pcp_relevant_features = @prediction_models[1].model.relevant_features.collect{|id, v| OpenTox::Feature.find(id)}
+ # check for outstanding nanoparticles
pcp = nanoparticles.sample
- pcp.physchem_descriptors.delete_if{|id,v| !@@pcp_relevant_features.include?(OpenTox::Feature.find(id))}
+ #while nos.include?(pcp.name)
+ # pcp = nanoparticles.sample
+ #end
+ # use only relevant features
+ pcp.physchem_descriptors.delete_if{|id,v| !@pcp_relevant_features.include?(OpenTox::Feature.find(id))}
@example_pcp = pcp
+
+ # check for outstanding nanoparticles
pc = nanoparticles.sample
- pc.physchem_descriptors.delete_if{|id,v| !@@pc_relevant_features.include?(OpenTox::Feature.find(id))}
+ #while nos.include?(pc.name)
+ # pcp = nanoparticles.sample
+ #end
+ # use only relevant features
+ #pc.physchem_descriptors.delete_if{|id,v| OpenTox::Feature.find(id).category != "P-CHEM"}
+ pc.physchem_descriptors.delete_if{|id,v| !@pc_relevant_features.include?(OpenTox::Feature.find(id))}
@example_pc = pc
haml :predict
@@ -45,7 +131,6 @@ get '/license' do
end
post '/predict/?' do
-
# choose the right prediction model
prediction_model = OpenTox::Model::NanoPrediction.find(params[:prediction_model])
size = params[:size].to_i
@@ -64,7 +149,13 @@ post '/predict/?' do
input_coating = in_coating
input_pc = {}
- (1..size).each{|i| input_pc["#{params["input_key_#{i}"]}"] = [params["input_value_#{i}"].to_f]}
+ (1..size).each{|i| input_pc["#{params["input_key_#{i}"]}"] = [params["input_value_#{i}"].to_f] unless params["input_value_#{i}"] == "-"}
+
+
+ # define relevant_features by input
+ @type = "pc" ? (@pc_relevant_features = input_pc.collect{|id,v| OpenTox::Feature.find(id)}) : (@pc_relevant_features = [])
+ @type = "pcp" ? (@pcp_relevant_features = input_pc.collect{|id,v| OpenTox::Feature.find(id)}) : (@pcp_relevant_features = [])
+
if input_pc == example_pc && input_core == example_core && input_coating == example_coating
# unchanged input = database hit
nanoparticle = OpenTox::Nanoparticle.find_by(:id => params[:example_id])
@@ -81,9 +172,9 @@ post '/predict/?' do
@match = false
@nanoparticle = nanoparticle
end
- # output
+ # prediction output
@input = input_pc
@prediction = prediction_model.model.predict_substance nanoparticle
-
+
haml :prediction
end
diff --git a/config.ru b/config.ru
index eec777d..36438a3 100644
--- a/config.ru
+++ b/config.ru
@@ -4,4 +4,10 @@ require 'bundler'
Bundler.require
require File.expand_path './application.rb'
require "sinatra/reloader" if development?
+
+FileUtils.mkdir_p 'log' unless File.exists?('log')
+log = File.new("log/nano-lazar.log", "a")
+$stdout.reopen(log)
+$stderr.reopen(log)
+
run Sinatra::Application
diff --git a/views/predict.haml b/views/predict.haml
index 1cd2916..0630b2c 100644
--- a/views/predict.haml
+++ b/views/predict.haml
@@ -14,7 +14,7 @@
= "#{idx+1}. #{m.model.feature_selection_algorithm_parameters[:category].nil? ? "Physchem & Proteomics" : "Physchem" }"
%div.tab-content
- @prediction_models.each_with_index do |m, idx|
- - m[:pc_model] ? (example = @example_pc; type = "pc") : (example = @example_pcp; type = "pcp")
+ - m[:pc_model] ? (example = @example_pc; type = "pc"; relevant_features = @pc_relevant_features) : (example = @example_pcp; type = "pcp"; relevant_features = @pcp_relevant_features)
#model.tab-pane{:id=>"#{idx}", :class => ("active" if idx == 0)}
%b Model:
%br
@@ -38,8 +38,20 @@
%br
Unit:
= m.unit
+ %br
+ Prediction algorithm:
+ = m.model.prediction_algorithm.split(".").last.gsub("_"," ")
+ %br
+ Prediction algorithm parameter:
+ = "random forest" if m.model.prediction_algorithm_parameters["method"] == "rf"
+ %br
+ Neighbor algorithm:
+ = m.model.neighbor_algorithm.gsub("_", " ")
+ %br
+ Neighbor algorithm parameter:
+ = "min sim = #{m.model.neighbor_algorithm_parameters["min_sim"]}"
%p
- - cv = OpenTox::CrossValidation.find(m.repeated_crossvalidation_id)
+ -#- cv = OpenTox::CrossValidation.find(m.repeated_crossvalidation_id)
%b Independent crossvalidations (log2 transformed):
- crossvalidations =[]
- m.repeated_crossvalidation.crossvalidation_ids.each{|cv| c = OpenTox::Validation::CrossValidation.find(cv); crossvalidations << c}
@@ -55,18 +67,18 @@
= "Num unpredicted"
= cv.nr_unpredicted
%br
- = "Root mean squared error:\t"
+ %a.ht5{:href=>"https://en.wikipedia.org/wiki/Root-mean-square_deviation", :rel=>"external"} RMSE:
= cv.rmse.round(3) if cv.rmse
%br
- = "Mean absolute error:\t"
+ %a.ht5{:href=>"https://en.wikipedia.org/wiki/Mean_absolute_error", :rel=>"external"} MAE:
= cv.mae.round(3) if cv.mae
%br
- = "R square:\t"
+ %a.ht5{:href=>"https://en.wikipedia.org/wiki/Coefficient_of_determination", :rel=>"external"}= "R"+"<sup>2</sup>"+":"
= cv.r_squared.round(3) if cv.r_squared
%br
- //%b QSAR report
- //%br
- //%a{:href=>to('/qsar-report/'+m.id)} download
+ %b QMRF report
+ %p
+ %a.btn.btn-default{:href=>to('/qmrf-report/'+m.id), :rel=>"external"} download
%hr
%form{:id=>idx, :role=>"form", :action=> to("/predict"), :method=>"post"}
%h3.help-block
@@ -79,13 +91,15 @@
%input{:id=>"example_core",:type=>"hidden",:name=>"example_core",:value=>"#{example.core}"}
%input{:id=>"example_coating",:type=>"hidden",:name=>"example_coating",:value=>"#{example.coating}"}
%input{:id=>"example_pc",:type=>"hidden",:name=>"example_pc",:value=>"#{example.physchem_descriptors}"}
- - size = example.physchem_descriptors.size
+ -#- size = example.physchem_descriptors.size
+ - size = relevant_features.size
%input{:id=>"size",:type=>"hidden",:name=>"size",:value=>size}
%input{:id=>"id",:type=>"hidden",:name=>"example_id",:value=>example.id}
// input form parameters to transfer
%div.form-group
%label{:for=>"selCore#{idx}"} Core
- %select.form-control{:id=>"selCore#{idx}", :name=>"input_core",:value=>example.core["name"]}
+ /%p= example.core["name"]
+ %select.form-control{:id=>"selCore#{idx}", :autocomplete=>"off", :name=>"input_core",:value=>example.core["name"]}
%option{:selected => ("selected" if example.core["name"] == "Ag")} Ag
%option{:selected => ("selected" if example.core["name"] == "Au")} Au
%input{:id=>"input_core",:type=>"hidden",:name=>"in_core",:value=>"#{example.core}"}
@@ -95,14 +109,20 @@
%input{:id=>"input_coating",:type=>"hidden",:name=>"in_coating",:value=>example.coating}
// prediction model id
%input{:id=>"prediction_model",:type=>"hidden",:name=>"prediction_model",:value=>m.id}
- - example.physchem_descriptors.sort_by{|d| OpenTox::Feature.find(d[0]).category}.each_with_index do |v,id|
- - feature = OpenTox::Feature.find_by(:id => v[0])
+ - relevant_features.sort_by{|d| d.category}.each_with_index do |relf,id|
+ -#- example.physchem_descriptors.sort_by{|d| OpenTox::Feature.find(d[0]).category}.each_with_index do |v,id|
+ - feature = relf
+ /%p= feature.id
+ - v = example.physchem_descriptors.find{|id,v| id == feature.id.to_s }
+ /%p= v
+ -#- feature = OpenTox::Feature.find_by(:id => v[0])
+ -#- feature = v
- name = feature.name
- if feature[:conditions] && !feature[:conditions]["MEDIUM"].blank?
- name = feature.name + " / " + feature[:conditions]["MEDIUM"]
- else
- name = feature.name
- - val = v[1]
+ - val = !v.nil? ? v[1] : "-"
- id = id + 1
- if feature.category == "Proteomics"
%h5
@@ -113,8 +133,10 @@
%h5
%a{:href=>$npo_search % string, :rel=>"external"}= name
// input physchem parameters
- %input.input-sm.form-control{:id=>id,:type=>"text",:name=>"input_value_#{id}",:value=>val[0]}
- %input{:id=>id,:type=>"hidden",:name=>"input_key_#{id}",:value=>v[0]}
+ %input.input-sm.form-control{:id=>id,:type=>"text",:name=>"input_value_#{id}",:value=>"#{val[0] if val[0]}", :disabled=>("disabled" if val[0] == "-")}
+ - if val[0] == "-"
+ %input{:id=>id,:type=>"hidden",:name=>"input_value_#{id}",:value=>"-"}
+ %input{:id=>id,:type=>"hidden",:name=>"input_key_#{id}",:value=>feature.id}
%hr
#predict
%button.btn.btn-success{:id=>"submitbutton", :type=>"submit", :onclick=>"showcircle();"}
diff --git a/views/prediction.haml b/views/prediction.haml
index 8f72a23..e6b4ae4 100644
--- a/views/prediction.haml
+++ b/views/prediction.haml
@@ -15,6 +15,8 @@
headerTemplate: '{content} {icon}',
widgets: ['uitheme', 'staticRow', 'stickyHeaders'],
widgetOptions: {
+ stickyHeaders_attachTo: 'neighbors',
+ stickyHeaders_offset: 0,
stickyHeaders_xScroll : null
},
sortList: [[1,1]],
@@ -41,7 +43,8 @@
Net cell association
%br
[mL/ug(Mg)]
- - @input.sort_by{|d| OpenTox::Feature.find(d[0]).category}.each do |key|
+ -#- @input.sort_by{|d| OpenTox::Feature.find(d[0]).category}.each do |key|
+ - @input.each{|d| OpenTox::Feature.find(d[0]).category}.each do |key|
- feature = OpenTox::Feature.find_by(:id=>key[0])
- name = feature.name
- if (feature[:conditions] && !feature[:conditions]["MEDIUM"].blank?)
@@ -88,12 +91,16 @@
%h5.th5 Prediction:
= @prediction[:value].round(3)
%br
- - if @prediction[:rmse]
+ - if @prediction[:value].blank?
+ %h5.th5 Prediction:
+ = "not available"
+ %br
+ -#- if @prediction[:rmse]
%h5.th5
%a{:href=>"https://en.wikipedia.org/wiki/Root-mean-square_deviation", :rel=>"external"} RMSE:
= @prediction[:rmse].round(3)
%br
- - if @prediction[:r_squared]
+ -#- if @prediction[:r_squared]
%h5.th5
%a{:href=>"https://en.wikipedia.org/wiki/Coefficient_of_determination", :rel=>"external"}= "R"+"<sup>2</sup>"+":"
= @prediction[:r_squared].round(3)
@@ -111,7 +118,8 @@
- if !@prediction[:value] && !@prediction[:measurements]
%h5.th5 not available
/ physchem
- - @input.sort_by{|d| OpenTox::Feature.find(d[0]).category}.each do |v|
+ -#- @input.sort_by{|d| OpenTox::Feature.find(d[0]).category}.each do |v|
+ - @input.each do |v|
%td.physchem
%div{:style=>"display:inline-block;padding-right:20px;"}
- if v[1].nil?
@@ -123,7 +131,7 @@
- if @prediction[:neighbors]
- @prediction[:neighbors].each_with_index do |neighbor,idx|
- nano = OpenTox::Nanoparticle.find(neighbor["_id"])
- - pc_descriptors = nano.physchem_descriptors.delete_if{|id,v| OpenTox::Feature.find(id).category != "P-CHEM"} if @type == "pc"
+ -#- nano.physchem_descriptors.delete_if{|id,v| OpenTox::Feature.find(id).category != "P-CHEM"} if @type == "pc"
%tr
/ ID
%td
@@ -144,8 +152,9 @@
%h5.th5 Measurement:
= neighbor["measurements"][0]
/ Physchem
- - nano.physchem_descriptors.delete_if{|id,v| @type == "pc" ? !@@pc_relevant_features.include?(OpenTox::Feature.find(id)) : !@@pcp_relevant_features.include?(OpenTox::Feature.find(id))}.sort_by{|id,v| OpenTox::Feature.find(id).category}.each do |k,v|
+ -#- nano.physchem_descriptors.delete_if{|id,v| @type == "pc" ? !@pc_relevant_features.include?(OpenTox::Feature.find(id)) : !@pcp_relevant_features.include?(OpenTox::Feature.find(id))}.sort_by{|id,v| OpenTox::Feature.find(id).category}.each do |k,v|
+ - nano.physchem_descriptors.delete_if{|id,v| @type == "pc" ? !@pc_relevant_features.include?(OpenTox::Feature.find(id)) : !@pcp_relevant_features.include?(OpenTox::Feature.find(id))}.sort_by{|id,v| @pc_relevant_features.index OpenTox::Feature.find(id)}.each do |k,v|
%td.physchem
- %div
+ -#%div
%div{:style=>"display:inline-block;padding-right:20px;"}
- = v[0].round(3) unless v.nil?
+ = v[0].round(3) unless v.nil?