ols 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ coverage/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in ols.gemspec
4
+ gemspec
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 0.0.1 2011-04-15
2
+
3
+ * Initial release:
4
+ * Basic wrapper around OLS database
5
+ * Builds tree objects automagically
6
+ * User configurable connection details
data/README.rdoc ADDED
@@ -0,0 +1,117 @@
1
+ = OLS
2
+
3
+ http://github.com/dazoakley/ols
4
+
5
+ OLS provides a simple interface to the EBI's Ontology Lookup Service (http://www.ebi.ac.uk/ontology-lookup/).
6
+ It provides an easy lookup of ontology terms and automagically builds up ontology trees using RubyTree
7
+ (http://rubytree.rubyforge.org/) as a base library.
8
+
9
+ <b>PLEASE NOTE</b>: The current version of this gem requires a local install of the OLS database running on MySQL.
10
+ Please see http://www.ebi.ac.uk/ontology-lookup/databaseExport.do I will update the code in the future
11
+ to run off the soap service.
12
+
13
+ == Install
14
+
15
+ gem install ols
16
+
17
+ == Usage
18
+
19
+ Include the module in your code:
20
+
21
+ require 'rubygems'
22
+ require 'ols'
23
+
24
+ Then, to lookup an ontology term:
25
+
26
+ ont = OLS::OntologyTerm.new('EMAP:3018')
27
+
28
+ This will create a simple tree object for the EMAP term EMAP:3018
29
+
30
+ ont.name # => "EMAP:3018"
31
+ ont.term # => "EMAP:3018"
32
+
33
+ ont.content # => "TS18,nose"
34
+ ont.term_name # => "TS18,nose"
35
+
36
+ Find out about your ontology term
37
+
38
+ ont.is_root? # => false
39
+ ont.is_leaf? # => false
40
+
41
+ <b>NOTE</b>: OntologyTerm's are lazily loaded, so upon initial build the OntologyTerm is just a single node in a
42
+ tree - no parents, no children. See here (note the "Total Nodes Loaded" count):
43
+
44
+ ont.to_s # => "Term: EMAP:3018 Term Name: TS18,nose Root Term?: false Leaf Node?: false Total Nodes Loaded: 1"
45
+
46
+ The tree for the term is built up (parents) and down (children) as it is requested:
47
+
48
+ ont.parentage # => Array of all parent terms (these will be loaded into the tree now)
49
+ ont.children # => Array of all direct child terms (these will also be loaded into the tree now)
50
+ ont.to_s # => "Term: EMAP:3018 Term Name: TS18,nose Root Term?: false Leaf Node?: false Total Nodes Loaded: 4"
51
+
52
+ Alternatively, if you want to force load the tree:
53
+
54
+ ont.buld_tree # => Will load both parents and children into the tree
55
+
56
+ Find out more about your tree:
57
+
58
+ ont.root # => Gives you the root node - in this case: "EMAP:0"
59
+ ont.all_child_terms # => An array of all child ontology terms
60
+ ont.all_child_name # => An array of all child ontology term names
61
+
62
+ For more information on general usage, take a look in the test suite. Also, OLS::OntologyTerm is a child object of
63
+ Tree::TreeNode (from the rubytree gem - http://rubytree.rubyforge.org/) and as such inherits all of its methods.
64
+
65
+ == Database Connection Details
66
+
67
+ The default database connection details are:
68
+
69
+ {
70
+ :database => 'ols',
71
+ :host => '127.0.0.1',
72
+ :port => 3306,
73
+ :user => 'ols',
74
+ :password => 'ols'
75
+ }
76
+
77
+ If your local copy of the OLS database requires different details, simply do the following once in your code
78
+ (substituting in your connection details) before any calls to OLS::OntologyTerm are made:
79
+
80
+ OLS.db_connection_details = {
81
+ :database => 'my_ols',
82
+ :host => 'ols.example.com',
83
+ :port => 3307,
84
+ :user => 'user1',
85
+ :password => 'pass1'
86
+ }
87
+
88
+ == Meta
89
+
90
+ Written by Darren Oakley (daz dot oakley at gmail dot com)
91
+
92
+ http://github.com/dazoakley/ols
93
+
94
+ == License
95
+
96
+ (The MIT License)
97
+
98
+ Copyright (c) 2011 Darren Oakley
99
+
100
+ Permission is hereby granted, free of charge, to any person obtaining
101
+ a copy of this software and associated documentation files (the
102
+ 'Software'), to deal in the Software without restriction, including
103
+ without limitation the rights to use, copy, modify, merge, publish,
104
+ distribute, sublicense, and/or sell copies of the Software, and to
105
+ permit persons to whom the Software is furnished to do so, subject to
106
+ the following conditions:
107
+
108
+ The above copyright notice and this permission notice shall be
109
+ included in all copies or substantial portions of the Software.
110
+
111
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
112
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
113
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
114
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
115
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
116
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
117
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'shoulda'
5
+ require 'rake/testtask'
6
+
7
+ desc 'Run the test suite under /test'
8
+ Rake::TestTask.new do |t|
9
+ t.libs << 'test'
10
+ t.test_files = FileList['test/test*.rb']
11
+ t.verbose = true
12
+ end
data/lib/ols.rb ADDED
@@ -0,0 +1,422 @@
1
+
2
+ require 'rubygems'
3
+ require 'tree'
4
+ require 'sequel'
5
+ require 'mysql2'
6
+ require 'json'
7
+
8
+ # Simple wrapper for interacting with the OLS (Ontology Lookup Service - http://www.ebi.ac.uk/ontology-lookup/)
9
+ # database (created and managed by the EBI). Handles interaction with the service and automagically turns
10
+ # the retieved ontology terms into usable tree stuctures.
11
+ #
12
+ # @author Darren Oakley
13
+ module OLS
14
+
15
+ class << self
16
+ attr_accessor :db_connection_details
17
+
18
+ def ols_db
19
+ @ols_db = connect_to_db() if @ols_db.nil?
20
+ @ols_db
21
+ end
22
+
23
+ private
24
+
25
+ def get_db_connection_details
26
+ defaults = {
27
+ :database => 'ols',
28
+ :host => '127.0.0.1',
29
+ :port => 3306,
30
+ :user => 'ols',
31
+ :password => 'ols'
32
+ }
33
+
34
+ if !OLS.db_connection_details.nil? and OLS.db_connection_details.is_a? Hash
35
+ defaults.merge!(OLS.db_connection_details)
36
+ end
37
+
38
+ defaults
39
+ end
40
+
41
+ def connect_to_db
42
+ params = { :adapter => 'mysql2', :encoding => 'utf8' }.merge(get_db_connection_details)
43
+ Sequel.connect(params)
44
+ end
45
+ end
46
+
47
+ # Error class for when we can't find a given ontology term.
48
+ class OntologyTermNotFoundError < StandardError; end
49
+
50
+ # Class representing an ontology term as part of a tree structure. Uses the Tree::TreeNode (rubytree)
51
+ # gem as a base class.
52
+ class OntologyTerm < Tree::TreeNode
53
+ attr_accessor :already_fetched_parents, :already_fetched_children
54
+
55
+ attr_accessor :root_term, :leaf_node
56
+ attr_writer :all_child_terms, :all_child_names
57
+ protected :root_term, :leaf_node
58
+
59
+ # @param [String] name The ontology term (id) i.e. GO:00032
60
+ # @param [String] content The ontology term name/description - optional this will be looked up in the OLS database
61
+ def initialize( name, content=nil )
62
+ super
63
+
64
+ @already_fetched_parents = false
65
+ @already_fetched_children = false
66
+ @root_term = false
67
+ @leaf_node = false
68
+
69
+ @all_child_terms = nil
70
+ @all_child_names = nil
71
+
72
+ get_term_details if @content.nil? or @content.empty?
73
+ end
74
+
75
+ # Override to ensure compatibility with Tree::TreeNode.
76
+ #
77
+ # @return [String] The ontology term (id) i.e. GO00032
78
+ def term
79
+ self.name
80
+ end
81
+
82
+ # Override to ensure compatibility with Tree::TreeNode.
83
+ #
84
+ # @return [String] The ontology term name/description
85
+ def term_name
86
+ self.content
87
+ end
88
+
89
+ # Returns +true+ if the receiver is a root node. Note that
90
+ # orphaned children will also be reported as root nodes.
91
+ #
92
+ # @return [Boolean] +true+ if this is a root node.
93
+ def is_root?
94
+ @root_term
95
+ end
96
+
97
+ # Returns +true+ if the receiver node is a 'leaf' - i.e., one without
98
+ # any children.
99
+ #
100
+ # @return [Boolean] +true+ if this is a leaf node.
101
+ def is_leaf?
102
+ @leaf_node
103
+ end
104
+
105
+ # Returns string representation of the receiver node.
106
+ # This method is primarily meant for debugging purposes.
107
+ #
108
+ # @return [String] A string representation of the node.
109
+ def to_s
110
+ "Term: #{@name}" +
111
+ " Term Name: " + (@content || "<Empty>") +
112
+ " Root Term?: #{is_root?}" +
113
+ " Leaf Node?: #{is_leaf?} " +
114
+ " Total Nodes Loaded: #{size()}"
115
+ end
116
+
117
+ # Returns an array of parent OntologyTerm objects.
118
+ #
119
+ # @return [Array] An array of parent OntologyTerm objects
120
+ def parentage
121
+ get_parents
122
+ super
123
+ end
124
+
125
+ # Returns the children of this term as a tree. Will include the current term
126
+ # as the 'root' of the tree.
127
+ #
128
+ # @return [OntologyTerm] The children of this term as a tree. Will include the current term as the 'root' of the tree.
129
+ def child_tree
130
+ build_tree
131
+ child_tree = self.clone
132
+ child_tree.remove_from_parent!
133
+ child_tree
134
+ end
135
+
136
+ # Returns an array of the direct children (OntologyTerm objects) of this term.
137
+ #
138
+ # @return [Array] An array of the direct children (OntologyTerm objects) of this term.
139
+ def children
140
+ get_children
141
+ super
142
+ end
143
+
144
+ # Returns a flat array containing all the possible child terms
145
+ # for this given ontology term.
146
+ #
147
+ # @return [Array] An array of all possible child terms (Strings) for this given ontology term
148
+ def all_child_terms
149
+ get_all_child_lists
150
+ return @all_child_terms
151
+ end
152
+
153
+ # Returns a flat array containing all the possible child term
154
+ # names for this given ontology term.
155
+ #
156
+ # @return [Array] A flat array containing all the possible child term names (Strings) for this given ontology term
157
+ def all_child_names
158
+ get_all_child_lists
159
+ return @all_child_names
160
+ end
161
+
162
+ # Function to force the OntologyTerm object to flesh out it's structure
163
+ # from the OLS database. By default OntologyTerm objects are lazy and will
164
+ # only retieve child data one level below themselves, so this is used to
165
+ # recursivley flesh out a full tree.
166
+ def build_tree
167
+ get_parents
168
+ get_children( self, true )
169
+ end
170
+
171
+ # Creates a JSON representation of this node including all it's children. This requires the JSON gem to be
172
+ # available, or else the operation fails with a warning message.
173
+ #
174
+ # @return The JSON representation of this subtree.
175
+ #
176
+ # @see {OntologyTerm#json_create}
177
+ def to_json(*a)
178
+ json_hash = {
179
+ "name" => name,
180
+ "content" => content,
181
+ "root_term" => @root_term,
182
+ "leaf_node" => @leaf_node,
183
+ "all_child_terms" => @all_child_terms,
184
+ "all_child_names" => @all_child_names,
185
+ JSON.create_id => self.class.name
186
+ }
187
+
188
+ if has_children?
189
+ json_hash["children"] = children
190
+ end
191
+
192
+ return JSON.generate( json_hash, :max_nesting => false )
193
+ end
194
+
195
+ # Class level function to build an OntologyTerm object from a serialized JSON hash
196
+ #
197
+ # @example
198
+ # emap = JSON.parse( File.read("emap.json"), :max_nesting => false )
199
+ #
200
+ # @param [Hash] json_hash The parsed JSON hash to de-serialize
201
+ # @return [OntologyTerm] The de-serialized object
202
+ def self.json_create(json_hash)
203
+ node = new(json_hash["name"], json_hash["content"])
204
+ node.already_fetched_children = true if json_hash["children"]
205
+
206
+ node.root_term = true if json_hash["root_term"]
207
+ node.leaf_node = true if json_hash["leaf_node"]
208
+ node.all_child_terms = json_hash["all_child_terms"]
209
+ node.all_child_names = json_hash["all_child_names"]
210
+
211
+ json_hash["children"].each do |child|
212
+ child.already_fetched_parents = true
213
+ child.already_fetched_children = true if child.has_children?
214
+ node << child
215
+ end if json_hash["children"]
216
+
217
+ return node
218
+ end
219
+
220
+ # Method to set the parent node for the receiver node.
221
+ # This method should *NOT* be invoked by client code.
222
+ #
223
+ # @param [OntologyTerm] parent The parent node.
224
+ # @return [OntologyTerm] The parent node.
225
+ def parent=(parent) # :nodoc:
226
+ @parent = parent
227
+ end
228
+
229
+ # Recursive function to query the OLS database and collect all of
230
+ # the parent objects and insert them into @parents in the correct
231
+ # order.
232
+ def get_parents( node=self )
233
+ unless @already_fetched_parents
234
+ sql = <<-SQL
235
+ select
236
+ subject_term.identifier as child_identifier,
237
+ subject_term.term_name as child_term,
238
+ predicate_term.term_name as relation,
239
+ object_term.identifier as parent_identifier,
240
+ object_term.term_name as parent_term,
241
+ object_term.is_root_term as parent_is_root
242
+ from
243
+ term_relationship tr
244
+ join term as subject_term on tr.subject_term_pk = subject_term.term_pk
245
+ join term as predicate_term on tr.predicate_term_pk = predicate_term.term_pk
246
+ join term as object_term on tr.object_term_pk = object_term.term_pk
247
+ where
248
+ predicate_term.term_name in ('part_of','is_a','develops_from')
249
+ and subject_term.identifier = ?
250
+ SQL
251
+
252
+ OLS.ols_db[ sql, node.term ].each do |row|
253
+ parent = OntologyTerm.new( row[:parent_identifier], row[:parent_term] )
254
+ parent.root_term = true if row[:parent_is_root].to_i == 1
255
+ parent << node
256
+ get_parents( parent )
257
+ end
258
+
259
+ @already_fetched_parents = true
260
+ end
261
+ end
262
+
263
+ # Recursive function to query the OLS database and collect all of
264
+ # the child objects and build up a tree of OntologyTerm's.
265
+ def get_children( node=self, recursively=false )
266
+ unless @already_fetched_children or node.has_children?
267
+ sql = <<-SQL
268
+ select
269
+ subject_term.identifier as child_identifier,
270
+ subject_term.term_name as child_term,
271
+ subject_term.is_leaf as child_is_leaf,
272
+ predicate_term.term_name as relation,
273
+ object_term.identifier as parent_identifier,
274
+ object_term.term_name as parent_term
275
+ from
276
+ term_relationship tr
277
+ join term as subject_term on tr.subject_term_pk = subject_term.term_pk
278
+ join term as predicate_term on tr.predicate_term_pk = predicate_term.term_pk
279
+ join term as object_term on tr.object_term_pk = object_term.term_pk
280
+ where
281
+ predicate_term.term_name in ('part_of','is_a','develops_from')
282
+ and object_term.identifier = ?
283
+ SQL
284
+
285
+ OLS.ols_db[sql,node.term].each do |row|
286
+ child = OntologyTerm.new( row[:child_identifier], row[:child_term] )
287
+ child.leaf_node = true if row[:child_is_leaf].to_i == 1
288
+ child.get_children( child, true ) if recursively and !child.is_leaf?
289
+ node << child
290
+ end
291
+
292
+ @already_fetched_children = true
293
+ end
294
+ end
295
+
296
+ # Returns a copy of the receiver node, with its parent and children links removed.
297
+ # The original node remains attached to its tree.
298
+ #
299
+ # @return [OntologyTerm] A copy of the receiver node.
300
+ def detached_copy
301
+ copy = OLS::OntologyTerm.new(@name, @content ? @content.clone : nil)
302
+ copy.root_term = @root_term
303
+ copy.leaf_node = @leaf_node
304
+ return copy
305
+ end
306
+
307
+ # Function that merges one OntologyTerm tree into another.
308
+ #
309
+ # @param [OntologyTerm] tree The tree that is to be merged into self
310
+ # @return [OntologyTerm] The merged tree
311
+ def merge( tree )
312
+ unless tree.is_a?(OLS::OntologyTerm)
313
+ raise TypeError, "You can only merge in another OntologyTerm tree!"
314
+ end
315
+
316
+ unless self.root.name == tree.root.name
317
+ raise ArgumentError, "Unable to merge trees as they do not share the same root!"
318
+ end
319
+
320
+ new_tree = merge_subtrees( self.root, tree.root )
321
+ end
322
+
323
+ private
324
+
325
+ # Utility function to recursivley merge two subtrees
326
+ #
327
+ # @param [OntologyTerm] tree1 The target tree to merge into
328
+ # @param [OntologyTerm] tree2 The donor tree (that will be merged into target)
329
+ def merge_subtrees( tree1, tree2 )
330
+ names1 = tree1.has_children? ? tree1.children.map { |child| child.name } : []
331
+ names2 = tree2.has_children? ? tree2.children.map { |child| child.name } : []
332
+
333
+ names_to_merge = names2 - names1
334
+ names_to_merge.each do |name|
335
+ tree1 << tree2[name].detached_subtree_copy
336
+ end
337
+
338
+ tree1.children.each do |child|
339
+ unless tree2[child.name].nil?
340
+ merge_subtrees( child, tree2[child.name] )
341
+ end
342
+ end
343
+
344
+ return tree1
345
+ end
346
+
347
+ # Helper function to query the OLS database and grab the full
348
+ # details of the ontology term.
349
+ def get_term_details
350
+ # This query ensures we look at the most recent fully loaded ontologies
351
+ sql = <<-SQL
352
+ select term.*
353
+ from term
354
+ join ontology on ontology.ontology_id = term.ontology_id
355
+ where term.identifier = ?
356
+ order by ontology.fully_loaded desc, ontology.load_date asc
357
+ SQL
358
+
359
+ term_set = OLS.ols_db[ sql, @name ].all()
360
+
361
+ if term_set.size == 0
362
+ get_term_from_synonym
363
+ else
364
+ subject = term_set.first
365
+ @content = subject[:term_name]
366
+ @term_pk = subject[:term_pk]
367
+ @ontology_id = subject[:ontology_id]
368
+ @root_term = true if subject[:is_root_term].to_i == 1
369
+ @leaf_node = true if subject[:is_leaf].to_i == 1
370
+ end
371
+ end
372
+
373
+ # Helper function to try to find an ontology term via a synonym.
374
+ def get_term_from_synonym
375
+ sql = <<-SQL
376
+ select term.*
377
+ from term
378
+ join ontology on ontology.ontology_id = term.ontology_id
379
+ join term_synonym on term.term_pk = term_synonym.term_pk
380
+ where term_synonym.synonym_value = ?
381
+ order by ontology.fully_loaded desc, ontology.load_date asc
382
+ SQL
383
+
384
+ term_set = OLS.ols_db[ sql, @name ].all()
385
+
386
+ if term_set.size == 0
387
+ raise OLS::OntologyTermNotFoundError, "Unable to find the term '#{@name}' in the OLS database."
388
+ end
389
+
390
+ subject = term_set.first
391
+ @name = subject[:identifier]
392
+ @content = subject[:term_name]
393
+ @term_pk = subject[:term_pk]
394
+ @ontology_id = subject[:ontology_id]
395
+ @root_term = true if subject[:is_root_term].to_i == 1
396
+ @leaf_node = true if subject[:is_leaf].to_i == 1
397
+ end
398
+
399
+ # Helper function to produce the flat lists of all the child
400
+ # terms and names.
401
+ def get_all_child_lists
402
+ get_children
403
+
404
+ if @all_child_terms.nil? and @all_child_names.nil?
405
+ @all_child_terms = []
406
+ @all_child_names = []
407
+
408
+ self.children.each do |child|
409
+ @all_child_terms.push( child.term )
410
+ @all_child_terms.push( child.all_child_terms )
411
+ @all_child_names.push( child.term_name )
412
+ @all_child_names.push( child.all_child_names )
413
+ end
414
+
415
+ @all_child_terms = @all_child_terms.flatten.uniq
416
+ @all_child_names = @all_child_names.flatten.uniq
417
+ end
418
+ end
419
+
420
+ end
421
+
422
+ end
@@ -0,0 +1,3 @@
1
+ module OLS
2
+ VERSION = "0.0.1"
3
+ end
data/ols.gemspec ADDED
@@ -0,0 +1,39 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "ols/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ols"
7
+ s.version = OLS::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Darren Oakley"]
10
+ s.email = ["daz.oakley@gmail.com"]
11
+ s.homepage = "https://github.com/dazoakley/ols"
12
+ s.summary = %q{A simple wrapper around a local copy of the OLS database}
13
+ s.description = %q{
14
+ OLS provides a simple interface to the EBI's Ontology Lookup Service (http://www.ebi.ac.uk/ontology-lookup/).
15
+ It provides an easy lookup of ontology terms and automagically builds up ontology trees using RubyTree
16
+ (http://rubytree.rubyforge.org/) as a base library.
17
+
18
+ PLEASE NOTE: The current version of this gem requires a local install of the OLS database running on MySQL.
19
+ Please see http://www.ebi.ac.uk/ontology-lookup/databaseExport.do I will update the code in the future
20
+ to run off the soap service.
21
+ }
22
+
23
+ s.rubyforge_project = "ols"
24
+
25
+ s.files = `git ls-files`.split("\n")
26
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
28
+ s.require_paths = ["lib"]
29
+
30
+ s.add_dependency "rubytree"
31
+ s.add_dependency "sequel"
32
+ s.add_dependency "mysql2"
33
+ s.add_dependency "json"
34
+
35
+ s.add_development_dependency "rake"
36
+ s.add_development_dependency "shoulda"
37
+ s.add_development_dependency "simplecov"
38
+ s.add_development_dependency "simplecov-rcov"
39
+ end
@@ -0,0 +1,34 @@
1
+ # Add the lib directory to the search path
2
+ $:.unshift( "#{File.expand_path(File.dirname(__FILE__))}/../lib" )
3
+
4
+ require 'rubygems'
5
+
6
+ # Set-up SimpleCov (code coverage tool for Ruby 1.9)
7
+ if /^1.9/ === RUBY_VERSION
8
+ begin
9
+ require 'simplecov'
10
+ require 'simplecov-rcov'
11
+
12
+ class SimpleCov::Formatter::MergedFormatter
13
+ def format(result)
14
+ SimpleCov::Formatter::HTMLFormatter.new.format(result)
15
+ SimpleCov::Formatter::RcovFormatter.new.format(result)
16
+ end
17
+ end
18
+
19
+ SimpleCov.formatter = SimpleCov::Formatter::MergedFormatter
20
+ SimpleCov.start
21
+ rescue LoadError
22
+ puts "[ERROR] Unable to load 'simplecov' - please run 'bundle install'"
23
+ end
24
+ end
25
+
26
+ require 'shoulda'
27
+ require 'ols'
28
+
29
+ OLS.db_connection_details = {
30
+ :port => 13306,
31
+ :database => 'htgt_ols',
32
+ :user => 'htgt',
33
+ :password => 'htgt'
34
+ }
data/test/test_ols.rb ADDED
@@ -0,0 +1,124 @@
1
+ require 'test_helper'
2
+
3
+ class OLSTest < Test::Unit::TestCase
4
+ include OLS
5
+
6
+ context "An OntologyTerm object" do
7
+ setup do
8
+ @emap_id = "EMAP:3018"
9
+ @emap_name = "TS18,nose"
10
+ @ont = OntologyTerm.new(@emap_id)
11
+ end
12
+
13
+ should "have basic attributes" do
14
+ assert_equal( @emap_id, @ont.name, "OntologyTerm.name does not equal '#{@emap_id}'." )
15
+ assert_equal( @emap_id, @ont.term, "OntologyTerm.term does not equal '#{@emap_id}'." )
16
+
17
+ assert_equal( @emap_name, @ont.content, "OntologyTerm.content does not equal '#{@emap_name}'." )
18
+ assert_equal( @emap_name, @ont.term_name, "OntologyTerm.term_name does not equal '#{@emap_name}'." )
19
+
20
+ assert_equal( false, @ont.term_name.nil?, "The OntologyTerm.term_name is nil." )
21
+ assert_equal( false, @ont.content.nil?, "The OntologyTerm.term_name is nil." )
22
+ end
23
+
24
+ should "raise appropriate errors" do
25
+ assert_raise(OntologyTermNotFoundError) { OntologyTerm.new("FLIBBLE:5") }
26
+ end
27
+
28
+ should "be able to represent itself as a String" do
29
+ string = @ont.to_s
30
+
31
+ assert( string.include?('Term Name'), "OntologyTerm.to_s does not include 'Term Name'." )
32
+ assert( string.include?(@ont.content), "OntologyTerm.to_s does not include '@content'." )
33
+ assert( string.include?('Root Term?'), "OntologyTerm.to_s does not include 'Root Term?'." )
34
+ assert( string.include?('Leaf Node?'), "OntologyTerm.to_s does not include 'Leaf Node?'." )
35
+ end
36
+
37
+ should "respond correctly to the .parentage method" do
38
+ assert( @ont.parentage.is_a?(Array), "OntologyTerm.parentage is not an Array when we have parents." )
39
+ assert( @ont.parentage[0].is_a?(OntologyTerm), "OntologyTerm.parentage[0] does not return an OntologyTerm tree." )
40
+ assert_equal( 4, @ont.parentage.size, "OntologyTerm.parentage is not returning the correct number of entries (we expect 4 for #{@emap_id})." )
41
+ end
42
+
43
+ should "be able to generate its child tree" do
44
+ assert( @ont.child_tree.is_a?(OntologyTerm), "OntologyTerm.child_tree does not return an OntologyTerm tree." )
45
+ assert_equal( @ont.term, @ont.child_tree.term, "OntologyTerm.child_tree.root is equal to self." )
46
+ end
47
+
48
+ should "respond correctly to the .children method" do
49
+ assert( @ont.children.is_a?(Array), "OntologyTerm.children is not an Array when we have children." )
50
+ assert( @ont.children[0].is_a?(OntologyTerm), "OntologyTerm.children[0] does not return an OntologyTerm tree." )
51
+ assert_equal( 3, @ont.children.size, "OntologyTerm.children is not returning the correct number of entries (we expect 3 direct children for #{@emap_id})." )
52
+ end
53
+
54
+ should "be able to generate a flat list of all child terms/names" do
55
+ assert( @ont.all_child_terms.is_a?(Array), "OntologyTerm.all_child_terms is not an Array." )
56
+ assert( @ont.all_child_terms[0].is_a?(String), "OntologyTerm.all_child_terms[0] is not an String." )
57
+ assert_equal( 14, @ont.all_child_terms.size, "OntologyTerm.all_child_terms is not returning the correct number of entries (we expect 14 children for #{@emap_id})." )
58
+
59
+ assert( @ont.all_child_names.is_a?(Array), "OntologyTerm.all_child_names is not an Array." )
60
+ assert( @ont.all_child_names[0].is_a?(String), "OntologyTerm.all_child_names[0] is not an String." )
61
+ assert_equal( 14, @ont.all_child_names.size, "OntologyTerm.all_child_names is not returning the correct number of entries (we expect 14 children for #{@emap_id})." )
62
+
63
+ assert_equal( @ont.all_child_terms.size, @ont.all_child_names.size, "OntologyTerm.all_child_terms and OntologyTerm.all_child_names do not produce an array of the same size." )
64
+ end
65
+
66
+ should "be able to locate ontology terms via synonyms" do
67
+ go_id = 'GO:0007242'
68
+ ont = OntologyTerm.new(go_id)
69
+
70
+ assert_equal( 'GO:0023034', ont.term, "A synonym search for GO:0007242 has not found GO:0023034." )
71
+ assert_equal( 'intracellular signaling pathway', ont.term_name, "A synonym search for GO:0007242 has not found 'intracellular signaling pathway'." )
72
+ end
73
+
74
+ should "be able to serialize/deserialize itself as a JSON string" do
75
+ @ont.build_tree()
76
+
77
+ json_string = nil
78
+ assert_nothing_raised(Exception) { json_string = @ont.to_json }
79
+ assert( json_string.is_a?(String) )
80
+
81
+ duplicate = nil
82
+ assert_nothing_raised(Exception) { duplicate = JSON.parse(json_string) }
83
+ assert( duplicate.is_a?(OntologyTerm) )
84
+ assert_equal( @ont.term, duplicate.term )
85
+ assert_equal( @ont.term_name, duplicate.term_name )
86
+ assert_equal( @ont.is_root?, duplicate.is_root? )
87
+ assert_equal( @ont.is_leaf?, duplicate.is_leaf? )
88
+ end
89
+
90
+ should "be able to produce a detached copy of itself" do
91
+ @ont.build_tree()
92
+ duplicate = @ont.detached_copy
93
+
94
+ assert_equal( @ont.term, duplicate.term )
95
+ assert_equal( @ont.term_name, duplicate.term_name )
96
+ assert_equal( @ont.is_root?, duplicate.is_root? )
97
+ assert_equal( @ont.is_leaf?, duplicate.is_leaf? )
98
+
99
+ assert_equal( false, duplicate.send(:already_fetched_parents) )
100
+ assert_equal( false, duplicate.send(:already_fetched_children) )
101
+ end
102
+
103
+ should "be able to merge two ontology trees" do
104
+ @ont2 = OntologyTerm.new('EMAP:3003')
105
+
106
+ @ont.build_tree
107
+ @ont2.build_tree
108
+
109
+ merged_tree = @ont.merge(@ont2)
110
+
111
+ assert( merged_tree['EMAP:2636']['EMAP:2822']['EMAP:2987'].is_a?(OntologyTerm) )
112
+ assert_equal( 2, merged_tree['EMAP:2636']['EMAP:2822']['EMAP:2987'].children.size )
113
+ assert_equal( 34, merged_tree.size )
114
+
115
+ another_ont = OntologyTerm.new('GO:0023034')
116
+ yet_another_ont = OntologyTerm.new('EMAP:3003')
117
+ another_ont.build_tree
118
+ yet_another_ont.build_tree
119
+
120
+ assert_raise(ArgumentError) { foo = another_ont.merge(yet_another_ont) }
121
+ assert_raise(TypeError) { bar = another_ont.merge('EMAP:3003') }
122
+ end
123
+ end
124
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ols
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Darren Oakley
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-04-15 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rubytree
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: sequel
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: mysql2
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :runtime
47
+ prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: json
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: rake
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: shoulda
73
+ requirement: &id006 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: simplecov
84
+ requirement: &id007 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
94
+ name: simplecov-rcov
95
+ requirement: &id008 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: *id008
104
+ description: "\n OLS provides a simple interface to the EBI's Ontology Lookup Service (http://www.ebi.ac.uk/ontology-lookup/). \n It provides an easy lookup of ontology terms and automagically builds up ontology trees using RubyTree \n (http://rubytree.rubyforge.org/) as a base library.\n\n PLEASE NOTE: The current version of this gem requires a local install of the OLS database running on MySQL. \n Please see http://www.ebi.ac.uk/ontology-lookup/databaseExport.do I will update the code in the future \n to run off the soap service.\n "
105
+ email:
106
+ - daz.oakley@gmail.com
107
+ executables: []
108
+
109
+ extensions: []
110
+
111
+ extra_rdoc_files: []
112
+
113
+ files:
114
+ - .gitignore
115
+ - Gemfile
116
+ - History.txt
117
+ - README.rdoc
118
+ - Rakefile
119
+ - lib/ols.rb
120
+ - lib/ols/version.rb
121
+ - ols.gemspec
122
+ - test/test_helper.rb
123
+ - test/test_ols.rb
124
+ has_rdoc: true
125
+ homepage: https://github.com/dazoakley/ols
126
+ licenses: []
127
+
128
+ post_install_message:
129
+ rdoc_options: []
130
+
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ hash: -2283321119041692548
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ hash: -2283321119041692548
148
+ segments:
149
+ - 0
150
+ version: "0"
151
+ requirements: []
152
+
153
+ rubyforge_project: ols
154
+ rubygems_version: 1.6.2
155
+ signing_key:
156
+ specification_version: 3
157
+ summary: A simple wrapper around a local copy of the OLS database
158
+ test_files:
159
+ - test/test_helper.rb
160
+ - test/test_ols.rb