From b3ed4f0dbf47ed4986b7ff745324fbde20123631 Mon Sep 17 00:00:00 2001 From: gebele Date: Mon, 27 Aug 2018 11:33:10 +0000 Subject: updated to bs 4 --- views/error.haml | 7 +- views/faq.haml | 8 +- views/layout.haml | 132 ++++++++++++++------------------ views/model_details.haml | 140 +++++++++++++++++----------------- views/neighbors.haml | 177 +++++++++++++++++++++++-------------------- views/predict.haml | 132 ++++++++++++++++---------------- views/prediction.haml | 193 ++++++++++++++++++++++++----------------------- views/style.scss | 52 +++---------- 8 files changed, 404 insertions(+), 437 deletions(-) (limited to 'views') diff --git a/views/error.haml b/views/error.haml index 05cb0da..ca6a0b2 100644 --- a/views/error.haml +++ b/views/error.haml @@ -1,7 +1,6 @@ -%div.well +%div.card %a.btn.btn-warning{:href => to('/predict')} - %i.glyphicon.glyphicon-menu-left + %i.fa.fa-caret-left Back - %hr - %div.well{:style=>"width:100%;margin-bottom:2em;"} + %div.card-body = @error diff --git a/views/faq.haml b/views/faq.haml index 818b96a..63479e2 100644 --- a/views/faq.haml +++ b/views/faq.haml @@ -1,2 +1,6 @@ -%div.well.faq - = @faq +%div.card + %a.btn.btn-warning{:href => to('/predict')} + %i.fa.fa-caret-left + Back + %div.card-body + = @faq diff --git a/views/layout.haml b/views/layout.haml index 2558071..a520ed6 100644 --- a/views/layout.haml +++ b/views/layout.haml @@ -6,77 +6,54 @@ %meta{'name'=>"viewport", :content=>"width=device-width, initial-scale=1"} %title lazar Toxicity Predictions %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/jquery.tablesorter.min.js"} - %script{:src=>"/javascripts/jquery.tablesorter.widgets.js"} + %link{:href=>"/stylesheets/bootstrap.min.css", :rel=>"stylesheet"} + %link{:href=>"/stylesheets/font-awesome.min.css", :rel=>"stylesheet"} + %link{:href=>"/style.css", :rel=>"stylesheet"} + %script{ :src=>"/javascripts/jquery.min.js"} + %script{ :src=>"/javascripts/popper.min.js"} %script{:src=>"/javascripts/lazar-gui.js"} - %script{:src=>"/javascripts/google_analytics_lazar.js"} + %script{ :src=>"/javascripts/bootstrap.js"} + //%script{ :src=>"/javascripts/bootstrap.js.map"} + //%script{:src=>"/javascripts/google_analytics_lazar.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-3 - %a{:href=> to("/")} - %img.media-object{:src=>"/images/IST_logo_s.png", :alt=>"logo", :width=>"150px", :heigth=>"150px"} - %div.col-md-6 - %h1.media-heading - lazar toxicity predictions - %div.col-md-3 - %h1.media-heading - %small - %a.btn{:href=>"https://nano-lazar.in-silico.ch", :rel=>"external"} - nano-lazar - %span.glyphicon.glyphicon-new-window - + %header.container-fluid.page-header + %div.row.align-items-center + %div.col-3 + %a.card-link{:href=> "https://in-silico.ch/", :rel=>"external"} + %img{:src=>"/images/IST_logo_s.png", :alt=>"logo", :width=>"100px", :heigth=>"100px"} + %a.card-link{:href=> "https://openrisknet.org/", :rel=>"external"} + %img{:src=>"/images/orn-logo.jpg", :alt=>"orn-logo", :width=>"100px", :heigth=>"100px"} + %div.col-6 + %h1 lazar toxicity predictions + %div.col-3 + %a{:href=>"https://twitter.com/intent/tweet?source=http%3A%2F%2Flazar.in-silico.ch&text=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Tweet"} + %span.fa.fa-2x.fa-twitter-square + %a{:href=>"https://plus.google.com/share?url=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Share on Google+"} + %span.fa.fa-2x.fa-google-plus-square + %a{:href=>"http://www.linkedin.com/shareArticle?mini=true&url=http%3A%2F%2Flazar.in-silico.ch&title=&summary=&source=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Share on LinkedIn"} + %span.fa.fa-2x.fa-linkedin-square + %a{:href=>"https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Flazar.in-silico.ch&title=&summary=&source=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Share on Facebook"} + %span.fa.fa-2x.fa-facebook-square %div.container-fluid %topline.alert - %div.row - %div.col-md-10 - Problems, bugs, ideas for improvements ? Please report at our - %a{:href => 'https://github.com/opentox/lazar-gui/issues', :rel => "external"} issue tracker - , check out the - %a{:href=> to("/faq"), :rel => "external"} FAQ - page or send us an email. - %a{ :href=>"mailto:info@in-silico.ch?subject=[lazar v#{@version}]", :target=>"_top"} - %img.share{:src=>"/images/Email.png"} - [version: #{@version}] - %div.col-md-2{:style=>"text-align:right;"} - %a{:href=>"https://twitter.com/intent/tweet?source=http%3A%2F%2Flazar.in-silico.ch&text=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Tweet"} - %img.share{:src=>"/images/Twitter.png"} - %a{:href=>"https://plus.google.com/share?url=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Share on Google+"} - %img.share{:src=>"/images/Google+.png"} - %a{:href=>"http://www.linkedin.com/shareArticle?mini=true&url=http%3A%2F%2Flazar.in-silico.ch&title=&summary=&source=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Share on LinkedIn"} - %img.share{:src=>"/images/LinkedIn.png"} - %a{:href=>"https://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Flazar.in-silico.ch&title=&summary=&source=http%3A%2F%2Flazar.in-silico.ch", :rel=>"external", :title=>"Share on Facebook"} - %img.share{:src=>"/images/Facebook.png"} - %div.row - %div.col-md-12 - Please cite - %a{ :href=>"https://doi.org/10.3389/fphar.2013.00038", :rel=>"external"} - %img{ :src=>"https://zenodo.org/badge/DOI/10.3389/zenodo.10.3389.svg", :alt=>"DOI"} - in scientific publications. + %p + Problems, bugs, ideas for improvements ? Please report at our + %a{:href => 'https://github.com/opentox/lazar-gui/issues', :rel => "external"} issue tracker + , check out the + %a{:href=> to("/faq")} FAQ + page or send us an email. + %a{ :href=>"mailto:info@in-silico.ch?subject=[lazar v#{@version}]", :target=>"_top"} + %span.fa.fa-envelope + [version: #{@version}] + %p + Please cite + %a{ :href=>"https://doi.org/10.3389/fphar.2013.00038", :rel=>"external"} + %img{ :src=>"https://zenodo.org/badge/DOI/10.3389/zenodo.10.3389.svg", :alt=>"DOI"} + in scientific publications. - :javascript - $(document).ready(function(){ - $("#back-top").hide(); - $(".blind").error(function(){ - $(this).attr('src', '/images/blind.png'); - }); - }); - $(document).ready(function(){ - $('[data-toggle="popover"]').popover(); - $('.modal').on('hidden.bs.modal', function () { - $(this).removeData('bs.modal'); - }); - }); = yield @@ -89,24 +66,13 @@ %a{:href => 'http://www.in-silico.ch', :rel => "external"} in silico toxicology gmbh 2004 - #{Time.now.year.to_s} | %a{:href => to("/license"), :rel => "external"} GPL3 License - %supporters - %div.panel.panel-default - Financial support by - %div.panel-body - %a{:href=>"http://www.bfr.bund.de/de/start.html", :rel=>"external"} - %img{:src=>"/images/bfr_logo.gif"} - %a{:href=>"http://www.opentox.org/", :rel=>"external"} - %img{:src=>"/images/ot_logo.png"} - %a{:href=>"https://enanomapper.net/", :rel=>"external"} - %img{:src=>"/images/enm_logo.png"} - %a{:href=>"https://www.researchgate.net/institution/Nestle_SA/department/Nestle_Research_Center", :rel=>"external"} - %img{:src=>"/images/nestec.jpg"} - #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;"} + %span.fa.fa-caret-up{:style => "font-size:3em;color:black;"} :javascript + //var $j = jQuery.noConflict(); + // $j is now an alias to the jQuery function; creating the new alias is optional. $("#back-top").hide(); $(function () { $(window).scroll(function () { @@ -124,3 +90,15 @@ return false; }); }); + $(document).ready(function(){ + $("#back-top").hide(); + $(".blind").on('error', function(){ + $(this).attr('src', '/images/blind.png'); + }); + }); + $(document).ready(function(){ + //$('[data-toggle="popover"]').popover(); + $('.modal').on('hidden.bs.modal', function () { + $(this).removeData('bs.modal'); + }); + }); diff --git a/views/model_details.haml b/views/model_details.haml index c5e3370..3f1cc7a 100644 --- a/views/model_details.haml +++ b/views/model_details.haml @@ -1,7 +1,6 @@ -%div.panel.panel-default - %div.panel-heading - %b Model: - %div.panel-body +%div.card.bg-light + %div.card-body + %h6.card-title Model: Source: %a{:href=>model.source, :rel=>"external"} = model.source @@ -18,10 +17,9 @@ %a{:href=>"#{to("/predict/dataset/#{training_dataset.name}")}"} = training_dataset.name -%div.panel.panel-default - %div.panel-heading - %b Algorithms: - %div.panel-body +%div.card.bg-light + %div.card-body + %h6.card-title Algorithms: 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"] @@ -40,18 +38,15 @@ = 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.card.bg-light + %div.card-body + - if type == "Classification" + %h6.card-title Independent crossvalidations: + - else + %h6.card-title Independent crossvalidations (-log10 transformed): %div.row{:id=>"validations#{model.id}"} - crossvalidations.each do |cv| - %span.col-xs-4.col-sm-4.col-md-4.col-lg-4 + %span.col-4 = "Num folds:\t" = cv.folds %br @@ -84,64 +79,65 @@ %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 + %div.table-responsive + %table.table.table-sm.table-borderless + %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: + %a{: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: + %a{: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"+"2"+":" + %a{:href=>"https://en.wikipedia.org/wiki/Coefficient_of_determination", :rel=>"external"}= "R"+"2"+":" = cv.r_squared.round(3) if cv.r_squared %br /= "Confidence plot:" @@ -152,10 +148,10 @@ /%p.plot / %img{:src=>"/corrp#{cv.id}.svg"} -%div.panel.panel-default - %div.panel-heading - %b QMRF: - %div.panel-body - %a.btn.btn-default.btn-xs{:href=>"#{to("/report/#{model.id}")}", :id=>"report#{model.id}", :style=>"font-size:small;"} - %span.glyphicon.glyphicon-download-alt +%div.card.bg-light + %div.card-body + %h6.card-title QMRF: + %a.btn.btn-outline-info{:href=>"#{to("/report/#{model.id}")}", :id=>"report#{model.id}", :style=>"font-size:small;"} + %span.fa.fa-download XML +%br diff --git a/views/neighbors.haml b/views/neighbors.haml index 8af59b6..f9d2691 100644 --- a/views/neighbors.haml +++ b/views/neighbors.haml @@ -1,83 +1,100 @@ -%div.results - %h3 Neighbors: - / tabs div - #tabs - %ul.nav.nav-tabs.nav-justified{:id=>"neighborTabs", :role=>"tablist", :style=>"width:100%;overflow-x:auto;"} - - @models.each_with_index do |model,i| - / get predictionFeature type - - m = Model::Lazar.find model.model_id.to_s - %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 - - @predictions.each_with_index do |prediction,j| - #results.tab-pane{:id=>"#{j+1}", :class => ("active" if j == 0)} - :javascript - $(document).ready(function(){ - $("table##{j+1}").tablesorter({ - debug: false, - theme: "bootstrap", - headerTemplate: '', - widgets: ['columns', 'uitheme', 'stickyHeaders'], - widgetOptions: { - stickyHeaders_attachTo : '.tab-content', - stickyHeaders : '', - stickyHeaders_offset : 0, - stickyHeaders_cloneId : '-sticky', - stickyHeaders_addResizeEvent : true, - stickyHeaders_includeCaption : true, - stickyHeaders_zIndex : 2, - stickyHeaders_attachTo : null, - stickyHeaders_xScroll : null, - stickyHeaders_yScroll : null, - stickyHeaders_filteredToTop: true - }, - sortList: [[2,1]], - headers: {sorter: false}, - widthFixed: false - }); - }); - - if prediction[:neighbors] - %div.table-responsive - %table{:id=>"#{j+1}", :style=>"border-style: solid;"} - %thead - %tr - %th.sorter-false{:style =>"vertical-align:middle;"} - Compound - %th.sorter-false{:style =>"vertical-align:middle;"} - Measured Activity - %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:"Tanimoto/Jaccard similarity based on Molprint2D fingerprints."}, :style=>"z-index:auto+10;"} - %tbody - - type = @model_types[j] - - unit = @models[j].unit - - prediction[:neighbors].uniq.each_with_index do |neighbor,count| - %tr - / 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(c.id.to_s)}/details"), :id=>"link#{j+1}#{count}"}} - = 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.signif(3)} (#{unit})
#{c.mmol_to_mg(value.delog10).signif(3)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("
") : neighbor[:measurement].join(", ") - - else - - if !neighbor[:measurement].nil? - = (type == "Regression") ? "#{neighbor[:measurement].delog10.signif(3)} (#{unit})
#{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) +%div.card.bg-light + %div.card-body + %div.card-title + %h3 Neighbors: + #tabs + %ul.nav.nav-pills.nav-justified{:id=>"neighborTabs", :role=>"tablist"} + - @models.each_with_index do |model,i| + / get predictionFeature type + - m = Model::Lazar.find model.model_id.to_s + %li.nav-item + %a.nav-link{:class => ("active" if i ==0), :href => "#results_#{i+1}", :id => "linkTab#{i+1}", data: {toggle:"tab"}, :onclick=>"sortTable('#{i+1}');"} + = "#{model.endpoint} (#{model.species})" + %div.tab-content + - @predictions.each_with_index do |prediction,j| + #results.tab-pane{:id=>"#{j+1}", :class => ("active" if j == 0)} + - if prediction[:neighbors] + %div.table-responsive + %table.table.table-bordered.table-hover{:id=>"nTable#{j+1}"} + %thead + %tr + %th{:scope=>"col"} + Compound + %th{:scope=>"col"} + SMILES + %th{:scope=>"col"} + Measured Activity + %a.btn.fa.fa-info-circle{: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{:scope=>"col"} + Similarity + %a.btn.fa.fa-info-circle{:href=>"javascript:void(0)", :title=>"Similarity", :tabindex=>"0", data: {trigger:"focus", container:"body", toggle:"popover", placement:"auto", html:"true", content:"Tanimoto/Jaccard similarity based on Molprint2D fingerprints."}, :style=>"z-index:auto+10;"} + %tbody + - type = @model_types[j] + - unit = @models[j].unit + - prediction[:neighbors].uniq.each_with_index do |neighbor,count| + %tr + / Compound + - c = Compound.find(neighbor) + %td + %a.btn.btn-link{:href => "#details#{j+1}", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(c.id.to_s)}/details"), :id=>"link#{j+1}#{count}"}} + = c.svg + %td + %p= c.smiles + + / Measured Activity + %td + - if neighbor[:measurement].is_a?(Array) + = (type == "Regression") ? neighbor[:measurement].collect{|value| "#{value.delog10.signif(3)} (#{unit})
#{c.mmol_to_mg(value.delog10).signif(3)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("
") : neighbor[:measurement].join(", ") + - else + - if !neighbor[:measurement].nil? + = (type == "Regression") ? "#{neighbor[:measurement].delog10.signif(3)} (#{unit})
#{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 + = neighbor[:similarity].round(3) - - else - %span.btn.btn-default.disabled - = "Not enough similar compounds in training dataset" + - else + %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 + %div.modal.fade{:id=>"details#{j+1}", :role=>"dialog"} + %div.modal-dialog.modal-lg{:role=>"document"} + %div.modal-content +- @models.each_with_index do |model,i| + :javascript + // sort all neighbors tables by similarity + document.addEventListener('DOMContentLoaded', function() { + var id = '#{i+1}'; + var table, rows, switching, i, x, y, shouldSwitch; + table = document.getElementById("nTable"+id); + switching = true; + /* Make a loop that will continue until + no switching has been done: */ + while (switching) { + // Start by saying: no switching is done: + switching = false; + rows = table.rows; + /* Loop through all table rows (except the + first, which contains table headers): */ + for (i = 1; i < (rows.length - 1); i++) { + // Start by saying there should be no switching: + shouldSwitch = false; + /* Get the two elements you want to compare, + one from current row and one from the next: */ + x = rows[i].getElementsByTagName("TD")[3]; + y = rows[i + 1].getElementsByTagName("TD")[3]; + // Check if the two rows should switch place: + if (parseFloat(x.innerHTML) < parseFloat(y.innerHTML)) { + // If so, mark as a switch and break the loop: + shouldSwitch = true; + break; + } + } + if (shouldSwitch) { + /* If a switch has been marked, make the switch + and mark that a switch has been done: */ + rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); + switching = true; + } + } + }, false); diff --git a/views/predict.haml b/views/predict.haml index 2308911..d23f26a 100644 --- a/views/predict.haml +++ b/views/predict.haml @@ -13,7 +13,7 @@ } }; - $(function() { + /*$(function() { $('a[data-toggle="tab"]').on('click', function (e) { localStorage.setItem('lastTab', $(e.target).attr('href')); }); @@ -21,7 +21,7 @@ if (lastTab) { $('a[href="'+lastTab+'"]').click(); } - }); + });*/ function getInput(){ identifier = document.getElementById("identifier").value.trim(); @@ -110,76 +110,72 @@ }; }; + function loadDetails(id) { + button = document.getElementById("link"+id); + span = button.childNodes[1]; + if (span.className == "fa fa-caret-right"){ + span.className = "fa fa-caret-down"; + } else if (span.className = "fa fa-caret-down"){ + span.className = "fa fa-caret-right"; + }; + image = document.getElementById("circle"+id); + if ($('modeldetails'+id).length == 0) { + $(button).hide(); + $(image).show(); + aClient = new HttpClient(); + aClient.get("#{to("/predict/modeldetails/")}"+id, function(response) { + var details = document.createElement("modeldetails"+id); + details.innerHTML = response; + document.getElementById("details"+id).appendChild(details); + $(button).show(); + $(image).hide(); + addExternalLinks(); + }); + } + } // 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())" } - %fieldset#top.well - %h2 1. Draw a chemical structure - #insert + %fieldset#top.card.bg-light + #insert.card-body + %h2.card-title 1. Draw a chemical structure %label   - #appletContainer - %br - %label{:for => 'identifier'} - or enter the - %a{:href => "http://en.wikipedia.org/wiki/Simplified_molecular_input_line_entry_specification", :rel => "external"} SMILES - string: + #appletContainer.d-flex %br - %input{:type => 'text', :name => 'identifier', :id => 'identifier', :size => '60'} %p - -#%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"} + %label{:for => 'identifier'} + or enter the + %a{:href => "http://en.wikipedia.org/wiki/Simplified_molecular_input_line_entry_specification", :rel => "external"} SMILES + string: + %input.form-control{:type => 'text', :name => 'identifier', :id => 'identifier'} + %p{:style=>"display:none;"} + %label{:for=>"fileselect"} + or upload a CSV file for batch predictions: + %br + %input.form-control-file{:type=>"file", :name=> "fileselect", :id=>"fileselect", :accept=>"text/csv"} - %fieldset#middle.well - %h2 2. Select one or more endpoints - #models + %fieldset#middle.card.bg-light + #models.card-body + %h2.card-title 2. Select one or more endpoints - @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,:style=>"margin-bottom:1em;"} - %span.col-lg-4.col-md-4.col-sm-4.col-xs-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-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(); - }); - } - } - %fieldset#bottom.well - %div.row - %div.col-lg-2.col-md-2.col-sm-2.col-xs-2 - %h2 - 3. Predict - %div.col-lg-10.col-md-10.col-sm-10.col-xs-10 - %button.has-feedback.btn.btn-warning.h2{:type => "submit", :id => "submit", :value=>"", :onclick => "getsmiles()"} - %span.glyphicon.glyphicon-play - %img.h2{:src=>"/images/wait30trans.gif", :id=>"circle", :class=>"circle", :alt=>"wait", :style=>"display:none;"} + %div.card{:id=>endpoint.gsub(/\s+/, "_")} + %div.card-header + %h5.card-title=endpoint + %div.card-body + - @models.select{|m| m.endpoint == endpoint}.each do |model| + %div.row{:id => model.id,:style=>"margin-bottom:1em;"} + %span.col-6 + %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-6 + %a.btn.btn-outline-info{:role=>"button", :data=>{:toggle=>"collapse"}, :href=>"#details#{model.id}", :aria=>{:expanded=>"false", :controls=>"details#{model.id}"}, :onclick=>"loadDetails('#{model.id}')", :id => "link#{model.id}", :style=>"font-size:small;"} + %span.fa.fa-caret-right + Details | Validation + %img.h2{:src=>"/images/wait30trans.gif", :id=>"circle#{model.id}", :class=>"circle#{model.id}", :alt=>"wait", :style=>"display:none;"} + %div.collapse{:id=>"details#{model.id}", :style=>"margin-left:1em;"} + %fieldset#bottom.card.bg-light + %div.card-body + %h2.card-title 3. Predict + %button.has-feedback.btn.btn-primary.btn-lg{:type => "submit", :id => "submit", :value=>"", :onclick => "getsmiles()"} + %span.fa.fa-play + %img.h2{:src=>"/images/wait30trans.gif", :id=>"circle", :class=>"circle", :alt=>"wait", :style=>"display:none;"} diff --git a/views/prediction.haml b/views/prediction.haml index 4181c22..1cddca6 100644 --- a/views/prediction.haml +++ b/views/prediction.haml @@ -1,95 +1,111 @@ :javascript $(document).ready(function(){ - $('[data-toggle="popover"]').popover(); + //$('[data-toggle="popover"]').popover(); $('.modal').on('hidden.bs.modal', function () { $(this).removeData('bs.modal'); }); + $('.modal').on('show.bs.modal', function(e){ + var button = $(e.relatedTarget); + var modal = $(this); + modal.find('.modal-content').load(button.data("remote")); + }); }); - -%div.well +%div.card %a.btn.btn-warning{:href => to('/predict')} - %i.glyphicon.glyphicon-menu-left + %span.fa.fa-caret-left New Prediction - / displays all prediction result in first table - %h3 Prediction Results: - %div.table-responsive - %table.table.table-bordered{:id=>"overview"} - %tbody - %tr - %td{:id=>"compound", :style=>"vertical-align:top;text-align:center;"} - %a.btn.btn-link{:href => "#details0", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@compound.id.to_s)}/details"), :id=>"link01"}} - = @compound.svg - %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] and !prediction[:value].nil? - %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 +%div.card.bg-light + %div.card-body + %h3.card-title Prediction Results: + %div.table-responsive + %table.table.table-bordered{:id=>"overview"} + %tbody + %tr + %td.align-items-center{:id=>"compound"} + %a.btn.btn-link{:href => "#details0", data: { toggle: "modal", remote: to("/prediction/#{@compound.id}/details"), :id=>"link01"}} + = @compound.svg + %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 + %b{:class => "title"} + = "#{@models[i].endpoint.gsub('_', ' ')} (#{@models[i].species})" + + / check for prediction + - if prediction[:neighbors] and !prediction[:value].nil? %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. + / 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 - %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 - - / show prediction - %p - %b Prediction: - / prediction popover - %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Prediction", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"

lazar searches the training dataset for similar compounds (neighbors) and calculates the prediction from their experimental activities.

Classification:
Majority vote of neighbor activities weighted by similarity.

Regression:
Prediction from a local partial least squares regression model with neighbor activities weighted by similarity.

Original publication.


\"DOI\""}} - %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] + :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] - / show prediction interval or probability + - else + - @dbhit[i] = false + + / 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=>"javascript:void(0)", :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.signif(3)} - #{interval[0].delog10.signif(3)} (#{unit})" + %b Prediction: + / prediction popover + %a.btn.fa.fa-info-circle{:href=>"javascript:void(0)", :title=>"Prediction", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"

