From 315db036a63defb5465178279cbc3cbffde375eb Mon Sep 17 00:00:00 2001 From: gebele Date: Tue, 10 Oct 2017 15:49:36 +0000 Subject: new batch mode with single calls --- views/batch.haml | 421 ++++++++++++++++++++++++++++++++++++++------------ views/neighbors.haml | 2 +- views/prediction.haml | 56 +++---- views/style.scss | 10 +- 4 files changed, 360 insertions(+), 129 deletions(-) (limited to 'views') diff --git a/views/batch.haml b/views/batch.haml index 0e7efc7..aaa09bf 100644 --- a/views/batch.haml +++ b/views/batch.haml @@ -1,10 +1,273 @@ +:javascript + function progress(model,idx,total) { + var p = 100/total; + var percent = Math.round((idx+1)*p); + var bar = document.getElementById("bar_"+model); + var prog = document.getElementById("progress_"+model); + bar.style.width = percent + '%'; + 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 ); + } + }; + + function renderResponse(model,idx,compound,last,total,tmppath) { + // create request + if (model == "Cramer"){ + var dataset = '#{@dataset.id}'; + var uri = "#{to("/batch/")}" + model + '/?dataset=' + escape(dataset) + '&tmppath=' + tmppath + '&last=' + last; + } else { + var dataset = '#{@dataset.id}'; + var uri = "#{to("/batch/")}" + model + '/?compound=' + escape(compound) + '&dataset=' + dataset + '&idx=' + idx + '&tmppath=' + tmppath + '&last=' + last; + }; + var aClient = new HttpClient(); + aClient.get(uri, function(res) { + // progress bar function + progress(model,idx,total); + + var response = JSON.parse(res); + var td = document.getElementById("prediction_"+compound+'_'+model+'_'+idx); + //td.innerHTML = ""; + if (model != "Cramer"){ + // init general structure + a = ["title", "type", "db_hit", "measurements", "prediction", "interval", "probability", "warnings", "info"]; + + // handles consesus mutagenicity + if (response['sa_prediction'] != false){ + var p = document.createElement("p"); + var h = document.createElement("h5"); + p.id = "sa"; + // Consensus mutagenicity + var t = document.createTextNode("Consensus mutagenicity"); + h.appendChild(t); + p.appendChild(h); + // handle db_hit first + if (response['db_hit'] != false){ + var value = document.createTextNode(response['db_hit']); + p.appendChild(value); + }; + // Structural alerts + var h2 = document.createElement("h5"); + var t = document.createTextNode("Structural alerts:"); + h2.appendChild(t); + p.appendChild(h2); + // prediction + var h3 = document.createElement("h5"); + var t = document.createTextNode("Prediction:"); + if (response['sa_prediction']['prediction'] == false){ + var value = document.createTextNode("non-mutagenic"); + }; + if (response['sa_prediction']['prediction'] == true){ + var value = document.createTextNode("mutagenic"); + }; + h3.appendChild(t); + p.appendChild(h3); + p.appendChild(value); + // confidence + var h4 = document.createElement("h5"); + var t = document.createTextNode("Confidence:"); + var value = document.createTextNode(response['confidence']); + h4.appendChild(t); + p.appendChild(h4); + p.appendChild(value); + // Structural alerts for mutagenicity + var h5 = document.createElement("h5"); + var t = document.createTextNode("Structural alerts for mutagenicity:"); + h5.appendChild(t); + p.appendChild(h5); + if (response['sa_matches'] != false){ + var value = document.createTextNode(response['sa_matches']); + p.appendChild(value); + } else { + var span = document.createElement("span"); + var value = document.createTextNode("none"); + span.style.fontStyle = "italic"; + span.appendChild(value); + p.appendChild(span); + }; + + // append to td + td.appendChild(p); + }; + + // proceed to general structure + for (val of a){ + var p = document.createElement("p"); + var h = document.createElement("h5"); + p.id = val; + if (val == "title") { + var value = document.createTextNode(response['model_name']); + h.appendChild(value); + p.appendChild(h); + } else if (val == "type") { + var t = document.createTextNode("Type: "); + var value = document.createTextNode(response['model_type']); + h.appendChild(t); + p.appendChild(h); + p.appendChild(value); + h.style.display = "inline"; + } else if (val == "db_hit" && response['db_hit'] != false && response['sa_prediction'] == false) { + var value = document.createTextNode(response['db_hit']); + p.appendChild(value); + } else if (val == "measurements" && response['measurements'] != false) { + var t = document.createTextNode("Measurements:"); + h.appendChild(t); + p.appendChild(h); + if (response['model_type'] == "Regression"){ + for (var i=0; i to('/predict')} %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 @@ -14,96 +277,62 @@ %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 + / displays prediction result in table tabs + #tabs + %ul.nav.nav-tabs.nav-justified{:id=>"batchTabs", :role=>"tablist"} + - @models.each_with_index do |model,i| + - m = Model::Validation.find model unless model == "Cramer" + %li{:class => ("active" if i == 0)} + %a{:href => "#results_#{i+1}", :id => "linkTab#{i+1}", data: {toggle:"tab"}} + = (model == "Cramer") ? "Oral toxicity (Cramer rules)" : "#{m.endpoint} (#{m.species})" + %img.dlwait{:src=>"/images/wait30trans.gif", :id=>"circle_#{model}", :class=>"circle", :alt=>"wait", :style=>"display:none;"} + %a.csv.btn{:id => "downbutton_#{model}", :href=>"#{to("/predict/#{@tmppaths[model]}/#{model}/#{@filename}")}", :title=>"download", :style=>"display:none;"} + %span.glyphicon.glyphicon-download-alt + CSV + + %div.tab-content + - csize = @compounds.size + - msize = @models.size + - timer = 0 + - @models.each_with_index do |model,j| + #results.tab-pane{:id=>"#{j+1}", :class => ("active" if j == 0)} + %div{:id=>"progress_"+model, :style=>"width:100%;height:2px;position:relative;background-color:#ccc;"} + %div{:id=>"bar_"+model, :style=>"background-color: #4CAF50;width:10px;height:2px;position:absolute;"} + %table.table.table-bordered + %tbody + - @compounds.each_with_index do |compound,cidx| + - timer += 800 + :javascript + $(document).ready(function() { + $("img.circle").show(); + var model = '#{model}', + msize = #{msize}, + idx = #{j+1}, + last = false, + compound = '#{compound.id}', + csize = #{csize}, + cidx = #{cidx}, + timer = #{timer}, + tmppath = '#{@tmppaths[model]}'; + // check for last request; + if (cidx+1 == csize) { + last = true; + }; + setTimeout(function(){ + if (model != "Cramer"){ + renderResponse(model,cidx,compound,last,csize,tmppath); + } else if (model == "Cramer" && cidx == 0){ + renderResponse(model,cidx,compound,last,csize,tmppath); + }; + }, timer ); + }); + // table layout: + // one row per prediction; + // first col compound; sec col results + %tr{:id=>model} + // compound + %td.col-md-6{:id=>"compound"} + %p=embedded_svg(compound.svg, title: compound.smiles) + %p=compound.smiles + // prediction values from js function + %td.col-md-6{:id=>"prediction_#{compound.id}_#{model}_#{cidx}", :style => "vertical-align:top;"} diff --git a/views/neighbors.haml b/views/neighbors.haml index 9c12be9..37c99d0 100644 --- a/views/neighbors.haml +++ b/views/neighbors.haml @@ -60,7 +60,7 @@ / Compound - c = Compound.find(neighbor) %td{:style =>"vertical-align:middle;padding-left:1em;width:50%;"} - = c.svg + = embedded_svg(c.svg, title: c.smiles) %p= c.smiles / Measured Activity diff --git a/views/prediction.haml b/views/prediction.haml index 62bed8b..b5a7e82 100644 --- a/views/prediction.haml +++ b/views/prediction.haml @@ -4,12 +4,6 @@ $('.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 @@ -24,7 +18,7 @@ %tr %td{:id=>"compound"} %b.title Compound - %p= embedded_svg @compound.svg, class: '.ignore', title: "#{@compound.smiles}" + %p= embedded_svg(@compound.svg, title: @compound.smiles) %p= @compound.smiles - @model_types = {} - @dbhit = {} @@ -47,6 +41,16 @@ %p %b Structural alerts: %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. All information
+ from this compound was removed from the training data before the
+ prediction, to obtain unbiased results. + %p %b Prediction: %br =(hash[:prediction] == true ? "mutagenic" : "non-mutagenic") @@ -71,19 +75,20 @@ - 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. All information
- from this compound was removed from the training data before the
- prediction, to obtain unbiased results. + - unless sa_prediction %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] - + :plain + 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. + %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] + - else - @dbhit[i] = false @@ -111,17 +116,6 @@ %br = "#{prediction[:probabilities].keys[1]}: #{prediction[:probabilities].values[1].signif(3)}" - / show warnings and info - -#%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(/,/, ",
") - else %p - if !prediction[:info].blank? @@ -148,6 +142,6 @@ / 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 + = haml :neighbors, :layout => false diff --git a/views/style.scss b/views/style.scss index ac070a1..2a8f9d4 100644 --- a/views/style.scss +++ b/views/style.scss @@ -89,7 +89,15 @@ supporters{ margin: 1em; } } - +.csv.btn{ + width: 100%; + height: 30px; +} +.dlwait{ + display: block; + margin-left: auto; + margin-right: auto; +} .footer{ margin-top:3em; } -- cgit v1.2.3