Class: TaxonWorks::Vendor::Biodiversity::Result
- Inherits:
-
Object
- Object
- TaxonWorks::Vendor::Biodiversity::Result
- Defined in:
- lib/vendor/biodiversity.rb
Instance Attribute Summary collapse
-
#citation ⇒ String
readonly
The bit after ` in `.
-
#combination ⇒ Combination
readonly
Ranks that are unambiguous have their Protonym set.
-
#disambiguated_combination ⇒ Combination
readonly
A memoized result of disambiguated_combination.
-
#mode ⇒ Object
how to match `ranked`: return names at that queried rank only (e.g. only match a subgenus to rank subgenus `groups`: return names at Group level (species or genus), i.e. a subgenus name in query will match genus OR subgenus in database.
-
#name ⇒ Object
query string.
-
#nomenclature_code ⇒ Object
one of :iczn, :icn, :icnp.
-
#parse_result ⇒ Object
the result of a ScientificNameParser parse.
- #parseable ⇒ Boolean readonly
-
#project_id ⇒ Object
project to query against.
-
#protonym_result ⇒ Hash
readonly
We inspect this internally, so it has to be decoupled.
-
#result ⇒ Hash
readonly
Summary for rendering purposes.
Instance Method Summary collapse
-
#ambiguous_ranks ⇒ Array
The ranks, as symbols, at which there are multiple (>1) Protonym matches !! subtly different than unambiguous_at, probably should use that?!.
- #author ⇒ String?
- #author_word_position ⇒ Object
- #author_year ⇒ Object
-
#authorship ⇒ Hash?
The Biodiversity authorship hash.
- #basic_scope(rank) ⇒ Scope
- #build_result ⇒ Hash
-
#combination_exists? ⇒ Combination, false
The Combination, if it exists.
- #detail ⇒ Hash
- #disambiguate_combination(target_protonym_ids = {}) ⇒ Combination
-
#finest_rank ⇒ Symbol?
Like `:genus`.
- #form ⇒ String?
- #genus ⇒ String?
- #grouped_protonyms(rank) ⇒ Scope
- #infraspecies(biodiversity_rank) ⇒ String?
-
#initialize(query_string: nil, project_id: nil, code: :iczn, match_mode: :groups) ⇒ Result
constructor
A new instance of Result.
- #is_authored? ⇒ Boolean
-
#is_unambiguous? ⇒ Boolean
True if for each parsed piece of there name there is 1 and only 1 result.
-
#name_count ⇒ Integer
The total monominals in the epithet.
- #name_without_author_year ⇒ Object
-
#other_matches ⇒ Hash
`:verbatim` - names that have verbatim supplied, these should be the only names NOT parsed that user is interested in `:subgenus` - names that exactly match a subgenus, these are potential new combinations as Genus alone `:original_combination` - names that exactly match the original combination.
-
#parse ⇒ @parse_result
A Biodiversity name parser result.
- #parse_values ⇒ Hash
-
#preparse ⇒ Array
TODO: deprecate.
- #protonyms(rank) ⇒ Scope
-
#ranked_protonyms(rank) ⇒ Scope
Protonyms at a given rank.
-
#scope_to_author_year(scope) ⇒ Scope
If there is an exact author year match scope it to that match, otherwise ignore the author year.
- #set_combination ⇒ Object
- #species ⇒ String?
-
#string(rank = nil) ⇒ String, false
A wrapper on string returning methods.
- #subgenus ⇒ String?
- #subspecies ⇒ String?
-
#unambiguous_at?(rank) ⇒ Protonym?
True if there is a single matching result or nominotypical subs.
- #variety ⇒ String?
- #year ⇒ String?
Constructor Details
#initialize(query_string: nil, project_id: nil, code: :iczn, match_mode: :groups) ⇒ Result
Returns a new instance of Result.
59 60 61 62 63 64 65 66 |
# File 'lib/vendor/biodiversity.rb', line 59 def initialize(query_string: nil, project_id: nil, code: :iczn, match_mode: :groups) @project_id = project_id @name = query_string @nomenclature_code = code @mode = match_mode parse if !query_string.blank? end |
Instance Attribute Details
#citation ⇒ String (readonly)
Returns the bit after ` in `.
41 42 43 |
# File 'lib/vendor/biodiversity.rb', line 41 def citation @citation end |
#combination ⇒ Combination (readonly)
Returns ranks that are unambiguous have their Protonym set.
57 58 59 |
# File 'lib/vendor/biodiversity.rb', line 57 def combination @combination end |
#disambiguated_combination ⇒ Combination (readonly)
Returns a memoized result of disambiguated_combination.
53 54 55 |
# File 'lib/vendor/biodiversity.rb', line 53 def disambiguated_combination @disambiguated_combination end |
#mode ⇒ Object
how to match
`ranked`: return names at that queried rank only (e.g. only match a subgenus to rank subgenus
`groups`: return names at Group level (species or genus), i.e. a subgenus name in query will match genus OR subgenus in database
21 22 23 |
# File 'lib/vendor/biodiversity.rb', line 21 def mode @mode end |
#name ⇒ Object
query string
16 17 18 |
# File 'lib/vendor/biodiversity.rb', line 16 def name @name end |
#nomenclature_code ⇒ Object
one of :iczn, :icn, :icnp
27 28 29 |
# File 'lib/vendor/biodiversity.rb', line 27 def nomenclature_code @nomenclature_code end |
#parse_result ⇒ Object
the result of a ScientificNameParser parse
30 31 32 |
# File 'lib/vendor/biodiversity.rb', line 30 def parse_result @parse_result end |
#parseable ⇒ Boolean (readonly)
45 46 47 |
# File 'lib/vendor/biodiversity.rb', line 45 def parseable @parseable end |
#project_id ⇒ Object
project to query against
24 25 26 |
# File 'lib/vendor/biodiversity.rb', line 24 def project_id @project_id end |
#protonym_result ⇒ Hash (readonly)
Returns we inspect this internally, so it has to be decoupled.
49 50 51 |
# File 'lib/vendor/biodiversity.rb', line 49 def protonym_result @protonym_result end |
#result ⇒ Hash (readonly)
Returns summary for rendering purposes.
38 39 40 |
# File 'lib/vendor/biodiversity.rb', line 38 def result @result end |
Instance Method Details
#ambiguous_ranks ⇒ Array
Returns the ranks, as symbols, at which there are multiple (>1) Protonym matches !! subtly different than unambiguous_at, probably should use that?!.
221 222 223 224 225 226 227 |
# File 'lib/vendor/biodiversity.rb', line 221 def ambiguous_ranks a = [ ] protonym_result.each do |k, v| a.push k if v.count > 1 end a end |
#author ⇒ String?
164 165 166 167 168 169 170 |
# File 'lib/vendor/biodiversity.rb', line 164 def if a = Utilities::Strings.(a[:authors]) else nil end end |
#author_word_position ⇒ Object
373 374 375 376 377 378 |
# File 'lib/vendor/biodiversity.rb', line 373 def if a = parse_result[:words] b = (a.detect { |v| v[:wordType] == 'AUTHOR_WORD'})&.dig(:start) p = [name.length, b].compact.min end end |
#author_year ⇒ Object
172 173 174 |
# File 'lib/vendor/biodiversity.rb', line 172 def [, year].compact.join(', ') end |
#authorship ⇒ Hash?
Returns the Biodiversity authorship hash.
159 160 161 |
# File 'lib/vendor/biodiversity.rb', line 159 def parse_result.dig(:authorship, :originalAuth) end |
#basic_scope(rank) ⇒ Scope
258 259 260 261 262 263 |
# File 'lib/vendor/biodiversity.rb', line 258 def basic_scope(rank) Protonym.where( project_id: project_id, name: string(rank) ) end |
#build_result ⇒ Hash
339 340 341 342 343 344 345 346 347 |
# File 'lib/vendor/biodiversity.rb', line 339 def build_result @result = {} @result[:protonyms] = protonym_result @result[:parse] = parse_values @result[:unambiguous] = is_unambiguous? @result[:existing_combination_id] = combination_exists?.try(:id) @result[:other_matches] = other_matches @result end |
#combination_exists? ⇒ Combination, false
Returns the Combination, if it exists.
365 366 367 368 369 370 371 |
# File 'lib/vendor/biodiversity.rb', line 365 def combination_exists? if is_unambiguous? Combination.match_exists?(**combination.protonym_ids_params) # TODO: pass name? else false end end |
#detail ⇒ Hash
104 105 106 |
# File 'lib/vendor/biodiversity.rb', line 104 def detail parse_result[:details] || {} end |
#disambiguate_combination(target_protonym_ids = {}) ⇒ Combination
235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/vendor/biodiversity.rb', line 235 def disambiguate_combination(target_protonym_ids = {}) return nil unless target_protonym_ids.any? c = combination b = ambiguous_ranks target_protonym_ids.each do |rank, id| if b.include?(rank) c.send("#{rank}_id=", id) if protonym_result[rank].map(&:id).include?(id) end end @disambiguated_combination = c end |
#finest_rank ⇒ Symbol?
Returns like `:genus`.
150 151 152 153 154 155 |
# File 'lib/vendor/biodiversity.rb', line 150 def finest_rank RANKS.reverse_each do |k| return k if send(k) end nil end |
#form ⇒ String?
134 135 136 |
# File 'lib/vendor/biodiversity.rb', line 134 def form infraspecies('f.') end |
#genus ⇒ String?
109 110 111 |
# File 'lib/vendor/biodiversity.rb', line 109 def genus parse_result[:words]&.detect { |w| %w{UNINOMIAL GENUS}.include?(w[:wordType]) }&.dig(:normalized) end |
#grouped_protonyms(rank) ⇒ Scope
287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/vendor/biodiversity.rb', line 287 def grouped_protonyms(rank) s = case rank when :genus, :subgenus basic_scope(rank).is_genus_group when :species, :subspecies, :variety, :form basic_scope(rank).is_species_group else Protonym.none end ( && finest_rank == rank) ? (s) : s end |
#infraspecies(biodiversity_rank) ⇒ String?
139 140 141 |
# File 'lib/vendor/biodiversity.rb', line 139 def infraspecies(biodiversity_rank) detail.dig(:infraspecies, :infraspecies)&.detect { |e| e[:rank] == biodiversity_rank }&.dig(:value) end |
#is_authored? ⇒ Boolean
200 201 202 |
# File 'lib/vendor/biodiversity.rb', line 200 def .size > 0 end |
#is_unambiguous? ⇒ Boolean
Returns true if for each parsed piece of there name there is 1 and only 1 result.
190 191 192 193 194 195 196 197 |
# File 'lib/vendor/biodiversity.rb', line 190 def is_unambiguous? RANKS.each do |r| if !send(r).nil? return false unless !send(r).nil? && !unambiguous_at?(r).nil? end end true end |
#name_count ⇒ Integer
Returns the total monominals in the epithet.
145 146 147 |
# File 'lib/vendor/biodiversity.rb', line 145 def name_count (detail[detail.keys.first].keys - [:authorship]).count end |
#name_without_author_year ⇒ Object
380 381 382 383 384 385 386 |
# File 'lib/vendor/biodiversity.rb', line 380 def pos = # author_word doesn't point to parens if any offset = pos > 0 && '(' == name[pos-1] ? 2 : 1 name[0..pos - offset].strip end |
#other_matches ⇒ Hash
Returns `:verbatim` - names that have verbatim supplied, these should be the only names NOT parsed that user is interested in `:subgenus` - names that exactly match a subgenus, these are potential new combinations as Genus alone `:original_combination` - names that exactly match the original combination.
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/vendor/biodiversity.rb', line 392 def other_matches h = { verbatim: [], subgenus: [], original: [] } h[:verbatim] = TaxonName.where(project_id: project_id, cached: ). where('verbatim_name is not null').order(:cached).all.to_a if parseable h[:subgenus] = Protonym.where( project_id: project_id, name: genus, rank_class: Ranks.lookup(nomenclature_code, :subgenus) ).all.to_a h[:original_combination] = Protonym.where(project_id: project_id). where( cached_original_combination: ).all.to_a if parseable h end |
#parse ⇒ @parse_result
Returns a Biodiversity name parser result.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/vendor/biodiversity.rb', line 70 def parse @combination = nil @disambiguated_combination = nil n, @citation = preparse begin @parse_result ||= ::Biodiversity::Parser.parse(n) rescue NoMethodError => e case e. when /canonical/ @parseable = false else raise end end @parse_result[:scientificName] = parse_result[:normalized] @parse_result end |
#parse_values ⇒ Hash
321 322 323 324 325 326 327 328 329 330 |
# File 'lib/vendor/biodiversity.rb', line 321 def parse_values h = { author: , year: year } RANKS.each do |r| h[r] = send(r) end h end |
#preparse ⇒ Array
Returns TODO: deprecate.
99 100 101 |
# File 'lib/vendor/biodiversity.rb', line 99 def preparse name.split(' in ') end |
#protonyms(rank) ⇒ Scope
267 268 269 270 271 272 273 274 275 276 |
# File 'lib/vendor/biodiversity.rb', line 267 def protonyms(rank) case mode when :ranked ranked_protonyms(rank) when :groups grouped_protonyms(rank) else Protonym.none end end |
#ranked_protonyms(rank) ⇒ Scope
Returns Protonyms at a given rank.
280 281 282 |
# File 'lib/vendor/biodiversity.rb', line 280 def ranked_protonyms(rank) basic_scope(rank).where(rank_class: Ranks.lookup(nomenclature_code, rank)) end |
#scope_to_author_year(scope) ⇒ Scope
Returns if there is an exact author year match scope it to that match, otherwise
ignore the author year.
303 304 305 306 |
# File 'lib/vendor/biodiversity.rb', line 303 def (scope) t = scope.where('(cached_author_year = ? OR cached_author_year = ?)', , .gsub(' & ', ' and ')) t.count > 0 ? t : scope end |
#set_combination ⇒ Object
355 356 357 358 359 360 361 |
# File 'lib/vendor/biodiversity.rb', line 355 def set_combination c = Combination.new RANKS.each do |r| c.send("#{r}=", unambiguous_at?(r)) end c end |
#species ⇒ String?
119 120 121 |
# File 'lib/vendor/biodiversity.rb', line 119 def species parse_result[:words]&.detect { |w| 'SPECIES' == w[:wordType] }&.dig(:normalized) end |
#string(rank = nil) ⇒ String, false
Returns a wrapper on string returning methods.
252 253 254 |
# File 'lib/vendor/biodiversity.rb', line 252 def string(rank = nil) send(rank) end |
#subgenus ⇒ String?
114 115 116 |
# File 'lib/vendor/biodiversity.rb', line 114 def subgenus (parse_result[:words] || [])[1..]&.detect { |w| %w{UNINOMIAL INFRA_GENUS}.include?(w[:wordType]) }&.dig(:normalized) end |
#subspecies ⇒ String?
124 125 126 |
# File 'lib/vendor/biodiversity.rb', line 124 def subspecies infraspecies(nil) end |
#unambiguous_at?(rank) ⇒ Protonym?
Returns true if there is a single matching result or nominotypical subs.
207 208 209 210 211 212 213 214 215 216 |
# File 'lib/vendor/biodiversity.rb', line 207 def unambiguous_at?(rank) return protonym_result[rank].first if protonym_result[rank].size == 1 if protonym_result[rank].size == 2 n1 = protonym_result[rank].first n2 = protonym_result[rank].last return n2 if n2.nominotypical_sub_of?(n1) return n1 if n1.nominotypical_sub_of?(n2) end nil end |
#variety ⇒ String?
129 130 131 |
# File 'lib/vendor/biodiversity.rb', line 129 def variety infraspecies('var.') end |
#year ⇒ String?
177 178 179 180 181 |
# File 'lib/vendor/biodiversity.rb', line 177 def year if a = return a.dig(:year, :year) end end |