summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgebele <gebele@in-silico.ch>2017-09-25 11:29:26 +0000
committergebele <gebele@in-silico.ch>2017-09-25 11:29:26 +0000
commite22513f460eeb42af5164537a7ecea9d21035cea (patch)
tree1a36c019ca4fce7e92c994ae9587f267b072974c
parent437b78faf4bcd820ea3193da18abf6b71eda8153 (diff)
before new batch
-rw-r--r--Gemfile2
-rw-r--r--VERSION2
-rw-r--r--application.rb268
-rw-r--r--helper.rb218
-rw-r--r--lazar-gui.gemspec2
-rw-r--r--views/batch.haml157
-rw-r--r--views/details.haml24
-rw-r--r--views/error.haml3
-rw-r--r--views/faq.haml2
-rw-r--r--views/faq_layout.haml67
-rw-r--r--views/license.haml1
-rw-r--r--views/model_details.haml284
-rw-r--r--views/neighbors.haml42
-rw-r--r--views/predict.haml83
-rw-r--r--views/prediction.haml190
-rw-r--r--views/significant_fragments.haml66
-rw-r--r--views/style.scss43
17 files changed, 646 insertions, 808 deletions
diff --git a/Gemfile b/Gemfile
index c86c89a..7b443e3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,8 @@
source "https://rubygems.org"
gemspec
gem "lazar", :path => "../lazar"
+gem "toxtree", :path => "../toxtree"
+gem "kazius-alerts", :path => "../kazius-alerts"
gem "gem-path"
gem "sinatra"
gem "sinatra-reloader"
diff --git a/VERSION b/VERSION
index ec63514..f599e28 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-9
+10
diff --git a/application.rb b/application.rb
index eefd833..70eecb5 100644
--- a/application.rb
+++ b/application.rb
@@ -1,38 +1,61 @@
-#require_relative 'helper.rb'
-require 'rdiscount'
include OpenTox
-configure :development do
+
+configure :production do
$logger = Logger.new(STDOUT)
+ enable :reloader
end
-helpers do
- class Numeric
- def percent_of(n)
- self.to_f / n.to_f * 100.0
- end
- end
-
+configure :development do
+ $logger = Logger.new(STDOUT)
+ enable :reloader
end
before do
@version = File.read("VERSION").chomp
end
+not_found do
+ redirect to('/predict')
+end
+
+error do
+ @error = request.env['sinatra.error']
+ haml :error
+end
+
+helpers do
+ def embedded_svg image, options={}
+ doc = Nokogiri::HTML::DocumentFragment.parse image
+ svg = doc.at_css 'svg'
+ title = doc.at_css 'title'
+ if options[:class].present?
+ svg['class'] = options[:class]
+ end
+ if options[:title].present?
+ title.children.remove
+ text_node = Nokogiri::XML::Text.new(options[:title], doc)
+ title.add_child(text_node)
+ end
+ doc.to_html.html_safe
+ end
+end
+
get '/?' do
redirect to('/predict')
end
get '/predict/?' do
- @models = OpenTox::Model::Prediction.all
+ @models = Model::Validation.all
@models = @models.delete_if{|m| m.model.name =~ /\b(Net cell association)\b/}
@endpoints = @models.collect{|m| m.endpoint}.sort.uniq
+ @endpoints << "Oral toxicity (Cramer rules)"
@models.count <= 0 ? (haml :info) : (haml :predict)
end
get '/predict/modeldetails/:model' do
- model = OpenTox::Model::Prediction.find params[:model]
- crossvalidations = OpenTox::Validation::RepeatedCrossValidation.find(model.repeated_crossvalidation_id).crossvalidations
+ model = Model::Validation.find params[:model]
+ crossvalidations = Validation::RepeatedCrossValidation.find(model.repeated_crossvalidation_id).crossvalidations
return haml :model_details, :layout=> false, :locals => {:model => model, :crossvalidations => crossvalidations}
end
@@ -48,43 +71,10 @@ get '/predict/dataset/:name' do
csv
end
-get '/predict/?:csv?' do
+get '/predict/:tmppath/:filename/?' do
response['Content-Type'] = "text/csv"
- @csv = "\"Compound\",\"Endpoint\",\"Type\",\"Prediction\",\"95% Prediction interval\"\n"
- @@batch.each do |key, values|
- compound = key
- smiles = compound.smiles
- values.each do |array|
- model = array[0]
- type = model.model.class.to_s.match("Classification") ? "Classification" : "Regression"
- prediction = array[1]
- endpoint = "#{model.endpoint.gsub('_', ' ')} (#{model.species})"
- if prediction[:confidence] == "measured"
- if prediction[:value].is_a?(Array)
- prediction[:value].each do |value|
- pred = value.numeric? ? "#{value} (#{model.unit}), #{compound.mmol_to_mg(value.delog10)} #{(model.unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : value
- int = (prediction[:prediction_interval].nil? ? nil : prediction[:prediction_interval])
- interval = (int.nil? ? "--" : "#{int[1].delog10} - #{int[0].delog10} (#{model.unit})")
- @csv += "\"#{smiles}\",\"#{endpoint}\",\"#{type}\",\"#{pred}\",\"#{interval}\"\n"
- end
- else
- pred = prediction[:value].numeric? ? "#{prediction[:value]} (#{model.unit}), #{compound.mmol_to_mg(prediction[:value].delog10)} #{(model.unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:value]
- confidence = "measured activity"
- end
- elsif prediction[:neighbors].size > 0
- type = model.model.class.to_s.match("Classification") ? "Classification" : "Regression"
- pred = prediction[:value].numeric? ? "#{prediction[:value].delog10} (#{model.unit}), #{compound.mmol_to_mg(prediction[:value].delog10)} #{(model.unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:value]
- int = (prediction[:prediction_interval].nil? ? nil : prediction[:prediction_interval])
- interval = (int.nil? ? "--" : "#{int[1].delog10} - #{int[0].delog10} (#{model.unit})")
- else
- type = ""
- pred = "Not enough similar compounds in training dataset."
- interval = ""
- end
- @csv += "\"#{smiles}\",\"#{endpoint}\",\"#{type}\",\"#{pred}\",\"#{interval}\"\n" unless prediction[:value].is_a?(Array)
- end
- end
- @csv
+ path = "/tmp/#{params[:tmppath]}"
+ send_file path, :filename => "lazar_batch_prediction_#{params[:filename]}", :type => "text/csv", :disposition => "attachment"
end
post '/predict/?' do
@@ -92,66 +82,196 @@ post '/predict/?' do
# process batch prediction
if !params[:fileselect].blank?
if params[:fileselect][:filename] !~ /\.csv$/
- @error_report = "Please submit a csv file."
- return haml :error
+ bad_request_error "Please submit a csv file."
end
File.open('tmp/' + params[:fileselect][:filename], "w") do |f|
f.write(params[:fileselect][:tempfile].read)
end
@filename = params[:fileselect][:filename]
begin
- input = OpenTox::Dataset.from_csv_file File.join("tmp", params[:fileselect][:filename]), true
+ input = Dataset.from_csv_file File.join("tmp", params[:fileselect][:filename]), true
if input.class == OpenTox::Dataset
- dataset = OpenTox::Dataset.find input
+ dataset = Dataset.find input
else
- @error_report = "Could not serialize file '#{@filename}' ."
- return haml :error
+ bad_request_error "Could not serialize file '#{@filename}'."
end
rescue
- @error_report = "Could not serialize file '#{@filename}' ."
- return haml :error
+ bad_request_error "Could not serialize file '#{@filename}'."
end
@compounds = dataset.compounds
if @compounds.size == 0
- @error_report = dataset[:warnings]
+ message = dataset[:warnings]
dataset.delete
- return haml :error
+ bad_request_error message
end
+
+ # for csv export
@batch = {}
- @compounds.each do |compound|
- @batch[compound] = []
- params[:selection].keys.each do |model_id|
- model = Model::Prediction.find model_id
+ # for haml table
+ @view = {}
+
+ @compounds.each{|c| @view[c] = []}
+ params[:selection].keys.each do |model_id|
+ model = Model::Validation.find model_id
+ @batch[model] = []
+ @compounds.each_with_index do |compound,idx|
prediction = model.predict(compound)
- @batch[compound] << [model, prediction]
+ @batch[model] << [compound, prediction]
+ @view[compound] << [model,prediction]
end
end
- @@batch = @batch
+
+ @csvhash = {}
@warnings = dataset[:warnings]
+ dupEntries = {}
+ delEntries = ""
+
+ # split duplicates and deleted entries
+ @warnings.each do |w|
+ substring = w.match(/line .* of/)
+ unless substring.nil?
+ delEntries += "\"#{w.sub(/\b(tmp\/)\b/,"")}\"\n"
+ end
+ substring = w.match(/rows .* Entries/)
+ unless substring.nil?
+ lines = []
+ substring[0].split(",").each{|s| lines << s[/\d+/]}
+ lines.shift
+ lines.each{|l| dupEntries[l.to_i] = w.split(".").first}
+ end
+ end
+
+ @batch.each_with_index do |hash, idx|
+ @csvhash[idx] = ""
+ model = hash[0]
+ # create header
+ if model.regression?
+ predAunit = "(#{model.unit})"
+ predBunit = "(#{model.unit =~ /mmol\/L/ ? "(mol/L)" : "(mg/kg_bw/day)"})"
+ @csvhash[idx] = "\"ID\",\"Endpoint\",\"Type\",\"Unique SMILES\",\"Prediction #{predAunit}\",\"Prediction #{predBunit}\",\"95% Prediction interval (low) #{predAunit}\",\"95% Prediction interval (high) #{predAunit}\",\"95% Prediction interval (low) #{predBunit}\",\"95% Prediction interval (high) #{predBunit}\",\"inApplicabilityDomain\",\"inTrainningSet\",\"Note\"\n"
+ else #classification
+ av = model.prediction_feature.accept_values
+ probFirst = av[0].capitalize
+ probLast = av[1].capitalize
+ @csvhash[idx] = "\"ID\",\"Endpoint\",\"Type\",\"Unique SMILES\",\"Prediction\",\"predProbability#{probFirst}\",\"predProbability#{probLast}\",\"inApplicabilityDomain\",\"inTrainningSet\",\"Note\"\n"
+ end
+ values = hash[1]
+ dupEntries.keys.each{|k| values.insert(k-1, dupEntries[k])}.compact!
+
+ values.each_with_index do |array, id|
+ type = (model.regression? ? "Regression" : "Classification")
+ endpoint = "#{model.endpoint.gsub('_', ' ')} (#{model.species})"
+
+ if id == 0
+ @csvhash[idx] += delEntries unless delEntries.blank?
+ end
+ unless array.kind_of? String
+ compound = array[0]
+ prediction = array[1]
+ smiles = compound.smiles
+
+ if prediction[:neighbors]
+ if prediction[:value]
+ pred = prediction[:value].numeric? ? "#{prediction[:value].delog10.signif(3)}" : prediction[:value]
+ predA = prediction[:value].numeric? ? "#{prediction[:value].delog10.signif(3)}" : prediction[:value]
+ predAunit = prediction[:value].numeric? ? "(#{model.unit})" : ""
+ predB = prediction[:value].numeric? ? "#{compound.mmol_to_mg(prediction[:value].delog10).signif(3)}" : prediction[:value]
+ predBunit = prediction[:value].numeric? ? "#{model.unit =~ /\b(mmol\/L)\b/ ? "(mg/L)" : "(mg/kg_bw/day)"}" : ""
+ int = (prediction[:prediction_interval].nil? ? nil : prediction[:prediction_interval])
+ intervalLow = (int.nil? ? "" : "#{int[1].delog10.signif(3)}")
+ intervalHigh = (int.nil? ? "" : "#{int[0].delog10.signif(3)}")
+ intervalLowMg = (int.nil? ? "" : "#{compound.mmol_to_mg(int[1].delog10).signif(3)}")
+ intervalHighMg = (int.nil? ? "" : "#{compound.mmol_to_mg(int[0].delog10).signif(3)}")
+ inApp = "yes"
+ inT = prediction[:info] =~ /\b(identical)\b/i ? "yes" : "no"
+ note = prediction[:warnings].join("\n") + ( prediction[:info] ? prediction[:info].sub(/\'.*\'/,"") : "\n" )
+
+ unless prediction[:probabilities].nil?
+ av = model.prediction_feature.accept_values
+ propA = "#{prediction[:probabilities][av[0]].to_f.signif(3)}"
+ propB = "#{prediction[:probabilities][av[1]].to_f.signif(3)}"
+ end
+ else
+ # no prediction value only one neighbor
+ inApp = "no"
+ inT = prediction[:info] =~ /\b(identical)\b/i ? "yes" : "no"
+ note = prediction[:warnings].join("\n") + ( prediction[:info] ? prediction[:info].sub(/\'.*\'/,"") : "\n" )
+ end
+ else
+ # no prediction value
+ inApp = "no"
+ inT = prediction[:info] =~ /\b(identical)\b/i ? "yes" : "no"
+ note = prediction[:warnings].join("\n") + ( prediction[:info] ? prediction[:info].sub(/\'.*\'/,"") : "\n" )
+ end
+ if @warnings
+ @warnings.each do |w|
+ note += (w.split(".").first + ".") if /\b(#{Regexp.escape(smiles)})\b/ === w
+ end
+ end
+ else
+ # string note for duplicates
+ endpoint = type = smiles = pred = predA = predB = propA = propB = intervalLow = intervalHigh = intervalLowMg = intervalHighMg = inApp = inT = ""
+ note = array
+ end
+ if model.regression?
+ @csvhash[idx] += "\"#{id+1}\",\"#{endpoint}\",\"#{type}\",\"#{smiles}\",\"#{predA}\",\"#{predB}\",\"#{intervalLow}\",\"#{intervalHigh}\",\"#{intervalLowMg}\",\"#{intervalHighMg}\",\"#{inApp}\",\"#{inT}\",\"#{note.chomp}\"\n"
+ else
+ @csvhash[idx] += "\"#{id+1}\",\"#{endpoint}\",\"#{type}\",\"#{smiles}\",\"#{pred}\",\"#{propA}\",\"#{propB}\",\"#{inApp}\",\"#{inT}\",\"#{note.chomp}\"\n"
+ end
+ end
+ end
+ t = Tempfile.new
+ @csvhash.each do |model, csv|
+ t.write(csv)
+ t.write("\n")
+ end
+ t.rewind
+ @tmppath = t.path.split("/").last
+
dataset.delete
File.delete File.join("tmp", params[:fileselect][:filename])
return haml :batch
end
# validate identifier input
- # transfered input
if !params[:identifier].blank?
@identifier = params[:identifier]
$logger.debug "input:#{@identifier}"
# get compound from SMILES
@compound = Compound.from_smiles @identifier
- if @compound.blank?
- @error_report = "'#{@identifier}' is not a valid SMILES string."
- return haml :error
- end
-
+ bad_request_error "'#{@identifier}' is not a valid SMILES string." if @compound.blank?
+
@models = []
@predictions = []
+ @toxtree = false
params[:selection].keys.each do |model_id|
- model = Model::Prediction.find model_id
- @models << model
- @predictions << model.predict(@compound)
+ if model_id == "Cramer"
+ @toxtree = true
+ @predictions << [Toxtree.predict(@compound.smiles, "Cramer rules"), Toxtree.predict(@compound.smiles, "Cramer rules with extensions")]
+ else
+ model = Model::Validation.find model_id
+ @models << model
+ if model.model.name =~ /kazius/
+ sa_prediction = KaziusAlerts.predict(@compound.smiles)
+ lazar_mutagenicity = model.predict(@compound)
+ confidence = 0
+ lazar_mutagenicity_val = (lazar_mutagenicity[:value] == "non-mutagenic" ? false : true)
+ if sa_prediction[:prediction] == false && lazar_mutagenicity_val == false
+ confidence = 0.85
+ elsif sa_prediction[:prediction] == true && lazar_mutagenicity_val == true
+ confidence = 0.85 * ( 1 - sa_prediction[:error_product] )
+ elsif sa_prediction[:prediction] == false && lazar_mutagenicity_val == true
+ confidence = 0.11
+ elsif sa_prediction[:prediction] == true && lazar_mutagenicity_val == false
+ confidence = ( 1 - sa_prediction[:error_product] ) - 0.57
+ end
+ @predictions << [lazar_mutagenicity, {:prediction => sa_prediction, :confidence => confidence}]
+ else
+ @predictions << model.predict(@compound)
+ end
+ end
end
+
haml :prediction
end
end
diff --git a/helper.rb b/helper.rb
deleted file mode 100644
index caa1923..0000000
--- a/helper.rb
+++ /dev/null
@@ -1,218 +0,0 @@
-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/lazar-gui.gemspec b/lazar-gui.gemspec
index 6f58687..592d929 100644
--- a/lazar-gui.gemspec
+++ b/lazar-gui.gemspec
@@ -14,6 +14,8 @@ Gem::Specification.new do |s|
s.files = `git ls-files`.split("\n")
s.add_runtime_dependency "lazar"
+ s.add_runtime_dependency "toxtree"
+ s.add_runtime_dependency "kazius-alerts"
s.add_runtime_dependency "gem-path", "~> 0.6.1", '>= 0.6.1'
s.add_runtime_dependency "sinatra", "~> 1.4.0", '>= 1.4.0'
s.add_runtime_dependency "rdiscount", "~> 2.1.0", '>= 2.1.0'
diff --git a/views/batch.haml b/views/batch.haml
index 6c37a2b..0e7efc7 100644
--- a/views/batch.haml
+++ b/views/batch.haml
@@ -2,11 +2,11 @@
%a.btn.btn-warning{:href => to('/predict')}
%span.glyphicon.glyphicon-menu-left{:aria=>{:hidden=>"true"}}
New Prediction
- %a.btn.btn-success{:href=>"#{to("/predict/#{@filename}")}", :title=>"download"}
+ %a.btn.btn-success{:id => "downbutton", :href=>"#{to("/predict/#{@tmppath}/#{@filename}")}", :title=>"download"}
%span.glyphicon.glyphicon-download-alt
- download CSV
+ Download CSV
- / show processed file name
+ / show file name
%topline
%div.row
%div.col-md-4
@@ -18,83 +18,92 @@
%div.table-responsive
%table.table.table-bordered{:id=>"batch", :style=>"background-color:white;"}
%tbody
- - if @warnings
- - @warnings.each do |warning|
+ - if @warnings
+ - @warnings.each do |warning|
+ %tr
+ %td
+ %b Warning
+ %td
+ = warning.sub(/\b(tmp\/)\b/,"")
+ - @view.each do |compound, array|
%tr
- %td
- %b Warning
- %td
- = warning.sub(/\b(tmp\/)\b/,"")
- / key = compound, values = [model,prediction]
- - @batch.each do |key, values|
- - compound = key
- %tr
- %td{:style=>"vertical-align:top;"}
- %p= compound.svg
- %p= compound.smiles
-
- / array[0] = model, array[1] = prediction
- - values.each_with_index do |array,i|
- %td{:style=>"vertical-align:top;white-space:nowrap;"}
- - model = array[0]
- / model type (classification|regression)
- - model.model.class.to_s.match("Classification") ? type = "Classification" : type = "Regression"
- - unit = model.unit
- - prediction = array[1]
-
- %b{:class => "title"}
- = "#{model.endpoint.gsub('_', ' ')} (#{model.species})"
-
- / check for prediction
- - if prediction[:neighbors].size > 0
- %p
- / show model type (classification|regression)
- %b Type:
- = type
- %p
- / check for database hit
- - if prediction[:warning] =~ /\b(identical)\b/i
-
- / show message about dbhit and measurements
+ %td{:style=>"vertical-align:top;"}
+ %p= compound.svg
+ %p= compound.smiles
+ - array.each do |model,prediction|
+ %td{:style=>"vertical-align:top;white-space:nowrap;"}
+ - model.model.class.to_s.match("Classification") ? type = "Classification" : type = "Regression"
+ - unit = model.unit
+
+ %b{:class => "title"}
+ = "#{model.endpoint.gsub('_', ' ')} (#{model.species})"
+
+ / check for prediction
+ - if prediction[:value]
%p
- %b Compound is part of the training dataset
+ / show model type (classification|regression)
+ %b Type:
+ = type
+ %p
+ / check for database hit
+ - if prediction[:info] =~ /\b(identical)\b/i
+
+ / show message about dbhit and measurements
%p
- %b Measured activity:
+ %b Compound is part of the training dataset
+ %p
+ %b Measured activity:
+ %br
+ - if prediction[:measurements].is_a?(Array)
+ = (type == "Regression") ? prediction[:measurements].collect{|value| "#{value.delog10.signif(3)} (#{unit})</br>#{compound.mmol_to_mg(value.delog10).signif(3)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("</br>") : prediction[:measurements].join(", ")
+ - else
+ = (type == "Regression") ? "#{prediction[:measurements].delog10.signif(3)} (#{unit})</br>#{compound.mmol_to_mg(prediction[:measurements].delog10).signif(3)} #{(unit =~ /\b(mmol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:measurements]
+
+
+ / show prediction
+ %p
+ %b Prediction:
%br
- - if prediction[:measurements].is_a?(Array)
- = (type == "Regression") ? prediction[:measurements].collect{|value| "#{value.delog10} (#{unit})</br>#{compound.mmol_to_mg(value.delog10)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("</br>") : prediction[:measurements].join(", ")
+ = (type == "Regression") ? "#{prediction[:value].delog10.signif(3)} (#{unit})</br>#{compound.mmol_to_mg(prediction[:value].delog10).signif(3)} #{(unit =~ /\b(mmol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:value]
+
+ / show prediction interval or probability
+ %p
+ - if type == "Regression"
+ %b 95% Prediction interval:
+ - interval = (prediction[:prediction_interval].nil? ? nil : prediction[:prediction_interval])
+ %br
+ = interval.nil? ? "" : "#{interval[1].delog10.signif(3)} - #{interval[0].delog10.signif(3)} (#{unit})"
+ %br
+ = "#{compound.mmol_to_mg(interval[1].delog10).signif(3)} - #{compound.mmol_to_mg(interval[0].delog10).signif(3)} #{(unit =~ /\b(mmol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" if !prediction[:prediction_interval].nil?
- else
- = (type == "Regression") ? "#{prediction[:measurements].delog10} (#{unit})</br>#{compound.mmol_to_mg(prediction[:measurements].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:measurements]
-
-
- / show prediction
- %p
- %b Prediction:
- %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]
-
- / show prediction interval or probability
+ %b Probability:
+ - unless prediction[:probabilities].nil?
+ - probabilities = ""
+ - prediction[:probabilities].each{|k,v| probabilities += "#{k}: #{v.signif(3)}<br>"}
+ %br
+ = probabilities
+ / show warnings
%p
- - if type == "Regression"
- %b 95% Prediction interval:
- - interval = (prediction[:prediction_interval].nil? ? nil : prediction[:prediction_interval])
+ - if !prediction[:info].blank?
+ %b Info:
%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:
- - unless prediction[:probabilities].nil?
+ %p=prediction[:info].sub(/\'.*\'/,"").sub(/,/, ",<br>")
+ - if !prediction[:warnings].blank?
+ %b Warnings:
+ - prediction[:warnings].uniq.each do |warning|
%br
- = "#{prediction[:probabilities].keys[0]}: #{prediction[:probabilities].values[0]}"
+ %p=warning.sub(/substances/, "substances<br>").sub(/prediction\:/, "prediction\:<br>")
+
+ / no prediction
+ - else
+ %br
+ - if !prediction[:info].blank?
+ %b Info:
+ %br
+ %p=prediction[:info].sub(/\'.*\'/,"").sub(/,/, ",<br>")
+ - if !prediction[:warnings].blank?
+ %b Warnings:
+ - prediction[:warnings].uniq.each do |warning|
%br
- / show warnings
- %p
- - if !prediction[:warning].nil?
- %b Warnings:
- %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Warnings", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"#{prediction[:warning]}"}}
-
- / no prediction
- - else
- %p
- = "Not enough similar compounds </br>in training dataset."
+ %p=warning.sub(/substances/, "substances<br>").sub(/prediction\:/, "prediction\:<br>")
+ %tr
diff --git a/views/details.haml b/views/details.haml
deleted file mode 100644
index bb8250d..0000000
--- a/views/details.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-%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
- %b="SMILES:"
- %p= @smiles
- %br
- %b="InChI:"
- %p= @inchi
- %br
- %b="Names:"
- %p{:style=>"padding-left:0.5em;"}
- - if @names !~ /^no names/i
- = @names.join("; ")
- - else
- = @names
- %hr
- %p{:style=>"padding-left:0.5em;"}
- / pubchem link
- %a.btn.btn-primary{:href=>"http://aop.in-silico.ch/", :title=>"Link opens in new window.", :alt=>"pubchem read across", :rel=>"external"} PubChem read across
- %i (experimental)
- %br
diff --git a/views/error.haml b/views/error.haml
index 555982b..05cb0da 100644
--- a/views/error.haml
+++ b/views/error.haml
@@ -4,5 +4,4 @@
Back
%hr
%div.well{:style=>"width:100%;margin-bottom:2em;"}
- = @error_report
-
+ = @error
diff --git a/views/faq.haml b/views/faq.haml
deleted file mode 100644
index 818b96a..0000000
--- a/views/faq.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-%div.well.faq
- = @faq
diff --git a/views/faq_layout.haml b/views/faq_layout.haml
deleted file mode 100644
index a9b6664..0000000
--- a/views/faq_layout.haml
+++ /dev/null
@@ -1,67 +0,0 @@
-!!!
-%html{:xmlns => "http://www.w3.org/1999/xhtml", "xml:lang" => "en", :lang => "en"}
- %head
- %meta{'charset'=>"utf-8"}
- %meta{'http-equiv'=>"X-UA-Compatible", :content=>"IE=edge"}
- %meta{'name'=>"viewport", :content=>"width=device-width, initial-scale=1"}
- %title Lazar GUI FAQ
- %link{:rel=>'icon', :type=>'image/x-icon', :href=>'/images/favicon.ico'}
- %link{:rel=>'stylesheet', :href=>"#{'/css/bootstrap.min.css'}"}
- %link{:rel=>'stylesheet', :href=>"#{'/css/theme.default.min.css'}"}
- %link{:rel=>'stylesheet', :href=>"#{'/css/theme.bootstrap.min.css'}"}
- %link{ :href=>"/style.css", :rel=>"stylesheet"}
- %link{ :href=>"/stylesheets/jquery-ui.css", :rel=>"stylesheet"}
- %script{:src=>"/javascripts/jquery-1.11.2.min.js"}
- %script{:src=>"/javascripts/bootstrap.min.js"}
- %script{ :src=>"/javascripts/lazar-gui.js"}
- %body
- %noscript
- %div{ :style=>"width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif"}
- Your web browser must have JavaScript enabled in order for this application to display correctly.
- %header.page-header
- %div.row
- %div.col-md-2
- %a{:href=> to("/predict")}
- %img.media-object{:src=>"/images/ist_logo.png", :alt=>"logo", :style=>"margin:0 3em 0 2em;"}
- %div.col-md-10
- %h1.media-heading{:style=>"margin: 0 0 0 1em;display:inline;"} Lazar GUI
- A Graphical User Interface for the <a href="http://github.com/opentox/lazar">Lazar</a> framework
-
- %div.container-fluid
- :javascript
- $(document).ready(function(){
- $("#back-top").hide();
- $(".blind").error(function(){
- $(this).attr('src', '/images/blind.png');
- });
- });
-
- = yield
-
- %footer.footer
- %div.container-fluid
- %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}
-
- #back-top{:style => "z-index:100;position:fixed;bottom:1%;right:1%;"}
- %a{:href => "", :style=>"text:decoration:none;color:#ccc;"}
- %span.glyphicon.glyphicon-circle-arrow-up{:style => "font-size:3em;color:black;"}
- :javascript
- $("#back-top").hide();
- $(function () {
- $(window).scroll(function () {
- if ($(this).scrollTop() > 600) {
- $('#back-top').fadeIn();
- } else {
- $('#back-top').fadeOut();
- }
- });
- // scroll body to 0px on click
- $('#back-top a').click(function () {
- $('body,html').animate({
- scrollTop: 0
- }, 500);
- return false;
- });
- });
diff --git a/views/license.haml b/views/license.haml
deleted file mode 100644
index 2813220..0000000
--- a/views/license.haml
+++ /dev/null
@@ -1 +0,0 @@
-= @license
diff --git a/views/model_details.haml b/views/model_details.haml
index 3fa8c8b..f1d5f9d 100644
--- a/views/model_details.haml
+++ b/views/model_details.haml
@@ -1,139 +1,149 @@
-%b Model:
-%br
-Source:
-%a{:href=>model.source, :rel=>"external"}
- = model.source
-%br
-- model.classification? ? type = "Classification" : type = "Regression"
-= "Type:\t"
-= type
-%br
-- training_dataset = OpenTox::Dataset.find model.model.training_dataset_id
-= "Training compounds:\t"
-= training_dataset.compounds.size
-%br
-= "Training dataset:\t"
-%a{:href=>"#{to("/predict/dataset/#{training_dataset.name}")}"}
- = training_dataset.name
-%br
-%b Algorithms:
-%br
-Similarity:
-%a{:href=> "http://www.rubydoc.info/gems/lazar/OpenTox%2F#{model.model.algorithms["similarity"]["method"].sub("::", "%2F")}", :rel=>"external"}
- = model.model.algorithms["similarity"]["method"]
-= ", min: #{model.model.algorithms["similarity"]["min"]}"
-%br
-Prediction:
-%a{:href=>"http://www.rubydoc.info/gems/lazar/OpenTox%2F#{model.model.algorithms["prediction"]["method"].sub("::","%2f")}", :rel=>"external"}
- = model.model.algorithms["prediction"]["method"]
-%br
-Descriptors:
-= model.model.algorithms["descriptors"]["method"]+","
-= model.model.algorithms["descriptors"]["type"]
-%p
-- if type == "Classification"
- %b Independent crossvalidations:
-- else
- %b Independent crossvalidations (-log10 transformed):
-%div.row{:id=>"validations#{model.id}", :style=>"background-color:#f5f5f5;"}
- - crossvalidations.each do |cv|
- %span.col-xs-4.col-sm-4.col-md-4.col-lg-4
- = "Num folds:\t"
- = cv.folds
- %br
- = "Num instances:\t"
- = cv.nr_instances
- %br
- = "Num unpredicted"
- = cv.nr_unpredicted
- - if model.classification?
- %br
- = "Accuracy:\t"
- = cv.accuracy.round(3) if cv.accuracy
- %br
- = "Weighted accuracy:\t"
- = cv.weighted_accuracy.round(3) if cv.weighted_accuracy
- %br
- = "True positive rate:\t"
- = cv.true_rate["active"].round(3) if cv.true_rate
- %br
- = "True negative rate:\t"
- = cv.true_rate["inactive"].round(3) if cv.true_rate
- %br
- = "Positive predictive value:\t"
- = cv.predictivity["active"].round(3) if cv.predictivity
- %br
- = "Negative predictive value:\t"
- = cv.predictivity["inactive"].round(3) if cv.predictivity
- %p
- - ["confusion_matrix", "weighted_confusion_matrix"].each_with_index do |matrix,idx|
- %b= (idx == 0 ? "Confusion Matrix" : "Weighted Confusion Matrix")
- %table.table.table-condensed.table-borderless{:style=>"width:20%;"}
- %tbody
- %tr
- %td
- %td
- %td
- %b actual
- %td
- %td
- %tr
- %td
- %td
- %td active
- %td inactive
- -#%td total
- %tr
- %td
- %b predicted
- %td active
- %td
- =( idx == 1 ? cv.send(matrix)[0][0].round(3) : cv.send(matrix)[0][0])
- %td
- =( idx == 1 ? cv.send(matrix)[0][1].round(3) : cv.send(matrix)[0][1])
- -#%td
- =cv.confusion_matrix[0][0]+cv.confusion_matrix[0][1]
- %tr
- %td
- %td inactive
- %td
- =( idx == 1 ? cv.send(matrix)[1][0].round(3) : cv.send(matrix)[1][0])
- %td
- =( idx == 1 ? cv.send(matrix)[1][1].round(3) : cv.send(matrix)[1][1])
- -#%td
- =cv.confusion_matrix[1][0]+cv.confusion_matrix[1][1]
- -#%tr
- %td
- %td total
- %td
- =cv.confusion_matrix[0][0]+cv.confusion_matrix[1][0]
- %td
- =cv.confusion_matrix[0][1]+cv.confusion_matrix[1][1]
- %td
- -#= "Confusion Matrix:\t"
- -#= cv.confusion_matrix
+%div.panel.panel-default
+ %div.panel-heading
+ %b Model:
+ %div.panel-body
+ Source:
+ %a{:href=>model.source, :rel=>"external"}
+ = model.source
+ %br
+ - model.classification? ? type = "Classification" : type = "Regression"
+ = "Type:\t"
+ = type
+ %br
+ - training_dataset = OpenTox::Dataset.find model.model.training_dataset_id
+ = "Training compounds:\t"
+ = training_dataset.data_entries.size
+ %br
+ = "Training dataset:\t"
+ %a{:href=>"#{to("/predict/dataset/#{training_dataset.name}")}"}
+ = training_dataset.name
+
+%div.panel.panel-default
+ %div.panel-heading
+ %b Algorithms:
+ %div.panel-body
+ Similarity:
+ %a{:href=> "http://www.rubydoc.info/gems/lazar/OpenTox%2F#{model.model.algorithms["similarity"]["method"].sub("::", "%2F")}", :rel=>"external"}
+ = model.model.algorithms["similarity"]["method"]
+ = ", min: #{model.model.algorithms["similarity"]["min"]}"
+ %br
+ Prediction:
+ %a{:href=>"http://www.rubydoc.info/gems/lazar/OpenTox%2F#{model.model.algorithms["prediction"]["method"].sub("::","%2f")}", :rel=>"external"}
+ = model.model.algorithms["prediction"]["method"]
+ %br
+ Descriptors:
+ = model.model.algorithms["descriptors"]["method"]+","
+ = model.model.algorithms["descriptors"]["type"]
+
+%div.panel.panel-default
+ - if type == "Classification"
+ %div.panel-heading
+ %b Independent crossvalidations:
+ - else
+ %div.panel-heading
+ %b Independent crossvalidations (-log10 transformed):
+ %div.panel-body
+ /%div.row{:id=>"validations#{model.id}", :style=>"background-color:#f5f5f5;"}
+ %div.row{:id=>"validations#{model.id}"}
+ - crossvalidations.each do |cv|
+ %span.col-xs-4.col-sm-4.col-md-4.col-lg-4
+ = "Num folds:\t"
+ = cv.folds
+ %br
+ = "Num instances:\t"
+ = cv.nr_instances
+ %br
+ = "Num unpredicted"
+ = cv.nr_unpredicted
+ - if model.classification?
+ %br
+ = "Accuracy:\t"
+ = cv.accuracy.round(3) if cv.accuracy
+ %br
+ = "Weighted accuracy:\t"
+ = cv.weighted_accuracy.round(3) if cv.weighted_accuracy
+ - if cv.true_rate
%br
- %br
- /= "Confidence plot:"
- /%p.plot
- / %img{:src=>"confp#{cv.id}.svg"}
- - if model.regression?
- %br
- %a.ht5{:href=>"https://en.wikipedia.org/wiki/Root-mean-square_deviation", :rel=>"external"} RMSE:
- = cv.rmse.round(3) if cv.rmse
- %br
- %a.ht5{:href=>"https://en.wikipedia.org/wiki/Mean_absolute_error", :rel=>"external"} MAE:
- = cv.mae.round(3) if cv.mae
- %br
- %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
- /= "Confidence plot:"
- /%p.plot
- / %img{:src=>"/confp#{cv.id}.svg"}
- /%br
- /= "Correlation plot"
- /%p.plot
- / %img{:src=>"/corrp#{cv.id}.svg"}
+ = "True positive rate:\t"
+ = cv.true_rate[cv.accept_values[0]].round(3)
+ %br
+ = "True negative rate:\t"
+ = cv.true_rate[cv.accept_values[1]].round(3)
+ - if cv.predictivity
+ %br
+ = "Positive predictive value:\t"
+ = cv.predictivity[cv.accept_values[0]].round(3)
+ %br
+ = "Negative predictive value:\t"
+ = cv.predictivity[cv.accept_values[1]].round(3)
+ %p
+ - ["confusion_matrix", "weighted_confusion_matrix"].each_with_index do |matrix,idx|
+ %b= (idx == 0 ? "Confusion Matrix" : "Weighted Confusion Matrix")
+ %table.table.table-condensed.table-borderless{:style=>"width:20%;"}
+ %tbody
+ %tr
+ %td
+ %td
+ %td
+ %b actual
+ %td
+ %td
+ %tr
+ %td
+ %td
+ %td active
+ %td inactive
+ -#%td total
+ %tr
+ %td
+ %b predicted
+ %td active
+ %td
+ =( idx == 1 ? cv.send(matrix)[0][0].round(3) : cv.send(matrix)[0][0])
+ %td
+ =( idx == 1 ? cv.send(matrix)[0][1].round(3) : cv.send(matrix)[0][1])
+ -#%td
+ =cv.confusion_matrix[0][0]+cv.confusion_matrix[0][1]
+ %tr
+ %td
+ %td inactive
+ %td
+ =( idx == 1 ? cv.send(matrix)[1][0].round(3) : cv.send(matrix)[1][0])
+ %td
+ =( idx == 1 ? cv.send(matrix)[1][1].round(3) : cv.send(matrix)[1][1])
+ -#%td
+ =cv.confusion_matrix[1][0]+cv.confusion_matrix[1][1]
+ -#%tr
+ %td
+ %td total
+ %td
+ =cv.confusion_matrix[0][0]+cv.confusion_matrix[1][0]
+ %td
+ =cv.confusion_matrix[0][1]+cv.confusion_matrix[1][1]
+ %td
+ -#= "Confusion Matrix:\t"
+ -#= cv.confusion_matrix
+ %br
+ %br
+ /= "Confidence plot:"
+ /%p.plot
+ / %img{:src=>"confp#{cv.id}.svg"}
+ - if model.regression?
+ %br
+ %a.ht5{:href=>"https://en.wikipedia.org/wiki/Root-mean-square_deviation", :rel=>"external"} RMSE:
+ = cv.rmse.round(3) if cv.rmse
+ %br
+ %a.ht5{:href=>"https://en.wikipedia.org/wiki/Mean_absolute_error", :rel=>"external"} MAE:
+ = cv.mae.round(3) if cv.mae
+ %br
+ %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
+ /= "Confidence plot:"
+ /%p.plot
+ / %img{:src=>"/confp#{cv.id}.svg"}
+ /%br
+ /= "Correlation plot"
+ /%p.plot
+ / %img{:src=>"/corrp#{cv.id}.svg"}
-%br
diff --git a/views/neighbors.haml b/views/neighbors.haml
index 32b8389..9c12be9 100644
--- a/views/neighbors.haml
+++ b/views/neighbors.haml
@@ -1,38 +1,19 @@
-/ unpacks multi prediction array ;
-/ prepare it for neighbors ;
-/ align single prediction to endpoint ;
-/ display preordered in table view ;
-
%div.results
%h3 Neighbors:
/ tabs div
#tabs
%ul.nav.nav-tabs.nav-justified{:id=>"neighborTabs", :role=>"tablist"}
- / each model a tab head ;
- / hash for predictionFeature
- - predictionFeature = {}
- @models.each_with_index do |model,i|
/ get predictionFeature type
- m = Model::Lazar.find model.model_id.to_s
- - predFeature = Feature.find m.prediction_feature_id.to_s
- / define feature type (numeric : nominal)
- - predFeatureType = (predFeature.numeric? ? "numeric" : "nominal")
- / use prediction feature id for neighbor compound features
- - predFeatureId = m.prediction_feature_id.to_s
- - predictionFeature[i] = {"id" => predFeatureId, "type" => predFeatureType}
%li{:class => ("active" if i == 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_with_index do |prediction,j|
- / pass model type for significant fragments view
+ - if prediction.dimension > 0
+ - prediction = prediction[0]
#results.tab-pane{:id=>"#{j+1}", :class => ("active" if j == 0)}
- / 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({
@@ -58,7 +39,7 @@
widthFixed: false
});
});
- - if prediction[:neighbors].size > 0
+ - if prediction[:neighbors]
%div.table-responsive
%table{:id=>"#{j+1}", :style=>"border-style: solid;"}
%thead
@@ -70,9 +51,7 @@
%a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Measured Activity", :tabindex=>"0", data: {trigger:"focus", container:"body", toggle:"popover", placement:"auto", html:"true", content:"Experimental result(s) from the training dataset."}, :style=>"z-index:auto+10;"}
%th.sorter-false{:style =>"vertical-align:middle;"}
Similarity
- %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Similarity", :tabindex=>"0", data: {trigger:"focus", container:"body", toggle:"popover", placement:"auto", html:"true", content:"<a href=\"https://en.wikipedia.org/wiki/Jaccard_index\">Tanimoto/Jaccard</a> similarity based on <a href=\"https://openbabel.org/docs/dev/FileFormats/MolPrint2D_format.html\">Molprint2D</a> fingerprints."}, :style=>"z-index:auto+10;"}
- / %th{:style =>"vertical-align:middle;"}
- / Supporting Information
+ %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Similarity", :tabindex=>"0", data: {trigger:"focus", container:"body", toggle:"popover", placement:"auto", html:"true", content:"<a alt=\"Link opens in new window.\" title=\"Link opens in new window.\" target=\"_blank\" href=\"https://en.wikipedia.org/wiki/Jaccard_index\">Tanimoto/Jaccard</a> similarity based on <a alt=\"Link opens in new window.\" title=\"Link opens in new window.\" target=\"_blank\" href=\"https://openbabel.org/docs/dev/FileFormats/MolPrint2D_format.html\">Molprint2D</a> fingerprints."}, :style=>"z-index:auto+10;"}
%tbody
- type = @model_types[j]
- unit = @models[j].unit
@@ -81,17 +60,16 @@
/ 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
+ = c.svg
%p= c.smiles
/ Measured Activity
%td{:style =>"vertical-align:middle;padding-left:1em;width:20%;white-space:nowrap;"}
- if neighbor[:measurement].is_a?(Array)
- = (type == "Regression") ? neighbor[:measurement].collect{|value| "#{value.delog10} (#{unit})</br>#{c.mmol_to_mg(value.delog10)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("</br>") : neighbor[:measurement].join(", ")
+ = (type == "Regression") ? neighbor[:measurement].collect{|value| "#{value.delog10.signif(3)} (#{unit})</br>#{c.mmol_to_mg(value.delog10).signif(3)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("</br>") : neighbor[:measurement].join(", ")
- else
- = (type == "Regression") ? "#{neighbor[:measurement].delog10} (#{unit})</br>#{c.mmol_to_mg(neighbor[:measurement].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : neighbor[:measurement]
-
+ - if !neighbor[:measurement].nil?
+ = (type == "Regression") ? "#{neighbor[:measurement].delog10.signif(3)} (#{unit})</br>#{c.mmol_to_mg(neighbor[:measurement].delog10).signif(3)} #{(unit =~ /\b(mmol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : neighbor[:measurement]
/ Similarity = tanimoto
%td{:style =>"vertical-align:middle;padding-left:1em;width:20%;"}
= neighbor[:similarity].round(3)
@@ -100,7 +78,3 @@
%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 9a7d0d4..eb9047b 100644
--- a/views/predict.haml
+++ b/views/predict.haml
@@ -111,7 +111,7 @@
};
// 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 !!(showcircle())" }
+%form{:name => "form", :action => to('/predict'), :method => "post", :enctype => "multipart/form-data", :onsubmit => "return !!(showcircle())" }
%fieldset#top.well
%h2 1. Draw a chemical structure
#insert
@@ -135,38 +135,63 @@
%fieldset#middle.well
%h2 2. Select one or more endpoints
#models
+ %input{:type => "checkbox", :name => "checkAll", :id => "checkAll"}
+ %label{:for => "checkAll"}
+ All
+ :javascript
+ $("#checkAll").click(function () {
+ if ($(this).prop('checked')){
+ $(".check").prop('checked', true);
+ }else{
+ $(".check").prop('checked', false);
+ };
+ });
- @endpoints.each do |endpoint|
%div{:id=>endpoint.gsub(/\s+/, "_")}
%h4.head-back=endpoint
- - @models.select{|m| m.endpoint == endpoint}.each do |model|
- %div.row{:id => model.id}
- %span.col-sm-4
- %input{:type => "checkbox", :name => "selection[#{model.id}]", :id => "selection[#{model.species.gsub(/\s+/, "_")}]", :value => true, :disabled => false}
- %label{:for => "selection[#{model.species.gsub(/\s+/, "_")}]"}
- = model.species
- %span.col-sm-8
- %a.btn.btn-default.btn-xs{:data=>{:toggle=>"collapse"}, :href=>"#details#{model.id}", :onclick=>"load#{model.id}Details('#{model}')", :id => "link#{model.id}", :style=>"font-size:small;"}
- Details | Validation
- %img.h2{:src=>"/images/wait30trans.gif", :id=>"circle#{model.id}", :class=>"circle#{model.id}", :alt=>"wait", :style=>"display:none;"}
- %div.panel-collapse.collapse{:id=>"details#{model.id}", :style=>"margin-left:1em;"}
- :javascript
- function load#{model.id}Details(model) {
- button = document.getElementById("link#{model.id}");
- image = document.getElementById("circle#{model.id}");
- if ($('modeldetails#{model.id}').length == 0) {
- $(button).hide();
- $(image).show();
- aClient = new HttpClient();
- aClient.get("#{to("/predict/modeldetails/#{model.id}")}", function(response) {
- var details = document.createElement("modeldetails#{model.id}");
- details.innerHTML = response;
- document.getElementById("details#{model.id}").appendChild(details);
- $(button).show();
- $(image).hide();
- addExternalLinks();
- });
+ - unless endpoint =~ /^Oral/
+ - @models.select{|m| m.endpoint == endpoint}.each do |model|
+ %div.row{:id => model.id,:style=>"margin-bottom:1em;"}
+ %span.col-lg-4.col-md-4.col-sm-4.col-xs-4
+ %input.check{:type => "checkbox", :name => "selection[#{model.id}]", :id => "selection[#{model.species.gsub(/\s+/, "_")}]", :value => true, :disabled => false}
+ %label{:for => "selection[#{model.species.gsub(/\s+/, "_")}]"}
+ = (endpoint =~ /mutagenicity/i ? "Consensus mutagenicity" : model.species)
+ %span.col-lg-8.col-md-8.col-sm-8.col-xs-8
+ %a.btn.btn-default.btn-xs{:data=>{:toggle=>"collapse"}, :href=>"#details#{model.id}", :onclick=>"load#{model.id}Details('#{model}')", :id => "link#{model.id}", :style=>"font-size:small;"}
+ %span.glyphicon.glyphicon-menu-right
+ Details | Validation
+ %img.h2{:src=>"/images/wait30trans.gif", :id=>"circle#{model.id}", :class=>"circle#{model.id}", :alt=>"wait", :style=>"display:none;"}
+ %div.panel-collapse.collapse{:id=>"details#{model.id}", :style=>"margin-left:1em;"}
+ :javascript
+ function load#{model.id}Details(model) {
+ button = document.getElementById("link#{model.id}");
+ span = button.childNodes[1];
+ if (span.className == "glyphicon glyphicon-menu-right"){
+ span.className = "glyphicon glyphicon-menu-down";
+ } else if (span.className = "glyphicon glyphicon-menu-down"){
+ span.className = "glyphicon glyphicon-menu-right";
+ };
+ image = document.getElementById("circle#{model.id}");
+ if ($('modeldetails#{model.id}').length == 0) {
+ $(button).hide();
+ $(image).show();
+ aClient = new HttpClient();
+ aClient.get("#{to("/predict/modeldetails/#{model.id}")}", function(response) {
+ var details = document.createElement("modeldetails#{model.id}");
+ details.innerHTML = response;
+ document.getElementById("details#{model.id}").appendChild(details);
+ $(button).show();
+ $(image).hide();
+ addExternalLinks();
+ });
+ }
}
- }
+ - else
+ %div.row{:id => "Cramer",:style=>"margin-bottom:1em;"}
+ %span.col-lg-4.col-md-4.col-sm-4.col-xs-4
+ %input.check{:type => "checkbox", :name => "selection[Cramer]", :id => "selection[Cramer]", :value => true, :disabled => false}
+ %label{:for => "selection[Cramer]"}
+ Cramer rules
%fieldset#bottom.well
%div.row
%div.col-md-2
diff --git a/views/prediction.haml b/views/prediction.haml
index b090be5..62bed8b 100644
--- a/views/prediction.haml
+++ b/views/prediction.haml
@@ -4,7 +4,14 @@
$('.modal').on('hidden.bs.modal', function () {
$(this).removeData('bs.modal');
});
+ /*TableExport.prototype.bootstrap = ["btn", "btn-default", "btn-toolbar"];
+ var BootstrapTable = document.getElementById('overview');
+ new TableExport(BootstrapTable, {
+ ignoreCSS: ".ignore",
+ bootstrap: true,
+ });*/
});
+
%div.well
%a.btn.btn-warning{:href => to('/predict')}
%i.glyphicon.glyphicon-menu-left
@@ -15,83 +22,132 @@
%table.table.table-bordered{:id=>"overview"}
%tbody
%tr
- %td{:id=>"compound", :style=>"vertical-align:top;"}
- %p= @compound.svg
+ %td{:id=>"compound"}
+ %b.title Compound
+ %p= embedded_svg @compound.svg, class: '.ignore', title: "#{@compound.smiles}"
%p= @compound.smiles
- @model_types = {}
- @dbhit = {}
- - @predictions.each_with_index do |prediction,i|
- - type = @models[i].model.class.to_s.match("Classification") ? "Classification" : "Regression"
- - @model_types[i] = type
- - unit = @models[i].unit
- %td{:style=>"vertical-align:top;white-space:nowrap;"}
- %b{:class => "title"}
- = "#{@models[i].endpoint.gsub('_', ' ')} (#{@models[i].species})"
-
- / check for prediction
- - if prediction[:neighbors].size > 0
- %p
- / show model type (classification|regression)
- %b Type:
- = type
- %p
- / check for database hit
- - if prediction[:warning] =~ /\b(identical)\b/i
- - @dbhit[i] = true
-
- / show message about dbhit and measurements
+ - toxtree = @predictions.pop if @toxtree == true
+ - unless @predictions.blank?
+ - @predictions.each_with_index do |prediction,i|
+ - if prediction.dimension > 0
+ - sa_prediction = prediction[1]
+ - prediction = prediction[0]
+ - type = @models[i].model.class.to_s.match("Classification") ? "Classification" : "Regression"
+ - @model_types[i] = type
+ - unit = @models[i].unit
+ %td{:style=>"vertical-align:top;white-space:nowrap;"}
+ %b.title
+ = (sa_prediction ? "Consensus mutagenicity" : "#{@models[i].endpoint.gsub('_', ' ')} (#{@models[i].species})")
+ / check kazius
+ - if sa_prediction
+ - hash = sa_prediction[:prediction]
+ - confidence = sa_prediction[:confidence]
+ %p
+ %b Structural alerts:
%p
- %b Compound is part of the training dataset
- %p
- %b Measured activity:
- %br
- - if prediction[:measurements].is_a?(Array)
- = (type == "Regression") ? prediction[:measurements].collect{|value| "#{value.delog10} (#{unit})</br>#{@compound.mmol_to_mg(value.delog10)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("</br>") : prediction[:measurements].join(", ")
- - else
- = (type == "Regression") ? "#{prediction[:measurements].delog10} (#{unit})</br>#{@compound.mmol_to_mg(prediction[:measurements].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:measurements]
-
- - else
- - @dbhit[i] = false
-
- / show prediction
- %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>."}}
%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]
+ =(hash[:prediction] == true ? "mutagenic" : "non-mutagenic")
+ %p
+ %b Confidence:
+ %br
+ =confidence.to_f.signif(3)
+ %p
+ %b Structural alerts for mutagenicity:
+ %br
+ =hash[:matches].flatten.first
+ %p
+ / check for prediction
+ - if prediction[:neighbors] and !prediction[:value].nil?
+ %b.title= ("Lazar #{@models[i].endpoint.gsub('_', ' ').downcase} (#{@models[i].species}):" if sa_prediction)
+ %p
+ / show model type (classification|regression)
+ %b Type:
+ = type
+ %p
+ / check for database hit
+ - if prediction[:info] =~ /\b(identical)\b/i
+ - @dbhit[i] = true
+ / show message about dbhit and measurements
+ %p
+ :plain
+ This compound was part of the training dataset. <i>All</i> information </br>
+ from this compound was removed from the training data before the </br>
+ prediction, to obtain unbiased results.
+ %p
+ %b Measured activity:
+ %br
+ - if prediction[:measurements].is_a?(Array)
+ = (type == "Regression") ? prediction[:measurements].collect{|value| "#{value.delog10.signif(3)} (#{unit})</br>#{@compound.mmol_to_mg(value.delog10).signif(3)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("</br>") : prediction[:measurements].join(", ")
+ - else
+ = (type == "Regression") ? "#{prediction[:measurements].delog10.signif(3)} (#{unit})</br>#{@compound.mmol_to_mg(prediction[:measurements].delog10).signif(3)} #{(unit =~ /\b(mmol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:measurements]
+
+ - else
+ - @dbhit[i] = false
- / show prediction interval or probability
+ / show prediction
%p
- - if type == "Regression"
- %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."}}
- %br
- = interval.nil? ? "--" : "#{interval[1].delog10} - #{interval[0].delog10} (#{unit})"
+ %b Prediction:
%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:
- - unless prediction[:probabilities].nil?
+ = (type == "Regression") ? "#{prediction[:value].delog10.signif(3)} (#{unit})</br>#{@compound.mmol_to_mg(prediction[:value].delog10).signif(3)} #{(unit =~ /\b(mmol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:value]
+
+ / show prediction interval or probability
+ %p
+ - if type == "Regression"
+ %b 95% Prediction interval:
+ - interval = (prediction[:prediction_interval].nil? ? nil : prediction[:prediction_interval])
+ %br
+ = interval.nil? ? "--" : "#{interval[1].delog10.signif(3)} - #{interval[0].delog10.signif(3)} (#{unit})"
%br
- = "#{prediction[:probabilities].keys[0]}: #{prediction[:probabilities].values[0]}"
+ = "#{@compound.mmol_to_mg(interval[1].delog10).signif(3)} - #{@compound.mmol_to_mg(interval[0].delog10).signif(3)} #{(unit =~ /\b(mmol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" if !interval.nil?
+ - else
+ %b Probability:
+ - unless prediction[:probabilities].nil?
+ %br
+ = "#{prediction[:probabilities].keys[0]}: #{prediction[:probabilities].values[0].signif(3)}"
+ - if prediction[:probabilities].size == 2
+ %br
+ = "#{prediction[:probabilities].keys[1]}: #{prediction[:probabilities].values[1].signif(3)}"
+
+ / show warnings and info
+ -#%p
+ - if !prediction[:info].blank?
+ %b Info:
%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
- - if !prediction[:warning].nil?
- %b Warnings:
- %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Warnings", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"auto", html:"true", content:"#{prediction[:warning]}"}}
- - else
- - @dbhit[i] = false
- %p
- = "Not enough similar compounds </br>in training dataset."
+ %p=prediction[:info].sub(/\'.*\'/,"").sub(/,/, ",<br>")
+ - if !prediction[:warnings].blank?
+ %b Warnings:
+ - prediction[:warnings].uniq.each do |warning|
+ %br
+ %p=warning.sub(/,/, ",<br>")
+ - else
+ %p
+ - if !prediction[:info].blank?
+ %b Info:
+ %br
+ %p=prediction[:info].sub(/\'.*\'/,"").sub(/,/, ",<br>")
+ - if !prediction[:warnings].blank?
+ %b Warnings:
+ - prediction[:warnings].uniq.each do |warning|
+ %p=warning.sub(/,/, ",<br>")
+
+ / show Cramer rules if checked
+ - if @toxtree == true
+ %td{:style=>"vertical-align:top;white-space:nowrap;"}
+ %b.title Oral toxicity (Cramer rules)
+ %p
+ %b Cramer rules:
+ %br
+ =toxtree.first["Cramer rules"]
+ %p
+ %b Cramer rules, with extensions:
+ %br
+ =toxtree.last["Cramer rules, with extensions"]
- / always show the neighbors table, message is given there
- = haml :neighbors, :layout => false, :model_type => @model_types, :dbhit => @dbhit
+ / always show the neighbors table, message is given there. Except only Cramer is selected.
+ - unless @predictions.blank?
+ = haml :neighbors, :layout => false, :model_type => @model_types, :dbhit => @dbhit
+
diff --git a/views/significant_fragments.haml b/views/significant_fragments.haml
deleted file mode 100644
index bd3598d..0000000
--- a/views/significant_fragments.haml
+++ /dev/null
@@ -1,66 +0,0 @@
-%div.modal-body{:style=>"padding:10px;"}
- %button.close{ :type=>" button", data: { dismiss:"modal"}} &times;
- - if @type =~ /classification/i
- %div.row
- %div.col-md-4
- %h3{:style=>"margin-left:8px;"}
- Significant fragments:
- %img{:src=>"#{@compound.uri}/image", :alt=>"#{@compound.smiles}", :title=>"#{@compound.smiles}", :width=>"300px", :heigth=>"300px"}
- - if !@significant_fragments.empty?
- %div.col-md-8
- %table{:id => "sf"}
- %tr
- / @value_map => hash; interpret the effect
- %th{:style=>"border:2px solid #E6E6E6;"}
- Predominantly in compounds with activity "inactive"
- %th{:style=>"border:2px solid #E6E6E6;"}
- p value
- - @significant_fragments.each do |fragments|
- / fragments == [effect, smarts, pValue]
- / fragments[0] = effect
- /- $logger.debug "effect:\t#{fragments[0]}\n"
- - if fragments[0] == @value_map.index("inactive")
- %tr
- %td
- / fragments[1] = smarts
- = fragments[1]
- -#%img{:src => "http://smartsview.de/smartsview/auto/png/1/both/#{CGI.escape(fragments[1])}", :class => "smarts"}
- %td
- /fragments[2] = pValue
- = fragments[2]
- %tr
- %th{:style=>"border:2px solid #E6E6E6;"}
- Predominantly in compounds with activity "active"
- %th{:style=>"border:2px solid #E6E6E6;"}
- p value
- - @significant_fragments.each do |fragments|
- / fragments == [effect, smarts, pValue]
- - if fragments[0] == @value_map.index("active")
- %tr
- %td
- -#%img{:src => "http://smartsview.de/smartsview/auto/png/1/both/#{CGI.escape(fragments[1])}", :class => "smarts"}
- = fragments[1]
- %td
- = fragments[2]
- %br
- - if @type =~ /regression/i
- %div.row
- %div.col-md-4
- %h3
- Descriptors:
- %img{:src=>"#{@compound.uri}/image", :alt=>"#{@compound.smiles}", :title=>"#{@compound.smiles}", :width=>"300px", :heigth=>"300px"}
- - if !@significant_fragments.empty?
- %div.col-md-8
- %table{:id =>"de"}
- %tr
- %th{:style=>"border:2px solid #E6E6E6;"}
- Descriptor
- %th{:style=>"border:2px solid #E6E6E6;"}
- value
- - @significant_fragments.each do |fragments|
- %tr
- %td
- = fragments[0]
- %td
- = fragments[1][0].round(3)
- %br
diff --git a/views/style.scss b/views/style.scss
index 2c84781..ac070a1 100644
--- a/views/style.scss
+++ b/views/style.scss
@@ -1,3 +1,29 @@
+@media (min-width: 320px){
+ .page-header{
+ img.media-object{
+ margin-left:0;
+ }
+ background-color: #fff;
+ padding:10px 0 10px 0;
+ margin: 0;
+ text-align:left;
+ //display:inline-block;
+ width:100%;
+ }
+}
+@media (min-width: 480px){
+ .page-header{
+ img.media-object{
+ margin-left:1em;
+ }
+ background-color: #fff;
+ padding:20px 0 20px 0;
+ margin: 0;
+ text-align:center;
+ //display:inline-block;
+ width:100%;
+ }
+}
body {
background-color:#E7E7E7;
}
@@ -9,14 +35,13 @@ h4.head-back, h5.head-back{
}
.nav-tabs {
background-color: #E7E7E7;
- margin-bottom: 0;
li.active a:hover {
background-color: #f5f5f5;
}
li a {
- height: 5em;
+ height: 7em;
}
}
img {
@@ -40,6 +65,9 @@ img {
.tablesorter-bootstrap thead .sorter-false {
cursor: default;
}
+.tablesorter-bootstrap thead {
+ background-color: #E7E7E7;
+}
ul.share-buttons{
list-style: none;
}
@@ -50,24 +78,15 @@ ul.share-buttons{
.dropdown-menu a {
padding: 0 2px 1px 2px !important;
}
-.page-header{
- background-color: #fff;
- padding:20px 0 20px 0;
- margin: 0;
- text-align:center;
- display:inline-block;
- width:100%;
-}
.share{
width: 30px;
padding-right: 5px;
}
supporters{
- background-color: white;
text-align:center;
img{
width: 200px;
- margin-right: 1em;
+ margin: 1em;
}
}