From c5ca09fb039e38abd89005d49ef373cf18b79039 Mon Sep 17 00:00:00 2001 From: gebele Date: Mon, 28 Nov 2016 14:13:18 +0000 Subject: bumped version;training dataset download;show warnings for batch;csv info and upload catch;code cleanup --- views/batch.haml | 106 +++++++++++++++++++++++++++++++++-------------- views/layout.haml | 38 +---------------- views/model_details.haml | 4 ++ views/neighbors.haml | 13 +++--- views/predict.haml | 1 + views/prediction.haml | 103 +++++++++++++++++++++++---------------------- 6 files changed, 142 insertions(+), 123 deletions(-) (limited to 'views') diff --git a/views/batch.haml b/views/batch.haml index 9bfa67e..6c37a2b 100644 --- a/views/batch.haml +++ b/views/batch.haml @@ -2,57 +2,99 @@ %a.btn.btn-warning{:href => to('/predict')} %span.glyphicon.glyphicon-menu-left{:aria=>{:hidden=>"true"}} New Prediction - / displays all prediction result in first table + %a.btn.btn-success{:href=>"#{to("/predict/#{@filename}")}", :title=>"download"} + %span.glyphicon.glyphicon-download-alt + download CSV + + / show processed file name + %topline + %div.row + %div.col-md-4 + %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;"} - %thead - %tr - %h3.col-md-4{:style=>"padding-left:0;"} Batch Prediction Results: - %h3.col-md-8= @filename - %tr - %span.btn.btn-default - %a{:href=>"#{to("/predict/#{@filename}")}", :title=>"download"} - %span.glyphicon.glyphicon-download-alt{:aria=>{:hidden=>"true"}} - CSV %tbody - / key = compound, values = array of arrays with model, prediction + - if @warnings + - @warnings.each do |warning| + %tr + %td + %b Warning + %td + = warning.sub(/\b(tmp\/)\b/,"") + / key = compound, values = [model,prediction] - @batch.each do |key, values| - compound = key - - mw = compound.molecular_weight %tr %td{:style=>"vertical-align:top;"} %p= compound.svg %p= compound.smiles - / array = single prediction [endpoint, result] + + / array[0] = model, array[1] = prediction - values.each_with_index do |array,i| %td{:style=>"vertical-align:top;white-space:nowrap;"} - model = array[0] + / model type (classification|regression) + - model.model.class.to_s.match("Classification") ? type = "Classification" : type = "Regression" + - unit = model.unit - prediction = array[1] + %b{:class => "title"} = "#{model.endpoint.gsub('_', ' ')} (#{model.species})" - %p - - if prediction[:confidence] == "measured" + + / check for prediction + - if prediction[:neighbors].size > 0 %p - %b Measured activity: - - if prediction[:value].is_a?(Array) - = prediction[:value][0].numeric? ? prediction[:value].collect{|v| weight = compound.mmol_to_mg(v, mw); '%.2e' % v + " (#{model.unit})"+" | #{'%.2e' % weight} (mg/kg_bw/day)"}.join("
") : prediction[:value].join(", ") - - else - = prediction[:value].numeric? ? "#{'%.2e' % prediction[:value]} (#{model.unit}) | #{'%.2e' % compound.mmol_to_mg(prediction[:value], mw)} (mg/kg_bw/day)" : prediction[:value] + / show model type (classification|regression) + %b Type: + = type %p - %b Compound is part of the training dataset - - elsif prediction[:neighbors].size > 0 + / check for database hit + - if prediction[:warning] =~ /\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} (#{unit})
#{compound.mmol_to_mg(value.delog10)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("
") : prediction[:measurements].join(", ") + - else + = (type == "Regression") ? "#{prediction[:measurements].delog10} (#{unit})
#{compound.mmol_to_mg(prediction[:measurements].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:measurements] + + + / show prediction %p - / model type (classification|regression) - %b Type: - = model.model.class.to_s.match("Classification") ? "Classification" : "Regression" - %br - %b Prediction: - = prediction[:value].numeric? ? "#{'%.2e' % prediction[:value]} (#{model.unit}) | #{'%.2e' % compound.mmol_to_mg(prediction[:value], mw)} (mg/kg_bw/day)" : prediction[:value] - %br - / TODO probability - %b Confidence: - = prediction[:confidence].round(3) + %b Prediction: + %br + = (type == "Regression") ? "#{prediction[:value].delog10} (#{unit})
#{compound.mmol_to_mg(prediction[:value].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:value] + + / show prediction interval or probability + %p + - if type == "Regression" + %b 95% Prediction interval: + - interval = (prediction[:prediction_interval].nil? ? nil : prediction[:prediction_interval]) + %br + = interval.nil? ? "--" : "#{interval[1].delog10} - #{interval[0].delog10} (#{unit})" + %br + = "#{compound.mmol_to_mg(interval[1].delog10)} - #{compound.mmol_to_mg(interval[0].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" if !prediction[:prediction_interval].nil? + - else + %b Probability: + - unless prediction[:probabilities].nil? + %br + = "#{prediction[:probabilities].keys[0]}: #{prediction[:probabilities].values[0]}" + %br + / show warnings %p + - if !prediction[:warning].nil? + %b Warnings: + %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Warnings", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"#{prediction[:warning]}"}} + + / no prediction - else %p = "Not enough similar compounds
in training dataset." diff --git a/views/layout.haml b/views/layout.haml index dddf854..5ed63e8 100644 --- a/views/layout.haml +++ b/views/layout.haml @@ -29,33 +29,11 @@ %h1.media-heading lazar toxicity predictions %div.col-md-2 - %h1.media-heading + %h5 %small - %a{:href=>"https://nano-lazar.in-silico.ch"} nano-lazar + [version: #{@version}] %div.container-fluid - %topline - %div.row - %div.col-md-8 - Problems, bugs, ideas for improvements ? Please report at our - %a{:href => 'https://github.com/opentox/lazar-gui/issues', :rel => "external"} issue tracker - or send us an email - %a{ :href=>"mailto:info@in-silico.ch", :target=>"_top"} - %img.share{:src=>"/images/Email.png"} - (version #{@version}). - %div.col-md-2 - %div.col-md-2 - %a{:href=>"https://twitter.com/intent/tweet?source=http%3A%2F%2Flazar.in-silico.ch&text=:%20http%3A%2F%2Flazar.in-silico.ch", :target=>"_blank", :title=>"Tweet"} - %img.share{:src=>"/images/Twitter.png"} - %a{:href=>"https://plus.google.com/share?url=http%3A%2F%2Flazar.in-silico.ch", :target=>"_blank", :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", :target=>"_blank", :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", :target=>"_blank", :title=>"Share on Facebook"} - %img.share{:src=>"/images/Facebook.png"} - %div.row - Previous version: - %a{:href=>"http://lazar-old.in-silico.ch", :rel => "external"} lazar-old :javascript $(document).ready(function(){ $("#back-top").hide(); @@ -79,18 +57,6 @@ %p.text-muted © %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.col-md-12 - %p Financial support by - %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%;"} diff --git a/views/model_details.haml b/views/model_details.haml index 7646471..3fa8c8b 100644 --- a/views/model_details.haml +++ b/views/model_details.haml @@ -12,6 +12,10 @@ Source: = "Training compounds:\t" = training_dataset.compounds.size %br += "Training dataset:\t" +%a{:href=>"#{to("/predict/dataset/#{training_dataset.name}")}"} + = training_dataset.name +%br %b Algorithms: %br Similarity: diff --git a/views/neighbors.haml b/views/neighbors.haml index d9f2796..32b8389 100644 --- a/views/neighbors.haml +++ b/views/neighbors.haml @@ -67,10 +67,10 @@ Compound %th.sorter-false{:style =>"vertical-align:middle;"} Measured Activity - %a.btn.glyphicon.glyphicon-info-sign{:href=>"#neighbors", :title=>"Measured Activity", :tabindex=>"0", data: {trigger:"focus", container:"body", toggle:"popover", placement:"left", html:"true", content:"Experimental result(s) from the training dataset."}, :style=>"z-index:auto+10;"} + %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=>"#neighbors", :title=>"Similarity", :tabindex=>"0", data: {trigger:"focus", container:"body", toggle:"popover", placement:"left", html:"true", content:"Tanimoto/Jaccard similarity based on Molprint2D fingerprints."}, :style=>"z-index:auto+10;"} + %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;"} / %th{:style =>"vertical-align:middle;"} / Supporting Information %tbody @@ -84,11 +84,14 @@ /%a.btn.btn-link{:href => "#details#{j+1}", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(neighbor["_id"])}/details"), :id=>"link#{j+1}#{count}"}} %p= c.svg %p= c.smiles + / Measured Activity %td{:style =>"vertical-align:middle;padding-left:1em;width:20%;white-space:nowrap;"} - = (type == "Regression" ? "#{neighbor[:measurement].delog10}" + " (#{unit})" : neighbor[:measurement]) - %br - = "#{c.mmol_to_mg(neighbor[:measurement].delog10)}" + " (#{(unit =~ /\b(mol\/L)\b/) ? "mg/L" : "mg/kg_bw/day"})" if type == "Regression" + - if neighbor[:measurement].is_a?(Array) + = (type == "Regression") ? neighbor[:measurement].collect{|value| "#{value.delog10} (#{unit})
#{c.mmol_to_mg(value.delog10)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("
") : neighbor[:measurement].join(", ") + - else + = (type == "Regression") ? "#{neighbor[:measurement].delog10} (#{unit})
#{c.mmol_to_mg(neighbor[:measurement].delog10)} #{(unit =~ /\b(mol\/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) diff --git a/views/predict.haml b/views/predict.haml index 66006d4..9a7d0d4 100644 --- a/views/predict.haml +++ b/views/predict.haml @@ -127,6 +127,7 @@ %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 %input{:type=>"file", :name=> "fileselect", :id=>"fileselect", :accept=>"text/csv"} diff --git a/views/prediction.haml b/views/prediction.haml index 2454aca..b090be5 100644 --- a/views/prediction.haml +++ b/views/prediction.haml @@ -18,7 +18,6 @@ %td{:id=>"compound", :style=>"vertical-align:top;"} %p= @compound.svg %p= @compound.smiles - -#- mw = @compound.molecular_weight - @model_types = {} - @dbhit = {} - @predictions.each_with_index do |prediction,i| @@ -28,62 +27,66 @@ %td{:style=>"vertical-align:top;white-space:nowrap;"} %b{:class => "title"} = "#{@models[i].endpoint.gsub('_', ' ')} (#{@models[i].species})" - %p - - if prediction[:warning] =~ /\b(identical)\b/i - - @dbhit[i] = true + + / check for prediction + - if prediction[:neighbors].size > 0 %p - /TODO combine with regular view, if prediction value is present - %b Measured activity: - - p prediction[:value] - - if prediction[:value].is_a?(Array) - = (type == "Regression") ? prediction[:value].collect{|value| "#{value} (#{unit}) , #{@compound.mmol_to_mg(value.delog10)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("
") : prediction[:value].join(", ") - - else - = (type == "Regression") ? "#{prediction[:value]} (#{unit}), #{@compound.mmol_to_mg(prediction[:value].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:value] - %p - %b Compound is part of the training dataset - / warning popover - %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Warnings", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"#{prediction[:warning]}"}} - - elsif prediction[:neighbors].size > 0 - %p - / model type (classification|regression) + / show model type (classification|regression) %b Type: = type - %br - %b Prediction: - / prediction popover - %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Prediction", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"

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."}} - %br - = (type == "Regression") ? "#{prediction[:value].delog10} (#{unit})
#{@compound.mmol_to_mg(prediction[:value].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:value] - / tabindex=0 seems the best fix for FF|S browsers on OSX better than trigger="click focus" which ends up in double click for FF. - %br - - if type == "Regression" - %b 95% Prediction interval: - - interval = (prediction[:prediction_interval].nil? ? ["- -","- -"] : prediction[:prediction_interval]) - / prediction intervall popover - %a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Prediction intervall", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"An estimate of prediction uncertainty. The \"real\" value should be with 95% probability within the prediction interval."}} - %br - = "#{interval[0].delog10} - #{interval[1].delog10} (#{unit})" - %br - = "#{@compound.mmol_to_mg(interval[0].delog10)} - #{@compound.mmol_to_mg(interval[1].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" if !prediction[:prediction_interval].nil? + %p + / check for database hit + - if prediction[:warning] =~ /\b(identical)\b/i + - @dbhit[i] = true + + / 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} (#{unit})
#{@compound.mmol_to_mg(value.delog10)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"}.join("
") : prediction[:measurements].join(", ") + - else + = (type == "Regression") ? "#{prediction[:measurements].delog10} (#{unit})
#{@compound.mmol_to_mg(prediction[:measurements].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:measurements] + - else - %b Probability: - - unless prediction[:probabilities].nil? + - @dbhit[i] = false + + / show prediction + %p + %b Prediction: + / prediction popover + -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Prediction", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"

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."}} + %br + = (type == "Regression") ? "#{prediction[:value].delog10} (#{unit})
#{@compound.mmol_to_mg(prediction[:value].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" : prediction[:value] + + / show prediction interval or probability + %p + - if type == "Regression" + %b 95% Prediction interval: + - interval = (prediction[:prediction_interval].nil? ? nil : prediction[:prediction_interval]) + / prediction interval popover + -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Prediction intervall", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"An estimate of prediction uncertainty. The \"real\" value should be with 95% probability within the prediction interval."}} %br - = "#{prediction[:probabilities].keys[0]}: #{prediction[:probabilities].values[0]}" + = interval.nil? ? "--" : "#{interval[1].delog10} - #{interval[0].delog10} (#{unit})" %br - = "#{prediction[:probabilities].keys[1]}: #{prediction[:probabilities].values[1]}" - / probability popover - -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Confidence", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"Indicates the applicability domain of a model. Predictions with a high confidence can be expected to be more reliable than predictions with low confidence. Confidence values may take any value between 0 and 1. For most models confidence > 0.025 is a sensible (hard) cutoff to distinguish between reliable and unreliable predictions."}} - %p - /TODO add tooltip for significant ftagments and descriptors - / - if @model_type[i] =~ /classification/i && (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0) - / Significant fragments: - / %a.btn.btn-default.btn-sm{:id=>"linkSigFragments", :href => "#detailsTop", :tabindex=>"0", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[i]}/#{CGI.escape(@compound.uri)}/fingerprints")}} Significant fragments - / - if @model_type[i] =~ /regression/i && (p.data_entries[0][1] != nil && p.data_entries[0][1] != 0.0) - / Descriptors - / %a.btn.btn-default.btn-sm{:id=>"linkDescriptors", :href => "#detailsTop", :tabindex=>"0", data: { toggle: "modal", remote: to("/prediction/#{CGI.escape(@model_uri)}/#{@model_type[i]}/#{CGI.escape(@compound.uri)}/fingerprints")}} Descriptors - / %p + = "#{@compound.mmol_to_mg(interval[1].delog10)} - #{@compound.mmol_to_mg(interval[0].delog10)} #{(unit =~ /\b(mol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" if !prediction[:prediction_interval].nil? + - else + %b Probability: + - unless prediction[:probabilities].nil? + %br + = "#{prediction[:probabilities].keys[0]}: #{prediction[:probabilities].values[0]}" + %br + = "#{prediction[:probabilities].keys[1]}: #{prediction[:probabilities].values[1]}" + / probability popover + -#%a.btn.glyphicon.glyphicon-info-sign{:href=>"#", :title=>"Confidence", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"left", html:"true", content:"Indicates the applicability domain of a model. Predictions with a high confidence can be expected to be more reliable than predictions with low confidence. Confidence values may take any value between 0 and 1. For most models confidence > 0.025 is a sensible (hard) cutoff to distinguish between reliable and unreliable predictions."}} + + / show warnings %p + - if !prediction[:warning].nil? + %b Warnings: + %a.btn.glyphicon.glyphicon-info-sign{:href=>"javascript:void(0)", :title=>"Warnings", :tabindex=>"0", data: {trigger:"focus", toggle:"popover", placement:"auto", html:"true", content:"#{prediction[:warning]}"}} - else - @dbhit[i] = false %p -- cgit v1.2.3