Class: OLS::Term

Inherits:
Object
  • Object
show all
Defined in:
lib/ols/term.rb

Overview

Class representing an ontology term

Author:

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(term_id, term_name, graph = nil) ⇒ Term

Creates a new OLS::Term object

Parameters:

  • term_id (String)

    The ontology term id

  • term_name (String)

    The ontology term name

Raises:

  • (ArgumentError)


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/ols/term.rb', line 15

def initialize(term_id,term_name,graph=nil)
  raise ArgumentError, "term_id cannot be empty/nil" if term_id.nil? || term_id =~ /^\s$/
  raise ArgumentError, "term_name cannot be empty/nil" if term_name.nil? || term_name =~ /^\s$/

  @term_id   = term_id
  @term_name = term_name

  @already_fetched_parents  = false
  @already_fetched_children = false
  @already_fetched_metadata = false

  if graph.nil?
    @graph = OLS::Graph.new
    @graph.add_to_graph(self)
  else
    @graph = graph
  end
end

Instance Attribute Details

#term_idObject (readonly)

Returns the value of attribute term_id.



9
10
11
# File 'lib/ols/term.rb', line 9

def term_id
  @term_id
end

#term_nameObject (readonly)

Returns the value of attribute term_name.



9
10
11
# File 'lib/ols/term.rb', line 9

def term_name
  @term_name
end

Instance Method Details

#[](term_id) ⇒ OLS::Term

Convenience method for accessing specific child terms.

Parameters:

  • term_id (String)

    The term_id for the child you wish to access

Returns:



255
256
257
258
259
260
261
# File 'lib/ols/term.rb', line 255

def [](term_id)
  children_as_a_hash = {}
  self.children.each do |child|
    children_as_a_hash[child.term_id] = child
  end
  children_as_a_hash[term_id]
end

#all_child_idsArray Also known as: all_child_term_ids

Returns an array of all child term_ids for this ontology term (all the way down to the bottom of the ontology). The array is NOT guarenteed to come out in any specific order whatsoever.

Returns:

  • (Array)

    An array of ontology term_ids



286
287
288
# File 'lib/ols/term.rb', line 286

def all_child_ids
  all_children.map(&:term_id)
end

#all_child_namesArray Also known as: all_child_term_names

Returns an array of all child term_names for this ontology term (all the way down to the bottom of the ontology). The array is NOT guarenteed to come out in any specific order whatsoever.

Returns:

  • (Array)

    An array of ontology term_names



295
296
297
# File 'lib/ols/term.rb', line 295

def all_child_names
  all_children.map(&:term_name)
end

#all_childrenArray

Returns an array of all child term objects for this ontology term (all the way down to the bottom of the ontology). The array is NOT guarenteed to come out in any specific order whatsoever.

Returns:

  • (Array)

    An array of OLS::Term objects



268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/ols/term.rb', line 268

def all_children
  return [] if is_leaf?

  children_array = []
  prev_children = self.children
  while ( !prev_children.empty? )
    children_array << prev_children
    prev_children = prev_children.map(&:children).flatten
  end

  children_array.flatten.uniq
end

#all_parent_idsArray Also known as: all_parent_term_ids

Returns an array of all parent term_ids for this ontology term (all the way to the top of the ontology). The array is ordered with the root term first and the most direct parent(s) last. Duplicates are also filtered out.

Returns:

  • (Array)

    An array of ontology term_ids



184
185
186
# File 'lib/ols/term.rb', line 184

def all_parent_ids
  all_parents.map(&:term_id)
end

#all_parent_namesArray Also known as: all_parent_term_names

Returns an array of all parent term_names for this ontology term (all the way to the top of the ontology). The array is ordered with the root term first and the most direct parent last. Duplicates are also filtered out.

Returns:

  • (Array)

    An array of ontology term_names



194
195
196
# File 'lib/ols/term.rb', line 194

def all_parent_names
  all_parents.map(&:term_name)
end

#all_parentsArray

Returns an array of all parent term objects for this ontology term (all the way to the top of the ontology). The array is ordered with the root term first and the most direct parent(s) last.

Returns:

  • (Array)

    An array of OLS::Term objects



165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/ols/term.rb', line 165

def all_parents
  return [] if is_root?

  parentage_array = []
  prev_parents = self.parents
  while ( !prev_parents.empty? )
    parentage_array << prev_parents
    prev_parents = prev_parents.map(&:parents).flatten
  end

  parentage_array.reverse.flatten.uniq
end

#children(skip_fetch = false) ⇒ Array

Returns the child terms for this ontology term.

Returns:

  • (Array)

    An array of child OLS::Term objects



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/ols/term.rb', line 204

