Repository navigation
Recover OBO idspaces so phenio node categories survive kgx contraction - #202
Merged
Merged
Conversation
kgx's default prefix map carries a generic OBO -> http://purl.obolibrary.org/obo/ entry and no per-ontology entry for DDPHENO, EMAPA, XAO, ZFA, ZFS, CHR, FBbt or WBbt, so their IRIs contract to OBO:DDPHENO_0000001. phenio_node_sources.py looks the category up by CURIE prefix, and NODE_SOURCES has no category under "OBO", so these nodes keep the generic biolink:NamedThing. 51,971 nodes -- including all 1,373 DDPHENO terms -- have been untyped since kg-phenio 20260603, when kgx 2.6.0 -> 2.7.0 restored the previously-wiped default prefix map for TsvSource and everything inheriting it. Split the local part back into its idspace before the lookup, replacing the XPO and HsapDv special cases with the general rule. Node IDs are left as-is: universalizer rewrites them during normalization and they have to stay in step with the edge endpoints phenio_edge_sources.py writes. Verified through the koza transform on real kgx 2.7.0 output -- the eight ontologies regain the categories they had in 20260508, with identical IDs, row count and columns. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
|
Thanks @AO33 ! |
caufieldjh
approved these changes
Aug 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every monarch-kg release from
2026-06-03on types DDPHENO (Dictyostelium phenotype) terms asbiolink:NamedThinginstead ofbiolink:PhenotypicFeature. It isn't just DDPHENO — 51,971 phenio nodes across eight ontologies lost their category between kg-phenio20260508and20260603:biolink:PhenotypicFeaturebiolink:NamedThingbiolink:AnatomicalEntitybiolink:NamedThingbiolink:AnatomicalEntitybiolink:NamedThingbiolink:AnatomicalEntitybiolink:NamedThingbiolink:AnatomicalEntitybiolink:NamedThingbiolink:AnatomicalEntitybiolink:NamedThingbiolink:MolecularEntitybiolink:NamedThingbiolink:LifeStagebiolink:NamedThingDownstream consumers that gate on category silently lose data. Anything selecting
biolink:PhenotypicFeatureneighbours drops Dictyostelium entirely, despite its 2,716has_phenotypeedges being present and intact.Cause
kgx 2.7.0 made
TsvSource.set_prefix_mapadditive rather than destructive, restoring kgx's 631-entry default prefix map for every source inheriting it — includingObographSource. That map carries a genericOBO -> http://purl.obolibrary.org/obo/entry and has no per-ontology entry for the eight ontologies above, so the generic prefix now wins IRI contraction:(FYPO, HP, MP, MONDO, CHEBI, UBERON and friends are unaffected — they have their own entries.)
phenio_node_sources.pylooks the category up by CURIE prefix.NODE_SOURCEShas no category under"OBO", so the genericOntologyClass -> NamedThingremap is never upgraded to the specific category. The pre-existingif node_curie_prefix == "OBO"branch recovered only XPO and HsapDv — the same bug class, patched by hand twice.Fix
split_generic_obo_curie()splits the local part back into its idspace before the lookup, replacing the two special cases with the general rule. Case is preserved, soFBbtstaysFBbt. Only well-formed<idspace>_<localid>local parts are split, so relation IRIs (OBO:fbbt#has_function_in), sub-namespaces (OBO:go/extensions/ro_0002092) and multi-underscore IDs (OBO:FBbt_root_00000000) keep the behaviour they already have.Node IDs are deliberately left as-is. universalizer rewrites them during normalization, and they have to stay in step with the edge endpoints
phenio_edge_sources.pywrites — rewriting them here alone would leave node IDs atFBbt:while universalizer'sobo_handle()still uppercased the edge endpoints toFBBT:, sending every FBbt/WBbt edge to the dangling pile.Verification
Driven through the real koza transform (
transform_sourcewithphenio_node_sources.yaml) over a fixture built from real kgx 2.7.0 obojson output:Same fixture on
mastervs this branch: the delta is exactly eight category changes and nineinforeschanges. Identical IDs, identical header, same row count in and out. Every recovered category matches what20260508shipped, so this restores the pre-regression state rather than introducing new typings.The new tests fail without the fix (all 10 category cases and 3 split cases). Full suite passes,
ruff check kg_phenio testsclean.Downstream checks
BAD_PREFIXESis tested before the split, on the un-recovered prefix, so recovery can't newly exclude a node.update_categoriesoverwrites only when the nodefile category is""orbiolink:OntologyClass, so the recovered specific categories survive normalization;namespace_cat_mapis empty, so there's no ns_map path either.RETAINED_CAT_LISTshort-circuit (PhenotypicFeature subjects skip thebiolink:categoryedge loop, including itsremove_edgesbookkeeping) is inert here:phenio_edge_sources.pyalready dropsbiolink:categorypredicates, so no such edge reaches the merged edge file.named thingdescendants, sotransform_phenio'svalid_node_categoriesfilter keeps them; nothing there branches onNamedThing, andqc_expect.yamlasserts only total phenio node/edge minimums, which don't change.Out of scope
FBbt->FBBT/WBbt->WBBTuppercasing. universalizer'sobo_handle()uppercases the prefix unconditionally, so anyOBO:-collapsed mixed-case idspace comes out wrong. That is the actual source of the casing problem — normalize.py: use merged.monarch context (fixes FBbt/WBbt prefix uppercasing) #201 targeted the prefixmaps context and the20260808release still shipsFBBT:. Fixing it means rewriting IDs in the node and edge transforms in lockstep; monarch-ingest currently normalizes the case on its side. Worth a follow-up.phenio_edge_sources.py's own OBO handling ((subject.split("_"))[0][4:]). It only feeds the edgeprimary_knowledge_source, and switching it to the shared helper would change infores values for relation-IRI subjects. Left alone.OBO:one would fix this for every kgx consumer, but it shifts IDs broadly and belongs upstream on its own release cycle. Happy to open an issue there.