Class: Autoselect::TaxonName::ColAncestryComparator
- Inherits:
-
Object
- Object
- Autoselect::TaxonName::ColAncestryComparator
- Defined in:
- lib/autoselect/taxon_name/col_ancestry_comparator.rb
Overview
Diffs TaxonWorks' real ancestor chain for a matched "anchor" TaxonName against Catalogue of Life's classification for the same lineage, producing one unified, kingdom-first row list.
CoL gives ranks as plain names (e.g. 'family'), so each TaxonWorks rank_class is converted to its plain name (via RANKS_LOOKUP) to see whether two rows are at the same rank.
To decide which of two different ranks is more specific, both names are looked up under one code. When CoL gives a code, the TaxonWorks chain is already in it, so that code is used; otherwise the anchor's own code is.
Instance Method Summary collapse
-
#anchor_col_code ⇒ String?
private
The anchor's nomenclatural code as a CoL code string, e.g.
-
#call ⇒ Array<Hash>
Kingdom-first, each row tagged :match => 'exact' | 'none' (CoL-only, to be created) | 'extra' (TaxonWorks-only) | 'conflict' (same rank, different name — the actual disagreement).
- #extra_row(tw_entry, rank_name) ⇒ Object private
-
#initialize(tw_chain:, col_chain:, col_code: nil) ⇒ ColAncestryComparator
constructor
A new instance of ColAncestryComparator.
- #matched_row(tw_entry, col_entry, rank_name) ⇒ Object private
-
#more_specific?(tw_entry, col_rank_name) ⇒ Boolean
private
The TaxonWorks chain is always in @rank_code's code (see the class comment), so tw_entry's own rank_class indexes RANK_SORT directly; only CoL's rank name can fail to resolve under that code.
- #none_row(col_entry) ⇒ Object private
- #rank_name_for(rank_class) ⇒ Object private
Constructor Details
#initialize(tw_chain:, col_chain:, col_code: nil) ⇒ ColAncestryComparator
Returns a new instance of ColAncestryComparator.
24 25 26 27 28 29 30 31 32 33 |
# File 'lib/autoselect/taxon_name/col_ancestry_comparator.rb', line 24 def initialize(tw_chain:, col_chain:, col_code: nil) @tw_chain = tw_chain @col_chain = col_chain @rank_code = if ::Vendor::Colrapi::COL_CODE_LOOKUP_MAP.key?(col_code) col_code else anchor_col_code end end |
Instance Method Details
#anchor_col_code ⇒ String? (private)
Returns the anchor's nomenclatural code as a CoL code string, e.g. 'botanical'; nil leaves col_rank_sort on its zoological default.
85 86 87 88 |
# File 'lib/autoselect/taxon_name/col_ancestry_comparator.rb', line 85 def anchor_col_code code = @tw_chain.last&.rank_class&.nomenclatural_code ::Vendor::Colrapi::COL_CODE_TO_NOMENCLATURE_CODE.key(code) end |
#call ⇒ Array<Hash>
Returns kingdom-first, each row tagged :match => 'exact' | 'none' (CoL-only, to be created) | 'extra' (TaxonWorks-only) | 'conflict' (same rank, different name — the actual disagreement).
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/autoselect/taxon_name/col_ancestry_comparator.rb', line 39 def call result = [] tw_i = @tw_chain.length - 1 col_i = @col_chain.length - 1 while tw_i >= 0 && col_i >= 0 tw_entry = @tw_chain[tw_i] col_entry = @col_chain[col_i] tw_rank_name = rank_name_for(tw_entry.rank_class) if tw_rank_name == col_entry[:rank] result.unshift(matched_row(tw_entry, col_entry, tw_rank_name)) tw_i -= 1 col_i -= 1 elsif more_specific?(tw_entry, col_entry[:rank]) result.unshift(extra_row(tw_entry, tw_rank_name)) tw_i -= 1 else result.unshift(none_row(col_entry)) col_i -= 1 end end while tw_i >= 0 entry = @tw_chain[tw_i] result.unshift(extra_row(entry, rank_name_for(entry.rank_class))) tw_i -= 1 end while col_i >= 0 result.unshift(none_row(@col_chain[col_i])) col_i -= 1 end result end |
#extra_row(tw_entry, rank_name) ⇒ Object (private)
123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/autoselect/taxon_name/col_ancestry_comparator.rb', line 123 def extra_row(tw_entry, rank_name) { rank: rank_name, col_name: nil, col_id: nil, dataset_id: nil, col_authorship: nil, taxonworks_id: tw_entry.id, taxonworks_name: tw_entry.cached, match: 'extra' } end |
#matched_row(tw_entry, col_entry, rank_name) ⇒ Object (private)
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/autoselect/taxon_name/col_ancestry_comparator.rb', line 105 def matched_row(tw_entry, col_entry, rank_name) # Compared by key, not raw name - see Vendor::Colrapi::NameTranslation. translation = ::Vendor::Colrapi::NameTranslation exact = translation.taxonworks_name_keys(tw_entry)[:current] == translation.col_name_key(col_entry[:col_name], col_entry[:rank]) { rank: rank_name, col_name: col_entry[:col_name], col_id: col_entry[:col_id], dataset_id: col_entry[:dataset_id], col_authorship: col_entry[:col_authorship], taxonworks_id: tw_entry.id, taxonworks_name: tw_entry.cached, match: exact ? 'exact' : 'conflict' } end |
#more_specific?(tw_entry, col_rank_name) ⇒ Boolean (private)
The TaxonWorks chain is always in @rank_code's code (see the class comment), so tw_entry's own rank_class indexes RANK_SORT directly; only CoL's rank name can fail to resolve under that code.
98 99 100 101 102 103 |
# File 'lib/autoselect/taxon_name/col_ancestry_comparator.rb', line 98 def more_specific?(tw_entry, col_rank_name) col_sort = ::Vendor::Colrapi.col_rank_sort(col_rank_name, @rank_code) return false if col_sort.nil? ::RANK_SORT[tw_entry.rank_class.to_s] > col_sort end |
#none_row(col_entry) ⇒ Object (private)
136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/autoselect/taxon_name/col_ancestry_comparator.rb', line 136 def none_row(col_entry) { rank: col_entry[:rank], col_name: col_entry[:col_name], col_id: col_entry[:col_id], dataset_id: col_entry[:dataset_id], col_authorship: col_entry[:col_authorship], above_genus_group: col_entry[:above_genus_group], rank_unknown: col_entry[:rank_unknown], taxonworks_id: nil, taxonworks_name: nil, match: 'none' } end |
#rank_name_for(rank_class) ⇒ Object (private)
78 79 80 |
# File 'lib/autoselect/taxon_name/col_ancestry_comparator.rb', line 78 def rank_name_for(rank_class) ::RANKS_LOOKUP[rank_class.to_s] end |