def children(skip_fetch=false)
  unless @already_fetched_children || skip_fetch
    # puts "--- REQUESTING CHILDREN (#{self.term_id}) ---"
    response = OLS.request(:get_term_children) { soap.body = { :termId => self.term_id, :distance => 1, :relationTypes => [1,2,3,4,5] } }
    unless response.nil?
      if response[:item].is_a? Array
        response[:item].each do |term|
          child = self.find_in_graph(term[:key]) || OLS::Term.new(term[:key],term[:value],@graph)
          self.add_child(child)
        end
      else
        term = response[:item]
        child = self.find_in_graph(term[:key]) || OLS::Term.new(term[:key],term[:value],@graph)
        self.add_child(child)
      end
    end

    @already_fetched_children = true
  end

  @graph[term_id][:children].map{ |child_id| self.find_in_graph(child_id) }
end

#children_idsArray Also known as: children_term_ids

Returns the term_ids for the direct children of this term.

Returns:

  • (Array)

    The term_ids for the direct children of this term



230
231
232
# File 'lib/ols/term.rb', line 230

def children_ids
  children.map(&:term_id)
end

#children_namesArray Also known as: children_term_names

Returns the term_names for the direct children of this term.

Returns:

  • (Array)

    The term_names for the direct children of this term



237
238
239
# File 'lib/ols/term.rb', line 237

def children_names
  children.map(&:term_name)
end

#definitionString

The ontology term definition

Returns:

  • (String)

    The ontology term definition



64
65
66
67
# File 'lib/ols/term.rb', line 64

def definition
  
  @definition
end

#depthNumber Also known as: level

Returns depth of this term in its ontology graph. Depth of a node is defined as:

Depth

Length of the terms path to its root. Depth of a root term is zero.

If this term has multiple parents (and more than one route through the graph to the root node) we will return the value for the shortest distance through the graph.

Returns:

  • (Number)

    Depth of this node.

Since:

  • 0.3.4



101
102
103
104
# File 'lib/ols/term.rb', line 101

def depth
  return 0 if self.is_root?
  1 + parents.map(&:depth).sort.first
end

#focus_graphObject

Flesh out and/or focus the ontology graph around this term.

This will fetch all children and parents for this term, and will also trick each parent/child object into thinking the ontology graph is fully formed so no further requests to OLS will be made (to further flesh out the graph). It will also cut down a much larger ontology graph to just focus on the parents/descendants of this term.

NOTE: This method does not affect self. It returns a completley new OLS::Term object containing a completley new internal OLS::Graph. Use #focus_graph! if you wish to cut down the existing graph.

i.e. This allows us to do the following

e = OLS.find_by_id('EMAP:0')
copy = e['EMAP:2636']['EMAP:2822']['EMAP:2987']['EMAP:3018'].focus_graph
copy.root.print_graph

gives:

* EMAP:0
    |---+ EMAP:2636
        |---+ EMAP:2822
            |---+ EMAP:2987
                |---+ EMAP:3018
                    |---+ EMAP:3022
                        |---+ EMAP:3023
                            |---+ EMAP:3024
                                |---> EMAP:3025
                                |---> EMAP:3026
                            |---+ EMAP:3027
                                |---> EMAP:3029
                                |---> EMAP:3028
                            |---+ EMAP:3030
                                |---> EMAP:3031
                                |---> EMAP:3032
                    |---> EMAP:3019
                    |---+ EMAP:3020
                        |---> EMAP:3021

See Also:



402
403
404
405
406
# File 'lib/ols/term.rb', line 402

def focus_graph
  copy = self.dup
  copy.really_focus_graph_around_term!
  copy
end

#focus_graph!Object

Flesh out and/or focus the ontology graph around this term.

This will fetch all children and parents for this term, and will also trick each parent/child object into thinking the ontology graph is fully formed so no further requests to OLS will be made (to further flesh out the graph). It will also cut down a much larger ontology graph to just focus on the parents/descendants of this term.

NOTE: This method will totally clobber the existing ontology graph that this term is part of by removing any term and relationship that is not supposed to be part of this focused graph. Use #focus_graph to pull out a copy and be non-destructive.

i.e. This allows us to do the following

e = OLS.find_by_id('EMAP:3018')
e.focus_graph!
e.root.print_graph

gives:

* EMAP:0
    |---+ EMAP:2636
        |---+ EMAP:2822
            |---+ EMAP:2987
                |---+ EMAP:3018
                    |---+ EMAP:3022
                        |---+ EMAP:3023
                            |---+ EMAP:3024
                                |---> EMAP:3025
                                |---> EMAP:3026
                            |---+ EMAP:3027
                                |---> EMAP:3029
                                |---> EMAP:3028
                            |---+ EMAP:3030
                                |---> EMAP:3031
                                |---> EMAP:3032
                    |---> EMAP:3019
                    |---+ EMAP:3020
                        |---> EMAP:3021

