"""Convert PyOBO into OBO Graph."""
from typing import Iterable, List
import bioregistry
import curies
from bioontologies.obograph import (
OBO_SYNONYM_TO_OIO,
OIO_TO_REFERENCE,
Definition,
Edge,
Graph,
GraphDocument,
Meta,
Node,
Synonym,
Xref,
)
from bioontologies.robot import ParseResults
from pyobo.struct import Obo, Reference, Term
from pyobo.struct.typedef import is_a
__all__ = [
"graph_from_obo",
"parse_results_from_obo",
]
[docs]def parse_results_from_obo(obo: Obo) -> ParseResults:
"""Get parse results from an OBO graph."""
graph = graph_from_obo(obo)
return ParseResults(graph_document=GraphDocument(graphs=[graph]))
def graph_from_obo(obo: Obo) -> Graph:
"""Get an OBO Graph object from a PyOBO object."""
nodes: List[Node] = []
edges: List[Edge] = []
for term in obo:
nodes.append(_get_class_node(term))
edges.extend(_iter_edges(term))
return Graph(
id=bioregistry.get_bioregistry_iri("bioregistry", obo.ontology),
prefix=obo.ontology,
meta=_get_meta(obo),
nodes=nodes,
edges=edges,
standardized=True, # from construction :)
)
def _get_meta(obo: Obo) -> Meta:
return Meta(
version=obo.data_version,
)
def _rewire(r: Reference) -> curies.Reference:
return curies.Reference(prefix=r.prefix, identifier=r.identifier)
def _get_class_node(term: Term) -> Node:
if not term.definition:
definition = None
else:
definition = Definition.from_parsed(
value=term.definition, references=[_rewire(p) for p in term.provenance]
)
if term.xrefs:
if not term.xref_types:
term.xref_types = [
Reference(prefix="oboInOwl", identifier="hasDbXref") for _ in term.xrefs
]
elif len(term.xrefs) != len(term.xref_types):
raise ValueError
xrefs = [
Xref.from_parsed(
predicate=_rewire(xref_type),
value=_rewire(xref),
)
for xref, xref_type in zip(term.xrefs, term.xref_types)
]
default_st = Reference(prefix="oboInOwl", identifier="SynonymType")
synonyms = [
Synonym.from_parsed(
name=synonym.name,
predicate=OIO_TO_REFERENCE[OBO_SYNONYM_TO_OIO[synonym.specificity]],
synonym_type=_rewire(synonym.type.reference) if synonym.type else default_st,
references=[_rewire(x) for x in synonym.provenance],
)
for synonym in term.synonyms
]
meta = Meta(
definition=definition,
xrefs=xrefs,
synonyms=synonyms,
basicPropertyValues=None, # TODO properties
deprecated=term.is_obsolete or False,
)
return Node(
id=term.bioregistry_link,
lbl=term.name,
meta=meta,
type="CLASS",
reference=_rewire(term.reference),
standardized=True,
)
def _iter_edges(term: Term) -> Iterable[Edge]:
for parent in term.parents:
yield Edge.from_parsed(
_rewire(term.reference),
_rewire(is_a.reference),
_rewire(parent),
)
for typedef, targets in term.relationships.items():
for target in targets:
yield Edge.from_parsed(
_rewire(term.reference),
_rewire(typedef.reference),
_rewire(target),
)