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 CHANGED
@@ -12,7 +12,7 @@ __all__ = [
12
12
  "get_git_hash",
13
13
  ]
14
14
 
15
- VERSION = "0.11.1"
15
+ VERSION = "0.11.2"
16
16
 
17
17
 
18
18
  def get_git_hash() -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyobo
3
- Version: 0.11.1
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
- License-File: LICENSE
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: more-itertools
61
- Requires-Dist: more-click >=0.0.2
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 >=0.2.7
66
- Requires-Dist: bioversions >=0.5.535
67
- Requires-Dist: bioregistry >=0.11.23
68
- Requires-Dist: bioontologies >=0.4.0
69
- Requires-Dist: zenodo-client >=0.0.5
70
- Requires-Dist: class-resolver
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 >=2.0
73
- Requires-Dist: drugbank-downloader
74
- Requires-Dist: chembl-downloader
75
- Requires-Dist: umls-downloader >=0.1.3
76
- Requires-Dist: typing-extensions
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 ; extra == 'tests'
85
- Requires-Dist: coverage ; extra == 'tests'
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=QvIJIOoOcrMgtVzkvER3psDs709LKt9w5I-rKlbzVcI,919
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.1.dist-info/LICENSE,sha256=QcgJZKGxlW5BwBNnCBL8VZLVtRvXs81Ch9lJRQSIpJg,1076
169
- pyobo-0.11.1.dist-info/METADATA,sha256=llPe8alNZWukCFjhvVKIEL6s2Vri9vfaSWRZE2DxMQg,24927
170
- pyobo-0.11.1.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
171
- pyobo-0.11.1.dist-info/entry_points.txt,sha256=YfZYzQyXBZ5dGiy4GsOUCOKKlNRNDcmR4vnlpD50q08,41
172
- pyobo-0.11.1.dist-info/top_level.txt,sha256=oVdkT-pbiGoSdGSQplXFuP1KQGJNf4GdRC65jn6y9t0,6
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
pyobo/apps/__init__.py DELETED
@@ -1,3 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- """A collection of web apps built on PyOBO."""
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()
@@ -1,3 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- """PyOBO's Gilda Service."""
@@ -1,8 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- """CLI for PyOBO's Gilda Service."""
4
-
5
- from .cli import main
6
-
7
- if __name__ == "__main__":
8
- main()
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,11 +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
- This is the Gilda grounding service.
8
- </p>
9
- {{ wtf.quick_form(form, form_type='horizontal') }}
10
- </div>
11
- {% endblock %}
@@ -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 %}
@@ -1,3 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- """PyOBO's Mapping Service."""
@@ -1,11 +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
- from .cli import main
9
-
10
- if __name__ == "__main__":
11
- main()
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()
@@ -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 %}
@@ -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.