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.
-
#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.
58 59 60 61 62 63 64 65 |
# File 'lib/vendor/biodiversity.rb', line 58 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 `.
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 |
#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?!.
220 221 222 223 224 225 226 |
# File 'lib/vendor/biodiversity.rb', line 220 def ambiguous_ranks a = [ ] protonym_result.each do |k, v| a.push k if v.count > 1 end a end |
#author ⇒ String?
163 164 165 166 167 168 169 |
# File 'lib/vendor/biodiversity.rb', line 163 def if a = Utilities::Strings.(a[:authors]) else nil end end |
#author_word_position ⇒ Object
372 373 374 375 376 377 |
# File 'lib/vendor/biodiversity.rb', line 372 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
171 172 173 |
# File 'lib/vendor/biodiversity.rb', line 171 def [, year].compact.join(', ') end |
#authorship ⇒ Hash?
Returns the Biodiversity authorship hash.
158 159 160 |
# File 'lib/vendor/biodiversity.rb', line 158 def parse_result.dig(:authorship, :originalAuth) end |
#basic_scope(rank) ⇒ Scope
257 258 259 260 261 262 |
# File 'lib/vendor/biodiversity.rb', line 257 def basic_scope(rank) Protonym.where( project_id: project_id, name: string(rank) ) end |
#build_result ⇒ Hash
338 339 340 341 342 343 344 345 346 |
# File 'lib/vendor/biodiversity.rb', line 338 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.
364 365 366 367 368 369 370 |
# File 'lib/vendor/biodiversity.rb', line 364 def combination_exists? if is_unambiguous? Combination.match_exists?(**combination.protonym_ids_params) # TODO: pass name? else false end end |
#detail ⇒ Hash
103 104 105 |
# File 'lib/vendor/biodiversity.rb', line 103 def detail parse_result[:details] || {} end |
#disambiguate_combination(target_protonym_ids = {}) ⇒ Combination
234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/vendor/biodiversity.rb', line 234 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`.
149 150 151 152 153 154 |
# File 'lib/vendor/biodiversity.rb', line 149 def finest_rank RANKS.reverse_each do |k| return k if send(k) end nil end |
#form ⇒ String?
133 134 135 |
# File 'lib/vendor/biodiversity.rb', line 133 def form infraspecies('f.') end |
#genus ⇒ String?
108 109 110 |
# File 'lib/vendor/biodiversity.rb', line 108 def genus parse_result[:words]&.detect { |w| %w{UNINOMIAL GENUS}.include?(w[:wordType]) }&.dig(:normalized) end |
#grouped_protonyms(rank) ⇒ Scope
286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/vendor/biodiversity.rb', line 286 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?
138 139 140 |
# File 'lib/vendor/biodiversity.rb', line 138 def infraspecies(biodiversity_rank) detail.dig(:infraspecies, :infraspecies)&.detect { |e| e[:rank] == biodiversity_rank }&.dig(:value) end |
#is_authored? ⇒ Boolean
199 200 201 |
# File 'lib/vendor/biodiversity.rb', line 199 def .size > 0 end |
#is_unambiguous? ⇒ Boolean
Returns true if for each parsed piece of there name there is 1 and only 1 result.
189 190 191 192 193 194 195 196 |
# File 'lib/vendor/biodiversity.rb', line 189 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.
144 145 146 |
# File 'lib/vendor/biodiversity.rb', line 144 def name_count (detail[detail.keys.first].keys - [:authorship]).count end |
#name_without_author_year ⇒ Object
379 380 381 382 383 384 385 |
# File 'lib/vendor/biodiversity.rb', line 379 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.
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 |
# File 'lib/vendor/biodiversity.rb', line 391 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.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/vendor/biodiversity.rb', line 69 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
320 321 322 323 324 325 326 327 328 329 |
# File 'lib/vendor/biodiversity.rb', line 320 def parse_values h = { author: , year: year } RANKS.each do |r| h[r] = send(r) end h end |
#preparse ⇒ Array
Returns TODO: deprecate.
98 99 100 |
# File 'lib/vendor/biodiversity.rb', line 98 def preparse name.split(' in ') end |
#protonyms(rank) ⇒ Scope
266 267 268 269 270 271 272 273 274 275 |
# File 'lib/vendor/biodiversity.rb', line 266 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.
279 280 281 |
# File 'lib/vendor/biodiversity.rb', line 279 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.
302 303 304 305 |
# File 'lib/vendor/biodiversity.rb', line 302 def (scope) t = scope.where('(cached_author_year = ? OR cached_author_year = ?)', , .gsub(' & ', ' and ')) t.count > 0 ? t : scope end |
#set_combination ⇒ Object
354 355 356 357 358 359 360 |
# File 'lib/vendor/biodiversity.rb', line 354 def set_combination c = Combination.new RANKS.each do |r| c.send("#{r}=", unambiguous_at?(r)) end c end |
#species ⇒ String?
118 119 120 |
# File 'lib/vendor/biodiversity.rb', line 118 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.
251 252 253 |
# File 'lib/vendor/biodiversity.rb', line 251 def string(rank = nil) send(rank) end |
#subgenus ⇒ String?
113 114 115 |
# File 'lib/vendor/biodiversity.rb', line 113 def subgenus (parse_result[:words] || [])[1..]&.detect { |w| %w{UNINOMIAL INFRA_GENUS}.include?(w[:wordType]) }&.dig(:normalized) end |
#subspecies ⇒ String?
123 124 125 |
# File 'lib/vendor/biodiversity.rb', line 123 def subspecies infraspecies(nil) end |
#unambiguous_at?(rank) ⇒ Protonym?
Returns true if there is a single matching result or nominotypical subs.
206 207 208 209 210 211 212 213 214 215 |
# File 'lib/vendor/biodiversity.rb', line 206 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?
128 129 130 |
# File 'lib/vendor/biodiversity.rb', line 128 def variety infraspecies('var.') end |
#year ⇒ String?
176 177 178 179 180 |
# File 'lib/vendor/biodiversity.rb', line 176 def year if a = return a.dig(:year, :year) end end |