From 1ffdd765fe4b4d9d80626070dea652fe467a2fa5 Mon Sep 17 00:00:00 2001 From: gebele Date: Thu, 1 Aug 2019 16:48:14 +0000 Subject: introduce task for upload and parse to dataset --- application.rb | 34 +++++++++++++--- public/javascripts/lazar-gui.js | 86 ++++++++++++++++++++++++++--------------- views/batch.haml | 34 +++++++++------- 3 files changed, 102 insertions(+), 52 deletions(-) diff --git a/application.rb b/application.rb index fa2a728..8872e5f 100644 --- a/application.rb +++ b/application.rb @@ -167,7 +167,7 @@ end post '/predict/?' do # process batch prediction - if !params[:fileselect].blank? + unless params[:fileselect].blank? if params[:fileselect][:filename] !~ /\.csv$/ bad_request_error "Wrong file extension for '#{params[:fileselect][:filename]}'. Please upload a CSV file." end @@ -175,9 +175,20 @@ post '/predict/?' do 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]) - $logger.debug "Processing '#{params[:fileselect][:filename]}'" - @compounds_size = input.compounds.size + uploadTask = Task.new + uploadTask.save + uploadDataset = Task.run do + t = uploadTask + t.update_percent(1) + $logger.debug "Processing '#{params[:fileselect][:filename]}'" + @input = Dataset.from_csv_file File.join("tmp", params[:fileselect][:filename]) + t.update_percent(100) + t.save + end + @upid = uploadTask.id + + #TODO route for compound size + @compounds_size = 0 #@input.compounds.size @models = params[:selection].keys @tasks = [] @models.each{|m| t = Task.new; t.save; @tasks << t} @@ -190,6 +201,10 @@ post '/predict/?' do prediction = {} model = Model::Validation.find model_id t.update_percent(10) + input = Dataset.find_by(:source => "tmp/"+@filename) + until input + sleep 1 + end prediction_dataset = model.predict input t.update_percent(70) t[:dataset_id] = prediction_dataset.id @@ -232,10 +247,18 @@ post '/predict/?' do end get '/prediction/task/?' do + # returns task progress in percentage if params[:turi] task = Task.find(params[:turi].to_s) response['Content-Type'] = "application/json" - return JSON.pretty_generate(:percent => task.percent) + if task.dataset_id + d = Dataset.find task.dataset_id + size = d.compounds.size + return JSON.pretty_generate(:percent => task.percent, :size => size) + else + return JSON.pretty_generate(:percent => task.percent) + end + # kills task process id elsif params[:ktpid] begin Process.kill(9,params[:ktpid].to_i) if !params[:ktpid].blank? @@ -244,6 +267,7 @@ get '/prediction/task/?' do end response['Content-Type'] = "application/json" return JSON.pretty_generate(:ktpid => params[:ktpid]) + # returns task details elsif params[:predictions] task = Task.find(params[:predictions]) pageSize = params[:pageSize].to_i - 1 diff --git a/public/javascripts/lazar-gui.js b/public/javascripts/lazar-gui.js index 214529b..dcbc4c5 100644 --- a/public/javascripts/lazar-gui.js +++ b/public/javascripts/lazar-gui.js @@ -204,6 +204,19 @@ var markers = []; est.innerHTML = newtime; };*/ +uploadDataset = function(task_uri) { + var uri = task_uri; + var aClient = new HttpClient(); + aClient.get(uri, function(res) { + var response = JSON.parse(res); + if (response['percent'] == 100){ + window.clearInterval(uploadInterval); + var element = document.getElementById("uploadDataset"); + element.parentNode.removeChild(element); + }; + }); +}; + renderTask = function(task_uri,id) { var uri = task_uri; var aClient = new HttpClient(); @@ -232,39 +245,48 @@ simpleTemplating = function(data) { return html; }; -pagePredictions = function(task_uri,model_id,id,compoundsSize){ +pagePredictions = function(task_uri,model_id,id, compounds_uri){ button = document.getElementById("detailsbutton_"+id); span = button.childNodes[1]; - if (span.className == "fa fa-caret-right"){ - span.className = "fa fa-caret-down"; - $('#data-container_'+id).removeClass("d-none"); - $('#data-container_'+id).show(); - $('#pager_'+id).show(); - $('#pager_'+id).pagination({ - dataSource: task_uri, - locator: 'prediction', - totalNumber: compoundsSize, - pageSize: 1, - showPageNumbers: true, - showGoInput: true, - formatGoInput: 'go to <%= input %>', - formatAjaxError: function(jqXHR, textStatus, errorThrown) { - $('#data-container_'+id).html(errorThrown); - }, - /*ajax: { - beforeSend: function() { - $('#data-container_'+id).html('Loading content ...'); + // get compounds size first + var compoundsSize = 0; + var aClient = new HttpClient(); + aClient.get(compounds_uri, function(res) { + var response = JSON.parse(res); + compoundsSize = response['size'] + // handle pager in callback function + // ensures compoundsSize is > 0 + if (span.className == "fa fa-caret-right"){ + span.className = "fa fa-caret-down"; + $('#data-container_'+id).removeClass("d-none"); + $('#data-container_'+id).show(); + $('#pager_'+id).show(); + $('#pager_'+id).pagination({ + dataSource: task_uri, + locator: 'prediction', + totalNumber: compoundsSize, + pageSize: 1, + showPageNumbers: true, + showGoInput: true, + formatGoInput: 'go to <%= input %>', + formatAjaxError: function(jqXHR, textStatus, errorThrown) { + $('#data-container_'+id).html(errorThrown); + }, + /*ajax: { + beforeSend: function() { + $('#data-container_'+id).html('Loading content ...'); + } + },*/ + callback: function(data, pagination) { + var html = simpleTemplating(data); + $('#data-container_'+id).html(html); + //$('#data-container_'+id).css("min-height", $(window).height() + "px" ); } - },*/ - callback: function(data, pagination) { - var html = simpleTemplating(data); - $('#data-container_'+id).html(html); - //$('#data-container_'+id).css("min-height", $(window).height() + "px" ); - } - }); - } else if (span.className = "fa fa-caret-down"){ - span.className = "fa fa-caret-right"; - $('#data-container_'+id).hide(); - $('#pager_'+id).hide(); - }; + }); + } else if (span.className = "fa fa-caret-down"){ + span.className = "fa fa-caret-right"; + $('#data-container_'+id).hide(); + $('#pager_'+id).hide(); + }; + }); }; diff --git a/views/batch.haml b/views/batch.haml index efb9b71..2e48ec0 100644 --- a/views/batch.haml +++ b/views/batch.haml @@ -11,24 +11,26 @@ %a.btn.btn-outline-info{:href => to("/predict?tpid=#{@pid}")} %span.fa.fa-caret-left{:aria=>{:hidden=>"true"}} New Prediction +%div.card.bg-light{:id=>"uploadDataset"} + %div.card-body + %h3.card-title="Processing file #{@filename} to dataset." + %img.h2{:src=>"/images/wait30trans.gif", :id=>"circle_upload", :class=>"circle", :alt=>"processing"} + :javascript + uploadInterval = setInterval(function(){ + uploadDataset('#{to("/prediction/task/?turi=#{@upid}")}'); + }, 1000 ); + %div.card.bg-light %div.card-body %h3.card-title="Batch prediction results for: #{@filename}" // prepare variable values for javascript // increase timer interval for large datasets - - ctimer = ((@compounds_size/1000) == 0 ? 1000 : ((@compounds_size/1000)*1000)) - //- approx = {} - //- sum_approx = 0 + - ctimer = 1000#((@compounds_size/1000) == 0 ? 1000 : ((@compounds_size/1000)*1000)) // process batch predictions - @models.each_with_index do |model,idx| - m = Model::Validation.find model - task = @tasks[idx].id - //- tasktime = task.generation_time.to_i - // assume single compound prediction time: classification=0.1s,regression=0.5s - //- task_approx = m.classification? ? (tasktime*1000 + @compounds_size*100) : (tasktime*1000 + @compounds_size*500) - //- approx[idx] = task_approx + sum_approx - //- sum_approx += (m.classification? ? @compounds_size*100 : @compounds_size*500) #result.card.bg-light{:id=>idx} %div.card-body %div.row @@ -36,14 +38,12 @@ %h5.card-title="#{m.endpoint} (#{m.species})" #pager{:id=>idx} %div.col-6 - %a.btn.btn-outline-info.btn-sm.disabled{:id => "detailsbutton_#{idx}", :data=>{:toggle=>"collapse"}, :href=>"javascript:void(0)", :onclick=>"pagePredictions('#{to("/prediction/task/?predictions=#{task}")}','#{model}','#{idx}','#{@compounds_size}')"} + %a.btn.btn-outline-info.btn-sm.disabled{:id => "detailsbutton_#{idx}", :data=>{:toggle=>"collapse"}, :href=>"javascript:void(0)", :onclick=>"pagePredictions('#{to("/prediction/task/?predictions=#{task}")}','#{model}','#{idx}','#{to("/prediction/task/?turi=#{task}")}')"} %span.fa.fa-caret-right Details %a.btn.btn-outline-info.btn-sm.disabled{:id => "downbutton_#{idx}", :href=>"#{to("/predict/batch/download?tid=#{task}")}", :title=>"download"} %span.fa.fa-download CSV - -#%div{:id=>"progress_#{idx}", :style=>"width:100%;height:3px;position:relative;background-color:#ccc;"} - %div{:id=>"bar_#{idx}", :style=>"background-color: #4CAF50;width:10px;height:3px;position:absolute;"} %p{:id=>"est_#{idx}"} waiting ... %img.h2{:src=>"/images/wait30trans.gif", :id=>"circle_#{idx}", :class=>"circle", :alt=>"wait", :style=>"display:none;"} @@ -60,7 +60,6 @@ var button = document.getElementById("detailsbutton_"+(idx-1)); if(!button.classList.contains('disabled')){ renderTask(task_uri,idx); - //remaining(idx,approximate); $("#est_"+idx).hide(); $("#circle_"+idx).show(); } @@ -68,9 +67,14 @@ }else{ markers[idx] = setInterval(function(){ renderTask(task_uri,idx); - //remaining(idx,approximate); - $("#est_"+idx).hide(); - $("#circle_"+idx).show(); + // check that dataset parsing is completed + if (document.getElementById("uploadDataset")){ + $("#est_"+idx).show(); + $("#circle_"+idx).hide(); + } else { + $("#est_"+idx).hide(); + $("#circle_"+idx).show(); + } }, timer ); }; }; -- cgit v1.2.3