summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormr <mr@mrautenberg.de>2011-10-19 13:11:24 +0200
committermr <mr@mrautenberg.de>2011-10-19 13:11:24 +0200
commitd89c87e844e81d016ab3ba8a240e03a609a7015e (patch)
tree6d5323fee132cfdaa492f9844704a9f855ff2635
parent778c58cad1c6a5b81655d731992c64a0efcec592 (diff)
parentf53928a35754c29f7ee912ed5f405731d451f49e (diff)
Merge branch 'release/v3.0.1'v3.0.1
-rw-r--r--ChangeLog6
-rw-r--r--application.rb33
-rw-r--r--helper.rb42
-rw-r--r--model.rb2
-rwxr-xr-xpublic/javascripts/toxcreate.js50
-rw-r--r--views/create.haml30
-rw-r--r--views/create_echa.haml2
-rw-r--r--views/model.haml3
-rw-r--r--views/model_echa.haml2
-rw-r--r--views/models.haml1
-rw-r--r--views/models_navigation.haml46
-rw-r--r--views/models_navigation_bottom.haml42
-rw-r--r--views/neighbors.haml2
-rw-r--r--views/predict.haml5
-rw-r--r--views/style.sass64
15 files changed, 258 insertions, 72 deletions
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..51762ea
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,6 @@
+v3.0.1 2011-10-19
+ * assign a model to an endpoints on creating a new model,
+ endpoint-list from ontology service,
+ endpoint uri in "Training dataset"
+ * fix missing "measured activity" predicting a classification model
+
diff --git a/application.rb b/application.rb
index 6d9ea76..6cdfcfb 100644
--- a/application.rb
+++ b/application.rb
@@ -96,8 +96,22 @@ get '/models/?' do
sort_by = params["sort_by"]
if sort_by
case sort_by
- when "name", "created_at", "type"
- @models = ToxCreateModel.all.sort_by(sort_by.to_sym, :order => "#{order} ALPHA")
+ when "created_at"
+ @models = ToxCreateModel.all.sort(:order => "#{order}")
+ when "name"
+ @models = ToxCreateModel.all.sort
+ if order == "ASC"
+ @models = @models.sort_by{|x| x.name.downcase}
+ else
+ @models = @models.sort{|x, y| y.name.downcase <=> x.name.downcase}
+ end
+ when "type", "endpoint"
+ @models = ToxCreateModel.all.sort
+ if order == "ASC"
+ @models = @models.sort_by{|x| [x.send(sort_by.to_sym),x.name.downcase]}
+ else
+ @models = @models.sort{|x,y|[y.send(sort_by.to_sym),x.name.downcase] <=> [x.send(sort_by.to_sym), y.name.downcase]}
+ end
when "id"
@models = ToxCreateModel.all.sort(:order => "#{order}")
end
@@ -186,8 +200,9 @@ get '/model/:id/:view/?' do
end
get '/predict/?' do
- @models = ToxCreateModel.all.sort(:order => "DESC")
+ @models = ToxCreateModel.all.sort
@models = @models.collect{|m| m if m.status == 'Completed'}.compact
+ @models = @models.sort_by{|x| [x.endpoint ? x.endpoint : "",x.name.downcase]}
haml :predict
end
@@ -232,8 +247,8 @@ end
post '/models' do # create a new model
- unless (params[:dataset] and params[:prediction_feature]) or (params[:file] and params[:file][:tempfile]) #params[:endpoint] and
- flash[:notice] = "Please upload a Excel or CSV file or select an AMBIT dataset."
+ unless (params[:dataset] and params[:prediction_feature]) or (params[:endpoint] and params[:file] and params[:file][:tempfile]) #params[:endpoint] and
+ flash[:notice] = "Please upload a Excel or CSV file and select an endpoint or select an AMBIT dataset."
redirect url_for('/create')
end
@@ -280,6 +295,8 @@ post '/models' do # create a new model
else
raise "#{params[:file][:filename]} has an unsupported file type."
end
+ @dataset.features[@dataset.features.keys.first][OWL.sameAs] = params[:endpoint].split(',').first if params[:endpoint]
+ @model.update :endpoint_uri => params[:endpoint].split(',').first, :endpoint => params[:endpoint].split(',')[1..99].to_s.gsub(/^"(.*?)"$/,'\1') if params[:endpoint]
@dataset.save(@subjectid)
rescue => e
error "Dataset creation failed '#{e.message}'",e
@@ -289,8 +306,12 @@ post '/models' do # create a new model
else
@prediction_feature = OpenTox::Feature.find(@dataset.features.keys.first,@subjectid)
end
+ #else
+ # test when external dataset is enabled:
+ #if @dataset.features[@dataset.features.keys.first][OWL.sameAs]
+ # @model.update :endpoint_uri => @dataset.features[@dataset.features.keys.first][OWL.sameAs], :endpoint => OpenTox::Ontology::Echa.get_endpoint_name(@dataset.features[@dataset.features.keys.first][OWL.sameAs])
+ #end
end
-
task.progress(10)
if @dataset.compounds.size < 10
error "Too few compounds to create a prediction model. Did you provide compounds in SMILES format and classification activities as described in the #{link_to "instructions", "/help"}? As a rule of thumb you will need at least 100 training compounds for nongeneric datasets. A lower number could be sufficient for congeneric datasets."
diff --git a/helper.rb b/helper.rb
index 9b47142..11f99f7 100644
--- a/helper.rb
+++ b/helper.rb
@@ -96,9 +96,14 @@ helpers do
haml :models_navigation, :layout => false
end
+ def models_navigation_bottom
+ @page = 0 unless @page
+ haml :models_navigation_bottom, :layout => false
+ end
+
def endpoint_option_list(max_time=3600)
out = ""
- tmpfile = File.join(TMP_DIR, "endpoint_option_list")
+ tmpfile = File.join(TMP_DIR, 'endpoint_option_list')
if File.exists? tmpfile
if Time.now-File.mtime(tmpfile) <= max_time
f = File.open(tmpfile, 'r+')
@@ -108,12 +113,39 @@ helpers do
File.unlink(tmpfile)
end
end
- result = OpenTox::Ontology::Echa.endpoint_option_list()
+ result = endpoint_selection()
if result.lines.count > 3
- f = File.new(tmpfile,"w")
+ f = File.new(tmpfile,'w')
f.print result
f.close
end
- return result
+ result
+ end
+
+ def endpoint_level(endpoint="Endpoints", level=1)
+ results = OpenTox::Ontology::Echa.echa_endpoints(endpoint) rescue results = []
+ out = ""
+ out += "<ul id='list_#{endpoint}' class='endpoint level_#{level}'>\n" if results.size > 0
+ results.each do |result|
+ r = result.split(',')
+ endpointname = CGI.escape(r.first.split("#").last).gsub(".","")
+ title = r[1..r.size-1].to_s
+ out += " <li class='level_#{level}'><input type='radio' name='endpoint' value='#{result}' id='#{endpointname}' class='endpoint_list' /><label for='#{endpointname}' id='label_#{endpointname}'>#{title.gsub("\"","")}</label>\n"
+ out += endpoint_level(endpointname, level + 1)
+ out += "</li>\n"
+ end
+ out += "</ul>\n" if results.size > 0
+ return out
end
-end
+
+ def endpoint_selection()
+ out = "<span id='endpoint_label'></span><input type='button' id='endpoint_list_button' value='Select endpoint' /> \n
+ <div id='div_endpoint'>\n"
+ out += "<b>Please select:</b>\n"
+ out += endpoint_level
+ js = ""
+ out += "</div>\n"
+ return out
+ end
+
+end \ No newline at end of file
diff --git a/model.rb b/model.rb
index bab5bde..05075f8 100644
--- a/model.rb
+++ b/model.rb
@@ -19,6 +19,8 @@ class ToxCreateModel < Ohm::Model
attribute :training_dataset
attribute :feature_dataset
+ attribute :endpoint_uri
+ attribute :endpoint
#attributey :validation_task_uri
attribute :validation_uri
diff --git a/public/javascripts/toxcreate.js b/public/javascripts/toxcreate.js
index 0e82040..ef2a953 100755
--- a/public/javascripts/toxcreate.js
+++ b/public/javascripts/toxcreate.js
@@ -25,12 +25,12 @@ $(function() {
$.each(stati, function(){
checkProgress(this);
if(checkStatus(this) > 0) newstati.push(this);
- });
+ });
if (newstati.length > 0) var statusCheck = setTimeout('checkStati("' + newstati.join(", ") + '")',10000);
};
-
+
checkStatus = function(id) {
- if(id == "") return -1;
+ if(id == "") return -1;
var opts = {method: 'get', action: 'model/' + id + '/status', id: id};
var status_changed = $.ajax({
type: opts.method,
@@ -43,15 +43,15 @@ $(function() {
success: function(data) {
var status_before = "";
if ($("span#model_" + id + "_status") != null) status_before = $("span#model_" + id + "_status").html().trim();
- if (status_before == "Deleting") return -1;
+ if (status_before == "Deleting") return -1;
var status_after = data.trim();
$("span#model_" + id + "_status").animate({"opacity": "0.2"},1000);
$("span#model_" + id + "_status").animate({"opacity": "1"},1000);
if( status_before != status_after) {
- $("span#model_" + id + "_status").html(data);
+ $("span#model_" + id + "_status").html(data);
loadModel(id, 'model');
if (status_after == "Completed" || status_after == "Error") id = -1;
- }
+ }
},
error: function(data) {
//alert("status check error");
@@ -60,8 +60,8 @@ $(function() {
});
return id;
};
-
-
+
+
checkProgress = function(id) {
var task = $("input#model_" + id + "_task").attr('value');
var opts = {action: task + "/percentageCompleted" , id: id};
@@ -74,9 +74,8 @@ $(function() {
},
success: function(data) {
var progress = data.trim();
- if (progress == "100") return -1;
-
- $("div#model_" + id + "_progress").progressbar("value", parseInt(progress));
+ if (progress == "100") return -1;
+ $("div#model_" + id + "_progress").progressbar("value", parseInt(progress));
$("div#model_" + id + "_progress").attr({title: parseInt(progress) + "%"});
},
error: function(data) {
@@ -84,10 +83,10 @@ $(function() {
}
});
return id;
- };
+ };
loadModel = function(id, view) {
- if(id == "") return -1;
+ if(id == "") return -1;
var opts = {method: 'get', action: 'model/' + id + '/' + view, view: view };
var out = id;
$.ajax({
@@ -118,7 +117,7 @@ jQuery.fn.editModel = function(options) {
trigger_on: 'click'
};
var opts = $.extend(defaults, options);
- this.bind(opts.trigger_on, function() {
+ this.bind(opts.trigger_on, function() {
$.ajax({
type: opts.method,
url: opts.action,
@@ -126,7 +125,7 @@ jQuery.fn.editModel = function(options) {
data: {
'_method': 'get'
},
- success: function(data) {
+ success: function(data) {
$("div#model_" + opts.id + "_name").html(data);
$("input#model_" + opts.id + "_name").focus();
},
@@ -145,8 +144,8 @@ jQuery.fn.cancelEdit = function(options) {
trigger_on: 'click'
};
var opts = $.extend(defaults, options);
-
- this.bind(opts.trigger_on, function() {
+
+ this.bind(opts.trigger_on, function() {
$.ajax({
type: opts.method,
url: opts.action,
@@ -154,7 +153,7 @@ jQuery.fn.cancelEdit = function(options) {
data: {
'_method': 'get'
},
- success: function(data) {
+ success: function(data) {
$("div#model_" + opts.id + "_name").html(data);
},
error: function(data) {
@@ -172,9 +171,9 @@ jQuery.fn.saveModel = function(options) {
trigger_on: 'click'
};
var opts = $.extend(defaults, options);
-
- this.bind(opts.trigger_on, function() {
- var name = $("input#model_" + opts.id + "_name").val();
+
+ this.bind(opts.trigger_on, function() {
+ var name = $("input#model_" + opts.id + "_name").val();
$.ajax({
type: opts.method,
url: opts.action,
@@ -183,7 +182,7 @@ jQuery.fn.saveModel = function(options) {
'_method': 'put',
'name': name
},
- success: function(data) {
+ success: function(data) {
$("div#model_" + opts.id + "_name").html(data);
},
error: function(data) {
@@ -215,7 +214,7 @@ jQuery.fn.deleteModel = function(type, options) {
data: {
'_method': 'delete'
},
- success: function(data) {
+ success: function(data) {
$("div#model_" + opts.id).fadeTo("slow",0).slideUp("slow").remove();
},
error: function(data) {
@@ -236,9 +235,6 @@ addExternalLinks = function() {
$('A[rel="external"]').each(function() {
$(this).attr('alt', 'Link opens in new window.');
$(this).attr('title', 'Link opens in new window.');
- });
- $('A[rel="external"]').click(function() {
- window.open($(this).attr('href'));
- return false;
+ $(this).attr('target', '_blank');
});
};
diff --git a/views/create.haml b/views/create.haml
index da85382..9b0ca09 100644
--- a/views/create.haml
+++ b/views/create.haml
@@ -1,3 +1,30 @@
+:javascript
+ $(document).ready(function() {
+ $(".endpoint_list").click(function() {
+ elem = this.id;
+ title = $("label#label_" + elem).html();
+ if($("ul#list_" + elem)) {
+ if ($("ul#list_" + elem).is(":hidden")) {
+ $("ul#list_" + elem).slideDown("slow");
+ } else {
+ $("ul#list_" + elem).slideUp("slow");
+ }
+ }
+ $("span#endpoint_label").html(title);
+ });
+ $("#endpoint_list_button").click(function() {
+ if ($("div#div_endpoint").is(":hidden")) {
+ $("div#div_endpoint").slideDown("slow");
+ $("input#endpoint_list_button").val("Hide");
+ $("input#endpoint_list_button").toggleClass("ok_button", true);
+ } else {
+ $("div#div_endpoint").slideUp("slow");
+ $("input#endpoint_list_button").val("Select endpoint");
+ $("input#endpoint_list_button").toggleClass("ok_button", false);
+ }
+ });
+ });
+
.input
%p
@@ -25,7 +52,8 @@
format:
%input{:type => 'file', :name => 'file', :id => 'file', :size => '41'}
%br
- -# = haml :model_echa, :layout => false
+ = haml :create_echa, :layout => false
+ %br
%input{ :type => "submit", :value => "Create model"}
=# link_to "Cancel", '/create'
diff --git a/views/create_echa.haml b/views/create_echa.haml
new file mode 100644
index 0000000..4815c35
--- /dev/null
+++ b/views/create_echa.haml
@@ -0,0 +1,2 @@
+For endpoint:
+= endpoint_option_list() \ No newline at end of file
diff --git a/views/model.haml b/views/model.haml
index 356ec65..fb264ca 100644
--- a/views/model.haml
+++ b/views/model.haml
@@ -40,6 +40,9 @@
- if model.nr_compounds
%dt Training compounds:
%dd= model.nr_compounds
+ - if model.endpoint
+ %dt Endpoint:
+ %dd= model.endpoint
- if model.error_messages
%dt Errors:
%dd= model.error_messages
diff --git a/views/model_echa.haml b/views/model_echa.haml
deleted file mode 100644
index 257a28a..0000000
--- a/views/model_echa.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-Select an endpoint:
-= endpoint_option_list \ No newline at end of file
diff --git a/views/models.haml b/views/models.haml
index 1419e37..af11a32 100644
--- a/views/models.haml
+++ b/views/models.haml
@@ -26,3 +26,4 @@
= haml :model, :locals=>{:model=>model}, :layout => false
-if @models.size == 0
.notice There are currently no models. You have to create a model first.
+= models_navigation_bottom if @models.size > 1 \ No newline at end of file
diff --git a/views/models_navigation.haml b/views/models_navigation.haml
index b491cb5..c5eda97 100644
--- a/views/models_navigation.haml
+++ b/views/models_navigation.haml
@@ -1,12 +1,12 @@
.models_navigation
-
+ - js = ""
%form{:name => "nav", :action => url_for('/models'), :method => "get", :id => "nav"}
%input{:type => :hidden, :name => :sort_by, :id => "sort_by", :value => params[:sort_by]}
%input{:type => :hidden, :name => :order, :id => "order", :value => params[:order]}
%input{:type => :hidden, :name => :page, :id => "page", :value => params[:page]}
Sort by:
- - ["created_at","name","type"].each do |s|
+ - ["created_at","name","type","endpoint"].each do |s|
- idname = s == "created_at" ? "date" : s
- if params[:sort_by] == s
%div{:id => idname, :class => "active"}
@@ -22,32 +22,42 @@
- if @models.size > 5
|
Models:
- = "#{@models.size}"
- - unless @page.to_i == 0
- #prev
- %img{:src => "arrow_left.png", :alt => 'previous', :title => 'previous'}/
- -else
- %img{:src => "arrow_left_inactive.png", :alt => '', :title => ''}/
-
- if @models.size < 5*@page+5
- last = @models.size
- else
- last = 5*@page+5
-
- = "(#{5*@page+1}-#{last}/#{@models.size})"
+
+ = "#{5*@page+1}-#{last} / #{@models.size}"
+
+ | Page:
+ - unless @page.to_i == 0
+ #prev{:class => "link"}
+ %img{:src => "arrow_left.png", :alt => 'previous', :title => 'previous'}/
+ -else
+ %img{:src => "arrow_left_inactive.png", :alt => '', :title => ''}/
+
+ - (0..(@models.size/5).to_f.ceil-1).each do |p|
+ -if p != @page.to_f
+ %a{:href => '#', :id => "page_link_#{p}", :class => "page page_link"} #{p+1}
+ - js += "$('#page_link_#{p}').click(function() \{ \n"
+ - js += " $('#page').val('#{p}');\n"
+ - js += " $('#nav').submit();\n"
+ - js += "});\n"
+ -else
+ %span{:class => "page page_active"} #{p+1}
+
- unless 5*@page.to_i+5 >= @models.size
- #next
+ #next{:class => "link"}
%img{:src => "arrow_right.png", :alt => 'next', :title => 'next'}/
-else
%img{:src => "arrow_right_inactive.png", :alt => '', :title => ''}/
- - js = ""
- - ["id","created_at","name","type"].each do |s|
+ - ["created_at","name","type","endpoint"].each do |s|
- idname = s == "created_at" ? "date" : s
- - js += "$('##{idname}').click(function() \{ \n "
- - js += " $('#sort_by').val('#{s}');\n "
- - js += " $('#nav').submit();\n "
- - js += "});\n "
+ - js += "$('##{idname}').click(function() \{ \n"
+ - js += " $('#sort_by').val('#{s}');\n"
+ - js += " $('#nav').submit();\n"
+ - js += "});\n"
:javascript
$("#prev").click(function() {
diff --git a/views/models_navigation_bottom.haml b/views/models_navigation_bottom.haml
new file mode 100644
index 0000000..b2425fa
--- /dev/null
+++ b/views/models_navigation_bottom.haml
@@ -0,0 +1,42 @@
+.models_navigation
+ - js = ""
+ - if @models.size > 5
+ Models:
+ - if @models.size < 5*@page+5
+ - last = @models.size
+ - else
+ - last = 5*@page+5
+ = "#{5*@page+1}-#{last} / #{@models.size}"
+ | Page:
+ - unless @page.to_i == 0
+ #prevbot{:class => "link"}
+ %img{:src => "arrow_left.png", :alt => 'previous', :title => 'previous'}/
+ -else
+ %img{:src => "arrow_left_inactive.png", :alt => '', :title => ''}/
+
+ - (0..(@models.size/5).to_f.ceil-1).each do |p|
+ -if p != @page.to_f
+ %a{:href => '#', :id => "page_linkbot_#{p}", :class => "page page_link"} #{p+1}
+ - js += "$('#page_linkbot_#{p}').click(function() \{ \n"
+ - js += " $('#page').val('#{p}');\n"
+ - js += " $('#nav').submit();\n"
+ - js += "});\n"
+ -else
+ %span{:class => "page page_active"} #{p+1}
+
+ - unless 5*@page.to_i+5 >= @models.size
+ #nextbot{:class => "link"}
+ %img{:src => "arrow_right.png", :alt => 'next', :title => 'next'}/
+ -else
+ %img{:src => "arrow_right_inactive.png", :alt => '', :title => ''}/
+
+ :javascript
+ $("#prevbot").click(function() {
+ $("#page").val(#{@page-1});
+ $("#nav").submit();
+ });
+ $("#nextbot").click(function() {
+ $("#page").val(#{@page+1});
+ $("#nav").submit();
+ });
+ #{js} \ No newline at end of file
diff --git a/views/neighbors.haml b/views/neighbors.haml
index e2d65fa..49b72b7 100644
--- a/views/neighbors.haml
+++ b/views/neighbors.haml
@@ -14,7 +14,7 @@
- compound = OpenTox::Compound.new(neighbor[OT.compound])
%tr
%td.image= compound_image(compound,@prediction.descriptors(compound),@value_map)
- %td= activity_markup(neighbor[OT.measuredActivity], @value_map)
+ %td= activity_markup(neighbor[OT.measuredActivity].to_s, @value_map)
%td= sprintf('%.03g', neighbor[OT.similarity])
%td
%ul
diff --git a/views/predict.haml b/views/predict.haml
index 670ca44..c6097ac 100644
--- a/views/predict.haml
+++ b/views/predict.haml
@@ -30,7 +30,12 @@
%legend
Choose one or more prediction models
%br
+ - endpoint = ''
- @models.each do |model|
+ -if model.endpoint != endpoint
+ -endpoint = model.endpoint
+ %b #{endpoint}:
+ %br
%input{:type => 'checkbox', :name => "selection[#{model.id}]", :value => true, :id => "model#{model.id}", :disabled => false}
%label{:for => "model#{model.id}"}
= model.name
diff --git a/views/style.sass b/views/style.sass
index c2a74cb..230c13c 100644
--- a/views/style.sass
+++ b/views/style.sass
@@ -5,6 +5,7 @@ $ot_purple: #5d308a
$body_color: white
$text_color: black
$notice_border: red
+$mouseover: #FFFF69
body
min-width: 30em
@@ -269,14 +270,7 @@ dl
float: left
.models_navigation
- #prev
- @extend a
- display: inline
- cursor: pointer
- #next
- @extend a
- display: inline
- cursor: pointer
+ margin-top: 4px
.link
@extend a
display: inline
@@ -287,13 +281,59 @@ dl
font-weight: bold
.thin
font-weight: 100
+ .page
+ border: solid 1px #999
+ background-color: #FFF
+ padding: 0px 3px
+ font-size: 94%
+ font-weight: bold
+ .page_link:hover
+ border-color: #000
+ color: #000
+ .page_active
+ background-color: #ccd2dc
+ color: #000
+ font-weight: bold
+ border-right-color: #000
+ border-bottom-color: #000
+
+ul.endpoint
+ list-style-type: none
+ margin-left: 0px
+ padding-left: 0px
+
+ul.level_2
+ display: none
+ul.level_3
+ display: none
+ul.level_4
+ display: none
.level_1
- padding-left: 10px
+ margin-left: 0px
font-weight: bold
.level_2
- padding-left: 20px
+ margin-left: 20px
+ font-weight: normal
.level_3
- padding-left: 30px
+ margin-left: 40px
+ font-weight: normal
.level_4
- padding-left: 40px
+ margin-left: 60px
+ font-weight: normal
+
+#endpoint_label
+ font-weight: bold
+ margin: 0 10px
+
+ul.endpoint
+ label:hover, label:active
+ background-color: $mouseover
+ border-bottom: solid #999 1px
+ border-top: solid #999 1px
+
+#div_endpoint
+ display: none
+
+.ok_button
+ background-color: $mouseover