summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgebele <gebele@in-silico.ch>2018-03-23 07:27:40 +0000
committergebele <gebele@in-silico.ch>2018-03-23 07:27:40 +0000
commit53da85660cc761fd49b33097ced875e09d3e9eed (patch)
tree341e0bf8d6326c0d96c67a14f165b86fc9321789
parent4aeecf41ff4659dc181fb4cad9658899d605f52c (diff)
store uploaded datasets
-rw-r--r--application.rb79
-rw-r--r--helper.rb7
-rw-r--r--views/predict.haml84
-rw-r--r--views/style.scss9
4 files changed, 132 insertions, 47 deletions
diff --git a/application.rb b/application.rb
index 04b5aa3..8f78845 100644
--- a/application.rb
+++ b/application.rb
@@ -33,6 +33,7 @@ get '/predict/?' do
rescue
nil
end
+ @existing_datasets = dataset_storage
@models = Model::Validation.all
@models = @models.delete_if{|m| m.model.name =~ /\b(Net cell association)\b/}
@endpoints = @models.collect{|m| m.endpoint}.sort.uniq
@@ -136,6 +137,22 @@ get '/predict/dataset/:name' do
csv
end
+get '/download/dataset/:id' do
+ response['Content-Type'] = "text/csv"
+ dataset = Dataset.find params[:id]
+ tempfile = Tempfile.new
+ tempfile.write(File.read("tmp/"+dataset.name+".csv"))
+ tempfile.rewind
+ send_file tempfile, :filename => dataset.name+".csv", :type => "text/csv", :disposition => "attachment"
+end
+
+get '/delete/dataset/:id' do
+ dataset = Dataset.find params[:id]
+ dataset.delete
+ File.delete File.join("tmp/"+dataset.name+".csv")
+ redirect to("/")
+end
+
get '/predict/csv/:task/:model/:filename/?' do
response['Content-Type'] = "text/csv"
task = Task.find params[:task].to_s
@@ -156,35 +173,49 @@ get '/predict/csv/:task/:model/:filename/?' do
end
post '/predict/?' do
-
# process batch prediction
- if !params[:fileselect].blank?
- if params[:fileselect][:filename] !~ /\.csv$/
- bad_request_error "Wrong file extension for '#{params[:fileselect][:filename]}'. Please upload a CSV file."
+ if !params[:fileselect].blank? || !params[:existing].blank?
+ if !params[:existing].blank?
+ @dataset = Dataset.find params[:existing].keys[0]
+ @compounds = @dataset.compounds
+ @filename = @dataset.name
end
- File.open('tmp/' + params[:fileselect][:filename], "w") do |f|
- f.write(params[:fileselect][:tempfile].read)
- end
- @filename = params[:fileselect][:filename]
- begin
- input = Dataset.from_csv_file File.join("tmp", params[:fileselect][:filename]), true
- $logger.debug "save dataset #{params[:fileselect][:filename]}"
- if input.class == OpenTox::Dataset
- @dataset = Dataset.find input
- @compounds = @dataset.compounds
- else
+ if !params[:fileselect].blank?
+ if params[:fileselect][:filename] !~ /\.csv$/
+ bad_request_error "Wrong file extension for '#{params[:fileselect][:filename]}'. Please upload a CSV file."
+ end
+ @filename = params[:fileselect][:filename]
+ begin
+ @dataset = Dataset.find_by(:name => params[:fileselect][:filename].sub(/\.csv$/,""))
+ if @dataset
+ $logger.debug "Take file from database."
+ @compounds = @dataset.compounds
+ else
+ File.open('tmp/' + params[:fileselect][:filename], "w") do |f|
+ f.write(params[:fileselect][:tempfile].read)
+ end
+ input = Dataset.from_csv_file File.join("tmp", params[:fileselect][:filename]), true
+ $logger.debug "Processing '#{params[:fileselect][:filename]}'"
+ if input.class == OpenTox::Dataset
+ @dataset = input
+ @compounds = input.compounds
+ else
+ File.delete File.join("tmp", params[:fileselect][:filename])
+ bad_request_error "Could not serialize file '#{@filename}'."
+ end
+ end
+ rescue
+ File.delete File.join("tmp", params[:fileselect][:filename])
bad_request_error "Could not serialize file '#{@filename}'."
end
- rescue
- bad_request_error "Could not serialize file '#{@filename}'."
- end
- if @compounds.size == 0
- message = dataset[:warnings]
- @dataset.delete
- bad_request_error message
+ if @compounds.size == 0
+ message = dataset[:warnings]
+ @dataset.delete
+ bad_request_error message
+ end
end
-
+
@models = params[:selection].keys
# for single predictions in batch
@tasks = []
@@ -322,7 +353,7 @@ post '/predict/?' do
@pid = task.pid
#@dataset.delete
- File.delete File.join("tmp", params[:fileselect][:filename])
+ #File.delete File.join("tmp", params[:fileselect][:filename])
return haml :batch
end
diff --git a/helper.rb b/helper.rb
index fd3b9f4..dc4b695 100644
--- a/helper.rb
+++ b/helper.rb
@@ -122,4 +122,11 @@ helpers do
csv
end
+ def dataset_storage
+ all = Dataset.where(:source => /^tmp/)
+ out = Hash.new
+ all.reverse.each{|d| out[d.id] = [d.name, d.created_at]}
+ out
+ end
+
end
diff --git a/views/predict.haml b/views/predict.haml
index 6b1c462..054bfa2 100644
--- a/views/predict.haml
+++ b/views/predict.haml
@@ -26,7 +26,14 @@
function getInput(){
identifier = document.getElementById("identifier").value.trim();
fileselect = document.getElementById("fileselect").value;
- if (fileselect != ""){
+ allexisting = document.querySelectorAll('[id^="existing"]');
+ existingcsv = false
+ for (var index = 0; index < allexisting.length; index++) {
+ if(allexisting[index].checked == true) {
+ existingcsv = true;
+ };
+ };
+ if (fileselect != "" || existingcsv == true){
return 1;
};
if (identifier != ""){
@@ -70,6 +77,12 @@
//TODO check file type is csv
return true;
};
+ allexisting = document.querySelectorAll('[id^="existing"]');
+ for (var index = 0; index < allexisting.length; index++) {
+ if(allexisting[index].checked == true) {
+ return true;
+ };
+ };
alert("Please select a file (csv).");
return false;
};
@@ -85,11 +98,12 @@
};
function checkboxes () {
var checked = false;
- $('input[type="checkbox"]').each(function() {
- if ($(this).is(":checked")) {
+ models = document.querySelectorAll('[id^="selection"]');
+ for (var index = 0; index < models.length; index++) {
+ if(models[index].checked == true) {
checked = true;
};
- });
+ };
if (checked == false){
alert("Please select an endpoint.");
$("img.circle").hide();
@@ -114,23 +128,43 @@
%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
- %label &nbsp;
- #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:
- %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
- %input{:type=>"file", :name=> "fileselect", :id=>"fileselect", :autocomplete=>"off", :accept=>"text/csv"}
+ %div.row
+ %div.col-md-6
+ #insert
+ %label &nbsp;
+ #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:
+ %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:"First column must contain a header with \"SMILES\" or \"InChI\" and the compounds. Also note that a file with the same name of a file that already exists won't be processed."}}
+ %br
+ %span.btn.btn-default.btn-file
+ %input{:type=>"file", :name=> "fileselect", :id=>"fileselect", :autocomplete=>"off", :accept=>"text/csv"}
+ %div.col-md-6
+ - if !@existing_datasets.blank?
+ %label{:for=>"storage"} or select an uploaded CSV file
+ #storage.storage-list
+ - @existing_datasets.each do |id,values|
+ %div.p2
+ %input.checkDataset{:type => "checkbox", :name => "existing[#{id}]", :id => "existing[#{id}]", :value => true, :disabled => false}
+ %div.btn-group{:role=>"group", :aria=>{:label=>"remove-download"}}
+ %a.btn.btn-secondary{:role=>"button", :href=>to("/delete/dataset/#{id}")}
+ %i.glyphicon.glyphicon-trash
+ %a.btn.btn-secondary{:role=>"button", :href=>to("/download/dataset/#{id}")}
+ %i.glyphicon.glyphicon-save
+ %div.p2
+ %label{:for => "existing[#{id}]"}
+ = values[0]
+ %div.p2
+ = values[1].strftime("%Y-%m-%d %H:%M:%S")
+ %hr
%fieldset#middle.well
%h2 2. Select one or more endpoints
@@ -146,6 +180,9 @@
$(".check").prop('checked', false);
};
});
+ $(".checkDataset").click(function () {
+ $('.checkDataset').not(this).prop('checked', false);
+ });
- @endpoints.each do |endpoint|
%div{:id=>endpoint.gsub(/\s+/, "_")}
%h4.head-back=endpoint
@@ -197,6 +234,7 @@
%div.col-md-2
%h2
3. Predict
- %div.col-md-10
- %input.btn.btn-warning.h2{ :type => "submit", :id => "submit", :value=>">>", :onclick => "getsmiles()"}
+ %div.col-md-10.input-group
+ %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;"}
diff --git a/views/style.scss b/views/style.scss
index 46c57c6..fc6f8f2 100644
--- a/views/style.scss
+++ b/views/style.scss
@@ -26,6 +26,10 @@
}
body {
background-color:#E7E7E7;
+
+ a {
+ color: inherit;
+ }
}
table.table-borderless tbody tr td{
border-top: none;
@@ -111,3 +115,8 @@ tr.hide-top > td {
.footer{
margin-top:3em;
}
+.storage-list {
+ height: 400px;
+ overflow-y: auto;
+ overflow-x: auto;
+}