Skip to content

Commit

Permalink
feat: query cross-ontology terms imported into a supported ontology (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
nayib-jose-gloria authored Oct 23, 2024
1 parent dbcdd29 commit 2e1a834
Show file tree
Hide file tree
Showing 7 changed files with 370 additions and 60 deletions.
38 changes: 29 additions & 9 deletions api/python/src/cellxgene_ontology_guide/ontology_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,17 @@ def get_term_label_to_id_map(self, ontology_name: str) -> Dict[str, str]:
:param ontology_name: str name of ontology to get map of term labels to term IDs
"""
if ontology_name not in self.cxg_schema.supported_ontologies:
raise ValueError(f"{ontology_name} is not a supported ontology, its metadata cannot be fetched.")
supported_ontology_name: Optional[str] = self._get_supported_ontology_name(ontology_name)
if not supported_ontology_name:
raise ValueError(f"{supported_ontology_name} is not a supported ontology, its metadata cannot be fetched.")

if self.term_label_to_id_map[ontology_name]:
return self.term_label_to_id_map[ontology_name]
if self.term_label_to_id_map[supported_ontology_name]:
return self.term_label_to_id_map[supported_ontology_name]

for term_id, term_metadata in self.cxg_schema.ontology(ontology_name).items():
self.term_label_to_id_map[ontology_name][term_metadata["label"]] = term_id
for term_id, term_metadata in self.cxg_schema.ontology(supported_ontology_name).items():
self.term_label_to_id_map[supported_ontology_name][term_metadata["label"]] = term_id

return self.term_label_to_id_map[ontology_name]
return self.term_label_to_id_map[supported_ontology_name]

def _parse_ontology_name(self, term_id: str) -> str:
"""
Expand All @@ -63,12 +64,31 @@ def _parse_ontology_name(self, term_id: str) -> str:
if not re.match(pattern, term_id):
raise ValueError(f"{term_id} does not conform to expected regex pattern {pattern} and cannot be queried.")

ontology_name = term_id.split(":")[0]
if ontology_name not in self.cxg_schema.supported_ontologies:
ontology_term_prefix = term_id.split(":")[0]
ontology_name: Optional[str] = self._get_supported_ontology_name(ontology_term_prefix)
if not ontology_name:
raise ValueError(f"{term_id} is not part of a supported ontology, its metadata cannot be fetched.")

return ontology_name

def _get_supported_ontology_name(self, ontology_term_prefix: str) -> Optional[str]:
"""
Get the source ontology name for a given ontology term prefix, if it is supported by the CxG schema.
If ontology_term_prefix is directly supported by the CxG schema, returns ontology_term_prefix.
If ontology_term_prefix is supported as an import from another ontology, returns the name of the source ontology
it is imported in.
Otherwise, returns None.
:param ontology_term_prefix: str ontology term prefix to check
:return: str name of ontology that term belongs to, or None if it is not directly supported nor imported in
a supported ontology in the CxG schema.
"""
if ontology_term_prefix in self.cxg_schema.supported_ontologies:
return ontology_term_prefix
supported_ontology_name: Optional[str] = self.cxg_schema.imported_ontologies.get(ontology_term_prefix)
return supported_ontology_name

def is_valid_term_id(self, term_id: str, ontology: Optional[str] = None) -> bool:
"""
Check if an ontology term ID is valid and defined in a supported ontology. If deprecated but defined
Expand Down
12 changes: 12 additions & 0 deletions api/python/src/cellxgene_ontology_guide/supported_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ class CXGSchema:
"""The schema version used by the class instance."""
supported_ontologies: Dict[str, Any]
"""A dictionary of supported ontologies for the schema version."""
imported_ontologies: Dict[str, str]
"""In our supported ontologies, the CxG schema can support terms imported from different ontologies.
This dictionary maps these 'additional ontologies' to their supported ontology name. For example,
for ZFS ontology terms imported into the ZFA ontology, imported_ontologies would be {"ZFS":"ZFA", ...}"""
ontology_file_names: Dict[str, str]
"""A dictionary of ontology names and their corresponding file names."""

Expand All @@ -75,6 +79,11 @@ def __init__(self, version: Optional[str] = None):

self.version = _version
self.supported_ontologies = ontology_info[_version]["ontologies"]
self.imported_ontologies = {
imported_ontology: ontology
for ontology, info in self.supported_ontologies.items()
for imported_ontology in info.get("additional_ontologies", [])
}
self.ontology_file_names: Dict[str, str] = {}
self.deprecated_on = ontology_info[_version].get("deprecated_on")
if self.deprecated_on:
Expand All @@ -87,6 +96,9 @@ def __init__(self, version: Optional[str] = None):

def ontology(self, name: str) -> Any:
"""Return the ontology terms for the given ontology name. Load from the file cache if available.
Does not support "additional ontologies" of another ontology.
:param name: str name of the ontology to get the terms for
:return: dict representation of the ontology terms
"""
Expand Down
Loading

0 comments on commit 2e1a834

Please sign in to comment.