From 515c72a9529ede73c46aecad4a152f6608deef8b Mon Sep 17 00:00:00 2001 From: Jesper Friis Date: Thu, 30 Dec 2021 20:15:35 +0100 Subject: [PATCH] When visualising restrictions, annotate the edges with the restriction type by default. Used to produce the graphs for the updated README for EMMO 1.0.0-beta3: https://github.com/emmo-repo/EMMO/tree/updated-readme-and-figures --- ontopy/graph.py | 27 +++++++++++++++++++-------- ontopy/ontology.py | 13 ++++++++----- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/ontopy/graph.py b/ontopy/graph.py index d5f4193fc..a9135fc98 100644 --- a/ontopy/graph.py +++ b/ontopy/graph.py @@ -87,6 +87,7 @@ }, "hasPart": {"color": "blue"}, "hasProperPart": {"color": "blue", "style": "dashed"}, + "hasMember": {"color": "blue", "style": "dotted"}, "hasParticipant": {"color": "red"}, "hasProperParticipant": {"color": "red", "style": "dashed"}, "hasSpatialPart": {"color": "darkgreen"}, @@ -193,7 +194,7 @@ class OntoGraph: # pylint: disable=too-many-instance-attributes - edges : attribute for individual edges (E) If style is None or "default", the default style is used. See https://www.graphviz.org/doc/info/attrs.html - edgelabels : bool | dict + edgelabels : None | bool | dict Whether to add labels to the edges of the generated graph. It is also possible to provide a dict mapping the full labels (with cardinality stripped off for restrictions) @@ -231,7 +232,7 @@ def __init__( # pylint: disable=too-many-arguments,too-many-locals entities=None, relations="isA", style=None, - edgelabels=True, + edgelabels=None, addnodes=False, addconstructs=False, included_namespaces=(), @@ -315,7 +316,7 @@ def add_entities( # pylint: disable=too-many-arguments self, entities=None, relations="isA", - edgelabels=True, + edgelabels=None, addnodes=False, addconstructs=False, nodeattrs=None, @@ -346,7 +347,7 @@ def add_branch( # pylint: disable=too-many-arguments,too-many-locals strict_leafs=False, exclude=None, relations="isA", - edgelabels=True, + edgelabels=None, addnodes=False, addconstructs=False, included_namespaces=(), @@ -471,17 +472,27 @@ def add_edge(self, subject, predicate, obj, edgelabel=None, **attrs): raise RuntimeError(f'`object` "{obj}" must have been added') key = (subject, predicate, obj) if key not in self.edges: + if edgelabel is None: edgelabel = self.edgelabels - if isinstance(edgelabel, str): + label = None + if edgelabel is None: + tokens = predicate.split() + if len(tokens) == 2 and tokens[1] in ("some", "only"): + label = tokens[1] + elif len(tokens) == 3 and tokens[1] in ( + "exactly", + "min", + "max", + ): + label = f"{tokens[1]} {tokens[2]}" + elif isinstance(edgelabel, str): label = edgelabel - if isinstance(edgelabel, dict): + elif isinstance(edgelabel, dict): label = edgelabel.get(predicate, predicate) elif edgelabel: label = predicate - else: - label = None kwargs = self.get_edge_attrs(predicate, attrs=attrs) self.dot.edge(subject, obj, label=label, **kwargs) diff --git a/ontopy/ontology.py b/ontopy/ontology.py index 6c55f7482..bf1077c87 100644 --- a/ontopy/ontology.py +++ b/ontopy/ontology.py @@ -1180,11 +1180,14 @@ def _number_of_generations(self, descendant, ancestor, counter): distance between a ancestor-descendant pair (counter+1).""" if descendant.name == ancestor.name: return counter - return min( - self._number_of_generations(parent, ancestor, counter + 1) - for parent in descendant.get_parents() - if ancestor in parent.ancestors() - ) + try: + return min( + self._number_of_generations(parent, ancestor, counter + 1) + for parent in descendant.get_parents() + if ancestor in parent.ancestors() + ) + except ValueError: + return counter def closest_common_ancestors(self, cls1, cls2): """Returns a list with closest_common_ancestor for cls1 and cls2"""