Duplicated structures (all structures/activities used for model building, please make sure, that the results were obtained from independent experiments):
" + 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()
- # 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']*/, '\0')
- 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 += ""+title+"" if title
- html += "<\/img>"
-
- if AA_SERVER
- user = OpenTox::Authorization.get_user(subjectid) if subjectid
- html += "
"
- unless user
- html += "You are currently not signed in to "+$url_provider.url_for("",:full)+
- ", sign in"
- else
- html += "You are signed in as '#{user}' to "+$url_provider.url_for("",:full)+
- ", sign out"
- end
- html += "
"
- end
-
- html += "
Description
"+description.link_urls+"
" if description
- html += "
Related links
"+related_links.link_urls+"
" if related_links
- if post_params
- html += "
POST parameters
"
- count = 0
- post_params.each do |p|
- html += "