cool-seq-tool 0.4.0.dev1__tar.gz → 0.4.0.dev2__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.
- {cool_seq_tool-0.4.0.dev1/src/cool_seq_tool.egg-info → cool_seq_tool-0.4.0.dev2}/PKG-INFO +7 -6
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/README.md +3 -3
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/pyproject.toml +53 -12
- cool_seq_tool-0.4.0.dev2/src/cool_seq_tool/data/__init__.py +2 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/data/data_downloads.py +19 -13
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/handlers/seqrepo_access.py +2 -4
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/mappers/exon_genomic_coords.py +25 -26
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/mappers/mane_transcript.py +112 -106
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/routers/default.py +7 -9
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/routers/mane.py +2 -2
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/schemas.py +30 -21
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/sources/mane_transcript_mappings.py +1 -1
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/sources/transcript_mappings.py +13 -16
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/sources/uta_database.py +134 -153
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/utils.py +5 -2
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/version.py +1 -1
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2/src/cool_seq_tool.egg-info}/PKG-INFO +7 -6
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool.egg-info/requires.txt +3 -2
- cool_seq_tool-0.4.0.dev1/src/cool_seq_tool/data/__init__.py +0 -2
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/LICENSE +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/setup.cfg +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/__init__.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/api.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/app.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/data/transcript_mapping.tsv +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/handlers/__init__.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/mappers/__init__.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/mappers/alignment.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/paths.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/routers/__init__.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/routers/mappings.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/sources/__init__.py +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool.egg-info/SOURCES.txt +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool.egg-info/dependency_links.txt +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool.egg-info/top_level.txt +0 -0
- {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: cool_seq_tool
|
3
|
-
Version: 0.4.0.
|
3
|
+
Version: 0.4.0.dev2
|
4
4
|
Summary: Common Operation on Lots of Sequences Tool
|
5
5
|
Author: Kori Kuzma, James Stevenson, Katie Stahl, Alex Wagner
|
6
6
|
License: MIT License
|
@@ -49,7 +49,7 @@ License-File: LICENSE
|
|
49
49
|
Requires-Dist: asyncpg
|
50
50
|
Requires-Dist: aiofiles
|
51
51
|
Requires-Dist: boto3
|
52
|
-
Requires-Dist:
|
52
|
+
Requires-Dist: agct>=0.1.0-dev1
|
53
53
|
Requires-Dist: polars
|
54
54
|
Requires-Dist: hgvs
|
55
55
|
Requires-Dist: biocommons.seqrepo
|
@@ -62,7 +62,7 @@ Requires-Dist: pre-commit; extra == "dev"
|
|
62
62
|
Requires-Dist: ipython; extra == "dev"
|
63
63
|
Requires-Dist: ipykernel; extra == "dev"
|
64
64
|
Requires-Dist: psycopg2-binary; extra == "dev"
|
65
|
-
Requires-Dist: ruff; extra == "dev"
|
65
|
+
Requires-Dist: ruff>=0.1.14; extra == "dev"
|
66
66
|
Provides-Extra: tests
|
67
67
|
Requires-Dist: pytest; extra == "tests"
|
68
68
|
Requires-Dist: pytest-cov; extra == "tests"
|
@@ -75,12 +75,13 @@ Requires-Dist: sphinx-autobuild==2021.3.14; extra == "docs"
|
|
75
75
|
Requires-Dist: sphinx-copybutton==0.5.2; extra == "docs"
|
76
76
|
Requires-Dist: sphinxext-opengraph==0.8.2; extra == "docs"
|
77
77
|
Requires-Dist: furo==2023.3.27; extra == "docs"
|
78
|
+
Requires-Dist: sphinx-github-changelog==1.2.1; extra == "docs"
|
78
79
|
|
79
80
|
<h1 align="center">
|
80
81
|
CoolSeqTool
|
81
82
|
</h1>
|
82
83
|
|
83
|
-
**[Documentation](https://coolseqtool.readthedocs.io/
|
84
|
+
**[Documentation](https://coolseqtool.readthedocs.io/latest/)** · [Installation](https://coolseqtool.readthedocs.io/latest/install.html) · [Usage](https://coolseqtool.readthedocs.io/latest/usage.html) · [API reference](https://coolseqtool.readthedocs.io/latest/reference/index.html)
|
84
85
|
|
85
86
|
## Overview
|
86
87
|
|
@@ -102,7 +103,7 @@ CoolSeqTool is available on [PyPI](https://pypi.org/project/cool-seq-tool)
|
|
102
103
|
python3 -m pip install cool-seq-tool
|
103
104
|
```
|
104
105
|
|
105
|
-
See the [installation instructions](https://coolseqtool.readthedocs.io/
|
106
|
+
See the [installation instructions](https://coolseqtool.readthedocs.io/latest/install.html) in the documentation for a description of dependency setup requirements.
|
106
107
|
|
107
108
|
---
|
108
109
|
|
@@ -127,4 +128,4 @@ All CoolSeqTool resources can be initialized by way of a top-level class instanc
|
|
127
128
|
|
128
129
|
## Feedback and contributing
|
129
130
|
|
130
|
-
We welcome bug reports, feature requests, and code contributions from users and interested collaborators. The [documentation](https://coolseqtool.readthedocs.io/
|
131
|
+
We welcome bug reports, feature requests, and code contributions from users and interested collaborators. The [documentation](https://coolseqtool.readthedocs.io/latest/contributing.html) contains guidance for submitting feedback and contributing new code.
|
@@ -2,7 +2,7 @@
|
|
2
2
|
CoolSeqTool
|
3
3
|
</h1>
|
4
4
|
|
5
|
-
**[Documentation](https://coolseqtool.readthedocs.io/
|
5
|
+
**[Documentation](https://coolseqtool.readthedocs.io/latest/)** · [Installation](https://coolseqtool.readthedocs.io/latest/install.html) · [Usage](https://coolseqtool.readthedocs.io/latest/usage.html) · [API reference](https://coolseqtool.readthedocs.io/latest/reference/index.html)
|
6
6
|
|
7
7
|
## Overview
|
8
8
|
|
@@ -24,7 +24,7 @@ CoolSeqTool is available on [PyPI](https://pypi.org/project/cool-seq-tool)
|
|
24
24
|
python3 -m pip install cool-seq-tool
|
25
25
|
```
|
26
26
|
|
27
|
-
See the [installation instructions](https://coolseqtool.readthedocs.io/
|
27
|
+
See the [installation instructions](https://coolseqtool.readthedocs.io/latest/install.html) in the documentation for a description of dependency setup requirements.
|
28
28
|
|
29
29
|
---
|
30
30
|
|
@@ -49,4 +49,4 @@ All CoolSeqTool resources can be initialized by way of a top-level class instanc
|
|
49
49
|
|
50
50
|
## Feedback and contributing
|
51
51
|
|
52
|
-
We welcome bug reports, feature requests, and code contributions from users and interested collaborators. The [documentation](https://coolseqtool.readthedocs.io/
|
52
|
+
We welcome bug reports, feature requests, and code contributions from users and interested collaborators. The [documentation](https://coolseqtool.readthedocs.io/latest/contributing.html) contains guidance for submitting feedback and contributing new code.
|
@@ -29,7 +29,7 @@ dependencies = [
|
|
29
29
|
"asyncpg",
|
30
30
|
"aiofiles",
|
31
31
|
"boto3",
|
32
|
-
"
|
32
|
+
"agct >= 0.1.0-dev1",
|
33
33
|
"polars",
|
34
34
|
"hgvs",
|
35
35
|
"biocommons.seqrepo",
|
@@ -41,7 +41,7 @@ dependencies = [
|
|
41
41
|
dynamic = ["version"]
|
42
42
|
|
43
43
|
[project.optional-dependencies]
|
44
|
-
dev = ["pre-commit", "ipython", "ipykernel", "psycopg2-binary", "ruff"]
|
44
|
+
dev = ["pre-commit", "ipython", "ipykernel", "psycopg2-binary", "ruff>=0.1.14"]
|
45
45
|
tests = ["pytest", "pytest-cov", "pytest-asyncio==0.18.3", "mock"]
|
46
46
|
docs = [
|
47
47
|
"sphinx==6.1.3",
|
@@ -50,6 +50,7 @@ docs = [
|
|
50
50
|
"sphinx-copybutton==0.5.2",
|
51
51
|
"sphinxext-opengraph==0.8.2",
|
52
52
|
"furo==2023.3.27",
|
53
|
+
"sphinx-github-changelog==1.2.1"
|
53
54
|
]
|
54
55
|
|
55
56
|
[project.urls]
|
@@ -86,14 +87,49 @@ branch = true
|
|
86
87
|
[tool.ruff]
|
87
88
|
src = ["src"]
|
88
89
|
exclude = ["docs/source/conf.py"]
|
89
|
-
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
# pep8-naming
|
94
|
-
#
|
95
|
-
|
96
|
-
|
90
|
+
select = [
|
91
|
+
"F", # https://docs.astral.sh/ruff/rules/#pyflakes-f
|
92
|
+
"E", "W", # https://docs.astral.sh/ruff/rules/#pycodestyle-e-w
|
93
|
+
"I", # https://docs.astral.sh/ruff/rules/#isort-i
|
94
|
+
"N", # https://docs.astral.sh/ruff/rules/#pep8-naming-n
|
95
|
+
"D", # https://docs.astral.sh/ruff/rules/#pydocstyle-d
|
96
|
+
"UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up
|
97
|
+
"ANN", # https://docs.astral.sh/ruff/rules/#flake8-annotations-ann
|
98
|
+
"ASYNC", # https://docs.astral.sh/ruff/rules/#flake8-async-async
|
99
|
+
"S", # https://docs.astral.sh/ruff/rules/#flake8-bandit-s
|
100
|
+
"B", # https://docs.astral.sh/ruff/rules/#flake8-bugbear-b
|
101
|
+
"A", # https://docs.astral.sh/ruff/rules/#flake8-builtins-a
|
102
|
+
"C4", # https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4
|
103
|
+
"DTZ", # https://docs.astral.sh/ruff/rules/#flake8-datetimez-dtz
|
104
|
+
"T10", # https://docs.astral.sh/ruff/rules/#flake8-datetimez-dtz
|
105
|
+
"EM", # https://docs.astral.sh/ruff/rules/#flake8-errmsg-em
|
106
|
+
"G", # https://docs.astral.sh/ruff/rules/#flake8-logging-format-g
|
107
|
+
"PIE", # https://docs.astral.sh/ruff/rules/#flake8-pie-pie
|
108
|
+
"T20", # https://docs.astral.sh/ruff/rules/#flake8-print-t20
|
109
|
+
"PT", # https://docs.astral.sh/ruff/rules/#flake8-pytest-style-pt
|
110
|
+
"Q", # https://docs.astral.sh/ruff/rules/#flake8-quotes-q
|
111
|
+
"RSE", # https://docs.astral.sh/ruff/rules/#flake8-raise-rse
|
112
|
+
"RET", # https://docs.astral.sh/ruff/rules/#flake8-return-ret
|
113
|
+
"SIM", # https://docs.astral.sh/ruff/rules/#flake8-simplify-sim
|
114
|
+
"PTH", # https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth
|
115
|
+
"PGH", # https://docs.astral.sh/ruff/rules/#pygrep-hooks-pgh
|
116
|
+
"RUF", # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf
|
117
|
+
]
|
118
|
+
fixable = [
|
119
|
+
"I",
|
120
|
+
"F401",
|
121
|
+
"D",
|
122
|
+
"UP",
|
123
|
+
"ANN",
|
124
|
+
"B",
|
125
|
+
"C4",
|
126
|
+
"G",
|
127
|
+
"PIE",
|
128
|
+
"PT",
|
129
|
+
"RSE",
|
130
|
+
"SIM",
|
131
|
+
"RUF"
|
132
|
+
]
|
97
133
|
|
98
134
|
# ANN101 - missing-type-self
|
99
135
|
# ANN003 - missing-type-kwargs
|
@@ -109,12 +145,14 @@ fixable = ["I", "F401"]
|
|
109
145
|
# E117 - over-indented*
|
110
146
|
# E501 - line-too-long*
|
111
147
|
# W191 - tab-indentation*
|
148
|
+
# S321 - suspicious-ftp-lib-usage
|
112
149
|
# *ignored for compatibility with formatter
|
113
150
|
ignore = [
|
114
151
|
"ANN101", "ANN003",
|
115
152
|
"D203", "D205", "D206", "D213", "D300", "D400", "D415",
|
116
153
|
"E111", "E114", "E117", "E501",
|
117
|
-
"W191"
|
154
|
+
"W191",
|
155
|
+
"S321",
|
118
156
|
]
|
119
157
|
|
120
158
|
[tool.ruff.per-file-ignores]
|
@@ -124,6 +162,9 @@ ignore = [
|
|
124
162
|
# N805 - invalid-first-argument-name-for-method
|
125
163
|
# F821 - undefined-name
|
126
164
|
# F401 - unused-import
|
127
|
-
"tests/*" = ["ANN001", "ANN2", "ANN102"]
|
165
|
+
"tests/*" = ["ANN001", "ANN2", "ANN102", "S101"]
|
128
166
|
"*__init__.py" = ["F401"]
|
129
167
|
"src/cool_seq_tool/schemas.py" = ["ANN201", "N805", "ANN001"]
|
168
|
+
|
169
|
+
[tool.ruff.lint.flake8-bugbear]
|
170
|
+
extend-immutable-calls = ["fastapi.Query"]
|
{cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/data/data_downloads.py
RENAMED
@@ -4,7 +4,6 @@ import gzip
|
|
4
4
|
import logging
|
5
5
|
import shutil
|
6
6
|
from ftplib import FTP
|
7
|
-
from os import remove
|
8
7
|
from pathlib import Path
|
9
8
|
|
10
9
|
from dateutil import parser
|
@@ -38,18 +37,20 @@ class DataDownload:
|
|
38
37
|
files = ftp.nlst()
|
39
38
|
mane_summary_file = [f for f in files if f.endswith(".summary.txt.gz")]
|
40
39
|
if not mane_summary_file:
|
41
|
-
|
40
|
+
msg = "Unable to download MANE summary data"
|
41
|
+
raise Exception(msg)
|
42
42
|
mane_summary_file = mane_summary_file[0]
|
43
43
|
self._mane_summary_path = self._data_dir / mane_summary_file[:-3]
|
44
44
|
mane_data_path = self._data_dir / mane_summary_file
|
45
45
|
if not self._mane_summary_path.exists():
|
46
46
|
logger.info("Downloading MANE summary file from NCBI.")
|
47
|
-
with open(
|
47
|
+
with mane_data_path.open("wb") as fp:
|
48
48
|
ftp.retrbinary(f"RETR {mane_summary_file}", fp.write)
|
49
|
-
with gzip.open(
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
with gzip.open(
|
50
|
+
mane_data_path, "rb"
|
51
|
+
) as f_in, self._mane_summary_path.open("wb") as f_out:
|
52
|
+
shutil.copyfileobj(f_in, f_out)
|
53
|
+
mane_data_path.unlink()
|
53
54
|
logger.info("MANE summary file download complete.")
|
54
55
|
return self._mane_summary_path
|
55
56
|
|
@@ -66,18 +67,23 @@ class DataDownload:
|
|
66
67
|
ftp_file_path = f"{ftp_dir_path}{lrg_refseqgene_file}"
|
67
68
|
timestamp = ftp.voidcmd(f"MDTM {ftp_file_path}")[4:].strip()
|
68
69
|
date = str(parser.parse(timestamp)).split()[0]
|
69
|
-
version =
|
70
|
+
version = (
|
71
|
+
datetime.datetime.strptime(date, "%Y-%m-%d")
|
72
|
+
.astimezone(tz=datetime.timezone.utc)
|
73
|
+
.strftime("%Y%m%d")
|
74
|
+
)
|
70
75
|
fn_versioned = f"{lrg_refseqgene_file}_{version}"
|
71
76
|
lrg_refseqgene_path = self._data_dir / lrg_refseqgene_file
|
72
77
|
self._lrg_refseqgene_path = self._data_dir / fn_versioned
|
73
78
|
if not self._lrg_refseqgene_path.exists():
|
74
79
|
logger.info("Downloading LRG RefSeq data from NCBI.")
|
75
80
|
ftp.cwd(ftp_dir_path)
|
76
|
-
with open(
|
81
|
+
with lrg_refseqgene_path.open("wb") as fp:
|
77
82
|
ftp.retrbinary(f"RETR {lrg_refseqgene_file}", fp.write)
|
78
|
-
with open(
|
79
|
-
|
80
|
-
|
81
|
-
|
83
|
+
with lrg_refseqgene_path.open(
|
84
|
+
"rb"
|
85
|
+
) as f_in, self._lrg_refseqgene_path.open("wb") as f_out:
|
86
|
+
shutil.copyfileobj(f_in, f_out)
|
87
|
+
lrg_refseqgene_path.unlink()
|
82
88
|
logger.info("LRG RefSeq data download complete.")
|
83
89
|
return self._lrg_refseqgene_path
|
{cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/handlers/seqrepo_access.py
RENAMED
@@ -152,8 +152,7 @@ class SeqRepoAccess(SeqRepoDataProxy):
|
|
152
152
|
acs.append(ac.split("refseq:")[-1])
|
153
153
|
if acs:
|
154
154
|
return acs, None
|
155
|
-
|
156
|
-
return None, f"{chromosome} is not a valid chromosome"
|
155
|
+
return None, f"{chromosome} is not a valid chromosome"
|
157
156
|
|
158
157
|
def ac_to_chromosome(self, ac: str) -> Tuple[Optional[str], Optional[str]]:
|
159
158
|
"""Get chromosome for accession.
|
@@ -172,8 +171,7 @@ class SeqRepoAccess(SeqRepoDataProxy):
|
|
172
171
|
)[0]
|
173
172
|
if aliases is None:
|
174
173
|
return None, f"Unable to get chromosome for {ac}"
|
175
|
-
|
176
|
-
return aliases, None
|
174
|
+
return aliases, None
|
177
175
|
|
178
176
|
def get_fasta_file(self, sequence_id: str, outfile_path: Path) -> None:
|
179
177
|
"""Retrieve FASTA file containing sequence for requested sequence ID.
|
@@ -112,8 +112,7 @@ class ExonGenomicCoordsMapper:
|
|
112
112
|
# Ensure valid inputs
|
113
113
|
if not transcript:
|
114
114
|
return self._return_warnings(resp, "Must provide `transcript`")
|
115
|
-
|
116
|
-
transcript = transcript.strip()
|
115
|
+
transcript = transcript.strip()
|
117
116
|
|
118
117
|
exon_start_exists, exon_end_exists = False, False
|
119
118
|
if exon_start is not None:
|
@@ -130,12 +129,11 @@ class ExonGenomicCoordsMapper:
|
|
130
129
|
return self._return_warnings(
|
131
130
|
resp, "Must provide either `exon_start` or `exon_end`"
|
132
131
|
)
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
)
|
132
|
+
if exon_start_exists and exon_end_exists and (exon_start > exon_end):
|
133
|
+
return self._return_warnings(
|
134
|
+
resp,
|
135
|
+
f"Start exon {exon_start} is greater than end exon {exon_end}",
|
136
|
+
)
|
139
137
|
|
140
138
|
# Get all exons and associated start/end coordinates for transcript
|
141
139
|
tx_exons, warning = await self.uta_db.get_tx_exons(transcript)
|
@@ -266,7 +264,7 @@ class ExonGenomicCoordsMapper:
|
|
266
264
|
if start is None and end is None:
|
267
265
|
return self._return_warnings(resp, "Must provide either `start` or `end`")
|
268
266
|
|
269
|
-
params = {key: None for key in GenomicData.model_fields
|
267
|
+
params = {key: None for key in GenomicData.model_fields}
|
270
268
|
if gene is not None:
|
271
269
|
gene = gene.upper().strip()
|
272
270
|
|
@@ -312,13 +310,12 @@ class ExonGenomicCoordsMapper:
|
|
312
310
|
|
313
311
|
for field in ["transcript", "gene", "chr", "strand"]:
|
314
312
|
if start_data:
|
315
|
-
if end_data:
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
return self._return_warnings(resp, msg)
|
313
|
+
if end_data and (start_data[field] != end_data[field]):
|
314
|
+
msg = (
|
315
|
+
f"Start `{field}`, {start_data[field]}, does "
|
316
|
+
f"not match End `{field}`, {end_data[field]}"
|
317
|
+
)
|
318
|
+
return self._return_warnings(resp, msg)
|
322
319
|
params[field] = start_data[field]
|
323
320
|
else:
|
324
321
|
params[field] = end_data[field]
|
@@ -440,7 +437,10 @@ class ExonGenomicCoordsMapper:
|
|
440
437
|
else:
|
441
438
|
error = "Strand does not match"
|
442
439
|
logger.warning(
|
443
|
-
|
440
|
+
"%s: %s != %s",
|
441
|
+
error,
|
442
|
+
alt_ac_data["start"][i],
|
443
|
+
alt_ac_data["end"][i],
|
444
444
|
)
|
445
445
|
return None, error
|
446
446
|
return tuple(alt_ac_data_values), None
|
@@ -482,7 +482,7 @@ class ExonGenomicCoordsMapper:
|
|
482
482
|
resp, "Must provide either `gene` or `transcript`"
|
483
483
|
)
|
484
484
|
|
485
|
-
params = {key: None for key in TranscriptExonData.model_fields
|
485
|
+
params = {key: None for key in TranscriptExonData.model_fields}
|
486
486
|
|
487
487
|
if alt_ac:
|
488
488
|
# Check if valid accession is given
|
@@ -550,7 +550,7 @@ class ExonGenomicCoordsMapper:
|
|
550
550
|
len_alt_acs = len(alt_acs)
|
551
551
|
if len_alt_acs > 1:
|
552
552
|
return None, f"Found more than one accessions: {alt_acs}"
|
553
|
-
|
553
|
+
if len_alt_acs == 0:
|
554
554
|
return None, "No genomic accessions found"
|
555
555
|
alt_ac = next(iter(alt_acs))
|
556
556
|
|
@@ -565,13 +565,12 @@ class ExonGenomicCoordsMapper:
|
|
565
565
|
elif len_genes == 0:
|
566
566
|
return None, "No genes found"
|
567
567
|
|
568
|
-
if input_gene is not None:
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
)
|
568
|
+
if input_gene is not None and output_gene != input_gene.upper():
|
569
|
+
return (
|
570
|
+
None,
|
571
|
+
f"Input gene, {input_gene}, does not match "
|
572
|
+
f"expected output gene, {output_gene}",
|
573
|
+
)
|
575
574
|
|
576
575
|
gene = output_gene if output_gene else input_gene
|
577
576
|
return (gene, alt_ac), None
|