*ALSO NOTE:* without e.focus_graph!, in this case it would print the complete EMAP graph (>13,000 terms).

See Also:



359
360
361
# File 'lib/ols/term.rb', line 359

def focus_graph!
  self.really_focus_graph_around_term!
end

#has_children?Boolean

Returns true if the ontology term has any children.

Returns:

  • (Boolean)

    true/false depending on if this term has children or not…



247
248
249
# File 'lib/ols/term.rb', line 247

def has_children?
  !self.children.empty?
end

#initialize_copy(source) ⇒ Object

Object function used by .clone and .dup to create copies of OLS::Term objects.



35
36
37
38
# File 'lib/ols/term.rb', line 35

def initialize_copy(source)
  super
  @graph = source.graph.dup
end

#is_leaf?Boolean

Is this a leaf node?

Returns:

  • (Boolean)

    true/false depending on if this is a leaf node or not…



50
51
52
# File 'lib/ols/term.rb', line 50

def is_leaf?
  self.children.empty?
end

#is_obsolete?Boolean

Is this ontology term obsolete?

Returns:

  • (Boolean)

    true/false depending on if this term is obsolete or not…



57
58
59
# File 'lib/ols/term.rb', line 57

def is_obsolete?
  @is_obsolete ||= OLS.request(:is_obsolete) { soap.body = { :termId => self.term_id } }
end

#is_root?Boolean

Is this a root node?

Returns:

  • (Boolean)

    true/false depending on if this is a root node or not…



43
44
45
# File 'lib/ols/term.rb', line 43

def is_root?
  self.parents.empty?
end

#merge!(other_graph) ⇒ Object

Merge in another ontology graph that shares the same root. Duplicate nodes (coming from other_graph) will NOT be overwritten in self.

Parameters:

  • other_graph (OLS::Term)

    The other graph to merge with.

Raises:

  • (TypeError)

    This exception is raised if other_graph is not a OLS::Term.

  • (ArgumentError)

    This exception is raised if other_graph does not have the same root as self.



308
309
310
311
312
313
314
315
316
# File 'lib/ols/term.rb', line 308

def merge!( other_graph )
  raise TypeError, 'You can only merge in another instance of OLS::Term' unless other_graph.is_a?(OLS::Term)
  raise ArgumentError, 'Unable to merge graphs as they do not share the same root' unless self.root.term_id == other_graph.root.term_id

  self.focus_graph!
  other_graph.focus_graph!

  merge_graphs( self.root, other_graph.root )
end

#parent_idsArray Also known as: parent_term_ids

Returns the term_ids for the direct parents of this term.

Returns:

  • (Array)

    The term_ids for the direct parents of this term



146
147
148
# File 'lib/ols/term.rb', line 146

def parent_ids
  parents.map(&:term_id)
end

#parent_namesArray Also known as: parent_term_names

Returns the term_names for the direct parents of this term.

Returns:

  • (Array)

    The term_names for the direct parents of this term



153
154
155
# File 'lib/ols/term.rb', line 153

def parent_names
  parents.map(&:term_name)
end

#parents(skip_fetch = false) ⇒ Array

Returns the direct parent terms for this ontology term

Returns:

  • (Array)

    An array of OLS::Term objects



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/ols/term.rb', line 120

def parents(skip_fetch=false)
  unless @already_fetched_parents || skip_fetch
    # puts "--- REQUESTING PARENTS (#{self.term_id}) ---"
    response = OLS.request(:get_term_parents) { soap.body = { :termId => self.term_id } }
    unless response.nil?
      if response[:item].is_a? Array
        response[:item].each do |term|
          parent = self.find_in_graph(term[:key]) || OLS::Term.new(term[:key],term[:value],@graph)
          self.add_parent(parent)
        end
      else
        term = response[:item]
        parent = self.find_in_graph(term[:key]) || OLS::Term.new(term[:key],term[:value],@graph)
        self.add_parent(parent)
      end
    end

    @already_fetched_parents = true
  end

  @graph[term_id][:parents].map{ |parent_id| self.find_in_graph(parent_id) }
end

Pretty prints the (sub)graph rooted at this ontology term.

Parameters:

  • show_term_name (Boolean) (defaults to: false)

    Show the term name?

  • level (Number) (defaults to: 1)

    The indentation level (4 spaces) to start with.



458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
# File 'lib/ols/term.rb', line 458

def print_graph(show_term_name=false,level=1)
  if is_root?
    print "*"
  else
    print(' ' * (level - 1) * 4)
    print "|---"
    print( self.has_children? ? "+" : ">" )
  end

  print_str = " #{self.term_id}"
  print_str << " - #{self.term_name}" if show_term_name
  puts print_str

  self.children.each { |child| child.print_graph(show_term_name,level + 1)}
