opentox-ruby-api-wrapper 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/bin/opentox-install-ubuntu.sh +2 -2
- data/bin/yaml2owl.rb +1 -1
- data/lib/algorithm.rb +4 -1
- data/lib/compound.rb +4 -4
- data/lib/config/config_ru.rb +8 -0
- data/lib/dataset.rb +162 -158
- data/lib/environment.rb +77 -6
- data/lib/features.rb +15 -0
- data/lib/model.rb +88 -103
- data/lib/opentox-ruby-api-wrapper.rb +1 -1
- data/lib/owl.rb +386 -149
- data/lib/rest_client_wrapper.rb +170 -0
- data/lib/spork.rb +2 -0
- data/lib/task.rb +148 -75
- data/lib/templates/config.yaml +53 -5
- data/lib/utils.rb +34 -2
- data/lib/validation.rb +10 -2
- metadata +97 -62
data/Rakefile
CHANGED
@@ -10,10 +10,10 @@ begin
|
|
10
10
|
gem.email = "helma@in-silico.ch"
|
11
11
|
gem.homepage = "http://github.com/helma/opentox-ruby-api-wrapper"
|
12
12
|
gem.authors = ["Christoph Helma"]
|
13
|
-
["sinatra", "rest-client", "rack", "rack-contrib", "rack-flash", "emk-sinatra-url-for", "
|
13
|
+
["sinatra", "rest-client", "rack", "rack-contrib", "rack-flash", "emk-sinatra-url-for", "sinatra-respond_to", "dm-more", "dm-core", "sinatra-static-assets","tmail"].each do |dep|
|
14
14
|
gem.add_dependency dep
|
15
15
|
end
|
16
|
-
['cucumber','jeweler'
|
16
|
+
['cucumber','jeweler'].each do |dep|
|
17
17
|
gem.add_development_dependency dep
|
18
18
|
end
|
19
19
|
gem.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*", 'lib/jeweler/templates/.gitignore']
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.5.0
|
@@ -90,9 +90,9 @@ sudo apt-get install postgresql-server-dev-8.4 | tee -a $INSTALLLOG
|
|
90
90
|
#echo "Installing gems jeweler sinatra emk-sinatra-url-for dm-core cehoffman-sinatra-respond_to rest-client rack-contrib thin cucumber datamapper data_objects do_sqlite3 rinruby"
|
91
91
|
sudo gem install jeweler | tee -a $INSTALLLOG
|
92
92
|
sudo gem install sinatra | tee -a $INSTALLLOG
|
93
|
-
sudo gem install
|
93
|
+
sudo gem install sinatra-url-for | tee -a $INSTALLLOG
|
94
94
|
sudo gem install dm-core | tee -a $INSTALLLOG
|
95
|
-
sudo gem install
|
95
|
+
sudo gem install sinatra-respond_to | tee -a $INSTALLLOG
|
96
96
|
sudo gem install rest-client | tee -a $INSTALLLOG
|
97
97
|
sudo gem install rack-contrib | tee -a $INSTALLLOG
|
98
98
|
sudo gem install thin | tee -a $INSTALLLOG
|
data/bin/yaml2owl.rb
CHANGED
@@ -5,7 +5,7 @@ require 'opentox-ruby-api-wrapper'
|
|
5
5
|
input = YAML.load_file(ARGV[0])
|
6
6
|
dataset = OpenTox::Dataset.new
|
7
7
|
dataset.title = input[:title]
|
8
|
-
dataset.
|
8
|
+
dataset.creator = input[:source]
|
9
9
|
input[:data].each do |c,f|
|
10
10
|
f.each do |k,v|
|
11
11
|
v.each do |value|
|
data/lib/algorithm.rb
CHANGED
@@ -21,8 +21,11 @@ module OpenTox
|
|
21
21
|
def self.create_model(params)
|
22
22
|
LOGGER.debug params
|
23
23
|
LOGGER.debug File.basename(__FILE__) + ": creating model"
|
24
|
+
LOGGER.debug File.join(@@config[:services]["opentox-algorithm"], "lazar")
|
25
|
+
#resource = RestClient::Resource.new(File.join(@@config[:services]["opentox-algorithm"], "lazar"), :user => @@users[:users].keys[0], :password => @@users[:users].values[0], :content_type => "application/x-yaml")
|
24
26
|
resource = RestClient::Resource.new(File.join(@@config[:services]["opentox-algorithm"], "lazar"), :user => @@users[:users].keys[0], :password => @@users[:users].values[0], :content_type => "application/x-yaml")
|
25
|
-
|
27
|
+
#@uri = resource.post(:dataset_uri => params[:dataset_uri], :feature_uri => params[:feature_uri], :feature_generation_uri => File.join(@@config[:services]["opentox-algorithm"], "fminer")).chomp
|
28
|
+
@uri = resource.post(:dataset_uri => params[:dataset_uri], :prediction_feature => params[:prediction_feature], :feature_generation_uri => File.join(@@config[:services]["opentox-algorithm"], "fminer")).body.chomp
|
26
29
|
end
|
27
30
|
|
28
31
|
def self.uri
|
data/lib/compound.rb
CHANGED
@@ -18,18 +18,18 @@ module OpenTox
|
|
18
18
|
@uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi))
|
19
19
|
elsif params[:name]
|
20
20
|
# paranoid URI encoding to keep SMILES charges and brackets
|
21
|
-
@inchi =
|
21
|
+
@inchi = RestClientWrapper.get("#{@@cactus_uri}#{URI.encode(params[:name], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}/stdinchi").chomp
|
22
22
|
@uri = File.join(@@config[:services]["opentox-compound"],URI.escape(@inchi))
|
23
23
|
elsif params[:uri]
|
24
24
|
@uri = params[:uri]
|
25
25
|
case params[:uri]
|
26
26
|
when /ambit/ # Ambit does not deliver InChIs reliably
|
27
|
-
smiles =
|
27
|
+
smiles = RestClientWrapper.get @uri, :accept => 'chemical/x-daylight-smiles'
|
28
28
|
@inchi = obconversion(smiles,'smi','inchi')
|
29
29
|
when /InChI/ # shortcut for IST services
|
30
30
|
@inchi = params[:uri].sub(/^.*InChI/, 'InChI')
|
31
31
|
else
|
32
|
-
@inchi =
|
32
|
+
@inchi = RestClientWrapper.get @uri, :accept => 'chemical/x-inchi'
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -44,7 +44,7 @@ module OpenTox
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def image
|
47
|
-
|
47
|
+
RestClientWrapper.get("#{@@cactus_uri}#{@inchi}/image")
|
48
48
|
end
|
49
49
|
|
50
50
|
def image_uri
|
data/lib/config/config_ru.rb
CHANGED
data/lib/dataset.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
LOGGER.progname = File.expand_path(__FILE__)
|
2
2
|
|
3
3
|
module OpenTox
|
4
|
-
|
4
|
+
|
5
5
|
class Dataset
|
6
6
|
|
7
|
-
attr_accessor :uri, :title, :
|
7
|
+
attr_accessor :uri, :title, :creator, :data, :features, :compounds
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
@data = {}
|
@@ -12,171 +12,175 @@ module OpenTox
|
|
12
12
|
@compounds = []
|
13
13
|
end
|
14
14
|
|
15
|
-
def self.find(uri)
|
16
|
-
|
15
|
+
def self.find(uri, accept_header=nil)
|
16
|
+
|
17
|
+
unless accept_header
|
18
|
+
#if uri.match(@@config[:services]["opentox-dataset"]) || uri=~ /188.40.32.88/ || uri =~ /informatik/
|
19
|
+
if !@@config[:accept_headers]["opentox-dataset"].grep(/yaml/).empty?
|
20
|
+
accept_header = 'application/x-yaml'
|
21
|
+
else
|
22
|
+
accept_header = "application/rdf+xml"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
case accept_header
|
27
|
+
when "application/x-yaml"
|
28
|
+
d = YAML.load RestClientWrapper.get(uri.to_s.strip, :accept => 'application/x-yaml').to_s
|
29
|
+
d.uri = uri unless d.uri
|
30
|
+
when "application/rdf+xml"
|
31
|
+
owl = OpenTox::Owl.from_uri(uri.to_s.strip, "Dataset")
|
32
|
+
|
33
|
+
d = Dataset.new
|
34
|
+
d.title = owl.get("title")
|
35
|
+
d.creator = owl.get("creator")
|
36
|
+
d.uri = owl.uri
|
37
|
+
|
38
|
+
# when loading a dataset from owl, only compound- and feature-uris are loaded
|
39
|
+
owl.load_dataset(d.compounds, d.features)
|
40
|
+
# all features are marked as dirty, loaded dynamically later
|
41
|
+
d.init_dirty_features(owl)
|
42
|
+
|
43
|
+
d.compounds.uniq!
|
44
|
+
d.features.uniq!
|
45
|
+
else
|
46
|
+
raise "cannot get datset with accept header: "+accept_header.to_s
|
47
|
+
end
|
48
|
+
return d
|
17
49
|
end
|
50
|
+
|
51
|
+
# creates a new dataset, using only those compounsd specified in new_compounds
|
52
|
+
# returns uri of new dataset
|
53
|
+
def create_new_dataset( new_compounds, new_features, new_title, new_creator )
|
54
|
+
|
55
|
+
raise "no new compounds selected" unless new_compounds and new_compounds.size>0
|
56
|
+
|
57
|
+
# load require features
|
58
|
+
if ((defined? @dirty_features) && (@dirty_features - new_features).size > 0)
|
59
|
+
(@dirty_features - new_features).each{|f| load_feature_values(f)}
|
60
|
+
end
|
61
|
+
|
62
|
+
dataset = OpenTox::Dataset.new
|
63
|
+
dataset.title = new_title
|
64
|
+
dataset.creator = new_creator
|
65
|
+
dataset.features = new_features
|
66
|
+
dataset.compounds = new_compounds
|
67
|
+
|
68
|
+
# Copy dataset data for compounds and features
|
69
|
+
# PENDING: why storing feature values in an array?
|
70
|
+
new_compounds.each do |c|
|
71
|
+
data_c = []
|
72
|
+
@data[c].each do |d|
|
73
|
+
m = {}
|
74
|
+
new_features.each do |f|
|
75
|
+
m[f] = d[f]
|
76
|
+
end
|
77
|
+
data_c << m
|
78
|
+
end
|
79
|
+
|
80
|
+
dataset.data[c] = data_c
|
81
|
+
end
|
82
|
+
return dataset.save
|
83
|
+
end
|
84
|
+
|
85
|
+
# returns classification value
|
86
|
+
def get_predicted_class(compound, feature)
|
87
|
+
v = get_value(compound, feature)
|
88
|
+
if v.is_a?(Hash)
|
89
|
+
if v.has_key?(:classification)
|
90
|
+
return v[:classification]
|
91
|
+
else
|
92
|
+
return "no classification key"
|
93
|
+
end
|
94
|
+
else
|
95
|
+
raise "predicted class value is not a hash\n"+
|
96
|
+
"value "+v.to_s+"\n"+
|
97
|
+
"value-class "+v.class.to_s+"\n"+
|
98
|
+
"dataset "+@uri.to_s+"\n"+
|
99
|
+
"compound "+compound.to_s+"\n"+
|
100
|
+
"feature "+feature.to_s+"\n"
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
# returns prediction confidence if available
|
106
|
+
def get_prediction_confidence(compound, feature)
|
107
|
+
v = get_value(compound, feature)
|
108
|
+
if v.is_a?(Hash)
|
109
|
+
if v.has_key?(:confidence)
|
110
|
+
return v[:confidence].abs
|
111
|
+
else
|
112
|
+
# PENDING: return nil isntead of raising an exception
|
113
|
+
raise "no confidence key"
|
114
|
+
end
|
115
|
+
else
|
116
|
+
raise "prediction confidence value is not a hash value\n"+
|
117
|
+
"value "+v.to_s+"\n"+
|
118
|
+
"value-class "+v.class.to_s+"\n"+
|
119
|
+
"dataset "+@uri.to_s+"\n"+
|
120
|
+
"compound "+compound.to_s+"\n"+
|
121
|
+
"feature "+feature.to_s+"\n"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# return compound-feature value
|
126
|
+
def get_value(compound, feature)
|
127
|
+
if (defined? @dirty_features) && @dirty_features.include?(feature)
|
128
|
+
load_feature_values(feature)
|
129
|
+
end
|
130
|
+
|
131
|
+
v = @data[compound]
|
132
|
+
raise "no values for compound "+compound.to_s if v==nil
|
133
|
+
if v.is_a?(Array)
|
134
|
+
# PENDING: why using an array here?
|
135
|
+
v.each do |e|
|
136
|
+
if e.is_a?(Hash)
|
137
|
+
if e.has_key?(feature)
|
138
|
+
return e[feature]
|
139
|
+
end
|
140
|
+
else
|
141
|
+
raise "invalid internal value type"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
raise "feature value no found: "+feature.to_s
|
145
|
+
else
|
146
|
+
raise "value is not an array\n"+
|
147
|
+
"value "+v.to_s+"\n"+
|
148
|
+
"value-class "+v.class.to_s+"\n"+
|
149
|
+
"dataset "+@uri.to_s+"\n"+
|
150
|
+
"compound "+compound.to_s+"\n"+
|
151
|
+
"feature "+feature.to_s+"\n"
|
152
|
+
end
|
153
|
+
end
|
18
154
|
|
155
|
+
# loads specified feature and removes dirty-flag, loads all features if feature is nil
|
156
|
+
def load_feature_values(feature=nil)
|
157
|
+
if feature
|
158
|
+
raise "feature already loaded" unless @dirty_features.include?(feature)
|
159
|
+
@owl.load_dataset_feature_values(@compounds, @data, feature)
|
160
|
+
@dirty_features.delete(feature)
|
161
|
+
else
|
162
|
+
@data = {}
|
163
|
+
@owl.load_dataset_feature_values(@compounds, @data)
|
164
|
+
@dirty_features.clear
|
165
|
+
end
|
166
|
+
end
|
19
167
|
|
20
168
|
def save
|
169
|
+
# loads all features before loading
|
170
|
+
if ((defined? @dirty_features) && @dirty_features.size > 0)
|
171
|
+
load_feature_values()
|
172
|
+
end
|
173
|
+
|
21
174
|
@features.uniq!
|
22
175
|
@compounds.uniq!
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
=begin
|
27
|
-
# create/add to entry from uris or Redland::Resources
|
28
|
-
def add(compound,feature,value)
|
29
|
-
compound = self.find_or_create_compound compound unless compound.class == Redland::Resource
|
30
|
-
feature = self.find_or_create_feature feature unless feature.class == Redland::Resource
|
31
|
-
data_entry = @model.subject OT['compound'], compound
|
32
|
-
if data_entry.nil?
|
33
|
-
data_entry = @model.create_resource
|
34
|
-
dataset = @model.subject(RDF['type'],OT[self.owl_class])
|
35
|
-
@model.add dataset, OT['dataEntry'], data_entry
|
36
|
-
@model.add data_entry, RDF['type'], OT["DataEntry"]
|
37
|
-
@model.add data_entry, OT['compound'], compound
|
38
|
-
end
|
39
|
-
values = @model.create_resource
|
40
|
-
@model.add data_entry, OT['values'], values
|
41
|
-
@model.add values, RDF['type'], OT['FeatureValue']
|
42
|
-
@model.add values, OT['feature'], feature
|
43
|
-
@model.add values, OT['value'], value.to_s
|
44
|
-
end
|
45
|
-
|
46
|
-
def add_tuple(compound,tuple)
|
47
|
-
compound = self.find_or_create_compound compound unless compound.class == Redland::Resource
|
48
|
-
data_entry = @model.subject OT['compound'], compound
|
49
|
-
if data_entry.nil?
|
50
|
-
data_entry = @model.create_resource
|
51
|
-
dataset = @model.subject(RDF['type'],OT[self.owl_class])
|
52
|
-
@model.add dataset, OT['dataEntry'], data_entry
|
53
|
-
@model.add data_entry, RDF['type'], OT["DataEntry"]
|
54
|
-
@model.add data_entry, OT['compound'], compound
|
55
|
-
end
|
56
|
-
@model.add data_entry, OT['values'], tuple
|
176
|
+
OpenTox::RestClientWrapper.post(@@config[:services]["opentox-dataset"],{:content_type => "application/x-yaml"},self.to_yaml).strip
|
57
177
|
end
|
58
178
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
@model.add tuple, RDF['type'], OT["Tuple"]
|
63
|
-
@model.add tuple, OT['feature'], feature
|
64
|
-
t.each do |name,value|
|
65
|
-
f = self.find_or_create_feature name unless name.class == Redland::Resource
|
66
|
-
complex_value = @model.create_resource
|
67
|
-
feature = self.find_or_create_feature(name)
|
68
|
-
@model.add tuple, OT['complexValue'], complex_value
|
69
|
-
@model.add complex_value, RDF['type'], OT["FeatureValue"]
|
70
|
-
@model.add complex_value, OT['feature'], f
|
71
|
-
@model.add complex_value, OT['value'], value.to_s
|
72
|
-
end
|
73
|
-
|
74
|
-
tuple
|
75
|
-
end
|
76
|
-
|
77
|
-
# find or create a new compound and return the resource
|
78
|
-
def find_or_create_compound(uri)
|
79
|
-
compound = @model.subject(DC["identifier"], uri)
|
80
|
-
if compound.nil?
|
81
|
-
compound = @model.create_resource(uri)
|
82
|
-
@model.add compound, RDF['type'], OT["Compound"]
|
83
|
-
@model.add compound, DC["identifier"], uri
|
84
|
-
end
|
85
|
-
compound
|
86
|
-
end
|
87
|
-
|
88
|
-
# find or create a new feature and return the resource
|
89
|
-
def find_or_create_feature(uri)
|
90
|
-
feature = @model.subject(DC["identifier"], uri)
|
91
|
-
if feature.nil?
|
92
|
-
feature = @model.create_resource(uri)
|
93
|
-
@model.add feature, RDF['type'], OT["Feature"]
|
94
|
-
@model.add feature, DC["identifier"], uri
|
95
|
-
@model.add feature, DC["title"], File.basename(uri).split(/#/)[1]
|
96
|
-
@model.add feature, DC['source'], uri
|
97
|
-
end
|
98
|
-
feature
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.create(data, content_type = 'application/rdf+xml')
|
102
|
-
resource = RestClient::Resource.new(@@config[:services]["opentox-dataset"], :user => @@users[:users].keys[0], :password => @@users[:users].values[0])
|
103
|
-
uri = resource.post data, :content_type => content_type
|
104
|
-
dataset = Dataset.new
|
105
|
-
dataset.read uri.chomp.to_s
|
106
|
-
dataset
|
107
|
-
end
|
108
|
-
|
109
|
-
def features
|
110
|
-
features = []
|
111
|
-
@model.subjects(RDF['type'], OT["Feature"]).each do |feature_node|
|
112
|
-
features << @model.object(feature_node, DC["identifier"])#
|
113
|
-
end
|
114
|
-
features
|
115
|
-
end
|
116
|
-
|
117
|
-
def data
|
118
|
-
data = {}
|
119
|
-
@model.subjects(RDF['type'], OT['DataEntry']).each do |data_entry|
|
120
|
-
compound_node = @model.object(data_entry, OT['compound'])
|
121
|
-
compound_uri = @model.object(compound_node, DC['identifier']).to_s
|
122
|
-
@model.find(data_entry, OT['values'], nil) do |s,p,values|
|
123
|
-
feature_node = @model.object values, OT['feature']
|
124
|
-
feature_uri = @model.object(feature_node, DC['identifier']).to_s.sub(/\^\^.*$/,'') # remove XML datatype
|
125
|
-
type = @model.object(values, RDF['type'])
|
126
|
-
if type == OT['FeatureValue']
|
127
|
-
value = @model.object(values, OT['value']).to_s
|
128
|
-
case value.to_s
|
129
|
-
when TRUE_REGEXP # defined in environment.rb
|
130
|
-
value = true
|
131
|
-
when FALSE_REGEXP # defined in environment.rb
|
132
|
-
value = false
|
133
|
-
else
|
134
|
-
LOGGER.warn compound_uri + " has value '" + value.to_s + "' for feature " + feature_uri
|
135
|
-
value = nil
|
136
|
-
end
|
137
|
-
data[compound_uri] = {} unless data[compound_uri]
|
138
|
-
data[compound_uri][feature_uri] = [] unless data[compound_uri][feature_uri]
|
139
|
-
data[compound_uri][feature_uri] << value unless value.nil?
|
140
|
-
elsif type == OT['Tuple']
|
141
|
-
entry = {}
|
142
|
-
data[compound_uri] = {} unless data[compound_uri]
|
143
|
-
data[compound_uri][feature_uri] = [] unless data[compound_uri][feature_uri]
|
144
|
-
@model.find(values, OT['complexValue'],nil) do |s,p,complex_value|
|
145
|
-
name_node = @model.object complex_value, OT['feature']
|
146
|
-
name = @model.object(name_node, DC['title']).to_s
|
147
|
-
value = @model.object(complex_value, OT['value']).to_s
|
148
|
-
v = value.sub(/\^\^.*$/,'') # remove XML datatype
|
149
|
-
v = v.to_f if v.match(/^[\.|\d]+$/) # guess numeric datatype
|
150
|
-
entry[name] = v
|
151
|
-
end
|
152
|
-
data[compound_uri][feature_uri] << entry
|
153
|
-
end
|
154
|
-
end
|
155
|
-
end
|
156
|
-
data
|
157
|
-
end
|
158
|
-
|
159
|
-
def compounds
|
160
|
-
compounds = []
|
161
|
-
@model.subjects(RDF['type'], OT["Compound"]).each do |compound_node|
|
162
|
-
compounds << @model.object(compound_node, DC["identifier"]).to_s
|
163
|
-
end
|
164
|
-
compounds
|
165
|
-
end
|
166
|
-
|
167
|
-
# Delete a dataset
|
168
|
-
def delete
|
169
|
-
resource = RestClient::Resource.new(@uri, :user => @@users[:users].keys[0], :password => @@users[:users].values[0])
|
170
|
-
resource.delete
|
179
|
+
def init_dirty_features(owl)
|
180
|
+
@dirty_features = @features
|
181
|
+
@owl = owl
|
171
182
|
end
|
183
|
+
end
|
172
184
|
|
173
|
-
def to_owl
|
174
|
-
end
|
175
|
-
|
176
|
-
def from_owl
|
177
|
-
end
|
178
|
-
|
179
|
-
=end
|
180
|
-
end
|
181
185
|
|
182
186
|
end
|
data/lib/environment.rb
CHANGED
@@ -40,10 +40,77 @@ if @@config[:database]
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
# mail for error messages
|
44
|
+
load File.join config_dir,"mail.rb" if File.exists?(File.join config_dir,"mail.rb")
|
45
|
+
|
46
|
+
# hack: store sinatra in global var to make url_for and halt methods accessible
|
47
|
+
before {$sinatra = self unless $sinatra}
|
48
|
+
|
49
|
+
class Sinatra::Base
|
50
|
+
# overwriting halt to log halts (!= 202)
|
51
|
+
def halt(*response)
|
52
|
+
LOGGER.error "halt "+response.first.to_s+" "+(response.size>1 ? response[1].to_s : "") if response and response.first and response.first >= 300
|
53
|
+
# orig sinatra code:
|
54
|
+
response = response.first if response.length == 1
|
55
|
+
throw :halt, response
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
43
59
|
# logging
|
60
|
+
class MyLogger < Logger
|
61
|
+
|
62
|
+
def pwd
|
63
|
+
path = Dir.pwd.to_s
|
64
|
+
index = path.rindex(/\//)
|
65
|
+
return path if index==nil
|
66
|
+
path[(index+1)..-1]
|
67
|
+
end
|
68
|
+
|
69
|
+
def trace()
|
70
|
+
lines = caller(0)
|
71
|
+
n = 2
|
72
|
+
line = lines[n]
|
73
|
+
|
74
|
+
while (line =~ /spork.rb/ or line =~ /as_task/ or line =~ /environment.rb/)
|
75
|
+
n += 1
|
76
|
+
line = lines[n]
|
77
|
+
end
|
78
|
+
|
79
|
+
index = line.rindex(/\/.*\.rb/)
|
80
|
+
return line if index==nil
|
81
|
+
line[index..-1]
|
82
|
+
end
|
83
|
+
|
84
|
+
def format(msg)
|
85
|
+
pwd.ljust(18)+" :: "+msg.to_s+" :: "+trace+" :: "+ENV['REMOTE_ADDR'].to_s
|
86
|
+
end
|
87
|
+
|
88
|
+
def debug(msg)
|
89
|
+
super format(msg)
|
90
|
+
end
|
91
|
+
|
92
|
+
def info(msg)
|
93
|
+
super format(msg)
|
94
|
+
end
|
95
|
+
|
96
|
+
def warn(msg)
|
97
|
+
super format(msg)
|
98
|
+
end
|
99
|
+
|
100
|
+
def error(msg)
|
101
|
+
super format(msg)
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
|
44
107
|
logfile = "#{LOG_DIR}/#{ENV["RACK_ENV"]}.log"
|
45
|
-
LOGGER =
|
46
|
-
|
108
|
+
LOGGER = MyLogger.new(logfile,'daily') # daily rotation
|
109
|
+
|
110
|
+
#LOGGER = MyLogger.new(STDOUT)
|
111
|
+
#LOGGER.datetime_format = "%Y-%m-%d %H:%M:%S "
|
112
|
+
|
113
|
+
#LOGGER.level = Logger::DEBUG
|
47
114
|
|
48
115
|
if File.exist?(user_file)
|
49
116
|
@@users = YAML.load_file(user_file)
|
@@ -56,8 +123,7 @@ end
|
|
56
123
|
begin
|
57
124
|
0 < @@users[:users].keys.length
|
58
125
|
rescue
|
59
|
-
|
60
|
-
exit
|
126
|
+
raise "Please edit #{user_file} and restart your application. Create at least one user with password."
|
61
127
|
end
|
62
128
|
|
63
129
|
# RDF namespaces
|
@@ -65,7 +131,12 @@ RDF = Redland::Namespace.new 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
|
|
65
131
|
OWL = Redland::Namespace.new 'http://www.w3.org/2002/07/owl#'
|
66
132
|
DC = Redland::Namespace.new 'http://purl.org/dc/elements/1.1/'
|
67
133
|
OT = Redland::Namespace.new 'http://www.opentox.org/api/1.1#'
|
134
|
+
XML = Redland::Namespace.new 'http://www.w3.org/2001/XMLSchema#'
|
68
135
|
|
69
136
|
# Regular expressions for parsing classification data
|
70
|
-
TRUE_REGEXP = /^(true|active
|
71
|
-
FALSE_REGEXP = /^(false|inactive
|
137
|
+
TRUE_REGEXP = /^(true|active|$1^)/
|
138
|
+
FALSE_REGEXP = /^(false|inactive|$0^)/
|
139
|
+
|
140
|
+
# Task durations
|
141
|
+
DEFAULT_TASK_MAX_DURATION = @@config[:default_task_max_duration]
|
142
|
+
EXTERNAL_TASK_MAX_DURATION = @@config[:external_task_max_duration]
|