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/cli/lookup.py
CHANGED
|
@@ -2,17 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import sys
|
|
5
|
-
from
|
|
5
|
+
from collections.abc import Mapping
|
|
6
6
|
|
|
7
7
|
import bioregistry
|
|
8
8
|
import click
|
|
9
9
|
from more_click import verbose_option
|
|
10
|
+
from typing_extensions import Unpack
|
|
10
11
|
|
|
11
12
|
from .utils import (
|
|
13
|
+
Clickable,
|
|
12
14
|
echo_df,
|
|
13
15
|
force_option,
|
|
14
|
-
|
|
16
|
+
force_process_option,
|
|
15
17
|
prefix_argument,
|
|
18
|
+
strict_option,
|
|
16
19
|
version_option,
|
|
17
20
|
)
|
|
18
21
|
from ..api import (
|
|
@@ -28,15 +31,17 @@ from ..api import (
|
|
|
28
31
|
get_id_synonyms_mapping,
|
|
29
32
|
get_id_to_alts,
|
|
30
33
|
get_ids,
|
|
34
|
+
get_mappings_df,
|
|
31
35
|
get_metadata,
|
|
32
36
|
get_name,
|
|
33
|
-
get_name_by_curie,
|
|
34
37
|
get_properties_df,
|
|
35
38
|
get_relations_df,
|
|
36
39
|
get_typedef_df,
|
|
37
40
|
get_xrefs_df,
|
|
38
41
|
)
|
|
39
|
-
from ..
|
|
42
|
+
from ..constants import LookupKwargs
|
|
43
|
+
from ..getters import get_ontology
|
|
44
|
+
from ..struct.reference import _parse_str_or_curie_or_uri
|
|
40
45
|
|
|
41
46
|
__all__ = [
|
|
42
47
|
"lookup",
|
|
@@ -48,150 +53,123 @@ def lookup():
|
|
|
48
53
|
"""Lookup resources."""
|
|
49
54
|
|
|
50
55
|
|
|
51
|
-
|
|
52
|
-
|
|
56
|
+
def lookup_annotate(f: Clickable) -> Clickable:
|
|
57
|
+
"""Add appropriate decorators to lookup CLI functions."""
|
|
58
|
+
for decorator in [
|
|
59
|
+
lookup.command(),
|
|
60
|
+
prefix_argument,
|
|
61
|
+
verbose_option,
|
|
62
|
+
force_option,
|
|
63
|
+
force_process_option,
|
|
64
|
+
strict_option,
|
|
65
|
+
version_option,
|
|
66
|
+
]:
|
|
67
|
+
f = decorator(f)
|
|
68
|
+
return f
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
identifier_option = click.option("-i", "--identifier")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@lookup_annotate
|
|
53
75
|
@click.option("-t", "--target")
|
|
54
|
-
|
|
55
|
-
@force_option
|
|
56
|
-
@no_strict_option
|
|
57
|
-
@version_option
|
|
58
|
-
def xrefs(prefix: str, target: str, force: bool, no_strict: bool, version: Optional[str]):
|
|
76
|
+
def xrefs(target: str, **kwargs: Unpack[LookupKwargs]) -> None:
|
|
59
77
|
"""Page through xrefs for the given namespace to the second given namespace."""
|
|
60
78
|
if target:
|
|
61
|
-
|
|
62
|
-
filtered_xrefs = get_filtered_xrefs(
|
|
63
|
-
prefix, target, force=force, strict=not no_strict, version=version
|
|
64
|
-
)
|
|
79
|
+
target_norm = bioregistry.normalize_prefix(target)
|
|
80
|
+
filtered_xrefs = get_filtered_xrefs(xref_prefix=target_norm, **kwargs)
|
|
65
81
|
click.echo_via_pager(
|
|
66
82
|
"\n".join(f"{identifier}\t{_xref}" for identifier, _xref in filtered_xrefs.items())
|
|
67
83
|
)
|
|
68
84
|
else:
|
|
69
|
-
all_xrefs_df = get_xrefs_df(
|
|
85
|
+
all_xrefs_df = get_xrefs_df(**kwargs)
|
|
70
86
|
echo_df(all_xrefs_df)
|
|
71
87
|
|
|
72
88
|
|
|
73
|
-
@
|
|
74
|
-
@
|
|
75
|
-
@
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
89
|
+
@lookup_annotate
|
|
90
|
+
@click.option("--include-names", is_flag=True)
|
|
91
|
+
@click.option("-t", "--target")
|
|
92
|
+
def mappings(include_names: bool, target: str | None, **kwargs: Unpack[LookupKwargs]) -> None:
|
|
93
|
+
"""Page through mappings for the given namespace."""
|
|
94
|
+
mappings_df = get_mappings_df(names=include_names, **kwargs)
|
|
95
|
+
if target:
|
|
96
|
+
target_norm = bioregistry.normalize_prefix(target)
|
|
97
|
+
if target_norm is None:
|
|
98
|
+
raise ValueError
|
|
99
|
+
idx = mappings_df["object_id"].map(
|
|
100
|
+
lambda x: bioregistry.normalize_prefix(x.split(":")[0]) == target_norm
|
|
101
|
+
)
|
|
102
|
+
mappings_df = mappings_df[idx]
|
|
103
|
+
echo_df(mappings_df)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@lookup_annotate
|
|
107
|
+
def metadata(**kwargs: Unpack[LookupKwargs]) -> None:
|
|
79
108
|
"""Print the metadata for the given namespace."""
|
|
80
|
-
metadata = get_metadata(
|
|
109
|
+
metadata = get_metadata(**kwargs)
|
|
81
110
|
click.echo(json.dumps(metadata, indent=2))
|
|
82
111
|
|
|
83
112
|
|
|
84
|
-
@
|
|
85
|
-
|
|
86
|
-
@verbose_option
|
|
87
|
-
@force_option
|
|
88
|
-
@no_strict_option
|
|
89
|
-
@version_option
|
|
90
|
-
def ids(prefix: str, force: bool, no_strict: bool, version: Optional[str]):
|
|
113
|
+
@lookup_annotate
|
|
114
|
+
def ids(**kwargs: Unpack[LookupKwargs]) -> None:
|
|
91
115
|
"""Page through the identifiers of entities in the given namespace."""
|
|
92
|
-
id_list = get_ids(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
@lookup.command()
|
|
97
|
-
@prefix_argument
|
|
98
|
-
@verbose_option
|
|
99
|
-
@force_option
|
|
100
|
-
@no_strict_option
|
|
101
|
-
@click.option("-i", "--identifier")
|
|
102
|
-
@version_option
|
|
103
|
-
def names(
|
|
104
|
-
prefix: str, identifier: Optional[str], force: bool, no_strict: bool, version: Optional[str]
|
|
105
|
-
):
|
|
106
|
-
"""Page through the identifiers and names of entities in the given namespace."""
|
|
107
|
-
id_to_name = get_id_name_mapping(prefix, force=force, strict=not no_strict, version=version)
|
|
108
|
-
if identifier is None:
|
|
109
|
-
_help_page_mapping(id_to_name)
|
|
116
|
+
id_list = get_ids(**kwargs)
|
|
117
|
+
if not id_list:
|
|
118
|
+
click.secho("no data", fg="red")
|
|
110
119
|
else:
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
@
|
|
123
|
-
@
|
|
124
|
-
|
|
125
|
-
def species(
|
|
126
|
-
prefix: str, identifier: Optional[str], force: bool, no_strict: bool, version: Optional[str]
|
|
127
|
-
):
|
|
120
|
+
click.echo_via_pager("\n".join(id_list))
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@lookup_annotate
|
|
124
|
+
@identifier_option
|
|
125
|
+
def names(identifier: str | None, **kwargs: Unpack[LookupKwargs]) -> None:
|
|
126
|
+
"""Page through the identifiers and names of entities in the given namespace."""
|
|
127
|
+
id_to_name = get_id_name_mapping(**kwargs)
|
|
128
|
+
_help_page_mapping(id_to_name, identifier=identifier)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@lookup_annotate
|
|
132
|
+
@identifier_option
|
|
133
|
+
def species(identifier: str | None, **kwargs: Unpack[LookupKwargs]) -> None:
|
|
128
134
|
"""Page through the identifiers and species of entities in the given namespace."""
|
|
129
|
-
id_to_species = get_id_species_mapping(
|
|
130
|
-
|
|
131
|
-
)
|
|
132
|
-
if identifier is None:
|
|
133
|
-
_help_page_mapping(id_to_species)
|
|
134
|
-
else:
|
|
135
|
-
species = id_to_species.get(identifier)
|
|
136
|
-
if species is None:
|
|
137
|
-
click.secho(f"No species available for {identifier}", fg="red")
|
|
138
|
-
else:
|
|
139
|
-
click.echo(species)
|
|
135
|
+
id_to_species = get_id_species_mapping(**kwargs)
|
|
136
|
+
_help_page_mapping(id_to_species, identifier=identifier)
|
|
140
137
|
|
|
141
138
|
|
|
142
|
-
@
|
|
143
|
-
@
|
|
144
|
-
|
|
145
|
-
@force_option
|
|
146
|
-
@click.option("-i", "--identifier")
|
|
147
|
-
@version_option
|
|
148
|
-
def definitions(prefix: str, identifier: Optional[str], force: bool, version: Optional[str]):
|
|
139
|
+
@lookup_annotate
|
|
140
|
+
@identifier_option
|
|
141
|
+
def definitions(identifier: str | None, **kwargs: Unpack[LookupKwargs]) -> None:
|
|
149
142
|
"""Page through the identifiers and definitions of entities in the given namespace."""
|
|
150
|
-
id_to_definition = get_id_definition_mapping(
|
|
151
|
-
|
|
152
|
-
_help_page_mapping(id_to_definition)
|
|
153
|
-
else:
|
|
154
|
-
definition = id_to_definition.get(identifier)
|
|
155
|
-
if definition is None:
|
|
156
|
-
click.secho(f"No definition available for {identifier}", fg="red")
|
|
157
|
-
else:
|
|
158
|
-
click.echo(definition)
|
|
143
|
+
id_to_definition = get_id_definition_mapping(**kwargs)
|
|
144
|
+
_help_page_mapping(id_to_definition, identifier=identifier)
|
|
159
145
|
|
|
160
146
|
|
|
161
|
-
@
|
|
162
|
-
|
|
163
|
-
@verbose_option
|
|
164
|
-
@force_option
|
|
165
|
-
@version_option
|
|
166
|
-
def typedefs(prefix: str, force: bool, version: Optional[str]):
|
|
147
|
+
@lookup_annotate
|
|
148
|
+
def typedefs(**kwargs: Unpack[LookupKwargs]) -> None:
|
|
167
149
|
"""Page through the identifiers and names of typedefs in the given namespace."""
|
|
168
|
-
df = get_typedef_df(
|
|
150
|
+
df = get_typedef_df(**kwargs)
|
|
169
151
|
echo_df(df)
|
|
170
152
|
|
|
171
153
|
|
|
172
|
-
def _help_page_mapping(id_to_name):
|
|
173
|
-
|
|
154
|
+
def _help_page_mapping(id_to_name: Mapping[str, str], *, identifier: str | None = None) -> None:
|
|
155
|
+
if not id_to_name:
|
|
156
|
+
click.secho("no data", fg="red")
|
|
157
|
+
elif identifier:
|
|
158
|
+
value = id_to_name.get(identifier)
|
|
159
|
+
if value:
|
|
160
|
+
click.echo(value)
|
|
161
|
+
else:
|
|
162
|
+
click.secho(f"no data for {identifier}", fg="red")
|
|
163
|
+
else:
|
|
164
|
+
click.echo_via_pager("\n".join("\t".join(item) for item in id_to_name.items()))
|
|
174
165
|
|
|
175
166
|
|
|
176
|
-
@
|
|
177
|
-
@
|
|
178
|
-
|
|
179
|
-
@force_option
|
|
180
|
-
@version_option
|
|
181
|
-
def synonyms(prefix: str, force: bool, version: Optional[str]):
|
|
167
|
+
@lookup_annotate
|
|
168
|
+
@identifier_option
|
|
169
|
+
def synonyms(identifier: str | None, **kwargs: Unpack[LookupKwargs]) -> None:
|
|
182
170
|
"""Page through the synonyms for entities in the given namespace."""
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if _prefix is None or identifier is None:
|
|
186
|
-
click.secho(f"could not normalize {prefix}")
|
|
187
|
-
return sys.exit(1)
|
|
188
|
-
name = get_name(_prefix, identifier)
|
|
189
|
-
id_to_synonyms = get_id_synonyms_mapping(_prefix, force=force)
|
|
190
|
-
click.echo(f"Synonyms for {_prefix}:{identifier} ! {name}")
|
|
191
|
-
for synonym in id_to_synonyms.get(identifier, []):
|
|
192
|
-
click.echo(synonym)
|
|
193
|
-
else: # it's a prefix
|
|
194
|
-
id_to_synonyms = get_id_synonyms_mapping(prefix, force=force, version=version)
|
|
171
|
+
id_to_synonyms = get_id_synonyms_mapping(**kwargs)
|
|
172
|
+
if identifier is None:
|
|
195
173
|
click.echo_via_pager(
|
|
196
174
|
"\n".join(
|
|
197
175
|
f"{identifier}\t{_synonym}"
|
|
@@ -199,136 +177,126 @@ def synonyms(prefix: str, force: bool, version: Optional[str]):
|
|
|
199
177
|
for _synonym in _synonyms
|
|
200
178
|
)
|
|
201
179
|
)
|
|
180
|
+
else:
|
|
181
|
+
synonyms = id_to_synonyms.get(identifier, [])
|
|
182
|
+
if not synonyms:
|
|
183
|
+
click.secho(f"No synonyms available for {identifier}", fg="red")
|
|
184
|
+
else:
|
|
185
|
+
click.echo_via_pager("\n".join(synonyms))
|
|
202
186
|
|
|
203
187
|
|
|
204
|
-
@
|
|
205
|
-
@prefix_argument
|
|
188
|
+
@lookup_annotate
|
|
206
189
|
@click.option(
|
|
207
190
|
"--relation", help="CURIE for the relationship or just the ID if local to the ontology"
|
|
208
191
|
)
|
|
209
192
|
@click.option("--target", help="Prefix for the target")
|
|
210
|
-
@verbose_option
|
|
211
|
-
@no_strict_option
|
|
212
|
-
@force_option
|
|
213
193
|
@click.option("--summarize", is_flag=True)
|
|
214
|
-
@version_option
|
|
215
194
|
def relations(
|
|
216
|
-
prefix: str,
|
|
217
195
|
relation: str,
|
|
218
196
|
target: str,
|
|
219
|
-
force: bool,
|
|
220
|
-
no_strict: bool,
|
|
221
197
|
summarize: bool,
|
|
222
|
-
|
|
223
|
-
):
|
|
198
|
+
**kwargs: Unpack[LookupKwargs],
|
|
199
|
+
) -> None:
|
|
224
200
|
"""Page through the relations for entities in the given namespace."""
|
|
225
201
|
if relation is None:
|
|
226
|
-
relations_df = get_relations_df(
|
|
202
|
+
relations_df = get_relations_df(**kwargs)
|
|
227
203
|
if summarize:
|
|
228
204
|
click.echo(relations_df[relations_df.columns[2]].value_counts())
|
|
229
205
|
else:
|
|
230
206
|
echo_df(relations_df)
|
|
231
207
|
else:
|
|
232
|
-
|
|
233
|
-
if
|
|
234
|
-
click.secho(f"not valid curie
|
|
235
|
-
|
|
208
|
+
relation_reference = _parse_str_or_curie_or_uri(relation, strict=False)
|
|
209
|
+
if relation_reference is None:
|
|
210
|
+
click.secho(f"not a valid curie: {relation}", fg="red")
|
|
211
|
+
raise sys.exit(1)
|
|
236
212
|
|
|
237
213
|
if target is not None:
|
|
238
214
|
norm_target = bioregistry.normalize_prefix(target)
|
|
239
215
|
if norm_target is None:
|
|
240
216
|
raise ValueError
|
|
241
217
|
relations_df = get_filtered_relations_df(
|
|
242
|
-
|
|
218
|
+
relation=relation_reference,
|
|
219
|
+
target=norm_target,
|
|
220
|
+
**kwargs,
|
|
243
221
|
)
|
|
244
222
|
else:
|
|
245
223
|
raise NotImplementedError(f"can not filter by target prefix {target}")
|
|
246
224
|
|
|
247
225
|
|
|
248
|
-
@
|
|
249
|
-
@prefix_argument
|
|
226
|
+
@lookup_annotate
|
|
250
227
|
@click.option("--include-part-of", is_flag=True)
|
|
251
228
|
@click.option("--include-has-member", is_flag=True)
|
|
252
|
-
@verbose_option
|
|
253
|
-
@force_option
|
|
254
|
-
@version_option
|
|
255
229
|
def hierarchy(
|
|
256
|
-
prefix: str,
|
|
257
230
|
include_part_of: bool,
|
|
258
231
|
include_has_member: bool,
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
):
|
|
232
|
+
**kwargs: Unpack[LookupKwargs],
|
|
233
|
+
) -> None:
|
|
262
234
|
"""Page through the hierarchy for entities in the namespace."""
|
|
263
235
|
h = get_hierarchy(
|
|
264
|
-
prefix,
|
|
265
236
|
include_part_of=include_part_of,
|
|
266
237
|
include_has_member=include_has_member,
|
|
267
|
-
|
|
268
|
-
version=version,
|
|
238
|
+
**kwargs,
|
|
269
239
|
)
|
|
270
|
-
|
|
240
|
+
if h.number_of_edges() == 0:
|
|
241
|
+
click.secho("no data", fg="red")
|
|
242
|
+
else:
|
|
243
|
+
click.echo_via_pager("\n".join(f"{u.curie}\t{v.curie}" for u, v in h.edges()))
|
|
271
244
|
|
|
272
245
|
|
|
273
|
-
@
|
|
274
|
-
@prefix_argument
|
|
246
|
+
@lookup_annotate
|
|
275
247
|
@click.argument("identifier")
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
248
|
+
def ancestors(
|
|
249
|
+
identifier: str,
|
|
250
|
+
**kwargs: Unpack[LookupKwargs],
|
|
251
|
+
) -> None:
|
|
280
252
|
"""Look up ancestors."""
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
253
|
+
# note, prefix is passed via kwargs
|
|
254
|
+
ancestors = get_ancestors(identifier=identifier, **kwargs)
|
|
255
|
+
for ancestor in sorted(ancestors or []):
|
|
256
|
+
click.echo(f"{ancestor.curie}\t{get_name(ancestor, version=kwargs['version'])}")
|
|
284
257
|
|
|
285
258
|
|
|
286
|
-
@
|
|
287
|
-
@prefix_argument
|
|
259
|
+
@lookup_annotate
|
|
288
260
|
@click.argument("identifier")
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
261
|
+
def descendants(
|
|
262
|
+
identifier: str,
|
|
263
|
+
**kwargs: Unpack[LookupKwargs],
|
|
264
|
+
) -> None:
|
|
293
265
|
"""Look up descendants."""
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
266
|
+
# note, prefix is passed via kwargs
|
|
267
|
+
descendants = get_descendants(identifier=identifier, **kwargs)
|
|
268
|
+
for descendant in sorted(descendants or []):
|
|
269
|
+
click.echo(f"{descendant.curie}\t{get_name(descendant, version=kwargs['version'])}")
|
|
297
270
|
|
|
298
271
|
|
|
299
|
-
@
|
|
300
|
-
@prefix_argument
|
|
272
|
+
@lookup_annotate
|
|
301
273
|
@click.option("-k", "--key")
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
274
|
+
def properties(
|
|
275
|
+
key: str | None,
|
|
276
|
+
**kwargs: Unpack[LookupKwargs],
|
|
277
|
+
) -> None:
|
|
306
278
|
"""Page through the properties for entities in the given namespace."""
|
|
307
279
|
if key is None:
|
|
308
|
-
properties_df = get_properties_df(
|
|
280
|
+
properties_df = get_properties_df(**kwargs)
|
|
309
281
|
else:
|
|
310
|
-
properties_df = get_filtered_properties_df(
|
|
282
|
+
properties_df = get_filtered_properties_df(prop=key, **kwargs)
|
|
311
283
|
echo_df(properties_df)
|
|
312
284
|
|
|
313
285
|
|
|
314
|
-
@
|
|
315
|
-
@
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
def alts(prefix: str, identifier: Optional[str], force: bool, version: Optional[str]):
|
|
286
|
+
@lookup_annotate
|
|
287
|
+
@identifier_option
|
|
288
|
+
def alts(
|
|
289
|
+
identifier: str | None,
|
|
290
|
+
**kwargs: Unpack[LookupKwargs],
|
|
291
|
+
) -> None:
|
|
321
292
|
"""Page through alt ids in a namespace."""
|
|
322
|
-
id_to_alts = get_id_to_alts(
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
click.secho(f"No alternate identifiers for {identifier}", fg="red")
|
|
333
|
-
else:
|
|
334
|
-
click.echo("\n".join(_alts))
|
|
293
|
+
id_to_alts = get_id_to_alts(**kwargs)
|
|
294
|
+
_help_page_mapping(id_to_alts, identifier=identifier)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
@lookup_annotate
|
|
298
|
+
def prefixes(**kwargs: Unpack[LookupKwargs]) -> None:
|
|
299
|
+
"""Page through prefixes appearing in an ontology."""
|
|
300
|
+
ontology = get_ontology(**kwargs)
|
|
301
|
+
for prefix in sorted(ontology._get_prefixes(), key=str.casefold):
|
|
302
|
+
click.echo(prefix)
|
pyobo/cli/utils.py
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import datetime
|
|
4
4
|
import pathlib
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
from typing import TypeVar
|
|
5
7
|
|
|
6
8
|
import click
|
|
7
9
|
import pandas as pd
|
|
@@ -9,12 +11,14 @@ import pandas as pd
|
|
|
9
11
|
from ..constants import DATABASE_DIRECTORY
|
|
10
12
|
|
|
11
13
|
__all__ = [
|
|
12
|
-
"
|
|
14
|
+
"Clickable",
|
|
13
15
|
"directory_option",
|
|
14
|
-
"
|
|
16
|
+
"echo_df",
|
|
15
17
|
"force_option",
|
|
18
|
+
"force_process_option",
|
|
16
19
|
"prefix_argument",
|
|
17
|
-
"
|
|
20
|
+
"strict_option",
|
|
21
|
+
"zenodo_option",
|
|
18
22
|
]
|
|
19
23
|
|
|
20
24
|
|
|
@@ -37,12 +41,21 @@ directory_option = click.option(
|
|
|
37
41
|
help=f"Build location. Defaults to {DATABASE_DIRECTORY}/<today>",
|
|
38
42
|
)
|
|
39
43
|
zenodo_option = click.option("--zenodo", is_flag=True, help="Automatically upload to zenodo")
|
|
40
|
-
|
|
41
|
-
"
|
|
44
|
+
strict_option = click.option(
|
|
45
|
+
"--strict/--no-strict",
|
|
46
|
+
default=False,
|
|
47
|
+
show_default=True,
|
|
48
|
+
help="Turn on or off failure on unparsable CURIEs",
|
|
42
49
|
)
|
|
43
50
|
prefix_argument = click.argument("prefix")
|
|
44
|
-
force_option = click.option(
|
|
51
|
+
force_option = click.option(
|
|
52
|
+
"-f", "--force", is_flag=True, help="Force re-downloading and re-processing"
|
|
53
|
+
)
|
|
45
54
|
version_option = click.option(
|
|
46
55
|
"--version",
|
|
47
56
|
help="Explicit version of the data. If not given, the most recent will be looked up.",
|
|
48
57
|
)
|
|
58
|
+
force_process_option = click.option(
|
|
59
|
+
"--force-process", is_flag=True, help="Force re-processing, but not necessarily re-downloading"
|
|
60
|
+
)
|
|
61
|
+
Clickable = TypeVar("Clickable", bound=Callable)
|
pyobo/constants.py
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
"""Constants for PyOBO."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
3
5
|
import logging
|
|
4
6
|
import re
|
|
5
7
|
|
|
6
8
|
import pystow
|
|
9
|
+
from typing_extensions import NotRequired, TypedDict
|
|
7
10
|
|
|
8
11
|
__all__ = [
|
|
9
|
-
"RAW_DIRECTORY",
|
|
10
12
|
"DATABASE_DIRECTORY",
|
|
13
|
+
"RAW_DIRECTORY",
|
|
11
14
|
"SPECIES_REMAPPING",
|
|
12
15
|
]
|
|
13
16
|
|
|
@@ -19,6 +22,15 @@ RAW_DIRECTORY = RAW_MODULE.base
|
|
|
19
22
|
DATABASE_MODULE = PYOBO_MODULE.module("database")
|
|
20
23
|
DATABASE_DIRECTORY = DATABASE_MODULE.base
|
|
21
24
|
|
|
25
|
+
#: The directory inside an ontology cache where
|
|
26
|
+
#: large artifacts like OBO, OWL, JSON, etc. go
|
|
27
|
+
BUILD_SUBDIRECTORY_NAME = "build"
|
|
28
|
+
#: The directory inside an ontology cache where
|
|
29
|
+
#: small caches for alts, xrefs, names, etc. go
|
|
30
|
+
CACHE_SUBDIRECTORY_NAME = "cache"
|
|
31
|
+
#: the directory for caching relations
|
|
32
|
+
RELATION_SUBDIRECTORY_NAME = "relations"
|
|
33
|
+
|
|
22
34
|
SPECIES_REMAPPING = {
|
|
23
35
|
"Canis familiaris": "Canis lupus familiaris",
|
|
24
36
|
}
|
|
@@ -29,7 +41,6 @@ GLOBAL_SKIP = {
|
|
|
29
41
|
"resid", # deprecated
|
|
30
42
|
"adw", # deprecated
|
|
31
43
|
}
|
|
32
|
-
GLOBAL_CHECK_IDS = False
|
|
33
44
|
|
|
34
45
|
#: Default prefix
|
|
35
46
|
DEFAULT_PREFIX = "debio"
|
|
@@ -79,7 +90,7 @@ TYPEDEFS_FILE = "typedefs.tsv.gz"
|
|
|
79
90
|
SPECIES_RECORD = "5334738"
|
|
80
91
|
SPECIES_FILE = "species.tsv.gz"
|
|
81
92
|
|
|
82
|
-
NCBITAXON_PREFIX = "
|
|
93
|
+
NCBITAXON_PREFIX = "ncbitaxon"
|
|
83
94
|
DATE_FORMAT = "%d:%m:%Y %H:%M"
|
|
84
95
|
PROVENANCE_PREFIXES = {
|
|
85
96
|
"pubmed",
|
|
@@ -97,3 +108,91 @@ PROVENANCE_PREFIXES = {
|
|
|
97
108
|
"isbn",
|
|
98
109
|
"issn",
|
|
99
110
|
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class DatabaseKwargs(TypedDict):
|
|
114
|
+
"""Keyword arguments for database CLI functions."""
|
|
115
|
+
|
|
116
|
+
strict: bool
|
|
117
|
+
force: bool
|
|
118
|
+
force_process: bool
|
|
119
|
+
skip_pyobo: bool
|
|
120
|
+
skip_below: str | None
|
|
121
|
+
skip_set: set[str] | None
|
|
122
|
+
use_tqdm: bool
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class SlimGetOntologyKwargs(TypedDict):
|
|
126
|
+
"""Keyword arguments for database CLI functions.
|
|
127
|
+
|
|
128
|
+
These arguments are global during iteration over _all_ ontologies, whereas the
|
|
129
|
+
additional ``version`` is added in the subclass below for specific instances when
|
|
130
|
+
only a single ontology is requested.
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
strict: NotRequired[bool]
|
|
134
|
+
force: NotRequired[bool]
|
|
135
|
+
force_process: NotRequired[bool]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class GetOntologyKwargs(SlimGetOntologyKwargs):
|
|
139
|
+
"""Represents the optional keyword arguments passed to :func:`pyobo.get_ontology`.
|
|
140
|
+
|
|
141
|
+
This dictionary doesn't contain ``prefix`` since this is always explicitly handled.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
version: NotRequired[str | None]
|
|
145
|
+
cache: NotRequired[bool]
|
|
146
|
+
use_tqdm: NotRequired[bool]
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def check_should_force(data: GetOntologyKwargs) -> bool:
|
|
150
|
+
"""Determine whether caching should be forced based on generic keyword arguments."""
|
|
151
|
+
# note that this could be applied to the superclass of GetOntologyKwargs
|
|
152
|
+
# but this function should only be used in the scope where GetOntologyKwargs
|
|
153
|
+
# is appropriate.
|
|
154
|
+
return data.get("force", False) or data.get("force_process", False)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def check_should_cache(data: GetOntologyKwargs) -> bool:
|
|
158
|
+
"""Determine whether caching should be done based on generic keyword arguments."""
|
|
159
|
+
return data.get("cache", True)
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def check_should_use_tqdm(data: GetOntologyKwargs) -> bool:
|
|
163
|
+
"""Determine whether caching should be done based on generic keyword arguments."""
|
|
164
|
+
return data.get("use_tqdm", True)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class LookupKwargs(GetOntologyKwargs):
|
|
168
|
+
"""Represents all arguments passed to :func:`pyobo.get_ontology`.
|
|
169
|
+
|
|
170
|
+
This dictionary does contain the ``prefix`` since it's used in the scope of CLI
|
|
171
|
+
functions.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
prefix: str
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class IterHelperHelperDict(SlimGetOntologyKwargs):
|
|
178
|
+
"""Represents arguments needed when iterating over all ontologies.
|
|
179
|
+
|
|
180
|
+
The explicitly defind arguments in this typed dict are used for the loop function
|
|
181
|
+
:func:`iter_helper_helper` and the rest that are inherited get passed to
|
|
182
|
+
:func:`pyobo.get_ontology` in each iteration.
|
|
183
|
+
"""
|
|
184
|
+
|
|
185
|
+
use_tqdm: bool
|
|
186
|
+
skip_below: str | None
|
|
187
|
+
skip_pyobo: bool
|
|
188
|
+
skip_set: set[str] | None
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
#: from table 2 of the Functional OWL syntax definition
|
|
192
|
+
#: at https://www.w3.org/TR/owl2-syntax/#IRIs
|
|
193
|
+
DEFAULT_PREFIX_MAP = {
|
|
194
|
+
"rdfs": "http://www.w3.org/2000/01/rdf-schema#",
|
|
195
|
+
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
|
196
|
+
"xsd": "http://www.w3.org/2001/XMLSchema#",
|
|
197
|
+
"owl": "http://www.w3.org/2002/07/owl#",
|
|
198
|
+
}
|