You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The wrapper only extracts class relationships for a hard-coded set of OBO properties in a single flat axiom shape. Relationships on any other property, and those stated in other (equivalent) ways, are silently dropped, so they never appear in a class's property listing (the Details view). Users have asked why some relationships show up on a class and others do not; this is the cause.
What "relationship extraction" is
The wrapper parses an ontology and emits a normalized RDF/XML export for BioPortal. Part of that job is deriving binary relationships between a named class A and a filler B from the logical axioms that mention A — chiefly SubClassOf and EquivalentClasses axioms whose right-hand side is (or contains) an existential restriction such as p some B. Each derived relationship is re-expressed as a ground triple A p B: an owl:AnnotationAssertion whose predicate is the object property's IRI (punned as an annotation property) and whose subject and object are the two class IRIs. BioPortal's backend reads these annotation assertions off each class, which is what makes a relationship appear in a class's property listing (the Details view) and, for OBO ontologies via a treeView predicate, in its tree hierarchy. This logic lives in OntologyParser.generateGroundTriplesForAxioms.
What the current code does
A relationship is emitted only if all of these hold:
the axiom is exactly SubClassOf(NamedClass, ObjectSomeValuesFrom(P, D)) — no intersections, no equivalences, no hasValue, no cardinality;
P and D are named;
P's IRI contains the substring "obo".
Among those, three fates:
Whitelisted (part_of/BFO_0000050, contains/RO_0001019, develops_from/RO_0002202) → a special metadata/obo/* annotation plus a treeView hierarchy edge.
OBO but not whitelisted → a plain annotation under the property's own IRI, no treeView.
Everything else — non-OBO property, anonymous filler, or any shape other than the flat SubClassOf + someValuesFrom — silently dropped.
Why relationships go missing in the Details view
The Details view is driven by Class#properties in ontologies_linked_data, which surfaces essentially all predicate→value assertions on a class (it is not gated on OBO). So a class shows whatever relationship triples the wrapper emitted for it — and the wrapper only emits for OBO-namespace properties in the one flat shape. Two consequences:
Non-OBO properties are entirely invisible. EDAM has 580 someValuesFrom relationships on has_topic, has_output, has_input, etc. (under edamontology.org, not OBO). Parsing EDAM with the current code emits zero relationship triples (0 metadata/obo/*, 0 treeView). None appear in the Details view.
Even within OBO, coverage is uneven. On UBERON the current code exposes ~3 relation types (part_of, develops_from, contains) and drops the rest — because they either are not whitelisted or are stated in a shape the extractor does not recognize (nested in an intersection, via an equivalence, etc.).
That unevenness — the same modelling construct getting a different fate, decided by a substring check and a hard-coded list — is exactly "why does relationship X show up but not Y?"
History (for context)
All formative work is by msalvadores; the timeline below is taken from the commits.
Only part_of was handled, and it was turned into a subclass edge. If a class had part_of some D (matched by the substring part_of), the code synthesized a real SubClassOf(A, D) axiom and added a metadata/part_of annotation. One property; part_of was effectively flattened into the class hierarchy. (5fee83e, 2013-09-14, NCBO-120)
The property set was fixed and the matching tightened. Substring matching was replaced by exact endsWith on a whitelist; contains/RO_0001019 and develops_from/RO_0002202 were added; the emitted IRIs moved into the metadata/obo/… namespace still used today. (356b573, 2013-09-27)
BFO's part_of IRI was added as a synonym for the shorthand.BFO_0000050 was matched alongside part_of. (e4dc494, 2013-09-27)
A treeView annotation was tried in place of the synthetic subclass, then abandoned. Three commits introduced it, then all three were reverted two weeks later (Dec 2, 2013).
The current form was settled: the logic was extracted into its own method and treeView reinstated. Each whitelisted relation emits an obo/* annotation plus a paired treeView edge; the synthetic subclass was dropped. (d6b43b2, 2015-01-09, NCBO-1152)
No change to the logic since, only a 2022 package rename. It has not changed in a decade.
It is worth remembering the context. In 2013–2015 the relationship between the OBO format and OWL was still being pinned down — the shorthand relation names (part_of), their full IRIs (BFO_0000050), and how OBO stanzas map onto OWL axioms were not as cleanly and consistently defined as they are today. The IRI substring checks and the shorthand-versus-IRI matching read as reasonable pragmatism against that moving target. That mapping is now well specified and stable, so those heuristics are no longer necessary — the relationships can be read directly from the OWL axioms.
Proposed fix
Extract relationships uniformly, for any object property, by walking the class expression:
No privilege: drop the contains("obo") gate and the hard-coded whitelist; emit each relationship under the property's own IRI.
Walk both SubClassOf(A, …) and EquivalentClasses(A, …) of named classes, descending into intersection operands, and emit A --p--> filler for someValuesFrom(p, namedClass), hasValue(p, individual), and min/exact cardinality (n ≥ 1). Also expand an intersection filler, so p some (B and C) yields A p B and A p C.
Do not descend into unions or complements (their operands are not entailed for every instance of A), and do not emit allValuesFrom (a constraint, not an existential relationship).
Once the above is in place, the legacy metadata/obo/* relationship annotations become redundant duplicates and can be removed, keeping only the treeView edges that drive the OBO hierarchy.
Impact, measured
Ontology
Before
After
EDAM
has_topic / has_output / has_input: 0
207 / 147 / 56
UBERON
~3 relation types
~180 relation types (tens of thousands of assertions)
UBERON now surfaces has part, regulates / positively / negatively regulates, occurs in, in taxon, capable of, the BSPO spatial relations, and UBERON's own connectivity relations (channel_for, extends_fibers_into, subdivision_of, sexually_homologous_to, …). Parse time is unchanged (~13s on the 96 MB file).
Still open / follow-ups
The treeView / hierarchy path is still OBO-only and whitelist-based. Broadening it changes the class tree and is deferred pending a decision plus downstream tree testing.
Removing the legacy metadata/obo/* relationship annotations requires a coordinated update to the ontologies_linked_data test test_obo_part_of, which asserts obo/part_of (the treeView assertion is unchanged); no production code reads those predicates.
Summary
The wrapper only extracts class relationships for a hard-coded set of OBO properties in a single flat axiom shape. Relationships on any other property, and those stated in other (equivalent) ways, are silently dropped, so they never appear in a class's property listing (the Details view). Users have asked why some relationships show up on a class and others do not; this is the cause.
What "relationship extraction" is
The wrapper parses an ontology and emits a normalized RDF/XML export for BioPortal. Part of that job is deriving binary relationships between a named class
Aand a fillerBfrom the logical axioms that mentionA— chieflySubClassOfandEquivalentClassesaxioms whose right-hand side is (or contains) an existential restriction such asp some B. Each derived relationship is re-expressed as a ground tripleA p B: anowl:AnnotationAssertionwhose predicate is the object property's IRI (punned as an annotation property) and whose subject and object are the two class IRIs. BioPortal's backend reads these annotation assertions off each class, which is what makes a relationship appear in a class's property listing (the Details view) and, for OBO ontologies via atreeViewpredicate, in its tree hierarchy. This logic lives inOntologyParser.generateGroundTriplesForAxioms.What the current code does
A relationship is emitted only if all of these hold:
SubClassOf(NamedClass, ObjectSomeValuesFrom(P, D))— no intersections, no equivalences, nohasValue, no cardinality;PandDare named;P's IRI contains the substring"obo".Among those, three fates:
part_of/BFO_0000050,contains/RO_0001019,develops_from/RO_0002202) → a specialmetadata/obo/*annotation plus atreeViewhierarchy edge.SubClassOf+someValuesFrom— silently dropped.Why relationships go missing in the Details view
The Details view is driven by
Class#propertiesinontologies_linked_data, which surfaces essentially all predicate→value assertions on a class (it is not gated on OBO). So a class shows whatever relationship triples the wrapper emitted for it — and the wrapper only emits for OBO-namespace properties in the one flat shape. Two consequences:someValuesFromrelationships onhas_topic,has_output,has_input, etc. (underedamontology.org, not OBO). Parsing EDAM with the current code emits zero relationship triples (0metadata/obo/*, 0 treeView). None appear in the Details view.part_of,develops_from,contains) and drops the rest — because they either are not whitelisted or are stated in a shape the extractor does not recognize (nested in an intersection, via an equivalence, etc.).That unevenness — the same modelling construct getting a different fate, decided by a substring check and a hard-coded list — is exactly "why does relationship X show up but not Y?"
History (for context)
All formative work is by msalvadores; the timeline below is taken from the commits.
part_ofwas handled, and it was turned into a subclass edge. If a class hadpart_of some D(matched by the substringpart_of), the code synthesized a realSubClassOf(A, D)axiom and added ametadata/part_ofannotation. One property; part_of was effectively flattened into the class hierarchy. (5fee83e, 2013-09-14, NCBO-120)endsWithon a whitelist;contains/RO_0001019anddevelops_from/RO_0002202were added; the emitted IRIs moved into themetadata/obo/…namespace still used today. (356b573, 2013-09-27)part_ofIRI was added as a synonym for the shorthand.BFO_0000050was matched alongsidepart_of. (e4dc494, 2013-09-27)treeViewannotation was tried in place of the synthetic subclass, then abandoned. Three commits introduced it, then all three were reverted two weeks later (Dec 2, 2013).treeViewreinstated. Each whitelisted relation emits anobo/*annotation plus a pairedtreeViewedge; the synthetic subclass was dropped. (d6b43b2, 2015-01-09, NCBO-1152)It is worth remembering the context. In 2013–2015 the relationship between the OBO format and OWL was still being pinned down — the shorthand relation names (
part_of), their full IRIs (BFO_0000050), and how OBO stanzas map onto OWL axioms were not as cleanly and consistently defined as they are today. The IRI substring checks and the shorthand-versus-IRI matching read as reasonable pragmatism against that moving target. That mapping is now well specified and stable, so those heuristics are no longer necessary — the relationships can be read directly from the OWL axioms.Proposed fix
Extract relationships uniformly, for any object property, by walking the class expression:
contains("obo")gate and the hard-coded whitelist; emit each relationship under the property's own IRI.SubClassOf(A, …)andEquivalentClasses(A, …)of named classes, descending into intersection operands, and emitA --p--> fillerforsomeValuesFrom(p, namedClass),hasValue(p, individual), andmin/exactcardinality (n ≥ 1). Also expand an intersection filler, sop some (B and C)yieldsA p BandA p C.allValuesFrom(a constraint, not an existential relationship).metadata/obo/*relationship annotations become redundant duplicates and can be removed, keeping only thetreeViewedges that drive the OBO hierarchy.Impact, measured
has_topic/has_output/has_input: 0UBERON now surfaces
has part,regulates/positively/negatively regulates,occurs in,in taxon,capable of, the BSPO spatial relations, and UBERON's own connectivity relations (channel_for,extends_fibers_into,subdivision_of,sexually_homologous_to, …). Parse time is unchanged (~13s on the 96 MB file).Still open / follow-ups
treeView/ hierarchy path is still OBO-only and whitelist-based. Broadening it changes the class tree and is deferred pending a decision plus downstream tree testing.metadata/obo/*relationship annotations requires a coordinated update to theontologies_linked_datatesttest_obo_part_of, which assertsobo/part_of(thetreeViewassertion is unchanged); no production code reads those predicates.