Skip to content

Commit

Permalink
Adding option for non-redundant entialed relationships.
Browse files Browse the repository at this point in the history
Fixes #739
  • Loading branch information
cmungall committed Apr 19, 2024
1 parent a52eed5 commit 3c0d188
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/oaklib/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3409,6 +3409,12 @@ def definitions(
show_default=True,
help="Include entailed indirect relationships",
)
@click.option(
"--non-redundant-entailed/--no-non-redundant-entailed",
default=False,
show_default=True,
help="Include entailed but exclude entailed redundant relationships",
)
@click.option(
"--include-tbox/--no-include-tbox",
default=True,
Expand Down Expand Up @@ -3439,6 +3445,7 @@ def relationships(
include_entailed: bool,
include_tbox: bool,
include_abox: bool,
non_redundant_entailed: bool,
include_metadata: bool,
):
"""
Expand Down Expand Up @@ -3509,6 +3516,15 @@ def relationships(
include_tbox=include_tbox,
include_entailed=include_entailed,
)
if non_redundant_entailed:
if not isinstance(impl, OboGraphInterface):
raise NotImplementedError(f"Cannot execute this using {impl} of type {type(impl)}")
up_it = impl.non_redundant_entailed_relationships(
subjects=curies,
predicates=actual_predicates,
include_abox=include_abox,
include_tbox=include_tbox,
)
if direction is None or direction == Direction.up.value:
it = up_it
elif direction == Direction.down.value:
Expand Down
30 changes: 30 additions & 0 deletions src/oaklib/interfaces/obograph_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,36 @@ def descendant_graph(
self.transitive_query_cache[key] = g
return g

def non_redundant_entailed_relationships(
self,
predicates: List[PRED_CURIE] = None,
**kwargs,
) -> Iterator[RELATIONSHIP]:
"""
Yields all relationships that are directly entailed.
See https://github.com/INCATools/ontology-access-kit/issues/739
:param kwargs: same as relationships
:return:
"""
if "include_entailed" in kwargs:
kwargs.pop("include_entailed")
relationships = list(
self.relationships(predicates=predicates, include_entailed=True, **kwargs)
)
rel_by_sp = defaultdict(list)
for s, p, o in relationships:
rel_by_sp[(s, p)].append(o)
for (s, p), objs in rel_by_sp.items():
redundant_set = set()
for o in objs:
ancs = list(self.ancestors(o, predicates=predicates, reflexive=False))
redundant_set.update(ancs)
for o in objs:
if o not in redundant_set:
yield s, p, o

def ancestors(
self,
start_curies: Union[CURIE, List[CURIE]],
Expand Down

0 comments on commit 3c0d188

Please sign in to comment.