Skip to content

Commit 2e1a834

Browse files
feat: query cross-ontology terms imported into a supported ontology (#232)
1 parent dbcdd29 commit 2e1a834

File tree

7 files changed

+370
-60
lines changed

7 files changed

+370
-60
lines changed

api/python/src/cellxgene_ontology_guide/ontology_parser.py

+29-9
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,17 @@ def get_term_label_to_id_map(self, ontology_name: str) -> Dict[str, str]:
4040
4141
:param ontology_name: str name of ontology to get map of term labels to term IDs
4242
"""
43-
if ontology_name not in self.cxg_schema.supported_ontologies:
44-
raise ValueError(f"{ontology_name} is not a supported ontology, its metadata cannot be fetched.")
43+
supported_ontology_name: Optional[str] = self._get_supported_ontology_name(ontology_name)
44+
if not supported_ontology_name:
45+
raise ValueError(f"{supported_ontology_name} is not a supported ontology, its metadata cannot be fetched.")
4546

46-
if self.term_label_to_id_map[ontology_name]:
47-
return self.term_label_to_id_map[ontology_name]
47+
if self.term_label_to_id_map[supported_ontology_name]:
48+
return self.term_label_to_id_map[supported_ontology_name]
4849

49-
for term_id, term_metadata in self.cxg_schema.ontology(ontology_name).items():
50-
self.term_label_to_id_map[ontology_name][term_metadata["label"]] = term_id
50+
for term_id, term_metadata in self.cxg_schema.ontology(supported_ontology_name).items():
51+
self.term_label_to_id_map[supported_ontology_name][term_metadata["label"]] = term_id
5152

52-
return self.term_label_to_id_map[ontology_name]
53+
return self.term_label_to_id_map[supported_ontology_name]
5354

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

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

7072
return ontology_name
7173

74+
def _get_supported_ontology_name(self, ontology_term_prefix: str) -> Optional[str]:
75+
"""
76+
Get the source ontology name for a given ontology term prefix, if it is supported by the CxG schema.
77+
78+
If ontology_term_prefix is directly supported by the CxG schema, returns ontology_term_prefix.
79+
If ontology_term_prefix is supported as an import from another ontology, returns the name of the source ontology
80+
it is imported in.
81+
Otherwise, returns None.
82+
83+
:param ontology_term_prefix: str ontology term prefix to check
84+
:return: str name of ontology that term belongs to, or None if it is not directly supported nor imported in
85+
a supported ontology in the CxG schema.
86+
"""
87+
if ontology_term_prefix in self.cxg_schema.supported_ontologies:
88+
return ontology_term_prefix
89+
supported_ontology_name: Optional[str] = self.cxg_schema.imported_ontologies.get(ontology_term_prefix)
90+
return supported_ontology_name
91+
7292
def is_valid_term_id(self, term_id: str, ontology: Optional[str] = None) -> bool:
7393
"""
7494
Check if an ontology term ID is valid and defined in a supported ontology. If deprecated but defined

api/python/src/cellxgene_ontology_guide/supported_versions.py

+12
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ class CXGSchema:
5757
"""The schema version used by the class instance."""
5858
supported_ontologies: Dict[str, Any]
5959
"""A dictionary of supported ontologies for the schema version."""
60+
imported_ontologies: Dict[str, str]
61+
"""In our supported ontologies, the CxG schema can support terms imported from different ontologies.
62+
This dictionary maps these 'additional ontologies' to their supported ontology name. For example,
63+
for ZFS ontology terms imported into the ZFA ontology, imported_ontologies would be {"ZFS":"ZFA", ...}"""
6064
ontology_file_names: Dict[str, str]
6165
"""A dictionary of ontology names and their corresponding file names."""
6266

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

7680
self.version = _version
7781
self.supported_ontologies = ontology_info[_version]["ontologies"]
82+
self.imported_ontologies = {
83+
imported_ontology: ontology
84+
for ontology, info in self.supported_ontologies.items()
85+
for imported_ontology in info.get("additional_ontologies", [])
86+
}
7887
self.ontology_file_names: Dict[str, str] = {}
7988
self.deprecated_on = ontology_info[_version].get("deprecated_on")
8089
if self.deprecated_on:
@@ -87,6 +96,9 @@ def __init__(self, version: Optional[str] = None):
8796

8897
def ontology(self, name: str) -> Any:
8998
"""Return the ontology terms for the given ontology name. Load from the file cache if available.
99+
100+
Does not support "additional ontologies" of another ontology.
101+
90102
:param name: str name of the ontology to get the terms for
91103
:return: dict representation of the ontology terms
92104
"""

0 commit comments

Comments
 (0)