From 3a11ba2918795821600b7113d0758415718d263a Mon Sep 17 00:00:00 2001 From: gebele Date: Mon, 11 Jun 2018 12:46:06 +0200 Subject: combine gui with rest --- lib/model.rb | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 lib/model.rb (limited to 'lib/model.rb') diff --git a/lib/model.rb b/lib/model.rb new file mode 100644 index 0000000..9fbd90f --- /dev/null +++ b/lib/model.rb @@ -0,0 +1,38 @@ + +# Get a list of all prediction models +# @param [Header] Accept one of text/uri-list, +# @return [text/uri-list] list of all prediction models +get "/model/?" do + models = Model::Validation.all + case @accept + when "text/uri-list" + uri_list = models.collect{|model| uri("/model/#{model.id}")} + return uri_list.join("\n") + "\n" + when "application/json" + models = JSON.parse models.to_json + list = [] + models.each{|m| list << uri("/model/#{m["_id"]["$oid"]}")} + return list.to_json + else + bad_request_error "Mime type #{@accept} is not supported." + end +end + +get "/model/:id/?" do + model = Model::Validation.find params[:id] + not_found_error "Model with id: #{params[:id]} not found." unless model + return model.to_json +end + + +post "/model/:id/?" do + identifier = params[:identifier].split(",") + compounds = identifier.collect{ |i| Compound.from_smiles i.strip } + model = Model::Validation.find params[:id] + batch = {} + compounds.each do |compound| + prediction = model.predict(compound) + batch[compound] = {:id => compound.id, :inchi => compound.inchi, :smiles => compound.smiles, :model => model, :prediction => prediction} + end + return batch.to_json +end -- cgit v1.2.3 From 878f014ec6cc808af99af5045bcc1a1143cab8d9 Mon Sep 17 00:00:00 2001 From: gebele Date: Thu, 5 Jul 2018 10:38:55 +0000 Subject: updated with endpoint list; refined error handling; refined prediction input --- lib/model.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/model.rb') diff --git a/lib/model.rb b/lib/model.rb index 9fbd90f..3764ee2 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -27,7 +27,7 @@ end post "/model/:id/?" do identifier = params[:identifier].split(",") - compounds = identifier.collect{ |i| Compound.from_smiles i.strip } + compounds = identifier.collect{ |i| Compound.from_smiles i.strip.gsub(/\A"|"\Z/,'') } model = Model::Validation.find params[:id] batch = {} compounds.each do |compound| -- cgit v1.2.3 From 9750e0309500259e9a56e267ce87984fb5bb5e53 Mon Sep 17 00:00:00 2001 From: gebele Date: Mon, 26 Nov 2018 15:29:26 +0000 Subject: clean out; better response codes; prepare for batch --- lib/model.rb | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 122 insertions(+), 9 deletions(-) (limited to 'lib/model.rb') diff --git a/lib/model.rb b/lib/model.rb index 3764ee2..42f3a95 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -1,4 +1,3 @@ - # Get a list of all prediction models # @param [Header] Accept one of text/uri-list, # @return [text/uri-list] list of all prediction models @@ -24,15 +23,129 @@ get "/model/:id/?" do return model.to_json end - post "/model/:id/?" do - identifier = params[:identifier].split(",") - compounds = identifier.collect{ |i| Compound.from_smiles i.strip.gsub(/\A"|"\Z/,'') } - model = Model::Validation.find params[:id] - batch = {} - compounds.each do |compound| + if request.content_type == "application/x-www-form-urlencoded" + identifier = params[:identifier].strip.gsub(/\A"|"\Z/,'') + compound = Compound.from_smiles identifier + model = Model::Validation.find params[:id] prediction = model.predict(compound) - batch[compound] = {:id => compound.id, :inchi => compound.inchi, :smiles => compound.smiles, :model => model, :prediction => prediction} + output = {:compound => {:id => compound.id, :inchi => compound.inchi, :smiles => compound.smiles}, + :model => model, + :prediction => prediction + } + return 200, output.to_json + elsif request.content_type =~ /^multipart\/form-data/ && request.content_length.to_i > 0 + @task = Task.new + @task.save + task = Task.run do + m = Model::Validation.find params[:id] + @task.update_percent(0.1) + dataset = Batch.from_csv_file params[:fileName][:tempfile] + compounds = dataset.compounds + $logger.debug compounds.size + identifiers = dataset.identifiers + ids = dataset.ids + type = (m.regression? ? "Regression" : "Classification") + # add header for regression + if type == "Regression" + unit = (type == "Regression") ? "(#{m.unit})" : "" + converted_unit = (type == "Regression") ? "#{m.unit =~ /\b(mmol\/L)\b/ ? "(mg/L)" : "(mg/kg_bw/day)"}" : "" + if ids.blank? + header = "ID,Input,Endpoint,Unique SMILES,inTrainingSet,Measurements #{unit},Prediction #{unit},Prediction #{converted_unit},"\ + "Prediction Interval Low #{unit},Prediction Interval High #{unit},"\ + "Prediction Interval Low #{converted_unit},Prediction Interval High #{converted_unit},"\ + "inApplicabilityDomain,Note\n" + else + header = "ID,Original ID,Input,Endpoint,Unique SMILES,inTrainingSet,Measurements #{unit},Prediction #{unit},Prediction #{converted_unit},"\ + "Prediction Interval Low #{unit},Prediction Interval High #{unit},"\ + "Prediction Interval Low #{converted_unit},Prediction Interval High #{converted_unit},"\ + "inApplicabilityDomain,Note\n" + end + end + # add header for classification + if type == "Classification" + av = m.prediction_feature.accept_values + if ids.blank? + header = "ID,Input,Endpoint,Unique SMILES,inTrainingSet,Measurements,Prediction,"\ + "predProbability #{av[0]},predProbability #{av[1]},inApplicabilityDomain,Note\n" + else + header = "ID,Original ID,Input,Endpoint,Unique SMILES,inTrainingSet,Measurements,Prediction,"\ + "predProbability #{av[0]},predProbability #{av[1]},inApplicabilityDomain,Note\n" + end + end + # predict compounds + p = 100.0/compounds.size + counter = 1 + predictions = [] + compounds.each_with_index do |cid,idx| + compound = Compound.find cid + #$logger.debug compound.inspect + if Prediction.where(compound: compound.id, model: m.id).exists? + prediction_object = Prediction.find_by(compound: compound.id, model: m.id) + prediction = prediction_object.prediction + prediction_id = prediction_object.id + # in case prediction object was created by single prediction + if prediction_object.csv.blank? + prediction_object[:csv] = prediction_to_csv(m,compound,prediction) + prediction_object.save + end + # identifier + identifier = identifiers[idx] + else + prediction = m.predict(compound) + # save prediction object + prediction_object = Prediction.new + prediction_id = prediction_object.id + prediction_object[:compound] = compound.id + prediction_object[:model] = m.id + # add additionally fields for html representation + unless prediction[:value].blank? || type == "Classification" + prediction[:prediction_value] = "#{prediction[:value].delog10.signif(3)} #{unit}" + prediction["converted_prediction_value"] = "#{compound.mmol_to_mg(prediction[:value].delog10).signif(3)} #{converted_unit}" + end + unless prediction[:prediction_interval].blank? + interval = prediction[:prediction_interval] + prediction[:interval] = "#{interval[1].delog10.signif(3)} - #{interval[0].delog10.signif(3)} #{unit}" + prediction[:converted_interval] = "#{compound.mmol_to_mg(interval[1].delog10).signif(3)} - #{compound.mmol_to_mg(interval[0].delog10).signif(3)} #{converted_unit}" + end + prediction["unit"] = unit + prediction["converted_unit"] = converted_unit + if prediction[:measurements].is_a?(Array) + prediction["measurements_string"] = (type == "Regression") ? prediction[:measurements].collect{|value| "#{value.delog10.signif(3)} #{unit}"} : prediction[:measurements].join("
") + prediction["converted_measurements"] = prediction[:measurements].collect{|value| "#{compound.mmol_to_mg(value.delog10).signif(3)} #{unit =~ /mmol\/L/ ? "(mg/L)" : "(mg/kg_bw/day)"}"} if type == "Regression" + else + output["measurements_string"] = (type == "Regression") ? "#{prediction[:measurements].delog10.signif(3)} #{unit}}" : prediction[:measurements] + output["converted_measurements"] = "#{compound.mmol_to_mg(prediction[:measurements].delog10).signif(3)} #{(unit =~ /\b(mmol\/L)\b/) ? "(mg/L)" : "(mg/kg_bw/day)"}" if type == "Regression" + end + + # store in prediction_object + prediction_object[:prediction] = prediction + prediction_object[:csv] = prediction_to_csv(m,compound,prediction) + prediction_object.save + + # identifier + identifier = identifiers[idx] + end + # collect prediction_object ids with identifier + predictions << {"#{identifier}" => prediction_id} + $logger.debug predictions.inspect + @task.update_percent((counter*p).ceil > 100 ? 100 : (counter*p).ceil) + counter += 1 + end + # write csv + @task[:csv] = header + # write predictions + # save task + # append predictions as last action otherwise they won't save + # mongoid works with shallow copy via #dup + @task[:predictions] = {m.id.to_s => predictions} + @task[:dataset_id] = dataset.id + @task[:model_id] = m.id + @task.save + end#main task + tid = @task.id.to_s + return 202, to("/task/#{tid}").to_json + else + bad_request_error "No accepted content type" end - return batch.to_json end -- cgit v1.2.3 From 741701df8ff0861b3607a30e9aaf8b8a0c303cdf Mon Sep 17 00:00:00 2001 From: gebele Date: Thu, 13 Jun 2019 15:28:59 +0000 Subject: update with API --- lib/model.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'lib/model.rb') diff --git a/lib/model.rb b/lib/model.rb index 42f3a95..9bf4f53 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -1,29 +1,29 @@ # Get a list of all prediction models # @param [Header] Accept one of text/uri-list, # @return [text/uri-list] list of all prediction models -get "/model/?" do +get "/api/model/?" do models = Model::Validation.all case @accept when "text/uri-list" - uri_list = models.collect{|model| uri("/model/#{model.id}")} + uri_list = models.collect{|model| uri("/api/model/#{model.id}")} return uri_list.join("\n") + "\n" when "application/json" models = JSON.parse models.to_json list = [] - models.each{|m| list << uri("/model/#{m["_id"]["$oid"]}")} + models.each{|m| list << uri("/api/model/#{m["_id"]["$oid"]}")} return list.to_json else - bad_request_error "Mime type #{@accept} is not supported." + halt 400, "Mime type #{@accept} is not supported." end end -get "/model/:id/?" do +get "/api/model/:id/?" do model = Model::Validation.find params[:id] - not_found_error "Model with id: #{params[:id]} not found." unless model + halt 400, "Model with id: #{params[:id]} not found." unless model return model.to_json end -post "/model/:id/?" do +post "/api/model/:id/?" do if request.content_type == "application/x-www-form-urlencoded" identifier = params[:identifier].strip.gsub(/\A"|"\Z/,'') compound = Compound.from_smiles identifier @@ -146,6 +146,6 @@ post "/model/:id/?" do tid = @task.id.to_s return 202, to("/task/#{tid}").to_json else - bad_request_error "No accepted content type" + halt 400, "No accepted content type" end end -- cgit v1.2.3 From bba7061d7ff2420f4eb2b6f88362edb71bc6bf25 Mon Sep 17 00:00:00 2001 From: gebele Date: Tue, 18 Jun 2019 15:04:55 +0000 Subject: return training dataset from source --- lib/model.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/model.rb') diff --git a/lib/model.rb b/lib/model.rb index 9bf4f53..b26447d 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -20,6 +20,7 @@ end get "/api/model/:id/?" do model = Model::Validation.find params[:id] halt 400, "Model with id: #{params[:id]} not found." unless model + model["training_dataset"] = model.model.training_dataset.id.to_s return model.to_json end -- cgit v1.2.3 From 1546e77e9b2796f20215caa23f06822c96be27ee Mon Sep 17 00:00:00 2001 From: gebele Date: Mon, 5 Aug 2019 09:48:54 +0000 Subject: ensure xhr requests are https to avoid mixed content issue in browsers --- lib/model.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/model.rb') diff --git a/lib/model.rb b/lib/model.rb index b26447d..55172b0 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -145,7 +145,7 @@ post "/api/model/:id/?" do @task.save end#main task tid = @task.id.to_s - return 202, to("/task/#{tid}").to_json + return 202, "//#{ENV['VIRTUAL_HOST']}/task/#{tid}".to_json else halt 400, "No accepted content type" end -- cgit v1.2.3 From 270bddf5081671cd1905d6cce6eb3659159f573a Mon Sep 17 00:00:00 2001 From: gebele Date: Fri, 16 Aug 2019 09:49:53 +0000 Subject: change hostname method --- lib/model.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/model.rb') diff --git a/lib/model.rb b/lib/model.rb index 55172b0..dfc779c 100644 --- a/lib/model.rb +++ b/lib/model.rb @@ -145,7 +145,7 @@ post "/api/model/:id/?" do @task.save end#main task tid = @task.id.to_s - return 202, "//#{ENV['VIRTUAL_HOST']}/task/#{tid}".to_json + return 202, "//#{$host_with_port}/task/#{tid}".to_json else halt 400, "No accepted content type" end -- cgit v1.2.3