Skip to content

Parse OBO Graph edge axiom annotations into Biolink evidence/provenance slots - #561

Open
kevinschaper wants to merge 1 commit into
masterfrom
obograph-edge-annotations
Open

Parse OBO Graph edge axiom annotations into Biolink evidence/provenance slots#561
kevinschaper wants to merge 1 commit into
masterfrom
obograph-edge-annotations

Conversation

@kevinschaper

Copy link
Copy Markdown
Collaborator

Problem

OWL axiom annotations survive an obographs conversion as edges[].meta, and that is where ontologies record why an assertion was made. MONDO annotates 47,249 of its 113,685 edges; PHENIO carries annotations on 1.42M of 1.67M.

ObographSource.read_edge copied meta verbatim into the record via its catch-all, so it reached the TSV as a Python-repr blob:

id  subject  predicate  object  relation  knowledge_source  meta
…   MONDO:0000004  biolink:subclass_of  MONDO:0002816  rdfs:subClassOf  PHENIO  {'basicPropertyValues': [{'pred': 'http://purl.org/dc/elements/1.1/source', 'val': 'DOID:10493'}, …]}

No evidence or provenance ever reached a Biolink slot.

Change

annotation Biolink slot
prov:wasDerivedFrom primary_knowledge_source (InfoRes CURIE from the ontology file stem)
dc:source / oboInOwl:source routed by value shape — see below
oboInOwl:evidence has_evidence
oboInOwl:is_inferred knowledge_level / agent_type

source values are heterogeneous, so they route by shape: PMID:/doi:publications; ORCID → agent_type=manual_agent; MONDO:Inferred/Entailedknowledge_level=logical_entailment; remaining CURIEs → xref. A curator ORCID outranks the reasoner markers, since the ones MONDO also emits (Redundant, indirect) describe the axiom's position in the hierarchy rather than how it was arrived at. Every raw value is also kept in _source, so nothing is lost.

The same MONDO edge now reads:

primary_knowledge_source  infores:mondo
knowledge_level           logical_entailment
agent_type                automated_agent
xref                      DOID:10493
_source                   DOID:10493|MONDO:Inferred

SSSOM slots and a short alias table (notes, comment, see_also, term_tracker_item, creator, date, editor_note) keep named columns. Everything else folds into _annotations as predicate=value pairs — across PHENIO's components the tail of one-off per-ontology properties (todo, quote, gene, even a misspelled cardonality) is long and nearly empty. Giving each its own column produced 57 edge columns of which ~40 were empty; the catch-all brings that to 25, and on 1.66M PHENIO edges _annotations is non-empty on just 56 rows.

Two data-quality fixes fall out of MONDO's hand-entered values: "PMID: 16322613" loses the stray space, and "PMID:32181500, PMID:32905580" splits into two references instead of one malformed CURIE. Full MONDO run goes from 2 malformed CURIEs to 0.

InfoRes derivation

The stem is used as-is (components/mondo.owlinfores:mondo). Deliberately mechanical: the registry does not agree with every stem — it lists infores:hpo, not infores:hp — and a project's existing IDs should win over a guess. infores_map overrides it, and prepare_input_args now passes that through so it can be set from a transform config YAML rather than only in Python:

input:
  format: obojson
  filename: [phenio.json]
  infores_map:
    hp: hpo

Compatibility

This changes obojson edge output for all consumers: the meta column is gone, replaced by the columns above. Downstream configs that declare meta need updating.

Testing

7 new tests covering InfoRes derivation, value-shape routing, knowledge_level/agent_type precedence, evidence/passthrough, the catch-all, CURIE normalization, and the config passthrough — the last verified to fail without the cli_utils change. Fixture built from real PHENIO/MONDO edges.

381 passed, 19 skipped, 1 failed — the failure is test_sink/test_jsonl_sink.py::test_write_jsonl2, which fails identically on unmodified master.

Validated at scale: full mondo.json (113,388 edges, 47s) and full phenio.json (1.66M edges) — primary_knowledge_source 54.5%, knowledge_level 3.2%, xref 2.8%, agent_type 0.8%.

OWL axiom annotations survive an obographs conversion as `edges[].meta`,
and it is where ontologies record why an assertion was made -- MONDO
alone annotates 47k of its 113k edges. ObographSource copied `meta`
verbatim into the record, so it reached a TSV as a Python-repr blob in a
`meta` column and no evidence or provenance ever landed on a Biolink
slot.

Map the annotations that have Biolink equivalents:

  prov:wasDerivedFrom  -> primary_knowledge_source, as an InfoRes CURIE
                          derived from the ontology file stem
  dc:source /          -> routed by value shape: PMID/doi to publications,
  oboInOwl:source         ORCID to agent_type=manual_agent,
                          MONDO:Inferred|Entailed to
                          knowledge_level=logical_entailment,
                          remaining CURIEs to xref
  oboInOwl:evidence    -> has_evidence
  oboInOwl:is_inferred -> knowledge_level / agent_type

SSSOM slots and a short alias table (notes, comment, see_also,
term_tracker_item, creator, date, editor_note) keep columns of their own.
Everything else folds into `_annotations` as predicate=value pairs:
across PHENIO's components the tail of one-off per-ontology properties is
long and almost empty -- giving each its own column produced 57 edge
columns of which ~40 held nothing, against 25 columns now. Raw `source`
values are also kept verbatim in `_source`, so no annotation is lost.

Two data-quality fixes fall out of MONDO's hand-entered values:
"PMID: 16322613" loses the stray space, and "PMID:32181500, PMID:32905580"
splits into two references rather than one malformed CURIE.

The InfoRes derivation stays mechanical -- the file stem is used as-is --
because the registry does not agree with every stem (it lists "hpo", not
"hp") and a project's existing IDs should win over a guess. `infores_map`
overrides it, and prepare_input_args now passes that through so it can be
set from a transform config YAML instead of only in Python.
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.

1 participant