end

#remove_childrenOLS::Term Also known as: detach_parents

Returns a copy of this ontology term object with the children removed.

Returns:

  • (OLS::Term)

    A copy of this term with the children removed

See Also:

Since:

  • 0.3.1



422
423
424
425
426
# File 'lib/ols/term.rb', line 422

def remove_children
  copy = self.dup
  copy.really_remove_children!
  copy
end

#remove_children!Object Also known as: detach_parents!

Remove the children from this ontology graph.

See Also:

Since:

  • 0.3.1



412
413
414
# File 'lib/ols/term.rb', line 412

def remove_children!
  self.really_remove_children!
end

#remove_parentsOLS::Term Also known as: detach_children

Returns a copy of this ontology term object with the parents removed.

Returns:

  • (OLS::Term)

    A copy of this term with the parents removed

See Also:

Since:

  • 0.3.1



445
446
447
448
449
# File 'lib/ols/term.rb', line 445

def remove_parents
  copy = self.dup
  copy.really_remove_parents!
  copy
end

#remove_parents!Object Also known as: detach_children!

Removes the parents from this ontology graph.

See Also:

Since:

  • 0.3.1



435
436
437
# File 'lib/ols/term.rb', line 435

def remove_parents!
  self.really_remove_parents!
end

#rootOLS::Term

Returns the root term for this ontology.

Returns:

  • (OLS::Term)

    The root term for this ontology



111
112
113
114
115
# File 'lib/ols/term.rb', line 111

def root
  root = self
  root = root.parents.first while !root.is_root?
  root
end

#sizeInteger

Returns the size of the full ontology graph (unique nodes).

Returns:

  • (Integer)

    The size of the full ontology graph (unique nodes)



88
89
90
# File 'lib/ols/term.rb', line 88

def size
  self.root.all_children.uniq.size + 1
end

#synonymsHash

Returns a hash listing the different types of synonyms known for this term, keyed by the synonym type

Returns:

  • (Hash)

    a hash listing the different types of synonyms known for this term



73
74
75
76
# File 'lib/ols/term.rb', line 73

def synonyms
  
  @synonyms ||= {}
end

#to_sString

Represent an OLS::Term as a String

Returns:

  • (String)

    A string representation of an OLS::Term



81
82
83
# File 'lib/ols/term.rb', line 81

def to_s
  "#{@term_id} - #{@term_name}"
end

#write_children_to_graphic_file(filename = 'graph', fmt = 'png') ⇒ Object

Save an image file showing graph structure of all children from the current term. Requires graphviz to convert the .dot source file to an image file.

Parameters:

  • filename (String) (defaults to: 'graph')

    The filename to save the DOT and image files to - omit the file extension

  • fmt (String) (defaults to: 'png')

    The image format to produce - i.e. png or jpg



479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
# File 'lib/ols/term.rb', line 479

def write_children_to_graphic_file(filename='graph',fmt='png')
  dotfile = filename + ".dot"
  imgfile = filename + "." + fmt

  nodes = [ self ] + self.all_children
  node_ranks = {}

  nodes.each do |node|
    node_ranks[node.level] ||= []
    node_ranks[node.level].push(node.term_id.gsub(':',''))
  end

  edges = self.all_children.map do |child|
    child.parents.map { |parent| "    #{parent.term_id} -> #{child.term_id}".gsub(':','') }
  end.flatten.uniq

  write_dot_and_image_file(dotfile,imgfile,fmt,nodes,node_ranks,edges)
end

#write_parentage_to_graphic_file(filename = 'graph', fmt = 'png') ⇒ Object

Save an image file showing graph structure of all parents for the current term. Requires graphviz to convert the .dot source file to an image file.

Parameters:

  • filename (String) (defaults to: 'graph')

    The filename to save the DOT and image files to - omit the file extension

  • fmt (String) (defaults to: 'png')

    The image format to produce - i.e. png or jpg



503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
# File 'lib/ols/term.rb', line 503

def write_parentage_to_graphic_file(filename='graph',fmt='png')
  dotfile = filename + ".dot"
  imgfile = filename + "." + fmt

  nodes = self.all_parents + [ self ]
  node_ranks = {}

  nodes.each do |node|
    node_ranks[node.level] ||= []
    node_ranks[node.level].push(node.term_id.gsub(':',''))
  end

  edges = self.all_parents.map do |parent|
    parent.children.map { |child| "    #{parent.term_id} -> #{child.term_id}".gsub(':','') }
  end.flatten.uniq

  write_dot_and_image_file(dotfile,imgfile,fmt,nodes,node_ranks,edges)
end