Skip to content

fix: default BUSCO lineage when predict cannot resolve taxonomy - #94

Merged
nextgenusfs merged 1 commit into
nextgenusfs:mainfrom
vinvomero:fix/predict-missing-taxonomy
Aug 24, 2026
Merged

fix: default BUSCO lineage when predict cannot resolve taxonomy#94
nextgenusfs merged 1 commit into
nextgenusfs:mainfrom
vinvomero:fix/predict-missing-taxonomy

Conversation

@vinvomero

Copy link
Copy Markdown
Contributor

Summary

Fixes #93. funannotate2 predict aborts with AttributeError: 'bool' object has no attribute 'get' when no taxonomy is available for the species: lookup_taxonomy() returns False on any JGI API failure (offline, 5xx, unrecognized name), and the training-data fallback params["taxonomy"] is also False for a novel/unpublished organism. The crash lands at the BUSCO-lineage selection step — after the ab initio predictions have already run — so a long run is lost to a late failure on exactly the "taxonomy unavailable" case.

While fixing this I also found a latent, separate issue on the same path: for a non-empty taxonomy that matches nothing in busco_taxonomy, best_taxonomy() falls through to random.choice(), so a random (but valid) BUSCO lineage is selected non-deterministically — and because the pick is always a valid key, a result in busco_taxonomy check can't catch it.

What this does

  • Adds busco_lineage_from_taxonomy() in utilities.py — a small pure helper that resolves a valid lineage deterministically. It returns a default (fungi) unless the taxonomy genuinely overlaps the reference on superkingdom/kingdom, and otherwise returns the matched lineage. This closes both the crash and the random-lineage path.
  • Routes predict() through the helper, defaulting to the fungi lineage and logging a clear warning that names the species and flags that a generic lineage is unreliable for a non-fungal genome (there is no --busco-lineage/--taxonomy override on predict, so it self-heals rather than aborting).
  • Hardens the offline branch to params.get("taxonomy"), so a params file that predates the taxonomy key no longer KeyErrors before the guard runs.

Tests

Adds regression, determinism, and edge-case coverage in tests/unit/test_utilities_taxonomy.py: the #93 crash inputs (False/None), a per-kingdom determinism invariant (so a future busco_taxonomy edit can't silently reintroduce the random tie-break), and non-string / partial / exact-match cases. All taxonomy unit tests pass locally.

Note — possible follow-up

I scoped this PR to predict to match the issue. The same "taxonomy can be False" pattern also reaches choose_best_busco_species() in annotate.py and train.py (and choose_best_augustus_species() in train.py), so funannotate2 annotate / train can hit the same crash class on their default (no --busco-lineage / --augustus-species) path. Happy to send a focused follow-up routing those call sites through the same helper if you'd like it — kept out of this PR to keep it reviewable.

🤖 Generated with Claude Code

`funannotate2 predict` crashed with "AttributeError: 'bool' object has no
attribute 'get'" when neither the JGI taxonomy lookup nor the training-data
fallback yielded a taxonomy (e.g. a novel/unpublished organism, or offline).
Separately, for a non-empty taxonomy that matched nothing in busco_taxonomy it
selected a *random* BUSCO lineage: best_taxonomy() falls back to
random.choice(), and that pick is always itself a valid key, so a
"result not in busco_taxonomy" check can never catch it.

Add busco_lineage_from_taxonomy() in utilities.py, which resolves a valid
lineage deterministically: it returns the default unless the taxonomy genuinely
overlaps the BUSCO reference on superkingdom/kingdom, and otherwise returns the
matched lineage. Route predict() through it, defaulting to the "fungi" lineage
and logging a clear warning (naming the species) whenever taxonomy can't be
resolved. Also harden the offline branch to use params.get("taxonomy") so a
legacy params file without the key no longer KeyErrors before the guard runs.

Adds regression, determinism (per-kingdom invariant), and edge-case
(non-string / partial / exact-match) tests in test_utilities_taxonomy.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@nextgenusfs
nextgenusfs merged commit 7709e86 into nextgenusfs:main Aug 24, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

taxonomy lookup error

2 participants