From 3e91ce8f09ff0830a87c4e337b678810d5de0f6c Mon Sep 17 00:00:00 2001 From: gebele Date: Fri, 23 Oct 2015 09:31:12 +0000 Subject: moved model details to new file and call it onclick;makup validated but svg images not;consistent layout --- application.rb | 5 ++ views/batch.haml | 6 +- views/model_details.haml | 121 ++++++++++++++++++++++++++++++++++ views/neighbors.haml | 11 ++-- views/predict.haml | 164 +++++++++++------------------------------------ views/prediction.haml | 11 ++-- 6 files changed, 174 insertions(+), 144 deletions(-) create mode 100644 views/model_details.haml diff --git a/application.rb b/application.rb index 8168c52..9c9cabb 100644 --- a/application.rb +++ b/application.rb @@ -29,6 +29,11 @@ get '/predict/?' do @models.count <= 0 ? (haml :info) : (haml :predict) end +get '/predict/modeldetails/:model' do + model = OpenTox::Model::Prediction.find params[:model] + return haml :model_details, :layout=> false, :locals => {:model => model} +end + get '/jme_help/?' do File.read(File.join('views','jme_help.html')) end diff --git a/views/batch.haml b/views/batch.haml index 44d22f1..8389651 100644 --- a/views/batch.haml +++ b/views/batch.haml @@ -1,7 +1,7 @@ %div.well %a.btn.btn-warning{:href => to('/predict')} %span.glyphicon.glyphicon-menu-left{:aria=>{:hidden=>"true"}} - Make New Prediction + New Prediction / displays all prediction result in first table %div.table-responsive %table.table.table-bordered{:id=>"batch", :style=>"background-color:white;"} @@ -24,7 +24,7 @@ %p= compound.smiles / array = single prediction [endpoint, result] - values.each_with_index do |array,i| - %td{:style=>"vertical-align:top;"} + %td{:style=>"vertical-align:top;white-space:nowrap;"} - model = array[0] - prediction = array[1] %b{:class => "title"} @@ -52,5 +52,5 @@ %p - else %p - Not enough similar compounds in training dataset. + = "Not enough similar compounds
in training dataset." %p diff --git a/views/model_details.haml b/views/model_details.haml new file mode 100644 index 0000000..f539a70 --- /dev/null +++ b/views/model_details.haml @@ -0,0 +1,121 @@ +%b Model: +%br +Source: +%a{:href=>model.source, :target=>"external"} + = model.source +%br += "Algorithm:\tLAZAR" +%br +- model.classification? ? type = "Classification" : type = "Regression" += "Type:\t" += type +%br +- training_dataset = OpenTox::Dataset.find model.training_dataset.id += "Training dataset:\t" += training_dataset.source.split("/").last +%br += "Training compounds:\t" += training_dataset.compounds.size + +%p +%b Validation (repeated): +%div.row{:id=>"validations#{model.id}", :style=>"background-color:#f5f5f5;"} + - model.crossvalidations.each do |crossvalidation| + %span.col-xs-4.col-sm-4.col-md-4.col-lg-4 + - cv = OpenTox::CrossValidation.find crossvalidation.id + = "Num folds:\t" + = cv.folds + %br + = "Num instances:\t" + = cv.nr_instances + %br + = "Num unpredicted" + = cv.nr_unpredicted + - if model.classification? + %br + = "Accuracy:\t" + = cv.accuracy.round(3) if cv.accuracy + %br + = "Weighted Accuracy:\t" + = cv.weighted_accuracy.round(3) if cv.weighted_accuracy + %br + = "True positive rate:\t" + = cv.true_rate["active"].round(3) if cv.true_rate["active"] + %br + = "True negative rate:\t" + = cv.true_rate["inactive"].round(3) if cv.true_rate["inactive"] + %br + = "Positive predictive value:\t" + = cv.predictivity["active"].round(3) if cv.predictivity["active"] + %br + = "Negative predictive value:\t" + = cv.predictivity["inactive"].round(3) if cv.predictivity["inactive"] + %p + %b 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 + =cv.confusion_matrix[0][0] + %td + =cv.confusion_matrix[0][1] + -#%td + =cv.confusion_matrix[0][0]+cv.confusion_matrix[0][1] + %tr + %td + %td inactive + %td + =cv.confusion_matrix[1][0] + %td + =cv.confusion_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 + - if model.regression? + %br + = "Root mean squared error:\t" + = cv.rmse.round(3) if cv.rmse + %br + = "Weighted root mean squared error:\t" + = cv.weighted_rmse.round(3) if cv.weighted_rmse + %br + = "Mean absolute error:\t" + = cv.mae.round(3) if cv.mae + %br + = "Weighted mean absolute error:\t" + = cv.weighted_mae.round(3) if cv.weighted_mae + %br + = "R square:\t" + = cv.r_squared.round(3) if cv.r_squared + /%br + /= "Correlation plot" + /= cv.correlation_plot + /%br + /= "Confidence plot:" + /= cv.confidence_plot +%br diff --git a/views/neighbors.haml b/views/neighbors.haml index 70bf4b8..bdc7f65 100644 --- a/views/neighbors.haml +++ b/views/neighbors.haml @@ -50,7 +50,7 @@ Similarity / %th{:style =>"vertical-align:middle;"} / Supporting Information - %info + %span %tr %td %td{:style=>"font-size:x-small;padding:0px;"} @@ -68,16 +68,15 @@ %p= Compound.find(neighbor[0]).smiles / Measured Activity %td{:style =>"vertical-align:middle;padding-left:1em;width:20%;"} - //= neighbor[2].collect{|n| '%.2e' % n}.join ", " - //= neighbor[2].join ", " - = (@type == "Regression") ? neighbor[2].collect{|n| n.round(2)}.join(", ") : neighbor[2].join(", ") + = (@type == "Regression") ? neighbor[2].collect{|n| '%.2e' % n}.join(", ") : neighbor[2].join(", ") / Similarity %td{:style =>"vertical-align:middle;padding-left:1em;width:20%;"} / TODO differentiate between no neighbors found and compound found in dataset, display neighbors for compounds in dataset? - = neighbor[1] != nil ? neighbor[1].round(2) : "Not enough similar compounds in training dataset." + = neighbor[1] != nil ? neighbor[1].round(2) : "Not enough similar compounds
in training dataset." - else - %span.btn.btn-default.disabled Not enough similar compounds in training dataset + %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 diff --git a/views/predict.haml b/views/predict.haml index 634054a..096fe95 100644 --- a/views/predict.haml +++ b/views/predict.haml @@ -1,6 +1,18 @@ -%link{ :href=>"/jsme/jsa.css", :rel=>"stylesheet"} +%link{ :href=>"/jsme/jsa.css", :rel=>"stylesheet", :property=>"stylesheet"} %script{:src=>"/jsme/jsme.nocache.js"} :javascript + 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() { $('a[data-toggle="tab"]').on('click', function (e) { localStorage.setItem('lastTab', $(e.target).attr('href')); @@ -124,140 +136,36 @@ %h2 2. Select one or more endpoints #models - @endpoints.each do |endpoint| - %div{:id=>endpoint} + %div{:id=>endpoint.gsub(/\s+/, "_")} %h4.head-back=endpoint - @models.select{|m| m.endpoint == endpoint}.each do |model| %div.row{:id => model.id} %span.col-sm-4 - %input{:type => "checkbox", :name => "selection[#{model.id}]", :id => "selection[#{model.species}]", :value => true, :disabled => false} - %label{:for => "selection[#{model.species}]"} + %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-sm-8 - %a.btn.btn-default.btn-xs{:data=>{:toggle=>"collapse"}, :href=>"#details#{model.id}", :id => "link#{model.id}", :style=>"font-size:small;"} + %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;"} 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;"} - %b Model: - %br - Source: - %a{:href=>model.source, :rel=>"external"} - = model.source - %br - = "Algorithm:\tLAZAR" - %br - - model.classification? ? type = "Classification" : type = "Regression" - = "Type:\t" - = type - %br - - training_dataset = OpenTox::Dataset.find model.training_dataset.id - = "Training dataset:\t" - = training_dataset.source.split("/").last - %br - = "Training compounds:\t" - = training_dataset.compounds.size - - %p - %b Validation (repeated): - %div.row{:style=>"background-color:#f5f5f5;"} - - model.crossvalidations.each do |crossvalidation| - %span.col-xs-4.col-sm-4.col-md-4.col-lg-4 - - cv = OpenTox::CrossValidation.find crossvalidation.id - = "Num folds:\t" - = cv.folds - %br - = "Num instances:\t" - = cv.nr_instances - %br - = "Num unpredicted" - = cv.nr_unpredicted - - if model.classification? - %br - = "Accuracy:\t" - = cv.accuracy.round(3) if cv.accuracy - %br - = "Weighted Accuracy:\t" - = cv.weighted_accuracy.round(3) if cv.weighted_accuracy - %br - = "True positive rate:\t" - = cv.true_rate["active"].round(3) if cv.true_rate["active"] - %br - = "True negative rate:\t" - = cv.true_rate["inactive"].round(3) if cv.true_rate["inactive"] - %br - = "Positive predictive value:\t" - = cv.predictivity["active"].round(3) if cv.predictivity["active"] - %br - = "Negative predictive value:\t" - = cv.predictivity["inactive"].round(3) if cv.predictivity["inactive"] - %p - %b 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 - =cv.confusion_matrix[0][0] - %td - =cv.confusion_matrix[0][1] - -#%td - =cv.confusion_matrix[0][0]+cv.confusion_matrix[0][1] - %tr - %td - %td inactive - %td - =cv.confusion_matrix[1][0] - %td - =cv.confusion_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 - - if model.regression? - %br - = "Root mean squared error:\t" - = cv.rmse.round(3) if cv.rmse - %br - = "Weighted root mean squared error:\t" - = cv.weighted_rmse.round(3) if cv.weighted_rmse - %br - = "Mean absolute error:\t" - = cv.mae.round(3) if cv.mae - %br - = "Weighted mean absolute error:\t" - = cv.weighted_mae.round(3) if cv.weighted_mae - %br - = "R square:\t" - = cv.r_squared.round(3) if cv.r_squared - /%br - /= "Correlation plot" - /= cv.correlation_plot - /%br - /= "Confidence plot:" - /= cv.confidence_plot - - + :javascript + function load#{model.id}Details(model) { + button = document.getElementById("link#{model.id}"); + 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(); + }); + } + } %fieldset#bottom.well %div.row %div.col-md-2 @@ -265,4 +173,4 @@ 3. Predict %div.col-md-10 %input.btn.btn-warning.h2{ :type => "submit", :id => "submit", :value=>">>", :onclick => "getsmiles()"} - %img.h2{:src=>"/images/wait30trans.gif", :id=>"circle", :class=>"circle", :style=>"display:none;"} + %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 47bd9b7..191ff15 100644 --- a/views/prediction.haml +++ b/views/prediction.haml @@ -8,14 +8,11 @@ %div.well %a.btn.btn-warning{:href => to('/predict')} %i.glyphicon.glyphicon-menu-left - Make New Prediction + New Prediction / displays all prediction result in first table + %h3 Prediction Results: %div.table-responsive %table.table.table-bordered{:id=>"overview", :style=>"background-color:white;"} - %thead - %tr - %h3 Prediction Results: - %tbody %tr %td{:id=>"compound", :style=>"vertical-align:top;"} @@ -23,7 +20,7 @@ %p= @compound.smiles - @predictions.each_with_index do |prediction,i| - type = @models[i].model.class.to_s.match("Classification") ? "Classification" : "Regression" - %td{:style=>"vertical-align:top;"} + %td{:style=>"vertical-align:top;white-space:nowrap;"} %b{:class => "title"} = "#{@models[i].endpoint.gsub('_', ' ')} (#{@models[i].species})" %p @@ -61,7 +58,7 @@ %p - else %p - Not enough similar compounds in training dataset. + = "Not enough similar compounds
in training dataset." / always show the neighbors table, message is given there = haml :neighbors, :layout => false, :model_type => @model_type -- cgit v1.2.3