lazar searches the training dataset for similar compounds (neighbors) and calculates the prediction from their experimental activities.

Classification:
Majority vote of neighbor activities weighted by similarity.

Regression:
Prediction from a local partial least squares regression model with neighbor activities weighted by similarity.

Original publication.


\"DOI\""}} %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 !interval.nil? - - else - %b Probability: - / probability popover - %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Pobability", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"Probability that the prediction belongs to one of the given classes."}} - - unless prediction[:probabilities].nil? + = (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]) + / prediction interval popover + %a.btn.fa.fa-info-circle{:href=>"javascript:void(0)", :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 - = "#{prediction[:probabilities].keys[0]}: #{prediction[:probabilities].values[0].signif(3)}" - - if prediction[:probabilities].size == 2 + = 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 !interval.nil? + - else + %b Probability: + / probability popover + %a.btn.fa.fa-info-circle{:href=>"javascript:void(0)", :title=>"Pobability", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"Probability that the prediction belongs to one of the given classes."}} + - unless prediction[:probabilities].nil? %br - = "#{prediction[:probabilities].keys[1]}: #{prediction[:probabilities].values[1].signif(3)}" - - / show warnings and info - %p + = "#{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 + %p=prediction[:info].sub(/\'.*\'/,"").sub(/,/, ",
") + - if !prediction[:warnings].blank? + %b Warnings: + - prediction[:warnings].uniq.each do |warning| + %p=warning #.sub(/,/, ",
") + /%p=warning.sub(/substances/, "substances
").sub(/prediction\:/, "prediction\:
") + - else + %br - if !prediction[:info].blank? %b Info: %br @@ -97,24 +113,13 @@ - if !prediction[:warnings].blank? %b Warnings: - prediction[:warnings].uniq.each do |warning| - %p=warning #.sub(/,/, ",
") - /%p=warning.sub(/substances/, "substances
").sub(/prediction\:/, "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(/,/, ",
") + %br + %p=warning.sub(/,/, ",
") - / 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 += haml :neighbors, :layout => false, :model_type => @model_types, :dbhit => @dbhit -%div.modal.fade{:id=>"details0", :role=>"dialog"} - %div.modal-dialog.modal-lg +%div.modal.fade{:id=>"details0", :tabindex=>"-1", :role=>"dialog"} + %div.modal-dialog.modal-lg{:role=>"document"} %div.modal-content diff --git a/views/style.scss b/views/style.scss index a23bb5d..f15fd21 100644 --- a/views/style.scss +++ b/views/style.scss @@ -1,49 +1,35 @@ -@media (min-width: 320px){ +/*@media (min-width: 320px){ .page-header{ - img.media-object{ - margin-left:0; - } + //img.media-object{ + // margin-left:0; + //} background-color: #fff; padding:10px 0 10px 0; margin: 0; - text-align:left; + //text-align:left; //display:inline-block; width:100%; } } @media (min-width: 480px){ .page-header{ - img.media-object{ - margin-left:1em; - } + //img.media-object{ + // margin-left:1em; + //} background-color: #fff; padding:20px 0 20px 0; margin: 0; - text-align:center; + //text-align:center; //display:inline-block; width:100%; } +}*/ +.page-header { + background-color: #fff; } body { background-color:#E7E7E7; } -table.table-borderless tbody tr td{ - border-top: none; -} -h4.head-back, h5.head-back{ - background-color: #E7E7E7; -} -.nav-tabs { - background-color: #E7E7E7; - - li.active a:hover { - background-color: #f5f5f5; - } - - li a { - //height: 7em; - } -} img { max-width: 100%; max-height: 100%; @@ -62,12 +48,6 @@ img { .faq h1 { text-align: center; } -.tablesorter-bootstrap thead .sorter-false { - cursor: default; -} -.tablesorter-bootstrap thead { - background-color: #E7E7E7; -} ul.share-buttons{ list-style: none; } @@ -82,14 +62,6 @@ ul.share-buttons{ width: 30px; padding-right: 5px; } -supporters{ - text-align:center; - img{ - width: 200px; - margin: 1em; - } -} - .footer{ margin-top:3em; } -- cgit v1.2.3