clean_names() recognizes a much wider set of taxonomic
qualifiers and rank abbreviations. Previously an unrecognized marker
survived into the cleaned name, so the name no longer matched the
backbone’s bare binomial/trinomial (it dropped to fuzzy) and the
annotation was lost from the qualifier column. Now folded
to their canonical tokens: the subspecies abbreviations
ssp. and nssp. and the spelled-out
subspecies (to subsp.); the sensu-stricto form
s.s. (to s.str.); the forma spellings
fo. and forma (to f.); the
infraspecific ranks subvar., subf., and
convar.; the notho- (hybrid) ranks nothosubsp.
and nothovar. (to subsp./var.,
the hybrid signal being carried separately by the multiplication sign);
cultivar cv.; the pathogen infrasubspecific categories
f. sp. (forma specialis, previously mislabelled as a bare
forma) and pv. (pathovar); the determination marker
nr. (“near”); the open-nomenclature markers
indet. and sp. nov.; the long and bare concept
forms s. lat. and coll. (to
s.l.); and the species-group markers group and
gr.. Each token matches only as a whole trailing word, so
it never touches a real epithet (Carex novae-zelandiae and
Convallaria majalis are untouched). The qualifier registry
in R/clean.R remains the single source of truth for every
spelling.taxify(x, backend = "wcvp") matches against Kew’s World
Checklist of Vascular Plants (Govaerts et al. 2021, ~1.4M names, CC BY
4.0); backend = "lcvp" matches the Leipzig Catalogue of
Vascular Plants (Freiberg et al. 2020, MIT). Both slot into the fallback
chain (backend = c("wcvp", "wfo")) and contribute their
genera (kingdom Plantae) to the unified genus register. Fifteen
backbones are now available.taxify() does not. synonyms() lists every
synonym that resolves to a name’s accepted taxon (the reverse of the
forward resolution). add_classification() fills the higher
ranks (kingdom, phylum, class, order) from the matched backbone,
complementing the family and genus already in
the core output. children() lists the accepted taxa within
a genus or family, for building a checklist rather than only validating
one. taxify_candidates() expands an ambiguous match
(is_ambiguous) into one row per candidate accepted taxon,
so homonyms can be resolved by hand.taxify() gains an aggregate_fallback
column that makes the default aggregates = "preserve"
accountable. Where a backbone carries no dedicated aggregate taxon for
an aggregate query, preserve falls back to the nominal binomial; that
collapse is now flagged (TRUE on fallback,
FALSE when the aggregate taxon was matched, NA
for non-aggregate queries and under collapse) rather than
being silent. Only Euro+Med (433 aggregate taxa) and WoRMS (189) carry
them, so preserve is a no-op for the other backbones – the flag now says
so per row.add_kew_sid() opens the Kew Seed Information Database
(SER-SID, CC BY 2.0): seed weight (thousand-seed weight over 42,000
species), storage behaviour (orthodox/recalcitrant/intermediate), oil
and protein content, life form, and fruit type, joined on
accepted_name across 50,146 accepted names. Verified
end-to-end (Quercus robur 3493 g/1000 seeds and recalcitrant;
Helianthus annuus 43.5% seed oil). Its seed weight also joins
the cross-source add_trait("seed_mass") verb as a seventh
source (a thousand-seed weight in grams equals the per-seed mass in mg;
grounded at ratio 1.00 against Diaz, BIEN, and AusTraits), roughly
doubling seed-mass species coverage.add_edwards_phyto() opens the Edwards et al. (2015)
phytoplankton nutrient-utilization database (~130 species): Droop/Monod
uptake and growth parameters for ammonium, nitrate, and phosphorus
(mu/k/vmax/qmin/qmax),
plus cell volume, carbon content, taxonomic group, and marine/freshwater
habitat. A curated core attaches by default; cols = "all"
surfaces every uptake parameter. Door-only (single-source physiology
with no cross-source analogue), so it stays out of the
add_trait() verb. Verified end-to-end (Alexandrium
catenella recovered as a marine dinoflagellate).add_trait() traits covering algae,
marine-benthic invertebrates, and octocorals, each grounded on its
source’s own vocabulary before wiring. Algae (AlgaeTraits):
calcification, gamete_type,
algal_life_cycle (dominant ploidy phase),
algal_substrate. Marine benthos, harmonized across two
sources (Arctic Traits + New Zealand Trait Database):
bioturbation (Solan/Queiros functional groups),
living_habit, feeding_guild. Octocoral
(Gomez-Gras et al. 2024): skeletal_rigidity,
colony_growth_form. Verified end-to-end (Corallina
calcified-articulated, Fucus diplontic, Laminaria haplodiplontic; the
bryozoan Alcyonidium gelatinosum an attached suspension-feeder with no
bioturbation).add_trait() traits, each
grounded on its source’s own values before wiring:
gc_content (prokaryote genome GC %, Madin et al.
sporulation (endospore formation, same source),
extending the prokaryote block; larval_nutrition (bee
larval food, EuPollTrait); colour_lightness (beetle body
greyness 0-255, saproxylic beetle traits, a melanism axis);
cell_surface_area (microalgae, um2, Rimet et al., alongside
cell_length/cell_width/cell_thickness/cell_biovolume);
carapace_length (turtle, mm, TurtleTraits); and
parental_care (fish Balon reproductive guild
guarder/non-guarder/bearer, Beukhof et al. 2019). Verified end-to-end
(Thermus aquaticus GC 67%, Bacillus subtilis sporulates, leatherback
carapace 2.26 m, stickleback a guarder).
add_trait("fruit_type") also gains AusTraits as a third
plant source.add_trait() traits, each grounded on the
source’s own values before wiring: zooxanthellate (coral
symbiotic state, from the Coral Trait Database and the octocoral
dataset, which share the zooxanthellate/azooxanthellate vocabulary),
optimal_growth_ph (prokaryote, from Madin et al. 2020, the
pH companion to optimal_growth_temperature), and
cell_thickness (microalgae, from Rimet et al., alongside
the existing
cell_length/cell_width/cell_biovolume).add_trait("diet_guild") now also draws on EltonTraits
(Wilman et al. 2014), extending diet guilds from birds and reptiles to
mammals. The guild is derived from the ten EltonTraits diet fractions
(built into elton_traits.vtr) and agrees 93% with
EltonTraits’ own diet classification and 83% with AVONET.
add_elton_traits() exposes the same diet_guild
column directly.add_trait("ellenberg_salt") gains Baseflor as a third
source: its salinity column is on the same 0-9 Ellenberg scale as
FloraWeb and Ecoflora (Pearson r = 0.88 on shared species), so it joins
them without rescaling.add_trait() traits egg_length and
egg_width (mm) gather reptile, bird, and turtle egg
dimensions from the Amniote database, ReptTraits, and TurtleTraits,
which agree to within measurement noise on shared species.add_trait("brain_mass") (g) coalesces COMBINE with
AnimalTraits (kg converted to grams), calibrated 1:1 on shared
species.reproductive_frequency now spans mammals through reptiles
and turtles (AnAge, PanTHERIA, ReptTraits, TurtleTraits added);
clutch_litter_size gains turtles (TurtleTraits) and birds
(Birdbase); age_at_maturity gains turtles and fish
(TurtleTraits, Beukhof); and longevity gains fish (Beukhof,
whose ~390 yr maximum is the Greenland shark).add_trait("pollination_vector") gains FloraWeb and
AusTraits, which agree 82-91% with the existing Baseflor and Ecoflora
sources on shared species. Named insect taxa (bee, beetle, fly, …)
resolve to insect; AusTraits’ coarse
biotic/abiotic and animal (bird, bat) records
have no single vector in this vocabulary and stay NA rather
than being guessed.add_trait() traits, each numeric source
shared-species calibrated (ratio ~1.00) against a co-registered source
before it was added: male_maturity (yr; AnAge, Amniote,
COMBINE – the male analogue of age_at_maturity),
incubation_period (days; Amniote, TurtleTraits egg
incubation, kept separate from the combined
gestation_incubation), diet_breadth (count of
dietary categories; COMBINE, PanTHERIA, Birdbase),
tongue_length (mm; Ostwald, EuPollTrait bee proboscis),
aspect_ratio (caudal-fin aspect ratio; Beukhof, Quimbayo),
and foraging_mode (active/ambush/mixed; ReptTraits,
TurtleTraits).add_trait("diet_guild") gains TurtleTraits and
Blanchard ant diets, mapped to the guild vocabulary by ordered regex
(compound “omnivorous to carnivorous” resolves to its primary guild; ant
“predator” to carnivore).add_trait() traits:
reproductive_mode (oviparous/ovoviviparous/ viviparous;
ReptTraits plus Sharkipedia, whose shark strategies collapse to
viviparous); the coral-habitat traits coloniality,
wave_exposure, and water_clarity (Coral Trait
DB and octocoral, sharing one vocabulary); and
head_length/head_width (mm; amphibian and
beetle morphometrics). The depth traits
depth_min/depth_max gain coral
occurrence-depth limits (Coral Trait DB, octocoral) in the same metres
unit as the fish sources.add_trait() traits, including a new
prokaryote domain from Madin et al. (2020): gram_stain,
oxygen_metabolism, cell_shape,
optimal_growth_temperature (deg C), and
genome_size (bp). Also caudal_fin_shape
(Beukhof + Quimbayo fish fin shape), voltinism (generations
per year; Arthropod Traits + EuPollTrait), migration
(AVONET), flightless (BIRDBASE), venomous
(ReptTraits), and sociality (EuPollTrait bees).
thermal_max gains Pottier amphibian CTmax on the same
degrees-C scale.add_trait() traits: wingspan
(mm; LepTraits butterflies, whose source column is labelled mm but is
actually cm, corrected on the known wingspans of monarch, cabbage white,
and swallowtail); leaf_length and leaf_width
(mm; AusTraits); fungal_trophic_mode (FUNGuild and
FungalTraits); feeding_mode and mouth_position
(fish; Beukhof, Quimbayo); air_breathing (FishBase);
motility (prokaryote; Madin); and lecty (bee
pollen host breadth; EuPollTrait).content_id (an md5 of
the built .vtr); a static cache is reconciled against it
entirely offline, re-downloading only when the bytes actually changed. A
pre-existing cache with no stored id is hashed in place, so an unchanged
asset is adopted without a download. Fixes stale
add_nesttrait() nest-modality columns and
add_disperse() bin-midpoint columns for anyone who cached
those before the rebuild. Every enrichment asset now carries a content
id, and the same gate is extended to backbones (a content id catches a
same-tag republish that a version bump would miss). The read-only
example database and its offline fixtures are never touched.add_trait() now joins genus-keyed sources on
genus: the ant-diet contribution to diet_guild
(Blanchard) was silently all-NA, and fungal_trophic_mode’s
FungalTraits source likewise. A registry guard test now asserts every
genus-keyed source is joined correctly.add_trait() attaches a single trait across every
source that carries it, reconciling their vocabularies and units. Where
each add_*() door joins one dataset,
add_trait("seed_mass") gathers the sources: it pulls seed
mass from Diaz et al. and GIFT and returns both in one unit (mg),
woodiness from Zanne and GIFT in one vocabulary, and likewise plant
height and SLA. The default mode = "coalesce" adds one
value per row with the columns that document it –
seed_mass, seed_mass_unit,
seed_mass_sources, and seed_mass_n – which
keeps chained calls tidy; mode = "wide" instead gives one
harmonized column per source (seed_mass_diaz,
seed_mass_gift) to inspect agreement and conflict. When
sources measure a trait by different methods (for example maximum vs
fine-root diameter), the value is not blended: the most complete source
is reported and a seed_mass_caution column explains the
difference. list_traits() lists the available traits and
trait_info() shows a trait’s sources, units, harmonization
notes, and cautions. The registry ships dozens of traits spanning plant
functional and root traits, animal body size, life history and
morphology, diel activity, thermal limits, phenology, indicator values,
and conservation status, each with a crosswalk grounded on the source
values rather than assumed.Enrichment doors are named after their source; the trait name is
reserved for add_trait(). add_woodiness(),
add_conservation_status(),
add_invasive_status(), and add_fish_traits()
are renamed to add_zanne() (Zanne et al. 2014),
add_iucn() (IUCN Red List), add_griis()
(GRIIS), and add_fishmorph() (FISHMORPH; also avoids
confusion with add_fishbase()). The old names are removed,
not deprecated – they never appeared in a release.
New add_gift() joins plant traits from GIFT, the
Global Inventory of Floras and Traits (Weigelt et al. 2020), by accepted
name. GIFT’s API exposes only the subset of its data it may redistribute
(CC BY 4.0; restricted references excluded); taxifydb fetches that
subset once at build time and it ships as a pre-built .vtr,
so add_gift() joins it offline like every other enrichment
– no runtime API calls. Choose which traits to attach via
cols= (any gift_ column names, or
"all"); the default is a convenient set of well-populated
ones (woodiness, growth form, life cycle and form, habit flags, height,
photosynthetic pathway, seed mass, dispersal, flowering months,
deciduousness, SLA). gift_traits() browses the available
columns.
reptiledb backend: the Reptile Database (Uetz et
al.), the global taxonomic reference for reptiles (snakes, lizards,
amphisbaenians, turtles, crocodiles and the tuatara). It carries ~12.6k
accepted species plus ~34k synonyms with full genus/family
classification, filling the one vertebrate class the other backbones
cover only partially. Use it like any backbone:
taxify(x, backend = "reptiledb"). License: CC-BY 4.0.add_repttraits() joins species-level reptile traits
from ReptTraits (Oskyrko et al. 2024) by accepted name. Beyond body-size
and life-history traits, it carries a per-species distribution signal –
biogeographic realm, elevation range and mean climate – across all
reptiles. This replaces the earlier add_lizard_traits(),
which drew on the same ReptTraits source but was mislabelled (it covered
all reptiles, not lizards) and exposed only the morphology columns.
License: CC-BY 4.0.inspect() flags probable typos and other anomalies
in a name list and returns only the anomalous rows, each labelled with
what stands out and, where known, the name to use instead.
inspect() does not match names against backbones itself –
that is taxify()‘s job. On a character vector it runs the
checks that need no matching: unknown (the genus is not in
the genus register, the union of all 13 backbones’ genera, so no
backbone recognises it – a real “probably not a name”),
near_duplicate (a near-twin of a more frequent name in the
same list, computed from the list alone, so it catches typos in names no
backbone contains), and outlier_group (a name whose kingdom
group is a tiny minority of an otherwise coherent list – the lone animal
or fungus among plants). To also surface the match-based anomalies, opt
in with backbones = TRUE (matches against every installed
backbone, listed in the report header) or match yourself first and
inspect the result – taxify(x) |> inspect() – which adds
typo (fuzzy-corrected spelling), synonym
(outdated name), ambiguous (homonym), case,
and the geographic checks geographic (a species with no
WCVP record in a declared region/coords) and
out_of_range (no region declared, yet the species’ range
falls outside the list’s main TDWG continents; skipped for globally
spread lists). Rows are ordered most-notable first and carry a
suggestion; each gets a tier describing what
it needs, not how bad it is: unresolved (no usable name),
review (a name is there but its identity is uncertain), or
note (correct, optional cleanup) – an anomaly may be
intended. inspect() is read-only: it never alters the input
or applies a correction. Narrow with min_tier. The
list-context labels cannot apply to a single name, so
inspect() on one name warns.taxify() gains a region argument for
geographically constrained fuzzy matching. Pass TDWG botanical regions
to restrict fuzzy candidates to species with WCVP
records in those regions; exact matches are always kept.
region accepts Level 3 codes (region = "BGM")
or region names at any level, matched case- and accent-insensitively
against a bundled WGSRPD crosswalk: a botanical country
("Belgium"), a Level 2 region
("Middle Europe"), or a Level 1 continent
("Europe", expanded to all its codes). The new
coords argument takes a c(lon, lat) pair or a
matrix/data.frame of coordinates and maps them to regions by
point-in-polygon against the WGSRPD Level 3 boundaries (downloaded and
cached on first use); region and coords are
unioned. coords also accepts an
sf/sfc object or a terra
SpatVector of points (reprojected automatically). The
point-in- polygon test uses terra or sf when
installed and falls back to a native implementation otherwise; the
engine can be forced with
options(taxify.pip_engine = "terra" | "sf" | "native"). The
filter only narrows genuinely ambiguous fuzzy candidates – a candidate
is dropped only when the same input name has another candidate that is
in-region or has no WCVP range data – so non-plant matches are never
affected and a name whose only candidate is out-of-region is still
returned. The companion range argument selects which WCVP
statuses count as in-region: "present" (default, any
record), "native", or "introduced".taxify_regions() lists the WGSRPD Level 3 botanical
regions (codes and names) used by region and by
add_wcvp(), with an optional search term."fishbase" (FishBase, ~36k
accepted fish species) and "sealifebase" (SeaLifeBase,
~100k accepted non-fish aquatic species). Both resolve synonyms to their
accepted names and carry kingdom / phylum / class / order
classification. Use them like any other backbone, e.g.
taxify("Gadus morhua", backend = "fishbase").add_sealifebase() joins SeaLifeBase morphological and
ecological traits (body length, mass, trophic level, depth range,
vulnerability, habitat, commercial importance) to a
taxify() result. It is the non-fish companion to
add_fishbase().add_groot() joins species-level root traits from the
Global Root Traits (GRooT) database: root diameter, specific root
length, tissue density, N and C concentration, root mass fraction,
lateral spread, mycorrhizal colonization and rooting depth (per-species
means for 6,154 vascular plant species).add_qualifier_info() has been removed.
taxify() now reports the qualifier natively (see New
features), so a separate parsing pass is no longer needed. Replace
taxify(x) |> add_qualifier_info() with
taxify(x). Note the integer qualifier_position
(a character index) is replaced by a two-value "genus" /
"species" placement.taxify() gains an aggregates argument, default
"preserve": an aggregate name ("... agg.",
"... s.l.") matches the backbone’s aggregate taxon where
one exists (for example in Euro+Med and WoRMS), otherwise it falls back
to the binomial species. aggregates = "collapse" keeps the
previous behaviour of stripping the marker and matching the
binomial.taxify() output carries two new columns.
qualifier is the canonical taxonomic qualifier with
spelling variants folded to one token ("aggr.",
"agg" and "sensu lato" map to
"agg." / "s.l.").
qualifier_position is "genus" for a leading
prefix ("Cf. Pinus sylvestris") and "species"
for an inline or trailing qualifier
("Pinus cf. sylvestris",
"Rubus fruticosus agg.")."... aggr."), and an aggregate query reaches
the aggregate-level trait. A single species’ trait is never propagated
up to the aggregate. Set
options(taxify.trait_provenance = TRUE) to add a
<enrichment>_inherited flag marking the inherited
values.normalize_aggregate_name() and
is_aggregate_name() (build-time helpers) so the taxifydb
build pipeline folds every backbone and enrichment aggregate marker
(agg, aggr., -agg,
s.l., sensu lato, coll., and
aggregate ranks such as SPECIES AGGREGATE) to one canonical
aggr. form. The runtime and build sides therefore recognize
aggregates uniformly across all backbones.summary() now counts abbreviated-genus matches
(match_type == "abbrev", e.g. "Q. robur").
Previously these were resolved correctly in the result but omitted from
the matched total and its breakdown, so the digest
under-reported the number of matched names. The matched
line now reads (exact, case-insensitive, fuzzy, abbrev),
and match_tally carries an abbrev count.add_fungalroot()
(genus-level mycorrhizal type), including the genus-keyed join and the
type vocabulary, and stacks it into the European and global
vascular-plant guidance.add_fungalroot() joins genus-level mycorrhizal type
from the FungalRoot database (Soudzilovskaia et al. 2020, GBIF
doi:10.15468/a7ujmj, CC BY-NC 4.0) to a taxify() result.
Because mycorrhizal type is conserved at the genus level, the join is on
genus, so any species in a covered genus is annotated with
mycorrhizal_type (AM, EcM,
ErM, OM, NM, the dual types,
Other, or uncertain),
mycorrhizal_status, and the supporting record count. Plant
genera only.Cf. prefix
(e.g. "Cf. Pinus sylvestris") is now recorded as the
cf. qualifier by clean_names(),
clean_one(), and add_qualifier_info().
Previously the prefix was stripped before matching but the qualifier was
lost, so only inline cf.
(e.g. "Pinus cf. sylvestris") was reported.
add_qualifier_info() now also matches the prefix
case-insensitively and reports qualifier_position = 1.taxify_data_dir() can now be redirected with the
taxify.data_dir option or the TAXIFY_DATA_DIR
environment variable, so the cache location is configurable (shared
caches, scratch directories, the bundled example data).taxify_example_data() returns the path to a small
bundled example database (a handful of species per backbone plus
matching enrichment tables). Setting
options(taxify.data_dir = taxify_example_data()) lets
matching and enrichment run fully offline.\dontrun{}. Only
add_pignatti() (fetched live via TR8) and
list_enrichments() (reads the online manifest) remain in
\donttest{}.add_floraweb() joins German-flora plant traits from
FloraWeb (the live BfN portal carrying the BiolFlor data of Klotz, Kuehn
& Durka 2002, plus Rothmaler morphology and Ellenberg indicator
values). It bundles the full per-species trait profile – morphology,
reproductive biology, the nine Ellenberg indicator values, ploidy and
chromosome number, and chorological distribution (59 _de
columns) – as a pre-built dataset, so it works offline.add_ecoflora() now joins a bundled, pre-built
Ecoflora dataset (18 _uk columns: canopy height, leaf
traits, life form, flowering phenology, pollination, seed weight, and
British-calibrated Ellenberg values) instead of fetching live through
TR8. It works offline and returns the full trait set rather than the
previous five columns.
add_pignatti() remains an on-demand TR8 source: its
values are from a copyrighted publication and cannot be
redistributed.
add_ecoflora(), add_biolflor(), and
add_pignatti() join plant traits that taxify does not ship
as a pre-built dataset, accessing them on demand through the suggested
TR8 package on your own machine; taxify redistributes nothing. The
reasons differ by source: add_ecoflora() adds British
flowering months, pollen vector, life form, and leaf longevity (CC
BY-NC-SA, which would allow redistribution, but ecoflora.org.uk has no
bulk download, so it is fetched live per species);
add_biolflor() adds Grime CSR strategy type, breeding
system, pollen vector, life form, life span, and apomixis (usable with
acknowledgement + citation per the BioFresh metadata statement, but no
bulk copy is obtainable while the UFZ site is offline, so fetched live);
add_pignatti() adds Italian Ellenberg-type indicator
values, life form, and chorotype (copyrighted; read from the copy
bundled in TR8, which TR8 redistributes, not taxify; works offline).
Columns are region-suffixed
(_uk/_de/_it) so they never
collide with add_baseflor(). TR8 is a Suggests dependency.
If a live source (Ecoflora, BiolFlor) is unreachable the call errors
rather than attaching silent NA.add_baseflor() joins plant traits from Baseflor
(Programme Catminat, Julve 1998 ff.; ODbL 1.0 / CC BY-SA 2.0) to a
taxify() result. It covers ~7,000 vascular plant taxa of
France and neighbouring regions and adds flowering phenology
(flower_begin_month, flower_end_month),
pollination vector, dispersal mode, breeding system, flower colour,
fruit type, woody growth form, and the continentality and salinity
indicator-value axes absent from EIVE. The enrichment is registered in
the manifest (list_enrichments()) with a pre-built
.vtr; light/temperature/moisture/reaction/nutrient axes are
left to add_eive() and Raunkiaer life form to
add_leda().tests/e2e/test-e2e-enrichment.R) for the enrichment join
fixed in 0.2.5 (#1). It checks that
add_conservation_status(), add_common_names(),
and add_woodiness() attach each value to the row’s own
accepted taxon, stay invariant to batch composition and order, and land
documented values on the correct species."Q. robur" now resolve.
A matching pass restricts the backbone to rows whose genus starts with
the given initial and whose specific epithet matches, resolving only
when that is unique. When two or more genera sharing the initial also
share the epithet the abbreviation is ambiguous: the row is left
unmatched with is_ambiguous = TRUE and the conflicting
accepted IDs in ambiguous_targets, rather than guessing a
genus. A genus spelled out in full elsewhere in the same input takes
precedence (the convention of abbreviating after first mention).
Resolved rows carry match_type = "abbrev".accepted_authorship output column: the authorship
of the resolved accepted name. For a synonym match,
authorship holds the synonym’s own author while
accepted_authorship holds the accepted name’s author, so
accepted_name and accepted_authorship together
form the accepted taxon’s full citation. Backbones that carry authorship
populate it; sources without authorship (NCBI, OTT) return
NA.taxify() no longer errors with “replacement has length
zero” for backbones whose .meta sidecar records the build
date as build_date (the current taxifydb build format)
rather than download_date. Backbone metadata now reads both
layouts and version formatting tolerates a missing date. This previously
broke matching against the WoRMS and Open Tree of Life backbones.Additional_repositories (https://gcol33.r-universe.dev), so
its location is discoverable as required for a Suggests dependency
outside the mainstream repositories.taxify() no longer errors with “incorrect number of
dimensions” when the genus register is present but the backend-coverage
file is not (the state on a clean install before any coverage download,
and during package checks). An early return() evaluated
inside a tryCatch() expression returned NULL
from the pre-filter, which $<- then turned into a list;
the out-of-scope pre-filter now resolves missing coverage to a no-op and
preserves the result data frame.
Replaced non-ASCII characters in roxygen documentation with ASCII equivalents so the PDF reference manual builds under LaTeX.
Ambiguous homonym synonyms now resolve to the epithet-preserving
accepted name (the homotypic basionym) instead of an arbitrary lowest-id
candidate. taxify("Pinus abies") resolves to Picea
abies (not Picea polita), and the spurious
is_ambiguous flag is cleared when one candidate keeps the
specific epithet (#2). Genuinely ambiguous names (no candidate, or
several, preserving the epithet) are still flagged.
Silenced tidyselect deprecation warnings emitted during fuzzy matching.
score_candidates() is exported (kept internal in the
reference index) so the companion taxifydb build pipeline
can collapse each backbone key to the single accepted name
taxify() resolves it to. This corrects enrichment joins
that previously landed trait/status values on within-genus neighbours
(#1); the fix reaches users through rebuilt enrichment data.