summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChristoph Helma <helma@in-silico.ch>2012-02-08 13:14:11 +0100
committerChristoph Helma <helma@in-silico.ch>2012-02-08 13:14:11 +0100
commit354aaa649e9eeed5d81793e09d9714b45063c147 (patch)
tree230fd99569bcec503b61e6336263ca1edec397d1 /lib
parentac54997dccc571471a0cdf62939e2fcbc42e06e2 (diff)
toxbank-investigation compatible version
Diffstat (limited to 'lib')
-rw-r--r--lib/algorithm.rb398
-rw-r--r--lib/authorization.rb156
-rw-r--r--lib/compound.rb31
-rw-r--r--lib/config/config_ru.rb54
-rw-r--r--lib/dataset.rb253
-rw-r--r--lib/environment.rb83
-rw-r--r--lib/error.rb98
-rw-r--r--lib/feature.rb44
-rw-r--r--lib/helper.rb98
-rw-r--r--lib/model.rb480
-rw-r--r--lib/ontology.rb55
-rw-r--r--lib/opentox-client.rb7
-rw-r--r--lib/opentox-ruby-minimal.rb2
-rw-r--r--lib/opentox-ruby.rb15
-rw-r--r--lib/opentox.owl809
-rw-r--r--lib/opentox.rb214
-rw-r--r--lib/overwrite.rb155
-rw-r--r--lib/parser.rb475
-rw-r--r--lib/rest_client_wrapper.rb182
-rw-r--r--lib/serializer.rb491
-rw-r--r--lib/spork.rb83
-rw-r--r--lib/task.rb367
-rw-r--r--lib/to-html.rb109
-rw-r--r--lib/validation.rb313
24 files changed, 354 insertions, 4618 deletions
diff --git a/lib/algorithm.rb b/lib/algorithm.rb
index 4c50d32..4986c40 100644
--- a/lib/algorithm.rb
+++ b/lib/algorithm.rb
@@ -1,407 +1,15 @@
-# R integration
-# workaround to initialize R non-interactively (former rinruby versions did this by default)
-# avoids compiling R with X
-#R = nil
-#require "rinruby"
-
module OpenTox
# Wrapper for OpenTox Algorithms
- module Algorithm
-
- include OpenTox
+ class Algorithm
# Execute algorithm with parameters, please consult the OpenTox API and the webservice documentation for acceptable parameters
# @param [optional,Hash] params Algorithm parameters
# @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
# @return [String] URI of new resource (dataset, model, ...)
- def run(params=nil, waiting_task=nil)
- #puts @uri
- RestClientWrapper.post(@uri, params, {:accept => 'text/uri-list'}, waiting_task).to_s
- end
-
- # Get OWL-DL representation in RDF/XML format
- # @return [application/rdf+xml] RDF/XML representation
- def to_rdfxml
- s = Serializer::Owl.new
- s.add_algorithm(@uri,@metadata)
- s.to_rdfxml
- end
-
- # Generic Algorithm class, should work with all OpenTox webservices
- class Generic
- include Algorithm
-
- # Find Generic Opentox Algorithm via URI, and loads metadata, could raise NotFound/NotAuthorized error
- # @param [String] uri Algorithm URI
- # @return [OpenTox::Algorithm::Generic] Algorithm instance
- def self.find(uri, subjectid=nil)
- return nil unless uri
- alg = Generic.new(uri)
- alg.load_metadata
- raise "cannot load algorithm metadata" if alg.metadata==nil or alg.metadata.size==0
- alg
- end
-
- end
-
- # Fminer algorithms (https://github.com/amaunz/fminer2)
- module Fminer
- include Algorithm
-
- # Backbone Refinement Class mining (http://bbrc.maunz.de/)
- class BBRC
- include Fminer
- # Initialize bbrc algorithm
- def initialize(subjectid=nil)
- super File.join(CONFIG[:services]["opentox-algorithm"], "fminer/bbrc")
- load_metadata
- end
- end
-
- # LAtent STructure Pattern Mining (http://last-pm.maunz.de)
- class LAST
- include Fminer
- # Initialize last algorithm
- def initialize(subjectid=nil)
- super File.join(CONFIG[:services]["opentox-algorithm"], "fminer/last")
- load_metadata
- end
- end
-
- end
-
- # Create lazar prediction model
- class Lazar
- include Algorithm
- # Initialize lazar algorithm
- def initialize(subjectid=nil)
- super File.join(CONFIG[:services]["opentox-algorithm"], "lazar")
- load_metadata
- end
- end
-
-=begin
- # Utility methods without dedicated webservices
-
- # Similarity calculations
- module Similarity
- include Algorithm
-
- # Tanimoto similarity
- # @param [Array] features_a Features of first compound
- # @param [Array] features_b Features of second compound
- # @param [optional, Hash] weights Weights for all features
- # @return [Float] (Weighted) tanimoto similarity
- def self.tanimoto(features_a,features_b,weights=nil)
- common_features = features_a & features_b
- all_features = (features_a + features_b).uniq
- common_p_sum = 0.0
- if common_features.size > 0
- if weights
- common_features.each{|f| common_p_sum += Algorithm.gauss(weights[f])}
- all_p_sum = 0.0
- all_features.each{|f| all_p_sum += Algorithm.gauss(weights[f])}
- common_p_sum/all_p_sum
- else
- common_features.to_f/all_features
- end
- else
- 0.0
- end
- end
-
- # Euclidean similarity
- # @param [Hash] properties_a Properties of first compound
- # @param [Hash] properties_b Properties of second compound
- # @param [optional, Hash] weights Weights for all properties
- # @return [Float] (Weighted) euclidean similarity
- def self.euclidean(properties_a,properties_b,weights=nil)
- common_properties = properties_a.keys & properties_b.keys
- if common_properties.size > 1
- dist_sum = 0
- common_properties.each do |p|
- if weights
- dist_sum += ( (properties_a[p] - properties_b[p]) * Algorithm.gauss(weights[p]) )**2
- else
- dist_sum += (properties_a[p] - properties_b[p])**2
- end
- end
- 1/(1+Math.sqrt(dist_sum))
- else
- 0.0
- end
- end
- end
-
- module Neighbors
-
- # Classification with majority vote from neighbors weighted by similarity
- # @param [Array] neighbors, each neighbor is a hash with keys `:similarity, :activity`
- # @param [optional] params Ignored (only for compatibility with local_svm_regression)
- # @return [Hash] Hash with keys `:prediction, :confidence`
- def self.weighted_majority_vote(neighbors,params={}, props=nil)
- conf = 0.0
- confidence = 0.0
- neighbors.each do |neighbor|
- case neighbor[:activity].to_s
- when 'true'
- conf += Algorithm.gauss(neighbor[:similarity])
- when 'false'
- conf -= Algorithm.gauss(neighbor[:similarity])
- end
- end
- if conf > 0.0
- prediction = true
- elsif conf < 0.0
- prediction = false
- else
- prediction = nil
- end
- confidence = conf/neighbors.size if neighbors.size > 0
- {:prediction => prediction, :confidence => confidence.abs}
- end
-
- # Local support vector regression from neighbors
- # @param [Array] neighbors, each neighbor is a hash with keys `:similarity, :activity, :features`
- # @param [Hash] params Keys `:similarity_algorithm,:p_values` are required
- # @return [Hash] Hash with keys `:prediction, :confidence`
- def self.local_svm_regression(neighbors, params, props=nil)
- take_logs=true
- neighbors.each do |n|
- if (! n[:activity].nil?) && (n[:activity].to_f < 0.0)
- take_logs = false
- end
- end
- acts = neighbors.collect do |n|
- act = n[:activity]
- take_logs ? Math.log10(act.to_f) : act.to_f
- end # activities of neighbors for supervised learning
-
- sims = neighbors.collect{ |n| Algorithm.gauss(n[:similarity]) } # similarity values btwn q and nbors
- begin
- prediction = (props.nil? ? local_svm(neighbors, acts, sims, "nu-svr", params) : local_svm_prop(props, acts, "nu-svr", params))
- prediction = (take_logs ? 10**(prediction.to_f) : prediction.to_f)
- LOGGER.debug "Prediction is: '" + prediction.to_s + "'."
- rescue Exception => e
- LOGGER.debug "#{e.class}: #{e.message} #{e.backtrace}"
- end
-
- conf = sims.inject{|sum,x| sum + x }
- confidence = conf/neighbors.size if neighbors.size > 0
- {:prediction => prediction, :confidence => confidence}
-
- end
-
- # Local support vector classification from neighbors
- # @param [Array] neighbors, each neighbor is a hash with keys `:similarity, :activity, :features`
- # @param [Hash] params Keys `:similarity_algorithm,:p_values` are required
- # @param [Array] props, propositionalization of neighbors and query structure e.g. [ Array_for_q, two-nested-Arrays_for_n ]
- # @return [Hash] Hash with keys `:prediction, :confidence`
- def self.local_svm_classification(neighbors, params, props=nil)
- acts = neighbors.collect do |n|
- act = n[:activity]
- end # activities of neighbors for supervised learning
- acts_f = acts.collect {|v| v == true ? 1.0 : 0.0}
- sims = neighbors.collect{ |n| Algorithm.gauss(n[:similarity]) } # similarity values btwn q and nbors
- begin
- prediction = (props.nil? ? local_svm(neighbors, acts_f, sims, "C-bsvc", params) : local_svm_prop(props, acts_f, "C-bsvc", params))
- LOGGER.debug "Prediction is: '" + prediction.to_s + "'."
- rescue Exception => e
- LOGGER.debug "#{e.class}: #{e.message} #{e.backtrace}"
- end
-
- conf = sims.inject{|sum,x| sum + x }
- confidence = conf/neighbors.size if neighbors.size > 0
- {:prediction => prediction, :confidence => confidence}
-
- end
-
-
- # Local support vector prediction from neighbors.
- # Uses pre-defined Kernel Matrix.
- # Not to be called directly (use local_svm_regression or local_svm_classification).
- # @param [Array] neighbors, each neighbor is a hash with keys `:similarity, :activity, :features`
- # @param [Array] acts, activities for neighbors.
- # @param [Array] sims, similarities for neighbors.
- # @param [String] type, one of "nu-svr" (regression) or "C-bsvc" (classification).
- # @param [Hash] params Keys `:similarity_algorithm,:p_values` are required
- # @param [Array] props, propositionalization of neighbors and query structure e.g. [ Array_for_q, two-nested-Arrays_for_n ]
- # @return [Numeric] A prediction value.
- def self.local_svm(neighbors, acts, sims, type, params)
- LOGGER.debug "Local SVM (Weighted Tanimoto Kernel)."
- neighbor_matches = neighbors.collect{ |n| n[:features] } # URIs of matches
- gram_matrix = [] # square matrix of similarities between neighbors; implements weighted tanimoto kernel
- if neighbor_matches.size == 0
- raise "No neighbors found."
- else
- # gram matrix
- (0..(neighbor_matches.length-1)).each do |i|
- gram_matrix[i] = [] unless gram_matrix[i]
- # upper triangle
- ((i+1)..(neighbor_matches.length-1)).each do |j|
- sim = eval("#{params[:similarity_algorithm]}(neighbor_matches[i], neighbor_matches[j], params[:p_values])")
- gram_matrix[i][j] = Algorithm.gauss(sim)
- gram_matrix[j] = [] unless gram_matrix[j]
- gram_matrix[j][i] = gram_matrix[i][j] # lower triangle
- end
- gram_matrix[i][i] = 1.0
- end
-
- #LOGGER.debug gram_matrix.to_yaml
- @r = RinRuby.new(false,false) # global R instance leads to Socket errors after a large number of requests
- @r.eval "library('kernlab')" # this requires R package "kernlab" to be installed
- LOGGER.debug "Setting R data ..."
- # set data
- @r.gram_matrix = gram_matrix.flatten
- @r.n = neighbor_matches.size
- @r.y = acts
- @r.sims = sims
-
- begin
- LOGGER.debug "Preparing R data ..."
- # prepare data
- @r.eval "y<-as.vector(y)"
- @r.eval "gram_matrix<-as.kernelMatrix(matrix(gram_matrix,n,n))"
- @r.eval "sims<-as.vector(sims)"
-
- # model + support vectors
- LOGGER.debug "Creating SVM model ..."
- @r.eval "model<-ksvm(gram_matrix, y, kernel=matrix, type=\"#{type}\", nu=0.5)"
- @r.eval "sv<-as.vector(SVindex(model))"
- @r.eval "sims<-sims[sv]"
- @r.eval "sims<-as.kernelMatrix(matrix(sims,1))"
- LOGGER.debug "Predicting ..."
- if type == "nu-svr"
- @r.eval "p<-predict(model,sims)[1,1]"
- elsif type == "C-bsvc"
- @r.eval "p<-predict(model,sims)"
- end
- if type == "nu-svr"
- prediction = @r.p
- elsif type == "C-bsvc"
- prediction = (@r.p.to_f == 1.0 ? true : false)
- end
- @r.quit # free R
- rescue Exception => e
- LOGGER.debug "#{e.class}: #{e.message} #{e.backtrace}"
- end
-
- end
- prediction
- end
-
- # Local support vector prediction from neighbors.
- # Uses propositionalized setting.
- # Not to be called directly (use local_svm_regression or local_svm_classification).
- # @param [Array] neighbors, each neighbor is a hash with keys `:similarity, :activity, :features`
- # @param [Array] acts, activities for neighbors.
- # @param [Array] props, propositionalization of neighbors and query structure e.g. [ Array_for_q, two-nested-Arrays_for_n ]
- # @param [String] type, one of "nu-svr" (regression) or "C-bsvc" (classification).
- # @param [Hash] params Keys `:similarity_algorithm,:p_values` are required
- # @return [Numeric] A prediction value.
- def self.local_svm_prop(props, acts, type, params)
-
- LOGGER.debug "Local SVM (Propositionalization / Kernlab Kernel)."
- n_prop = props[0] # is a matrix, i.e. two nested Arrays.
- q_prop = props[1] # is an Array.
-
- #neighbor_matches = neighbors.collect{ |n| n[:features] } # URIs of matches
- #gram_matrix = [] # square matrix of similarities between neighbors; implements weighted tanimoto kernel
- if n_prop.size == 0
- raise "No neighbors found."
- else
- # gram matrix
- #(0..(neighbor_matches.length-1)).each do |i|
- # gram_matrix[i] = [] unless gram_matrix[i]
- # # upper triangle
- # ((i+1)..(neighbor_matches.length-1)).each do |j|
- # sim = eval("#{params[:similarity_algorithm]}(neighbor_matches[i], neighbor_matches[j], params[:p_values])")
- # gram_matrix[i][j] = Algorithm.gauss(sim)
- # gram_matrix[j] = [] unless gram_matrix[j]
- # gram_matrix[j][i] = gram_matrix[i][j] # lower triangle
- # end
- # gram_matrix[i][i] = 1.0
- #end
-
- #LOGGER.debug gram_matrix.to_yaml
- @r = RinRuby.new(false,false) # global R instance leads to Socket errors after a large number of requests
- @r.eval "library('kernlab')" # this requires R package "kernlab" to be installed
- LOGGER.debug "Setting R data ..."
- # set data
- @r.n_prop = n_prop.flatten
- @r.n_prop_x_size = n_prop.size
- @r.n_prop_y_size = n_prop[0].size
- @r.y = acts
- @r.q_prop = q_prop
-
- begin
- LOGGER.debug "Preparing R data ..."
- # prepare data
- @r.eval "y<-matrix(y)"
- @r.eval "prop_matrix<-matrix(n_prop, n_prop_x_size, n_prop_y_size, byrow=TRUE)"
- @r.eval "q_prop<-matrix(q_prop, 1, n_prop_y_size, byrow=TRUE)"
-
- # model + support vectors
- LOGGER.debug "Creating SVM model ..."
- @r.eval "model<-ksvm(prop_matrix, y, type=\"#{type}\", nu=0.5)"
- LOGGER.debug "Predicting ..."
- if type == "nu-svr"
- @r.eval "p<-predict(model,q_prop)[1,1]"
- elsif type == "C-bsvc"
- @r.eval "p<-predict(model,q_prop)"
- end
- if type == "nu-svr"
- prediction = @r.p
- elsif type == "C-bsvc"
- prediction = (@r.p.to_f == 1.0 ? true : false)
- end
- @r.quit # free R
- rescue Exception => e
- LOGGER.debug "#{e.class}: #{e.message} #{e.backtrace}"
- end
- end
- prediction
- end
-
-
- end
-
- module Substructure
- include Algorithm
- # Substructure matching
- # @param [OpenTox::Compound] compound Compound
- # @param [Array] features Array with Smarts strings
- # @return [Array] Array with matching Smarts
- def self.match(compound,features)
- compound.match(features)
- end
- end
-
- module Dataset
- include Algorithm
- # API should match Substructure.match
- def features(dataset_uri,compound_uri)
- end
- end
-
- # Gauss kernel
- # @return [Float]
- def self.gauss(x, sigma = 0.3)
- d = 1.0 - x.to_f
- Math.exp(-(d*d)/(2*sigma*sigma))
- end
-
- # Median of an array
- # @param [Array] Array with values
- # @return [Float] Median
- def self.median(array)
- return nil if array.empty?
- array.sort!
- m_pos = array.size / 2
- return array.size % 2 == 1 ? array[m_pos] : (array[m_pos-1] + array[m_pos])/2
+ def run params=nil
+ post params, {:accept => 'text/uri-list'}
end
-=end
end
end
diff --git a/lib/authorization.rb b/lib/authorization.rb
index 27ae734..d447f88 100644
--- a/lib/authorization.rb
+++ b/lib/authorization.rb
@@ -2,52 +2,52 @@ module OpenTox
#Module for Authorization and Authentication
#@example Authentication
- # require "opentox-ruby"
+ # require "opentox-client"
# OpenTox::Authorization::AA_SERVER = "https://opensso.in-silico.ch" #if not set in .opentox/conf/[environment].yaml
- # token = OpenTox::Authorization.authenticate("benutzer", "passwort")
+ # token = OpenTox::Authorization.authenticate("benutzer", "passwort")
#@see http://www.opentox.org/dev/apis/api-1.2/AA OpenTox A&A API 1.2 specification
-
+
module Authorization
#Helper Class AA to create and send default policies out of xml templates
- #@example Creating a default policy to a URI
- # aa=OpenTox::Authorization::AA.new(tok)
+ #@example Creating a default policy to a URI
+ # aa=OpenTox::Authorization::AA.new(tok)
# xml=aa.get_xml('http://uri....')
- # OpenTox::Authorization.create_policy(xml,tok)
-
+ # OpenTox::Authorization.create_policy(xml,tok)
+
class AA
- attr_accessor :user, :subjectid, :policy
-
+ attr_accessor :user, :subjectid, :policy
+
#Generates AA object - requires subjectid
- # @param [String] subjectid
+ # @param [String] subjectid
def initialize(subjectid)
@user = Authorization.get_user(subjectid)
@subjectid = subjectid
@policy = Policies.new()
end
-
+
#Cleans AA Policies and loads default xml file into policy attribute
- #set uri and user, returns Policyfile(XML) for open-sso
+ #set uri and user, returns Policyfile(XML) for open-sso
# @param [String] URI to create a policy for
def get_xml(uri)
@policy.drop_policies
@policy.load_default_policy(@user, uri)
return @policy.to_xml
- end
-
+ end
+
#Loads and sends Policyfile(XML) to open-sso server
- # @param [String] URI to create a policy for
- def send(uri)
+ # @param [String] URI to create a policy for
+ def send(uri)
xml = get_xml(uri)
ret = false
- ret = Authorization.create_policy(xml, @subjectid)
+ ret = Authorization.create_policy(xml, @subjectid)
LOGGER.debug "Policy send with subjectid: #{@subjectid}"
LOGGER.warn "Not created Policy is: #{xml}" if !ret
- ret
+ ret
end
-
+
end
-
+
#Returns the open-sso server set in the config file .opentox/config/[environment].yaml
# @return [String, nil] the openSSO server URI or nil
def self.server
@@ -55,11 +55,11 @@ module OpenTox
end
#Authentication against OpenSSO. Returns token. Requires Username and Password.
- # @param [String, String]Username,Password
+ # @param [String, String]Username,Password
# @return [String, nil] gives subjectid or nil
def self.authenticate(user, pw)
return nil if !AA_SERVER
- begin
+ begin
resource = RestClient::Resource.new("#{AA_SERVER}/auth/authenticate")
out = resource.post(:username=>user, :password => pw).sub("token.id=","").sub("\n","")
return out
@@ -67,20 +67,20 @@ module OpenTox
return nil
end
end
-
+
#Logout on opensso. Make token invalid. Requires token
- # @param [String]subjectid the subjectid
+ # @param [String]subjectid the subjectid
# @return [Boolean] true if logout is OK
def self.logout(subjectid)
begin
resource = RestClient::Resource.new("#{AA_SERVER}/auth/logout")
resource.post(:subjectid => subjectid)
- return true
+ return true
rescue
return false
end
- end
-
+ end
+
#Authorization against OpenSSO for a URI with request-method (action) [GET/POST/PUT/DELETE]
# @param [String,String,String]uri,action,subjectid
# @return [Boolean, nil] returns true, false or nil (if authorization-request fails).
@@ -91,12 +91,12 @@ module OpenTox
return true if resource.post(:uri => uri, :action => action, :subjectid => subjectid) == "boolean=true\n"
rescue
return nil
- end
+ end
end
- #Checks if a token is a valid token
- # @param [String]subjectid subjectid from openSSO session
- # @return [Boolean] subjectid is valid or not.
+ #Checks if a token is a valid token
+ # @param [String]subjectid subjectid from openSSO session
+ # @return [Boolean] subjectid is valid or not.
def self.is_token_valid(subjectid)
return true if !AA_SERVER
begin
@@ -106,7 +106,7 @@ module OpenTox
return false
end
end
-
+
#Returns array with all policies of the token owner
# @param [String]subjectid requires subjectid
# @return [Array, nil] returns an Array of policy names or nil if request fails
@@ -116,15 +116,15 @@ module OpenTox
out = resource.get(:subjectid => subjectid)
return out.split("\n")
rescue RestClient::InternalServerError => e
- raise e.response
+ raise e.response
rescue
return nil
end
end
#Returns a policy in xml-format
- # @param [String, String]policy,subjectid
- # @return [String] XML of the policy
+ # @param [String, String]policy,subjectid
+ # @return [String] XML of the policy
def self.list_policy(policy, subjectid)
begin
resource = RestClient::Resource.new("#{AA_SERVER}/pol")
@@ -133,7 +133,7 @@ module OpenTox
return nil
end
end
-
+
# Lists policies alongside with affected uris
# @param [String] subjectid
# @return [Hash] keys: all policies of the subjectid owner, values: uris affected by those policies
@@ -154,7 +154,7 @@ module OpenTox
p.load_xml( list_policy(policy, subjectid) )
p.uris
end
-
+
#Returns the owner (who created the first policy) of an URI
# @param [String, String]uri,subjectid
# return [String, nil]owner,nil returns owner of the URI
@@ -164,39 +164,39 @@ module OpenTox
return resource.get(:uri => uri, :subjectid => subjectid).sub("\n","")
rescue
return nil
- end
- end
-
+ end
+ end
+
#Checks if a policy exists to a URI. Requires URI and token.
# @param [String, String]uri,subjectid
- # return [Boolean]
+ # return [Boolean]
def self.uri_has_policy(uri, subjectid)
owner = get_uri_owner(uri, subjectid)
return true if owner and owner != "null"
false
end
-
+
#List all policynames for a URI. Requires URI and token.
# @param [String, String]uri,subjectid
- # return [Array, nil] returns an Array of policy names or nil if request fails
+ # return [Array, nil] returns an Array of policy names or nil if request fails
def self.list_uri_policies(uri, subjectid)
begin
resource = RestClient::Resource.new("#{AA_SERVER}/pol")
- out = resource.get(:uri => uri, :polnames => true, :subjectid => subjectid)
+ out = resource.get(:uri => uri, :polnames => true, :subjectid => subjectid)
policies = []; notfirstline = false
out.split("\n").each do |line|
policies << line if notfirstline
- notfirstline = true
+ notfirstline = true
end
- return policies
+ return policies
rescue
return nil
- end
- end
+ end
+ end
#Sends a policy in xml-format to opensso server. Requires policy-xml and token.
# @param [String, String]policyxml,subjectid
- # return [Boolean] returns true if policy is created
+ # return [Boolean] returns true if policy is created
def self.create_policy(policy, subjectid)
begin
resource = RestClient::Resource.new("#{AA_SERVER}/Pol/opensso-pol")
@@ -206,7 +206,7 @@ module OpenTox
return false
end
end
-
+
#Deletes a policy
# @param [String, String]policyname,subjectid
# @return [Boolean,nil]
@@ -214,7 +214,7 @@ module OpenTox
begin
resource = RestClient::Resource.new("#{AA_SERVER}/pol")
LOGGER.debug "OpenTox::Authorization.delete_policy policy: #{policy} with token: #{subjectid}"
- return true if resource.delete(:subjectid => subjectid, :id => policy)
+ return true if resource.delete(:subjectid => subjectid, :id => policy)
rescue
return nil
end
@@ -222,7 +222,7 @@ module OpenTox
#Returns array of all possible LDAP-Groups
# @param [String]subjectid
- # @return [Array]
+ # @return [Array]
def self.list_groups(subjectid)
begin
resource = RestClient::Resource.new("#{AA_SERVER}/opensso/identity/search")
@@ -233,8 +233,8 @@ module OpenTox
rescue
[]
end
- end
-
+ end
+
#Returns array of the LDAP-Groups of an user
# @param [String]subjectid
# @return [Array] gives array of LDAP groups of a user
@@ -244,17 +244,17 @@ module OpenTox
out = resource.post(:name => user, :admin => subjectid, :attributes_names => "group")
grps = []
out.split("\n").each do |line|
- grps << line.sub("identitydetails.group=","") if line.include?("identitydetails.group=")
+ grps << line.sub("identitydetails.group=","") if line.include?("identitydetails.group=")
end
return grps
rescue
[]
end
- end
-
+ end
+
#Returns the owner (user id) of a token
# @param [String]subjectid
- # @return [String]user
+ # @return [String]user
def self.get_user(subjectid)
begin
resource = RestClient::Resource.new("#{AA_SERVER}/opensso/identity/attributes")
@@ -265,14 +265,14 @@ module OpenTox
user = line.sub("userdetails.attribute.value=","") if line.include?("userdetails.attribute.value=")
check = false
end
- check = true if line.include?("userdetails.attribute.name=uid")
+ check = true if line.include?("userdetails.attribute.name=uid")
end
return user
rescue
nil
end
end
-
+
#Send default policy with Authorization::AA class
# @param [String, String]URI,subjectid
def self.send_policy(uri, subjectid)
@@ -282,7 +282,7 @@ module OpenTox
LOGGER.debug "OpenTox::Authorization send policy for URI: #{uri} | subjectid: #{subjectid} - policy created: #{ret}"
ret
end
-
+
#Deletes all policies of an URI
# @param [String, String]URI,subjectid
# @return [Boolean]
@@ -303,20 +303,20 @@ module OpenTox
# @return [Boolean] true if policy checked/created successfully (or no uri/subjectid given), false else
def self.check_policy(uri, subjectid)
return true unless uri and subjectid
- token_valid = OpenTox::Authorization.is_token_valid(subjectid)
+ token_valid = OpenTox::Authorization.is_token_valid(subjectid)
LOGGER.debug "OpenTox::Authorization.check_policy with uri: #{uri}, subjectid: #{subjectid} is valid: #{token_valid}"
# check if subjectid is valid
unless token_valid
# abort if invalid
- LOGGER.error "OpenTox::Authorization.check_policy, subjectid NOT valid: #{subjectid}"
+ LOGGER.error "OpenTox::Authorization.check_policy, subjectid NOT valid: #{subjectid}"
return false
end
-
+
if !uri_has_policy(uri, subjectid)
# if no policy exists, create a policy, return result of send policy
send_policy(uri, subjectid)
else
- # if policy exists check for POST rights
+ # if policy exists check for POST rights
if authorize(uri, "POST", subjectid)
true
else
@@ -325,19 +325,19 @@ module OpenTox
end
end
true
- end
+ end
- class << self
+ class << self
alias :token_valid? :is_token_valid
end
- # Check Authorization for a resource (identified via URI) with method and subjectid.
+ # Check Authorization for a resource (identified via URI) with method and subjectid.
# @param [String] uri
# @param [String] request_method, should be GET, POST, PUT, DELETE
# @param [String] subjectid
# @return [Boolean] true if access granted, else otherwise
def self.authorized?(uri, request_method, subjectid)
- if CONFIG[:authorization][:free_request].include?(request_method)
+ if CONFIG[:authorization][:free_request].include?(request_method)
#LOGGER.debug "authorized? >>true<< (request is free), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
true
elsif OpenTox::Authorization.free_uri?(uri, request_method)
@@ -355,38 +355,38 @@ module OpenTox
ret = OpenTox::Authorization.authorize(uri, request_method, subjectid)
LOGGER.debug "authorized? >>#{ret}<< (uri (not) authorized), method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}" unless ret
ret
- else
+ else
LOGGER.error "invalid request/uri method: #{request_method}, URI: #{uri}, subjectid: #{subjectid}"
false
end
end
-
+
private
def self.free_uri?(uri, request_method)
if CONFIG[:authorization][:free_uris]
CONFIG[:authorization][:free_uris].each do |request_methods,uris|
- if request_methods and uris and request_methods.include?(request_method.to_sym)
+ if request_methods and uris and request_methods.include?(request_method.to_sym)
uris.each do |u|
return true if u.match uri
end
end
end
- end
+ end
return false
end
-
+
def self.authorize_exception?(uri, request_method)
if CONFIG[:authorization][:authorize_exceptions]
CONFIG[:authorization][:authorize_exceptions].each do |request_methods,uris|
- if request_methods and uris and request_methods.include?(request_method.to_sym)
+ if request_methods and uris and request_methods.include?(request_method.to_sym)
uris.each do |u|
return true if u.match uri
end
end
end
- end
+ end
return false
- end
-
+ end
+
end
end
diff --git a/lib/compound.rb b/lib/compound.rb
index 974e46e..8761d50 100644
--- a/lib/compound.rb
+++ b/lib/compound.rb
@@ -1,5 +1,4 @@
-@@cactus_uri="http://cactus.nci.nih.gov/chemical/structure/"
-@@ambit_uri="http://ambit.uni-plovdiv.bg:8080/ambit2/depict/cdk?search="
+CACTUS_URI="http://cactus.nci.nih.gov/chemical/structure/"
module OpenTox
@@ -12,21 +11,21 @@ module OpenTox
# @param [String] smiles Smiles string
# @return [OpenTox::Compound] Compound
def self.from_smiles service_uri, smiles, subjectid=nil
- Compound.new RestClientWrapper.post(service_uri, smiles, :content_type => 'chemical/x-daylight-smiles').to_s.chomp
+ Compound.new RestClient.post(service_uri, smiles, {:content_type => 'chemical/x-daylight-smiles', :subjectid => subjectid})
end
# Create a compound from inchi string
# @param [String] smiles InChI string
# @return [OpenTox::Compound] Compound
- def self.from_inchi(service_uri, inchi)
- Compound.new RestClientWrapper.post(service_uri, inchi, :content_type => 'chemical/x-inchi').to_s.chomp
+ def self.from_inchi service_uri, inchi, subjectid=nil
+ Compound.new RestClient.post(service_uri, inchi, {:content_type => 'chemical/x-inchi', :subjectid => subjectid})
end
# Create a compound from sdf string
# @param [String] smiles SDF string
# @return [OpenTox::Compound] Compound
- def self.from_sdf(service_uri, sdf)
- Compound.new RestClientWrapper.post(service_uri, sdf, :content_type => 'chemical/x-mdl-sdfile').to_s.chomp
+ def self.from_sdf service_uri, sdf, subjectid=nil
+ Compound.new RestClient.post(service_uri, sdf, {:content_type => 'chemical/x-mdl-sdfile', :subjectid => subjectid})
end
# Create a compound from name. Relies on an external service for name lookups.
@@ -34,34 +33,32 @@ module OpenTox
# compound = OpenTox::Compound.from_name("Benzene")
# @param [String] name name can be also an InChI/InChiKey, CAS number, etc
# @return [OpenTox::Compound] Compound
- def self.from_name(service_uri, name)
- # paranoid URI encoding to keep SMILES charges and brackets
- inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(name, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").to_s.chomp
- Compound.new File.join(service_uri,URI.escape(inchi))
+ def self.from_name service_uri, name, subjectid=nil
+ Compound.new RestClient.post(service_uri, name, {:content_type => 'text/plain', :subjectid => subjectid})
end
# Get InChI
# @return [String] InChI string
def to_inchi
- RestClientWrapper.get(@uri, :accept => 'chemical/x-inchi').to_s.chomp if @uri
+ get(:accept => 'chemical/x-inchi').to_s.chomp if @uri
end
# Get (canonical) smiles
# @return [String] Smiles string
def to_smiles
- RestClientWrapper.get(@uri, :accept => 'chemical/x-daylight-smiles').chomp
+ get(:accept => 'chemical/x-daylight-smiles').chomp
end
# Get sdf
# @return [String] SDF string
def to_sdf
- RestClientWrapper.get(@uri, :accept => 'chemical/x-mdl-sdfile').chomp
+ get(:accept => 'chemical/x-mdl-sdfile').chomp
end
# Get gif image
# @return [image/gif] Image data
def to_gif
- RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/image")
+ get("#{CACTUS_URI}#{to_inchi}/image")
end
# Get png image
@@ -69,7 +66,7 @@ module OpenTox
# image = compound.to_png
# @return [image/png] Image data
def to_png
- RestClientWrapper.get(File.join @uri, "image")
+ get(File.join @uri, "image")
end
# Get URI of compound image
@@ -84,7 +81,7 @@ module OpenTox
# @return [String] Compound names
def to_names
begin
- RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/names").split("\n")
+ get("#{CACTUS_URI}#{to_inchi}/names").split("\n")
rescue
"not available"
end
diff --git a/lib/config/config_ru.rb b/lib/config/config_ru.rb
deleted file mode 100644
index dc04263..0000000
--- a/lib/config/config_ru.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-require 'rubygems'
-require 'rack'
-require 'rack/contrib'
-require 'application.rb'
-
-# log at centralized place
-logfile = "#{LOG_DIR}/#{ENV["RACK_ENV"]}.log"
-log = File.new(logfile, "a+")
-$stdout.reopen(log)
-$stderr.reopen(log)
-$stdout.sync = true
-$stderr.sync = true
-set :logging, false
-set :raise_errors, true
-set :lock, true
-
-['public','tmp'].each do |dir|
- FileUtils.mkdir_p dir unless File.exists?(dir)
-end
-
-use Rack::ShowExceptions
-=begin
-if defined?(MAIL)
-
- # monkeypatch with the original method
- # strangely enough my mailserver returns "Connection refused - connect(2)" errors without this patch
- module Rack
- class MailExceptions
-
- def send_notification(exception, env)
- mail = generate_mail(exception, env)
- smtp = config[:smtp]
- env['mail.sent'] = true
- return if smtp[:server] == 'example.com'
-
- Net::SMTP.start smtp[:server], smtp[:port], smtp[:domain], smtp[:user_name], smtp[:password], smtp[:authentication] do |server|
- mail.to.each do |recipient|
- server.send_message mail.to_s, mail.from, recipient
- end
- end
- end
- end
- end
-
-
- require "socket"
- use Rack::MailExceptions do |mail|
- mail.to MAIL[:user_name]
- mail.subject '[ERROR] %s'
- mail.from "#{Socket.gethostname}@#{MAIL[:domain]}"
- mail.smtp MAIL
- end
-end
-=end
diff --git a/lib/dataset.rb b/lib/dataset.rb
index 84dce65..3de9d1f 100644
--- a/lib/dataset.rb
+++ b/lib/dataset.rb
@@ -4,9 +4,9 @@ module OpenTox
# TODO: fix API Doc
class Dataset
- include OpenTox
+ #include OpenTox
- attr_reader :features, :compounds, :data_entries, :metadata
+ #attr_reader :features, :compounds, :data_entries, :metadata
# Create dataset with optional URI. Does not load data into the dataset - you will need to execute one of the load_* methods to pull data from a service or to insert it from other representations.
# @example Create an empty dataset
@@ -22,78 +22,19 @@ module OpenTox
@data_entries = {}
end
- # Create an empty dataset and save it at the dataset service (assigns URI to dataset)
- # @example Create new dataset and save it to obtain a URI
- # dataset = OpenTox::Dataset.create
- # @param [optional, String] uri Dataset URI
- # @return [OpenTox::Dataset] Dataset object
- def self.create(uri=CONFIG[:services]["opentox-dataset"], subjectid=nil)
- dataset = Dataset.new(nil,subjectid)
- dataset.save
- dataset
- end
-
- # Find a dataset and load all data. This can be time consuming, use Dataset.new together with one of the load_* methods for a fine grained control over data loading.
- # @param [String] uri Dataset URI
- # @return [OpenTox::Dataset] Dataset object with all data
- def self.find(uri, subjectid=nil)
- return nil unless uri
- dataset = Dataset.new(uri, subjectid)
- dataset.load_metadata
- dataset
- end
-
- # Create dataset from CSV file (format specification: http://toxcreate.org/help)
- # - loads data_entries, compounds, features
- # - sets metadata (warnings) for parser errors
- # - you will have to set remaining metadata manually
- # @param [String] file CSV file path
- # @return [OpenTox::Dataset] Dataset object with CSV data
- def self.create_from_csv_file(file, subjectid=nil)
- dataset = Dataset.create(CONFIG[:services]["opentox-dataset"], subjectid)
- #RestClientWrapper.post(dataset.uri,File.read(file), {:content_type => "text/csv", :subjectid => @subjectid})
- RestClientWrapper.post(dataset.uri,{:file => File.new(file)},{:accept => "text/uri-list", :subjectid => subjectid})#, {:content_type => "text/csv", :subjectid => @subjectid})
- dataset.load_metadata
- dataset
- end
-
- # replaces find as exist check, takes not as long, does NOT raise an un-authorized exception
- # @param [String] uri Dataset URI
- # @return [Boolean] true if dataset exists and user has get rights, false else
- def self.exist?(uri, subjectid=nil)
- return false unless uri
- dataset = Dataset.new(uri, subjectid)
- begin
- dataset.load_metadata.size > 0
- rescue
- false
- end
- end
-
- # Get all datasets from a service
- # @param [optional,String] uri URI of the dataset service, defaults to service specified in configuration
- # @return [Array] Array of dataset object without data (use one of the load_* methods to pull data from the server)
- def self.all(uri=CONFIG[:services]["opentox-dataset"], subjectid=nil)
- RestClientWrapper.get(uri,{:accept => "text/uri-list",:subjectid => subjectid}).to_s.each_line.collect{|u| Dataset.new(u.chomp, subjectid)}
- end
-
+=begin
# Load YAML representation into the dataset
# @param [String] yaml YAML representation of the dataset
# @return [OpenTox::Dataset] Dataset object with YAML data
- def store_yaml(yaml)
- RestClientWrapper.post(@uri,yaml, {:content_type => "application/x-yaml", :subjectid => @subjectid})
- end
-
- def store_rdfxml(rdfxml)
- RestClientWrapper.post(@uri, rdfxml, {:content_type => "application/rdf+xml", :subjectid => @subjectid})
+ def self.from_yaml service_uri, yaml, subjectid=nil
+ Dataset.create(service_uri, subjectid).post yaml, :content_type => "application/x-yaml"
end
# Load RDF/XML representation from a file
# @param [String] file File with RDF/XML representation of the dataset
# @return [OpenTox::Dataset] Dataset object with RDF/XML data
- def store_rdfxml_file(file)
- #RestClientWrapper.post(@uri, :file => File.new(file))#, {:content_type => "application/rdf+xml", :subjectid => @subjectid})
- RestClientWrapper.post(@uri, File.read(file), {:content_type => "application/rdf+xml", :subjectid => @subjectid})
+ def self.from_rdfxml service_uri, rdfxml, subjectid=nil
+ Dataset.create(service_uri, subjectid).post rdfxml, :content_type => "application/rdf+xml"
end
# Load CSV string (format specification: http://toxcreate.org/help)
@@ -102,8 +43,8 @@ module OpenTox
# - you will have to set remaining metadata manually
# @param [String] csv CSV representation of the dataset
# @return [OpenTox::Dataset] Dataset object with CSV data
- def store_csv(csv)
- RestClientWrapper.post(@uri, csv, {:content_type => "text/csv", :subjectid => @subjectid})
+ def self.from_csv service_uri, csv, subjectid=nil
+ Dataset.from_file(service_uri, csv, subjectid)
end
# Load Spreadsheet book (created with roo gem http://roo.rubyforge.org/, excel format specification: http://toxcreate.org/help)
@@ -112,53 +53,101 @@ module OpenTox
# - you will have to set remaining metadata manually
# @param [Excel] book Excel workbook object (created with roo gem)
# @return [OpenTox::Dataset] Dataset object with Excel data
- def store_spreadsheet_file(file)
- RestClientWrapper.post(@uri, :file => File.new(file))#, {:content_type => "application/vnd.ms-excel", :subjectid => @subjectid})
+ def self.from_xls service_uri, xls, subjectid=nil
+ Dataset.create(service_uri, subjectid).post xls, :content_type => "application/vnd.ms-excel"
end
- # Load and return only metadata of a Dataset object
- # @return [Hash] Metadata of the dataset
- def load_metadata
- if (CONFIG[:yaml_hosts].include?(URI.parse(@uri).host))
- @metadata = YAML.load(RestClientWrapper.get(File.join(@uri,"metadata"), {:accept => "application/x-yaml", :subjectid => @subjectid}))
- else
- add_metadata Parser::Owl::Dataset.new(@uri, @subjectid).load_metadata
- end
- self.uri = @uri if @uri # keep uri
- @metadata
+ def self.from_sdf service_uri, sdf, subjectid=nil
+ Dataset.create(service_uri, subjectid).post sdf, :content_type => 'chemical/x-mdl-sdfile'
end
+=end
# Load all data (metadata, data_entries, compounds and features) from URI
- def load_all
- if (CONFIG[:yaml_hosts].include?(URI.parse(@uri).host))
- copy YAML.load(RestClientWrapper.get(@uri, {:accept => "application/x-yaml", :subjectid => @subjectid}))
- else
- parser = Parser::Owl::Dataset.new(@uri, @subjectid)
- copy parser.load_uri
+ # TODO: move to opentox-server
+ def data_entries reload=true
+ if reload
+ file = Tempfile.new("ot-rdfxml")
+ file.puts get :accept => "application/rdf+xml"
+ file.close
+ to_delete = file.path
+
+ data = {}
+ feature_values = {}
+ feature = {}
+ feature_accept_values = {}
+ other_statements = {}
+ `rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`.each_line do |line|
+ triple = line.chomp.split(' ',3)
+ triple = triple[0..2].collect{|i| i.sub(/\s+.$/,'').gsub(/[<>"]/,'')}
+ case triple[1]
+ when /#{RDF::OT.values}|#{RDF::OT1.values}/i
+ data[triple[0]] = {:compound => "", :values => []} unless data[triple[0]]
+ data[triple[0]][:values] << triple[2]
+ when /#{RDF::OT.value}|#{RDF::OT1.value}/i
+ feature_values[triple[0]] = triple[2]
+ when /#{RDF::OT.compound}|#{RDF::OT1.compound}/i
+ data[triple[0]] = {:compound => "", :values => []} unless data[triple[0]]
+ data[triple[0]][:compound] = triple[2]
+ when /#{RDF::OT.feature}|#{RDF::OT1.feature}/i
+ feature[triple[0]] = triple[2]
+ when /#{RDF.type}/i
+ if triple[2]=~/#{RDF::OT.Compound}|#{RDF::OT1.Compound}/i and !data[triple[0]]
+ data[triple[0]] = {:compound => triple[0], :values => []}
+ end
+ when /#{RDF::OT.acceptValue}|#{RDF::OT1.acceptValue}/i # acceptValue in ambit datasets is only provided in dataset/<id> no in dataset/<id>/features
+ feature_accept_values[triple[0]] = [] unless feature_accept_values[triple[0]]
+ feature_accept_values[triple[0]] << triple[2]
+ else
+ end
+ end
+ File.delete(to_delete) if to_delete
+ data.each do |id,entry|
+ if entry[:values].size==0
+ # no feature values add plain compounds
+ @compounds << entry[:compound] unless @compounds.include? entry[:compound]
+ else
+ entry[:values].each do |value_id|
+ if feature_values[value_id]
+ split = feature_values[value_id].split(/\^\^/)
+ case split[-1]
+ when RDF::XSD.double, RDF::XSD.float
+ value = split.first.to_f
+ when RDF::XSD.boolean
+ value = split.first=~/(?i)true/ ? true : false
+ else
+ value = split.first
+ end
+ end
+ @compounds << entry[:compound] unless @compounds.include? entry[:compound]
+ @features[feature[value_id][value_id]] = {} unless @features[feature[value_id]]
+ @data_entries[entry[:compound].to_s] = {} unless @data_entries[entry[:compound].to_s]
+ @data_entries[entry[:compound].to_s][feature[value_id]] = [] unless @data_entries[entry[:compound]][feature[value_id]]
+ @data_entries[entry[:compound].to_s][feature[value_id]] << value if value!=nil
+ end
+ end
+ end
+ features subjectid
+ #feature_accept_values.each do |feature, values|
+ #self.features[feature][OT.acceptValue] = values
+ #end
+ self.metadata = metadata(subjectid)
end
+ @data_entries
end
# Load and return only compound URIs from the dataset service
# @return [Array] Compound URIs in the dataset
- def load_compounds
- RestClientWrapper.get(File.join(uri,"compounds"),{:accept=> "text/uri-list", :subjectid => @subjectid}).to_s.each_line do |compound_uri|
- @compounds << compound_uri.chomp
- end
- @compounds.uniq!
+ def compounds reload=true
+ reload ? @compounds = Compound.all(File.join(@uri,"compounds")) : @compounds
end
# Load and return only features from the dataset service
# @return [Hash] Features of the dataset
- def load_features
- if (CONFIG[:yaml_hosts].include?(URI.parse(@uri).host))
- @features = YAML.load(RestClientWrapper.get(File.join(@uri,"features"), {:accept => "application/x-yaml", :subjectid => @subjectid}))
- else
- parser = Parser::Owl::Dataset.new(@uri, @subjectid)
- @features = parser.load_features
- end
- @features
+ def features reload=true
+ reload ? @features = Feature.all(File.join(@uri,"features")) : @features
end
+=begin
# returns the accept_values of a feature, i.e. the classification domain / all possible feature values
# @param [String] feature the URI of the feature
# @return [Array] return array with strings, nil if value is not set (e.g. when feature is numeric)
@@ -182,48 +171,46 @@ module OpenTox
"unknown"
end
end
-
- # Get Spreadsheet representation
- # @return [Spreadsheet::Workbook] Workbook which can be written with the spreadsheet gem (data_entries only, metadata will will be discarded))
- def to_spreadsheet
- Spreadsheet::Workbook.new(RestClientWrapper.get(@uri, {:accept => "application/vnd.ms-excel", :subjectid => @subjectid}))
- end
+=end
# Get Excel representation (alias for to_spreadsheet)
# @return [Spreadsheet::Workbook] Workbook which can be written with the spreadsheet gem (data_entries only, metadata will will be discarded))
def to_xls
- to_spreadsheet
+ get :accept => "application/vnd.ms-excel"
end
# Get CSV string representation (data_entries only, metadata will be discarded)
# @return [String] CSV representation
def to_csv
- RestClientWrapper.get(@uri, {:accept => "text/csv", :subjectid => @subjectid})
+ get :accept => "text/csv"
+ end
+
+ def to_sdf
+ get :accept => 'chemical/x-mdl-sdfile'
end
+
# Get OWL-DL in ntriples format
# @return [String] N-Triples representation
def to_ntriples
- RestClientWrapper.get(@uri, {:accept => "application/rdf+xml", :subjectid => @subjectid})
+ get :accept => "application/rdf+xml"
end
# Get OWL-DL in RDF/XML format
# @return [String] RDF/XML representation
def to_rdfxml
- RestClientWrapper.get(@uri, {:accept => "application/rdf+xml", :subjectid => @subjectid})
+ get :accept => "application/rdf+xml"
end
# Get name (DC.title) of a feature
# @param [String] feature Feature URI
# @return [String] Feture title
def feature_name(feature)
- load_features
- @features[feature][DC.title]
+ features[feature][DC.title]
end
def title
- load_metadata
- @metadata[DC.title]
+ metadata[DC.title]
end
# Insert a statement (compound_uri,feature_uri,value)
@@ -314,11 +301,6 @@ module OpenTox
@uri
end
- # Delete dataset at the dataset service
- def delete
- RestClientWrapper.delete(@uri, :subjectid => @subjectid)
- end
-
private
# Copy a dataset (rewrites URI)
def copy(dataset)
@@ -333,39 +315,4 @@ module OpenTox
end
end
end
-
- # Class with special methods for lazar prediction datasets
- class LazarPrediction < Dataset
-
- # Find a prediction dataset and load all data.
- # @param [String] uri Prediction dataset URI
- # @return [OpenTox::Dataset] Prediction dataset object with all data
- def self.find(uri, subjectid=nil)
- prediction = LazarPrediction.new(uri, subjectid)
- prediction.load_all
- prediction
- end
-
- def value(compound)
- @data_entries[compound.uri].collect{|f,v| v.first if f.match(/value/)}.compact.first
- end
-
- def confidence(compound)
- @data_entries[compound.uri].collect{|f,v| v.first if f.match(/confidence/)}.compact.first
- end
-
- def descriptors(compound)
- @data_entries[compound.uri].collect{|f,v| @features[f] if f.match(/descriptor/)}.compact if @data_entries[compound.uri]
- end
-
- def measured_activities(compound)
- source = @metadata[OT.hasSource]
- @data_entries[compound.uri].collect{|f,v| v if f.match(/#{source}/)}.compact.flatten
- end
-
- def neighbors(compound)
- @data_entries[compound.uri].collect{|f,v| @features[f] if f.match(/neighbor/)}.compact
- end
-
- end
end
diff --git a/lib/environment.rb b/lib/environment.rb
deleted file mode 100644
index cae743c..0000000
--- a/lib/environment.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# set default environment
-ENV['RACK_ENV'] = 'production' unless ENV['RACK_ENV']
-
-# load/setup configuration
-basedir = File.join(ENV['HOME'], ".opentox")
-config_dir = File.join(basedir, "config")
-config_file = File.join(config_dir, "#{ENV['RACK_ENV']}.yaml")
-user_file = File.join(config_dir, "users.yaml")
-
-TMP_DIR = File.join(basedir, "tmp")
-LOG_DIR = File.join(basedir, "log")
-
-if File.exist?(config_file)
- CONFIG = YAML.load_file(config_file)
- raise "could not load config, config file: "+config_file.to_s unless CONFIG
-else
- FileUtils.mkdir_p TMP_DIR
- FileUtils.mkdir_p LOG_DIR
- FileUtils.mkdir_p config_dir
- FileUtils.cp(File.join(File.dirname(__FILE__), 'templates/config.yaml'), config_file)
- puts "Please edit #{config_file} and restart your application."
- exit
-end
-
-# database
-#`redis-server /opt/redis/redis.conf` unless File.exists? "/var/run/redis.pid" # removed by AM
-# Ohm.connect :thread_safe => true
-
-# load mail settings for error messages
-#load File.join config_dir,"mail.rb" if File.exists?(File.join config_dir,"mail.rb")
-
-logfile = "#{LOG_DIR}/#{ENV["RACK_ENV"]}.log"
-#LOGGER = OTLogger.new(logfile,'daily') # daily rotation
-LOGGER = OTLogger.new(logfile) # no rotation
-LOGGER.formatter = Logger::Formatter.new #this is neccessary to restore the formating in case active-record is loaded
-if CONFIG[:logger] and CONFIG[:logger] == "debug"
- LOGGER.level = Logger::DEBUG
-else
- LOGGER.level = Logger::WARN
-end
-
-# Regular expressions for parsing classification data
-TRUE_REGEXP = /^(true|active|1|1.0|tox)$/i
-FALSE_REGEXP = /^(false|inactive|0|0.0|low tox)$/i
-
-# Task durations
-DEFAULT_TASK_MAX_DURATION = 36000
-#EXTERNAL_TASK_MAX_DURATION = 36000
-
-# OWL Namespaces
-class OwlNamespace
-
- attr_accessor :uri
- def initialize(uri)
- @uri = uri
- end
-
- def [](property)
- @uri+property.to_s
- end
-
- def type # for RDF.type
- "#{@uri}type"
- end
-
- def method_missing(property)
- @uri+property.to_s
- end
-
-end
-
-RDF = OwlNamespace.new 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
-OWL = OwlNamespace.new 'http://www.w3.org/2002/07/owl#'
-DC = OwlNamespace.new 'http://purl.org/dc/elements/1.1/'
-OT = OwlNamespace.new 'http://www.opentox.org/api/1.1#'
-OTA = OwlNamespace.new 'http://www.opentox.org/algorithmTypes.owl#'
-XSD = OwlNamespace.new 'http://www.w3.org/2001/XMLSchema#'
-
-AA_SERVER = CONFIG[:authorization] ? (CONFIG[:authorization][:server] ? CONFIG[:authorization][:server] : nil) : nil
-CONFIG[:authorization][:authenticate_request] = [""] unless CONFIG[:authorization][:authenticate_request]
-CONFIG[:authorization][:authorize_request] = [""] unless CONFIG[:authorization][:authorize_request]
-CONFIG[:authorization][:free_request] = [""] unless CONFIG[:authorization][:free_request]
-
diff --git a/lib/error.rb b/lib/error.rb
deleted file mode 100644
index 45b7545..0000000
--- a/lib/error.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# adding additional fields to Exception class to format errors according to OT-API
-class Exception
- attr_accessor :errorCause
- def http_code; 500; end
-end
-
-module OpenTox
-
- class BadRequestError < RuntimeError
- def http_code; 400; end
- end
-
- class NotAuthorizedError < RuntimeError
- def http_code; 401; end
- end
-
- class NotFoundError < RuntimeError
- def http_code; 404; end
- end
-
- class ServiceUnavailableError < RuntimeError
- def http_code; 503; end
- end
-
- class RestCallError < RuntimeError
- attr_accessor :rest_params
- def http_code; 502; end
- end
-
- class ErrorReport
-
- # TODO replace params with URIs (errorCause -> OT.errorCause)
- attr_reader :message, :actor, :errorCause, :http_code, :errorDetails, :errorType
-
- private
- def initialize( http_code, erroType, message, actor, errorCause, rest_params=nil, backtrace=nil )
- @http_code = http_code
- @errorType = erroType
- @message = message
- @actor = actor
- @errorCause = errorCause
- @rest_params = rest_params
- @backtrace = backtrace
- end
-
- public
- # creates a error report object, from an ruby-exception object
- # @param [Exception] error
- # @param [String] actor, URI of the call that cause the error
- def self.create( error, actor )
- rest_params = error.rest_params if error.is_a?(OpenTox::RestCallError) and error.rest_params
- backtrace = error.backtrace.short_backtrace if CONFIG[:backtrace]
- ErrorReport.new( error.http_code, error.class.to_s, error.message, actor, error.errorCause, rest_params, backtrace )
- end
-
- def self.from_rdf(rdf)
- metadata = OpenTox::Parser::Owl.from_rdf( rdf, OT.ErrorReport ).metadata
- ErrorReport.new(metadata[OT.statusCode], metadata[OT.errorCode], metadata[OT.message], metadata[OT.actor], metadata[OT.errorCause])
- end
-
- # overwrite sorting to make easier readable
- def to_yaml_properties
- p = super
- p = ( p - ["@backtrace"]) + ["@backtrace"] if @backtrace
- p = ( p - ["@errorCause"]) + ["@errorCause"] if @errorCause
- p
- end
-
- def rdf_content()
- c = {
- RDF.type => [OT.ErrorReport],
- OT.statusCode => @http_code,
- OT.message => @message,
- OT.actor => @actor,
- OT.errorCode => @errorType,
- }
- c[OT.errorCause] = @errorCause.rdf_content if @errorCause
- c
- end
-
- def to_rdfxml
- s = Serializer::Owl.new
- s.add_resource(CONFIG[:services]["opentox-task"]+"/tmpId/ErrorReport/tmpId", OT.errorReport, rdf_content)
- s.to_rdfxml
- end
- end
-end
-
-class Array
- def short_backtrace
- short = []
- each do |c|
- break if c =~ /sinatra\/base/
- short << c
- end
- short.join("\n")
- end
-end
diff --git a/lib/feature.rb b/lib/feature.rb
deleted file mode 100644
index 84a85b9..0000000
--- a/lib/feature.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-module OpenTox
- class Feature
- include OpenTox
-
- attr_accessor :subjectid
-
- # Find a feature
- # @param [String] uri Feature URI
- # @return [OpenTox::Feature] Feature object
- def self.find(uri, subjectid=nil)
- return nil unless uri
- feature = Feature.new uri, subjectid
- if (CONFIG[:yaml_hosts].include?(URI.parse(uri).host))
- feature.add_metadata YAML.load(RestClientWrapper.get(uri,{:accept => "application/x-yaml", :subjectid => @subjectid}))
- else
- feature.add_metadata Parser::Owl::Dataset.new(uri).load_metadata
- end
- feature.subjectid = subjectid
- feature
- end
-
- # provides feature type, possible types are "regression" or "classification"
- # @return [String] feature type, unknown if OT.isA property is unknown/ not set
- def feature_type
- if metadata[RDF.type].flatten.include?(OT.NominalFeature)
- "classification"
- elsif metadata[RDF.type].flatten.include?(OT.NumericFeature)
- "regression"
- elsif metadata[OWL.sameAs]
- metadata[OWL.sameAs].each do |f|
- begin
- type = Feature.find(f, subjectid).feature_type
- return type unless type=="unknown"
- rescue => ex
- LOGGER.warn "could not load same-as-feature '"+f.to_s+"' for feature '"+uri.to_s+"' : "+ex.message.to_s
- end
- end
- "unknown"
- else
- "unknown"
- end
- end
- end
-end
diff --git a/lib/helper.rb b/lib/helper.rb
deleted file mode 100644
index 04300e0..0000000
--- a/lib/helper.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-=begin
-helpers do
-
- # Authentification
- def protected!(subjectid)
- if env["session"]
- unless authorized?(subjectid)
- flash[:notice] = "You don't have access to this section: "
- redirect back
- end
- elsif !env["session"] && subjectid
- unless authorized?(subjectid)
- LOGGER.debug "URI not authorized: clean: " + clean_uri("#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}").to_s + " full: #{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']} with request: #{request.env['REQUEST_METHOD']}"
- raise OpenTox::NotAuthorizedError.new "Not authorized"
- end
- else
- raise OpenTox::NotAuthorizedError.new "Not authorized" unless authorized?(subjectid)
- end
- end
-
- #Check Authorization for URI with method and subjectid.
- def authorized?(subjectid)
- request_method = request.env['REQUEST_METHOD']
- uri = clean_uri("#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}")
- request_method = "GET" if request_method == "POST" && uri =~ /\/model\/\d+\/?$/
- return OpenTox::Authorization.authorized?(uri, request_method, subjectid)
- end
-
- #cleans URI from querystring and file-extension. Sets port 80 to emptystring
- # @param [String] uri
- def clean_uri(uri)
- uri = uri.sub(" ", "%20") #dirty hacks => to fix
- uri = uri[0,uri.index("InChI=")] if uri.index("InChI=")
-
- out = URI.parse(uri)
- out.path = out.path[0, out.path.length - (out.path.reverse.rindex(/\/{1}\d+\/{1}/))] if out.path.index(/\/{1}\d+\/{1}/) #cuts after /id/ for a&a
- port = (out.scheme=="http" && out.port==80)||(out.scheme=="https" && out.port==443) ? "" : ":#{out.port.to_s}"
- "#{out.scheme}://#{out.host}#{port}#{out.path.chomp("/")}" #"
- end
-
- #unprotected uri for login
- def login_requests
- return env['REQUEST_URI'] =~ /\/login$/
- end
-
- def uri_available?(urlStr)
- url = URI.parse(urlStr)
- subjectidstr = @subjectid ? "?subjectid=#{CGI.escape @subjectid}" : ""
- Net::HTTP.start(url.host, url.port) do |http|
- return http.head("#{url.request_uri}#{subjectidstr}").code == "200"
- end
- end
-
- def get_subjectid
- begin
- subjectid = nil
- subjectid = session[:subjectid] if session[:subjectid]
- subjectid = params[:subjectid] if params[:subjectid] and !subjectid
- subjectid = request.env['HTTP_SUBJECTID'] if request.env['HTTP_SUBJECTID'] and !subjectid
- subjectid = request.cookies["subjectid"] unless subjectid
- # see http://rack.rubyforge.org/doc/SPEC.html
- subjectid = CGI.unescape(subjectid) if subjectid.include?("%23")
- @subjectid = subjectid
- rescue
- subjectid = nil
- end
- end
- def get_extension
- extension = File.extname(request.path_info)
- unless extension.empty?
- case extension.gsub(".","")
- when "html"
- @accept = 'text/html'
- when "yaml"
- @accept = 'application/x-yaml'
- when "csv"
- @accept = 'text/csv'
- when "rdfxml"
- @accept = 'application/rdf+xml'
- when "xls"
- @accept = 'application/ms-excel'
- when "css"
- @accept = 'text/css'
- else
- # halt 404, "File format #{extension} not supported."
- end
- end
- end
-end
-
-before do
- @subjectid = get_subjectid()
- @accept = get_extension()
- unless !AA_SERVER or login_requests or CONFIG[:authorization][:free_request].include?(env['REQUEST_METHOD'])
- protected!(@subjectid)
- end
-end
-=end
diff --git a/lib/model.rb b/lib/model.rb
index a806b74..95aa9ff 100644
--- a/lib/model.rb
+++ b/lib/model.rb
@@ -1,488 +1,14 @@
module OpenTox
- module Model
-
- include OpenTox
-
- # Find a lazar model
- # @param [String] uri Model URI
- # @return [OpenTox::Model::Lazar] lazar model
- def self.find(uri, subjectid=nil)
- if CONFIG[:yaml_hosts].include?(URI.parse(uri).host)
- YAML.load RestClientWrapper.get(uri,{:accept => 'application/x-yaml', :subjectid => subjectid})
- else
- parser = Parser::Owl::Feature.new(uri, @subjectid)
- @metadata = parser.load_uri.metadata
- end
- end
-
- # Get URIs of all models
- # @return [Array] List of lazar model URIs
- def self.all(subjectid=nil)
- RestClientWrapper.get(CONFIG[:services]["opentox-model"], :subjectid => subjectid).to_s.split("\n")
- end
+ class Model
# Run a model with parameters
# @param [Hash] params Parameters for OpenTox model
# @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
# @return [text/uri-list] Task or resource URI
- def run( params, accept_header=nil, waiting_task=nil )
- unless accept_header
- if CONFIG[:yaml_hosts].include?(URI.parse(@uri).host)
- accept_header = 'application/x-yaml'
- else
- accept_header = 'application/rdf+xml'
- end
- end
- LOGGER.info "running model "+@uri.to_s+", params: "+params.inspect+", accept: "+accept_header.to_s
- RestClientWrapper.post(@uri,params,{:accept => accept_header},waiting_task).to_s
- end
-
- # Generic OpenTox model class for all API compliant services
- class Generic
- include Model
-
- # Find Generic Opentox Model via URI, and loads metadata, could raise NotFound/NotAuthorized error
- # @param [String] uri Model URI
- # @return [OpenTox::Model::Generic] Model instance
- def self.find(uri,subjectid=nil)
- return nil unless uri
- model = Generic.new(uri,subjectid)
- model.load_metadata
- raise "could not load model metadata '"+uri.to_s+"'" if model.metadata==nil or model.metadata.size==0
- model
- end
-
- # provides feature type, possible types are "regression" or "classification"
- # @return [String] feature type, "unknown" if type could not be estimated
- def feature_type
- unless @feature_type
- load_predicted_variables unless @predicted_variable
- @feature_type = OpenTox::Feature.find( @predicted_variable, @subjectid ).feature_type
- end
- @feature_type
- end
-
- def predicted_variable
- load_predicted_variables unless @predicted_variable
- @predicted_variable
- end
-
- def predicted_confidence
- load_predicted_variables unless @predicted_confidence
- @predicted_confidence
- end
-
- private
- def load_predicted_variables
- load_metadata if @metadata==nil or @metadata.size==0 or (@metadata.size==1 && @metadata.values[0]==@uri)
- if @metadata[OT.predictedVariables]
- predictedVariables = @metadata[OT.predictedVariables]
- if predictedVariables.is_a?(Array)
- if (predictedVariables.size==1)
- @predicted_variable = predictedVariables[0]
- elsif (predictedVariables.size==2)
- # PENDING identify confidence
- conf_index = -1
- predictedVariables.size.times do |i|
- f = OpenTox::Feature.find(predictedVariables[i])
- conf_index = i if f.metadata[DC.title]=~/(?i)confidence/
- end
- raise "could not estimate predicted variable from model: '"+uri.to_s+
- "', number of predicted-variables==2, but no confidence found" if conf_index==-1
- @predicted_variable = predictedVariables[1-conf_index]
- @predicted_confidence = predictedVariables[conf_index]
- else
- raise "could not estimate predicted variable from model: '"+uri.to_s+"', number of predicted-variables > 2"
- end
- else
- raise "could not estimate predicted variable from model: '"+uri.to_s+"', predicted-variables is no array"
- end
- end
- raise "could not estimate predicted variable from model: '"+uri.to_s+"'" unless @predicted_variable
- end
+ def run params=nil
+ post params, {:accept => 'text/uri-list'}
end
- # Lazy Structure Activity Relationship class
- class Lazar < Generic
-
- #include Model
- include Algorithm
-
- attr_accessor :compound, :prediction_dataset, :features, :effects, :activities, :p_values, :fingerprints, :feature_calculation_algorithm, :similarity_algorithm, :prediction_algorithm, :min_sim, :subjectid, :prop_kernel, :value_map
-
- def initialize(uri=nil,subjectid=nil)
-
- if uri
- super uri
- else
- super CONFIG[:services]["opentox-model"]
- end
-
- @metadata[OT.algorithm] = File.join(CONFIG[:services]["opentox-algorithm"],"lazar")
-
- @features = []
- @effects = {}
- @activities = {}
- @p_values = {}
- @fingerprints = {}
- @value_map = {}
-
- @feature_calculation_algorithm = "Substructure.match"
- @similarity_algorithm = "Similarity.tanimoto"
- @prediction_algorithm = "Neighbors.weighted_majority_vote"
-
- @min_sim = 0.3
- @prop_kernel = false
-
- end
-
- # Find a lazar model via URI, and loads metadata, could raise NotFound/NotAuthorized error
- # @param [String] uri Model URI
- # @return [OpenTox::Model::Generic] Model instance
- def self.find(uri,subjectid=nil)
- return nil unless uri
- model = Lazar.new(uri,subjectid)
- model.load_metadata
- raise "could not load model metadata '"+uri.to_s+"'" if model.metadata==nil or model.metadata.size==0
- model
- end
-
- # Create a new lazar model
- # @param [optional,Hash] params Parameters for the lazar algorithm (OpenTox::Algorithm::Lazar)
- # @return [OpenTox::Model::Lazar] lazar model
- def self.create(params)
- subjectid = params[:subjectid]
- lazar_algorithm = OpenTox::Algorithm::Generic.new File.join( CONFIG[:services]["opentox-algorithm"],"lazar")
- model_uri = lazar_algorithm.run(params)
- OpenTox::Model::Lazar.find(model_uri, subjectid)
- end
-
-=begin
- # Get a parameter value
- # @param [String] param Parameter name
- # @return [String] Parameter value
- def parameter(param)
- @metadata[OT.parameters].collect{|p| p[OT.paramValue] if p[DC.title] == param}.compact.first
- end
-
- # Predict a dataset
- # @param [String] dataset_uri Dataset URI
- # @param [optional,subjectid]
- # @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @return [OpenTox::Dataset] Dataset with predictions
- def predict_dataset(dataset_uri, subjectid=nil, waiting_task=nil)
- @prediction_dataset = Dataset.create(CONFIG[:services]["opentox-dataset"], subjectid)
- @prediction_dataset.add_metadata({
- OT.hasSource => @uri,
- DC.creator => @uri,
- DC.title => URI.decode(File.basename( @metadata[OT.dependentVariables] )),
- OT.parameters => [{DC.title => "dataset_uri", OT.paramValue => dataset_uri}]
- })
- d = Dataset.new(dataset_uri,subjectid)
- d.load_compounds(subjectid)
- count = 0
- d.compounds.each do |compound_uri|
- begin
- predict(compound_uri,false,subjectid)
- count += 1
- waiting_task.progress( count/d.compounds.size.to_f*100.0 ) if waiting_task
- rescue => ex
- LOGGER.warn "prediction for compound "+compound_uri.to_s+" failed: "+ex.message
- end
- end
- @prediction_dataset.save(subjectid)
- @prediction_dataset
- end
-
- # Predict a compound
- # @param [String] compound_uri Compound URI
- # @param [optinal,Boolean] verbose Verbose prediction (output includes neighbors and features)
- # @return [OpenTox::Dataset] Dataset with prediction
- def predict(compound_uri,verbose=false,subjectid=nil)
-
- @compound = Compound.new compound_uri
- features = {}
-
- unless @prediction_dataset
- @prediction_dataset = Dataset.create(CONFIG[:services]["opentox-dataset"], subjectid)
- @prediction_dataset.add_metadata( {
- OT.hasSource => @uri,
- DC.creator => @uri,
- DC.title => URI.decode(File.basename( @metadata[OT.dependentVariables] )),
- OT.parameters => [{DC.title => "compound_uri", OT.paramValue => compound_uri}]
- } )
- end
-
- return @prediction_dataset if database_activity(subjectid)
-
- load_metadata(subjectid)
- case OpenTox::Feature.find(metadata[OT.dependentVariables]).feature_type
- when "classification"
- # AM: Balancing, see http://www.maunz.de/wordpress/opentox/2011/balanced-lazar
- l = Array.new # larger
- s = Array.new # smaller fraction
-
- raise "no fingerprints in model" if @fingerprints.size==0
-
- @fingerprints.each do |training_compound,training_features|
- @activities[training_compound].each do |act|
- case act.to_s
- when "false"
- l << training_compound
- when "true"
- s << training_compound
- else
- LOGGER.warn "BLAZAR: Activity #{act.to_s} should not be reached."
- end
- end
- end
- if s.size > l.size then
- l,s = s,l # happy swapping
- LOGGER.info "BLAZAR: |s|=#{s.size}, |l|=#{l.size}."
- end
- # determine ratio
- modulo = l.size.divmod(s.size)# modulo[0]=ratio, modulo[1]=rest
- LOGGER.info "BLAZAR: Balance: #{modulo[0]}, rest #{modulo[1]}."
-
- # AM: Balanced predictions
- addon = (modulo[1].to_f/modulo[0]).ceil # what will be added in each round
- slack = (addon!=0 ? modulo[1].divmod(addon)[1] : 0) # what remains for the last round
- position = 0
- predictions = Array.new
-
- prediction_best=nil
- neighbors_best=nil
-
- begin
- for i in 1..modulo[0] do
- (i == modulo[0]) && (slack>0) ? lr_size = s.size + slack : lr_size = s.size + addon # determine fraction
- LOGGER.info "BLAZAR: Neighbors round #{i}: #{position} + #{lr_size}."
- neighbors_balanced(s, l, position, lr_size) # get ratio fraction of larger part
- if @prop_kernel && @prediction_algorithm.include?("svm")
- props = get_props
- else
- props = nil
- end
- prediction = eval("#{@prediction_algorithm}(@neighbors,{:similarity_algorithm => @similarity_algorithm, :p_values => @p_values}, props)")
- if prediction_best.nil? || prediction[:confidence].abs > prediction_best[:confidence].abs
- prediction_best=prediction
- neighbors_best=@neighbors
- end
- position = position + lr_size
- end
- rescue Exception => e
- LOGGER.error "BLAZAR failed in prediction: "+e.class.to_s+": "+e.message
- end
-
- prediction=prediction_best
- @neighbors=neighbors_best
- ### END AM balanced predictions
-
- else # AM: no balancing
- LOGGER.info "LAZAR: Unbalanced."
- neighbors
- if @prop_kernel && @prediction_algorithm.include?("svm")
- props = get_props
- else
- props = nil
- end
- prediction = eval("#{@prediction_algorithm}(@neighbors,{:similarity_algorithm => @similarity_algorithm, :p_values => @p_values}, props)")
- end
-
- value_feature_uri = File.join( @uri, "predicted", "value")
- confidence_feature_uri = File.join( @uri, "predicted", "confidence")
-
- #prediction_feature_uris = {value_feature_uri => prediction[:prediction], confidence_feature_uri => prediction[:confidence]}
- #prediction_feature_uris[value_feature_uri] = nil if @neighbors.size == 0 or prediction[:prediction].nil?
-
- @prediction_dataset.metadata[OT.dependentVariables] = @metadata[OT.dependentVariables]
- @prediction_dataset.metadata[OT.predictedVariables] = [value_feature_uri, confidence_feature_uri]
-
- if OpenTox::Feature.find(metadata[OT.dependentVariables]).feature_type == "classification"
- @prediction_dataset.add @compound.uri, value_feature_uri, @value_map[prediction[:prediction]]
- else
- @prediction_dataset.add @compound.uri, value_feature_uri, prediction[:prediction]
- end
- @prediction_dataset.add @compound.uri, confidence_feature_uri, prediction[:confidence]
- #prediction_feature_uris.each do |prediction_feature_uri,value|
- #@prediction_dataset.add @compound.uri, prediction_feature_uri, @value_map[value]
- #end
-
- if verbose
- if @feature_calculation_algorithm == "Substructure.match"
- f = 0
- @compound_features.each do |feature|
- feature_uri = File.join( @prediction_dataset.uri, "feature", "descriptor", f.to_s)
- features[feature] = feature_uri
- @prediction_dataset.add_feature(feature_uri, {
- RDF.type => [OT.Substructure],
- OT.smarts => feature,
- OT.pValue => @p_values[feature],
- OT.effect => @effects[feature]
- })
- @prediction_dataset.add @compound.uri, feature_uri, true
- f+=1
- end
- else
- @compound_features.each do |feature|
- features[feature] = feature
- @prediction_dataset.add @compound.uri, feature, true
- end
- end
- n = 0
- @neighbors.each do |neighbor|
- neighbor_uri = File.join( @prediction_dataset.uri, "feature", "neighbor", n.to_s )
- @prediction_dataset.add_feature(neighbor_uri, {
- OT.compound => neighbor[:compound],
- OT.similarity => neighbor[:similarity],
- OT.measuredActivity => neighbor[:activity],
- RDF.type => [OT.Neighbor]
- })
- @prediction_dataset.add @compound.uri, neighbor_uri, true
- f = 0 unless f
- neighbor[:features].each do |feature|
- if @feature_calculation_algorithm == "Substructure.match"
- feature_uri = File.join( @prediction_dataset.uri, "feature", "descriptor", f.to_s) unless feature_uri = features[feature]
- else
- feature_uri = feature
- end
- @prediction_dataset.add neighbor[:compound], feature_uri, true
- unless features.has_key? feature
- features[feature] = feature_uri
- @prediction_dataset.add_feature(feature_uri, {
- RDF.type => [OT.Substructure],
- OT.smarts => feature,
- OT.pValue => @p_values[feature],
- OT.effect => @effects[feature]
- })
- f+=1
- end
- end
- n+=1
- end
- end
- #end
-
- @prediction_dataset.save(subjectid)
- @prediction_dataset
- end
-
- # Calculate the propositionalization matrix aka instantiation matrix (0/1 entries for features)
- # Same for the vector describing the query compound
- def get_props
- matrix = Array.new
- begin
- @neighbors.each do |n|
- n = n[:compound]
- row = []
- @features.each do |f|
- if ! @fingerprints[n].nil?
- row << (@fingerprints[n].include?(f) ? 0.0 : @p_values[f])
- else
- row << 0.0
- end
- end
- matrix << row
- end
- row = []
- @features.each do |f|
- row << (@compound.match([f]).size == 0 ? 0.0 : @p_values[f])
- end
- rescue Exception => e
- LOGGER.debug "get_props failed with '" + $! + "'"
- end
- [ matrix, row ]
- end
-
- # Find neighbors and store them as object variable, access only a subset of compounds for that.
- def neighbors_balanced(s, l, start, offset)
- @compound_features = eval("#{@feature_calculation_algorithm}(@compound,@features)") if @feature_calculation_algorithm
- @neighbors = []
- [ l[start, offset ] , s ].flatten.each do |training_compound| # AM: access only a balanced subset
- training_features = @fingerprints[training_compound]
- add_neighbor training_features, training_compound
- end
-
- end
-
- # Find neighbors and store them as object variable, access all compounds for that.
- def neighbors
- @compound_features = eval("#{@feature_calculation_algorithm}(@compound,@features)") if @feature_calculation_algorithm
- @neighbors = []
- @fingerprints.each do |training_compound,training_features| # AM: access all compounds
- add_neighbor training_features, training_compound
- end
- end
-
- # Adds a neighbor to @neighbors if it passes the similarity threshold.
- def add_neighbor(training_features, training_compound)
- sim = eval("#{@similarity_algorithm}(@compound_features,training_features,@p_values)")
- if sim > @min_sim
- @activities[training_compound].each do |act|
- @neighbors << {
- :compound => training_compound,
- :similarity => sim,
- :features => training_features,
- :activity => act
- }
- end
- end
- end
-
- # Find database activities and store them in @prediction_dataset
- # @return [Boolean] true if compound has databasse activities, false if not
- def database_activity(subjectid)
- if @activities[@compound.uri]
- @activities[@compound.uri].each { |act| @prediction_dataset.add @compound.uri, @metadata[OT.dependentVariables], act }
- @prediction_dataset.add_metadata(OT.hasSource => @metadata[OT.trainingDataset])
- @prediction_dataset.save(subjectid)
- true
- else
- false
- end
- end
-
- def prediction_features
- [prediction_value_feature,prediction_confidence_feature]
- end
-
- def prediction_value_feature
- dependent_uri = @metadata[OT.dependentVariables].first
- feature = OpenTox::Feature.new File.join( @uri, "predicted", "value")
- feature.add_metadata( {
- RDF.type => [OT.ModelPrediction],
- OT.hasSource => @uri,
- DC.creator => @uri,
- DC.title => URI.decode(File.basename( dependent_uri )),
- OWL.sameAs => dependent_uri
- })
- feature
- end
-
- def prediction_confidence_feature
- dependent_uri = @metadata[OT.dependentVariables].first
- feature = OpenTox::Feature.new File.join( @uri, "predicted", "confidence")
- feature.add_metadata( {
- RDF.type => [OT.ModelPrediction],
- OT.hasSource => @uri,
- DC.creator => @uri,
- DC.title => "#{URI.decode(File.basename( dependent_uri ))} confidence"
- })
- feature
- end
-
- # Save model at model service
- def save(subjectid)
- self.uri = RestClientWrapper.post(@uri,self.to_yaml,{:content_type => "application/x-yaml", :subjectid => subjectid})
- end
-
- # Delete model at model service
- def delete(subjectid)
- RestClientWrapper.delete(@uri, :subjectid => subjectid) unless @uri == CONFIG[:services]["opentox-model"]
- end
-
-=end
- end
end
end
diff --git a/lib/ontology.rb b/lib/ontology.rb
deleted file mode 100644
index fa4ea6f..0000000
--- a/lib/ontology.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-module OpenTox
- module Ontology
- module Echa
-=begin
- require 'sparql/client'
- @sparql = SPARQL::Client.new("http://apps.ideaconsult.net:8080/ontology")
- def self.qs(classname="Endpoints")
- return "PREFIX ot:<http://www.opentox.org/api/1.1#>
- PREFIX ota:<http://www.opentox.org/algorithms.owl#>
- PREFIX owl:<http://www.w3.org/2002/07/owl#>
- PREFIX dc:<http://purl.org/dc/elements/1.1/>
- PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
- PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
- PREFIX otee:<http://www.opentox.org/echaEndpoints.owl#>
- PREFIX toxcast:<http://www.opentox.org/toxcast.owl#>
- select *
- where {
- ?endpoint rdfs:subClassOf otee:#{classname}.
- ?endpoint dc:title ?title.
- }"
- end
-
- def self.make_option_list(endpoint="Endpoints", level=1)
- out = ""
- results = @sparql.query(qs(endpoint)) rescue results = []
- results.each do |result|
- endpointname = result.Endpoints.to_s.split('#').last
- title = result.bound?(:title) ? result.title : endpointname
- out += "<option value='#{title}' id='#{endpointname}' class='level_#{level}'>#{title}</option>\n"
- out += make_option_list(endpointname, level + 1)
- end
- return out
- end
-
- def self.get_endpoint_selectlist(include_blank=true)
- out = "<select id='endpoint' name='endpoint'>\n"
- out += "<option value='' id='please_select'>Please select</option>\n" if include_blank
- out += make_option_list
- out += "</select>\n"
- return out
- end
-=end
-
- def self.endpoints
- RestClientWrapper.get("http://apps.ideaconsult.net:8080/ambit2/query/ndatasets_endpoint",:accept => "text/csv").collect { |line| line.split(',').first if line.match(/^http/) }.compact
- end
-
- def self.datasets(endpoint)
- RestClientWrapper.get("http://apps.ideaconsult.net:8080/ambit2/dataset?feature_sameas=#{URI.encode endpoint}", :accept => "text/uri-list").split("\n")
- end
-
- end
-
- end
-end
diff --git a/lib/opentox-client.rb b/lib/opentox-client.rb
new file mode 100644
index 0000000..bc297b5
--- /dev/null
+++ b/lib/opentox-client.rb
@@ -0,0 +1,7 @@
+require 'rdf'
+require 'rdf/raptor'
+require "rest-client"
+require "opentox"
+require "task"
+require "compound"
+require "dataset"
diff --git a/lib/opentox-ruby-minimal.rb b/lib/opentox-ruby-minimal.rb
deleted file mode 100644
index e0d5489..0000000
--- a/lib/opentox-ruby-minimal.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require "opentox"
-require "compound"
diff --git a/lib/opentox-ruby.rb b/lib/opentox-ruby.rb
deleted file mode 100644
index 63935fa..0000000
--- a/lib/opentox-ruby.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-#['rubygems', 'sinatra', 'sinatra/url_for', 'ohm', 'rest_client', 'yaml', 'cgi', 'spork', 'error', 'overwrite', 'environment'].each do |lib|
-['rubygems', 'rest_client', 'yaml', 'cgi', 'error', 'overwrite', 'environment'].each do |lib|
- require lib
-end
-
-#begin
- #require 'openbabel'
-#rescue LoadError
- #puts "Please install Openbabel with 'rake openbabel:install' in the compound component"
-#end
-
-#['opentox', 'compound','dataset', 'parser','serializer', 'algorithm','model','task','validation','feature', 'rest_client_wrapper', 'authorization', 'policy', 'helper', 'to-html', 'ontology' ].each do |lib|
-['opentox', 'compound','dataset', 'parser','serializer', 'algorithm','model','task','validation','feature', 'rest_client_wrapper', 'authorization', 'policy', 'ontology' ].each do |lib|
- require lib
-end
diff --git a/lib/opentox.owl b/lib/opentox.owl
deleted file mode 100644
index 4760055..0000000
--- a/lib/opentox.owl
+++ /dev/null
@@ -1,809 +0,0 @@
-<?xml version="1.0"?>
-<rdf:RDF
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:protege="http://protege.stanford.edu/plugins/owl/protege#"
- xmlns:xsp="http://www.owl-ontologies.com/2005/08/07/xsp.owl#"
- xmlns:ot="http://www.opentox.org/api/1.1#"
- xmlns:owl="http://www.w3.org/2002/07/owl#"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:p1="http://purl.org/dc/elements/1.1/#"
- xmlns:owl2xml="http://www.w3.org/2006/12/owl2-xml#"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
- xmlns:swrl="http://www.w3.org/2003/11/swrl#"
- xmlns:swrlb="http://www.w3.org/2003/11/swrlb#"
- xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
- xml:base="http://www.opentox.org/api/1.1">
- <owl:Ontology rdf:about="">
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/dev/apis/api-1.1</dc:identifier>
- <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >2009-11-22</dc:date>
- <dc:contributor rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >martin.guetlein@gmail.com</dc:contributor>
- <dc:contributor rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >jeliazkova.nina@gmail.com</dc:contributor>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >OpenTox resource ontology</rdfs:comment>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >OpenTox API</dc:title>
- <dc:creator rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >OpenTox</dc:creator>
- </owl:Ontology>
- <owl:Class rdf:ID="Dataset">
- <dc:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:description>
- <rdfs:seeAlso rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/dev/apis/api-1.1/dataset</rdfs:seeAlso>
- <dc:creator rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:creator>
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >/dataset/{datasetid}</dc:identifier>
- <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:date>
- <dc:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Original source of the dataset</dc:source>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:title>
- <dc:publisher rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:publisher>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Provides access to chemical compounds and their features (e.g. structural, physical-chemical, biological, toxicological properties)</rdfs:comment>
- <owl:disjointWith>
- <owl:Class rdf:ID="Feature"/>
- </owl:disjointWith>
- <owl:disjointWith>
- <owl:Class rdf:ID="Parameter"/>
- </owl:disjointWith>
- <dc:contributor rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:contributor>
- <rdfs:subClassOf>
- <owl:Class rdf:ID="OpentoxResource"/>
- </rdfs:subClassOf>
- <owl:disjointWith>
- <owl:Class rdf:ID="Model"/>
- </owl:disjointWith>
- <owl:disjointWith>
- <owl:Class rdf:ID="FeatureValuePair"/>
- </owl:disjointWith>
- </owl:Class>
- <owl:Class rdf:ID="FeatureValue">
- <owl:disjointWith>
- <owl:Class rdf:ID="Tuple"/>
- </owl:disjointWith>
- <rdfs:subClassOf>
- <owl:Class rdf:about="#FeatureValuePair"/>
- </rdfs:subClassOf>
- </owl:Class>
- <owl:Class rdf:about="#OpentoxResource">
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >A generic OpenTox resource</rdfs:comment>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >name of the resource</dc:title>
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >URI of the resource</dc:identifier>
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >1.1</owl:versionInfo>
- </owl:Class>
- <owl:Class rdf:ID="ConfusionMatrix">
- <rdfs:subClassOf>
- <owl:Class rdf:ID="ClassificationStatistics"/>
- </rdfs:subClassOf>
- </owl:Class>
- <owl:Class rdf:about="#Model">
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:title>
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >TODO: Specify allowed values for model content</owl:versionInfo>
- <dc:format rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >The native format of the model content (e.g. PMML, Weka model, etc.)</dc:format>
- <owl:disjointWith>
- <owl:Class rdf:about="#Parameter"/>
- </owl:disjointWith>
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >TODO: Introduce a link to User resource</owl:versionInfo>
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >/model/{modelid}</dc:identifier>
- <dc:creator rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >The model creator (perhaps a link to User resource)</dc:creator>
- <dc:rights rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:rights>
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >The date of model creation</dc:date>
- </owl:Class>
- <owl:Class rdf:ID="Validation">
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >A validation corresponds to the validation of a model on a test dataset. The results are stored in another dataset. Parameters with default values are optional.</rdfs:comment>
- <dc:date rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Datetime</dc:date>
- <rdfs:seeAlso rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/dev/apis/api-1.1/Validation</rdfs:seeAlso>
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- </owl:Class>
- <owl:Class rdf:ID="Report">
- <rdfs:seeAlso rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/dev/apis/api-1.1/Validation#validation-report</rdfs:seeAlso>
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- </owl:Class>
- <owl:Class rdf:ID="Algorithm">
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >TODO: AlgorithmType, or link to Algorithm ontology</owl:versionInfo>
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >1.1</owl:versionInfo>
- <dc:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Reference</dc:source>
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >TODO: statistics supported - is it possible to reuse ValidationInfo classes?</owl:versionInfo>
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >/algorithm/{algorithmid}</dc:identifier>
- <dc:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:description>
- <rdfs:seeAlso rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/dev/apis/api-1.1/Algorithm</rdfs:seeAlso>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Name of the algorithm</dc:title>
- <owl:disjointWith>
- <owl:Class rdf:about="#Feature"/>
- </owl:disjointWith>
- <owl:disjointWith rdf:resource="#Model"/>
- <owl:disjointWith>
- <owl:Class rdf:ID="Compound"/>
- </owl:disjointWith>
- <owl:disjointWith rdf:resource="#Dataset"/>
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- <owl:disjointWith>
- <owl:Class rdf:about="#Parameter"/>
- </owl:disjointWith>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Provides access to OpenTox algorithms</rdfs:comment>
- <dc:publisher rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:publisher>
- <owl:disjointWith>
- <owl:Class rdf:about="#FeatureValuePair"/>
- </owl:disjointWith>
- <owl:disjointWith>
- <owl:Class rdf:ID="DataEntry"/>
- </owl:disjointWith>
- </owl:Class>
- <owl:Class rdf:ID="CrossValidationInfo">
- <rdfs:subClassOf>
- <owl:Class rdf:ID="ValidationInfo"/>
- </rdfs:subClassOf>
- </owl:Class>
- <owl:Class rdf:about="#ValidationInfo">
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >encapsulates validation information</rdfs:comment>
- <rdfs:subClassOf rdf:resource="#Validation"/>
- </owl:Class>
- <owl:Class rdf:about="#Compound">
- <owl:disjointWith rdf:resource="#Model"/>
- <owl:disjointWith>
- <owl:Class rdf:about="#FeatureValuePair"/>
- </owl:disjointWith>
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >/compound/{compoundid}</dc:identifier>
- <rdfs:seeAlso rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/dev/apis/api-1.1/structure</rdfs:seeAlso>
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- <owl:disjointWith>
- <owl:Class rdf:about="#Feature"/>
- </owl:disjointWith>
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >1.1</owl:versionInfo>
- <owl:disjointWith>
- <owl:Class rdf:about="#DataEntry"/>
- </owl:disjointWith>
- <owl:disjointWith>
- <owl:Class rdf:about="#Parameter"/>
- </owl:disjointWith>
- <owl:disjointWith rdf:resource="#Dataset"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >API for OpenTox compound webservices</rdfs:comment>
- </owl:Class>
- <owl:Class rdf:ID="Conformer">
- <rdfs:subClassOf>
- <owl:Restriction>
- <owl:onProperty>
- <owl:FunctionalProperty rdf:ID="has3Dstructure"/>
- </owl:onProperty>
- <owl:hasValue rdf:datatype="http://www.w3.org/2001/XMLSchema#boolean"
- >true</owl:hasValue>
- </owl:Restriction>
- </rdfs:subClassOf>
- <rdfs:subClassOf rdf:resource="#Compound"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >[Optional] support for multiple (e.g. 3D) structures per chemical compound (single structure by default)</rdfs:comment>
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >/compound/{compoundid}/conformer/{conformerid}</dc:identifier>
- </owl:Class>
- <owl:Class rdf:about="#ClassificationStatistics">
- <rdfs:subClassOf rdf:resource="#ValidationInfo"/>
- </owl:Class>
- <owl:Class rdf:about="#FeatureValuePair">
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:identifier>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></rdfs:comment>
- <owl:disjointWith>
- <owl:Class rdf:about="#Parameter"/>
- </owl:disjointWith>
- <owl:disjointWith rdf:resource="#Model"/>
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- </owl:Class>
- <owl:Class rdf:about="#Feature">
- <owl:disjointWith rdf:resource="#Model"/>
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >1.1</owl:versionInfo>
- <dc:source rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:source>
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- <owl:disjointWith rdf:resource="#FeatureValuePair"/>
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >/feature/{featureid}</dc:identifier>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:title>
- <owl:disjointWith>
- <owl:Class rdf:about="#Parameter"/>
- </owl:disjointWith>
- <dc:description rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:description>
- </owl:Class>
- <owl:Class rdf:about="#Parameter">
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:title>
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- </owl:Class>
- <owl:Class rdf:ID="YScrambling">
- <rdfs:subClassOf rdf:resource="#ValidationInfo"/>
- </owl:Class>
- <owl:Class rdf:about="#DataEntry">
- <owl:disjointWith rdf:resource="#Feature"/>
- <dc:identifier rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >/dataset/{datasetid}/compound/{compoundid}?feature_uri[]=featureuris</dc:identifier>
- <owl:disjointWith rdf:resource="#Model"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- ></dc:title>
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >1.1</owl:versionInfo>
- <owl:disjointWith rdf:resource="#Parameter"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Encapsulates a dataset entry - defined by a single Compound (or conformer) and multiple FeatureValues. Could be regarded as "Compound with features"</rdfs:comment>
- <owl:disjointWith rdf:resource="#FeatureValuePair"/>
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- <owl:disjointWith rdf:resource="#Dataset"/>
- </owl:Class>
- <owl:Class rdf:ID="Task">
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- </owl:Class>
- <owl:Class rdf:ID="Crossvalidation">
- <rdfs:subClassOf rdf:resource="#OpentoxResource"/>
- </owl:Class>
- <owl:Class rdf:ID="EmptyDataset">
- <rdfs:subClassOf rdf:resource="#Dataset"/>
- </owl:Class>
- <owl:Class rdf:about="#Tuple">
- <owl:disjointWith rdf:resource="#FeatureValue"/>
- <rdfs:subClassOf rdf:resource="#FeatureValuePair"/>
- </owl:Class>
- <owl:Class rdf:ID="ClassValueStatistics">
- <rdfs:subClassOf rdf:resource="#ClassificationStatistics"/>
- </owl:Class>
- <owl:Class rdf:ID="ConfusionMatrixCell">
- <rdfs:subClassOf rdf:resource="#ConfusionMatrix"/>
- </owl:Class>
- <owl:Class rdf:ID="RegressionStatistics">
- <rdfs:subClassOf rdf:resource="#ValidationInfo"/>
- </owl:Class>
- <owl:ObjectProperty rdf:ID="conformer">
- <rdfs:domain rdf:resource="#Compound"/>
- <rdfs:range rdf:resource="#Conformer"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="crossvalidationDataset">
- <rdfs:range rdf:resource="#Dataset"/>
- <rdfs:domain rdf:resource="#Crossvalidation"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="validation">
- <rdfs:range rdf:resource="#ValidationInfo"/>
- <rdfs:domain rdf:resource="#Validation"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="confusionMatrixPredicted">
- <rdfs:range rdf:resource="#FeatureValuePair"/>
- <rdfs:domain rdf:resource="#ConfusionMatrixCell"/>
- <rdfs:subPropertyOf>
- <owl:ObjectProperty rdf:ID="confusionMatrixEntry"/>
- </rdfs:subPropertyOf>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="validationPredictionDataset">
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >PredictionDatasetURI</rdfs:comment>
- <rdfs:subPropertyOf rdf:resource="#validation"/>
- <rdfs:domain rdf:resource="#Validation"/>
- <rdfs:range rdf:resource="#Dataset"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="validationTrainingDataset">
- <rdfs:subPropertyOf rdf:resource="#validation"/>
- <rdfs:range rdf:resource="#Dataset"/>
- <rdfs:domain rdf:resource="#Validation"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="complexValue">
- <rdfs:range rdf:resource="#FeatureValue"/>
- <rdfs:domain rdf:resource="#Tuple"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="model">
- <rdfs:domain rdf:resource="#Model"/>
- <rdfs:range rdf:resource="#Dataset"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="dependentVariables">
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >A model can have one or more dependent variables, described as multiple features, specified by this relationship.</rdfs:comment>
- <rdfs:domain rdf:resource="#Model"/>
- <rdfs:subPropertyOf rdf:resource="#model"/>
- <rdfs:range rdf:resource="#Feature"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="crossvalidationAlgorithm">
- <rdfs:range rdf:resource="#Algorithm"/>
- <rdfs:domain rdf:resource="#Crossvalidation"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="validationCrossvalidation">
- <rdfs:range rdf:resource="#Crossvalidation"/>
- <rdfs:domain rdf:resource="#CrossValidationInfo"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="parameters">
- <rdfs:subPropertyOf rdf:resource="#model"/>
- <rdfs:range rdf:resource="#Parameter"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Algorithms and Models can have multiple parameters</rdfs:comment>
- <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/api/1.1</rdfs:isDefinedBy>
- <rdfs:domain>
- <owl:Class>
- <owl:unionOf rdf:parseType="Collection">
- <owl:Class rdf:about="#Algorithm"/>
- <owl:Class rdf:about="#Model"/>
- </owl:unionOf>
- </owl:Class>
- </rdfs:domain>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="validationTestDataset">
- <rdfs:range rdf:resource="#Dataset"/>
- <rdfs:subPropertyOf rdf:resource="#validation"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Test dataset , used in a validation exercise</rdfs:comment>
- <rdfs:domain rdf:resource="#Validation"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="predictedVariables">
- <rdfs:range rdf:resource="#Feature"/>
- <rdfs:subPropertyOf rdf:resource="#model"/>
- <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/api/1.1</rdfs:isDefinedBy>
- <rdfs:domain rdf:resource="#Model"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Variables, holding the predicted values, generated by the model</rdfs:comment>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="dataEntry">
- <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/api/1.1</rdfs:isDefinedBy>
- <rdfs:range rdf:resource="#DataEntry"/>
- <rdfs:domain rdf:resource="#Dataset"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >A Dataset contains multiple DataEntries. This property specifies the relationship between Dataset and DataEntry.</rdfs:comment>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="unscrambledDatasetURI">
- <rdfs:domain rdf:resource="#YScrambling"/>
- <rdfs:subPropertyOf rdf:resource="#validation"/>
- <rdfs:range rdf:resource="#Dataset"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >a link to UnscrambledDataset</dc:title>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >UnscrambledDatasetURI</rdfs:comment>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="independentVariables">
- <rdfs:domain rdf:resource="#Model"/>
- <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/api/1.1</rdfs:isDefinedBy>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >A model can have multiple independent variables, described as multiple features, specified by this relationship.</rdfs:comment>
- <rdfs:subPropertyOf rdf:resource="#model"/>
- <rdfs:range rdf:resource="#Feature"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="hasValidationInfo">
- <rdfs:subPropertyOf rdf:resource="#validation"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Links Validation with Validation Info. One validation exercise may have multiple types of validation informaton</rdfs:comment>
- <rdfs:domain rdf:resource="#Validation"/>
- <rdfs:range rdf:resource="#ValidationInfo"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="predictedFeature">
- <rdfs:domain rdf:resource="#Validation"/>
- <rdfs:range rdf:resource="#Feature"/>
- <rdfs:subPropertyOf rdf:resource="#validation"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="classValue">
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- <rdfs:range rdf:resource="#FeatureValuePair"/>
- <rdfs:subPropertyOf>
- <owl:ObjectProperty rdf:ID="classValueStatistics"/>
- </rdfs:subPropertyOf>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:about="#confusionMatrixEntry">
- <rdfs:range rdf:resource="#ConfusionMatrixCell"/>
- <rdfs:domain rdf:resource="#ConfusionMatrix"/>
- <rdfs:subPropertyOf>
- <owl:ObjectProperty rdf:ID="confusionMatrix"/>
- </rdfs:subPropertyOf>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="report">
- <rdfs:domain rdf:resource="#Report"/>
- <rdfs:range rdf:resource="#Validation"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="values">
- <rdfs:range rdf:resource="#FeatureValuePair"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >A DataEntry is defined with a single compound and multiple feature values. This property sets the relationship between a DataEntry and multiple FeatureValues</rdfs:comment>
- <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/api/1.1</rdfs:isDefinedBy>
- <rdfs:domain rdf:resource="#DataEntry"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:about="#classValueStatistics">
- <rdfs:domain rdf:resource="#ClassificationStatistics"/>
- <rdfs:range rdf:resource="#ClassValueStatistics"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:about="#confusionMatrix">
- <rdfs:domain rdf:resource="#ClassificationStatistics"/>
- <rdfs:range rdf:resource="#ConfusionMatrix"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="confusionMatrixActual">
- <rdfs:domain rdf:resource="#ConfusionMatrixCell"/>
- <rdfs:subPropertyOf rdf:resource="#confusionMatrixEntry"/>
- <rdfs:range rdf:resource="#FeatureValuePair"/>
- </owl:ObjectProperty>
- <owl:ObjectProperty rdf:ID="validationReport">
- <rdfs:range rdf:resource="#Validation"/>
- <rdfs:subPropertyOf rdf:resource="#report"/>
- <rdfs:domain rdf:resource="#Report"/>
- </owl:ObjectProperty>
- <owl:DatatypeProperty rdf:ID="precision">
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="numFalsePositives">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="stratified">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/>
- <rdfs:domain rdf:resource="#Crossvalidation"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="numFolds">
- <rdfs:domain rdf:resource="#Crossvalidation"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="falsePositiveRate">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="fMeasure">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="yScramblingInfo">
- <rdfs:domain rdf:resource="#YScrambling"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="falseNegativeRate">
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="hasStatus">
- <rdfs:range>
- <owl:DataRange>
- <owl:oneOf rdf:parseType="Resource">
- <rdf:first rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Cancelled</rdf:first>
- <rdf:rest rdf:parseType="Resource">
- <rdf:rest rdf:parseType="Resource">
- <rdf:first rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Running</rdf:first>
- <rdf:rest rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"/>
- </rdf:rest>
- <rdf:first rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Completed</rdf:first>
- </rdf:rest>
- </owl:oneOf>
- </owl:DataRange>
- </rdfs:range>
- <rdfs:domain rdf:resource="#Task"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="percentUnpredicted">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <rdfs:domain rdf:resource="#Validation"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="classificationStatistics">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <rdfs:domain rdf:resource="#ClassificationStatistics"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="rSquare">
- <rdfs:subPropertyOf>
- <owl:DatatypeProperty rdf:ID="regressionStatistics"/>
- </rdfs:subPropertyOf>
- <rdfs:domain rdf:resource="#RegressionStatistics"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="truePositiveRate">
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="percentWithoutClass">
- <rdfs:domain rdf:resource="#Validation"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="numWithoutClass">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- <rdfs:domain rdf:resource="#Validation"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="paramValue">
- <rdfs:domain rdf:resource="#Parameter"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Parameter value</dc:title>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >The value of a Parameter</rdfs:comment>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="statisticsSupported">
- <rdfs:domain rdf:resource="#Algorithm"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="numUnpredicted">
- <rdfs:domain rdf:resource="#Validation"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="crossValidationInfo">
- <rdfs:domain rdf:resource="#CrossValidationInfo"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:about="#regressionStatistics">
- <rdfs:domain rdf:resource="#RegressionStatistics"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="numTrueNegatives">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="recall">
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="numInstances">
- <rdfs:domain rdf:resource="#Validation"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="numFalseNegatives">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="units">
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Units</dc:title>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Units for a feature value</rdfs:comment>
- <owl:versionInfo rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >TODO: make use of units ontology</owl:versionInfo>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="areaUnderROC">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="randomSeed">
- <rdfs:domain rdf:resource="#Crossvalidation"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#long"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="trueNegativeRate">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="confusionMatrixValue">
- <rdfs:domain rdf:resource="#ConfusionMatrixCell"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- </owl:DatatypeProperty>
- <owl:DatatypeProperty rdf:ID="numTruePositives">
- <rdfs:domain rdf:resource="#ClassValueStatistics"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- </owl:DatatypeProperty>
- <owl:TransitiveProperty rdf:ID="isA">
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Allows to define "is a" relationships outside of particular class hierarchy</rdfs:comment>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
- </owl:TransitiveProperty>
- <owl:FunctionalProperty rdf:ID="validationModel">
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Model used in a validation exercise</rdfs:comment>
- <rdfs:subPropertyOf rdf:resource="#validation"/>
- <rdfs:range rdf:resource="#Model"/>
- <rdfs:domain rdf:resource="#Validation"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="numIncorrect">
- <rdfs:domain rdf:resource="#ClassificationStatistics"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Number incorrect</dc:title>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- <rdfs:subPropertyOf rdf:resource="#classificationStatistics"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="percentCorrect">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Percent Correct</dc:title>
- <rdfs:domain rdf:resource="#ClassificationStatistics"/>
- <rdfs:subPropertyOf rdf:resource="#classificationStatistics"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="rootMeanSquaredError">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >RootMeanSquaredError</rdfs:comment>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- <rdfs:subPropertyOf rdf:resource="#regressionStatistics"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="yScramblingEnabled">
- <rdfs:subPropertyOf rdf:resource="#yScramblingInfo"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- <rdfs:domain rdf:resource="#YScrambling"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >YScramblingEnabled</dc:title>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >YScramblingEnabled</rdfs:comment>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="yScramblingSeed">
- <rdfs:subPropertyOf rdf:resource="#yScramblingInfo"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >YScramblingSeed</dc:title>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >YScramblingSeed</rdfs:comment>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- <rdfs:domain rdf:resource="#YScrambling"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="fold">
- <rdfs:domain rdf:resource="#CrossValidationInfo"/>
- <rdfs:subPropertyOf rdf:resource="#crossValidationInfo"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:about="#has3Dstructure">
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Has 3D structure</dc:title>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >True, if the compound has 3D structure</rdfs:comment>
- <rdfs:domain rdf:resource="#Compound"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="value">
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Literal</rdfs:comment>
- <rdfs:domain rdf:resource="#FeatureValue"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Feature value</dc:title>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="trainingDataset">
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
- <rdfs:domain rdf:resource="#Model"/>
- <rdfs:subPropertyOf rdf:resource="#model"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >A model is derived by applying an Algorithm on a training Dataset.</rdfs:comment>
- <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/api/1.1</rdfs:isDefinedBy>
- <rdfs:range rdf:resource="#Dataset"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="realRuntime">
- <rdfs:domain rdf:resource="#Validation"/>
- <rdfs:domain rdf:resource="#Crossvalidation"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#long"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="algorithm">
- <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/api/1.1</rdfs:isDefinedBy>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >The algorithm, used to create the Model</rdfs:comment>
- <rdfs:range rdf:resource="#Algorithm"/>
- <rdfs:subPropertyOf rdf:resource="#model"/>
- <rdfs:domain rdf:resource="#Model"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="numCorrect">
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#int"/>
- <rdfs:subPropertyOf rdf:resource="#classificationStatistics"/>
- <rdfs:domain rdf:resource="#ClassificationStatistics"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Number correct</dc:title>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="hasSource">
- <rdfs:domain rdf:resource="#Feature"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
- <rdfs:range>
- <owl:Class>
- <owl:unionOf rdf:parseType="Collection">
- <owl:Class rdf:about="#Algorithm"/>
- <owl:Class rdf:about="#Dataset"/>
- <owl:Class rdf:about="#Model"/>
- </owl:unionOf>
- </owl:Class>
- </rdfs:range>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="paramScope">
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >specifies if a parameter is optional or mandatory</rdfs:comment>
- <rdfs:domain rdf:resource="#Parameter"/>
- <rdfs:range>
- <owl:DataRange>
- <owl:oneOf rdf:parseType="Resource">
- <rdf:rest rdf:parseType="Resource">
- <rdf:rest rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"/>
- <rdf:first rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >optional</rdf:first>
- </rdf:rest>
- <rdf:first rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >mandatory</rdf:first>
- </owl:oneOf>
- </owl:DataRange>
- </rdfs:range>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Parameter scope</dc:title>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="percentageCompleted">
- <rdfs:domain rdf:resource="#Task"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Percentage completed</dc:title>
- <rdfs:subPropertyOf rdf:resource="#classificationStatistics"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="compound">
- <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/api/1.1</rdfs:isDefinedBy>
- <rdfs:range rdf:resource="#Compound"/>
- <rdfs:domain rdf:resource="#DataEntry"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >A DataEntry is defined with a single compound and multiple feature values. This property sets the relationship between a DataEntry and a Compound</rdfs:comment>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="percentIncorrect">
- <rdfs:subPropertyOf rdf:resource="#classificationStatistics"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- <dc:title rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >Percent Incorrect</dc:title>
- <rdfs:domain rdf:resource="#ClassificationStatistics"/>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="meanAbsolutError">
- <rdfs:subPropertyOf rdf:resource="#regressionStatistics"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >MeanAbsolutError</rdfs:comment>
- <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#float"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#DatatypeProperty"/>
- </owl:FunctionalProperty>
- <owl:FunctionalProperty rdf:ID="feature">
- <rdfs:range rdf:resource="#Feature"/>
- <rdfs:comment rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >FeatureValue contains a value for specific Feature, specified by this relationship.</rdfs:comment>
- <rdfs:domain rdf:resource="#FeatureValuePair"/>
- <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#ObjectProperty"/>
- <rdfs:isDefinedBy rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
- >http://opentox.org/api/1.1</rdfs:isDefinedBy>
- </owl:FunctionalProperty>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/date"/>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/source"/>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/identifier"/>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/title"/>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/rights"/>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/publisher"/>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/description"/>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/format"/>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/creator"/>
- <owl:AnnotationProperty rdf:about="http://purl.org/dc/elements/1.1/contributor"/>
-</rdf:RDF>
-
-<!-- Created with Protege (with OWL Plugin 3.4.1, Build 536) http://protege.stanford.edu -->
diff --git a/lib/opentox.rb b/lib/opentox.rb
index a6ac1d4..a9cbeab 100644
--- a/lib/opentox.rb
+++ b/lib/opentox.rb
@@ -1,23 +1,100 @@
-require 'rdf'
-require 'rdf/raptor'
-#require "parser.rb"
-require "rest_client_wrapper.rb"
-require "overwrite.rb"
-require "error.rb"
-
-RDF::OT = RDF::Vocabulary.new 'http://www.opentox.org/api/1.1#'
+#TODO: switch services to 1.2
+#TODO: error handling
+RDF::OT = RDF::Vocabulary.new 'http://www.opentox.org/api/1.2#'
+RDF::OT1 = RDF::Vocabulary.new 'http://www.opentox.org/api/1.1#'
RDF::OTA = RDF::Vocabulary.new 'http://www.opentox.org/algorithmTypes.owl#'
SERVICES = ["Compound", "Feature", "Dataset", "Algorithm", "Model", "Validation", "Task"]
+# not working
+RestClient.add_before_execution_proc do |req, params|
+ params[:subjectid] = @subjectid
+end
+
+class String
+ def to_object
+ # TODO: fix, this is unsafe
+ self =~ /dataset/ ? uri = File.join(self.chomp,"metadata") : uri = self.chomp
+ raise "#{uri} is not a valid URI." unless RDF::URI.new(uri).uri?
+ RDF::Reader.open(uri) do |reader|
+ reader.each_statement do |statement|
+ if statement.predicate == RDF.type and statement.subject == uri
+ klass = "OpenTox::#{statement.object.to_s.split("#").last}"
+ object = eval "#{klass}.new \"#{uri}\""
+ end
+ end
+ end
+ # fallback: guess class from uri
+ # TODO: fix services and remove
+ unless object
+ case uri
+ when /compound/
+ object = OpenTox::Compound.new uri
+ when /feature/
+ object = OpenTox::Feature.new uri
+ when /dataset/
+ object = OpenTox::Dataset.new uri.sub(/\/metadata/,'')
+ when /algorithm/
+ object = OpenTox::Algorithm.new uri
+ when /model/
+ object = OpenTox::Model.new uri
+ when /validation/
+ object = OpenTox::Validation.new uri
+ when /task/
+ object = OpenTox::Task.new uri
+ else
+ raise "Class for #{uri} not found."
+ end
+ end
+ if object.class == Task # wait for tasks
+ object.wait_for_completion
+ object = object.result_uri.to_s.to_object
+ end
+ object
+ end
+
+=begin
+ def object_from_uri
+ # TODO: fix, this is unsafe
+ self =~ /dataset/ ? uri = File.join(self.chomp,"metadata") : uri = self.chomp
+ RDF::Reader.open(uri) do |reader|
+ reader.each_statement do |statement|
+ if statement.predicate == RDF.type and statement.subject == uri
+ klass = "OpenTox::#{statement.object.to_s.split("#").last}"
+ return eval "#{klass}.new \"#{uri}\""
+ end
+ end
+ end
+ # guess class from uri
+ # TODO: fix services and remove
+ case uri
+ when /compound/
+ return OpenTox::Compound.new uri
+ when /feature/
+ return OpenTox::Feature.new uri
+ when /dataset/
+ return OpenTox::Dataset.new uri.sub(/\/metadata/,'')
+ when /algorithm/
+ return OpenTox::Algorithm.new uri
+ when /model/
+ return OpenTox::Model.new uri
+ when /validation/
+ return OpenTox::Validation.new uri
+ when /task/
+ return OpenTox::Task.new uri
+ else
+ raise "Class for #{uri} not found."
+ end
+ end
+=end
+end
+
module OpenTox
- attr_accessor :subjectid, :uri
+ attr_accessor :subjectid, :uri, :response
attr_writer :metadata
- # Initialize OpenTox object with optional subjectid
- # @param [optional, String] subjectid
def initialize uri=nil, subjectid=nil
- @uri = uri
+ @uri = uri.chomp
@subjectid = subjectid
end
@@ -36,104 +113,73 @@ module OpenTox
end
def save
- rdf = RDF::Writer.buffer do |writer|
+ rdf = RDF::Writer.for(:rdfxml).buffer do |writer|
@metadata.each { |p,o| writer << RDF::Statement.new(RDF::URI.new(@uri), p, o) }
end
- puts rdf
- #post(@uri, rdf, { :content_type => 'application/rdf+xml', :subjectid => subjectid}).to_s.chomp, @subjectid
+ post rdf, { :content_type => 'application/rdf+xml'}
end
# REST API
- # returns OpenTox::WrapperResult, not OpenTox objects
-
- # perfoms a GET REST call
- # raises OpenTox::Error if call fails (rescued in overwrite.rb -> halt 502)
- # per default: waits for Task to finish and returns result URI of Task
- # @param [optional,Hash] headers contains params like accept-header
- # @param [wait,Boolean] wait set to false to NOT wait for task if result is task
- # @return [OpenTox::WrapperResult] a String containing the result-body of the REST call
- def get headers={}, wait=true
- headers[:subjectid] = @subjectid
- RestClientWrapper.get(@uri.to_s, headers, nil, wait).chomp
+ def get params={}
+ params[:subjectid] ||= @subjectid
+ params[:accept] ||= 'application/rdf+xml'
+ @response = RestClient.get @uri, params
end
- # performs a POST REST call
- # raises OpenTox::Error if call fails (rescued in overwrite.rb -> halt 502)
- # per default: waits for Task to finish and returns result URI of Task
- # @param [optional,String] payload data posted to the service
- # @param [optional,Hash] headers contains params like accept-header
- # @param [wait,Boolean] wait set to false to NOT wait for task if result is task
- # @return [OpenTox::WrapperResult] a String containing the result-body of the REST call
- def post payload={}, headers={}, wait=true
- headers[:subjectid] = @subjectid
- RestClientWrapper.post(@uri.to_s, payload, headers, nil, wait).chomp
+ def post payload={}, params={}
+ params[:subjectid] ||= @subjectid
+ params[:accept] ||= 'application/rdf+xml'
+ @response = RestClient.post(@uri.to_s, payload, params)
+ begin
+ @response.to_s.to_object
+ rescue
+ @response
+ end
end
- # performs a PUT REST call
- # raises OpenTox::Error if call fails (rescued in overwrite.rb -> halt 502)
- # @param [optional,String] payload data put to the service
- # @param [optional,Hash] headers contains params like accept-header
- # @return [OpenTox::WrapperResult] a String containing the result-body of the REST call
- def put payload={}, headers={}
- headers[:subjectid] = @subjectid
- RestClientWrapper.put(@uri.to_s, payload, headers).chomp
+ def put payload={}, params={}
+ params[:subjectid] ||= @subjectid
+ params[:accept] ||= 'application/rdf+xml'
+ @response = RestClient.put(@uri.to_s, payload, params)
end
- # performs a DELETE REST call
- # raises OpenTox::Error if call fails (rescued in overwrite.rb -> halt 502)
- # @return [OpenTox::WrapperResult] a String containing the result-body of the REST call
- def delete
- RestClientWrapper.delete(@uri.to_s,:subjectid => @subjectid)
+ def delete params={}
+ params[:subjectid] ||= @subjectid
+ params[:accept] ||= 'application/rdf+xml'
+ @response = RestClient.delete(@uri.to_s,:subjectid => @subjectid)
end
+ # class methods
+ module ClassMethods
- module Service
def create service_uri, subjectid=nil
- service = eval("#{self}.new(\"#{service_uri}\", #{subjectid})")
- uri = service.post({}, {}, subjectid).to_s
- eval "#{self}.new(\"#{uri}\", #{subjectid})"
+ uri = RestClient.post(service_uri, {}, :subjectid => subjectid).chomp
+ eval("#{self}.new(\"#{uri}\", #{subjectid})")
end
+
+ def from_file service_uri, file, subjectid=nil
+ RestClient.post(service_uri, :file => File.new(file), :subjectid => subjectid).chomp.to_object
+ end
+
+ def all service_uri, subjectid=nil
+ uris = RestClient.get(service_uri, {:accept => 'text/uri-list'}).split("\n").compact
+ uris.collect{|uri| eval "#{self}.new(\"#{uri}\", #{subjectid})"}
+ end
+
+ end
+
+ class FromUri
end
# create default classes
SERVICES.each do |s|
eval "class #{s}
include OpenTox
- extend OpenTox::Service
+ extend OpenTox::ClassMethods
end"
end
-=begin
private
- def uri_available?
- url = URI.parse(@uri)
- #req = Net::HTTP.new(url.host,url.port)
- #req['subjectid'] = @subjectid if @subjectid
- Net::HTTP.start(url.host, url.port) do |http|
- return http.head("#{url.request_uri}#{subjectidstr}").code == "200"
- end
- end
-
- module Collection
-
- include OpenTox
-
- def create metadata
- object_class.new post(service_uri, metadata.to_rdfxml, { :content_type => 'application/rdf+xml', :subjectid => subjectid}).to_s.chomp, @subject_id
- end
-
- # Get all objects from a service
- # @return [Array] List of available Objects
- def all
- get(:accept => "text/uri-list").to_s.split(/\n/).collect{|uri| object_class.new uri,@subjectid}
- end
-
- # create collection classes
- SERVICES.each { |s| eval "class #{s}; include Collection; end" }
-
- end
-=end
-
end
diff --git a/lib/overwrite.rb b/lib/overwrite.rb
deleted file mode 100644
index d541b61..0000000
--- a/lib/overwrite.rb
+++ /dev/null
@@ -1,155 +0,0 @@
-require 'uri'
-=begin
-# class overwrites aka monkey patches
-# hack: store sinatra instance in global var $url_provider to make url_for and halt methods accessible
-before {
- raise "should not happen, url provider already differently initialized "+
- $url_provider.request.host.to_s+" != "+self.request.host.to_s if
- $url_provider and $url_provider.request.host!=self.request.host and
- $url_provider.request.script_name!=self.request.script_name
- $url_provider = self
- # stupid internet explorer does not ask for text/html, add this manually
- request.env['HTTP_ACCEPT'] += ";text/html" if request.env["HTTP_USER_AGENT"]=~/MSIE/
- request.env['HTTP_ACCEPT']=request.params["media"] if request.params["media"]
-}
-
-# Error handling
-# Errors are logged as error and formated according to acccept-header
-# Non OpenTox::Errors (defined in error.rb) are handled as internal error (500), stacktrace is logged
-# IMPT: set sinatra settings :show_exceptions + :raise_errors to false in config.ru, otherwise Rack::Showexceptions takes over
-error Exception do
- error = request.env['sinatra.error']
- # log error message and backtrace to logfile
- LOGGER.error error.class.to_s+": "+error.message
- LOGGER.error ":\n"+error.backtrace.join("\n")
-
- actor = "#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}#{request.env['REQUEST_URI']}"
- rep = OpenTox::ErrorReport.create(error, actor)
-
- case request.env['HTTP_ACCEPT']
- when /rdf/
- content_type 'application/rdf+xml'
- halt error.http_code,rep.to_rdfxml
- when /html/
- content_type 'text/html'
- halt error.http_code,(OpenTox.text_to_html rep.to_yaml, @subjectid)
- else
- content_type 'application/x-yaml'
- halt error.http_code,rep.to_yaml
- end
-end
-
-class Sinatra::Base
-
- def return_task( task )
- raise "http_code == nil" unless task.http_code!=nil
- case request.env['HTTP_ACCEPT']
- when /rdf/
- response['Content-Type'] = "application/rdf+xml"
- halt task.http_code,task.to_rdfxml
- when /yaml/
- response['Content-Type'] = "application/x-yaml"
- halt task.http_code,task.to_yaml # PENDING differs from task-webservice
- when /html/
- response['Content-Type'] = "text/html"
- halt task.http_code,OpenTox.text_to_html(task.to_yaml, @subjectid)
- else # default /uri-list/
- response['Content-Type'] = "text/uri-list"
- if task.completed?
- halt task.http_code,task.resultURI+"\n"
- else
- halt task.http_code,task.uri+"\n"
- end
- end
- end
-end
-=end
-
-class String
- def task_uri?
- self.uri? && !self.match(/task/).nil?
- end
-
- def dataset_uri?
- self.uri? && !self.match(/dataset/).nil?
- end
-
- def self.model_uri?
- self.uri? && !self.match(/model/).nil?
- end
-
- def uri?
- begin
- u = URI::parse(self)
- return (u.scheme!=nil and u.host!=nil)
- rescue URI::InvalidURIError
- return false
- end
- end
-
- def underscore
- self.gsub(/::/, '/').
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
- tr("-", "_").
- downcase
- end
-end
-
-require 'logger'
-# logging
-#class Logger
-class OTLogger < Logger
-
- def pwd
- path = Dir.pwd.to_s
- index = path.rindex(/\//)
- return path if index==nil
- path[(index+1)..-1]
- end
-
- def trace()
- lines = caller(0)
- n = 2
- line = lines[n]
-
- while (line =~ /spork.rb/ or line =~ /create/ or line =~ /overwrite.rb/)
- n += 1
- line = lines[n]
- end
-
- index = line.rindex(/\/.*\.rb/)
- return line if index==nil
- line[index..-1]
- end
-
- def format(msg)
- pwd.ljust(18)+" :: "+msg.to_s+" :: "+trace
- end
-
- def debug(msg)
- super format(msg)
- end
-
- def info(msg)
- super format(msg)
- end
-
- def warn(msg)
- super format(msg)
- end
-
- def error(msg)
- super format(msg)
- end
-
-end
-
-# make migration from datamapper more straightforward
-=begin
-class Ohm::Model
- def self.get(id)
- self[id]
- end
-end
-=end
diff --git a/lib/parser.rb b/lib/parser.rb
deleted file mode 100644
index 7475d6d..0000000
--- a/lib/parser.rb
+++ /dev/null
@@ -1,475 +0,0 @@
-#require 'spreadsheet'
-#require 'roo'
-
-# OWL Namespaces
-class OwlNamespace
-
- attr_accessor :uri
- def initialize(uri)
- @uri = uri
- end
-
- def [](property)
- @uri+property.to_s
- end
-
- def type # for RDF.type
- "#{@uri}type"
- end
-
- def method_missing(property)
- @uri+property.to_s
- end
-
-end
-
-RDF = OwlNamespace.new 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
-OWL = OwlNamespace.new 'http://www.w3.org/2002/07/owl#'
-DC = OwlNamespace.new 'http://purl.org/dc/elements/1.1/'
-OT = OwlNamespace.new 'http://www.opentox.org/api/1.1#'
-OTA = OwlNamespace.new 'http://www.opentox.org/algorithmTypes.owl#'
-XSD = OwlNamespace.new 'http://www.w3.org/2001/XMLSchema#'
-
-class String
-
- # Split RDF statement into triples
- # @return [Array] Array with [subject,predicate,object]
- def to_triple
- self.chomp.split(' ',3).collect{|i| i.sub(/\s+.$/,'').gsub(/[<>"]/,'')}
- end
-
-end
-
-module OpenTox
-
- # Parser for various input formats
- module Parser
-
- # OWL-DL parser
- module Owl
-
- # Create a new OWL-DL parser
- # @param uri URI of OpenTox object
- # @return [OpenTox::Parser::Owl] OWL-DL parser
- def initialize(uri)
- @uri = uri
- @metadata = {}
- end
-
- # Read metadata from opentox service
- # @return [Hash] Object metadata
- def load_metadata(subjectid=nil)
- # avoid using rapper directly because of 2 reasons:
- # * http errors wont be noticed
- # * subjectid cannot be sent as header
- ##uri += "?subjectid=#{CGI.escape(subjectid)}" if subjectid
- ## `rapper -i rdfxml -o ntriples #{uri} 2>/dev/null`.each_line do |line|
- if File.exist?(@uri)
- file = File.new(@uri)
- else
- file = Tempfile.new("ot-rdfxml")
- if @dataset
- # do not concat /metadata to uri string, this would not work for dataset/R401577?max=3
- uri = URI::parse(@uri)
- uri.path = File.join(uri.path,"metadata")
- uri = uri.to_s
- else
- uri = @uri
- end
- file.puts OpenTox::RestClientWrapper.get uri,{:subjectid => subjectid,:accept => "application/rdf+xml"},nil,false
- file.close
- to_delete = file.path
- end
- statements = []
- parameter_ids = []
- `rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`.each_line do |line|
- triple = line.to_triple
- if triple[0] == @uri
- if triple[1] == RDF.type || triple[1]==OT.predictedVariables # allow multiple types
- @metadata[triple[1]] = [] unless @metadata[triple[1]]
- @metadata[triple[1]] << triple[2].split('^^').first
- else
- @metadata[triple[1]] = triple[2].split('^^').first
- end
- end
- statements << triple
- parameter_ids << triple[2] if triple[1] == OT.parameters
- end
- File.delete(to_delete) if to_delete
- unless parameter_ids.empty?
- @metadata[OT.parameters] = []
- parameter_ids.each do |p|
- parameter = {}
- statements.each{ |t| parameter[t[1]] = t[2] if t[0] == p and t[1] != RDF['type']}
- @metadata[OT.parameters] << parameter
- end
- end
- @metadata
- end
-
- # creates owl object from rdf-data
- # @param [String] rdf
- # @param [String] type of the info (e.g. OT.Task, OT.ErrorReport) needed to get the subject-uri
- # @return [Owl] with uri and metadata set
- def self.from_rdf( rdf, type )
- # write to file and read convert with rapper into tripples
- file = Tempfile.new("ot-rdfxml")
- file.puts rdf
- file.close
- #puts "cmd: rapper -i rdfxml -o ntriples #{file} 2>/dev/null"
- triples = `rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`
-
- # load uri via type
- uri = nil
- triples.each_line do |line|
- triple = line.to_triple
- if triple[1] == RDF['type'] and triple[2]==type
- raise "uri already set, two uris found with type: "+type.to_s if uri
- uri = triple[0]
- end
- end
- File.delete(file.path)
- # load metadata
- metadata = {}
- triples.each_line do |line|
- triple = line.to_triple
- metadata[triple[1]] = triple[2].split('^^').first if triple[0] == uri and triple[1] != RDF['type']
- end
- owl = Owl::Generic.new(uri)
- owl.metadata = metadata
- owl
- end
-
- # Generic parser for all OpenTox classes
- class Generic
- include Owl
-
- attr_accessor :uri, :metadata
- end
-
- # OWL-DL parser for datasets
- class Dataset
-
- include Owl
-
- attr_writer :uri
-
- # Create a new OWL-DL dataset parser
- # @param uri Dataset URI
- # @return [OpenTox::Parser::Owl::Dataset] OWL-DL parser
- def initialize(uri, subjectid=nil)
- super uri
- @dataset = ::OpenTox::Dataset.new(@uri, subjectid)
- end
-
- # Read data from dataset service. Files can be parsed by setting #uri to a filename (after initialization with a real URI)
- # @example Read data from an external service
- # parser = OpenTox::Parser::Owl::Dataaset.new "http://wwbservices.in-silico.ch/dataset/1"
- # dataset = parser.load_uri
- # @example Create dataset from RDF/XML file
- # dataset = OpenTox::Dataset.create
- # parser = OpenTox::Parser::Owl::Dataaset.new dataset.uri
- # parser.uri = "dataset.rdfxml" # insert your input file
- # dataset = parser.load_uri
- # dataset.save
- # @return [Hash] Internal dataset representation
- def load_uri(subjectid=nil)
-
- # avoid using rapper directly because of 2 reasons:
- # * http errors wont be noticed
- # * subjectid cannot be sent as header
- ##uri += "?subjectid=#{CGI.escape(subjectid)}" if subjectid
- ##`rapper -i rdfxml -o ntriples #{file} 2>/dev/null`.each_line do |line|
- if File.exist?(@uri)
- file = File.new(@uri)
- else
- file = Tempfile.new("ot-rdfxml")
- file.puts OpenTox::RestClientWrapper.get @uri,{:subjectid => subjectid,:accept => "application/rdf+xml"},nil,false
- file.close
- to_delete = file.path
- end
-
- data = {}
- feature_values = {}
- feature = {}
- feature_accept_values = {}
- other_statements = {}
- `rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`.each_line do |line|
- triple = line.chomp.split(' ',3)
- triple = triple[0..2].collect{|i| i.sub(/\s+.$/,'').gsub(/[<>"]/,'')}
- case triple[1]
- when /#{OT.values}/i
- data[triple[0]] = {:compound => "", :values => []} unless data[triple[0]]
- data[triple[0]][:values] << triple[2]
- when /#{OT.value}/i
- feature_values[triple[0]] = triple[2]
- when /#{OT.compound}/i
- data[triple[0]] = {:compound => "", :values => []} unless data[triple[0]]
- data[triple[0]][:compound] = triple[2]
- when /#{OT.feature}/i
- feature[triple[0]] = triple[2]
- when /#{RDF.type}/i
- if triple[2]=~/#{OT.Compound}/i and !data[triple[0]]
- data[triple[0]] = {:compound => triple[0], :values => []}
- end
- when /#{OT.acceptValue}/i # acceptValue in ambit datasets is only provided in dataset/<id> no in dataset/<id>/features
- feature_accept_values[triple[0]] = [] unless feature_accept_values[triple[0]]
- feature_accept_values[triple[0]] << triple[2]
- else
- end
- end
- File.delete(to_delete) if to_delete
- data.each do |id,entry|
- if entry[:values].size==0
- # no feature values add plain compounds
- @dataset.add_compound(entry[:compound])
- else
- entry[:values].each do |value_id|
- if feature_values[value_id]
- split = feature_values[value_id].split(/\^\^/)
- case split[-1]
- when XSD.double, XSD.float
- value = split.first.to_f
- when XSD.boolean
- value = split.first=~/(?i)true/ ? true : false
- else
- value = split.first
- end
- end
- @dataset.add entry[:compound],feature[value_id],value
- end
- end
- end
- load_features subjectid
- feature_accept_values.each do |feature, values|
- @dataset.features[feature][OT.acceptValue] = values
- end
- @dataset.metadata = load_metadata(subjectid)
- @dataset
- end
-
- # Read only features from a dataset service.
- # @return [Hash] Internal features representation
- def load_features(subjectid=nil)
- if File.exist?(@uri)
- file = File.new(@uri)
- else
- file = Tempfile.new("ot-rdfxml")
- # do not concat /features to uri string, this would not work for dataset/R401577?max=3
- uri = URI::parse(@uri)
- # PENDING
- # ambit models return http://host/dataset/id?feature_uris[]=sth but
- # amibt dataset services does not support http://host/dataset/id/features?feature_uris[]=sth
- # -> load features from complete dataset
- uri.path = File.join(uri.path,"features") unless @uri=~/\?feature_uris\[\]/
- uri = uri.to_s
- file.puts OpenTox::RestClientWrapper.get uri,{:subjectid => subjectid,:accept => "application/rdf+xml"},nil,false
- file.close
- to_delete = file.path
- end
- statements = []
- features = Set.new
- `rapper -i rdfxml -o ntriples #{file.path} 2>/dev/null`.each_line do |line|
- triple = line.chomp.split('> ').collect{|i| i.sub(/\s+.$/,'').gsub(/[<>"]/,'')}[0..2]
- statements << triple
- features << triple[0] if triple[1] == RDF.type and (triple[2] =~ /Feature|Substructure/)
- end
- File.delete(to_delete) if to_delete
- statements.each do |triple|
- if features.include? triple[0]
- @dataset.features[triple[0]] = {} unless @dataset.features[triple[0]]
- @dataset.features[triple[0]][triple[1]] = triple[2].split('^^').first
- end
- end
- @dataset.features
- end
-
- end
-
- end
-
-=begin
- # Parser for getting spreadsheet data into a dataset
- class Spreadsheets
-
- attr_accessor :dataset
-
- def initialize
- @data = []
- @features = []
- @feature_types = {}
-
- @format_errors = ""
- @smiles_errors = []
- @activity_errors = []
- @duplicates = {}
- end
-
- # Load Spreadsheet book (created with roo gem http://roo.rubyforge.org/, excel format specification: http://toxcreate.org/help)
- # @param [Excel] book Excel workbook object (created with roo gem)
- # @return [OpenTox::Dataset] Dataset object with Excel data
- def load_spreadsheet(book)
- book.default_sheet = 0
- add_features book.row(1)
-
- # AM: fix mixed read in
- regression_features=false
- 2.upto(book.last_row) { |i|
- row = book.row(i)
- regression_features = detect_regression_features row
- break if regression_features==true
- }
-
- 2.upto(book.last_row) { |i| add_values book.row(i),regression_features }
- warnings
- @dataset
- end
-
- # Load CSV string (format specification: http://toxcreate.org/help)
- # @param [String] csv CSV representation of the dataset
- # @return [OpenTox::Dataset] Dataset object with CSV data
- def load_csv(csv)
- row = 0
- input = csv.split("\n")
- add_features split_row(input.shift)
-
-
- # AM: fix mixed read in
- regression_features=false
- input.each { |row|
- row = split_row(row)
- regression_features = detect_regression_features row
- break if regression_features==true
- }
- input.each { |row| add_values split_row(row),regression_features }
- warnings
- @dataset
- end
-
-
- private
-
- def warnings
-
- info = ''
- @feature_types.each do |feature,types|
- if types.uniq.size > 1
- type = OT.NumericFeature
- else
- type = types.first
- end
- @dataset.add_feature_metadata(feature,{RDF.type => [type]})
- info += "\"#{@dataset.feature_name(feature)}\" detected as #{type.split('#').last}."
-
- # TODO: rewrite feature values
- # TODO if value.to_f == 0 @activity_errors << "#{smiles} Zero values not allowed for regression datasets - entry ignored."
- end
-
- @dataset.metadata[OT.Info] = info
-
- warnings = ''
- warnings += "<p>Incorrect Smiles structures (ignored):</p>" + @smiles_errors.join("<br/>") unless @smiles_errors.empty?
- warnings += "<p>Irregular activities (ignored):</p>" + @activity_errors.join("<br/>") unless @activity_errors.empty?
- duplicate_warnings = ''
- @duplicates.each {|inchi,lines| duplicate_warnings << "<p>#{lines.join('<br/>')}</p>" if lines.size > 1 }
- 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?
-
- @dataset.metadata[OT.Warnings] = warnings
-
- end
-
- def add_features(row)
- row.shift # get rid of smiles entry
- row.each do |feature_name|
- feature_uri = File.join(@dataset.uri,"feature",URI.encode(feature_name))
- @feature_types[feature_uri] = []
- @features << feature_uri
- @dataset.add_feature(feature_uri,{DC.title => feature_name})
- end
- end
-
- def detect_regression_features row
- row.shift
- regression_features=false
- row.each_index do |i|
- value = row[i]
- type = feature_type(value)
- if type == OT.NumericFeature
- regression_features=true
- end
- end
- regression_features
- end
-
- def add_values(row, regression_features=false)
-
- smiles = row.shift
- compound = Compound.from_smiles(smiles)
- if compound.nil? or compound.inchi.nil? or compound.inchi == ""
- @smiles_errors << smiles+", "+row.join(", ")
- return false
- end
- @duplicates[compound.inchi] = [] unless @duplicates[compound.inchi]
- @duplicates[compound.inchi] << smiles+", "+row.join(", ")
-
- row.each_index do |i|
- value = row[i]
- feature = @features[i]
- type = feature_type(value)
-
- @feature_types[feature] << type
-
- if (regression_features)
- val = value.to_f
- else
- case type
- when OT.NominalFeature
- case value.to_s
- when TRUE_REGEXP
- val = true
- when FALSE_REGEXP
- val = false
- end
- when OT.NumericFeature
- val = value.to_f
- when OT.StringFeature
- val = value.to_s
- @activity_errors << smiles+", "+row.join(", ")
- end
- end
- if val!=nil
- @dataset.add(compound.uri, feature, val)
- if type!=OT.NumericFeature
- @dataset.features[feature][OT.acceptValue] = [] unless @dataset.features[feature][OT.acceptValue]
- @dataset.features[feature][OT.acceptValue] << val.to_s unless @dataset.features[feature][OT.acceptValue].include?(val.to_s)
- end
- end
- end
- end
-
- def numeric?(value)
- true if Float(value) rescue false
- end
-
- def classification?(value)
- !value.to_s.strip.match(TRUE_REGEXP).nil? or !value.to_s.strip.match(FALSE_REGEXP).nil?
- end
-
- def feature_type(value)
- if classification? value
- return OT.NominalFeature
- elsif numeric? value
- return OT.NumericFeature
- else
- return OT.StringFeature
- end
- end
-
- def split_row(row)
- row.chomp.gsub(/["']/,'').split(/\s*[,;]\s*/) # remove quotes
- end
-
- end
-=end
- end
-end
diff --git a/lib/rest_client_wrapper.rb b/lib/rest_client_wrapper.rb
deleted file mode 100644
index 30f04cc..0000000
--- a/lib/rest_client_wrapper.rb
+++ /dev/null
@@ -1,182 +0,0 @@
-require 'rest-client'
-module OpenTox
-
- class WrapperResult < String
- attr_accessor :content_type, :code
- end
-
- class RestClientWrapper
-
- # performs a GET REST call
- # raises OpenTox::Error if call fails (rescued in overwrite.rb -> halt 502)
- # per default: waits for Task to finish and returns result URI of Task
- # @param [String] uri destination URI
- # @param [optional,Hash] headers contains params like accept-header
- # @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @param [wait,Boolean] wait set to false to NOT wait for task if result is task
- # @return [OpenTox::WrapperResult] a String containing the result-body of the REST call
- def self.get(uri, headers={}, waiting_task=nil, wait=true )
- execute( "get", uri, nil, headers, waiting_task, wait)
- end
-
- # performs a POST REST call
- # raises OpenTox::Error if call fails (rescued in overwrite.rb -> halt 502)
- # per default: waits for Task to finish and returns result URI of Task
- # @param [String] uri destination URI
- # @param [optional,String] payload data posted to the service
- # @param [optional,Hash] headers contains params like accept-header
- # @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @param [wait,Boolean] wait set to false to NOT wait for task if result is task
- # @return [OpenTox::WrapperResult] a String containing the result-body of the REST call
- def self.post(uri, payload=nil, headers={}, waiting_task=nil, wait=true )
- execute( "post", uri, payload, headers, waiting_task, wait )
- end
-
- # performs a PUT REST call
- # raises OpenTox::Error if call fails (rescued in overwrite.rb -> halt 502)
- # @param [String] uri destination URI
- # @param [optional,Hash] headers contains params like accept-header
- # @param [optional,String] payload data put to the service
- # @return [OpenTox::WrapperResult] a String containing the result-body of the REST call
- def self.put(uri, payload=nil, headers={} )
- execute( "put", uri, payload, headers )
- end
-
- # performs a DELETE REST call
- # raises OpenTox::Error if call fails (rescued in overwrite.rb -> halt 502)
- # @param [String] uri destination URI
- # @param [optional,Hash] headers contains params like accept-header
- # @return [OpenTox::WrapperResult] a String containing the result-body of the REST call
- def self.delete(uri, headers=nil )
- execute( "delete", uri, nil, headers)
- end
-
- private
- def self.execute( rest_call, uri, payload=nil, headers={}, waiting_task=nil, wait=true )
-
- raise OpenTox::BadRequestError.new "uri is nil" unless uri
- raise OpenTox::BadRequestError.new "not a uri: "+uri.to_s unless uri.to_s.uri?
- raise "headers are no hash: "+headers.inspect unless headers==nil or headers.is_a?(Hash)
- raise OpenTox::BadRequestError.new "accept should go into the headers" if payload and payload.is_a?(Hash) and payload[:accept]
- raise OpenTox::BadRequestError.new "content_type should go into the headers" if payload and payload.is_a?(Hash) and payload[:content_type]
- raise "__waiting_task__ must be 'nil' or '(sub)task', is "+waiting_task.class.to_s if
- waiting_task!=nil and !(waiting_task.is_a?(Task) || waiting_task.is_a?(SubTask))
- headers.each{ |k,v| headers.delete(k) if v==nil } if headers #remove keys with empty values, as this can cause problems
- ## PENDING partner services accept subjectid only in header
- headers = {} unless headers
- headers[:subjectid] = payload.delete(:subjectid) if payload and payload.is_a?(Hash) and payload.has_key?(:subjectid)
-
- # PENDING needed for NUTA, until we finally agree on how to send subjectid
- headers[:subjectid] = payload.delete(:subjectid) if uri=~/ntua/ and payload and payload.is_a?(Hash) and payload.has_key?(:subjectid)
-
- begin
- #LOGGER.debug "RestCall: "+rest_call.to_s+" "+uri.to_s+" "+headers.inspect+" "+payload.inspect
- resource = RestClient::Resource.new(uri,{:timeout => 60})
- if rest_call=="post" || rest_call=="put"
- result = resource.send(rest_call, payload, headers)
- else
- result = resource.send(rest_call, headers)
- end
- #LOGGER.debug "result body size: #{result.body.size}"
-
- # PENDING NTUA does return errors with 200
- raise RestClient::ExceptionWithResponse.new(result) if uri=~/ntua/ and result.body =~ /about.*http:\/\/anonymous.org\/error/
-
- # result is a string, with the additional fields content_type and code
- res = WrapperResult.new(result.body)
- res.content_type = result.headers[:content_type]
- raise "content-type not set" unless res.content_type
- res.code = result.code
-
- # TODO: Ambit returns task representation with 200 instead of result URI
- return res if res.code==200 || !wait
-
- while (res.code==201 || res.code==202)
- res = wait_for_task(res, uri, waiting_task)
- end
- raise "illegal status code: '"+res.code.to_s+"'" unless res.code==200
- return res
-
- rescue RestClient::RequestTimeout => ex
- received_error ex.message, 408, nil, {:rest_uri => uri, :headers => headers, :payload => payload}
- rescue Errno::ETIMEDOUT => ex
- received_error ex.message, 408, nil, {:rest_uri => uri, :headers => headers, :payload => payload}
- rescue Errno::ECONNREFUSED => ex
- received_error ex.message, 500, nil, {:rest_uri => uri, :headers => headers, :payload => payload}
- rescue RestClient::ExceptionWithResponse => ex
- # error comming from a different webservice,
- received_error ex.http_body, ex.http_code, ex.response.net_http_res.content_type, {:rest_uri => uri, :headers => headers, :payload => payload}
- rescue OpenTox::RestCallError => ex
- # already a rest-error, probably comes from wait_for_task, just pass through
- raise ex
- rescue => ex
- # some internal error occuring in rest_client_wrapper, just pass through
- raise ex
- end
- end
-
- def self.wait_for_task( res, base_uri, waiting_task=nil )
- #TODO remove TUM hack
- res.content_type = "text/uri-list" if base_uri =~/tu-muenchen/ and res.content_type == "application/x-www-form-urlencoded;charset=UTF-8"
-
- task = nil
- case res.content_type
- when /application\/rdf\+xml/
- task = OpenTox::Task.from_rdfxml(res)
- when /yaml/
- task = OpenTox::Task.from_yaml(res)
- when /text\//
- raise "uri list has more than one entry, should be a task" if res.content_type=~/text\/uri-list/ and res.split("\n").size > 1 #if uri list contains more then one uri, its not a task
- task = OpenTox::Task.find(res.to_s.chomp) if res.to_s.uri?
- else
- raise "unknown content-type for task : '"+res.content_type.to_s+"'"+" base-uri: "+base_uri.to_s+" content: "+res[0..200].to_s
- end
-
- #LOGGER.debug "result is a task '"+task.uri.to_s+"', wait for completion"
- task.wait_for_completion waiting_task
- unless task.completed? # maybe task was cancelled / error
- if task.errorReport
- received_error task.errorReport, task.http_code, nil, {:rest_uri => task.uri, :rest_code => task.http_code}
- else
- raise "task status: '"+task.status.to_s+"' but errorReport nil"
- end
- end
-
- res = WrapperResult.new task.result_uri
- res.code = task.http_code
- res.content_type = "text/uri-list"
- return res
- end
-
- def self.received_error( body, code, content_type=nil, params=nil )
-
- # try to parse body
- report = nil
- if body.is_a?(OpenTox::ErrorReport)
- report = body
- else
- case content_type
- when /yaml/
- report = YAML.load(body)
- when /rdf/
- report = OpenTox::ErrorReport.from_rdf(body)
- end
- end
-
- unless report
- # parsing was not successfull
- # raise 'plain' RestCallError
- err = OpenTox::RestCallError.new("REST call returned error: '"+body.to_s+"'")
- err.rest_params = params
- raise err
- else
- # parsing sucessfull
- # raise RestCallError with parsed report as error cause
- err = OpenTox::RestCallError.new("REST call subsequent error")
- err.errorCause = report
- err.rest_params = params
- raise err
- end
- end
- end
-end
diff --git a/lib/serializer.rb b/lib/serializer.rb
deleted file mode 100644
index 5a9fd0a..0000000
--- a/lib/serializer.rb
+++ /dev/null
@@ -1,491 +0,0 @@
-require 'spreadsheet'
-require 'yajl'
-
-module OpenTox
-
- # Serialzer for various oputput formats
- module Serializer
-
- # OWL-DL Serializer, modelled according to to http://n2.talis.com/wiki/RDF_JSON_Specification
- class Owl
-
- attr_accessor :object
-
- def initialize
-
- @object = {
- # this should come from opentox.owl
- OT.Compound => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.Feature => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.Model => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.NominalFeature => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.NumericFeature => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.StringFeature => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.Dataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.DataEntry => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.FeatureValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.Algorithm => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.Parameter => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.Task => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OTA.PatternMiningSupervised => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OTA.ClassificationLazySingleTarget => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OTA.RegressionLazySingleTarget => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
-
- #classes for validation
- OT.Validation => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.ClassificationStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.ConfusionMatrix => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.ConfusionMatrixCell => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.ClassValueStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.RegressionStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.Crossvalidation => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.CrossvalidationInfo => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
- OT.ErrorReport => { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } ,
-
- OT.compound => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.feature => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.dataEntry => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.values => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.algorithm => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.parameters => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.featureDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.dependentVariables => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.predictedVariables => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.paramValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
-
- #object props for validation#
- OT.model => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.trainingDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.predictionFeature => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.predictionDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.crossvalidation => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.testTargetDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.testDataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.classificationStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.confusionMatrix => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.confusionMatrixCell => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.classValueStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.regressionStatistics => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.validation => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.crossvalidationInfo => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
- OT.dataset => { RDF["type"] => [{ "type" => "uri", "value" => OWL.ObjectProperty }] } ,
-
- DC.title => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- DC.identifier => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- DC.contributor => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- DC.creator => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- DC.description => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- DC.date => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- #OT.isA => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.Warnings => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- XSD.anyURI => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.hasStatus => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.resultURI => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.percentageCompleted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.acceptValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
-
- # annotation props for validation
- OT.numUnpredicted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.crossvalidationFold => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.numInstances => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.numWithoutClass => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.percentWithoutClass => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.percentUnpredicted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.confusionMatrixActual => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.confusionMatrixPredicted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.confusionMatrixValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.numIncorrect => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.percentCorrect => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.numCorrect => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.accuracy => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.trueNegativeRate => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.truePositiveRate => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.falseNegativeRate => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.falsePositiveRate => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.numTrueNegatives => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.numTruePositives => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.numFalseNegatives => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.numFalsePositives => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.classValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.precision => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.areaUnderRoc => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.weightedAreaUnderRoc => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.weightedAccuracy => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.fMeasure => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.percentIncorrect => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.validationType => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.realRuntime => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.sampleCorrelationCoefficient => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.targetVarianceActual => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.targetVariancePredicted => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.meanAbsoluteError => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.sumSquaredError => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.rootMeanSquaredError => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.rSquare => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.stratified => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.numFolds => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.randomSeed => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.reportType => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.message => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.statusCode => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.actor => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
- OT.errorCode => { RDF["type"] => [{ "type" => "uri", "value" => OWL.AnnotationProperty }] } ,
-
- OT.hasSource => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } ,
- OT.value => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } ,
- OT.paramScope => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } ,
- #OT.paramValue => { RDF["type"] => [{ "type" => "uri", "value" => OWL.DatatypeProperty }] } ,
- }
-
- @data_entries = {}
- @values_id = 0
- @parameter_id = 0
-
- @classes = Set.new
- @object_properties = Set.new
- @annotation_properties = Set.new
- @datatype_properties = Set.new
-
- @objects = Set.new
- end
-
- # Add a compound
- # @param [String] uri Compound URI
- def add_compound(uri)
- @object[uri] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Compound }] }
- end
-
- # Add a feature
- # @param [String] uri Feature URI
- def add_feature(uri,metadata)
- @object[uri] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Feature }] }
- add_metadata uri, metadata
- end
-
- # Add a dataset
- # @param [String] uri Dataset URI
- def add_dataset(dataset)
- @dataset = dataset.uri
- @object[dataset.uri] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Dataset }] }
- add_metadata dataset.uri, dataset.metadata
- dataset.compounds.each { |compound| add_compound compound }
- dataset.features.each { |feature,metadata| add_feature feature,metadata }
- dataset.data_entries.each do |compound,entry|
- entry.each do |feature,values|
- values.each { |value| add_data_entry compound,feature,value }
- end
- end
- end
-
- # Add a algorithm
- # @param [String] uri Algorithm URI
- def add_algorithm(uri,metadata)
- @object[uri] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Algorithm }] }
- add_metadata uri, metadata
- end
-
- # Add a model
- # @param [String] uri Model URI
- def add_model(uri,metadata)
- @object[uri] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Model }] }
- add_metadata uri, metadata
- @object[metadata[OT.featureDataset]] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Dataset }] }
- @object[metadata[OT.trainingDataset]] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Dataset }] }
- @object[metadata[OT.dependentVariables]] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Feature }] }
- metadata[OT.predictedVariables].each{|feature| @object[feature] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Feature }] }}
- # TODO: add algorithms from parameters
- @object["http://ot-dev.in-silico.ch/algorithm/fminer/bbrc"] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Algorithm }] }
- @object["http://ot-dev.in-silico.ch/algorithm/fminer/last"] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Algorithm }] }
- @object["http://ot-dev.in-silico.ch/algorithm/lazar"] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Algorithm }] }
- end
-
- # Add a task
- # @param [String] uri Model URI
- def add_task(uri,metadata)
- @object[uri] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Task }] }
- add_metadata uri, metadata
- end
-
- # Add a resource defined by resource_class and content
- # (see documentation of add_content for example)
- # @param [String] uri of resource
- # @param [String] resource class, e.g. OT.Validation
- # @param [Hash] content as hash
- def add_resource(uri, resource_class, content)
- @object[uri] = { RDF["type"] => [{ "type" => "uri", "value" => resource_class }] }
- @@content_id = 1
- add_content uri, content
- end
-
- private
- @@content_id = 1
-
- # Recursiv function to add content
- # @example
- # { DC.description => "bla",
- # OT.similar_resources => [ "http://uri1", "http://uri2" ],
- # OT.matrixCells =>
- # [ { RDF.type => OT.MatrixCell, OT.cellIndex=1 OT.cellValue => "xy" },
- # { RDF.type => OT.MatrixCell, OT.cellIndex=2 OT.cellValue => "z" } ],
- # OT.info => { RDF.type => OT.ImportantInfo,
- # DC.description => "blub" }
- # }
- # @param [String] uri
- # @param [Hash] content as hash, uri must already have been added to @object
- def add_content(uri, hash)
- raise "content is no hash: "+hash.class.to_s unless hash.is_a?(Hash)
- hash.each do |u,v|
- if v.is_a? Hash
- # value is again a hash, i.e. a new owl class is added
- # first make sure type (==class) is set
- type = v[RDF.type]
- raise "type missing for "+u.to_s+" content:\n"+v.inspect unless type
- raise "class unknown "+type.to_s+" (for "+u.to_s+")" unless @object.has_key?(type)
- # create new node and add to current uri
- genid = "_:#{type.split('#')[-1]}#{@@content_id}"
- @@content_id += 1
- @object[uri] = {} unless @object[uri]
- @object[uri][u] = [{ "type" => "bnode", "value" => genid }]
- # add content to new class
- add_content(genid,v)
- elsif v.is_a? Array
- # value is an array, i.e. a list of values with property is added
- v.each{ |vv| add_content( uri, { u => vv } ) }
- else # v.is_a? String
- # simple string value
- @object[uri] = {} unless @object[uri]
- @object[uri][u] = [] unless @object[uri][u]
- raise "property unknown "+u.to_s if !@object.has_key?(u) and u!=RDF.type
- # use << to allow different values for one property
- @object[uri][u] << {"type" => type(v), "value" => v }
- end
- end
- end
-
- public
-
- # Add metadata
- # @param [Hash] metadata
- def add_metadata(uri,metadata)
- id = 0
- metadata.each do |u,v|
- #if v.is_a? Array and (u == OT.parameters or u == RDF.type)
- if v.is_a? Array and u == OT.parameters#or u == RDF.type)
- @object[uri][u] = [] unless @object[uri][u]
- v.each do |value|
- id+=1
- genid = "_:genid#{id}"
- @object[uri][u] << {"type" => "bnode", "value" => genid}
- @object[genid] = { RDF["type"] => [{ "type" => "uri", "value" => OT.Parameter}] }
- value.each do |name,entry|
- @object[genid][name] = [{"type" => type(entry), "value" => entry }]
- end
- end
- elsif v.is_a? Array #and u == RDF.type
- @object[uri] = {} unless @object[uri]
- v.each do |value|
- @object[uri][u] = [] unless @object[uri][u]
- @object[uri][u] << {"type" => type(value), "value" => value }
- end
- elsif v.is_a? String
- @object[uri] = {} unless @object[uri]
- @object[uri][u] = [{"type" => type(v), "value" => v }]
- end
- end
- end
-
- # Add a data entry
- # @param [String] compound Compound URI
- # @param [String] feature Feature URI
- # @param [Boolead,Float] value Feature value
- def add_data_entry(compound,feature,value)
- add_compound(compound) unless @object[compound]
- add_feature(feature,{}) unless @object[feature]
- unless data_entry = @data_entries[compound]
- data_entry = "_:dataentry#{@data_entries.size}"
- @data_entries[compound] = data_entry
- @object[@dataset][OT.dataEntry] = [] unless @object[@dataset][OT.dataEntry]
- @object[@dataset][OT.dataEntry] << {"type" => "bnode", "value" => data_entry}
- @object[data_entry] = {
- RDF["type"] => [{ "type" => "uri", "value" => OT.DataEntry }],
- OT.compound => [{ "type" => "uri", "value" => compound }],
- OT.values => [],
- }
- end
- values = "_:values#{@values_id}"
- @values_id += 1
- @object[data_entry][OT.values] << {"type" => "bnode", "value" => values}
- case type(value)
- when "uri"
- v = [{ "type" => "uri", "value" => value}]
- when "literal"
- v = [{ "type" => "literal", "value" => value, "datatype" => datatype(value) }]
- else
- raise "Illegal type #{type(value)} for #{value}."
- end
- @object[values] = {
- RDF["type"] => [{ "type" => "uri", "value" => OT.FeatureValue }],
- OT.feature => [{ "type" => "uri", "value" => feature }],
- OT.value => v
- }
- @object[feature][RDF["type"]] << { "type" => "uri", "value" => featuretype(value) }
- #@object[feature][RDF["type"]] = { "type" => "uri", "value" => featuretype(value) }
- end
-
- # Serializers
-
- # Convert to N-Triples
- # @return [text/plain] Object OWL-DL in N-Triples format
- def to_ntriples
-
- @triples = Set.new
- @object.each do |s,entry|
- s = url(s) if type(s) == "uri"
- entry.each do |p,objects|
- p = url(p)
- objects.each do |o|
- case o["type"]
- when "uri"
- o = url(o["value"])
- when "literal"
- o = literal(o["value"],datatype(o["value"]))
- when "bnode"
- o = o["value"]
- end
- @triples << [s,p,o]
- end
- end
- end
- @triples.sort.collect{ |s| s.join(' ').concat(" .") }.join("\n")+"\n"
- end
-
- # Convert to RDF/XML
- # @return [text/plain] Object OWL-DL in RDF/XML format
- def to_rdfxml
- Tempfile.open("owl-serializer"){|f| f.write(self.to_ntriples); @path = f.path}
- # TODO: add base uri for ist services
- `rapper -i ntriples -f 'xmlns:ot="#{OT.uri}"' -f 'xmlns:ota="#{OTA.uri}"' -f 'xmlns:dc="#{DC.uri}"' -f 'xmlns:rdf="#{RDF.uri}"' -f 'xmlns:owl="#{OWL.uri}"' -o rdfxml #{@path} 2>/dev/null`
- end
-
- # Convert to JSON as specified in http://n2.talis.com/wiki/RDF_JSON_Specification
- # (Ambit services use a different JSON representation)
- # @return [text/plain] Object OWL-DL in JSON format
- def to_json
- #rdf_types
- Yajl::Encoder.encode(@object)
- end
-
- # Helpers for type detection
- private
-
- def datatype(value)
- if value.is_a? TrueClass or value.is_a? FalseClass
- XSD.boolean
- elsif value.is_a? Float
- XSD.float
- else
- XSD.string
- end
- end
-
- def featuretype(value)
- if value.is_a? TrueClass or value.is_a? FalseClass
- datatype = OT.NominalFeature
- elsif value.is_a? Float
- datatype = OT.NumericFeature
- else
- datatype = OT.StringFeature
- end
- end
-
- def type(value)
- begin
- uri = URI.parse(value)
- if uri.class == URI::HTTP or uri.class == URI::HTTPS
- "uri"
- elsif value.match(/^_/)
- "bnode"
- else
- "literal"
- end
- rescue
- "literal"
- end
- end
-
- def literal(value,type)
- # concat and << are faster string concatination operators than +
- '"'.concat(value.to_s).concat('"^^<').concat(type).concat('>')
- end
-
- def url(uri)
- # concat and << are faster string concatination operators than +
- '<'.concat(uri).concat('>')
- end
-
- def rdf_types
- @classes.each { |c| @object[c] = { RDF["type"] => [{ "type" => "uri", "value" => OWL['Class'] }] } }
- @object_properties.each { |p| @object[p] = { RDF["type"] => [{ "type" => "uri", "value" => OWL['ObjectProperty'] }] } }
- @annotation_properties.each { |a| @object[a] = { RDF["type"] => [{ "type" => "uri", "value" => OWL['AnnotationProperty'] }] } }
- @datatype_properties.each { |d| @object[d] = { RDF["type"] => [{ "type" => "uri", "value" => OWL['DatatypeProperty'] }] } }
- end
-
- end
-
- # Serializer for spreadsheet formats
- class Spreadsheets # to avoid nameclash with Spreadsheet gem
-
- # Create a new spreadsheet serializer
- # @param [OpenTox::Dataset] dataset Dataset object
- def initialize(dataset)
- @rows = []
- @rows << ["SMILES"]
- features = dataset.features.keys
- @rows.first << features
- @rows.first.flatten!
- dataset.data_entries.each do |compound,entries|
- smiles = Compound.new(compound).to_smiles
- row = Array.new(@rows.first.size)
- row[0] = smiles
- entries.each do |feature, values|
- i = features.index(feature)+1
- values.each do |value|
- if row[i]
- row[i] = "#{row[i]} #{value}" # multiple values
- else
- row[i] = value
- end
- end
- end
- @rows << row
- end
- end
-
- # Convert to CSV string
- # @return [String] CSV string
- def to_csv
- @rows.collect{|r| r.join(", ")}.join("\n")
- end
-
- # Convert to spreadsheet workbook
- # @return [Spreadsheet::Workbook] Workbook object (use the spreadsheet gemc to write a file)
- def to_spreadsheet
- Spreadsheet.client_encoding = 'UTF-8'
- book = Spreadsheet::Workbook.new
- sheet = book.create_worksheet(:name => '')
- sheet.column(0).width = 100
- i = 0
- @rows.each do |row|
- row.each do |c|
- sheet.row(i).push c
- end
- i+=1
- end
- book
- end
-
- end
-
-
- end
-end
diff --git a/lib/spork.rb b/lib/spork.rb
deleted file mode 100644
index c77b5b5..0000000
--- a/lib/spork.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# A way to cleanly handle process forking in Sinatra when using Passenger, aka "sporking some code".
-# This will allow you to properly execute some code asynchronously, which otherwise does not work correctly.
-#
-# Written by Ron Evans
-# More info at http://deadprogrammersociety.com
-#
-# Mostly lifted from the Spawn plugin for Rails (http://github.com/tra/spawn)
-# but with all of the Rails stuff removed.... cause you are using Sinatra. If you are using Rails, Spawn is
-# what you need. If you are using something else besides Sinatra that is Rack-based under Passenger, and you are having trouble with
-# asynch processing, let me know if spork helped you.
-#
-module Spork
- # things to close in child process
- @@resources = []
- def self.resources
- @@resources
- end
-
- # set the resource to disconnect from in the child process (when forking)
- def self.resource_to_close(resource)
- @@resources << resource
- end
-
- # close all the resources added by calls to resource_to_close
- def self.close_resources
- @@resources.each do |resource|
- resource.close if resource && resource.respond_to?(:close) && !resource.closed?
- end
- @@resources = []
- end
-
- # actually perform the fork... er, spork
- # valid options are:
- # :priority => to set the process priority of the child
- # :logger => a logger object to use from the child
- # :no_detach => true if you want to keep the child process under the parent control. usually you do NOT want this
- def self.spork(options={})
- logger = options[:logger]
- logger.debug "spork> parent PID = #{Process.pid}" if logger
-
- child = fork do
- begin
- start = Time.now
- logger.debug "spork> child PID = #{Process.pid}" if logger
-
- # set the nice priority if needed
- Process.setpriority(Process::PRIO_PROCESS, 0, options[:priority]) if options[:priority]
-
- # disconnect from the rack
- Spork.close_resources
-
- # run the block of code that takes so long
- yield
-
- rescue => ex
- #raise ex
- logger.error "spork> Exception in child[#{Process.pid}] - #{ex.class}: #{ex.message}" if logger
- ensure
- logger.info "spork> child[#{Process.pid}] took #{Time.now - start} sec" if logger
- # this form of exit doesn't call at_exit handlers
- exit!(0)
- end
- end
-
- # detach from child process (parent may still wait for detached process if they wish)
- Process.detach(child) unless options[:no_detach]
-
- return child
- end
-
-end
-
-# Patch to work with passenger
-if defined? Passenger::Rack::RequestHandler
- class Passenger::Rack::RequestHandler
- alias_method :orig_process_request, :process_request
- def process_request(env, input, output)
- Spork.resource_to_close(input)
- Spork.resource_to_close(output)
- orig_process_request(env, input, output)
- end
- end
-end
diff --git a/lib/task.rb b/lib/task.rb
index 3815177..0adb7a0 100644
--- a/lib/task.rb
+++ b/lib/task.rb
@@ -1,401 +1,72 @@
-
+DEFAULT_TASK_MAX_DURATION = 36000
module OpenTox
# Class for handling asynchronous tasks
class Task
- include OpenTox
- attr_accessor :http_code, :due_to_time
-
- def initialize(uri=nil)
- super uri
- @http_code = 202
- @metadata = {
- DC.title => "",
- DC.date => "",
- OT.hasStatus => "Running",
- OT.percentageCompleted => 0.0,
- OT.resultURI => "",
- DC.creator => "", # not mandatory according to API
- DC.description => "", # not mandatory according to API
- }
- end
-
- # Create a new task for the code in the block. Catches halts and exceptions and sets task state to error if necessary. The block has to return the URI of the created resource.
- # @example
- # task = OpenTox::Task.create do
- # # this code will be executed as a task
- # model = OpenTox::Algorithm.run(params) # this can be time consuming
- # model.uri # Important: return URI of the created resource
- # end
- # task.status # returns "Running", because tasks are forked
- # @param [String] title Task title
- # @param [String] creator Task creator
- # @return [OPenTox::Task] Task
- def self.create( title=nil, creator=nil, max_duration=DEFAULT_TASK_MAX_DURATION, description=nil )
-
- params = {:title=>title, :creator=>creator, :max_duration=>max_duration, :description=>description }
- task_uri = RestClientWrapper.post(CONFIG[:services]["opentox-task"], params, {}, nil, false).to_s
- task = Task.new(task_uri.chomp)
-
- # measure current memory consumption
-=begin
- memory = `free -m|sed -n '2p'`.split
- free_memory = memory[3].to_i + memory[6].to_i # include cache
- if free_memory < 20 # require at least 200 M free memory
- LOGGER.warn "Cannot start task - not enough memory left (#{free_memory} M free)"
- task.cancel
- return task
- #raise "Insufficient memory to start a new task"
- end
-
- cpu_load = `cat /proc/loadavg`.split(/\s+/)[0..2].collect{|c| c.to_f}
- nr_cpu_cores = `cat /proc/cpuinfo |grep "cpu cores"|cut -d ":" -f2|tr -d " "`.split("\n").collect{|c| c.to_i}.inject{|sum,n| sum+n}
- nr_cpu_cores = 1 if !nr_cpu_cores
- #if cpu_load[0] > nr_cpu_cores and cpu_load[0] > cpu_load[1] and cpu_load[1] > cpu_load[2] # average CPU load of the last minute is high and CPU load is increasing
- # LOGGER.warn "Cannot start task - CPU load too high (#{cpu_load.join(", ")})"
- # task.cancel
- # return task
- # #raise "Server too busy to start a new task"
- #end
-=end
- task_pid = Spork.spork(:logger => LOGGER) do
- LOGGER.debug "Task #{task.uri} started #{Time.now}"
- begin
- result = yield task
- LOGGER.debug "Task #{task.uri} done #{Time.now} -> "+result.to_s
- task.completed(result)
- rescue => error
- LOGGER.error "task failed: "+error.class.to_s+": "+error.message
- LOGGER.error ":\n"+error.backtrace.join("\n")
- task.error(OpenTox::ErrorReport.create(error, creator))
- end
- end
- task.pid = task_pid
- LOGGER.debug "Started task: "+task.uri.to_s
- task
- end
-
- # Find a task for querying, status changes
- # @param [String] uri Task URI
- # @return [OpenTox::Task] Task object
- def self.find(uri)
- return nil unless uri
- task = Task.new(uri)
- task.load_metadata
- raise "could not load task metadata" if task.metadata==nil or task.metadata.size==0
- task
- end
- # Find a task for querying, status changes
- # @param [String] uri Task URI
- # @return [OpenTox::Task] Task object
- def self.exist?(uri)
- begin
- return find(uri)
- rescue
- end
+ def self.create service_uri
+ Task.new RestClient.post(service_uri,{}).chomp
+ #eval("#{self}.new(\"#{uri}\", #{subjectid})")
end
- # Get a list of all tasks
- # @param [optional, String] uri URI of task service
- # @return [text/uri-list] Task URIs
- def self.all(uri=CONFIG[:services]["opentox-task"])
- OpenTox.all uri
- end
-
- def self.from_yaml(yaml)
- @metadata = YAML.load(yaml)
- end
-
- def self.from_rdfxml(rdfxml)
- owl = OpenTox::Parser::Owl.from_rdf(rdfxml, OT.Task)
- task = Task.new(owl.uri)
- task.add_metadata(owl.metadata)
- task
- end
-
- def to_rdfxml
- s = Serializer::Owl.new
- @metadata[OT.errorReport] = @uri+"/ErrorReport/tmpId" if @error_report
- s.add_task(@uri,@metadata)
- s.add_resource(@uri+"/ErrorReport/tmpId", OT.errorReport, @error_report.rdf_content) if @error_report
- s.to_rdfxml
+ def http_code
+ get(@uri).code
end
def status
- @metadata[OT.hasStatus]
+ metadata[RDF::OT.hasStatus].to_s
end
def result_uri
- @metadata[OT.resultURI]
+ metadata[RDF::OT.resultURI]
end
def description
- @metadata[DC.description]
+ metadata[RDF::DC.description]
end
def errorReport
- @metadata[OT.errorReport]
+ metadata[RDF::OT.errorReport]
end
def cancel
- RestClientWrapper.put(File.join(@uri,'Cancelled'),{:cannot_be => "empty"})
- load_metadata
+ RestClient.put(File.join(@uri,'Cancelled'),{:cannot_be => "empty"})
end
def completed(uri)
- RestClientWrapper.put(File.join(@uri,'Completed'),{:resultURI => uri})
- load_metadata
+ RestClient.put(File.join(@uri,'Completed'),{:resultURI => uri})
end
def error(error_report)
raise "no error report" unless error_report.is_a?(OpenTox::ErrorReport)
- RestClientWrapper.put(File.join(@uri,'Error'),{:errorReport => error_report.to_yaml})
- load_metadata
- end
-
- # not stored just for to_rdf
- def add_error_report( error_report )
- raise "not an error report: "+error_report.class.to_s unless error_report.is_a?(ErrorReport)
- @error_report = error_report
+ RestClient.put(File.join(@uri,'Error'),{:errorReport => error_report.to_yaml})
end
def pid=(pid)
- RestClientWrapper.put(File.join(@uri,'pid'), {:pid => pid})
+ RestClient.put(File.join(@uri,'pid'), {:pid => pid})
end
def running?
- @metadata[OT.hasStatus] == 'Running'
+ metadata[RDF::OT.hasStatus] == 'Running'
end
def completed?
- @metadata[OT.hasStatus] == 'Completed'
+ metadata[RDF::OT.hasStatus] == 'Completed'
end
def error?
- @metadata[OT.hasStatus] == 'Error'
+ metadata[RDF::OT.hasStatus] == 'Error'
end
- def load_metadata
- if (CONFIG[:yaml_hosts].include?(URI.parse(@uri).host))
- result = RestClientWrapper.get(@uri, {:accept => 'application/x-yaml'}, nil, false)
- @metadata = YAML.load result.to_s
- @http_code = result.code
- else
- @metadata = Parser::Owl::Generic.new(@uri).load_metadata
- @http_code = RestClientWrapper.get(uri, {:accept => 'application/rdf+xml'}, nil, false).code
- end
- raise "could not load task metadata for task "+@uri.to_s if @metadata==nil || @metadata.size==0
- end
-
- # create is private now, use OpenTox::Task.as_task
- #def self.create( params )
- #task_uri = RestClientWrapper.post(CONFIG[:services]["opentox-task"], params, {}, false).to_s
- #Task.find(task_uri.chomp)
- #end
-
-=begin
- def self.from_data(data, content_type, code, base_uri)
- task = Task.new(nil)
- task.http_code = code
- task.reload_from_data(data, content_type, base_uri)
- return task
- end
-
- def reload( accept_header=nil )
- unless accept_header
- if (CONFIG[:yaml_hosts].include?(URI.parse(uri).host))
- accept_header = "application/x-yaml"
- else
- accept_header = 'application/rdf+xml'
- end
- end
- result = RestClientWrapper.get(uri, {:accept => accept_header}, false)#'application/x-yaml'})
- @http_code = result.code
- reload_from_data(result, result.content_type, uri)
- end
-
- def reload_from_data( data, content_type, base_uri )
- case content_type
- when /yaml/
- task = YAML.load data
- TASK_ATTRIBS.each do |a|
- raise "task yaml data invalid, key missing: "+a.to_s unless task.has_key?(a)
- send("#{a.to_s}=".to_sym,task[a])
- end
- when /application\/rdf\+xml/
- owl = OpenTox::Owl.from_data(data,base_uri,"Task")
- self.uri = owl.uri
- (TASK_ATTRIBS-[:uri]).each{|a| self.send("#{a.to_s}=".to_sym, owl.get(a.to_s))}
- else
- raise "content type for tasks not supported: "+content_type.to_s
- end
- raise "uri is nil after loading" unless @uri and @uri.to_s.strip.size>0
- end
-=end
-
# waits for a task, unless time exceeds or state is no longer running
- # @param [optional,OpenTox::Task] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
# @param [optional,Numeric] dur seconds pausing before cheking again for completion
- def wait_for_completion( waiting_task=nil, dur=0.3)
-
- waiting_task.waiting_for(self.uri) if waiting_task
+ def wait_for_completion(dur=0.3)
due_to_time = Time.new + DEFAULT_TASK_MAX_DURATION
- LOGGER.debug "start waiting for task "+@uri.to_s+" at: "+Time.new.to_s+", waiting at least until "+due_to_time.to_s
-
- load_metadata # for extremely fast tasks
- check_state
while self.running?
- sleep dur
- load_metadata
- # if another (sub)task is waiting for self, set progress accordingly
- waiting_task.progress(@metadata[OT.percentageCompleted].to_f) if waiting_task
- check_state
- if (Time.new > due_to_time)
- raise "max wait time exceeded ("+DEFAULT_TASK_MAX_DURATION.to_s+"sec), task: '"+@uri.to_s+"'"
- end
- end
- waiting_task.waiting_for(nil) if waiting_task
- LOGGER.debug "Task '"+@metadata[OT.hasStatus].to_s+"': "+@uri.to_s+", Result: "+@metadata[OT.resultURI].to_s
- end
-
- # updates percentageCompleted value (can only be increased)
- # task has to be running
- # @param [Numeric] pct value between 0 and 100
- def progress(pct)
- #puts "task := "+pct.to_s
- raise "no numeric >= 0 and <= 100 : '"+pct.to_s+"'" unless pct.is_a?(Numeric) and pct>=0 and pct<=100
- if (pct > @metadata[OT.percentageCompleted] + 0.0001)
- RestClientWrapper.put(File.join(@uri,'Running'),{:percentageCompleted => pct})
- load_metadata
- end
- end
-
- def waiting_for(task_uri)
- RestClientWrapper.put(File.join(@uri,'Running'),{:waiting_for => task_uri})
- end
-
- private
- VALID_TASK_STATES = ["Cancelled", "Completed", "Running", "Error"]
-
- def check_state
- begin
- raise "illegal task state, invalid status: '"+@metadata[OT.hasStatus].to_s+"'" unless
- @metadata[OT.hasStatus] unless VALID_TASK_STATES.include?(@metadata[OT.hasStatus])
- raise "illegal task state, task is completed, resultURI is no URI: '"+@metadata[OT.resultURI].to_s+
- "'" unless @metadata[OT.resultURI] and @metadata[OT.resultURI].to_s.uri? if completed?
- if @http_code == 202
- raise "#{@uri}: illegal task state, code is 202, but hasStatus is not Running: '"+@metadata[OT.hasStatus]+"'" unless running?
- elsif @http_code == 201
- # ignore hasStatus
- # raise "#{@uri}: illegal task state, code is 201, but hasStatus is not Completed: '"+@metadata[OT.hasStatus]+"'" unless completed?
- raise "#{@uri}: illegal task state, code is 201, resultURI is no task-URI: '"+@metadata[OT.resultURI].to_s+
- "'" unless @metadata[OT.resultURI] and @metadata[OT.resultURI].to_s.uri?
- end
- rescue => ex
- raise OpenTox::BadRequestError.new ex.message+" (task-uri:"+@uri+")"
+ raise "max wait time exceeded ("+DEFAULT_TASK_MAX_DURATION.to_s+"sec), task: '"+@uri.to_s+"'" if (Time.new > due_to_time)
end
end
end
- # Convenience class to split a (sub)task into subtasks
- #
- # example:
- # a crossvalidation is split into creating datasets and performing the validations
- # creating the dataset is 1/3 of the work, perform the validations is 2/3:
- # Task.as_task do |task|
- # create_datasets( SubTask.new(task, 0, 33) )
- # perfom_validations( SubTask.new(task, 33, 100) )
- # end
- # inside the create_datasets / perform_validations you can use subtask.progress(<val>)
- # with vals from 0-100
- #
- # note that you can split a subtask into further subtasks
- class SubTask
-
- def initialize(task, min, max)
- raise "not a task or subtask" if task!=nil and !(task.is_a?(Task) or task.is_a?(SubTask))
- raise "invalid max ("+max.to_s+"), min ("+min.to_s+") params" unless
- min.is_a?(Numeric) and max.is_a?(Numeric) and min >= 0 and max <= 100 and max > min
- @task = task
- @min = min
- @max = max
- @delta = max - min
- end
-
- # convenience method to handle null tasks
- def self.create(task, min, max)
- if task
- SubTask.new(task, min, max)
- else
- nil
- end
- end
-
- def waiting_for(task_uri)
- @task.waiting_for(task_uri)
- end
-
- def progress(pct)
- raise "no numeric >= 0 and <= 100 : '"+pct.to_s+"'" unless pct.is_a?(Numeric) and pct>=0 and pct<=100
- #puts "subtask := "+pct.to_s+" -> task := "+(@min + @delta * pct.to_f * 0.01).to_s
- @task.progress( @min + @delta * pct.to_f * 0.01 )
- end
-
- def running?()
- @task.running?
- end
- end
-
-
- # The David Gallagher feature:
- # a fake sub task to keep the progress bar movin for external jobs
- # note: param could be a subtask
- #
- # usage (for a call that is normally finished in under 60 seconds):
- # fsk = FakeSubTask.new(task, 60)
- # external_lib_call.start
- # external_lib_call.wait_until_finished
- # fsk.finished
- #
- # what happens:
- # the FakeSubTask updates the task.progress each second until
- # runtime is up or the finished mehtod is called
- #
- # example if the param runtime is too low:
- # 25% .. 50% .. 75% .. 100% .. 100% .. 100% .. 100% .. 100%
- # example if the param runtime is too high:
- # 5% .. 10% .. 15% .. 20% .. 25% .. 30% .. 35% .. 100%
- # the latter example is better (keep the bar movin!)
- # -> better make a conservative runtime estimate
- class FakeSubTask
-
- def initialize(task, runtime)
- @task = task
- @thread = Thread.new do
- timeleft = runtime
- while (timeleft > 0 and @task.running?)
- sleep 1
- timeleft -= 1
- @task.progress( (runtime - timeleft) / runtime.to_f * 100 )
- end
- end
- end
-
- # convenience method to handle null tasks
- def self.create(task, runtime)
- if task
- FakeSubTask.new(task, runtime)
- else
- nil
- end
- end
-
- def finished
- @thread.exit
- @task.progress(100) if @task.running?
- end
- end
-
end
diff --git a/lib/to-html.rb b/lib/to-html.rb
deleted file mode 100644
index 04fa158..0000000
--- a/lib/to-html.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-OT_LOGO = File.join(CONFIG[:services]["opentox-validation"],"resources/ot-logo.png")
-
-class String
-
- # encloses URI in text with with link tag
- # @return [String] new text with marked links
- def link_urls
- self.gsub(/(?i)http(s?):\/\/[^\r\n\s']*/, '<a href="\0">\0</a>')
- end
-end
-
-module OpenTox
-
- # produces a html page for making web services browser friendly
- # format of text (=string params) is preserved (e.g. line breaks)
- # urls are marked as links
- # @example post params:
- # [ [ [:mandatory_param_1], [:mandatory_param_2], [:optional_param,"default_value"] ],
- # [ [:alteranative_mandatory_param_1], [:alteranative_mandatory_param_2] ]
- # ]
- # @param [String] text this is the actual content,
- # @param [optional,String] related_links info on related resources
- # @param [optional,String] description general info
- # @param [optional,Array] post_params, array of arrays containing info on POST operation, see example
- # @return [String] html page
- def self.text_to_html( text, subjectid=nil, related_links=nil, description=nil, post_params=nil )
-
- # TODO add title as parameter
- title = nil #$sinatra.url_for($sinatra.request.env['PATH_INFO'], :full) if $sinatra
- html = "<html>"
- html += "<title>"+title+"</title>" if title
- html += "<img src=\""+OT_LOGO+"\"><\/img><body>"
-
- if AA_SERVER
- user = OpenTox::Authorization.get_user(subjectid) if subjectid
- html += "<pre><p align=\"right\">"
- unless user
- html += "You are currently not signed in to "+$url_provider.url_for("",:full)+
- ", <a href="+$url_provider.url_for("/sign_in",:full)+">sign in</a>"
- else
- html += "You are signed in as '#{user}' to "+$url_provider.url_for("",:full)+
- ", <a href="+$url_provider.url_for("/sign_out",:full)+">sign out</a>"
- end
- html += " </p></pre>"
- end
-
- html += "<h3>Description</h3><pre><p>"+description.link_urls+"</p></pre>" if description
- html += "<h3>Related links</h3><pre><p>"+related_links.link_urls+"</p></pre>" if related_links
- if post_params
- html += "<h3>POST parameters</h3>"
- count = 0
- post_params.each do |p|
- html += "<pre><p>alternatively:</p></pre>" if count > 0
- html += "<pre><p><table><thead><tr><th>param</th><th>default_value</th></tr></thead>"
- p.each do |k,v|
- html += "<tr><th>"+k.to_s+"</th><th>"+(v!=nil ? v.to_s : "<i>mandatory</i>")+"</th></tr>"
- end
- html += "</table></p></pre>"
- count += 1
- end
- end
- html += "<h3>Content</h3>" if description || related_links
- html += "<pre><p style=\"padding:15px; border:10px solid \#5D308A\">"
- html += text.link_urls
- html += "</p></pre></body></html>"
- html
- end
-
- def self.sign_in( msg=nil )
- html = "<html><title>Login</title><img src="+OT_LOGO+"><body>"
- html += "<form method='POST' action='"+$url_provider.url_for("/sign_in",:full)+"'>"
- html += "<pre><p style=\"padding:15px; border:10px solid \#5D308A\">"
- html += msg+"\n\n" if msg
- html += "Please sign in to "+$url_provider.url_for("",:full)+"\n\n"
- html += "<table border=0>"
- html += "<tr><td>user:</td><td><input type='text' name='user' size='15' /></td></tr>"+
- "<tr><td>password:</td><td><input type='password' name='password' size='15' /></td></tr>"+
- #"<input type=hidden name=back_to value="+back_to.to_s+">"+
- "<tr><td><input type='submit' value='Sign in' /></td></tr>"
- html += "</table></p></pre></form></body></html>"
- html
- end
-end
-
-get '/sign_out/?' do
- response.set_cookie("subjectid",{:value=>nil})
- content_type "text/html"
- content = "Sucessfully signed out from "+$url_provider.url_for("",:full)
- OpenTox.text_to_html(content)
-end
-
-get '/sign_in/?' do
- content_type "text/html"
- OpenTox.sign_in
-end
-
-post '/sign_in/?' do
- subjectid = OpenTox::Authorization.authenticate(params[:user], params[:password])
- if (subjectid)
- response.set_cookie("subjectid",{:value=>subjectid})
- content_type "text/html"
- content = "Sucessfully signed in as '"+params[:user]+"' to "+$url_provider.url_for("",:full)
- OpenTox.text_to_html(content,subjectid)
- else
- content_type "text/html"
- OpenTox.sign_in("Login failed, please try again")
- end
-end
-
diff --git a/lib/validation.rb b/lib/validation.rb
deleted file mode 100644
index d7a337c..0000000
--- a/lib/validation.rb
+++ /dev/null
@@ -1,313 +0,0 @@
-module OpenTox
- class Validation
- include OpenTox
-
- # find validation, raises error if not found
- # @param [String] uri
- # @param [String,optional] subjectid
- # @return [OpenTox::Validation]
- def self.find( uri, subjectid=nil )
- val = Validation.new(uri)
- val.load_metadata( subjectid )
- val
- end
-
- # returns a filtered list of validation uris
- # @param [Hash,optional] params, validation-params to filter the uris (could be model, training_dataset, ..)
- # @return [Array]
- def self.list( params={} )
- filter_string = ""
- params.each do |k,v|
- filter_string = "?" if filter_string.length==0
- filter_string += k.to_s+"="+v
- end
- (OpenTox::RestClientWrapper.get(CONFIG[:services]["opentox-validation"]+filter_string).split("\n"))
- end
-
- # creates a training test split validation, waits until it finishes, may take some time
- # @param [Hash] params (required:algorithm_uri,dataset_uri,prediction_feature, optional:algorithm_params,split_ratio(0.67),random_seed(1))
- # @param [String,optional] subjectid
- # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @return [OpenTox::Validation]
- def self.create_training_test_split( params, subjectid=nil, waiting_task=nil )
- params[:subjectid] = subjectid if subjectid
- uri = OpenTox::RestClientWrapper.post( File.join(CONFIG[:services]["opentox-validation"],"training_test_split"),
- params,{:content_type => "text/uri-list"},waiting_task )
- Validation.new(uri)
- end
-
- # looks for report for this validation, creates a report if no report is found
- # @param [String,optional] subjectid
- # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @return [String] report uri
- def find_or_create_report( subjectid=nil, waiting_task=nil )
- @report = ValidationReport.find_for_validation(@uri, subjectid) unless @report
- @report = ValidationReport.create(@uri, subjectid, waiting_task) unless @report
- @report.uri
- end
-
- # creates a validation object from crossvaldiation statistics, raise error if not found
- # (as crossvaldiation statistics are returned as an average valdidation over all folds)
- # @param [String] crossvalidation uri
- # @param [String,optional] subjectid
- # @return [OpenTox::Validation]
- def self.from_cv_statistics( crossvalidation_uri, subjectid=nil )
- find( File.join(crossvalidation_uri, 'statistics'),subjectid )
- end
-
- # loads metadata via yaml from validation object
- # fields (like for example the validated model) can be acces via validation.metadata[OT.model]
- def load_metadata( subjectid=nil )
- @metadata = YAML.load(OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid, :accept => "application/x-yaml"}))
- end
-
- # PENDING: creates summary as used for ToxCreate
- def summary
- if @metadata[OT.classificationStatistics]
- res = {
- :nr_predictions => @metadata[OT.numInstances].to_i - @metadata[OT.numUnpredicted].to_i,
- :correct_predictions => @metadata[OT.classificationStatistics][OT.percentCorrect],
- :weighted_area_under_roc => @metadata[OT.classificationStatistics][OT.weightedAreaUnderRoc],
- }
- @metadata[OT.classificationStatistics][OT.classValueStatistics].each do |s|
- if s[OT.classValue].to_s=="true"
- res[:true_positives] = s[OT.numTruePositives]
- res[:false_positives] = s[OT.numFalsePositives]
- res[:true_negatives] = s[OT.numTrueNegatives]
- res[:false_negatives] = s[OT.numFalseNegatives]
- res[:sensitivity] = s[OT.truePositiveRate]
- res[:specificity] = s[OT.trueNegativeRate]
- break
- end
- end
- res
- elsif @metadata[OT.regressionStatistics]
- {
- :nr_predictions => @metadata[OT.numInstances].to_i - @metadata[OT.numUnpredicted].to_i,
- :r_square => @metadata[OT.regressionStatistics][OT.rSquare],
- :root_mean_squared_error => @metadata[OT.regressionStatistics][OT.rootMeanSquaredError],
- :mean_absolute_error => @metadata[OT.regressionStatistics][OT.meanAbsoluteError],
- }
- end
- end
- end
-
- class Crossvalidation
- include OpenTox
-
- attr_reader :report
-
- # find crossvalidation, raises error if not found
- # @param [String] uri
- # @param [String,optional] subjectid
- # @return [OpenTox::Crossvalidation]
- def self.find( uri, subjectid=nil )
- cv = Crossvalidation.new(uri)
- cv.load_metadata( subjectid )
- cv
- end
-
- # returns a filtered list of crossvalidation uris
- # @param [Hash,optional] params, crossvalidation-params to filter the uris (could be algorithm, dataset, ..)
- # @return [Array]
- def self.list( params={} )
- filter_string = ""
- params.each do |k,v|
- filter_string = "?" if filter_string.length==0
- filter_string += k.to_s+"="+v
- end
- (OpenTox::RestClientWrapper.get(File.join(CONFIG[:services]["opentox-validation"],"crossvalidation")+filter_string).split("\n"))
- end
-
- # creates a crossvalidations, waits until it finishes, may take some time
- # @param [Hash] params (required:algorithm_uri,dataset_uri,prediction_feature, optional:algorithm_params,num_folds(10),random_seed(1),stratified(false))
- # @param [String,optional] subjectid
- # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @return [OpenTox::Crossvalidation]
- def self.create( params, subjectid=nil, waiting_task=nil )
- params[:subjectid] = subjectid if subjectid
- uri = OpenTox::RestClientWrapper.post( File.join(CONFIG[:services]["opentox-validation"],"crossvalidation"),
- params,{:content_type => "text/uri-list"},waiting_task )
- Crossvalidation.new(uri)
- end
-
- # looks for report for this crossvalidation, creates a report if no report is found
- # @param [String,optional] subjectid
- # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @return [String] report uri
- def find_or_create_report( subjectid=nil, waiting_task=nil )
- @report = CrossvalidationReport.find_for_crossvalidation(@uri, subjectid) unless @report
- @report = CrossvalidationReport.create(@uri, subjectid, waiting_task) unless @report
- @report.uri
- end
-
- # loads metadata via yaml from crossvalidation object
- # fields (like for example the validations) can be acces via validation.metadata[OT.validation]
- def load_metadata( subjectid=nil )
- @metadata = YAML.load(OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid, :accept => "application/x-yaml"}))
- end
-
- # PENDING: creates summary as used for ToxCreate
- def summary( subjectid=nil )
- Validation.from_cv_statistics( @uri, subjectid ).summary
- end
- end
-
- class ValidationReport
- include OpenTox
-
- # finds ValidationReport via uri, raises error if not found
- # @param [String] uri
- # @param [String,optional] subjectid
- # @return [OpenTox::ValidationReport]
- def self.find( uri, subjectid=nil )
- OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid})
- rep = ValidationReport.new(uri)
- rep.load_metadata( subjectid )
- rep
- end
-
- # finds ValidationReport for a particular validation
- # @param [String] crossvalidation uri
- # @param [String,optional] subjectid
- # @return [OpenTox::ValidationReport] nil if no report found
- def self.find_for_validation( validation_uri, subjectid=nil )
- uris = RestClientWrapper.get(File.join(CONFIG[:services]["opentox-validation"],
- "/report/validation?validation="+validation_uri), {:subjectid => subjectid}).chomp.split("\n")
- uris.size==0 ? nil : ValidationReport.new(uris[-1])
- end
-
- # creates a validation report via validation
- # @param [String] validation uri
- # @param [String,optional] subjectid
- # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @return [OpenTox::ValidationReport]
- def self.create( validation_uri, subjectid=nil, waiting_task=nil )
- uri = RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/report/validation"),
- { :validation_uris => validation_uri, :subjectid => subjectid }, {}, waiting_task )
- ValidationReport.new(uri)
- end
-
- end
-
- class CrossvalidationReport
- include OpenTox
-
- # finds CrossvalidationReport via uri, raises error if not found
- # @param [String] uri
- # @param [String,optional] subjectid
- # @return [OpenTox::CrossvalidationReport]
- def self.find( uri, subjectid=nil )
- OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid})
- rep = CrossvalidationReport.new(uri)
- rep.load_metadata( subjectid )
- rep
- end
-
- # finds CrossvalidationReport for a particular crossvalidation
- # @param [String] crossvalidation uri
- # @param [String,optional] subjectid
- # @return [OpenTox::CrossvalidationReport] nil if no report found
- def self.find_for_crossvalidation( crossvalidation_uri, subjectid=nil )
- uris = RestClientWrapper.get(File.join(CONFIG[:services]["opentox-validation"],
- "/report/crossvalidation?crossvalidation="+crossvalidation_uri), {:subjectid => subjectid}).chomp.split("\n")
- uris.size==0 ? nil : CrossvalidationReport.new(uris[-1])
- end
-
- # creates a crossvalidation report via crossvalidation
- # @param [String] crossvalidation uri
- # @param [String,optional] subjectid
- # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @return [OpenTox::CrossvalidationReport]
- def self.create( crossvalidation_uri, subjectid=nil, waiting_task=nil )
- uri = RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/report/crossvalidation"),
- { :validation_uris => crossvalidation_uri, :subjectid => subjectid }, {}, waiting_task )
- CrossvalidationReport.new(uri)
- end
- end
-
-
- class AlgorithmComparisonReport
- include OpenTox
-
- # finds AlgorithmComparisonReport via uri, raises error if not found
- # @param [String] uri
- # @param [String,optional] subjectid
- # @return [OpenTox::CrossvalidationReport]
- def self.find( uri, subjectid=nil )
- OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid})
- rep = AlgorithmComparisonReport.new(uri)
- rep.load_metadata( subjectid )
- rep
- end
-
- # finds AlgorithmComparisonReport for a particular crossvalidation
- # @param [String] crossvalidation uri
- # @param [String,optional] subjectid
- # @return [OpenTox::AlgorithmComparisonReport] nil if no report found
- def self.find_for_crossvalidation( crossvalidation_uri, subjectid=nil )
- uris = RestClientWrapper.get(File.join(CONFIG[:services]["opentox-validation"],
- "/report/algorithm_comparison?crossvalidation="+crossvalidation_uri), {:subjectid => subjectid}).chomp.split("\n")
- uris.size==0 ? nil : AlgorithmComparisonReport.new(uris[-1])
- end
-
- # creates a crossvalidation report via crossvalidation
- # @param [Hash] crossvalidation uri_hash, see example
- # @param [String,optional] subjectid
- # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @return [OpenTox::AlgorithmComparisonReport]
- # example for hash:
- # { :lazar-bbrc => [ http://host/validation/crossvalidation/x1, http://host/validation/crossvalidation/x2 ],
- # :lazar-last => [ http://host/validation/crossvalidation/xy, http://host/validation/crossvalidation/xy ] }
- def self.create( crossvalidation_uri_hash, subjectid=nil, waiting_task=nil )
- identifier = []
- validation_uris = []
- crossvalidation_uri_hash.each do |id, uris|
- uris.each do |uri|
- identifier << id
- validation_uris << uri
- end
- end
- uri = RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/report/algorithm_comparison"),
- { :validation_uris => validation_uris.join(","), :identifier => identifier.join(","), :subjectid => subjectid }, {}, waiting_task )
- AlgorithmComparisonReport.new(uri)
- end
- end
-
- class QMRFReport
- include OpenTox
-
- # finds QMRFReport, raises Error if not found
- # @param [String] uri
- # @param [String,optional] subjectid
- # @return [OpenTox::QMRFReport]
- def self.find( uri, subjectid=nil )
- # PENDING load crossvalidation data?
- OpenTox::RestClientWrapper.get(uri,{:subjectid => subjectid})
- QMRFReport.new(uri)
- end
-
- # finds QMRF report for a particular model
- # @param [String] model_uri
- # @param [String,optional] subjectid
- # @return [OpenTox::QMRFReport] nil if no report found
- def self.find_for_model( model_uri, subjectid=nil )
- uris = RestClientWrapper.get(File.join(CONFIG[:services]["opentox-validation"],
- "/reach_report/qmrf?model="+model_uri), {:subjectid => subjectid}).chomp.split("\n")
- uris.size==0 ? nil : QMRFReport.new(uris[-1])
- end
-
- # creates a qmrf report via model
- # @param [String] model_uri
- # @param [String,optional] subjectid
- # @param [OpenTox::Task,optional] waiting_task (can be a OpenTox::Subtask as well), progress is updated accordingly
- # @return [OpenTox::QMRFReport]
- def self.create( model_uri, subjectid=nil, waiting_task=nil )
- uri = RestClientWrapper.post(File.join(CONFIG[:services]["opentox-validation"],"/reach_report/qmrf"),
- { :model_uri => model_uri, :subjectid => subjectid }, {}, waiting_task )
- QMRFReport.new(uri)
- end
- end
-
-end
-