pyobo 0.11.2__py3-none-any.whl → 0.12.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyobo/.DS_Store +0 -0
- pyobo/__init__.py +95 -20
- pyobo/__main__.py +0 -0
- pyobo/api/__init__.py +81 -10
- pyobo/api/alts.py +52 -42
- pyobo/api/combine.py +39 -0
- pyobo/api/edges.py +68 -0
- pyobo/api/hierarchy.py +231 -203
- pyobo/api/metadata.py +14 -19
- pyobo/api/names.py +207 -127
- pyobo/api/properties.py +117 -117
- pyobo/api/relations.py +68 -94
- pyobo/api/species.py +24 -21
- pyobo/api/typedefs.py +11 -11
- pyobo/api/utils.py +66 -13
- pyobo/api/xrefs.py +107 -114
- pyobo/cli/__init__.py +0 -0
- pyobo/cli/cli.py +35 -50
- pyobo/cli/database.py +210 -160
- pyobo/cli/database_utils.py +155 -0
- pyobo/cli/lookup.py +163 -195
- pyobo/cli/utils.py +19 -6
- pyobo/constants.py +102 -3
- pyobo/getters.py +209 -191
- pyobo/gilda_utils.py +52 -250
- pyobo/identifier_utils/__init__.py +33 -0
- pyobo/identifier_utils/api.py +305 -0
- pyobo/identifier_utils/preprocessing.json +873 -0
- pyobo/identifier_utils/preprocessing.py +27 -0
- pyobo/identifier_utils/relations/__init__.py +8 -0
- pyobo/identifier_utils/relations/api.py +162 -0
- pyobo/identifier_utils/relations/data.json +5824 -0
- pyobo/identifier_utils/relations/data_owl.json +57 -0
- pyobo/identifier_utils/relations/data_rdf.json +1 -0
- pyobo/identifier_utils/relations/data_rdfs.json +7 -0
- pyobo/mocks.py +9 -6
- pyobo/ner/__init__.py +9 -0
- pyobo/ner/api.py +72 -0
- pyobo/ner/normalizer.py +33 -0
- pyobo/obographs.py +48 -40
- pyobo/plugins.py +5 -4
- pyobo/py.typed +0 -0
- pyobo/reader.py +1354 -395
- pyobo/reader_utils.py +155 -0
- pyobo/resource_utils.py +42 -22
- pyobo/resources/__init__.py +0 -0
- pyobo/resources/goc.py +75 -0
- pyobo/resources/goc.tsv +188 -0
- pyobo/resources/ncbitaxon.py +4 -5
- pyobo/resources/ncbitaxon.tsv.gz +0 -0
- pyobo/resources/ro.py +3 -2
- pyobo/resources/ro.tsv +0 -0
- pyobo/resources/so.py +0 -0
- pyobo/resources/so.tsv +0 -0
- pyobo/sources/README.md +12 -8
- pyobo/sources/__init__.py +52 -29
- pyobo/sources/agrovoc.py +0 -0
- pyobo/sources/antibodyregistry.py +11 -12
- pyobo/sources/bigg/__init__.py +13 -0
- pyobo/sources/bigg/bigg_compartment.py +81 -0
- pyobo/sources/bigg/bigg_metabolite.py +229 -0
- pyobo/sources/bigg/bigg_model.py +46 -0
- pyobo/sources/bigg/bigg_reaction.py +77 -0
- pyobo/sources/biogrid.py +1 -2
- pyobo/sources/ccle.py +7 -12
- pyobo/sources/cgnc.py +9 -6
- pyobo/sources/chebi.py +1 -1
- pyobo/sources/chembl/__init__.py +9 -0
- pyobo/sources/{chembl.py → chembl/chembl_compound.py} +13 -25
- pyobo/sources/chembl/chembl_target.py +160 -0
- pyobo/sources/civic_gene.py +55 -15
- pyobo/sources/clinicaltrials.py +160 -0
- pyobo/sources/complexportal.py +24 -24
- pyobo/sources/conso.py +14 -22
- pyobo/sources/cpt.py +0 -0
- pyobo/sources/credit.py +1 -9
- pyobo/sources/cvx.py +27 -5
- pyobo/sources/depmap.py +9 -12
- pyobo/sources/dictybase_gene.py +2 -7
- pyobo/sources/drugbank/__init__.py +9 -0
- pyobo/sources/{drugbank.py → drugbank/drugbank.py} +11 -16
- pyobo/sources/{drugbank_salt.py → drugbank/drugbank_salt.py} +3 -8
- pyobo/sources/drugcentral.py +17 -13
- pyobo/sources/expasy.py +31 -34
- pyobo/sources/famplex.py +13 -18
- pyobo/sources/flybase.py +8 -13
- pyobo/sources/gard.py +62 -0
- pyobo/sources/geonames/__init__.py +9 -0
- pyobo/sources/geonames/features.py +28 -0
- pyobo/sources/{geonames.py → geonames/geonames.py} +87 -26
- pyobo/sources/geonames/utils.py +115 -0
- pyobo/sources/gmt_utils.py +6 -7
- pyobo/sources/go.py +20 -13
- pyobo/sources/gtdb.py +154 -0
- pyobo/sources/gwascentral/__init__.py +9 -0
- pyobo/sources/{gwascentral_phenotype.py → gwascentral/gwascentral_phenotype.py} +5 -7
- pyobo/sources/{gwascentral_study.py → gwascentral/gwascentral_study.py} +1 -7
- pyobo/sources/hgnc/__init__.py +9 -0
- pyobo/sources/{hgnc.py → hgnc/hgnc.py} +56 -70
- pyobo/sources/{hgncgenefamily.py → hgnc/hgncgenefamily.py} +8 -18
- pyobo/sources/icd/__init__.py +9 -0
- pyobo/sources/{icd10.py → icd/icd10.py} +35 -37
- pyobo/sources/icd/icd11.py +148 -0
- pyobo/sources/{icd_utils.py → icd/icd_utils.py} +66 -20
- pyobo/sources/interpro.py +4 -9
- pyobo/sources/itis.py +0 -5
- pyobo/sources/kegg/__init__.py +0 -0
- pyobo/sources/kegg/api.py +16 -38
- pyobo/sources/kegg/genes.py +9 -20
- pyobo/sources/kegg/genome.py +1 -7
- pyobo/sources/kegg/pathway.py +9 -21
- pyobo/sources/mesh.py +58 -24
- pyobo/sources/mgi.py +3 -10
- pyobo/sources/mirbase/__init__.py +11 -0
- pyobo/sources/{mirbase.py → mirbase/mirbase.py} +8 -11
- pyobo/sources/{mirbase_constants.py → mirbase/mirbase_constants.py} +0 -0
- pyobo/sources/{mirbase_family.py → mirbase/mirbase_family.py} +4 -8
- pyobo/sources/{mirbase_mature.py → mirbase/mirbase_mature.py} +3 -7
- pyobo/sources/msigdb.py +74 -39
- pyobo/sources/ncbi/__init__.py +9 -0
- pyobo/sources/ncbi/ncbi_gc.py +162 -0
- pyobo/sources/{ncbigene.py → ncbi/ncbigene.py} +18 -19
- pyobo/sources/nih_reporter.py +60 -0
- pyobo/sources/nlm/__init__.py +9 -0
- pyobo/sources/nlm/nlm_catalog.py +48 -0
- pyobo/sources/nlm/nlm_publisher.py +36 -0
- pyobo/sources/nlm/utils.py +116 -0
- pyobo/sources/npass.py +6 -8
- pyobo/sources/omim_ps.py +11 -4
- pyobo/sources/pathbank.py +4 -8
- pyobo/sources/pfam/__init__.py +9 -0
- pyobo/sources/{pfam.py → pfam/pfam.py} +3 -8
- pyobo/sources/{pfam_clan.py → pfam/pfam_clan.py} +2 -7
- pyobo/sources/pharmgkb/__init__.py +15 -0
- pyobo/sources/pharmgkb/pharmgkb_chemical.py +89 -0
- pyobo/sources/pharmgkb/pharmgkb_disease.py +77 -0
- pyobo/sources/pharmgkb/pharmgkb_gene.py +108 -0
- pyobo/sources/pharmgkb/pharmgkb_pathway.py +63 -0
- pyobo/sources/pharmgkb/pharmgkb_variant.py +84 -0
- pyobo/sources/pharmgkb/utils.py +86 -0
- pyobo/sources/pid.py +1 -6
- pyobo/sources/pombase.py +6 -10
- pyobo/sources/pubchem.py +4 -9
- pyobo/sources/reactome.py +5 -11
- pyobo/sources/rgd.py +11 -16
- pyobo/sources/rhea.py +37 -36
- pyobo/sources/ror.py +69 -42
- pyobo/sources/selventa/__init__.py +0 -0
- pyobo/sources/selventa/schem.py +4 -7
- pyobo/sources/selventa/scomp.py +1 -6
- pyobo/sources/selventa/sdis.py +4 -7
- pyobo/sources/selventa/sfam.py +1 -6
- pyobo/sources/sgd.py +6 -11
- pyobo/sources/signor/__init__.py +7 -0
- pyobo/sources/signor/download.py +41 -0
- pyobo/sources/signor/signor_complexes.py +105 -0
- pyobo/sources/slm.py +12 -15
- pyobo/sources/umls/__init__.py +7 -1
- pyobo/sources/umls/__main__.py +0 -0
- pyobo/sources/umls/get_synonym_types.py +20 -4
- pyobo/sources/umls/sty.py +57 -0
- pyobo/sources/umls/synonym_types.tsv +1 -1
- pyobo/sources/umls/umls.py +18 -22
- pyobo/sources/unimod.py +46 -0
- pyobo/sources/uniprot/__init__.py +1 -1
- pyobo/sources/uniprot/uniprot.py +40 -32
- pyobo/sources/uniprot/uniprot_ptm.py +4 -34
- pyobo/sources/utils.py +3 -2
- pyobo/sources/wikipathways.py +7 -10
- pyobo/sources/zfin.py +5 -10
- pyobo/ssg/__init__.py +12 -16
- pyobo/ssg/base.html +0 -0
- pyobo/ssg/index.html +26 -13
- pyobo/ssg/term.html +12 -2
- pyobo/ssg/typedef.html +0 -0
- pyobo/struct/__init__.py +54 -8
- pyobo/struct/functional/__init__.py +1 -0
- pyobo/struct/functional/dsl.py +2572 -0
- pyobo/struct/functional/macros.py +423 -0
- pyobo/struct/functional/obo_to_functional.py +385 -0
- pyobo/struct/functional/ontology.py +272 -0
- pyobo/struct/functional/utils.py +112 -0
- pyobo/struct/reference.py +331 -136
- pyobo/struct/struct.py +1484 -657
- pyobo/struct/struct_utils.py +1078 -0
- pyobo/struct/typedef.py +162 -210
- pyobo/struct/utils.py +12 -5
- pyobo/struct/vocabulary.py +138 -0
- pyobo/utils/__init__.py +0 -0
- pyobo/utils/cache.py +16 -15
- pyobo/utils/io.py +51 -41
- pyobo/utils/iter.py +5 -5
- pyobo/utils/misc.py +41 -53
- pyobo/utils/ndex_utils.py +0 -0
- pyobo/utils/path.py +73 -70
- pyobo/version.py +3 -3
- pyobo-0.12.1.dist-info/METADATA +671 -0
- pyobo-0.12.1.dist-info/RECORD +201 -0
- pyobo-0.12.1.dist-info/WHEEL +4 -0
- {pyobo-0.11.2.dist-info → pyobo-0.12.1.dist-info}/entry_points.txt +1 -0
- pyobo-0.12.1.dist-info/licenses/LICENSE +21 -0
- pyobo/aws.py +0 -162
- pyobo/cli/aws.py +0 -47
- pyobo/identifier_utils.py +0 -142
- pyobo/normalizer.py +0 -232
- pyobo/registries/__init__.py +0 -16
- pyobo/registries/metaregistry.json +0 -507
- pyobo/registries/metaregistry.py +0 -135
- pyobo/sources/icd11.py +0 -105
- pyobo/xrefdb/__init__.py +0 -1
- pyobo/xrefdb/canonicalizer.py +0 -214
- pyobo/xrefdb/priority.py +0 -59
- pyobo/xrefdb/sources/__init__.py +0 -60
- pyobo/xrefdb/sources/biomappings.py +0 -36
- pyobo/xrefdb/sources/cbms2019.py +0 -91
- pyobo/xrefdb/sources/chembl.py +0 -83
- pyobo/xrefdb/sources/compath.py +0 -82
- pyobo/xrefdb/sources/famplex.py +0 -64
- pyobo/xrefdb/sources/gilda.py +0 -50
- pyobo/xrefdb/sources/intact.py +0 -113
- pyobo/xrefdb/sources/ncit.py +0 -133
- pyobo/xrefdb/sources/pubchem.py +0 -27
- pyobo/xrefdb/sources/wikidata.py +0 -116
- pyobo/xrefdb/xrefs_pipeline.py +0 -180
- pyobo-0.11.2.dist-info/METADATA +0 -711
- pyobo-0.11.2.dist-info/RECORD +0 -157
- pyobo-0.11.2.dist-info/WHEEL +0 -5
- pyobo-0.11.2.dist-info/top_level.txt +0 -1
pyobo/api/hierarchy.py
CHANGED
|
@@ -1,291 +1,319 @@
|
|
|
1
1
|
"""High-level API for hierarchies."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import warnings
|
|
4
5
|
from collections.abc import Iterable
|
|
5
6
|
from functools import lru_cache
|
|
6
|
-
from typing import
|
|
7
|
+
from typing import overload
|
|
7
8
|
|
|
8
9
|
import networkx as nx
|
|
9
|
-
|
|
10
|
-
from
|
|
11
|
-
|
|
12
|
-
from .
|
|
13
|
-
from
|
|
14
|
-
from
|
|
10
|
+
from curies import ReferenceTuple
|
|
11
|
+
from typing_extensions import NotRequired, Unpack
|
|
12
|
+
|
|
13
|
+
from .edges import get_edges
|
|
14
|
+
from .names import get_name, get_references
|
|
15
|
+
from .properties import get_literal_properties
|
|
16
|
+
from .utils import _get_pi
|
|
17
|
+
from ..constants import GetOntologyKwargs
|
|
18
|
+
from ..struct import has_member, has_part, is_a, member_of, part_of
|
|
15
19
|
from ..struct.reference import Reference
|
|
20
|
+
from ..struct.struct_utils import ReferenceHint, _ensure_ref
|
|
16
21
|
|
|
17
22
|
__all__ = [
|
|
23
|
+
"get_ancestors",
|
|
24
|
+
"get_children",
|
|
25
|
+
"get_descendants",
|
|
18
26
|
"get_hierarchy",
|
|
19
27
|
"get_subhierarchy",
|
|
20
|
-
"get_descendants",
|
|
21
|
-
"get_ancestors",
|
|
22
28
|
"has_ancestor",
|
|
23
29
|
"is_descendent",
|
|
24
|
-
"get_children",
|
|
25
30
|
]
|
|
26
31
|
|
|
27
|
-
|
|
28
32
|
logger = logging.getLogger(__name__)
|
|
29
33
|
|
|
30
34
|
|
|
35
|
+
class HierarchyKwargs(GetOntologyKwargs):
|
|
36
|
+
"""Keyword argument hints for hierarchy getter functions."""
|
|
37
|
+
|
|
38
|
+
include_part_of: NotRequired[bool]
|
|
39
|
+
include_has_member: NotRequired[bool]
|
|
40
|
+
|
|
41
|
+
|
|
31
42
|
def get_hierarchy(
|
|
32
43
|
prefix: str,
|
|
33
44
|
*,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
properties: Optional[Iterable[str]] = None,
|
|
38
|
-
use_tqdm: bool = False,
|
|
39
|
-
force: bool = False,
|
|
40
|
-
version: Optional[str] = None,
|
|
45
|
+
extra_relations: Iterable[ReferenceHint] | None = None,
|
|
46
|
+
properties: Iterable[ReferenceHint] | None = None,
|
|
47
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
41
48
|
) -> nx.DiGraph:
|
|
42
49
|
"""Get hierarchy of parents as a directed graph.
|
|
43
50
|
|
|
44
51
|
:param prefix: The name of the namespace.
|
|
45
|
-
:param include_part_of: Add "part of" relations. Only works if the relations are
|
|
46
|
-
defined using bfo:0000050 ! part of or bfo:0000051 ! has part
|
|
47
|
-
:param include_has_member: Add "has member" relations. These aren't part of the BFO,
|
|
48
|
-
are hacked into PyOBO using :data:`pyobo.struct.typedef.has_member` for
|
|
49
|
-
from protein families to their actual proteins.
|
|
50
|
-
:param extra_relations: Other relations that you want to include in the hierarchy.
|
|
51
|
-
example, it might be useful to include the positively_regulates
|
|
52
|
-
:param properties: Properties to include in the data part of each node. For example,
|
|
53
|
-
to include SMILES strings with the ChEBI tree.
|
|
54
|
-
:param use_tqdm: Show a progress bar
|
|
52
|
+
:param include_part_of: Add "part of" relations. Only works if the relations are
|
|
53
|
+
properly defined using bfo:0000050 ! part of or bfo:0000051 ! has part
|
|
54
|
+
:param include_has_member: Add "has member" relations. These aren't part of the BFO,
|
|
55
|
+
but are hacked into PyOBO using :data:`pyobo.struct.typedef.has_member` for
|
|
56
|
+
relationships like from protein families to their actual proteins.
|
|
57
|
+
:param extra_relations: Other relations that you want to include in the hierarchy.
|
|
58
|
+
For example, it might be useful to include the positively_regulates
|
|
59
|
+
:param properties: Properties to include in the data part of each node. For example,
|
|
60
|
+
might want to include SMILES strings with the ChEBI tree.
|
|
55
61
|
:param force: should the resources be reloaded when extracting relations?
|
|
62
|
+
|
|
56
63
|
:returns: A directional graph representing the hierarchy
|
|
57
64
|
|
|
58
|
-
This function thinly wraps :func:`_get_hierarchy_helper` to make it easier to work
|
|
65
|
+
This function thinly wraps :func:`_get_hierarchy_helper` to make it easier to work
|
|
66
|
+
with the lru_cache mechanism.
|
|
59
67
|
"""
|
|
60
68
|
return _get_hierarchy_helper(
|
|
61
69
|
prefix=prefix,
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
extra_relations=_tp(prefix, extra_relations),
|
|
71
|
+
properties=_tp(prefix, properties),
|
|
72
|
+
**kwargs,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _tp(prefix: str, references: Iterable[ReferenceHint] | None) -> tuple[Reference, ...]:
|
|
77
|
+
return tuple(
|
|
78
|
+
sorted(_ensure_ref(reference, ontology_prefix=prefix) for reference in references or [])
|
|
69
79
|
)
|
|
70
80
|
|
|
71
81
|
|
|
72
82
|
@lru_cache
|
|
73
|
-
@wrap_norm_prefix
|
|
74
83
|
def _get_hierarchy_helper(
|
|
75
84
|
prefix: str,
|
|
76
85
|
*,
|
|
77
|
-
extra_relations: tuple[
|
|
78
|
-
properties: tuple[
|
|
79
|
-
include_part_of: bool,
|
|
80
|
-
include_has_member: bool,
|
|
81
|
-
|
|
82
|
-
force: bool = False,
|
|
83
|
-
version: Optional[str] = None,
|
|
86
|
+
extra_relations: tuple[Reference, ...],
|
|
87
|
+
properties: tuple[Reference, ...],
|
|
88
|
+
include_part_of: bool = False,
|
|
89
|
+
include_has_member: bool = False,
|
|
90
|
+
**kwargs: Unpack[GetOntologyKwargs],
|
|
84
91
|
) -> nx.DiGraph:
|
|
92
|
+
predicates, reverse_predicates = _get_predicate_sets(
|
|
93
|
+
extra_relations, include_part_of, include_has_member
|
|
94
|
+
)
|
|
95
|
+
|
|
85
96
|
rv = nx.DiGraph()
|
|
97
|
+
rv.add_nodes_from(get_references(prefix, **kwargs))
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
version=version,
|
|
93
|
-
)
|
|
94
|
-
for source_id, target_ns, target_id in is_a_df.values:
|
|
95
|
-
rv.add_edge(f"{prefix}:{source_id}", f"{target_ns}:{target_id}", relation="is_a")
|
|
99
|
+
for s, p, o in get_edges(prefix, **kwargs):
|
|
100
|
+
if p in predicates:
|
|
101
|
+
rv.add_edge(s, o, relation=p)
|
|
102
|
+
elif p in reverse_predicates:
|
|
103
|
+
rv.add_edge(o, s, relation=p)
|
|
96
104
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
version=version,
|
|
104
|
-
)
|
|
105
|
-
for target_id, source_ns, source_id in has_member_df.values:
|
|
106
|
-
rv.add_edge(f"{source_ns}:{source_id}", f"{prefix}:{target_id}", relation="is_a")
|
|
105
|
+
properties_ = set(properties)
|
|
106
|
+
for s, p, op in get_literal_properties(prefix, **kwargs):
|
|
107
|
+
if s in rv and p in properties_:
|
|
108
|
+
rv.nodes[s][p] = op.value
|
|
109
|
+
|
|
110
|
+
return rv
|
|
107
111
|
|
|
112
|
+
|
|
113
|
+
def _get_predicate_sets(
|
|
114
|
+
extra_relations: Iterable[Reference], include_part_of: bool, include_has_member: bool
|
|
115
|
+
) -> tuple[set[Reference], set[Reference]]:
|
|
116
|
+
predicates: set[Reference] = {is_a.reference, *extra_relations}
|
|
117
|
+
reverse_predicates: set[Reference] = set()
|
|
108
118
|
if include_part_of:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
)
|
|
116
|
-
for source_id, target_ns, target_id in part_of_df.values:
|
|
117
|
-
rv.add_edge(f"{prefix}:{source_id}", f"{target_ns}:{target_id}", relation="part_of")
|
|
118
|
-
|
|
119
|
-
has_part_df = get_filtered_relations_df(
|
|
120
|
-
prefix=prefix,
|
|
121
|
-
relation=part_of,
|
|
122
|
-
use_tqdm=use_tqdm,
|
|
123
|
-
force=force,
|
|
124
|
-
version=version,
|
|
125
|
-
)
|
|
126
|
-
for target_id, source_ns, source_id in has_part_df.values:
|
|
127
|
-
rv.add_edge(f"{source_ns}:{source_id}", f"{prefix}:{target_id}", relation="part_of")
|
|
128
|
-
|
|
129
|
-
for relation in extra_relations:
|
|
130
|
-
if not isinstance(relation, (TypeDef, Reference)):
|
|
131
|
-
raise TypeError
|
|
132
|
-
relation_df = get_filtered_relations_df(
|
|
133
|
-
prefix=prefix,
|
|
134
|
-
relation=relation,
|
|
135
|
-
use_tqdm=use_tqdm,
|
|
136
|
-
force=force,
|
|
137
|
-
version=version,
|
|
138
|
-
)
|
|
139
|
-
for source_id, target_ns, target_id in relation_df.values:
|
|
140
|
-
rv.add_edge(
|
|
141
|
-
f"{prefix}:{source_id}", f"{target_ns}:{target_id}", relation=relation.identifier
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
for prop in properties:
|
|
145
|
-
props = get_filtered_properties_mapping(
|
|
146
|
-
prefix=prefix, prop=prop, use_tqdm=use_tqdm, force=force
|
|
147
|
-
)
|
|
148
|
-
for identifier, value in props.items():
|
|
149
|
-
curie = f"{prefix}:{identifier}"
|
|
150
|
-
if curie in rv:
|
|
151
|
-
rv.nodes[curie][prop] = value
|
|
119
|
+
predicates.add(part_of.reference)
|
|
120
|
+
reverse_predicates.add(has_part.reference)
|
|
121
|
+
if include_has_member:
|
|
122
|
+
predicates.add(has_member.reference)
|
|
123
|
+
reverse_predicates.add(member_of.reference)
|
|
124
|
+
return predicates, reverse_predicates
|
|
152
125
|
|
|
153
|
-
return rv
|
|
154
126
|
|
|
127
|
+
# docstr-coverage:excused `overload`
|
|
128
|
+
@overload
|
|
129
|
+
def is_descendent(
|
|
130
|
+
prefix: str,
|
|
131
|
+
identifier: str,
|
|
132
|
+
ancestor_prefix: str = ...,
|
|
133
|
+
ancestor_identifier: str = ...,
|
|
134
|
+
/,
|
|
135
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
136
|
+
) -> bool: ...
|
|
155
137
|
|
|
138
|
+
|
|
139
|
+
# docstr-coverage:excused `overload`
|
|
140
|
+
@overload
|
|
156
141
|
def is_descendent(
|
|
157
|
-
|
|
142
|
+
descendant: Reference,
|
|
143
|
+
ancestor: Reference,
|
|
144
|
+
_1: None = ...,
|
|
145
|
+
_2: None = ...,
|
|
146
|
+
/,
|
|
147
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
148
|
+
) -> bool: ...
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def is_descendent(
|
|
152
|
+
prefix: str | Reference,
|
|
153
|
+
identifier: str | Reference,
|
|
154
|
+
ancestor_prefix: str | None = None,
|
|
155
|
+
ancestor_identifier: str | None = None,
|
|
156
|
+
/,
|
|
157
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
158
158
|
) -> bool:
|
|
159
159
|
"""Check that the first identifier has the second as a descendent.
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
:param prefix: The prefix for the descendant
|
|
162
|
+
:param identifier: The local unique identifier for the descendant
|
|
163
|
+
:param ancestor_prefix: The prefix for the ancestor
|
|
164
|
+
:param ancestor_identifier: The local unique identifier for the ancestor
|
|
165
|
+
:param kwargs: Keyword arguments for :func:`get_hierarchy`
|
|
166
|
+
:return: If the decendant has the given ancestor
|
|
167
|
+
|
|
168
|
+
Check that ``GO:0070246`` (natural killer cell apoptotic process) is a descendant of
|
|
169
|
+
``GO:0006915`` (apoptotic process)
|
|
170
|
+
|
|
171
|
+
>>> nk_apoptosis = Reference.from_curie(
|
|
172
|
+
... "GO:0070246", name="natural killer cell apoptotic process"
|
|
173
|
+
... )
|
|
174
|
+
>>> apoptosis = Reference.from_curie("GO:0006915", name="apoptotic process")
|
|
175
|
+
>>> assert is_descendent(nk_apoptosis, apoptosis)
|
|
176
|
+
|
|
177
|
+
Using deprecated old-style arguments:
|
|
178
|
+
|
|
163
179
|
>>> assert is_descendent("go", "0070246", "go", "0006915")
|
|
164
180
|
"""
|
|
165
|
-
|
|
166
|
-
|
|
181
|
+
descendant, ancestor = _get_double_reference(
|
|
182
|
+
prefix, identifier, ancestor_prefix, ancestor_identifier
|
|
183
|
+
)
|
|
184
|
+
descendants = get_descendants(ancestor, **kwargs)
|
|
185
|
+
return descendants is not None and descendant in descendants
|
|
167
186
|
|
|
168
187
|
|
|
169
188
|
@lru_cache
|
|
170
189
|
def get_descendants(
|
|
171
|
-
prefix: str,
|
|
172
|
-
identifier:
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
force: bool = False,
|
|
177
|
-
**kwargs,
|
|
178
|
-
) -> Optional[set[str]]:
|
|
190
|
+
prefix: str | Reference | ReferenceTuple,
|
|
191
|
+
identifier: str | None = None,
|
|
192
|
+
/,
|
|
193
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
194
|
+
) -> set[Reference] | None:
|
|
179
195
|
"""Get all the descendants (children) of the term as CURIEs."""
|
|
180
|
-
|
|
181
|
-
hierarchy = get_hierarchy(
|
|
182
|
-
|
|
183
|
-
include_has_member=include_has_member,
|
|
184
|
-
include_part_of=include_part_of,
|
|
185
|
-
use_tqdm=use_tqdm,
|
|
186
|
-
force=force,
|
|
187
|
-
**kwargs,
|
|
188
|
-
)
|
|
189
|
-
if curie not in hierarchy:
|
|
196
|
+
t = _get_pi(prefix, identifier)
|
|
197
|
+
hierarchy = get_hierarchy(prefix=t.prefix, **kwargs)
|
|
198
|
+
if t not in hierarchy:
|
|
190
199
|
return None
|
|
191
|
-
return nx.ancestors(hierarchy,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
def _pic(prefix, identifier=None) -> tuple[str, str, str]:
|
|
195
|
-
if identifier is None:
|
|
196
|
-
curie = prefix
|
|
197
|
-
prefix, identifier = prefix.split(":")
|
|
198
|
-
else:
|
|
199
|
-
curie = f"{prefix}:{identifier}"
|
|
200
|
-
return curie, prefix, identifier
|
|
200
|
+
return nx.ancestors(hierarchy, t) # note this is backwards
|
|
201
201
|
|
|
202
202
|
|
|
203
203
|
@lru_cache
|
|
204
204
|
def get_children(
|
|
205
|
-
prefix: str,
|
|
206
|
-
identifier:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
force: bool = False,
|
|
211
|
-
**kwargs,
|
|
212
|
-
) -> Optional[set[str]]:
|
|
205
|
+
prefix: str | Reference | ReferenceTuple,
|
|
206
|
+
identifier: str | None = None,
|
|
207
|
+
/,
|
|
208
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
209
|
+
) -> set[Reference] | None:
|
|
213
210
|
"""Get all the descendants (children) of the term as CURIEs."""
|
|
214
|
-
|
|
215
|
-
hierarchy = get_hierarchy(
|
|
216
|
-
|
|
217
|
-
include_has_member=include_has_member,
|
|
218
|
-
include_part_of=include_part_of,
|
|
219
|
-
use_tqdm=use_tqdm,
|
|
220
|
-
force=force,
|
|
221
|
-
**kwargs,
|
|
222
|
-
)
|
|
223
|
-
if curie not in hierarchy:
|
|
211
|
+
t = _get_pi(prefix, identifier)
|
|
212
|
+
hierarchy = get_hierarchy(prefix=t.prefix, **kwargs)
|
|
213
|
+
if t not in hierarchy:
|
|
224
214
|
return None
|
|
225
|
-
return set(hierarchy.predecessors(
|
|
215
|
+
return set(hierarchy.predecessors(t))
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# docstr-coverage:excused `overload`
|
|
219
|
+
@overload
|
|
220
|
+
def has_ancestor(
|
|
221
|
+
prefix: str,
|
|
222
|
+
identifier: str,
|
|
223
|
+
ancestor_prefix: str = ...,
|
|
224
|
+
ancestor_identifier: str = ...,
|
|
225
|
+
/,
|
|
226
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
227
|
+
) -> bool: ...
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
# docstr-coverage:excused `overload`
|
|
231
|
+
@overload
|
|
232
|
+
def has_ancestor(
|
|
233
|
+
descendant: Reference,
|
|
234
|
+
ancestor: Reference,
|
|
235
|
+
_1: None = ...,
|
|
236
|
+
_2: None = ...,
|
|
237
|
+
/,
|
|
238
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
239
|
+
) -> bool: ...
|
|
226
240
|
|
|
227
241
|
|
|
228
242
|
def has_ancestor(
|
|
229
|
-
prefix
|
|
243
|
+
prefix: str | Reference,
|
|
244
|
+
identifier: str | Reference,
|
|
245
|
+
ancestor_prefix: str | None = None,
|
|
246
|
+
ancestor_identifier: str | None = None,
|
|
247
|
+
/,
|
|
248
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
230
249
|
) -> bool:
|
|
231
250
|
"""Check that the first identifier has the second as an ancestor.
|
|
232
251
|
|
|
233
|
-
|
|
252
|
+
:param prefix: The prefix for the descendant
|
|
253
|
+
:param identifier: The local unique identifier for the descendant
|
|
254
|
+
:param ancestor_prefix: The prefix for the ancestor
|
|
255
|
+
:param ancestor_identifier: The local unique identifier for the ancestor
|
|
256
|
+
:param kwargs: Keyword arguments for :func:`get_hierarchy`
|
|
257
|
+
:return: If the decendant has the given ancestor
|
|
258
|
+
|
|
259
|
+
Check that ``GO:0008219`` (cell death) is an ancestor of ``GO:0006915``
|
|
260
|
+
(apoptotic process):
|
|
261
|
+
|
|
262
|
+
>>> apoptosis = Reference.from_curie("GO:0006915", name="apoptotic process")
|
|
263
|
+
>>> cell_death = Reference.from_curie("GO:0008219", name="cell death")
|
|
264
|
+
>>> assert has_ancestor(apoptosis, cell_death)
|
|
265
|
+
|
|
266
|
+
The same, using the deprecated argumentation style:
|
|
267
|
+
|
|
234
268
|
>>> assert has_ancestor("go", "0006915", "go", "0008219")
|
|
235
269
|
"""
|
|
236
|
-
|
|
237
|
-
|
|
270
|
+
descendant, ancestor = _get_double_reference(
|
|
271
|
+
prefix, identifier, ancestor_prefix, ancestor_identifier
|
|
272
|
+
)
|
|
273
|
+
ancestors = get_ancestors(descendant, **kwargs)
|
|
274
|
+
return ancestors is not None and ancestor in ancestors
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def _get_double_reference(
|
|
278
|
+
a: str | Reference, b: str | Reference, c: str | None, d: str | None
|
|
279
|
+
) -> tuple[Reference, Reference]:
|
|
280
|
+
if isinstance(a, Reference) and isinstance(b, Reference):
|
|
281
|
+
return a, b
|
|
282
|
+
elif all(isinstance(x, str) for x in (a, b, c, d)):
|
|
283
|
+
warnings.warn("passing strings is deprecated", DeprecationWarning, stacklevel=2)
|
|
284
|
+
return Reference(prefix=a, identifier=b), Reference(prefix=c, identifier=d)
|
|
285
|
+
else:
|
|
286
|
+
raise TypeError
|
|
238
287
|
|
|
239
288
|
|
|
240
289
|
@lru_cache
|
|
241
290
|
def get_ancestors(
|
|
242
|
-
prefix: str,
|
|
243
|
-
identifier:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
force: bool = False,
|
|
248
|
-
**kwargs,
|
|
249
|
-
) -> Optional[set[str]]:
|
|
291
|
+
prefix: str | Reference | ReferenceTuple,
|
|
292
|
+
identifier: str | None = None,
|
|
293
|
+
/,
|
|
294
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
295
|
+
) -> set[Reference] | None:
|
|
250
296
|
"""Get all the ancestors (parents) of the term as CURIEs."""
|
|
251
|
-
|
|
252
|
-
hierarchy = get_hierarchy(
|
|
253
|
-
|
|
254
|
-
include_has_member=include_has_member,
|
|
255
|
-
include_part_of=include_part_of,
|
|
256
|
-
use_tqdm=use_tqdm,
|
|
257
|
-
force=force,
|
|
258
|
-
**kwargs,
|
|
259
|
-
)
|
|
260
|
-
if curie not in hierarchy:
|
|
297
|
+
t = _get_pi(prefix, identifier)
|
|
298
|
+
hierarchy = get_hierarchy(prefix=t.prefix, **kwargs)
|
|
299
|
+
if t not in hierarchy:
|
|
261
300
|
return None
|
|
262
|
-
|
|
301
|
+
|
|
302
|
+
return nx.descendants(hierarchy, t) # note this is backwards
|
|
263
303
|
|
|
264
304
|
|
|
265
305
|
def get_subhierarchy(
|
|
266
|
-
prefix: str,
|
|
267
|
-
identifier:
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
use_tqdm: bool = False,
|
|
271
|
-
force: bool = False,
|
|
272
|
-
**kwargs,
|
|
306
|
+
prefix: str | Reference | ReferenceTuple,
|
|
307
|
+
identifier: str | None = None,
|
|
308
|
+
/,
|
|
309
|
+
**kwargs: Unpack[HierarchyKwargs],
|
|
273
310
|
) -> nx.DiGraph:
|
|
274
311
|
"""Get the subhierarchy for a given node."""
|
|
275
|
-
|
|
276
|
-
hierarchy = get_hierarchy(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
include_part_of=include_part_of,
|
|
280
|
-
use_tqdm=use_tqdm,
|
|
281
|
-
force=force,
|
|
282
|
-
**kwargs,
|
|
283
|
-
)
|
|
284
|
-
logger.info(
|
|
285
|
-
"getting descendants of %s:%s ! %s", prefix, identifier, get_name(prefix, identifier)
|
|
286
|
-
)
|
|
287
|
-
curies = nx.ancestors(hierarchy, curie) # note this is backwards
|
|
312
|
+
t = _get_pi(prefix, identifier)
|
|
313
|
+
hierarchy = get_hierarchy(prefix=t.prefix, **kwargs)
|
|
314
|
+
logger.info("getting descendants of %s ! %s", t.curie, get_name(t))
|
|
315
|
+
descendants = set(nx.ancestors(hierarchy, t)) | {t} # note this is backwards
|
|
288
316
|
logger.info("inducing subgraph")
|
|
289
|
-
sg = hierarchy.subgraph(
|
|
317
|
+
sg = hierarchy.subgraph(descendants).copy()
|
|
290
318
|
logger.info("subgraph has %d nodes/%d edges", sg.number_of_nodes(), sg.number_of_edges())
|
|
291
319
|
return sg
|
pyobo/api/metadata.py
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
"""High-level API for metadata."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from collections.abc import Mapping
|
|
5
4
|
from functools import lru_cache
|
|
6
|
-
from typing import
|
|
5
|
+
from typing import Any, cast
|
|
7
6
|
|
|
8
|
-
from
|
|
7
|
+
from typing_extensions import Unpack
|
|
8
|
+
|
|
9
|
+
from .utils import get_version_from_kwargs
|
|
10
|
+
from ..constants import GetOntologyKwargs, check_should_force
|
|
9
11
|
from ..getters import get_ontology
|
|
10
12
|
from ..identifier_utils import wrap_norm_prefix
|
|
11
13
|
from ..utils.cache import cached_json
|
|
12
|
-
from ..utils.path import
|
|
14
|
+
from ..utils.path import CacheArtifact, get_cache_path
|
|
13
15
|
|
|
14
16
|
__all__ = [
|
|
15
17
|
"get_metadata",
|
|
@@ -20,21 +22,14 @@ logger = logging.getLogger(__name__)
|
|
|
20
22
|
|
|
21
23
|
@lru_cache
|
|
22
24
|
@wrap_norm_prefix
|
|
23
|
-
def get_metadata(
|
|
24
|
-
prefix: str, *, force: bool = False, version: Optional[str] = None
|
|
25
|
-
) -> Mapping[str, str]:
|
|
25
|
+
def get_metadata(prefix: str, **kwargs: Unpack[GetOntologyKwargs]) -> dict[str, Any]:
|
|
26
26
|
"""Get metadata for the ontology."""
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if force:
|
|
34
|
-
logger.debug("[%s] forcing reload for metadata", prefix)
|
|
35
|
-
else:
|
|
36
|
-
logger.debug("[%s] no cached metadata found. getting from OBO loader", prefix)
|
|
37
|
-
ontology = get_ontology(prefix, force=force, version=version)
|
|
27
|
+
version = get_version_from_kwargs(prefix, kwargs)
|
|
28
|
+
path = get_cache_path(prefix, CacheArtifact.metadata, version=version)
|
|
29
|
+
|
|
30
|
+
@cached_json(path=path, force=check_should_force(kwargs))
|
|
31
|
+
def _get_json() -> dict[str, Any]:
|
|
32
|
+
ontology = get_ontology(prefix, **kwargs)
|
|
38
33
|
return ontology.get_metadata()
|
|
39
34
|
|
|
40
|
-
return _get_json()
|
|
35
|
+
return cast(dict[str, Any], _get_json())
|