Source code for pronto.relationship

import datetime
import typing
from typing import Any, Dict, FrozenSet, Mapping, Optional, Set, Tuple

import frozendict

from .entity import Entity, EntityData
from .definition import Definition
from .synonym import Synonym, SynonymData
from .xref import Xref
from .pv import PropertyValue
from .utils.impl import set
from .utils.meta import typechecked

if typing.TYPE_CHECKING:
    from .ontology import Ontology
    from .term import Term


[docs]class RelationshipData(EntityData): id: str anonymous: bool name: Optional[str] namespace: Optional[str] alternate_ids: Set[str] definition: Optional[Definition] comment: Optional[str] subsets: Set[str] synonyms: Set[SynonymData] xrefs: Set[Xref] annotations: Set[PropertyValue] domain: Optional[str] range: Optional[str] builtin: bool holds_over_chain: Set[Tuple[str, str]] antisymmetric: bool cyclic: bool reflexive: bool asymmetric: bool symmetric: bool transitive: bool functional: bool inverse_functional: bool intersection_of: Set[str] union_of: Set[str] equivalent_to: Set[str] disjoint_from: Set[str] inverse_of: Optional[str] transitive_over: Set[str] equivalent_to_chain: Set[Tuple[str, str]] disjoint_over: Set[str] relationships: Dict[str, Set[str]] obsolete: bool created_by: Optional[str] creation_date: Optional[datetime.datetime] replaced_by: Set[str] consider: Set[str] expand_assertion_to: Set[Definition] expand_expression_to: Set[Definition] metadata_tag: bool class_level: bool __slots__ = tuple(__annotations__) # noqa: E0602 def __init__( self, id: str, anonymous: bool = False, name: Optional[str] = None, namespace: Optional[str] = None, alternate_ids: Optional[Set[str]] = None, definition: Optional[Definition] = None, comment: Optional[str] = None, subsets: Optional[Set[str]] = None, synonyms: Optional[Set[SynonymData]] = None, xrefs: Optional[Set[Xref]] = None, annotations: Optional[Set[PropertyValue]] = None, domain: Optional[str] = None, range: Optional[str] = None, builtin: bool = False, holds_over_chain: Optional[Set[Tuple[str, str]]] = None, antisymmetric: bool = False, cyclic: bool = False, reflexive: bool = False, asymmetric: bool = False, symmetric: bool = False, transitive: bool = False, functional: bool = False, inverse_functional: bool = False, intersection_of: Optional[Set[str]] = None, union_of: Optional[Set[str]] = None, equivalent_to: Optional[Set[str]] = None, disjoint_from: Optional[Set[str]] = None, inverse_of: Optional[str] = None, transitive_over: Optional[Set[str]] = None, equivalent_to_chain: Optional[Set[Tuple[str, str]]] = None, disjoint_over: Optional[Set[str]] = None, relationships: Optional[Dict[str, Set[str]]] = None, obsolete: bool = False, created_by: Optional[str] = None, creation_date: Optional[datetime.datetime] = None, replaced_by: Optional[Set[str]] = None, consider: Optional[Set[str]] = None, expand_assertion_to: Optional[Set[Definition]] = None, expand_expression_to: Optional[Set[Definition]] = None, metadata_tag: bool = False, class_level: bool = False, ): self.id = id self.anonymous = anonymous self.name = name self.namespace = namespace self.alternate_ids = alternate_ids or set() self.definition = definition self.comment = comment self.subsets = subsets or set() self.synonyms = synonyms or set() self.xrefs = xrefs or set() self.annotations = annotations or set() self.domain = domain self.range = range self.builtin = builtin self.holds_over_chain = holds_over_chain or set() self.antisymmetric = antisymmetric self.cyclic = cyclic self.reflexive = reflexive self.asymmetric = asymmetric self.symmetric = symmetric self.transitive = transitive self.functional = functional self.inverse_functional = inverse_functional self.intersection_of = intersection_of or set() self.union_of = union_of or set() self.equivalent_to = equivalent_to or set() self.disjoint_from = disjoint_from or set() self.inverse_of = inverse_of self.transitive_over = transitive_over or set() self.equivalent_to_chain = equivalent_to_chain or set() self.disjoint_over = disjoint_over or set() self.relationships = relationships or dict() self.obsolete = obsolete self.created_by = created_by self.creation_date = creation_date self.replaced_by = replaced_by or set() self.consider = consider or set() self.expand_assertion_to = expand_assertion_to or set() self.expand_expression_to = expand_expression_to or set() self.metadata_tag = metadata_tag self.class_level = class_level
[docs]class Relationship(Entity): """A relationship, constitute the edges of the ontology graph. Also sometimes referede as typedefs, relationship types, properties or predicates. Formally equivalent to a property (either ``ObjectProperty`` or ``AnnotationProperty``) in OWL2. """ if typing.TYPE_CHECKING: def __init__(self, ontology: "Ontology", reldata: "RelationshipData"): super().__init__(ontology, reldata) def _data(self) -> "RelationshipData": return typing.cast("RelationshipData", super()._data()) # --- Data descriptors --------------------------------------------------- @property def antisymmetric(self) -> bool: """`bool`: whether this relationship is anti-symmetric. """ return self._data().antisymmetric @antisymmetric.setter @typechecked(property=True) def antisymmetric(self, value: bool) -> None: self._data().antisymmetric = value @property def asymmetric(self) -> bool: """`bool`: whether this relationship is asymmetric. """ return self._data().asymmetric @asymmetric.setter @typechecked(property=True) def asymmetric(self, value: bool) -> None: self._data().asymmetric = value @property def class_level(self) -> bool: return self._data().class_level @class_level.setter @typechecked(property=True) def class_level(self, value: bool) -> None: self._data().class_level = value @property def consider(self) -> FrozenSet["Relationship"]: rdata, ont = self._data(), self._ontology() return frozenset(ont.get_relationship(r) for r in rdata.consider) @property def cyclic(self) -> bool: return self._data().cyclic @property def disjoint_from(self) -> FrozenSet["Relationship"]: rdata, ont = self._data(), self._ontology() return frozenset(ont.get_relationship(t) for t in rdata.disjoint_from) @property def disjoint_over(self) -> FrozenSet["Relationship"]: rdata, ont = self._data(), self._ontology() return frozenset(ont.get_relationship(t) for t in rdata.disjoint_over) @property def domain(self) -> Optional["Term"]: rshipdata, ontology = self._data(), self._ontology() if rshipdata.domain is not None: return ontology.get_term(rshipdata.domain) return None @domain.setter # @typechecked(property=True) def domain(self, value: Optional["Term"]) -> None: rshipdata, ontology = self._data(), self._ontology() if value is not None: try: ontology.get_term(value.id) except KeyError: raise ValueError(f"{value} is not a term in {ontology}") rshipdata.domain = value.id if value is not None else None @property def equivalent_to_chain(self) -> FrozenSet[Tuple["Relationship", "Relationship"]]: return frozenset( { tuple(map(self._ontology().get_relationship, chain)) for chain in self._data().equivalent_to_chain } ) @property def expand_assertion_to(self) -> FrozenSet[Definition]: return frozenset(self._data().expand_assertion_to) @property def expand_expression_to(self) -> FrozenSet[Definition]: return frozenset(self._data().expand_expression_to) @property def functional(self) -> bool: return self._data().functional @functional.setter @typechecked(property=True) def functional(self, value: bool) -> None: self._data().functional = value @property def inverse_functional(self) -> bool: return self._data().inverse_functional @inverse_functional.setter @typechecked(property=True) def inverse_functional(self, value: bool) -> None: self._data().inverse_functional = value @property def metadata_tag(self) -> bool: return self._data().metadata_tag @metadata_tag.setter @typechecked(property=True) def metadata_tag(self, value: bool): self._data().metadata_tag = value @property def relationships(self) -> Mapping["Relationship", FrozenSet["Relationship"]]: ont, reldata = self._ontology(), self._data() return frozendict.frozendict( { ont.get_relationship(rel): frozenset( ont.get_relationship(rel) for rel in rels ) for rel, rels in reldata.relationships.items() } ) @property def holds_over_chain(self) -> FrozenSet[Tuple["Relationship", "Relationship"]]: ont: "Ontology" = self._ontology() data: "RelationshipData" = self._data() return frozenset( {tuple(map(ont.get_term, chain)) for chain in data.holds_over_chain} ) @property def inverse_of(self) -> Optional["Relationship"]: ont, reldata = self._ontology(), self._data() if reldata.inverse_of is not None: return ont.get_relationship(reldata.inverse_of) return None @inverse_of.setter def inverse_of(self, value: Optional["Relationship"]): self._data().inverse_of = None if value is None else value.id @property def intersection_of(self) -> FrozenSet["Relationship"]: ont, reldata = self._ontology(), self._data() return frozenset({ont.get_relationship(r) for r in reldata.intersection_of}) @property def range(self) -> Optional["Term"]: range, ont = self._data().range, self._ontology() return ont.get_term(range) if range is not None else None @range.setter def range(self, value: Optional["Term"]): if value is not None: try: self._ontology().get_term(value.id) except KeyError: raise ValueError(f"{value} is not in {self._ontology()}") self._data().range = value.id if value is not None else None @property def reflexive(self) -> bool: return self._data().reflexive @reflexive.setter @typechecked(property=True) def reflexive(self, value: bool): self._data().reflexive = value @property def replaced_by(self) -> FrozenSet["Relationship"]: ont, data = self._ontology(), self._data() return frozenset({ont.get_relationship(r) for r in data.replaced_by}) @property def symmetric(self) -> bool: return self._data().symmetric @symmetric.setter @typechecked(property=True) def symmetric(self, value: bool): self._data().symmetric = value @property def transitive(self) -> bool: return self._data().transitive @transitive.setter @typechecked(property=True) def transitive(self, value: bool): self._data().transitive = value @property def transitive_over(self) -> FrozenSet["Relationship"]: ont, reldata = self._ontology(), self._data() return frozenset(ont.get_relationship(x) for x in reldata.transitive_over) @property def union_of(self) -> FrozenSet["Relationship"]: data, ont = self._data(), self._ontology() return frozenset(ont.get_relationship(r) for r in data.union_of)
_BUILTINS = { "is_a": RelationshipData( id="is_a", anonymous=False, name="is a", namespace=None, alternate_ids=None, definition=Definition( "A subclassing relationship between one term and another", xrefs=set( { Xref( "http://owlcollab.github.io/oboformat/doc/GO.format.obo-1_4.html" ) } ), ), comment=None, subsets=None, synonyms=None, xrefs=None, annotations=None, domain=None, range=None, builtin=True, holds_over_chain=None, antisymmetric=True, cyclic=True, reflexive=True, asymmetric=False, symmetric=False, transitive=True, functional=False, inverse_functional=False, intersection_of=None, union_of=None, equivalent_to=None, disjoint_from=None, inverse_of=None, transitive_over=None, equivalent_to_chain=None, disjoint_over=None, relationships=None, obsolete=False, created_by=None, creation_date=None, replaced_by=None, consider=None, expand_assertion_to=None, # TODO expand_expression_to=None, # TODO metadata_tag=False, class_level=True, ) }