Class: Vendor::Biodiversity::Result
- Inherits:
-
Object
- Object
- 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.
-
#normalized ⇒ Object
readonly
Boolean - true, we match on words from verbatim: - false, we match on words from normalized:.
-
#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, verbatim: false) ⇒ 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, verbatim: false) ⇒ Result
Returns a new instance of Result.
64 65 66 67 68 69 70 71 72 |
# File 'lib/vendor/biodiversity.rb', line 64 def initialize(query_string: nil, project_id: nil, code: :iczn, match_mode: :groups, verbatim: false) @project_id = project_id @name = query_string @nomenclature_code = code @mode = match_mode @normalized = !verbatim parse if !query_string.blank? end |
Instance Attribute Details
#citation ⇒ String (readonly)
Returns the bit after ‘ in `.
40 41 42 |
# File 'lib/vendor/biodiversity.rb', line 40 def citation @citation end |
#combination ⇒ Combination (readonly)
Returns ranks that are unambiguous have their Protonym set.
56 57 58 |
# File 'lib/vendor/biodiversity.rb', line 56 def combination @combination end |
#disambiguated_combination ⇒ Combination (readonly)
Returns a memoized result of disambiguated_combination.
52 53 54 |
# File 'lib/vendor/biodiversity.rb', line 52 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
20 21 22 |
# File 'lib/vendor/biodiversity.rb', line 20 def mode @mode end |
#name ⇒ Object
query string
15 16 17 |
# File 'lib/vendor/biodiversity.rb', line 15 def name @name end |
#nomenclature_code ⇒ Object
one of :iczn, :icn, :icnp
26 27 28 |
# File 'lib/vendor/biodiversity.rb', line 26 def nomenclature_code @nomenclature_code end |
#normalized ⇒ Object (readonly)
Returns Boolean
-
true, we match on words from verbatim:
-
false, we match on words from normalized:.
61 62 63 |
# File 'lib/vendor/biodiversity.rb', line 61 def normalized @normalized end |
#parse_result ⇒ Object
the result of a ScientificNameParser parse
29 30 31 |
# File 'lib/vendor/biodiversity.rb', line 29 def parse_result @parse_result end |
#parseable ⇒ Boolean (readonly)
44 45 46 |
# File 'lib/vendor/biodiversity.rb', line 44 def parseable @parseable end |
#project_id ⇒ Object
project to query against
23 24 25 |
# File 'lib/vendor/biodiversity.rb', line 23 def project_id @project_id end |
#protonym_result ⇒ Hash (readonly)
Returns we inspect this internally, so it has to be decoupled.
48 49 50 |
# File 'lib/vendor/biodiversity.rb', line 48 def protonym_result @protonym_result end |
#result ⇒ Hash (readonly)
Returns summary for rendering purposes.
37 38 39 |
# File 'lib/vendor/biodiversity.rb', line 37 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?!.
239 240 241 242 243 244 245 |
# File 'lib/vendor/biodiversity.rb', line 239 def ambiguous_ranks a = [ ] protonym_result.each do |k, v| a.push k if v.count > 1 end a end |
#author ⇒ String?
182 183 184 185 186 187 188 |
# File 'lib/vendor/biodiversity.rb', line 182 def if a = Utilities::Strings.(a[:authors]) else nil end end |
#author_word_position ⇒ Object
391 392 393 394 395 396 |
# File 'lib/vendor/biodiversity.rb', line 391 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
190 191 192 |
# File 'lib/vendor/biodiversity.rb', line 190 def [, year].compact.join(', ') end |
#authorship ⇒ Hash?
Returns the Biodiversity authorship hash.
177 178 179 |
# File 'lib/vendor/biodiversity.rb', line 177 def parse_result.dig(:authorship, :originalAuth) end |
#basic_scope(rank) ⇒ Scope
276 277 278 279 280 281 |
# File 'lib/vendor/biodiversity.rb', line 276 def basic_scope(rank) Protonym.where( project_id: project_id, name: string(rank) ) end |
#build_result ⇒ Hash
357 358 359 360 361 362 363 364 365 |
# File 'lib/vendor/biodiversity.rb', line 357 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.
383 384 385 386 387 388 389 |
# File 'lib/vendor/biodiversity.rb', line 383 def combination_exists? if is_unambiguous? Combination.match_exists?(**combination.protonym_ids_params) # TODO: pass name? else false end end |
#detail ⇒ Hash
114 115 116 |
# File 'lib/vendor/biodiversity.rb', line 114 def detail parse_result[:details] || {} end |
#disambiguate_combination(target_protonym_ids = {}) ⇒ Combination
253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/vendor/biodiversity.rb', line 253 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`.
168 169 170 171 172 173 |
# File 'lib/vendor/biodiversity.rb', line 168 def finest_rank RANKS.reverse_each do |k| return k if send(k) end nil end |
#form ⇒ String?
152 153 154 |
# File 'lib/vendor/biodiversity.rb', line 152 def form infraspecies('f.') end |
#genus ⇒ String?
119 120 121 122 123 124 125 |
# File 'lib/vendor/biodiversity.rb', line 119 def genus if parse_result[:rank] == 'subgen.' parse_result.dig(:details, :uninomial, :parent) else parse_result[:words]&.detect{ |w| %w{UNINOMIAL GENUS}.include?(w[:wordType]) }&.dig(normalized) end end |
#grouped_protonyms(rank) ⇒ Scope
305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/vendor/biodiversity.rb', line 305 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?
157 158 159 |
# File 'lib/vendor/biodiversity.rb', line 157 def infraspecies(biodiversity_rank) detail.dig(:infraspecies, :infraspecies)&.detect { |e| e[:rank] == biodiversity_rank }&.dig(:value) end |
#is_authored? ⇒ Boolean
218 219 220 |
# File 'lib/vendor/biodiversity.rb', line 218 def .size > 0 end |
#is_unambiguous? ⇒ Boolean
Returns true if for each parsed piece of there name there is 1 and only 1 result.
208 209 210 211 212 213 214 215 |
# File 'lib/vendor/biodiversity.rb', line 208 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.
163 164 165 |
# File 'lib/vendor/biodiversity.rb', line 163 def name_count (detail[detail.keys.first].keys - [:authorship]).count end |
#name_without_author_year ⇒ Object
398 399 400 401 402 403 404 |
# File 'lib/vendor/biodiversity.rb', line 398 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.
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 |
# File 'lib/vendor/biodiversity.rb', line 410 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.
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/vendor/biodiversity.rb', line 80 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
339 340 341 342 343 344 345 346 347 348 |
# File 'lib/vendor/biodiversity.rb', line 339 def parse_values h = { author: , year: year } RANKS.each do |r| h[r] = send(r) end h end |
#preparse ⇒ Array
Returns TODO: deprecate.
109 110 111 |
# File 'lib/vendor/biodiversity.rb', line 109 def preparse name.split(' in ') end |
#protonyms(rank) ⇒ Scope
285 286 287 288 289 290 291 292 293 294 |
# File 'lib/vendor/biodiversity.rb', line 285 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.
298 299 300 |
# File 'lib/vendor/biodiversity.rb', line 298 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.
321 322 323 324 |
# File 'lib/vendor/biodiversity.rb', line 321 def (scope) t = scope.where('(cached_author_year = ? OR cached_author_year = ?)', , .gsub(' & ', ' and ')) t.count > 0 ? t : scope end |
#set_combination ⇒ Object
373 374 375 376 377 378 379 |
# File 'lib/vendor/biodiversity.rb', line 373 def set_combination c = Combination.new RANKS.each do |r| c.send("#{r}=", unambiguous_at?(r)) end c end |
#species ⇒ String?
137 138 139 |
# File 'lib/vendor/biodiversity.rb', line 137 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.
270 271 272 |
# File 'lib/vendor/biodiversity.rb', line 270 def string(rank = nil) send(rank) end |
#subgenus ⇒ String?
128 129 130 131 132 133 134 |
# File 'lib/vendor/biodiversity.rb', line 128 def subgenus if parse_result[:rank] == 'subgen.' parse_result.dig(:details, :uninomial, :uninomial) else (parse_result[:words] || [])[1..]&.detect{ |w| %w{UNINOMIAL INFRA_GENUS}.include?(w[:wordType]) }&.dig(normalized) end end |
#subspecies ⇒ String?
142 143 144 |
# File 'lib/vendor/biodiversity.rb', line 142 def subspecies infraspecies(nil) end |
#unambiguous_at?(rank) ⇒ Protonym?
Returns true if there is a single matching result or nominotypical subs.
225 226 227 228 229 230 231 232 233 234 |
# File 'lib/vendor/biodiversity.rb', line 225 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?
147 148 149 |
# File 'lib/vendor/biodiversity.rb', line 147 def variety infraspecies('var.') end |
#year ⇒ String?
195 196 197 198 199 |
# File 'lib/vendor/biodiversity.rb', line 195 def year if a = return a.dig(:year, :year) end end |