diff options
Diffstat (limited to 'application.rb')
-rw-r--r-- | application.rb | 143 |
1 files changed, 89 insertions, 54 deletions
diff --git a/application.rb b/application.rb index 7bf1059..60d50cd 100644 --- a/application.rb +++ b/application.rb @@ -1,7 +1,7 @@ ['rubygems', "haml", "sass", "rack-flash"].each do |lib| require lib end -gem "opentox-ruby", "~> 1" +gem "opentox-ruby", "~> 2" require 'opentox-ruby' gem 'sinatra-static-assets' require 'sinatra/static_assets' @@ -27,7 +27,7 @@ helpers do private def delete_model(model, subjectid=nil) task = OpenTox::Task.create("Deleting model: #{model.uri}",url_for("/delete",:full)) do |task| - begin RestClient.put(File.join(model.task_uri, 'Cancelled'),subjectid) if model.task_uri rescue LOGGER.warn "Cannot cancel task #{model.task_uri}" end + begin OpenTox::RestClientWrapper.put(File.join(model.task_uri, "Cancelled"), "Cancelled",{:subjectid => subjectid}) if model.task_uri rescue LOGGER.warn "Cannot cancel task #{model.task_uri}" end task.progress(15) delete_dependent(model.uri, subjectid) if model.uri task.progress(30) @@ -60,7 +60,7 @@ helpers do end before do - if !logged_in and !( env['REQUEST_URI'] =~ /\/login$/ and env['REQUEST_METHOD'] == "POST" ) #or !AA_SERVER + if !logged_in and !( env['REQUEST_URI'] =~ /\/login$/ and env['REQUEST_METHOD'] == "POST" ) or !AA_SERVER login("guest","guest") end end @@ -179,9 +179,30 @@ get %r{/compound/(.*)} do |inchi| OpenTox::Compound.from_inchi(inchi).to_names.join(', ') end +get '/echa' do + @endpoints = OpenTox::Ontology::Echa.endpoints + haml :echa +end + +post '/ambit' do + session[:echa] = params[:endpoint] + @datasets = OpenTox::Ontology::Echa.datasets(params[:endpoint]) + haml :ambit +end + +post '/feature' do + session[:dataset] = params[:dataset] + @features = [] + OpenTox::Dataset.new(params[:dataset]).load_features.each do |uri,metadata| + @features << OpenTox::Feature.find(uri, @subjectid) if metadata[OWL.sameAs].match(/#{session[:echa]}/) + end + haml :feature +end + post '/models' do # create a new model - unless params[:file] and params[:file][:tempfile] #params[:endpoint] and - flash[:notice] = "Please upload a Excel or CSV file." + + 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." redirect url_for('/create') end @@ -190,75 +211,93 @@ post '/models' do # create a new model flash[:notice] = "Please login to create a new model." redirect url_for('/create') end + subjectid = session[:subjectid] ? session[:subjectid] : nil - @model = ToxCreateModel.create(:name => params[:file][:filename].sub(/\..*$/,""), :subjectid => subjectid) + + if params[:dataset] and params[:prediction_feature] + @dataset = OpenTox::Dataset.new(params[:dataset],subjectid) + name = @dataset.load_metadata[DC.title] + @prediction_feature = OpenTox::Feature.find params[:prediction_feature], subjectid + @dataset.load_compounds + elsif params[:file][:filename] + name = params[:file][:filename].sub(/\..*$/,"") + end + + @model = ToxCreateModel.create(:name => name, :subjectid => subjectid) @model.update :web_uri => url_for("/model/#{@model.id}", :full), :warnings => "" task = OpenTox::Task.create("Uploading dataset and creating lazar model",url_for("/models",:full)) do |task| task.progress(5) @model.update :status => "Uploading and saving dataset", :task_uri => task.uri - begin - @dataset = OpenTox::Dataset.create(nil, subjectid) - # check format by extension - not all browsers provide correct content-type]) - case File.extname(params[:file][:filename]) - when ".csv" - csv = params[:file][:tempfile].read - @dataset.load_csv(csv, subjectid) - when ".xls", ".xlsx" - excel_file = params[:file][:tempfile].path + File.extname(params[:file][:filename]) - File.rename(params[:file][:tempfile].path, excel_file) # add extension, spreadsheet does not read files without extensions - @dataset.load_spreadsheet(Excel.new excel_file, subjectid) + + unless params[:dataset] and params[:prediction_feature] + begin + @dataset = OpenTox::Dataset.create(nil, subjectid) + # check format by extension - not all browsers provide correct content-type]) + case File.extname(params[:file][:filename]) + when ".csv" + csv = params[:file][:tempfile].read + @dataset.load_csv(csv, subjectid) + when ".xls", ".xlsx" + excel_file = params[:file][:tempfile].path + File.extname(params[:file][:filename]) + File.rename(params[:file][:tempfile].path, excel_file) # add extension, spreadsheet does not read files without extensions + @dataset.load_spreadsheet(Excel.new excel_file, subjectid) + if @dataset.metadata[OT.Errors] + error "Incorrect file format. Please follow the instructions for #{link_to "Excel", "/help"} or #{link_to "CSV", "/help"} formats." + end + else + error "#{params[:file][:filename]} has a unsupported file type." + end + @dataset.save(subjectid) + rescue => e + error "Dataset creation failed with #{e.message}" + end + if @dataset.features.keys.size != 1 + error "More than one feature in dataset #{params[:file][:filename]}. Please delete irrelvant columns and try again." else - error "#{params[:file][:filename]} has a unsupported file type." + @prediction_feature = OpenTox::Feature.find(@dataset.features.keys.first,subjectid) end - rescue => e - error "Dataset creation failed with #{e.message}" end - @dataset.save(subjectid) + 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", "/excel_format"}? 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." - end - if @dataset.features.keys.size != 1 - error "More than one feature in dataset #{params[:file][:filename]}. Please delete irrelvant columns and try again." - end - if @dataset.metadata[OT.Errors] - error "Incorrect file format. Please follow the instructions for #{link_to "Excel", "/excel_format"} or #{link_to "CSV", "/csv_format"} formats." + 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." end @model.update :training_dataset => @dataset.uri, :nr_compounds => @dataset.compounds.size, :status => "Creating prediction model" - @model.update :warnings => @dataset.metadata[OT.Warnings] unless @dataset.metadata[OT.Warnings].empty? + @model.update :warnings => @dataset.metadata[OT.Warnings] unless @dataset.metadata[OT.Warnings] and @dataset.metadata[OT.Warnings].empty? task.progress(15) begin - lazar = OpenTox::Model::Lazar.create(:dataset_uri => @dataset.uri, :subjectid => subjectid) + lazar = OpenTox::Model::Lazar.create(:dataset_uri => @dataset.uri, :prediction_feature => @prediction_feature.uri, :subjectid => subjectid) rescue => e - error "Model creation failed with '#{e.message}'. Please check if the input file is in a valid #{link_to "Excel", "/excel_format"} or #{link_to "CSV", "/csv_format"} format." + error "Model creation failed with '#{e.message}'."# Please check if the input file is in a valid #{link_to "Excel", "/help"} or #{link_to "CSV", "/help"} format." end task.progress(25) +=begin type = "unknown" - case lazar.metadata[OT.isA] - when /Classification/ + if lazar.metadata[RDF.type].grep(/Classification/) type = "classification" - when /Regression/ + elsif lazar.metadata[RDF.type].grep(/Regression/) type = "regression" end - @model.update :type => type, :feature_dataset => lazar.metadata[OT.featureDataset], :uri => lazar.uri +=end + @model.update :type => @prediction_feature.feature_type, :feature_dataset => lazar.metadata[OT.featureDataset], :uri => lazar.uri - unless url_for("",:full).match(/localhost/) + if CONFIG[:services]["opentox-validation"] @model.update :status => "Validating model" begin - validation = OpenTox::Crossvalidation.create( - {:algorithm_uri => lazar.metadata[OT.algorithm], - :dataset_uri => lazar.parameter("dataset_uri"), - :subjectid => subjectid, - :prediction_feature => lazar.parameter("prediction_feature"), - :algorithm_params => "feature_generation_uri=#{lazar.parameter("feature_generation_uri")}"}, - nil, OpenTox::SubTask.new(task,25,80)) + validation = OpenTox::Crossvalidation.create( { + :algorithm_uri => lazar.metadata[OT.algorithm], + :dataset_uri => lazar.parameter("dataset_uri"), + :subjectid => subjectid, + :prediction_feature => lazar.parameter("prediction_feature"), + :algorithm_params => "feature_generation_uri=#{lazar.parameter("feature_generation_uri")}" }, + nil, OpenTox::SubTask.new(task,25,80)) + @model.update(:validation_uri => validation.uri) LOGGER.debug "Validation URI: #{@model.validation_uri}" # create summary validation.summary(subjectid).each do |k,v| - #LOGGER.debug "mr ::: k: #{k.inspect} - v: #{v.inspect}" begin eval "@model.update :#{k.to_s} => v" if v rescue @@ -278,17 +317,13 @@ post '/models' do # create a new model @model.update :warnings => @model.warnings + "\nModel validation failed with #{e.message}.", :status => "Error", :error_messages => e.message end + else + @model.update(:status => "Completed") #, :warnings => @model.warnings + "\nValidation service cannot be accessed from localhost.") + task.progress(100) end - - - #@model.warnings += "<p>Incorrect Smiles structures (ignored):</p>" + parser.smiles_errors.join("<br/>") unless parser.smiles_errors.empty? - #@model.warnings += "<p>Irregular activities (ignored):</p>" + parser.activity_errors.join("<br/>") unless parser.activity_errors.empty? - #duplicate_warnings = '' - #parser.duplicates.each {|inchi,lines| duplicate_warnings += "<p>#{lines.join('<br/>')}</p>" if lines.size > 1 } - #@model.warnings += "<p>Duplicated structures (all structures/activities used for model building, please make sure, that the results were obtained from <em>independent</em> experiments):</p>" + duplicate_warnings unless duplicate_warnings.empty? lazar.uri end - @model.update(:task_uri => task.uri) + @model.update :task_uri => task.uri flash[:notice] = "Model creation and validation started - this may last up to several hours depending on the number and size of the training compounds." redirect url_for('/models') @@ -325,7 +360,7 @@ post '/predict/?' do # post chemical name to model } else predicted_feature = prediction_dataset.metadata[OT.dependentVariables] - prediction = OpenTox::Feature.find(predicted_feature) + prediction = OpenTox::Feature.find(predicted_feature, subjectid) if prediction.metadata[OT.error] @predictions << { :title => model.name, @@ -351,7 +386,7 @@ post "/lazar/?" do # get detailed prediction @page = params[:page].to_i if params[:page] @model_uri = params[:model_uri] lazar = OpenTox::Model::Lazar.new @model_uri - prediction_dataset_uri = lazar.run(:compound_uri => params[:compound_uri], :subjectid => params[:subjectid]) + prediction_dataset_uri = lazar.run(:compound_uri => params[:compound_uri], :subjectid => session[:subjectid]) @prediction = OpenTox::LazarPrediction.find(prediction_dataset_uri, session[:subjectid]) @compound = OpenTox::Compound.new(params[:compound_uri]) haml :lazar |