summaryrefslogtreecommitdiff
path: root/views
diff options
context:
space:
mode:
authorgebele <gebele@in-silico.ch>2017-10-10 15:49:36 +0000
committergebele <gebele@in-silico.ch>2017-10-17 12:00:59 +0200
commit315db036a63defb5465178279cbc3cbffde375eb (patch)
treef63a88711ada7354c0bc883c4b32449f6b86f336 /views
parente22513f460eeb42af5164537a7ecea9d21035cea (diff)
new batch mode with single calls
Diffstat (limited to 'views')
-rw-r--r--views/batch.haml421
-rw-r--r--views/neighbors.haml2
-rw-r--r--views/prediction.haml56
-rw-r--r--views/style.scss10
4 files changed, 360 insertions, 129 deletions
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<response['measurements'].length; i++){
+ var value = document.createTextNode(response['measurements'][i]);
+ var br = document.createElement("br");
+ p.appendChild(value);
+ p.appendChild(br);
+ if (response['converted_measurements'] != false) {
+ var value = document.createTextNode(response['converted_measurements'][i]);
+ var br = document.createElement("br");
+ p.appendChild(value);
+ p.appendChild(br);
+ if (i+1 != response['measurements'].length){
+ var br2 = document.createElement("br");
+ p.appendChild(br2);
+ };
+ };
+ };
+ } else if (response['model_type'] == "Classification"){
+ for (var i=0; i<response['measurements'].length; i++){
+ var value = document.createTextNode(response['measurements'][i]);
+ var br = document.createElement("br");
+ p.appendChild(value);
+ p.appendChild(br);
+ };
+ };
+ } else if (val == "prediction" && response['prediction_value'] != false) {
+ var t = document.createTextNode("Prediction:");
+ var value = document.createTextNode(response['prediction_value']+" "+response['model_unit']);
+ h.appendChild(t);
+ p.appendChild(h);
+ p.appendChild(value);
+ if (response['converted_value'] != false) {
+ var br = document.createElement("br");
+ var value = document.createTextNode(response['converted_value']+" "+response['converted_model_unit']);
+ p.appendChild(br);
+ p.appendChild(value);
+ };
+ if (response['model_type'] == "Classification" && response['probability'] != false){
+ var h = document.createElement("h5");
+ var t = document.createTextNode("Probability:");
+ h.appendChild(t);
+ p.appendChild(h);
+ for (var i=0; i<response['probability'].length; i++){
+ var value = document.createTextNode(response['probability'][i]);
+ var br = document.createElement("br");
+ p.appendChild(value);
+ p.appendChild(br);
+ };
+ };
+ } else if (val == "interval" && response['interval'] != false) {
+ var t = document.createTextNode("95% Prediction interval:");
+ var value = document.createTextNode(response['interval']+" "+response['model_unit']);
+ h.appendChild(t);
+ p.appendChild(h);
+ p.appendChild(value);
+ if (response['converted_interval'] != false) {
+ var br = document.createElement("br");
+ var value = document.createTextNode(response['converted_interval']+" "+response['converted_model_unit']);
+ p.appendChild(br);
+ p.appendChild(value);
+ };
+ } else if (val == "warnings" && response['warnings'] != false && response['db_hit'] == false) {
+ var t = document.createTextNode("Warnings: ");
+ h.appendChild(t);
+ p.appendChild(h);
+ for (var i=0; i<response['warnings'].length; i++){
+ var value = document.createTextNode(response['warnings'][i]);
+ var br = document.createElement("br");
+ p.appendChild(value);
+ p.appendChild(br);
+ };
+ } else if (val == "info" && response['info'] != false) {
+ var t = document.createTextNode("Info: ");
+ var value = document.createTextNode(response['info']);
+ h.appendChild(t);
+ p.appendChild(h);
+ p.appendChild(value);
+ };
+
+ // append to td
+ td.appendChild(p);
+ };
+ };// if model != Cramer
+ if (model == "Cramer"){
+ for(i=0; i < response['tds'].length; i++){
+ progress('Cramer',i,response['tds'].length);
+ var td = document.getElementById(response['tds'][i]);
+ var p = document.createElement("p");
+ var h = document.createElement("h5");
+ var t = document.createTextNode("Oral toxicity (Cramer rules)");
+ p.id = "cramer";
+ h.appendChild(t);
+ p.appendChild(h);
+ var h2 = document.createElement("h5");
+ var t = document.createTextNode("Cramer rules:");
+ h2.appendChild(t);
+ p.appendChild(h2);
+ if (response['cramer_rules'][i] != "nil"){
+ var value = document.createTextNode(response['cramer_rules'][i]);
+ p.appendChild(value);
+ } else {
+ var span = document.createElement("span");
+ var value = document.createTextNode("none");
+ span.style.fontStyle = "italic";
+ span.appendChild(value);
+ p.appendChild(span);
+ };
+ var h3 = document.createElement("h5");
+ var t = document.createTextNode("Cramer rules, with extensions:");
+ h3.appendChild(t);
+ p.appendChild(h3);
+ if (response['cramer_rules_extensions'][i] != "nil"){
+ var value = document.createTextNode(response['cramer_rules_extensions'][i]);
+ 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);
+ if (i === response['tds'].length-1) {
+ $("img#circle_Cramer").hide();
+ $("a#downbutton_Cramer").show();
+ };
+
+ };
+ };// if model == Cramer
+ // if last compound change progress to download;
+ if (last == true) {
+ $("img#circle_"+model).hide();
+ $("a#downbutton_"+model).show();
+ };
+ });
+ };
+
+
%div.well
%a.btn.btn-warning{:href => 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})</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
- = (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
- %b Probability:
- - unless prediction[:probabilities].nil?
- - probabilities = ""
- - prediction[:probabilities].each{|k,v| probabilities += "#{k}: #{v.signif(3)}<br>"}
- %br
- = probabilities
- / show warnings
- %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|
- %br
- %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
- %p=warning.sub(/substances/, "substances<br>").sub(/prediction\:/, "prediction\:<br>")
- %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. <i>All</i> information </br>
+ from this compound was removed from the training data before the </br>
+ 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. <i>All</i> information </br>
- from this compound was removed from the training data before the </br>
- 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})</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]
-
+ :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
@@ -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(/,/, ",<br>")
- - if !prediction[:warnings].blank?
- %b Warnings:
- - prediction[:warnings].uniq.each do |warning|
- %br
- %p=warning.sub(/,/, ",<br>")
- 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;
}