summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrautenberg <rautenberg@in-silico.ch>2016-08-30 16:37:45 +0200
committerrautenberg <rautenberg@in-silico.ch>2016-08-30 16:37:45 +0200
commit8432a0f85806693dce66e667ba8eed3954402bb9 (patch)
tree492d1df85cf55b9fd5b926d5aa3f10b86b97031e
parent5ef0e8554ae1d30bfb5bcf9f6eb0540e9184ca3d (diff)
new structure, adjusted yard doc, new routes for validation
-rw-r--r--.yardopts5
-rw-r--r--ChangeLog5
-rw-r--r--VERSION2
-rw-r--r--api/api.json4
-rw-r--r--application.rb218
-rw-r--r--config.ru2
-rw-r--r--lazar-rest.gemspec3
-rw-r--r--lib/api.rb9
-rw-r--r--lib/compound.rb61
-rw-r--r--lib/dataset.rb28
-rw-r--r--lib/lazar-rest.rb28
-rw-r--r--lib/model.rb50
-rw-r--r--lib/validation.rb71
-rw-r--r--test/api.rb2
-rw-r--r--test/compound.rb2
-rw-r--r--test/descriptor.rb2
-rw-r--r--test/model.rb2
-rw-r--r--test/setup.rb1
-rw-r--r--test/validation.rb17
19 files changed, 284 insertions, 228 deletions
diff --git a/.yardopts b/.yardopts
new file mode 100644
index 0000000..7582b41
--- /dev/null
+++ b/.yardopts
@@ -0,0 +1,5 @@
+--readme README.md
+--title 'REST servive for Lazar'
+--charset utf-8
+--plugin yard-sinatra
+yardoc lib/*.rb - README.md ChangeLog VERSION LICENSE
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..a750665
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,5 @@
+2016-08-30
+* new code structure
+* addaption to new lazar and nano-lazar
+2015-10
+* initial version \ No newline at end of file
diff --git a/VERSION b/VERSION
index a13cb90..8a9ecc2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.0.1beta \ No newline at end of file
+0.0.1 \ No newline at end of file
diff --git a/api/api.json b/api/api.json
index c1c8bc8..d811f21 100644
--- a/api/api.json
+++ b/api/api.json
@@ -235,7 +235,7 @@
"tags": [
"validation"
],
- "description": "Get Validation representation",
+ "description": "Get validation representation",
"parameters": [
{
"name": "accept",
@@ -244,7 +244,6 @@
"required": true,
"type": "string",
"enum": [
- "text/uri-list",
"application/json"
]
},
@@ -256,7 +255,6 @@
}
],
"produces": [
- "text/uri-list",
"application/json"
],
"responses": {
diff --git a/application.rb b/application.rb
deleted file mode 100644
index 0d0cb63..0000000
--- a/application.rb
+++ /dev/null
@@ -1,218 +0,0 @@
-include OpenTox
-
-require 'rack/cors'
-
-set :show_exceptions => false
-
-# add CORS support for swagger
-use Rack::Cors do |config|
- config.allow do |allow|
- allow.origins '*'
- allow.resource "/#{SERVICE}/*",
- :methods => [:head, :get, :post, :put, :delete, :options],
- :headers => :any,
- :max_age => 0
- end
-end
-before do
- @accept = request.env['HTTP_ACCEPT']
- response['Content-Type'] = @accept
-end
-
-# route to swagger API file
-get "/api/api.json" do
- response['Content-Type'] = "application/json"
- api_file = File.join("api", "api.json")
- bad_request_error "API Documentation in Swagger JSON is not implemented.", uri("/#{SERVICE}/api") unless File.exists?(api_file)
- api_hash = JSON.parse(File.read(api_file))
- api_hash["host"] = request.env['HTTP_HOST']
- return api_hash.to_json
-end
-
-
-# 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 = OpenTox::Model::Prediction.all
- case @accept
- when "text/uri-list"
- uri_list = models.collect{|model| uri("/model/#{model.model_id}")}
- return uri_list.join("\n") + "\n"
- when "application/json"
- models = JSON.parse models.to_json
- models.each_index do |idx|
- models[idx][:URI] = uri("/model/#{models[idx]["model_id"]["$oid"]}")
- models[idx][:crossvalidation_uri] = uri("/crossvalidation/#{models[idx]["crossvalidation_id"]["$oid"]}") if models[idx]["crossvalidation_id"]
- end
- return models.to_json
- else
- bad_request_error "Mime type #{@accept} is not supported."
- end
-end
-
-get "/model/:id/?" do
- model = OpenTox::Model::Lazar.find params[:id]
- resource_not_found_error "Model with id: #{params[:id]} not found." unless model
- model[:URI] = uri("/model/#{model.id}")
- model[:neighbor_algorithm_parameters][:feature_dataset_uri] = uri("/dataset/#{model[:neighbor_algorithm_parameters][:feature_dataset_id]}") if model[:neighbor_algorithm_parameters][:feature_dataset_id]
- model[:training_dataset_uri] = uri("/dataset/#{model.training_dataset_id}") if model.training_dataset_id
- model[:prediction_feature_uri] = uri("/dataset/#{model.prediction_feature_id}") if model.prediction_feature_id
- return model.to_json
-end
-
-
-
-post "/model/:id/?" do
- identifier = params[:identifier].split(",")
- begin
- # get compound from SMILES
- compounds = identifier.collect{ |i| Compound.from_smiles i.strip }
- rescue
- @error_report = "Attention, '#{params[:identifier]}' is not a valid SMILES string."
- return @error_report
- end
- model = OpenTox::Model::Lazar.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
-
-VALIDATION_TYPES = ["repeatedcrossvalidation", "leaveoneout", "crossvalidation", "regressioncrossvalidation"]
-
-
-# Get a list of ayll possible validation types
-# @param [Header] Accept one of text/uri-list, application/json
-# @return [text/uri-list] URI list of all validation types
-get "/validation/?" do
- case @accept
- when "text/uri-list"
- uri_list = VALIDATION_TYPES.collect{|validationtype| uri("/validation/#{validationtype}")}
- return uri_list.join("\n") + "\n"
- when "application/json"
- return VALIDATION_TYPES.to_json
- else
- bad_request_error "Mime type #{@accept} is not supported."
- end
-end
-
-
-# Get a list of all validations
-# @param [Header] Accept one of text/uri-list, application/json
-# @param [Path] Validationtype One of "repeatedcrossvalidation", "leaveoneout", "crossvalidation", "regressioncrossvalidation"
-# @return [text/uri-list] list of all validations of a validation type
-get "/validation/:validationtype/?" do
- bad_request_error "There is no such validation type as: #{params[:validationtype]}" unless VALIDATION_TYPES.include? params[:validationtype]
- case params[:validationtype]
- when "repeatedcrossvalidation"
- validations = OpenTox::Validation::RepeatedCrossValidation.all
- when "leaveoneout"
- validations = OpenTox::Validation::LeaveOneOut.all
- when "crossvalidation"
- validations = OpenTox::Validation::CrossValidation.all
- when "regressioncrossvalidation"
- validations = OpenTox::Validation::RegressionCrossValidation.all
- end
-
- case @accept
- when "text/uri-list"
- uri_list = validations.collect{|validation| uri("/validation/#{params[:validationtype]}/#{validation.id}")}
- return uri_list.join("\n") + "\n"
- when "application/json"
- validations = JSON.parse validations.to_json
- validations.each_index do |idx|
- validations[idx][:URI] = uri("/validation/#{params[:validationtype]}/#{validations[idx]["$oid"]}")
- #models[idx][:crossvalidation_uri] = uri("/crossvalidation/#{models[idx]["crossvalidation_id"]["$oid"]}") if models[idx]["crossvalidation_id"]
- end
- return validations.to_json
- else
- bad_request_error "Mime type #{@accept} is not supported."
- end
-end
-
-get "/validation/:validationtype/:id/?" do
- bad_request_error "There is no such validation type as: #{params[:validationtype]}" unless VALIDATION_TYPES.include? params[:validationtype]
- case params[:validationtype]
- when "repeatedcrossvalidation"
- validation = OpenTox::Validation::RepeatedCrossValidation.find params[:id]
- when "leaveoneout"
- validation = OpenTox::Validation::LeaveOneOut.find params[:id]
- when "crossvalidation"
- validation = OpenTox::Validation::CrossValidation.find params[:id]
- when "regressioncrossvalidation"
- validation = OpenTox::Validation::RegressionCrossValidation.find params[:id]
- end
-
- resource_not_found_error "#{params[:validationtype]} with id: #{params[:id]} not found." unless validation
- #model[:URI] = uri("/model/#{model.id}")
- #model[:neighbor_algorithm_parameters][:feature_dataset_uri] = uri("/dataset/#{model[:neighbor_algorithm_parameters][:feature_dataset_id]}") if model[:neighbor_algorithm_parameters][:feature_dataset_id]
- #model[:training_dataset_uri] = uri("/dataset/#{model.training_dataset_id}") if model.training_dataset_id
- #model[:prediction_feature_uri] = uri("/dataset/#{model.prediction_feature_id}") if model.prediction_feature_id
- return validation.to_json
-end
-
-# Get a list of a single or all descriptors
-# @param [Header] Accept one of text/plain, application/json
-# @param [Path] Descriptor name (e.G.: Openbabel.HBA1)
-# @return [text/plain, application/json] list of all prediction models
-get "/compound/descriptor/?:descriptor?" do
- case @accept
- when "application/json"
- return "#{JSON.pretty_generate OpenTox::PhysChem::DESCRIPTORS} " unless params[:descriptor]
- return {params[:descriptor] => OpenTox::PhysChem::DESCRIPTORS[params[:descriptor]]}.to_json
- else
- return OpenTox::PhysChem::DESCRIPTORS.collect{|k, v| "#{k}: #{v}\n"} unless params[:descriptor]
- return OpenTox::PhysChem::DESCRIPTORS[params[:descriptor]]
- end
-end
-
-post "/compound/descriptor/?" do
- bad_request_error "Missing Parameter " unless (params[:identifier] or params[:file]) and params[:descriptor]
- descriptor = params['descriptor'].split(',')
- if params[:file]
- data = OpenTox::Dataset.from_csv_file params[:file][:tempfile]
- else
- data = OpenTox::Compound.from_smiles params[:identifier]
- end
- d = Algorithm::Descriptor.physchem data, descriptor
- csv = d.to_csv
- csv = "SMILES,#{params[:descriptor]}\n#{params[:identifier]},#{csv}" if params[:identifier]
- case @accept
- when "application/csv"
- return csv
- when "application/json"
- lines = CSV.parse(csv)
- keys = lines.delete lines.first
- data = lines.collect{|values|Hash[keys.zip(values)]}
- return JSON.pretty_generate(data)
- end
-end
-
-get %r{/compound/(.+)} do |inchi|
- bad_request_error "Input parameter #{inchi} is not an InChI" unless inchi.match(/^InChI=/)
- compound = OpenTox::Compound.from_inchi URI.unescape(inchi)
- response['Content-Type'] = @accept
- case @accept
- when "application/json"
- return JSON.pretty_generate JSON.parse(compound.to_json)
- when "chemical/x-daylight-smiles"
- return compound.smiles
- when "chemical/x-inchi"
- return compound.inchi
- when "chemical/x-mdl-sdfile"
- return compound.sdf
- when "chemical/x-mdl-molfile"
- when "image/png"
- return compound.png
- when "image/svg+xml"
- return compound.svg
- when "text/plain"
- return "#{compound.names}\n"
- else
- return compound.inspect
- end
-end
-
diff --git a/config.ru b/config.ru
index 8a70672..1dd7b70 100644
--- a/config.ru
+++ b/config.ru
@@ -1,5 +1,5 @@
SERVICE = "lazar-rest"
require 'bundler'
Bundler.require
-require File.expand_path './application.rb'
+require File.expand_path './lib/lazar-rest.rb'
run Sinatra::Application \ No newline at end of file
diff --git a/lazar-rest.gemspec b/lazar-rest.gemspec
index 7fbe452..fec1088 100644
--- a/lazar-rest.gemspec
+++ b/lazar-rest.gemspec
@@ -12,7 +12,8 @@ Gem::Specification.new do |s|
s.rubyforge_project = "lazar-rest"
- s.files = `git ls-files`.split("\n")
+ s.files = `git ls-files`.split("\n")
+ s.require_paths = ["lib"]
s.required_ruby_version = '>= 1.9.2'
s.add_runtime_dependency "lazar"
diff --git a/lib/api.rb b/lib/api.rb
new file mode 100644
index 0000000..98623dc
--- /dev/null
+++ b/lib/api.rb
@@ -0,0 +1,9 @@
+# route to swagger API file
+get "/api/api.json" do
+ response['Content-Type'] = "application/json"
+ api_file = File.join("api", "api.json")
+ bad_request_error "API Documentation in Swagger JSON is not implemented.", uri("/#{SERVICE}/api") unless File.exists?(api_file)
+ api_hash = JSON.parse(File.read(api_file))
+ api_hash["host"] = request.env['HTTP_HOST']
+ return api_hash.to_json
+end \ No newline at end of file
diff --git a/lib/compound.rb b/lib/compound.rb
new file mode 100644
index 0000000..fc4ec55
--- /dev/null
+++ b/lib/compound.rb
@@ -0,0 +1,61 @@
+# Get a list of a single or all descriptors
+# @param [Header] Accept one of text/plain, application/json
+# @param [Path] Descriptor name (e.G.: Openbabel.HBA1)
+# @return [text/plain, application/json] list of all prediction models
+get "/compound/descriptor/?:descriptor?" do
+ case @accept
+ when "application/json"
+ return "#{JSON.pretty_generate OpenTox::PhysChem::DESCRIPTORS} " unless params[:descriptor]
+ return {params[:descriptor] => OpenTox::PhysChem::DESCRIPTORS[params[:descriptor]]}.to_json
+ else
+ return OpenTox::PhysChem::DESCRIPTORS.collect{|k, v| "#{k}: #{v}\n"} unless params[:descriptor]
+ return OpenTox::PhysChem::DESCRIPTORS[params[:descriptor]]
+ end
+end
+
+post "/compound/descriptor/?" do
+ bad_request_error "Missing Parameter " unless (params[:identifier] or params[:file]) and params[:descriptor]
+ descriptor = params['descriptor'].split(',')
+ if params[:file]
+ data = OpenTox::Dataset.from_csv_file params[:file][:tempfile]
+ else
+ data = OpenTox::Compound.from_smiles params[:identifier]
+ end
+ d = Algorithm::Descriptor.physchem data, descriptor
+ csv = d.to_csv
+ csv = "SMILES,#{params[:descriptor]}\n#{params[:identifier]},#{csv}" if params[:identifier]
+ case @accept
+ when "application/csv"
+ return csv
+ when "application/json"
+ lines = CSV.parse(csv)
+ keys = lines.delete lines.first
+ data = lines.collect{|values|Hash[keys.zip(values)]}
+ return JSON.pretty_generate(data)
+ end
+end
+
+get %r{/compound/(.+)} do |inchi|
+ bad_request_error "Input parameter #{inchi} is not an InChI" unless inchi.match(/^InChI=/)
+ compound = OpenTox::Compound.from_inchi URI.unescape(inchi)
+ response['Content-Type'] = @accept
+ case @accept
+ when "application/json"
+ return JSON.pretty_generate JSON.parse(compound.to_json)
+ when "chemical/x-daylight-smiles"
+ return compound.smiles
+ when "chemical/x-inchi"
+ return compound.inchi
+ when "chemical/x-mdl-sdfile"
+ return compound.sdf
+ when "chemical/x-mdl-molfile"
+ when "image/png"
+ return compound.png
+ when "image/svg+xml"
+ return compound.svg
+ when "text/plain"
+ return "#{compound.names}\n"
+ else
+ return compound.inspect
+ end
+end \ No newline at end of file
diff --git a/lib/dataset.rb b/lib/dataset.rb
new file mode 100644
index 0000000..227ff20
--- /dev/null
+++ b/lib/dataset.rb
@@ -0,0 +1,28 @@
+include OpenTox
+
+# route to swagger API file
+get "/dataset/?" do
+ datasets = OpenTox::Dataset.all
+ case @accept
+ when "text/uri-list"
+ uri_list = datasets.collect{|dataset| uri("/dataset/#{dataset.id}")}
+ return uri_list.join("\n") + "\n"
+ when "application/json"
+ datasets = JSON.parse datasets.to_json
+ datasets.each_index do |idx|
+ datasets[idx][:URI] = uri("/dataset/#{datasets[idx]["_id"]["$oid"]}")
+ #models[idx][:crossvalidation_uri] = uri("/crossvalidation/#{models[idx]["crossvalidation_id"]["$oid"]}") if models[idx]["crossvalidation_id"]
+ end
+ return models.to_json
+ else
+ bad_request_error "Mime type #{@accept} is not supported."
+ end
+
+end
+
+
+# d = OpenTox::Dataset.find :id => "57c446d13c58a77ec9baaecf"
+# d.data_entries
+# d.name d.source
+# OpenTox::Substance.find :id => "57c446d23c58a77ec9baaed8"
+# OpenTox::Feature.find :id => "57c446d53c58a77ec9bab236" \ No newline at end of file
diff --git a/lib/lazar-rest.rb b/lib/lazar-rest.rb
new file mode 100644
index 0000000..dc806ce
--- /dev/null
+++ b/lib/lazar-rest.rb
@@ -0,0 +1,28 @@
+include OpenTox
+
+require 'rack/cors'
+
+set :show_exceptions => false
+
+# add CORS support for swagger
+use Rack::Cors do |config|
+ config.allow do |allow|
+ allow.origins '*'
+ allow.resource "/#{SERVICE}/*",
+ :methods => [:head, :get, :post, :put, :delete, :options],
+ :headers => :any,
+ :max_age => 0
+ end
+end
+before do
+ @accept = request.env['HTTP_ACCEPT']
+ response['Content-Type'] = @accept
+end
+
+[
+ "api.rb",
+ "compound.rb",
+ "dataset.rb",
+ "model.rb",
+ "validation.rb"
+].each{ |f| require_relative f }
diff --git a/lib/model.rb b/lib/model.rb
new file mode 100644
index 0000000..6188cce
--- /dev/null
+++ b/lib/model.rb
@@ -0,0 +1,50 @@
+
+# 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 = OpenTox::Model::Prediction.all
+ case @accept
+ when "text/uri-list"
+ uri_list = models.collect{|model| uri("/model/#{model.model_id}")}
+ return uri_list.join("\n") + "\n"
+ when "application/json"
+ models = JSON.parse models.to_json
+ models.each_index do |idx|
+ models[idx][:URI] = uri("/model/#{models[idx]["model_id"]["$oid"]}")
+ models[idx][:crossvalidation_uri] = uri("/crossvalidation/#{models[idx]["crossvalidation_id"]["$oid"]}") if models[idx]["crossvalidation_id"]
+ end
+ return models.to_json
+ else
+ bad_request_error "Mime type #{@accept} is not supported."
+ end
+end
+
+get "/model/:id/?" do
+ model = OpenTox::Model::Lazar.find params[:id]
+ resource_not_found_error "Model with id: #{params[:id]} not found." unless model
+ model[:URI] = uri("/model/#{model.id}")
+ model[:neighbor_algorithm_parameters][:feature_dataset_uri] = uri("/dataset/#{model[:neighbor_algorithm_parameters][:feature_dataset_id]}") if model[:neighbor_algorithm_parameters][:feature_dataset_id]
+ model[:training_dataset_uri] = uri("/dataset/#{model.training_dataset_id}") if model.training_dataset_id
+ model[:prediction_feature_uri] = uri("/dataset/#{model.prediction_feature_id}") if model.prediction_feature_id
+ return model.to_json
+end
+
+
+post "/model/:id/?" do
+ identifier = params[:identifier].split(",")
+ begin
+ # get compound from SMILES
+ compounds = identifier.collect{ |i| Compound.from_smiles i.strip }
+ rescue
+ @error_report = "Attention, '#{params[:identifier]}' is not a valid SMILES string."
+ return @error_report
+ end
+ model = OpenTox::Model::Lazar.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
diff --git a/lib/validation.rb b/lib/validation.rb
new file mode 100644
index 0000000..5963c63
--- /dev/null
+++ b/lib/validation.rb
@@ -0,0 +1,71 @@
+# All available validation types
+VALIDATION_TYPES = ["repeatedcrossvalidation", "leaveoneout", "crossvalidation", "regressioncrossvalidation"]
+
+# Get a list of ayll possible validation types
+# @param [Header] Accept one of text/uri-list, application/json
+# @return [text/uri-list] URI list of all validation types
+get "/validation/?" do
+ uri_list = VALIDATION_TYPES.collect{|validationtype| uri("/validation/#{validationtype}")}
+ case @accept
+ when "text/uri-list"
+ return uri_list.join("\n") + "\n"
+ when "application/json"
+ return uri_list.to_json
+ else
+ bad_request_error "Mime type #{@accept} is not supported."
+ end
+end
+
+# Get a list of all validations
+# @param [Header] Accept one of text/uri-list, application/json
+# @param [Path] Validationtype One of "repeatedcrossvalidation", "leaveoneout", "crossvalidation", "regressioncrossvalidation"
+# @return [text/uri-list] list of all validations of a validation type
+get "/validation/:validationtype/?" do
+ bad_request_error "There is no such validation type as: #{params[:validationtype]}" unless VALIDATION_TYPES.include? params[:validationtype]
+ case params[:validationtype]
+ when "repeatedcrossvalidation"
+ validations = OpenTox::Validation::RepeatedCrossValidation.all
+ when "leaveoneout"
+ validations = OpenTox::Validation::LeaveOneOut.all
+ when "crossvalidation"
+ validations = OpenTox::Validation::CrossValidation.all
+ when "regressioncrossvalidation"
+ validations = OpenTox::Validation::RegressionCrossValidation.all
+ end
+
+ case @accept
+ when "text/uri-list"
+ uri_list = validations.collect{|validation| uri("/validation/#{params[:validationtype]}/#{validation.id}")}
+ return uri_list.join("\n") + "\n"
+ when "application/json"
+ validations = JSON.parse validations.to_json
+ validations.each_index do |idx|
+ validations[idx][:URI] = uri("/validation/#{params[:validationtype]}/#{validations[idx]["_id"]["$oid"]}")
+ end
+ return validations.to_json
+ else
+ bad_request_error "Mime type #{@accept} is not supported."
+ end
+end
+
+# Get validation representation
+get "/validation/:validationtype/:id/?" do
+ bad_request_error "There is no such validation type as: #{params[:validationtype]}" unless VALIDATION_TYPES.include? params[:validationtype]
+ case params[:validationtype]
+ when "repeatedcrossvalidation"
+ validation = OpenTox::Validation::RepeatedCrossValidation.find params[:id]
+ when "leaveoneout"
+ validation = OpenTox::Validation::LeaveOneOut.find params[:id]
+ when "crossvalidation"
+ validation = OpenTox::Validation::CrossValidation.find params[:id]
+ when "regressioncrossvalidation"
+ validation = OpenTox::Validation::RegressionCrossValidation.find params[:id]
+ end
+
+ resource_not_found_error "#{params[:validationtype]} with id: #{params[:id]} not found." unless validation
+ #model[:URI] = uri("/model/#{model.id}")
+ #model[:neighbor_algorithm_parameters][:feature_dataset_uri] = uri("/dataset/#{model[:neighbor_algorithm_parameters][:feature_dataset_id]}") if model[:neighbor_algorithm_parameters][:feature_dataset_id]
+ #model[:training_dataset_uri] = uri("/dataset/#{model.training_dataset_id}") if model.training_dataset_id
+ #model[:prediction_feature_uri] = uri("/dataset/#{model.prediction_feature_id}") if model.prediction_feature_id
+ return validation.to_json
+end \ No newline at end of file
diff --git a/test/api.rb b/test/api.rb
index 643777a..daa2e31 100644
--- a/test/api.rb
+++ b/test/api.rb
@@ -1,5 +1,5 @@
require_relative "setup.rb"
-$api_uri = "https://mr-test.in-silico.ch/api/api.json"
+$api_uri = "#{$host}/api/api.json"
class ApiTest < MiniTest::Test
diff --git a/test/compound.rb b/test/compound.rb
index b33a4a1..5fac83d 100644
--- a/test/compound.rb
+++ b/test/compound.rb
@@ -1,6 +1,6 @@
require_relative "setup.rb"
-$compound_uri = "https://mr-test.in-silico.ch/compound"
+$compound_uri = "#{$host}/compound"
$compound = ["InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H"]
class CompoundTest < MiniTest::Test
diff --git a/test/descriptor.rb b/test/descriptor.rb
index 3f9491c..8438898 100644
--- a/test/descriptor.rb
+++ b/test/descriptor.rb
@@ -1,6 +1,6 @@
require_relative "setup.rb"
-$host = "https://mr-test.in-silico.ch"
+$host = "#{$host}"
class DescriptorTest < MiniTest::Test
diff --git a/test/model.rb b/test/model.rb
index c629c67..8068d06 100644
--- a/test/model.rb
+++ b/test/model.rb
@@ -1,6 +1,6 @@
require_relative "setup.rb"
-$model_uri = "https://mr-test.in-silico.ch/model"
+$model_uri = "#{$host}/model"
class ModelTest < MiniTest::Test
def test_00_get_urilist
diff --git a/test/setup.rb b/test/setup.rb
index 0ca77c6..b670fdd 100644
--- a/test/setup.rb
+++ b/test/setup.rb
@@ -2,6 +2,7 @@ require 'minitest/autorun'
require_relative '../../lazar/lib/lazar.rb'
require_relative '../../lazar/test/setup.rb'
+$host = "https://mr-test.in-silico.ch"
include OpenTox
REST_TEST_DIR ||= File.expand_path(File.dirname(__FILE__))
REST_DATA_DIR ||= File.join(REST_TEST_DIR,"data")
diff --git a/test/validation.rb b/test/validation.rb
new file mode 100644
index 0000000..54e0bbc
--- /dev/null
+++ b/test/validation.rb
@@ -0,0 +1,17 @@
+require_relative "setup.rb"
+
+$validation_uri = "#{$host}/validation"
+class ModelTest < MiniTest::Test
+
+ def test_00_get_urilist
+ res = RestClientWrapper.get $validation_uri, {}, {:accept => "text/uri-list"}
+ assert_equal res.code, 200
+ end
+
+ def test_01_get_400
+ assert_raises OpenTox::BadRequestError do
+ res = OpenTox::RestClientWrapper.get $validation_uri, {}, {:accept => "text/notimplemented-type"}
+ end
+ end
+
+end \ No newline at end of file