pyobo 0.11.1__py3-none-any.whl → 0.11.2__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/version.py +1 -1
- {pyobo-0.11.1.dist-info → pyobo-0.11.2.dist-info}/METADATA +23 -23
- {pyobo-0.11.1.dist-info → pyobo-0.11.2.dist-info}/RECORD +6 -22
- {pyobo-0.11.1.dist-info → pyobo-0.11.2.dist-info}/WHEEL +1 -1
- pyobo/apps/__init__.py +0 -3
- pyobo/apps/cli.py +0 -24
- pyobo/apps/gilda/__init__.py +0 -3
- pyobo/apps/gilda/__main__.py +0 -8
- pyobo/apps/gilda/app.py +0 -48
- pyobo/apps/gilda/cli.py +0 -36
- pyobo/apps/gilda/templates/base.html +0 -33
- pyobo/apps/gilda/templates/home.html +0 -11
- pyobo/apps/gilda/templates/matches.html +0 -32
- pyobo/apps/mapper/__init__.py +0 -3
- pyobo/apps/mapper/__main__.py +0 -11
- pyobo/apps/mapper/cli.py +0 -37
- pyobo/apps/mapper/mapper.py +0 -187
- pyobo/apps/mapper/templates/base.html +0 -35
- pyobo/apps/mapper/templates/mapper_home.html +0 -64
- pyobo-0.11.1.dist-info/LICENSE +0 -21
- {pyobo-0.11.1.dist-info → pyobo-0.11.2.dist-info}/entry_points.txt +0 -0
- {pyobo-0.11.1.dist-info → pyobo-0.11.2.dist-info}/top_level.txt +0 -0
pyobo/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyobo
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.2
|
|
4
4
|
Summary: A python package for handling and generating OBO
|
|
5
5
|
Author-email: Charles Tapley Hoyt <cthoyt@gmail.com>
|
|
6
6
|
Maintainer-email: Charles Tapley Hoyt <cthoyt@gmail.com>
|
|
@@ -49,40 +49,40 @@ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
|
49
49
|
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
50
50
|
Requires-Python: >=3.9
|
|
51
51
|
Description-Content-Type: text/markdown
|
|
52
|
-
|
|
53
|
-
Requires-Dist: obonet >=0.3.0
|
|
52
|
+
Requires-Dist: obonet>=0.3.0
|
|
54
53
|
Requires-Dist: click
|
|
55
54
|
Requires-Dist: tqdm
|
|
56
55
|
Requires-Dist: pyyaml
|
|
57
56
|
Requires-Dist: pandas
|
|
58
57
|
Requires-Dist: requests
|
|
59
58
|
Requires-Dist: protmapper
|
|
60
|
-
Requires-Dist:
|
|
61
|
-
Requires-Dist:
|
|
59
|
+
Requires-Dist: more_itertools
|
|
60
|
+
Requires-Dist: more_click>=0.0.2
|
|
62
61
|
Requires-Dist: humanize
|
|
63
62
|
Requires-Dist: tabulate
|
|
64
63
|
Requires-Dist: cachier
|
|
65
|
-
Requires-Dist: pystow
|
|
66
|
-
Requires-Dist: bioversions
|
|
67
|
-
Requires-Dist: bioregistry
|
|
68
|
-
Requires-Dist: bioontologies
|
|
69
|
-
Requires-Dist: zenodo-client
|
|
70
|
-
Requires-Dist:
|
|
64
|
+
Requires-Dist: pystow>=0.2.7
|
|
65
|
+
Requires-Dist: bioversions>=0.5.535
|
|
66
|
+
Requires-Dist: bioregistry>=0.11.23
|
|
67
|
+
Requires-Dist: bioontologies>=0.4.0
|
|
68
|
+
Requires-Dist: zenodo-client>=0.0.5
|
|
69
|
+
Requires-Dist: class_resolver
|
|
71
70
|
Requires-Dist: psycopg2-binary
|
|
72
|
-
Requires-Dist: pydantic
|
|
73
|
-
Requires-Dist:
|
|
74
|
-
Requires-Dist:
|
|
75
|
-
Requires-Dist:
|
|
76
|
-
Requires-Dist:
|
|
71
|
+
Requires-Dist: pydantic>=2.0
|
|
72
|
+
Requires-Dist: requests-ftp
|
|
73
|
+
Requires-Dist: drugbank_downloader
|
|
74
|
+
Requires-Dist: chembl_downloader
|
|
75
|
+
Requires-Dist: umls_downloader>=0.1.3
|
|
76
|
+
Requires-Dist: typing_extensions
|
|
77
77
|
Requires-Dist: rdflib
|
|
78
|
-
Provides-Extra: docs
|
|
79
|
-
Requires-Dist: sphinx >=8 ; extra == 'docs'
|
|
80
|
-
Requires-Dist: sphinx-rtd-theme >=3.0 ; extra == 'docs'
|
|
81
|
-
Requires-Dist: sphinx-click ; extra == 'docs'
|
|
82
|
-
Requires-Dist: sphinx-automodapi ; extra == 'docs'
|
|
83
78
|
Provides-Extra: tests
|
|
84
|
-
Requires-Dist: pytest
|
|
85
|
-
Requires-Dist: coverage
|
|
79
|
+
Requires-Dist: pytest; extra == "tests"
|
|
80
|
+
Requires-Dist: coverage; extra == "tests"
|
|
81
|
+
Provides-Extra: docs
|
|
82
|
+
Requires-Dist: sphinx>=8; extra == "docs"
|
|
83
|
+
Requires-Dist: sphinx-rtd-theme>=3.0; extra == "docs"
|
|
84
|
+
Requires-Dist: sphinx-click; extra == "docs"
|
|
85
|
+
Requires-Dist: sphinx_automodapi; extra == "docs"
|
|
86
86
|
|
|
87
87
|
<!--
|
|
88
88
|
<p align="center">
|
|
@@ -12,7 +12,7 @@ pyobo/plugins.py,sha256=UyEnXxFP2q9IdYp5o7DDXPBrcExvTx4LkvhvWXx-XQc,1227
|
|
|
12
12
|
pyobo/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
13
|
pyobo/reader.py,sha256=C_-Dz0ScyFdr8DivHTYyDhIVg8SOwS_Y0DIuqKT2EJI,21292
|
|
14
14
|
pyobo/resource_utils.py,sha256=8ZQx8d-HbmPyc_WHUhqx1yjUKFZMF101FopZwZPghoE,4273
|
|
15
|
-
pyobo/version.py,sha256=
|
|
15
|
+
pyobo/version.py,sha256=5XT91psNM717pWEmUHFJc4A_TdbD4AvRx-gAxK9qm4Y,919
|
|
16
16
|
pyobo/api/__init__.py,sha256=7_uVqbZVEWrKNBYxVJb86K9-dLsGD2d2H5wjLzIP1wU,1301
|
|
17
17
|
pyobo/api/alts.py,sha256=fYA3S3odeem2-HvzeqUn0jkAFGdmbL1SYXCjIqKmRqs,2836
|
|
18
18
|
pyobo/api/hierarchy.py,sha256=-zgM4n0n0h5v5aPOhG0AR3isOt10Vtpo6EwVYN00ngI,9509
|
|
@@ -24,21 +24,6 @@ pyobo/api/species.py,sha256=Ze1yr3n9jCVQVYXmn_hw_FiziTYchddCNTW9ChDH85U,2259
|
|
|
24
24
|
pyobo/api/typedefs.py,sha256=Z4IZ5ggJe1N7lKMMrng5P8WnZo0nalsaLTMLmQT0w2Y,1130
|
|
25
25
|
pyobo/api/utils.py,sha256=zM56HjlYNPXjnhIe3oS7Yv5mAEfHHbhnf1gpJOnem1M,3274
|
|
26
26
|
pyobo/api/xrefs.py,sha256=InnBazYid5SBoRCMfE3lrBIRtdvwNi2oozjlGaX06ls,6007
|
|
27
|
-
pyobo/apps/__init__.py,sha256=iACi86TkTiGxwneGmfaudZOIEqZ45YjPXng7XjPE38Y,72
|
|
28
|
-
pyobo/apps/cli.py,sha256=gnXBAaESw1T1BvgMpTv-0P26hM2vKCAXPy0SOskgUwU,335
|
|
29
|
-
pyobo/apps/gilda/__init__.py,sha256=jpLIHJOmR_66tdXXUWFP9NiZnpQKvjv5YpCJWoAKnUI,54
|
|
30
|
-
pyobo/apps/gilda/__main__.py,sha256=9EEwzUlwcFHrfAEzveIvmqHiPu52wLt8o4Xe_vFcWf0,124
|
|
31
|
-
pyobo/apps/gilda/app.py,sha256=rHqGR52fnbhqRPWktbIZc8ZZcFEIKp6rq7ledFuN_Lg,1315
|
|
32
|
-
pyobo/apps/gilda/cli.py,sha256=OteTZy060Elmg38sl091kHfaHjjLTJaAtLdUpWgr6ug,702
|
|
33
|
-
pyobo/apps/gilda/templates/base.html,sha256=MxFNPgWW4wYzXXS3RwXMcMJAc1_lUhguQvVYQYjSjLY,888
|
|
34
|
-
pyobo/apps/gilda/templates/home.html,sha256=ZAqegzBGgVct9UzmfC0dfGJ6_jbDSCpbwqe2WB-00AA,273
|
|
35
|
-
pyobo/apps/gilda/templates/matches.html,sha256=x3mvMCevr8IoXSXmm_aOQlKNBycvMpBedLLCt2znNXQ,934
|
|
36
|
-
pyobo/apps/mapper/__init__.py,sha256=9PK1LtsCTVcQQzSPtpa6f1dgjsoeygq9cAP7AXqEiJY,56
|
|
37
|
-
pyobo/apps/mapper/__main__.py,sha256=XScQCj6oK2OslWyZ8yzcaietLJm_XxDLA22CMoyy6dM,169
|
|
38
|
-
pyobo/apps/mapper/cli.py,sha256=AHPPXqSd3LTMhHIsmhErMB_gpfDeDs6IGlPdHQKMIq0,682
|
|
39
|
-
pyobo/apps/mapper/mapper.py,sha256=yVIHGlTwFNtKEF07K-oqsqy8ggIalN6SfmyzB4E--2I,5787
|
|
40
|
-
pyobo/apps/mapper/templates/base.html,sha256=w9d8e8qKnVy_h7RT5hWV9EwghgPqn0y3xJ-tZw0v9TQ,982
|
|
41
|
-
pyobo/apps/mapper/templates/mapper_home.html,sha256=XugUb76C6B1JGQTCb2tDhZ-XyY-636qeZJODUTrpjdw,2785
|
|
42
27
|
pyobo/cli/__init__.py,sha256=pTiLuzjjpi0P69yVjQ2kE6nBUmZuYFnqdJNDZLDkgvk,71
|
|
43
28
|
pyobo/cli/aws.py,sha256=_S08OhNY-vdx-KIT4ix3Zluey9lVY0RWJhDjwcwrw2M,964
|
|
44
29
|
pyobo/cli/cli.py,sha256=gWEMOWEfjpTdCjxJm1F3Kq73FD1xoGfG9p_8r0YJ4Ro,3522
|
|
@@ -165,9 +150,8 @@ pyobo/xrefdb/sources/intact.py,sha256=l2gqxm9OLPpQqhNqAIT_jk7AHx61itsUCz-5dowwMb
|
|
|
165
150
|
pyobo/xrefdb/sources/ncit.py,sha256=QTo9BSGuurvy9M54viS6_v6dF36O8DbUGU6iiyqKsPI,3729
|
|
166
151
|
pyobo/xrefdb/sources/pubchem.py,sha256=VK_yPCaoa-CKQNkq9iAF0Zh0D_zxqa92YG4OBbvnA9c,771
|
|
167
152
|
pyobo/xrefdb/sources/wikidata.py,sha256=JSrl3YWMQA_gxw7IXJRnxWWetcAV82aM5-5J3IHFzoQ,3562
|
|
168
|
-
pyobo-0.11.
|
|
169
|
-
pyobo-0.11.
|
|
170
|
-
pyobo-0.11.
|
|
171
|
-
pyobo-0.11.
|
|
172
|
-
pyobo-0.11.
|
|
173
|
-
pyobo-0.11.1.dist-info/RECORD,,
|
|
153
|
+
pyobo-0.11.2.dist-info/METADATA,sha256=OhM135rj_cy5fzwcUBqk0Hfm4ItzYdR7DjKVt5pX8Hg,24916
|
|
154
|
+
pyobo-0.11.2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
155
|
+
pyobo-0.11.2.dist-info/entry_points.txt,sha256=YfZYzQyXBZ5dGiy4GsOUCOKKlNRNDcmR4vnlpD50q08,41
|
|
156
|
+
pyobo-0.11.2.dist-info/top_level.txt,sha256=oVdkT-pbiGoSdGSQplXFuP1KQGJNf4GdRC65jn6y9t0,6
|
|
157
|
+
pyobo-0.11.2.dist-info/RECORD,,
|
pyobo/apps/__init__.py
DELETED
pyobo/apps/cli.py
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
|
-
"""CLI for PyOBO apps."""
|
|
4
|
-
|
|
5
|
-
import click
|
|
6
|
-
|
|
7
|
-
from .gilda.cli import main as gilda_main
|
|
8
|
-
from .mapper.cli import main as mapper_main
|
|
9
|
-
|
|
10
|
-
__all__ = [
|
|
11
|
-
"main",
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@click.group(name="apps")
|
|
16
|
-
def main():
|
|
17
|
-
"""Apps."""
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
main.add_command(gilda_main)
|
|
21
|
-
main.add_command(mapper_main)
|
|
22
|
-
|
|
23
|
-
if __name__ == "__main__":
|
|
24
|
-
main()
|
pyobo/apps/gilda/__init__.py
DELETED
pyobo/apps/gilda/__main__.py
DELETED
pyobo/apps/gilda/app.py
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
|
-
"""PyOBO's Gilda Service."""
|
|
4
|
-
|
|
5
|
-
from typing import Iterable, Union
|
|
6
|
-
|
|
7
|
-
import flask
|
|
8
|
-
from flask_bootstrap import Bootstrap
|
|
9
|
-
from flask_wtf import FlaskForm
|
|
10
|
-
from wtforms.fields import StringField, SubmitField
|
|
11
|
-
from wtforms.validators import DataRequired
|
|
12
|
-
|
|
13
|
-
from pyobo.gilda_utils import get_grounder
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class Form(FlaskForm):
|
|
17
|
-
"""Form for submitting a query."""
|
|
18
|
-
|
|
19
|
-
text = StringField("Text", validators=[DataRequired()])
|
|
20
|
-
submit = SubmitField()
|
|
21
|
-
|
|
22
|
-
def make_response(self):
|
|
23
|
-
"""Make a response with the text."""
|
|
24
|
-
return flask.redirect(flask.url_for("ground", text=self.text.data))
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def get_app(prefix: Union[str, Iterable[str]]):
|
|
28
|
-
"""Make an app for grounding the text."""
|
|
29
|
-
grounder = get_grounder(prefix)
|
|
30
|
-
|
|
31
|
-
app = flask.Flask(__name__)
|
|
32
|
-
app.config["WTF_CSRF_ENABLED"] = False
|
|
33
|
-
Bootstrap(app)
|
|
34
|
-
|
|
35
|
-
@app.route("/", methods=["GET", "POST"])
|
|
36
|
-
def home():
|
|
37
|
-
"""Ground the given text."""
|
|
38
|
-
form = Form()
|
|
39
|
-
if form.validate_on_submit():
|
|
40
|
-
return form.make_response()
|
|
41
|
-
return flask.render_template("home.html", form=form)
|
|
42
|
-
|
|
43
|
-
@app.route("/ground/<text>")
|
|
44
|
-
def ground(text: str):
|
|
45
|
-
"""Ground the given text."""
|
|
46
|
-
return flask.jsonify([scored_match.to_json() for scored_match in grounder.ground(text)])
|
|
47
|
-
|
|
48
|
-
return app
|
pyobo/apps/gilda/cli.py
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
|
-
"""CLI for PyOBO's Gilda Service."""
|
|
4
|
-
|
|
5
|
-
import click
|
|
6
|
-
from more_click import (
|
|
7
|
-
host_option,
|
|
8
|
-
port_option,
|
|
9
|
-
run_app,
|
|
10
|
-
verbose_option,
|
|
11
|
-
with_gunicorn_option,
|
|
12
|
-
workers_option,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
__all__ = [
|
|
16
|
-
"main",
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@click.command(name="gilda")
|
|
21
|
-
@click.argument("prefix", nargs=-1)
|
|
22
|
-
@verbose_option
|
|
23
|
-
@host_option
|
|
24
|
-
@workers_option
|
|
25
|
-
@port_option
|
|
26
|
-
@with_gunicorn_option
|
|
27
|
-
def main(prefix: str, host: str, port: str, with_gunicorn: bool, workers: int):
|
|
28
|
-
"""Run the Gilda service for this database."""
|
|
29
|
-
from .app import get_app
|
|
30
|
-
|
|
31
|
-
app = get_app(prefix)
|
|
32
|
-
run_app(app, host=host, port=port, with_gunicorn=with_gunicorn, workers=workers)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if __name__ == "__main__":
|
|
36
|
-
main()
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
{% block head %}
|
|
5
|
-
<!-- Required meta tags -->
|
|
6
|
-
<meta charset="utf-8">
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
8
|
-
|
|
9
|
-
{% block styles %}
|
|
10
|
-
<!-- Bootstrap CSS -->
|
|
11
|
-
{{ bootstrap.load_css() }}
|
|
12
|
-
{% endblock %}
|
|
13
|
-
|
|
14
|
-
<script src="https://kit.fontawesome.com/4c86883252.js" crossorigin="anonymous"></script>
|
|
15
|
-
|
|
16
|
-
<title>{% block title %}{% endblock %}</title>
|
|
17
|
-
{% endblock %}
|
|
18
|
-
</head>
|
|
19
|
-
<body>
|
|
20
|
-
<div class="container" style="margin-top: 50px; margin-bottom: 50px">
|
|
21
|
-
<div class="row">
|
|
22
|
-
<div class="card">
|
|
23
|
-
<!-- Your page content -->
|
|
24
|
-
{% block content %}{% endblock %}
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
{% block scripts %}
|
|
29
|
-
<!-- Optional JavaScript -->
|
|
30
|
-
{{ bootstrap.load_js() }}
|
|
31
|
-
{% endblock %}
|
|
32
|
-
</body>
|
|
33
|
-
</html>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
{% extends "base.html" %}
|
|
2
|
-
|
|
3
|
-
{% block content %}
|
|
4
|
-
<h5 class="card-header">Gilda</h5>
|
|
5
|
-
<div class="card-body">
|
|
6
|
-
<p>
|
|
7
|
-
Results for <code>{{ form.text.data }}</code>
|
|
8
|
-
{% if form.context.data %} with context
|
|
9
|
-
<i>{{ form.context.data }}</i>{% endif %}
|
|
10
|
-
</p>
|
|
11
|
-
</div>
|
|
12
|
-
<table class="table table-striped table-hover">
|
|
13
|
-
<thead>
|
|
14
|
-
<tr>
|
|
15
|
-
<th>Database</th>
|
|
16
|
-
<th>Identifier</th>
|
|
17
|
-
<th>Name</th>
|
|
18
|
-
<th>Score</th>
|
|
19
|
-
</tr>
|
|
20
|
-
</thead>
|
|
21
|
-
<tbody>
|
|
22
|
-
{% for match in matches %}
|
|
23
|
-
<tr>
|
|
24
|
-
<td>{{ match['term']['db'] }}</td>
|
|
25
|
-
<td>{{ match['term']['id'] }}</td>
|
|
26
|
-
<td>{{ match['term']['entry_name'] }}</td>
|
|
27
|
-
<td class="text-right">{{ match['score'] | round(4) }}</td>
|
|
28
|
-
</tr>
|
|
29
|
-
{% endfor %}
|
|
30
|
-
</tbody>
|
|
31
|
-
</table>
|
|
32
|
-
{% endblock %}
|
pyobo/apps/mapper/__init__.py
DELETED
pyobo/apps/mapper/__main__.py
DELETED
pyobo/apps/mapper/cli.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
|
-
"""CLI for PyOBO's Mapping Service.
|
|
4
|
-
|
|
5
|
-
Run with ``python -m pyobo.apps.mapper``.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import click
|
|
9
|
-
from more_click import (
|
|
10
|
-
host_option,
|
|
11
|
-
port_option,
|
|
12
|
-
run_app,
|
|
13
|
-
verbose_option,
|
|
14
|
-
with_gunicorn_option,
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
__all__ = [
|
|
18
|
-
"main",
|
|
19
|
-
]
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@click.command(name="mapper")
|
|
23
|
-
@click.option("-x", "--mappings-file")
|
|
24
|
-
@port_option
|
|
25
|
-
@host_option
|
|
26
|
-
@with_gunicorn_option
|
|
27
|
-
@verbose_option
|
|
28
|
-
def main(mappings_file, host: str, port: str, with_gunicorn: bool):
|
|
29
|
-
"""Run the mappings app."""
|
|
30
|
-
from .mapper import get_app
|
|
31
|
-
|
|
32
|
-
app = get_app(mappings_file)
|
|
33
|
-
run_app(app=app, host=host, port=port, with_gunicorn=with_gunicorn)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if __name__ == "__main__":
|
|
37
|
-
main()
|
pyobo/apps/mapper/mapper.py
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
|
|
3
|
-
"""PyOBO's Mapping Service.
|
|
4
|
-
|
|
5
|
-
Run with ``python -m pyobo.apps.mapper``.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import logging
|
|
9
|
-
from functools import lru_cache
|
|
10
|
-
from typing import Any, Dict, Iterable, List, Mapping, Optional, Union
|
|
11
|
-
|
|
12
|
-
import bioregistry
|
|
13
|
-
import pandas as pd
|
|
14
|
-
from flasgger import Swagger
|
|
15
|
-
from flask import (
|
|
16
|
-
Blueprint,
|
|
17
|
-
Flask,
|
|
18
|
-
abort,
|
|
19
|
-
current_app,
|
|
20
|
-
jsonify,
|
|
21
|
-
render_template,
|
|
22
|
-
url_for,
|
|
23
|
-
)
|
|
24
|
-
from flask_bootstrap import VERSION_BOOTSTRAP, Bootstrap
|
|
25
|
-
from werkzeug.local import LocalProxy
|
|
26
|
-
|
|
27
|
-
from pyobo import Canonicalizer
|
|
28
|
-
from pyobo.constants import PROVENANCE, SOURCE_PREFIX, TARGET_PREFIX
|
|
29
|
-
from pyobo.identifier_utils import normalize_curie
|
|
30
|
-
from pyobo.resource_utils import ensure_inspector_javert_df
|
|
31
|
-
|
|
32
|
-
__all__ = [
|
|
33
|
-
"get_app",
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
logger = logging.getLogger(__name__)
|
|
37
|
-
|
|
38
|
-
summary_df = LocalProxy(lambda: current_app.config["summary"])
|
|
39
|
-
canonicalizer: Canonicalizer = LocalProxy(lambda: current_app.config["canonicalizer"])
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@lru_cache()
|
|
43
|
-
def _single_source_shortest_path(curie: str) -> Optional[Mapping[str, List[Mapping[str, str]]]]:
|
|
44
|
-
return canonicalizer.single_source_shortest_path(curie=curie)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@lru_cache()
|
|
48
|
-
def _all_shortest_paths(source_curie: str, target_curie: str) -> List[List[Mapping[str, str]]]:
|
|
49
|
-
return canonicalizer.all_shortest_paths(source_curie=source_curie, target_curie=target_curie)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
#: The blueprint that gets added to the app
|
|
53
|
-
search_blueprint = Blueprint("search", __name__)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
@search_blueprint.route("/")
|
|
57
|
-
def home():
|
|
58
|
-
"""Show the home page."""
|
|
59
|
-
return render_template("mapper_home.html")
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
@search_blueprint.route("/mappings/<curie>")
|
|
63
|
-
def single_source_mappings(curie: str):
|
|
64
|
-
"""Return all length xrefs from the given identifier."""
|
|
65
|
-
if curie not in canonicalizer.graph:
|
|
66
|
-
return jsonify(
|
|
67
|
-
success=False,
|
|
68
|
-
query=dict(curie=curie),
|
|
69
|
-
message="could not find curie",
|
|
70
|
-
)
|
|
71
|
-
return jsonify(_single_source_shortest_path(curie))
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
@search_blueprint.route("/mappings/<source_curie>/<target_curie>")
|
|
75
|
-
def all_mappings(source_curie: str, target_curie: str):
|
|
76
|
-
"""Return all shortest paths of xrefs between the two identifiers."""
|
|
77
|
-
if source_curie not in canonicalizer.graph:
|
|
78
|
-
return jsonify(
|
|
79
|
-
success=False,
|
|
80
|
-
query=dict(source_curie=source_curie, target_curie=target_curie),
|
|
81
|
-
message="could not find source curie",
|
|
82
|
-
)
|
|
83
|
-
if target_curie not in canonicalizer.graph:
|
|
84
|
-
return jsonify(
|
|
85
|
-
success=False,
|
|
86
|
-
query=dict(source_curie=source_curie, target_curie=target_curie),
|
|
87
|
-
message="could not find target curie",
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
return jsonify(_all_shortest_paths(source_curie, target_curie))
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
@search_blueprint.route("/mappings/summarize")
|
|
94
|
-
def summarize():
|
|
95
|
-
"""Summarize the mappings."""
|
|
96
|
-
return summary_df.to_html(index=False)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
@search_blueprint.route("/mappings/summarize_by/<prefix>")
|
|
100
|
-
def summarize_one(prefix: str):
|
|
101
|
-
"""Summarize the mappings."""
|
|
102
|
-
norm_prefix = bioregistry.normalize_prefix(prefix)
|
|
103
|
-
if norm_prefix is None:
|
|
104
|
-
return abort(500, f"invalid prefix: {prefix}")
|
|
105
|
-
in_df = summary_df.loc[summary_df[TARGET_PREFIX] == norm_prefix, [SOURCE_PREFIX, "count"]]
|
|
106
|
-
out_df = summary_df.loc[summary_df[SOURCE_PREFIX] == norm_prefix, [TARGET_PREFIX, "count"]]
|
|
107
|
-
return f"""
|
|
108
|
-
<h1>Incoming Mappings to {norm_prefix}</h1>
|
|
109
|
-
{in_df.to_html(index=False)}
|
|
110
|
-
<h1>Outgoing Mappings from {norm_prefix}</h1>
|
|
111
|
-
{out_df.to_html(index=False)}
|
|
112
|
-
"""
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
@search_blueprint.route("/canonicalize/<curie>")
|
|
116
|
-
def canonicalize(curie: str):
|
|
117
|
-
"""Return the best CURIE."""
|
|
118
|
-
# TODO maybe normalize the curie first?
|
|
119
|
-
norm_prefix, norm_identifier = normalize_curie(curie)
|
|
120
|
-
if norm_prefix is None or norm_identifier is None:
|
|
121
|
-
return jsonify(
|
|
122
|
-
query=curie,
|
|
123
|
-
normalizable=False,
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
norm_curie = f"{norm_prefix}:{norm_identifier}"
|
|
127
|
-
|
|
128
|
-
rv: Dict[str, Any] = dict(query=curie)
|
|
129
|
-
if norm_curie != curie:
|
|
130
|
-
rv["norm_curie"] = norm_curie
|
|
131
|
-
|
|
132
|
-
if norm_curie not in canonicalizer.graph:
|
|
133
|
-
rv["found"] = False
|
|
134
|
-
else:
|
|
135
|
-
result_curie = canonicalizer.canonicalize(norm_curie)
|
|
136
|
-
rv.update(
|
|
137
|
-
found=True,
|
|
138
|
-
result=result_curie,
|
|
139
|
-
mappings=url_for(
|
|
140
|
-
f".{all_mappings.__name__}",
|
|
141
|
-
source_curie=norm_curie,
|
|
142
|
-
target_curie=result_curie,
|
|
143
|
-
),
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
return jsonify(rv)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
def get_app(paths: Union[None, str, Iterable[str]] = None) -> Flask:
|
|
150
|
-
"""Build the Flask app."""
|
|
151
|
-
app = Flask(__name__)
|
|
152
|
-
Swagger(app)
|
|
153
|
-
|
|
154
|
-
logger.info("using bootstrap_flask %s", VERSION_BOOTSTRAP)
|
|
155
|
-
Bootstrap(app)
|
|
156
|
-
|
|
157
|
-
if paths is None:
|
|
158
|
-
df = ensure_inspector_javert_df()
|
|
159
|
-
elif isinstance(paths, str):
|
|
160
|
-
df = pd.read_csv(paths, sep="\t", dtype=str)
|
|
161
|
-
else:
|
|
162
|
-
df = pd.concat(pd.read_csv(path, sep="\t", dtype=str) for path in paths)
|
|
163
|
-
|
|
164
|
-
app.config["summary"] = summarize_xref_df(df)
|
|
165
|
-
app.config["summary_provenances"] = summarize_xref_provenances_df(df)
|
|
166
|
-
# TODO allow for specification of priorities in the canonicalizer
|
|
167
|
-
app.config["canonicalizer"] = Canonicalizer.from_df(df)
|
|
168
|
-
app.register_blueprint(search_blueprint)
|
|
169
|
-
return app
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
def summarize_xref_df(df: pd.DataFrame) -> pd.DataFrame:
|
|
173
|
-
"""Get all meta-mappings."""
|
|
174
|
-
return _summarize(df, [SOURCE_PREFIX, TARGET_PREFIX])
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def summarize_xref_provenances_df(df: pd.DataFrame) -> pd.DataFrame:
|
|
178
|
-
"""Get all meta-mappings."""
|
|
179
|
-
return _summarize(df, [SOURCE_PREFIX, TARGET_PREFIX, PROVENANCE])
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
def _summarize(df: pd.DataFrame, columns) -> pd.DataFrame:
|
|
183
|
-
"""Get all meta-mappings."""
|
|
184
|
-
rv = df[columns].groupby(columns).size().reset_index()
|
|
185
|
-
rv.columns = [*columns, "count"]
|
|
186
|
-
rv.sort_values("count", inplace=True, ascending=False)
|
|
187
|
-
return rv
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
{% block head %}
|
|
5
|
-
<!-- Required meta tags -->
|
|
6
|
-
<meta charset="utf-8">
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
8
|
-
|
|
9
|
-
{% block styles %}
|
|
10
|
-
<!-- Bootstrap CSS -->
|
|
11
|
-
{{ bootstrap.load_css() }}
|
|
12
|
-
{% endblock %}
|
|
13
|
-
|
|
14
|
-
<script src="https://kit.fontawesome.com/4c86883252.js" crossorigin="anonymous"></script>
|
|
15
|
-
|
|
16
|
-
<title>{% block title %}{% endblock %}</title>
|
|
17
|
-
{% endblock %}
|
|
18
|
-
</head>
|
|
19
|
-
<body>
|
|
20
|
-
<div class="container" style="margin-top: 25px; margin-bottom: 25px">
|
|
21
|
-
<div class="row justify-content-center">
|
|
22
|
-
<div class="col-md-8 col-lg-8">
|
|
23
|
-
<div class="card">
|
|
24
|
-
<!-- Your page content -->
|
|
25
|
-
{% block content %}{% endblock %}
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
{% block scripts %}
|
|
31
|
-
<!-- Optional JavaScript -->
|
|
32
|
-
{{ bootstrap.load_js() }}
|
|
33
|
-
{% endblock %}
|
|
34
|
-
</body>
|
|
35
|
-
</html>
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
{% extends "base.html" %}
|
|
2
|
-
|
|
3
|
-
{% block content %}
|
|
4
|
-
<h5 class="card-header">Inspector Javert's Mapper</h5>
|
|
5
|
-
<div class="card-body">
|
|
6
|
-
<p class="card-text">
|
|
7
|
-
This service resolves <a href="https://en.wikipedia.org/wiki/CURIE">CURIEs</a>
|
|
8
|
-
to the best CURIE that's mapped to it.
|
|
9
|
-
</p>
|
|
10
|
-
<p>
|
|
11
|
-
A summary of all of the xrefs can be found <a href="{{ url_for('.summarize') }}">here</a>.
|
|
12
|
-
You can also look at a summary for a specific prefix like <a
|
|
13
|
-
href="{{ url_for('.summarize_one', prefix='umls') }}"><code>UMLS</code></a>.
|
|
14
|
-
</p>
|
|
15
|
-
<ul>
|
|
16
|
-
<li>
|
|
17
|
-
Use the <code>/mappings</code> endpoint to look up equivalent entities,
|
|
18
|
-
for example, <a
|
|
19
|
-
href="{{ url_for('.single_source_mappings', curie='hgnc:6893') }}"><code>hgnc:6893</code></a>.
|
|
20
|
-
</li>
|
|
21
|
-
<li>
|
|
22
|
-
Use the <code>/mappings</code> endpoint to look up all mappings between two entities,
|
|
23
|
-
for example, <a
|
|
24
|
-
href="{{ url_for('.all_mappings', source_curie='hgnc:6893', target_curie='ensembl:ENSG00000186868') }}"><code>hgnc:6893</code>
|
|
25
|
-
and <code>ensembl:ENSG00000186868</code></a>.
|
|
26
|
-
</li>
|
|
27
|
-
</ul>
|
|
28
|
-
</div>
|
|
29
|
-
<table class="table">
|
|
30
|
-
<thead>
|
|
31
|
-
<tr>
|
|
32
|
-
<th scope="col">CURIE</th>
|
|
33
|
-
<th scope="col">Description</th>
|
|
34
|
-
</tr>
|
|
35
|
-
</thead>
|
|
36
|
-
<tr>
|
|
37
|
-
<td><a href="{{ url_for('.canonicalize', curie='hgnc:6893') }}">hgnc:6893</a></td>
|
|
38
|
-
<td>✅ maps correct identifier to higher priority namespace (ncbigene)</td>
|
|
39
|
-
</tr>
|
|
40
|
-
<tr>
|
|
41
|
-
<td><a href="{{ url_for('.canonicalize', curie='ncbigene:4137') }}">ncbigene:4137</a></td>
|
|
42
|
-
<td>✅ already priority namespace</td>
|
|
43
|
-
</tr>
|
|
44
|
-
<tr>
|
|
45
|
-
<td><a href="{{ url_for('.canonicalize', curie='DOID:00000') }}">DOID:00000</a></td>
|
|
46
|
-
<td>❌ invalid identifier</td>
|
|
47
|
-
</tr>
|
|
48
|
-
<tr>
|
|
49
|
-
<td><a href="{{ url_for('.canonicalize', curie='NNN:00000') }}">NNN:00000</a></td>
|
|
50
|
-
<td>❌ invalid prefix</td>
|
|
51
|
-
</tr>
|
|
52
|
-
<tr>
|
|
53
|
-
<td><a href="{{ url_for('.canonicalize', curie='wikidata:Q42') }}">wikidata:Q42</a></td>
|
|
54
|
-
<td>❌ unmapped prefix</td>
|
|
55
|
-
</tr>
|
|
56
|
-
</table>
|
|
57
|
-
<div class="card-footer text-center">
|
|
58
|
-
Developed with ❤️ in 🇩🇪 by <a href="https://github.com/cthoyt">@cthoyt</a>.
|
|
59
|
-
|
|
60
|
-
(<span class="text-muted"><a href="https://github.com/pyobo/pyobo">source code</a></span> |
|
|
61
|
-
<span class="text-muted"><a
|
|
62
|
-
href="https://cthoyt.com/2020/04/19/inspector-javerts-xref-database.html">blog post</a></span>)
|
|
63
|
-
</div>
|
|
64
|
-
{% endblock %}
|
pyobo-0.11.1.dist-info/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 Charles Tapley Hoyt
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
File without changes
|
|
File without changes
|