genelastic 0.6.1__tar.gz → 0.7.0__tar.gz
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.
- genelastic-0.7.0/PKG-INFO +105 -0
- genelastic-0.7.0/README.md +60 -0
- genelastic-0.7.0/pyproject.toml +114 -0
- genelastic-0.7.0/src/genelastic/api/extends/example.py +6 -0
- genelastic-0.7.0/src/genelastic/api/routes.py +221 -0
- genelastic-0.7.0/src/genelastic/api/server.py +80 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/api/settings.py +3 -2
- genelastic-0.7.0/src/genelastic/common/__init__.py +39 -0
- genelastic-0.7.0/src/genelastic/common/cli.py +63 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/common/elastic.py +80 -49
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/common/exceptions.py +0 -2
- genelastic-0.7.0/src/genelastic/common/types.py +25 -0
- genelastic-0.7.0/src/genelastic/import_data/__init__.py +27 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/analyses.py +17 -20
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/analysis.py +69 -65
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/bi_process.py +7 -5
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/bi_processes.py +8 -8
- genelastic-0.7.0/src/genelastic/import_data/cli_gen_data.py +116 -0
- genelastic-0.7.0/src/genelastic/import_data/cli_import.py +379 -0
- genelastic-0.6.1/src/genelastic/import_data/info.py → genelastic-0.7.0/src/genelastic/import_data/cli_info.py +104 -75
- genelastic-0.7.0/src/genelastic/import_data/cli_integrity.py +384 -0
- genelastic-0.7.0/src/genelastic/import_data/cli_validate.py +54 -0
- genelastic-0.7.0/src/genelastic/import_data/constants.py +24 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/data_file.py +23 -20
- genelastic-0.7.0/src/genelastic/import_data/filename_pattern.py +57 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/import_bundle.py +56 -47
- genelastic-0.7.0/src/genelastic/import_data/import_bundle_factory.py +298 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/logger.py +22 -18
- genelastic-0.7.0/src/genelastic/import_data/random_bundle.py +402 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/tags.py +46 -26
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/wet_process.py +8 -4
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/import_data/wet_processes.py +13 -8
- genelastic-0.7.0/src/genelastic/ui/__init__.py +0 -0
- genelastic-0.7.0/src/genelastic/ui/server.py +87 -0
- genelastic-0.7.0/src/genelastic/ui/settings.py +11 -0
- genelastic-0.7.0/src/genelastic.egg-info/PKG-INFO +105 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic.egg-info/SOURCES.txt +11 -6
- genelastic-0.7.0/src/genelastic.egg-info/entry_points.txt +6 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic.egg-info/requires.txt +11 -3
- genelastic-0.7.0/tests/test_010_analyses.py +14 -0
- genelastic-0.7.0/tests/test_100_import_bundle_format.py +701 -0
- genelastic-0.7.0/tests/test_200_cli_gen_data.py +232 -0
- genelastic-0.6.1/PKG-INFO +0 -41
- genelastic-0.6.1/README.md +0 -3
- genelastic-0.6.1/pyproject.toml +0 -60
- genelastic-0.6.1/src/genelastic/api/extends/example.py +0 -7
- genelastic-0.6.1/src/genelastic/api/routes.py +0 -84
- genelastic-0.6.1/src/genelastic/api/server.py +0 -72
- genelastic-0.6.1/src/genelastic/common/__init__.py +0 -12
- genelastic-0.6.1/src/genelastic/common/cli.py +0 -35
- genelastic-0.6.1/src/genelastic/common/types.py +0 -20
- genelastic-0.6.1/src/genelastic/import_data/__init__.py +0 -9
- genelastic-0.6.1/src/genelastic/import_data/constants.py +0 -45
- genelastic-0.6.1/src/genelastic/import_data/filename_pattern.py +0 -63
- genelastic-0.6.1/src/genelastic/import_data/gen_data.py +0 -194
- genelastic-0.6.1/src/genelastic/import_data/import_bundle_factory.py +0 -290
- genelastic-0.6.1/src/genelastic/import_data/import_data.py +0 -292
- genelastic-0.6.1/src/genelastic/import_data/integrity.py +0 -290
- genelastic-0.6.1/src/genelastic/import_data/validate_data.py +0 -43
- genelastic-0.6.1/src/genelastic.egg-info/PKG-INFO +0 -41
- genelastic-0.6.1/src/genelastic.egg-info/entry_points.txt +0 -6
- genelastic-0.6.1/tests/test_010_analyses.py +0 -16
- genelastic-0.6.1/tests/test_100_import_bundle_format.py +0 -598
- {genelastic-0.6.1 → genelastic-0.7.0}/setup.cfg +0 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/__init__.py +0 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/api/__init__.py +0 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic/api/extends/__init__.py +0 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic.egg-info/dependency_links.txt +0 -0
- {genelastic-0.6.1 → genelastic-0.7.0}/src/genelastic.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: genelastic
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Generate and store genetic data into an Elasticsearch database.
|
|
5
|
+
Author: CNRGH
|
|
6
|
+
Author-email: Pierrick ROGER <pierrick.roger@cnrgh.fr>, Maxime BLANCHON <maxime.blanchon@cnrgh.fr>
|
|
7
|
+
License: CeCILL
|
|
8
|
+
Keywords: CNRGH,genelastic,generation,storage,elasticsearch,database
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: License :: OSI Approved :: CEA CNRS Inria Logiciel Libre License, version 2.1 (CeCILL-2.1)
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Requires-Dist: elasticsearch
|
|
16
|
+
Requires-Dist: PyVCF3
|
|
17
|
+
Requires-Dist: schema
|
|
18
|
+
Requires-Dist: PyYAML
|
|
19
|
+
Requires-Dist: biophony>=1.2.1
|
|
20
|
+
Requires-Dist: colorlog
|
|
21
|
+
Provides-Extra: tests
|
|
22
|
+
Requires-Dist: pytest; extra == "tests"
|
|
23
|
+
Requires-Dist: mypy; extra == "tests"
|
|
24
|
+
Requires-Dist: coverage; extra == "tests"
|
|
25
|
+
Requires-Dist: yamllint; extra == "tests"
|
|
26
|
+
Requires-Dist: types-PyYAML; extra == "tests"
|
|
27
|
+
Requires-Dist: ruff<0.9,>=0.8.1; extra == "tests"
|
|
28
|
+
Requires-Dist: pre-commit<4.1,>=4.0.1; extra == "tests"
|
|
29
|
+
Requires-Dist: types-requests; extra == "tests"
|
|
30
|
+
Requires-Dist: ansible<10.5,>=10.4.0; extra == "tests"
|
|
31
|
+
Requires-Dist: ansible-lint<25,>=24.12.2; extra == "tests"
|
|
32
|
+
Provides-Extra: docs
|
|
33
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
34
|
+
Requires-Dist: sphinx-autoapi; extra == "docs"
|
|
35
|
+
Requires-Dist: furo; extra == "docs"
|
|
36
|
+
Provides-Extra: api
|
|
37
|
+
Requires-Dist: flask; extra == "api"
|
|
38
|
+
Requires-Dist: elasticsearch; extra == "api"
|
|
39
|
+
Requires-Dist: environs; extra == "api"
|
|
40
|
+
Requires-Dist: connexion[flask,swagger-ui,uvicorn]; extra == "api"
|
|
41
|
+
Provides-Extra: ui
|
|
42
|
+
Requires-Dist: flask; extra == "ui"
|
|
43
|
+
Requires-Dist: requests; extra == "ui"
|
|
44
|
+
Requires-Dist: environs; extra == "ui"
|
|
45
|
+
|
|
46
|
+
# genelastic
|
|
47
|
+
|
|
48
|
+
Storing of genetics data into an Elasticsearch database.
|
|
49
|
+
|
|
50
|
+
## Prerequisites
|
|
51
|
+
|
|
52
|
+
- `python` >= 3.11
|
|
53
|
+
- `make`
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
To install dependencies, run the following command:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
python -m venv .venv
|
|
61
|
+
source .venv/bin/activate
|
|
62
|
+
make install.deps
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Configuration
|
|
66
|
+
|
|
67
|
+
To start the **API server**, the following environment variables should be defined:
|
|
68
|
+
|
|
69
|
+
- `GENAPI_ES_URL`: URL of the Elasticsearch server,
|
|
70
|
+
- `GENAPI_ES_ENCODED_API_KEY`: Encoded API key,
|
|
71
|
+
- `GENAPI_ES_INDEX_PREFIX`: Prefix to identify indices of interest,
|
|
72
|
+
- `GENAPI_ES_CERT_FP`: Certificate fingerprint of the Elasticsearch server.
|
|
73
|
+
|
|
74
|
+
Then, run the following command:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
make start-api
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
To start the **UI server**, the following environment variables should be defined:
|
|
81
|
+
|
|
82
|
+
- `GENUI_API_URL`: URL of the API server.
|
|
83
|
+
|
|
84
|
+
Then, run the following command:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
make start-ui
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Developers
|
|
91
|
+
|
|
92
|
+
This project uses [pre-commit](https://pre-commit.com/) to manage Git hooks scripts. To install project hooks, run:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pre-commit install
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
After that, each commit will succeed only if all hooks (defined in `.pre-commit-config.yaml`) pass.
|
|
99
|
+
|
|
100
|
+
If necessary (though not recommended),
|
|
101
|
+
you can skip these hooks by using the `--no-verify` / `-n` option when committing:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
git commit -m "My commit message" --no-verify # This commit will not run installed hooks.
|
|
105
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# genelastic
|
|
2
|
+
|
|
3
|
+
Storing of genetics data into an Elasticsearch database.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- `python` >= 3.11
|
|
8
|
+
- `make`
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
To install dependencies, run the following command:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
python -m venv .venv
|
|
16
|
+
source .venv/bin/activate
|
|
17
|
+
make install.deps
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
To start the **API server**, the following environment variables should be defined:
|
|
23
|
+
|
|
24
|
+
- `GENAPI_ES_URL`: URL of the Elasticsearch server,
|
|
25
|
+
- `GENAPI_ES_ENCODED_API_KEY`: Encoded API key,
|
|
26
|
+
- `GENAPI_ES_INDEX_PREFIX`: Prefix to identify indices of interest,
|
|
27
|
+
- `GENAPI_ES_CERT_FP`: Certificate fingerprint of the Elasticsearch server.
|
|
28
|
+
|
|
29
|
+
Then, run the following command:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
make start-api
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
To start the **UI server**, the following environment variables should be defined:
|
|
36
|
+
|
|
37
|
+
- `GENUI_API_URL`: URL of the API server.
|
|
38
|
+
|
|
39
|
+
Then, run the following command:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
make start-ui
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Developers
|
|
46
|
+
|
|
47
|
+
This project uses [pre-commit](https://pre-commit.com/) to manage Git hooks scripts. To install project hooks, run:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pre-commit install
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
After that, each commit will succeed only if all hooks (defined in `.pre-commit-config.yaml`) pass.
|
|
54
|
+
|
|
55
|
+
If necessary (though not recommended),
|
|
56
|
+
you can skip these hooks by using the `--no-verify` / `-n` option when committing:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git commit -m "My commit message" --no-verify # This commit will not run installed hooks.
|
|
60
|
+
```
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools >= 70.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "genelastic"
|
|
7
|
+
version = "0.7.0"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"elasticsearch",
|
|
10
|
+
"PyVCF3",
|
|
11
|
+
"schema",
|
|
12
|
+
"PyYAML",
|
|
13
|
+
"biophony>=1.2.1",
|
|
14
|
+
"colorlog",
|
|
15
|
+
]
|
|
16
|
+
requires-python = ">= 3.11"
|
|
17
|
+
authors = [
|
|
18
|
+
{ name = "CNRGH" },
|
|
19
|
+
{ name = "Pierrick ROGER", email = "pierrick.roger@cnrgh.fr" },
|
|
20
|
+
{ name = "Maxime BLANCHON", email = "maxime.blanchon@cnrgh.fr" }]
|
|
21
|
+
description = "Generate and store genetic data into an Elasticsearch database."
|
|
22
|
+
readme = "README.md"
|
|
23
|
+
license = { text = "CeCILL" }
|
|
24
|
+
keywords = ["CNRGH", "genelastic", "generation", "storage", "elasticsearch", "database"]
|
|
25
|
+
classifiers = [
|
|
26
|
+
"Development Status :: 3 - Alpha",
|
|
27
|
+
"Intended Audience :: Science/Research",
|
|
28
|
+
"License :: OSI Approved :: CEA CNRS Inria Logiciel Libre License, version 2.1 (CeCILL-2.1)",
|
|
29
|
+
"Programming Language :: Python :: 3.11"
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
tests = [
|
|
34
|
+
"pytest",
|
|
35
|
+
"mypy",
|
|
36
|
+
"coverage",
|
|
37
|
+
"yamllint",
|
|
38
|
+
"types-PyYAML",
|
|
39
|
+
"ruff >= 0.8.1, < 0.9",
|
|
40
|
+
"pre-commit >= 4.0.1, < 4.1",
|
|
41
|
+
"types-requests",
|
|
42
|
+
"ansible >= 10.4.0, < 10.5",
|
|
43
|
+
"ansible-lint >= 24.12.2, < 25"
|
|
44
|
+
]
|
|
45
|
+
docs = [
|
|
46
|
+
"sphinx",
|
|
47
|
+
"sphinx-autoapi",
|
|
48
|
+
"furo"
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
api = [
|
|
52
|
+
"flask",
|
|
53
|
+
"elasticsearch",
|
|
54
|
+
"environs",
|
|
55
|
+
"connexion[flask,swagger-ui,uvicorn]"
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
ui = [
|
|
59
|
+
"flask",
|
|
60
|
+
"requests",
|
|
61
|
+
"environs"
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[project.scripts]
|
|
65
|
+
gnl-data = "genelastic.import_data.cli_gen_data:main"
|
|
66
|
+
gnl-import = "genelastic.import_data.cli_import:main"
|
|
67
|
+
gnl-info = "genelastic.import_data.cli_info:main"
|
|
68
|
+
gnl-integrity = "genelastic.import_data.cli_integrity:main"
|
|
69
|
+
gnl-validate = "genelastic.import_data.cli_validate:main"
|
|
70
|
+
|
|
71
|
+
[tool.ruff]
|
|
72
|
+
line-length = 80
|
|
73
|
+
target-version = "py311"
|
|
74
|
+
|
|
75
|
+
[tool.ruff.lint]
|
|
76
|
+
ignore = [
|
|
77
|
+
"E501",
|
|
78
|
+
"D100",
|
|
79
|
+
"D103",
|
|
80
|
+
"D104",
|
|
81
|
+
"D105",
|
|
82
|
+
"D107",
|
|
83
|
+
"D205",
|
|
84
|
+
"D415",
|
|
85
|
+
"TRY400",
|
|
86
|
+
"S311", # Disable rule 'Standard pseudo-random generators are not suitable for cryptographic purposes'.
|
|
87
|
+
# Bellow are rules disabled as they conflict with 'ruff format'.
|
|
88
|
+
# https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
|
89
|
+
"W191",
|
|
90
|
+
"E111",
|
|
91
|
+
"E114",
|
|
92
|
+
"E117",
|
|
93
|
+
"D206",
|
|
94
|
+
"D300",
|
|
95
|
+
"Q000",
|
|
96
|
+
"Q001",
|
|
97
|
+
"Q002",
|
|
98
|
+
"Q003",
|
|
99
|
+
"COM812",
|
|
100
|
+
"COM819",
|
|
101
|
+
"ISC001",
|
|
102
|
+
"ISC002",
|
|
103
|
+
]
|
|
104
|
+
select = ["ALL"]
|
|
105
|
+
|
|
106
|
+
[tool.ruff.lint.per-file-ignores]
|
|
107
|
+
"tests/*" = [
|
|
108
|
+
"S101", # Disable "Use of assert detected" rule.
|
|
109
|
+
"PLR2004", # Disable "Magic value used in comparison" rule.
|
|
110
|
+
"SLF001" # Disable "Private member accessed" rule.
|
|
111
|
+
]
|
|
112
|
+
|
|
113
|
+
[tool.ruff.lint.pydocstyle]
|
|
114
|
+
convention = "google"
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
from importlib.metadata import version
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from flask import Response, current_app, jsonify
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def ping() -> Response:
|
|
9
|
+
"""Test route to verify that the server is online."""
|
|
10
|
+
return jsonify({"message": "pong"})
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def list_indices() -> Response:
|
|
14
|
+
"""Route to list Elasticsearch indexes."""
|
|
15
|
+
return current_app.elastic_query_conn.get_indices() # type: ignore[attr-defined, no-any-return]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def retrieve_document(index_id: str, document_id: str) -> Response:
|
|
19
|
+
"""Route to retrieve a document by its ID."""
|
|
20
|
+
document = current_app.elastic_query_conn.get_document_by_id( # type: ignore[attr-defined]
|
|
21
|
+
index_id, document_id
|
|
22
|
+
)
|
|
23
|
+
return jsonify(document)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def list_wet_processes() -> Response:
|
|
27
|
+
"""Route to list wet processes."""
|
|
28
|
+
wet_processes_index = (
|
|
29
|
+
f"{current_app.config['GENAPI_ES_INDEX_PREFIX']}-wet_processes"
|
|
30
|
+
)
|
|
31
|
+
result = current_app.elastic_query_conn.get_field_values( # type: ignore[attr-defined]
|
|
32
|
+
wet_processes_index, "proc_id"
|
|
33
|
+
)
|
|
34
|
+
return jsonify(list(result))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def list_bi_processes() -> Response:
|
|
38
|
+
"""Route to list bi processes."""
|
|
39
|
+
bi_processes_index = (
|
|
40
|
+
f"{current_app.config['GENAPI_ES_INDEX_PREFIX']}-bi_processes"
|
|
41
|
+
)
|
|
42
|
+
result = current_app.elastic_query_conn.get_field_values( # type: ignore[attr-defined]
|
|
43
|
+
bi_processes_index, "proc_id"
|
|
44
|
+
)
|
|
45
|
+
return jsonify(list(result))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def list_analyses() -> Response:
|
|
49
|
+
"""Route to list analyses."""
|
|
50
|
+
analyses_index = f"{current_app.config['GENAPI_ES_INDEX_PREFIX']}-analyses"
|
|
51
|
+
result = current_app.elastic_query_conn.get_field_values( # type: ignore[attr-defined]
|
|
52
|
+
analyses_index, "path"
|
|
53
|
+
)
|
|
54
|
+
filenames = [Path(path).name for path in result]
|
|
55
|
+
return jsonify(filenames)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def list_analyses_wet_processes(proc_id: str) -> Response:
|
|
59
|
+
"""Route to list analyses one of specific wet process"""
|
|
60
|
+
analyses_index = f"{current_app.config['GENAPI_ES_INDEX_PREFIX']}-analyses"
|
|
61
|
+
|
|
62
|
+
search_query = {
|
|
63
|
+
"query": {
|
|
64
|
+
"term": {
|
|
65
|
+
"metadata.wet_process.keyword": proc_id,
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
response = current_app.elastic_query_conn.client.search( # type: ignore[attr-defined]
|
|
70
|
+
index=analyses_index, body=search_query
|
|
71
|
+
)
|
|
72
|
+
result = [hit["_source"]["path"] for hit in response["hits"]["hits"]]
|
|
73
|
+
|
|
74
|
+
return jsonify(result)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def list_analyses_bi_processes(proc_id: str) -> Response:
|
|
78
|
+
"""Route to list analyses one of specific bi process"""
|
|
79
|
+
analyses_index = f"{current_app.config['GENAPI_ES_INDEX_PREFIX']}-analyses"
|
|
80
|
+
|
|
81
|
+
search_query = {
|
|
82
|
+
"query": {
|
|
83
|
+
"term": {
|
|
84
|
+
"metadata.bi_process.keyword": proc_id,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
response = current_app.elastic_query_conn.client.search( # type: ignore[attr-defined]
|
|
89
|
+
index=analyses_index, body=search_query
|
|
90
|
+
)
|
|
91
|
+
result = [hit["_source"]["path"] for hit in response["hits"]["hits"]]
|
|
92
|
+
|
|
93
|
+
return jsonify(result)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def list_snv_documents() -> Response:
|
|
97
|
+
"""Route to list all documents containing a mutation at a single position (SNV)."""
|
|
98
|
+
index_pattern = "genelastic-file-*"
|
|
99
|
+
target_value = "SNV"
|
|
100
|
+
|
|
101
|
+
search_query = {
|
|
102
|
+
"aggs": {
|
|
103
|
+
"snv_docs": {
|
|
104
|
+
"composite": {
|
|
105
|
+
"sources": [
|
|
106
|
+
{"alt_value": {"terms": {"field": "alt.keyword"}}}
|
|
107
|
+
],
|
|
108
|
+
"size": 1000,
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"query": {"term": {"alt.keyword": target_value}},
|
|
113
|
+
"size": 0,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
all_documents = []
|
|
117
|
+
buckets = current_app.elastic_query_conn.run_composite_aggregation( # type: ignore[attr-defined]
|
|
118
|
+
index_pattern, search_query
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
for bucket in buckets:
|
|
122
|
+
alt_value = bucket["key"]["alt_value"]
|
|
123
|
+
|
|
124
|
+
search_query_docs = {
|
|
125
|
+
"query": {"term": {"alt.keyword": alt_value}},
|
|
126
|
+
"size": 1000,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
response = current_app.elastic_query_conn.client.search( # type: ignore[attr-defined]
|
|
130
|
+
index=index_pattern, body=search_query_docs
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
all_documents.extend(response["hits"]["hits"])
|
|
134
|
+
|
|
135
|
+
return jsonify(all_documents)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def build_snv_search_query(
|
|
139
|
+
target_alt: str, target_svtype: str
|
|
140
|
+
) -> dict[str, Any]:
|
|
141
|
+
"""Helper function to build the search query for SNV documents with specified alt and SVTYPE."""
|
|
142
|
+
return {
|
|
143
|
+
"query": {
|
|
144
|
+
"bool": {
|
|
145
|
+
"must": [
|
|
146
|
+
{"term": {"alt.keyword": target_alt}},
|
|
147
|
+
{"term": {"info.SVTYPE.keyword": target_svtype}},
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"size": 1000,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def build_snv_mutation_search_query(
|
|
156
|
+
target_svtypes: list[str],
|
|
157
|
+
) -> dict[str, Any]:
|
|
158
|
+
"""Helper function to build the search query for SNV mutations with specified SVTYPE values."""
|
|
159
|
+
return {
|
|
160
|
+
"query": {
|
|
161
|
+
"bool": {
|
|
162
|
+
"must": [
|
|
163
|
+
{"term": {"alt.keyword": "SNV"}},
|
|
164
|
+
{"terms": {"info.SVTYPE.keyword": target_svtypes}},
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"size": 1000,
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def list_snv_insertion_documents() -> Response:
|
|
173
|
+
"""Route to list all documents containing an insertion (INS) at a single position (SNV)."""
|
|
174
|
+
index_pattern = "genelastic-file-*"
|
|
175
|
+
search_query = build_snv_search_query(target_alt="SNV", target_svtype="INS")
|
|
176
|
+
|
|
177
|
+
response = current_app.elastic_query_conn.client.search( # type: ignore[attr-defined]
|
|
178
|
+
index=index_pattern, body=search_query
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
all_documents = [hit["_source"] for hit in response["hits"]["hits"]]
|
|
182
|
+
|
|
183
|
+
return jsonify(all_documents)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def list_snv_deletion_documents() -> Response:
|
|
187
|
+
"""Route to list all documents containing a deletion (DEL) at a single position (SNV)."""
|
|
188
|
+
index_pattern = "genelastic-file-*"
|
|
189
|
+
search_query = build_snv_search_query(target_alt="SNV", target_svtype="DEL")
|
|
190
|
+
|
|
191
|
+
response = current_app.elastic_query_conn.client.search( # type: ignore[attr-defined]
|
|
192
|
+
index=index_pattern, body=search_query
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
all_documents = [hit["_source"] for hit in response["hits"]["hits"]]
|
|
196
|
+
|
|
197
|
+
return jsonify(all_documents)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def list_snv_mutation_documents() -> Response:
|
|
201
|
+
"""Route to list all documents containing a mutation at a single position (SNV)."""
|
|
202
|
+
index_pattern = "genelastic-file-*"
|
|
203
|
+
target_svtypes = ["INS", "DEL"]
|
|
204
|
+
|
|
205
|
+
search_query = build_snv_mutation_search_query(
|
|
206
|
+
target_svtypes=target_svtypes
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
response = current_app.elastic_query_conn.client.search( # type: ignore[attr-defined]
|
|
210
|
+
index=index_pattern, body=search_query
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
all_documents = [hit["_source"] for hit in response["hits"]["hits"]]
|
|
214
|
+
|
|
215
|
+
return jsonify(all_documents)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def get_genelastic_version() -> Response:
|
|
219
|
+
"""Retourne la version du package genelastic."""
|
|
220
|
+
top_level_package = __package__.split(".")[0]
|
|
221
|
+
return jsonify({"version": version(top_level_package)})
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import connexion
|
|
5
|
+
import yaml
|
|
6
|
+
|
|
7
|
+
from genelastic.common import ElasticQueryConn
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def load_yaml(file_path: Path) -> Any: # noqa: ANN401
|
|
11
|
+
"""Load a YAML file and return its content."""
|
|
12
|
+
content = None
|
|
13
|
+
with Path.open(file_path, encoding="utf-8") as f:
|
|
14
|
+
try:
|
|
15
|
+
content = yaml.safe_load(f)
|
|
16
|
+
except yaml.YAMLError as exc:
|
|
17
|
+
raise SystemExit(exc) from exc
|
|
18
|
+
return content
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def aggregate_openapi_specs(
|
|
22
|
+
main_spec_file: Path, additional_spec_path: Path
|
|
23
|
+
) -> Any: # noqa: ANN401
|
|
24
|
+
"""Aggregate OpenAPI specifications from a main file and a directory
|
|
25
|
+
of additional specifications.
|
|
26
|
+
"""
|
|
27
|
+
main_spec = load_yaml(main_spec_file)
|
|
28
|
+
try:
|
|
29
|
+
entries = additional_spec_path.iterdir()
|
|
30
|
+
except OSError as exc:
|
|
31
|
+
raise SystemExit(exc) from exc
|
|
32
|
+
|
|
33
|
+
if "paths" not in main_spec:
|
|
34
|
+
main_spec["paths"] = []
|
|
35
|
+
|
|
36
|
+
for entry in entries:
|
|
37
|
+
if not entry.is_file():
|
|
38
|
+
continue
|
|
39
|
+
|
|
40
|
+
if entry.suffix not in [".yml", ".yaml"]:
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
content = load_yaml(entry)
|
|
44
|
+
|
|
45
|
+
if "paths" in content:
|
|
46
|
+
main_spec["paths"].update(content["paths"])
|
|
47
|
+
|
|
48
|
+
return main_spec
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# Initialiser l'application Connexion
|
|
52
|
+
connexion_app = connexion.FlaskApp(__name__)
|
|
53
|
+
connexion_app.app.config.from_object("src.genelastic.api.settings.Config")
|
|
54
|
+
|
|
55
|
+
# Initialiser le client Elasticsearch
|
|
56
|
+
es_url = connexion_app.app.config["GENAPI_ES_URL"]
|
|
57
|
+
es_cert_fp = connexion_app.app.config["GENAPI_ES_CERT_FP"]
|
|
58
|
+
es_api_key = connexion_app.app.config["GENAPI_ES_ENCODED_API_KEY"]
|
|
59
|
+
|
|
60
|
+
connexion_app.app.elastic_query_conn = ElasticQueryConn(
|
|
61
|
+
es_url, es_cert_fp, api_key=es_api_key
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
connexion_app.app.logger.debug(
|
|
65
|
+
"Successfully connected to Elasticsearch server: %s",
|
|
66
|
+
connexion_app.app.elastic_query_conn.client.info(),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Chemins des fichiers YAML
|
|
70
|
+
main_yaml_file = Path(__file__).parents[0] / "specification.yml"
|
|
71
|
+
additional_yaml_dir = Path(__file__).parents[0] / "extends"
|
|
72
|
+
|
|
73
|
+
# Charger et combiner les fichiers YAML
|
|
74
|
+
yaml_spec = aggregate_openapi_specs(main_yaml_file, additional_yaml_dir)
|
|
75
|
+
|
|
76
|
+
# Ajouter la spécification vers OpenAPI
|
|
77
|
+
connexion_app.add_api(yaml_spec)
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
connexion_app.run(debug=True)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
# pylint: disable=missing-module-docstring
|
|
2
1
|
from environs import Env
|
|
3
2
|
|
|
4
3
|
env = Env()
|
|
5
4
|
env.read_env()
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
|
|
8
7
|
class Config:
|
|
8
|
+
"""Flask config class."""
|
|
9
|
+
|
|
9
10
|
# Charger toutes les variables d'environnement nécessaires
|
|
10
11
|
GENAPI_ES_URL = env.url("GENAPI_ES_URL").geturl()
|
|
11
12
|
GENAPI_ES_ENCODED_API_KEY = env.str("GENAPI_ES_ENCODED_API_KEY")
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Genelastic package for common code between API and import scripts."""
|
|
2
|
+
|
|
3
|
+
from .cli import add_es_connection_args, add_verbose_control_args
|
|
4
|
+
from .elastic import ElasticImportConn, ElasticQueryConn
|
|
5
|
+
from .exceptions import DBIntegrityError
|
|
6
|
+
from .types import (
|
|
7
|
+
AnalysisDocument,
|
|
8
|
+
AnalysisMetaData,
|
|
9
|
+
BioInfoProcessData,
|
|
10
|
+
Bucket,
|
|
11
|
+
BulkItems,
|
|
12
|
+
BundleDict,
|
|
13
|
+
MetadataDocument,
|
|
14
|
+
ProcessDocument,
|
|
15
|
+
RandomAnalysisData,
|
|
16
|
+
RandomBiProcessData,
|
|
17
|
+
RandomWetProcessData,
|
|
18
|
+
WetProcessesData,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
__all__ = [
|
|
22
|
+
"AnalysisDocument",
|
|
23
|
+
"AnalysisMetaData",
|
|
24
|
+
"BioInfoProcessData",
|
|
25
|
+
"Bucket",
|
|
26
|
+
"BulkItems",
|
|
27
|
+
"BundleDict",
|
|
28
|
+
"DBIntegrityError",
|
|
29
|
+
"ElasticImportConn",
|
|
30
|
+
"ElasticQueryConn",
|
|
31
|
+
"MetadataDocument",
|
|
32
|
+
"ProcessDocument",
|
|
33
|
+
"RandomAnalysisData",
|
|
34
|
+
"RandomBiProcessData",
|
|
35
|
+
"RandomWetProcessData",
|
|
36
|
+
"WetProcessesData",
|
|
37
|
+
"add_es_connection_args",
|
|
38
|
+
"add_verbose_control_args",
|
|
39
|
+
]
|