class MiGA::Taxonomy
Taxonomic classifications in MiGA.
#
def <<(value)
Add +value+ to the hierarchy, that can be an Array, a String, or a Hash, as
#
def <<(value) case value when Hash value.each do |r, n| next if n.nil? || n == '' @ranks[self.class.normalize_rank(r)] = n.tr('_', ' ') end when Array value.each { |v| self << v } when String self << Hash[*value.split(':', 2)] else raise 'Unsupported class: ' + value.class.name end end
def KNOWN_RANKS()
def KNOWN_RANKS() @@KNOWN_RANKS end
def LONG_RANKS()
def LONG_RANKS() @@LONG_RANKS end
def [](rank)
#
def [](rank) @ranks[rank.to_sym] end
def add_alternative(tax, replace = true)
Add an alternative taxonomy. If the namespace matches an existing namespace,
#
def add_alternative(tax, replace = true) return if tax.nil? raise 'Unsupported taxonomy class.' unless tax.is_a? MiGA::Taxonomy alt_ns = alternative(tax.namespace) if !replace || tax.namespace.nil? || alt_ns.nil? @alt << tax else alt_ns.reset(tax.to_s) end end
def alternative(which = nil)
String), including the master taxonomy.
- Otherwise, returns the first taxonomy with namespace +which+ (coerced as
(starting with 0, the master taxonomy).
- If +which+ is Integer, returns the indexed taxonomy
(not including the master taxonomy).
- If +which+ is nil (default), returns all alternative taxonomies as Array
Get the alternative taxonomies.
#
def alternative(which = nil) case which when nil @alt when Integer ([self] + @alt)[which] else ([self] + @alt).find { |i| i.namespace.to_s == which.to_s } end end
def delete_alternative
#
def delete_alternative alt = @alt.dup @alt = [] alt end
def domain
#
def domain self[:d] end
def dup
#
def dup self.class.new(to_s, nil, alternative.map(&:dup)) end
def highest(force_ranks = false)
If +force_ranks+ is true, it always returns the value for domain (d)
Get the most general rank as a two-entry Array (rank and value).
#
def highest(force_ranks = false) sorted_ranks(force_ranks).first end
def in?(taxon)
Evaluates if the loaded taxonomy includes +taxon+. It assumes that +taxon+
#
def in?(taxon) r = taxon.ranks.keys.first return false if self[r].nil? self[r].casecmp(taxon[r]).zero? end
def initialize(str, ranks = nil, alt = [])
String, Array, or Hash entries as defined above (except +ranks+ are not
value pairs is also supported. If +alt+ is passed, it must be an Array of
order as ther ranks in +ranks+. Alternatively, +str+ as a Hash with rank =>
either a rank:value pair (if +ranks+ is nil), or just values in the same
space-delimited entries, the array is a vector of entries. Each entry can be
Create MiGA::Taxonomy from String or Array +str+. The string is a series of
#
def initialize(str, ranks = nil, alt = []) reset(str, ranks) @alt = (alt || []).map { |i| Taxonomy.new(i) } end
def initialize_by_ranks(str, ranks)
def initialize_by_ranks(str, ranks) ranks = ranks.split(/\s+/) unless ranks.is_a? Array str = str.split(/\s+/) unless str.is_a? Array unless ranks.size == str.size raise "Unequal number of ranks and names: #{ranks} => #{str}" end str.each_with_index { |i, k| self << "#{ranks[k]}:#{i}" } end
def initialize_by_str(str)
def initialize_by_str(str) case str when Array, Hash self << str else "#{str} ".scan(/([A-Za-z]+):([^:]*)( )/) { |r, n, _| self << { r => n } } end end
def json_create(o)
#
def json_create(o) new(o['str'], nil, o['alt']) end
def lowest(force_ranks = false)
If +force_ranks+ is true, it always returns the value for dataset (ds)
Get the most specific rank as a two-entry Array (rank and value).
#
def lowest(force_ranks = false) sorted_ranks(force_ranks).last end
def namespace
#
def namespace self[:ns] end
def normalize_rank(rank)
#
def normalize_rank(rank) return unless rank return rank.to_sym if @@_KNOWN_RANKS_H[rank.to_sym] rank = rank.to_s.downcase return if rank == 'no rank' rank = @@RANK_SYNONYMS[rank] unless @@RANK_SYNONYMS[rank].nil? rank = rank.to_sym return unless @@_KNOWN_RANKS_H[rank] rank end
def reset(str, ranks = nil)
Reset ranks (including namespace) while leaving alternatives untouched.
#
def reset(str, ranks = nil) @ranks = {} if ranks.nil? initialize_by_str(str) else initialize_by_ranks(str, ranks) end end
def sorted_ranks(force_ranks = false, with_namespace = false)
If +force_ranks+ is true, it returns all standard ranks even if undefined.
Sorted list of ranks, as an Array of two-entry Arrays (rank and value).
#
def sorted_ranks(force_ranks = false, with_namespace = false) @@KNOWN_RANKS.map do |r| next if (r == :ns && !with_namespace) || (ranks[r].nil? && !force_ranks) [r, ranks[r]] end.compact end
def to_json(*a)
#
def to_json(*a) hsh = { JSON.create_id => self.class.name, 'str' => to_s } hsh['alt'] = alternative.map(&:to_s) unless alternative.empty? hsh.to_json(*a) end
def to_s(force_ranks = false)
Generate cannonical String for the taxonomy. If +force_ranks+ is true,
#
def to_s(force_ranks = false) sorted_ranks(force_ranks, true) .map { |r| "#{r[0]}:#{(r[1] || '').gsub(/[\s:]/, '_')}" }.join(' ') end