Skip to content

Commit

Permalink
Fix mapping of infrageneric names
Browse files Browse the repository at this point in the history
- Maps iNat's rank+epithet to a full MO name.
E.g. "Section Distantes" to "Morchella sect. Distantes"
  • Loading branch information
JoeCohen committed Aug 10, 2024
1 parent 7d50d64 commit 285522f
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 2 deletions.
50 changes: 48 additions & 2 deletions app/classes/inat_obs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,57 @@ def license
end

def name_id
mo_names = Name.where(text_name: inat_taxon[:name],
rank: inat_taxon[:rank].titleize).
mo_names = Name.where(
# parse it to get MO's text_name rank abbreviation
# E.g. "sect." instead of "section"
text_name: Name.parse_name(full_name).text_name,
rank: inat_taxon[:rank].titleize
).
# iNat doesn't have taxon names "sensu xxx"
# so don't map them to MO Names sensu xxx
where.not(Name[:author] =~ /^sensu /)

best_mo_name(mo_names)
end

# For infrageneric ranks, the iNat `:name` string is only the epithet.
# Ex: "Distantes"
# So get a complete string. Ex: "Morchella section Distantes"
def full_name
if infrageneric?
genus_rank_epithet
else
inat_taxon[:name]
end
end

def infrageneric?
%w[subgenus section subsection stirps series subseries].
include?(inat_taxon[:rank])
end

def genus_rank_epithet
# Search the identifications of this iNat observation
# for an identification of the inat_taxon[:id]
inat_identifications.each do |identification|
next unless identifies_this_obs?(identification)

# search the identification's ancestors to find the genus
identification[:taxon][:ancestors].each do |ancestor|
next unless ancestor[:rank] == "genus"

# return a string comprising Genus rank epithet
# ex: "Morchella section Distantes"
return "#{ancestor[:name]} #{inat_taxon[:rank]} #{inat_taxon[:name]}"
end
end
end

def identifies_this_obs?(identification)
identification[:taxon][:id] == inat_taxon[:id]
end

def best_mo_name(mo_names)
return Name.unknown.id if mo_names.none?
return mo_names.first.id if mo_names.one?

Expand Down
18 changes: 18 additions & 0 deletions test/models/inat_obs_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,24 @@ def test_name_sensu
assert_equal(names(:coprinus).text_name, mock_inat_obs.text_name)
end

def test_infrageneric_name
name = Name.create(
user: rolf,
rank: "Section",
text_name: "Morchella sect. Distantes",
search_name: "Morchella sect. Distantes Boud.",
display_name: "**__Morchella__** sect. **__Distantes__** Boud.",
sort_name: "Morchella {2sect. Distantes Boud.",
author: "Boud.",
icn_id: 547_941
)

mock_inat_obs = mock_observation("distantes")

assert_equal(name.id, mock_inat_obs.name_id)
assert_equal(name.text_name, mock_inat_obs.text_name)
end

def test_names_alternative_authors
# Make sure fixtures still OK
names = Name.where(text_name: "Lentinellus ursinus", rank: "Species",
Expand Down

0 comments on commit 285522f

Please sign in to comment.