From 198165e4a0e46c522e28b69f10c9c8e5327f6bbb Mon Sep 17 00:00:00 2001 From: gebele Date: Tue, 22 May 2018 09:22:40 +0000 Subject: add additional files --- .bundle/config | 2 + .gitignore | 1 + VERSION | 2 +- application.rb | 16 ++- batch.rb | 91 ++++++++++++++++ helper.rb | 137 ++++++++++++++++++++++- prediction.rb | 35 ++++++ task.rb | 53 +++++++++ views/batch.haml | 229 ++++++++++++++++++++++----------------- views/details.haml | 28 ----- views/faq.haml | 2 - views/license.haml | 1 - views/predict.haml | 10 +- views/significant_fragments.haml | 66 ----------- 14 files changed, 469 insertions(+), 204 deletions(-) create mode 100644 .bundle/config create mode 100644 batch.rb create mode 100644 prediction.rb create mode 100644 task.rb delete mode 100644 views/details.haml delete mode 100644 views/faq.haml delete mode 100644 views/license.haml delete mode 100644 views/significant_fragments.haml diff --git a/.bundle/config b/.bundle/config new file mode 100644 index 0000000..601c76b --- /dev/null +++ b/.bundle/config @@ -0,0 +1,2 @@ +--- +BUNDLE_PATH: "/home/ist/.gem" diff --git a/.gitignore b/.gitignore index 49b161f..0dace87 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ Gemfile.lock .sass-cache/ +login.rb diff --git a/VERSION b/VERSION index f0bb29e..3a3cd8c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.0 +1.3.1 diff --git a/application.rb b/application.rb index 895b0c2..af78b05 100644 --- a/application.rb +++ b/application.rb @@ -1,7 +1,19 @@ -require 'rdiscount' -require_relative 'qmrf_report.rb' +[ + 'batch.rb', + 'helper.rb', + 'login.rb', + 'prediction.rb', + 'qmrf_report.rb', + 'task.rb' +].each do |lib| + require_relative lib +end + include OpenTox +use Rack::Auth::Basic, "Please enter your login credentials." do |username, password| + [username, password] == [$user, $pass] +end configure :production do $logger = Logger.new(STDOUT) diff --git a/batch.rb b/batch.rb new file mode 100644 index 0000000..0002279 --- /dev/null +++ b/batch.rb @@ -0,0 +1,91 @@ +require 'csv' +require 'tempfile' + +module OpenTox + + class Batch + + include OpenTox + include Mongoid::Document + include Mongoid::Timestamps + store_in collection: "batch" + field :name, type: String + field :source, type: String + field :identifiers, type: Array + field :compounds, type: Array + field :warnings, type: Array, default: [] + + def self.from_csv_file file + source = file + name = File.basename(file,".*") + batch = self.find_by(:source => source, :name => name) + if batch + $logger.debug "Skipping import of #{file}, it is already in the database (id: #{batch.id})." + else + $logger.debug "Parsing #{file}." + table = CSV.read file, :skip_blanks => true, :encoding => 'windows-1251:utf-8' + batch = self.new(:source => source, :name => name, :identifiers => [], :compounds => []) + + # features + feature_names = table.shift.collect{|f| f.strip} + warnings << "Duplicated features in table header." unless feature_names.size == feature_names.uniq.size + compound_format = feature_names.shift.strip + bad_request_error "#{compound_format} is not a supported compound format. Accepted formats: SMILES, InChI." unless compound_format =~ /SMILES|InChI/i + numeric = [] + features = [] + # guess feature types + feature_names.each_with_index do |f,i| + metadata = {:name => f} + values = table.collect{|row| val=row[i+1].to_s.strip; val.blank? ? nil : val }.uniq.compact + types = values.collect{|v| v.numeric? ? true : false}.uniq + feature = nil + if values.size == 0 # empty feature + elsif values.size > 5 and types.size == 1 and types.first == true # 5 max classes + numeric[i] = true + feature = NumericFeature.find_or_create_by(metadata) + else + metadata["accept_values"] = values + numeric[i] = false + feature = NominalFeature.find_or_create_by(metadata) + end + features << feature if feature + end + + table.each_with_index do |vals,i| + identifier = vals.shift.strip + batch.identifiers << identifier + begin + case compound_format + when /SMILES/i + compound = OpenTox::Compound.from_smiles(identifier) + when /InChI/i + compound = OpenTox::Compound.from_inchi(identifier) + end + rescue + compound = nil + end + if compound.nil? # compound parsers may return nil + batch.warnings << "Cannot parse #{compound_format} compound '#{identifier}' at line #{i+2} of #{source}." + next + end + batch.compounds << compound.id + end + batch.compounds.duplicates.each do |duplicate| + dup = Compound.find duplicate + positions = [] + batch.compounds.each_with_index do |co,i| + c = Compound.find co + if !c.blank? and c.inchi and c.inchi == dup.inchi + positions << i+1 + end + end + batch.warnings << "Duplicate compound at ID #{positions.join(' and ')}." + end + batch.save + end + batch + end + + end + +end diff --git a/helper.rb b/helper.rb index 54dbd5e..06b1517 100644 --- a/helper.rb +++ b/helper.rb @@ -1,3 +1,138 @@ 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 + + def prediction_to_csv(m,c,p) + model = m + model_name = "#{model.endpoint.gsub('_', ' ')} (#{model.species})" + model_unit = model.regression? ? "(#{model.unit})" : "" + converted_model_unit = model.regression? ? "#{model.unit =~ /\b(mmol\/L)\b/ ? "(mg/L)" : "(mg/kg_bw/day)"}" : "" + + csv = "" + compound = c + prediction = p + output = {} + line = "" + output["model_name"] = model_name + output["model_unit"] = model_unit + output["converted_model_unit"] = converted_model_unit + + if prediction[:value] + inApp = (prediction[:warnings].join(" ") =~ /Cannot/ ? "no" : (prediction[:warnings].join(" ") =~ /may|Insufficient|Weighted/ ? "maybe" : "yes")) + if prediction[:info] =~ /\b(identical)\b/i + prediction[:info] = "This compound was part of the training dataset. All information "\ + "from this compound was removed from the training data before the "\ + "prediction to obtain unbiased results." + end + note = "\"#{prediction[:warnings].uniq.join(" ")}\"" + + output["prediction_value"] = model.regression? ? "#{prediction[:value].delog10.signif(3)}" : "#{prediction[:value]}" + output["converted_value"] = model.regression? ? "#{compound.mmol_to_mg(prediction[:value].delog10).signif(3)}" : nil + + if prediction[:measurements].is_a?(Array) + output["measurements"] = model.regression? ? prediction[:measurements].collect{|value| "#{value.delog10.signif(3)}"} : prediction[:measurements].collect{|value| "#{value}"} + output["converted_measurements"] = model.regression? ? prediction[:measurements].collect{|value| "#{compound.mmol_to_mg(value.delog10).signif(3)}"} : false + else + output["measurements"] = model.regression? ? "#{prediction[:measurements].delog10.signif(3)}" : "#{prediction[:measurements]}" + output["converted_measurements"] = model.regression? ? "#{compound.mmol_to_mg(prediction[:measurements].delog10).signif(3)}" : false + + end #db_hit + + if model.regression? + + if !prediction[:prediction_interval].blank? + interval = prediction[:prediction_interval] + output['interval'] = [] + output['converted_interval'] = [] + output['interval'] << interval[1].delog10.signif(3) + output['interval'] << interval[0].delog10.signif(3) + output['converted_interval'] << compound.mmol_to_mg(interval[1].delog10).signif(3) + output['converted_interval'] << compound.mmol_to_mg(interval[0].delog10).signif(3) + end #prediction interval + + line += "#{output['model_name']},#{compound.smiles},"\ + "\"#{prediction[:info] ? prediction[:info] : "no"}\",\"#{output['measurements'].join("; ") if prediction[:info]}\","\ + "#{!output['prediction_value'].blank? ? output['prediction_value'] : ""},"\ + "#{!output['converted_value'].blank? ? output['converted_value'] : ""},"\ + "#{!prediction[:prediction_interval].blank? ? output['interval'].first : ""},"\ + "#{!prediction[:prediction_interval].blank? ? output['interval'].last : ""},"\ + "#{!prediction[:prediction_interval].blank? ? output['converted_interval'].first : ""},"\ + "#{!prediction[:prediction_interval].blank? ? output['converted_interval'].last : ""},"\ + "#{inApp},#{note.nil? ? "" : note.chomp}\n" + else # Classification + + if !prediction[:probabilities].blank? + output['probabilities'] = [] + prediction[:probabilities].each{|k,v| output['probabilities'] << v.signif(3)} + end + + line += "Consensus mutagenicity,#{compound.smiles},"\ + "\"#{prediction[:info] ? prediction[:info] : "no"}\",\"#{output['measurements'].join("; ") if prediction[:info]}\","\ + "#{prediction['Consensus prediction']},"\ + "#{prediction['Consensus confidence']},"\ + "#{prediction['Structural alerts for mutagenicity']},"\ + "#{output['prediction_value']},"\ + "#{!prediction[:probabilities].blank? ? output['probabilities'].first : ""},"\ + "#{!prediction[:probabilities].blank? ? output['probabilities'].last : ""},"\ + "#{inApp},#{note.nil? ? "" : note}\n" + + end + + output['warnings'] = prediction[:warnings] if prediction[:warnings] + + else #no prediction value + inApp = "no" + if prediction[:info] =~ /\b(identical)\b/i + prediction[:info] = "This compound was part of the training dataset. All information "\ + "from this compound was removed from the training data before the "\ + "prediction to obtain unbiased results." + end + note = "\"#{prediction[:warnings].join(" ")}\"" + + output['warnings'] = prediction[:warnings] + output['info'] = prediction[:info] if prediction[:info] + + if model.regression? + line += "#{output['model_name']},#{compound.smiles},#{prediction[:info] ? prediction[:info] : "no"},"\ + "#{prediction[:measurements].collect{|m| m.delog10.signif(3)}.join("; ") if prediction[:info]},,,,,,,"+ [inApp,note].join(",")+"\n" + else + #line += "Consensus mutagenicity,#{compound.smiles},#{prediction[:info] ? prediction[:info] : "no"},"\ + # "#{prediction[:measurements].join("; ") if prediction[:info]},,,,,,,"+ [inApp,note].join(",")+"\n" + line += "Consensus mutagenicity,#{compound.smiles},"\ + "\"#{prediction[:info] ? prediction[:info] : "no"}\",\"#{output['measurements'].join("; ") if prediction[:info]}\","\ + "#{prediction['Consensus prediction']},"\ + "#{prediction['Consensus confidence']},"\ + "#{prediction['Structural alerts for mutagenicity']},"\ + "#{output['prediction_value']},"\ + "#{!prediction[:probabilities].blank? ? output['probabilities'].first : ""},"\ + "#{!prediction[:probabilities].blank? ? output['probabilities'].last : ""},"\ + "#{inApp},#{note.nil? ? "" : note}\n" + end + + end + csv += line + # output + csv + end + + def dataset_storage + all = Batch.where(:source => /^tmp/) + out = Hash.new + all.reverse.each{|d| out[d.id] = [d.name, d.created_at]} + out + end + end diff --git a/prediction.rb b/prediction.rb new file mode 100644 index 0000000..afceb08 --- /dev/null +++ b/prediction.rb @@ -0,0 +1,35 @@ +module OpenTox + + class Prediction + + include OpenTox + include Mongoid::Document + include Mongoid::Timestamps + store_in collection: "predictions" + field :compound, type: BSON::ObjectId + field :model, type: BSON::ObjectId + field :prediction, type: Hash, default:{} + field :csv, type: String + + attr_accessor :compound, :model, :prediction, :csv + + def compound + self[:compound] + end + + def model + self[:model] + end + + def prediction + self[:prediction] + end + + def csv + self[:csv] + end + + end + +end + diff --git a/task.rb b/task.rb new file mode 100644 index 0000000..9b9ca26 --- /dev/null +++ b/task.rb @@ -0,0 +1,53 @@ +DEFAULT_TASK_MAX_DURATION = 36000 + +module OpenTox + + class Task + + include OpenTox + include Mongoid::Document + include Mongoid::Timestamps + store_in collection: "tasks" + field :pid, type: Integer + field :percent, type: Float, default: 0 + field :predictions, type: Hash, default:{} + field :csv, type: String + + attr_accessor :pid, :percent, :predictions, :csv + + def pid + self[:pid] + end + + def percent + self[:percent] + end + + def predictions + self[:predictions] + end + + def csv + self[:csv] + end + + def update_percent(percent) + self[:percent] = percent + save + end + + def self.run + task = Task.new #uri + pid = fork do + yield + end + Process.detach(pid) + task[:pid] = pid + task.save + task + end + + end + +end + diff --git a/views/batch.haml b/views/batch.haml index 0e7efc7..7f6ddb7 100644 --- a/views/batch.haml +++ b/views/batch.haml @@ -1,10 +1,94 @@ +:javascript + + function progress(value,id) { + var percent = Math.round(value); + var bar = document.getElementById("bar_"+id); + var prog = document.getElementById("progress_"+id); + bar.style.width = value + '%'; + if (percent == 100){ + prog.style.display = "none"; + }; + }; + + var HttpClient = function() { + this.get = function(aUrl, aCallback) { + var anHttpRequest = new XMLHttpRequest(); + anHttpRequest.onreadystatechange = function() { + if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200) + aCallback(anHttpRequest.responseText); + } + anHttpRequest.open( "GET", aUrl, true ); + anHttpRequest.send( null ); + } + }; + + var markers = []; + + function renderTask(task_id,model_id,id) { + var uri = "#{to("/")}" + 'task/?turi=' + task_id; + var aClient = new HttpClient(); + aClient.get(uri, function(res) { + var response = JSON.parse(res); + if (model_id == "Cramer"){ + $("img.circle").show(); + }else{ + progress(response['percent'],id); + } + if (response['percent'] == 100){ + window.clearInterval(markers[id]); + $("a#downbutton_"+id).removeClass("disabled"); + $("a#detailsbutton_"+id).removeClass("disabled"); + $("img.circle").hide(); + }; + }); + }; + function simpleTemplating(data) { + var html = ''; + return html; + }; + function pagePredictions(task_id,model_id,id){ + button = document.getElementById("detailsbutton_"+id); + span = button.childNodes[1]; + if (span.className == "glyphicon glyphicon-menu-right"){ + span.className = "glyphicon glyphicon-menu-down"; + $('#data-container_'+id).show(); + $('#pager_'+id).show(); + $('#pager_'+id).pagination({ + dataSource: '#{to("/")}' + 'task/?predictions=' + task_id + '&model=' + model_id , + locator: 'prediction', + totalNumber: #{@compounds.size}, + pageSize: 1, + showPageNumbers: true, + showGoInput: true, + formatGoInput: 'go to <%= input %>', + formatAjaxError: function(jqXHR, textStatus, errorThrown) { + $('#data-container_'+id).html(errorThrown); + }, + /*ajax: { + beforeSend: function() { + $('#data-container_'+id).html('Loading content ...'); + } + },*/ + callback: function(data, pagination) { + var html = simpleTemplating(data); + $('#data-container_'+id).html(html); + $('#data-container_'+id).css("min-height", $(window).height() + "px" ); + } + }); + } else if (span.className = "glyphicon glyphicon-menu-down"){ + span.className = "glyphicon glyphicon-menu-right"; + $('#data-container_'+id).hide(); + $('#pager_'+id).hide(); + }; + }; %div.well - %a.btn.btn-warning{:href => to('/predict')} + %a.btn.btn-warning{:href => to("/predict?tpid=#{@pid}")} %span.glyphicon.glyphicon-menu-left{:aria=>{:hidden=>"true"}} New Prediction - %a.btn.btn-success{:id => "downbutton", :href=>"#{to("/predict/#{@tmppath}/#{@filename}")}", :title=>"download"} - %span.glyphicon.glyphicon-download-alt - Download CSV / show file name %topline @@ -13,97 +97,46 @@ %h3 Batch Prediction Results: %div.col-md-8 %h3= @filename - - / displays all prediction result in one table - %div.table-responsive - %table.table.table-bordered{:id=>"batch", :style=>"background-color:white;"} - %tbody - - if @warnings - - @warnings.each do |warning| - %tr - %td - %b Warning - %td - = warning.sub(/\b(tmp\/)\b/,"") - - @view.each do |compound, array| - %tr - %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 - / 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 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})
#{compound.mmol_to_mg(value.delog10).signif(3)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("
") : prediction[:measurements].join(", ") - - else - = (type == "Regression") ? "#{prediction[:measurements].delog10.signif(3)} (#{unit})
#{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 - = (type == "Regression") ? "#{prediction[:value].delog10.signif(3)} (#{unit})
#{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 - %b Probability: - - unless prediction[:probabilities].nil? - - probabilities = "" - - prediction[:probabilities].each{|k,v| probabilities += "#{k}: #{v.signif(3)}
"} - %br - = probabilities - / show warnings - %p - - if !prediction[:info].blank? - %b Info: - %br - %p=prediction[:info].sub(/\'.*\'/,"").sub(/,/, ",
") - - if !prediction[:warnings].blank? - %b Warnings: - - prediction[:warnings].uniq.each do |warning| - %br - %p=warning.sub(/substances/, "substances
").sub(/prediction\:/, "prediction\:
") - - / no prediction - - else - %br - - if !prediction[:info].blank? - %b Info: - %br - %p=prediction[:info].sub(/\'.*\'/,"").sub(/,/, ",
") - - if !prediction[:warnings].blank? - %b Warnings: - - prediction[:warnings].uniq.each do |warning| - %br - %p=warning.sub(/substances/, "substances
").sub(/prediction\:/, "prediction\:
") - %tr + + + - @models.each_with_index do |model,idx| + - m = Model::Validation.find model + - task = @tasks[idx].id + #result.panel{:id=>idx} + %div.row + %div.col-md-6 + %h5= "#{m.endpoint} (#{m.species})" + #pager{:id=>idx} + %div.col-md-6.h5 + %a.btn.btn-default.btn-xs.disabled{:id => "detailsbutton_#{idx}", :data=>{:toggle=>"collapse"}, :href=>"javascript:void(0)", :onclick=>"pagePredictions('#{task}','#{model}','#{idx}')", :style=>"font-size:small;"} + %span.glyphicon.glyphicon-menu-right + Details + %a.btn.btn-default.btn-xs.disabled{:id => "downbutton_#{idx}", :href=>"#{to("/predict/csv/#{task}/#{model}/#{@filename}")}", :title=>"download", :style=>"font-size:small;"} + %span.glyphicon.glyphicon-download-alt + CSV + - if model == "Cramer" + %img.h2{:src=>"/images/wait30trans.gif", :id=>"circle", :class=>"circle", :alt=>"wait", :style=>"display:none;"} + - if model != "Cramer" + %div{:id=>"progress_#{idx}", :style=>"width:100%;height:3px;position:relative;background-color:#ccc;"} + %div{:id=>"bar_#{idx}", :style=>"background-color: #4CAF50;width:10px;height:3px;position:absolute;"} + - # increase interval timer for large datasets + - ctimer = ((@compounds.size/1000) == 0 ? 1000 : ((@compounds.size/1000)*1000)) + :javascript + var timer = #{ctimer}; + $(document).ready(function(){ + // check button class before execute a task + if (#{idx} > 0){ + markers[#{idx}] = setInterval(function(){ + var button = document.getElementById("detailsbutton_#{idx-1}"); + if(!button.classList.contains('disabled')){ + renderTask('#{task}','#{model}',#{idx}); + } + }, timer ); + }else{ + markers[#{idx}] = setInterval(function(){ + renderTask('#{task}','#{model}',#{idx}); + }, timer ); + }; + }); + #data-container{:id=>idx,:style=>"width:100%;"} + -#pager{:id=>idx} diff --git a/views/details.haml b/views/details.haml deleted file mode 100644 index be4948a..0000000 --- a/views/details.haml +++ /dev/null @@ -1,28 +0,0 @@ -:javascript - $(document).ready(function(){ - addExternalLinks(); - }); -%div.modal-body{:style=>"padding:10px;"} - %button.close{ :type=>" button", data: { dismiss:"modal"}} × - %h3 - Names and synonyms: - %p= @compound.svg - %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/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/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/predict.haml b/views/predict.haml index 2308911..1c995e9 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"} + %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{:style=>"display:none;"} - %input{:type=>"file", :name=> "fileselect", :id=>"fileselect", :accept=>"text/csv", :disabled=>"disabled", :type=>"hidden"} + %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"} %fieldset#middle.well %h2 2. Select one or more endpoints 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"}} × - - 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 -- cgit v1.2.3