Skip to content

Commit

Permalink
Merge pull request #169 from biolink/add-utility-predicate-methods
Browse files Browse the repository at this point in the history
Added a couple of utility methods useful at my end but which seemed to belong in BMT
  • Loading branch information
sierra-moxon committed May 15, 2024
2 parents 6ac23d9 + ffaae99 commit e421af4
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 2 deletions.
55 changes: 55 additions & 0 deletions bmt/toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1590,10 +1590,65 @@ def is_mixin(self, name: str) -> bool:
is_mixin = element.mixin if isinstance(element, Definition) else False
return is_mixin

def is_symmetric(self, name: str) -> bool:
"""
Checks if a given element identified by name, is a symmetric (predicate) slot.
Parameters
----------
name: str
The name or alias of an element in the Biolink Model
Returns
-------
bool
That the named element is tagged as symmetric: true in Biolink Model
"""
if not name:
return False
element: Optional[Element] = self.get_element(name)
if element is not None and element['symmetric']:
return True
else:
return False

@lru_cache(CACHE_SIZE)
def get_inverse(self, slot_name: str):
return self.view.inverse(slot_name)

@lru_cache(CACHE_SIZE)
def get_inverse_predicate(
self, predicate: Optional[str],
formatted: bool = False
) -> Optional[str]:
"""
Utility wrapper of logic to robustly test if a predicate exists and has an inverse.
Parameters
----------
predicate: Optional[str]
CURIE or string name of predicate in the Biolink Model, for which the inverse is sought
formatted: bool
Whether to format element names as CURIEs
Returns
-------
Optional[str]
CURIE string of inverse predicate, if it exists; None otherwise
"""
if predicate and self.is_predicate(predicate):
predicate_name = parse_name(predicate)
inverse_predicate_name = self.get_inverse(predicate_name)
if not inverse_predicate_name:
if self.is_symmetric(predicate_name):
inverse_predicate_name = predicate_name
else:
inverse_predicate_name = None
if inverse_predicate_name:
ip = self.get_element(inverse_predicate_name)
return format_element(ip) if formatted else str(ip.name)
return None

@lru_cache(CACHE_SIZE)
def has_inverse(self, name: str) -> bool:
"""
Expand Down
24 changes: 22 additions & 2 deletions tests/unit/test_toolkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def test_sv(toolkit):
print(ancs)
assert 'related to' in ancs


def test_get_denormalized_association_slots(toolkit):
annotations = toolkit.get_denormalized_association_slots(formatted=True)
print(annotations)
Expand Down Expand Up @@ -667,9 +668,17 @@ def test_is_mixin(toolkit):
assert not toolkit.is_mixin("this_does_not_exist")


def test_is_symmetric(toolkit):
assert not toolkit.is_symmetric("")
assert not toolkit.is_symmetric("this_predicate_does_not_exist")
assert toolkit.is_symmetric(RELATED_TO)
assert toolkit.is_symmetric(INTERACTS_WITH)
assert not toolkit.is_symmetric(AFFECTS)


def test_is_translator_canonical_predicate(toolkit):
assert toolkit.is_translator_canonical_predicate("studied to treat")
assert not toolkit.is_translator_canonical_predicate("this_does_not_exist")
assert not toolkit.is_translator_canonical_predicate("this_predicate_does_not_exist")
assert not toolkit.is_translator_canonical_predicate("completed by")
assert toolkit.is_translator_canonical_predicate("regulates")

Expand All @@ -686,6 +695,13 @@ def test_get_inverse(toolkit):
assert toolkit.get_inverse(sd.name) == HAS_ACTIVE_COMPONENT


def test_get_get_inverse_predicate(toolkit):
assert toolkit.get_inverse_predicate(ACTIVE_IN) == HAS_ACTIVE_COMPONENT
assert toolkit.get_inverse_predicate(HAS_ACTIVE_COMPONENT) == ACTIVE_IN
assert toolkit.get_inverse_predicate(RELATED_TO) == RELATED_TO
assert toolkit.get_inverse_predicate(RELATED_TO, formatted=True) == BIOLINK_RELATED_TO


def test_category(toolkit):
assert toolkit.is_category(NAMED_THING)
assert toolkit.is_category(GENE)
Expand Down Expand Up @@ -868,7 +884,11 @@ def test_permissible_value_ancestors(toolkit):
)
assert "increased" in toolkit.get_permissible_value_parent("upregulated", "DirectionQualifierEnum")
assert "upregulated" in toolkit.get_permissible_value_children("increased", "DirectionQualifierEnum")
assert "synthesis" in toolkit.get_permissible_value_descendants("activity_or_abundance", "GeneOrGeneProductOrChemicalEntityAspectEnum")
assert "synthesis" in \
toolkit.get_permissible_value_descendants(
"activity_or_abundance",
"GeneOrGeneProductOrChemicalEntityAspectEnum"
)


def test_ancestors_for_kgx(toolkit):
Expand Down

0 comments on commit e421af4

Please sign in to comment.