merge-cli 2.0.2__tar.gz → 3.0.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.
- {merge_cli-2.0.2 → merge_cli-3.0.0}/PKG-INFO +3 -4
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli/api.py +12 -73
- merge_cli-3.0.0/merge_cli/cli.py +693 -0
- merge_cli-3.0.0/merge_cli/config.py +87 -0
- merge_cli-3.0.0/merge_cli/data/__init__.py +0 -0
- merge_cli-3.0.0/merge_cli/data/models/.gitkeep +6 -0
- merge_cli-3.0.0/merge_cli/data/models/BestModel_Clinvar-noncoding.pkl +0 -0
- merge_cli-3.0.0/merge_cli/data/models/BestModel_Clinvar.pkl +0 -0
- merge_cli-3.0.0/merge_cli/data/models/BestModel_Splice_Unsupervised Only.pkl +0 -0
- merge_cli-3.0.0/merge_cli/data/models/__init__.py +0 -0
- merge_cli-3.0.0/merge_cli/data/models/ensemble_predict.py +831 -0
- merge_cli-3.0.0/merge_cli/local_engine.py +602 -0
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli.egg-info/PKG-INFO +3 -4
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli.egg-info/SOURCES.txt +8 -2
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli.egg-info/requires.txt +0 -1
- {merge_cli-2.0.2 → merge_cli-3.0.0}/pyproject.toml +13 -6
- merge_cli-2.0.2/README.md +0 -114
- merge_cli-2.0.2/merge_cli/cli.py +0 -754
- merge_cli-2.0.2/merge_cli/config.py +0 -86
- merge_cli-2.0.2/merge_cli/local_engine.py +0 -370
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli/__init__.py +0 -0
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli/ensemble_predict.py +0 -0
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli/output.py +0 -0
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli.egg-info/dependency_links.txt +0 -0
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli.egg-info/entry_points.txt +0 -0
- {merge_cli-2.0.2 → merge_cli-3.0.0}/merge_cli.egg-info/top_level.txt +0 -0
- {merge_cli-2.0.2 → merge_cli-3.0.0}/setup.cfg +0 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: merge-cli
|
|
3
|
-
Version:
|
|
4
|
-
Summary: MERGE 变异致病性预测 CLI
|
|
5
|
-
Project-URL: Homepage, https://
|
|
3
|
+
Version: 3.0.0
|
|
4
|
+
Summary: MERGE 变异致病性预测 CLI(服务器固定,集成模型内嵌,无需手动配置)
|
|
5
|
+
Project-URL: Homepage, https://merge.fanglab.cn
|
|
6
6
|
Requires-Python: >=3.11
|
|
7
7
|
Requires-Dist: click>=8.1
|
|
8
8
|
Requires-Dist: rich>=13.0
|
|
9
9
|
Requires-Dist: requests>=2.31
|
|
10
|
-
Requires-Dist: keyring>=24.0
|
|
11
10
|
Requires-Dist: pysam>=0.22; sys_platform != "win32"
|
|
12
11
|
Requires-Dist: numpy>=1.26
|
|
13
12
|
Requires-Dist: pandas>=2.1
|
|
@@ -1,44 +1,31 @@
|
|
|
1
1
|
"""
|
|
2
|
-
merge_cli/api.py
|
|
2
|
+
merge_cli/api.py — v3.0.0
|
|
3
3
|
封装所有对 Django 后端的 HTTP 请求。
|
|
4
|
-
|
|
4
|
+
服务器地址固定为 https://merge.fanglab.cn/,无需 Token 认证。
|
|
5
5
|
"""
|
|
6
6
|
import sys
|
|
7
7
|
from typing import Optional
|
|
8
8
|
|
|
9
9
|
import requests
|
|
10
10
|
|
|
11
|
-
from .config import
|
|
11
|
+
from .config import FIXED_API_URL
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
_TIMEOUT_BATCH = 60 # 批量提交:只是上传文件,后台异步处理
|
|
13
|
+
_TIMEOUT_SINGLE = 180
|
|
14
|
+
_TIMEOUT_BATCH = 60
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
def _headers() -> dict:
|
|
19
|
-
token = get_token()
|
|
20
|
-
h = {"Accept": "application/json"}
|
|
21
|
-
if token:
|
|
22
|
-
h["Authorization"] = f"Token {token}"
|
|
23
|
-
return h
|
|
16
|
+
_BASE = FIXED_API_URL
|
|
24
17
|
|
|
25
18
|
|
|
26
|
-
def
|
|
27
|
-
|
|
28
|
-
if not url:
|
|
29
|
-
print("错误:未配置 API 地址。请先运行:merge config set-url https://your-server.com")
|
|
30
|
-
sys.exit(1)
|
|
31
|
-
return url
|
|
19
|
+
def _headers() -> dict:
|
|
20
|
+
return {"Accept": "application/json"}
|
|
32
21
|
|
|
33
22
|
|
|
34
23
|
# ─────────────────────────────────────────────────────────────
|
|
35
24
|
# 1. 单变异预测 POST /predict/
|
|
36
|
-
# 对应 views.py: combined_prediction_view
|
|
37
25
|
# ─────────────────────────────────────────────────────────────
|
|
38
26
|
def predict_single(
|
|
39
27
|
chrom: str, pos: int, ref: str, alt: str,
|
|
40
28
|
genome_version: str = "hg38",
|
|
41
|
-
# 模型开关,与 views.py POST 参数名一一对应
|
|
42
29
|
use_alphagenome: bool = True,
|
|
43
30
|
use_hyenadna: bool = True,
|
|
44
31
|
use_nt: bool = True,
|
|
@@ -49,10 +36,6 @@ def predict_single(
|
|
|
49
36
|
use_evo2: bool = True,
|
|
50
37
|
use_evo1: bool = True,
|
|
51
38
|
) -> dict:
|
|
52
|
-
"""
|
|
53
|
-
调用 /predict/ 端点,返回完整 prediction 字典。
|
|
54
|
-
包含 dbnsfp / alphagenome / hyenadna / nt / gpn_msa / popeve / evo2 / evo1 / errors。
|
|
55
|
-
"""
|
|
56
39
|
payload = {
|
|
57
40
|
"chr": chrom, "pos": pos, "ref": ref, "alt": alt,
|
|
58
41
|
"genome_version": genome_version,
|
|
@@ -67,7 +50,7 @@ def predict_single(
|
|
|
67
50
|
"use_evo1": str(use_evo1).lower(),
|
|
68
51
|
}
|
|
69
52
|
resp = requests.post(
|
|
70
|
-
f"{
|
|
53
|
+
f"{_BASE}/predict/",
|
|
71
54
|
json=payload,
|
|
72
55
|
headers=_headers(),
|
|
73
56
|
timeout=_TIMEOUT_SINGLE,
|
|
@@ -78,17 +61,11 @@ def predict_single(
|
|
|
78
61
|
|
|
79
62
|
# ─────────────────────────────────────────────────────────────
|
|
80
63
|
# 2. 集成模型评分 POST /ensemble/
|
|
81
|
-
# 对应 views.py: ensemble_predict_view
|
|
82
|
-
# 通常在 predict_single 成功后自动调用
|
|
83
64
|
# ─────────────────────────────────────────────────────────────
|
|
84
65
|
def predict_ensemble(prediction: dict, all_transcripts: list) -> dict:
|
|
85
|
-
"""
|
|
86
|
-
用 /predict/ 返回的 prediction 字典再调用 /ensemble/,
|
|
87
|
-
获取 MERGE 集成得分和 SHAP 图(base64 PNG)。
|
|
88
|
-
"""
|
|
89
66
|
payload = {"prediction": prediction, "all_transcripts": all_transcripts}
|
|
90
67
|
resp = requests.post(
|
|
91
|
-
f"{
|
|
68
|
+
f"{_BASE}/ensemble/",
|
|
92
69
|
json=payload,
|
|
93
70
|
headers=_headers(),
|
|
94
71
|
timeout=_TIMEOUT_SINGLE,
|
|
@@ -99,7 +76,6 @@ def predict_ensemble(prediction: dict, all_transcripts: list) -> dict:
|
|
|
99
76
|
|
|
100
77
|
# ─────────────────────────────────────────────────────────────
|
|
101
78
|
# 3. 批量提交 POST /api/submit_batch_job/
|
|
102
|
-
# 对应 views.py: submit_batch_job
|
|
103
79
|
# ─────────────────────────────────────────────────────────────
|
|
104
80
|
def submit_batch(
|
|
105
81
|
vcf_path: str,
|
|
@@ -115,10 +91,6 @@ def submit_batch(
|
|
|
115
91
|
use_evo2: bool = True,
|
|
116
92
|
use_evo1: bool = True,
|
|
117
93
|
) -> dict:
|
|
118
|
-
"""
|
|
119
|
-
上传 VCF 文件,异步批量预测,结果发送至 email。
|
|
120
|
-
返回 job_id 供后续查询状态。
|
|
121
|
-
"""
|
|
122
94
|
data = {
|
|
123
95
|
"notify_email": email,
|
|
124
96
|
"genome_version": genome_version,
|
|
@@ -134,7 +106,7 @@ def submit_batch(
|
|
|
134
106
|
}
|
|
135
107
|
with open(vcf_path, "rb") as f:
|
|
136
108
|
resp = requests.post(
|
|
137
|
-
f"{
|
|
109
|
+
f"{_BASE}/api/submit_batch_job/",
|
|
138
110
|
data=data,
|
|
139
111
|
files={"vcf_file": (vcf_path.split("/")[-1], f)},
|
|
140
112
|
headers=_headers(),
|
|
@@ -146,45 +118,12 @@ def submit_batch(
|
|
|
146
118
|
|
|
147
119
|
# ─────────────────────────────────────────────────────────────
|
|
148
120
|
# 4. 查询批量任务状态 GET /api/batch_job/<job_id>/
|
|
149
|
-
# 对应 views.py: batch_job_status
|
|
150
121
|
# ─────────────────────────────────────────────────────────────
|
|
151
122
|
def get_batch_status(job_id: str) -> dict:
|
|
152
123
|
resp = requests.get(
|
|
153
|
-
f"{
|
|
124
|
+
f"{_BASE}/api/batch_job/{job_id}/",
|
|
154
125
|
headers=_headers(),
|
|
155
126
|
timeout=30,
|
|
156
127
|
)
|
|
157
128
|
resp.raise_for_status()
|
|
158
129
|
return resp.json()
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
# ─────────────────────────────────────────────────────────────
|
|
162
|
-
# 5. 开放注册 POST /api/register/
|
|
163
|
-
# 对应 views.py: register_and_get_token
|
|
164
|
-
# 公开接口,不需要携带 Token
|
|
165
|
-
# ─────────────────────────────────────────────────────────────
|
|
166
|
-
def register(username: str, email: str, password: str) -> dict:
|
|
167
|
-
resp = requests.post(
|
|
168
|
-
f"{_base()}/api/register/",
|
|
169
|
-
json={"username": username, "email": email, "password": password},
|
|
170
|
-
headers={"Content-Type": "application/json", "Accept": "application/json"},
|
|
171
|
-
timeout=30,
|
|
172
|
-
)
|
|
173
|
-
resp.raise_for_status()
|
|
174
|
-
return resp.json()
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
# ─────────────────────────────────────────────────────────────
|
|
178
|
-
# 6. 已有账号重新登录取 Token POST /api/login/
|
|
179
|
-
# 对应 views.py: login_and_get_token
|
|
180
|
-
# 公开接口,不需要携带 Token
|
|
181
|
-
# ─────────────────────────────────────────────────────────────
|
|
182
|
-
def login(username: str, password: str) -> dict:
|
|
183
|
-
resp = requests.post(
|
|
184
|
-
f"{_base()}/api/login/",
|
|
185
|
-
json={"username": username, "password": password},
|
|
186
|
-
headers={"Content-Type": "application/json", "Accept": "application/json"},
|
|
187
|
-
timeout=30,
|
|
188
|
-
)
|
|
189
|
-
resp.raise_for_status()
|
|
190
|
-
return resp.json()
|