@dsh-bio/dsh-bio-gem 0.1.16 → 0.1.17
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.
- package/README.md +2 -2
- package/docs/ARCHITECTURE.md +11 -11
- package/docs/releases/v0.1.17.md +32 -0
- package/package.json +1 -1
- package/python/benchmark.py +6 -4
- package/python/biomass_tools.py +9 -3
- package/python/budget.py +1 -1
- package/python/build_whitelist.py +10 -4
- package/python/essential_scan.py +2 -2
- package/python/gapseq_wsl.py +1 -1
- package/python/gem_ops.py +2 -2
- package/python/l3_fix.py +9 -3
- package/python/model_card.py +1 -1
- package/python/roundtrip_check.py +1 -1
- package/python/sensitivity.py +1 -1
- package/python/validate.py +3 -3
- package/skills/gem-expert.md +1 -1
- package/src/tools.js +3 -3
package/README.md
CHANGED
|
@@ -129,7 +129,7 @@ unzip -o diamond.zip diamond.exe -d "$HOME/.dsh/dsh-bio-gem/venv-carveme/Scripts
|
|
|
129
129
|
|
|
130
130
|
```sh
|
|
131
131
|
# 冒烟:不依赖 dsh,直测 Python 层 + 工具注册表
|
|
132
|
-
#
|
|
132
|
+
# 资产(C58 模型等)不在仓库内:用 --assets-root 或 DSH_BIO_GEM_ASSETS 指定;缺资产时相关检查 SKIP
|
|
133
133
|
GEM_PYTHON=<你的-cobra-python> node test/smoke.js --skip-build # 跳过 ~70s 的 build 单测
|
|
134
134
|
GEM_PYTHON=<你的-cobra-python> node test/smoke.js # 含 build 单测
|
|
135
135
|
# 托管领域扩展的只读 integration 协议(无需 dsh 实例)
|
|
@@ -198,7 +198,7 @@ npx -y @deepseek-ai/dsh --profile web --dump-config | grep dsh-bio-gem
|
|
|
198
198
|
|
|
199
199
|
CarveMe + diamond are required only by `gem_build`; the other 20 tools need nothing but a `cobra`-enabled Python.
|
|
200
200
|
|
|
201
|
-
## 工具(
|
|
201
|
+
## 工具(23)
|
|
202
202
|
|
|
203
203
|
| 工具 | 作用 | 状态 |
|
|
204
204
|
|---|---|---|
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# dsh-bio-gem — 架构文档(
|
|
1
|
+
# dsh-bio-gem — 架构文档(2026-08-29 起)
|
|
2
2
|
|
|
3
3
|
## 1. 定位一句话
|
|
4
4
|
|
|
@@ -10,7 +10,7 @@ dsh 平台的 **GEM 构建侧插件**:输入细菌全基因组(支持多质
|
|
|
10
10
|
|
|
11
11
|
| 日期 | 决策 | 依据 |
|
|
12
12
|
|---|---|---|
|
|
13
|
-
| 08-28 | 插件名 dsh-bio-gem;资产盘点:消费侧已就绪、补构建侧闭环 |
|
|
13
|
+
| 08-28 | 插件名 dsh-bio-gem;资产盘点:消费侧已就绪、补构建侧闭环 | 用户决策 |
|
|
14
14
|
| 08-29 | 引擎路线:**任务门槛路由**(不是简单 auto);落地节奏 **M1 CarveMe+补洞 → M2 gapseq WSL 桥 → M3 双引擎交叉** | 独立设计评估 + 实测(CarveMe AB 不生长=补洞是生存线;WSL 桥显著降级交付风险;Docker 非 WSL 替代)|
|
|
15
15
|
| 08-29 | MVP 工具集:gem_build / gem_validate(G1G2G3 必做,G4 条件、G5 抽检)/ gem_gapfind(L1L2L3)/ gem_gapfill(L1L2 规则自动)/ gem_report(薄版模型卡);**gem_essentiality 不进首版** | 消费侧 bio_gene_knockout 已存在,避免重复实现 |
|
|
16
16
|
| 08-29 | 修正建议:弃 μ 判据用 FBA 通量判据;pyrodigal 注释前端降 backlog;测试矩阵首版收敛 C58+2 公开株 | 输出口径为 objective_value;默认输入是带注释基因组 |
|
|
@@ -21,18 +21,18 @@ dsh 平台的 **GEM 构建侧插件**:输入细菌全基因组(支持多质
|
|
|
21
21
|
|
|
22
22
|
| 工具 | Python 层 | 状态 |
|
|
23
23
|
|---|---|---|
|
|
24
|
-
| gem_build | build.py CLI(CarveMe M9 gapfill;fna 自动注释)| ✅
|
|
25
|
-
| gem_validate | op validate(G1-G6 + GATE_REGISTRY)| ✅
|
|
26
|
-
| gem_gapfind | op gapfind(L1-L3 分级 + 跨引擎介质归一化)| ✅
|
|
27
|
-
| gem_gapfill | op gapfill(L1/L2 规则 + provenance)| ✅
|
|
28
|
-
| gem_phenotype | op phenotype_fix(表型回填迭代)| ✅
|
|
24
|
+
| gem_build | build.py CLI(CarveMe M9 gapfill;fna 自动注释)| ✅ 已完成(C58 63-70s)|
|
|
25
|
+
| gem_validate | op validate(G1-G6 + GATE_REGISTRY)| ✅ 已完成 |
|
|
26
|
+
| gem_gapfind | op gapfind(L1-L3 分级 + 跨引擎介质归一化)| ✅ 已完成 |
|
|
27
|
+
| gem_gapfill | op gapfill(L1/L2 规则 + provenance)| ✅ 已完成 |
|
|
28
|
+
| gem_phenotype | op phenotype_fix(表型回填迭代)| ✅ 已完成 |
|
|
29
29
|
| gem_essentiality | op essential_scan(FVA 预筛 + 手工敲除;预测自动入账本)| ✅ P0 DONE |
|
|
30
30
|
| gem_annotate | op annotate(官方优先 + pyrodigal)| ✅ P0 DONE |
|
|
31
31
|
| gem_gapseq | op gapseq(WSL 原子四步,可选项)| ✅ 桥全通 |
|
|
32
|
-
| gem_l3_fix | op l3_fix(L3 补洞:L3a 连通性 + L3b 白名单/BiGG;证据分级 + 预算闸门 + G6 回滚)| ✅
|
|
32
|
+
| gem_l3_fix | op l3_fix(L3 补洞:L3a 连通性 + L3b 白名单/BiGG;证据分级 + 预算闸门 + G6 回滚)| ✅ 已完成(C58 Arabinose 0→0.851)|
|
|
33
33
|
| gem_report | op model_info(+ ledger_summary 基率摘要)| ✅ DONE |
|
|
34
34
|
| gem_media_resolve | op media_resolve(介质解析 RPC,消费侧统一入口)| ✅ DONE |
|
|
35
|
-
| gem_biomass | op biomass_inspect / biomass_apply(inspect 组分+对照参考;apply 覆盖表+三联对照+原文件不动回滚)| ✅
|
|
35
|
+
| gem_biomass | op biomass_inspect / biomass_apply(inspect 组分+对照参考;apply 覆盖表+三联对照+原文件不动回滚)| ✅ 已完成(复位 delta 0.0)|
|
|
36
36
|
| gem_fluxscan | op fluxscan(通量区间制:FVA 区间+pFBA 点值+条件对区间分离判定,overlap=伪影禁止引用)| ✅ 已完成(C58 AB 0.519981 / 蔗糖 supplement 0.97077)|
|
|
37
37
|
| gem_sensitivity | op sensitivity(GAM×biomass 22 组合全量+稳定性三分类+单组分漂移;模型卡 robustness v3)| ✅ 已完成(基准复现 155)|
|
|
38
38
|
| gem_ledger | op ledger(prediction ledger:list/query/update;幂等追加式账本)| ✅ 已完成(C58 155+19 条幂等复跑)|
|
|
@@ -54,10 +54,10 @@ dsh 平台的 **GEM 构建侧插件**:输入细菌全基因组(支持多质
|
|
|
54
54
|
## 4. 引擎路线(M1→M2→M3)
|
|
55
55
|
|
|
56
56
|
- **M1(已完成 08-29,C58 实测)**:CarveMe 纯 Windows(独立 venv ~/.dsh/dsh-bio-gem/venv-carveme + diamond PATH 注入)。输入(protein.faa)→ carve -g M9(54s)→ 精确 M9 介质(media_db 提取)G3 PASS(C58 测 0.782)→ 用户目标介质 resolve(跨引擎自然名)→ G3 FAIL 时 L1/L2 规则补洞 → 模型卡。**CarveMe 模型实测:M9 可生长;AB 目标介质 FAIL 且为 L3 内部路径(L1/L2 规则不可修)——诚实报告为已知边界(研究设计既有结论:CarveMe M9 补洞局限)。**
|
|
57
|
-
- **M2(2026-08-29
|
|
57
|
+
- **M2(2026-08-29 起)**:gapseq WSL2 桥(`python/gapseq_wsl.py`)。能力探测四件套(wsl/发行版/gapseq 版本/序列库注册 up-to-date——防假已装 UniProt 灾难);新版 wsl.exe 输出 UTF-8(旧版 UTF-16LE,双解码兼容);doall 哨兵文件轮询(30-60min,每 2min 进度 + 日志尾部旁观);产物拷回 → 目标介质验证(AB 自然名)→ L1/L2 补洞闭环 → 模型卡。gem_build `engine` 参数(carveme|gapseq)+ 60min 超时。分发时采用**私有发行版**(wsl --import 自包含 bundle:R+gapseq+序列库 v1.5+哈希校验,版本钉死)。任务分步化(draft/build/transport/fill/adjust 每步落盘 → 断点续跑)待做。
|
|
58
58
|
- **M3**:双引擎交叉验证,产出**分歧清单**(两引擎不一致反应/基因 = 低置信区,需文献/实验校验)而非平均;可选集成 gemsembler(先验证成熟度);所有比对按**反应级等价类**而非基因级(引擎 GPR 粒度不同)。
|
|
59
59
|
|
|
60
|
-
## 5.
|
|
60
|
+
## 5. 验证关卡规格(产品化 + G0)
|
|
61
61
|
|
|
62
62
|
| 关卡 | 内容 | 首版 | 判定线 |
|
|
63
63
|
|---|---|---|---|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# @dsh-bio/dsh-bio-gem v0.1.17
|
|
2
|
+
|
|
3
|
+
> **主题**:默认值通用化与公开信息审计修复。
|
|
4
|
+
> 基因组尺度代谢模型(GEM)构建插件:基因组输入 → 构建 → 验证 → 补洞 → 出报告(标准 SBML + 模型卡)。
|
|
5
|
+
|
|
6
|
+
## 修复与改进
|
|
7
|
+
|
|
8
|
+
**默认值通用化(面向所有用户)**
|
|
9
|
+
- 资源路径默认值不再绑定开发机目录:解释器/工具与参考资源改为**插件数据目录 + 环境变量**优先
|
|
10
|
+
(`GEM_GAPSEQ_DB` / `GEM_DIAMOND` / `GEM_WHITELIST_DB_DIR` / `GEM_UNIVERSAL_MODEL` / `GEM_INX_MODEL`),
|
|
11
|
+
缺失时给出可操作提示而非静默失败。
|
|
12
|
+
- BiGG 模型下载的代理回退改为读取**环境变量代理**(`HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY`),
|
|
13
|
+
不再固定本机端口;描述与实现一致。
|
|
14
|
+
|
|
15
|
+
**测试与文档**
|
|
16
|
+
- 回归脚本资产配置显式化:`--assets-root` 或 `DSH_BIO_GEM_ASSETS` 指定模型资产;缺资产时相关检查 SKIP(不误报为回归失败)。
|
|
17
|
+
- 文档一致性:生长值单位口径说明(归一化 biomass 为 1/h;一般反应通量为 mmol/gDW/h)、工具计数、
|
|
18
|
+
架构文档状态与内部代号清理、基准报告路径通用化。
|
|
19
|
+
|
|
20
|
+
## 安装
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
npx -y @deepseek-ai/dsh plugin --profile web add @dsh-bio/dsh-bio-gem
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
桌面端(0.2.0+):用桌面端自带 CLI(`--profile desktop`)或应用内「插件」页安装。
|
|
27
|
+
分析用 Python(cobra)优先复用 dsh-bio-genie 自举环境;未装 genie 时见 README 第 2 节。
|
|
28
|
+
|
|
29
|
+
## 已知边界(诚实清单)
|
|
30
|
+
|
|
31
|
+
- `gem_build` 的 gapseq 引擎为实验性(WSL2 环境绑定,30–60 分钟/模型);默认 carveme 引擎已可出可验证模型。
|
|
32
|
+
- 其余边界见 v0.1.12 清单。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-bio/dsh-bio-gem",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "基因组尺度代谢模型(GEM)构建插件:输入细菌全基因组(蛋白FASTA,支持多质粒/多染色体),自动构建+验证+补洞+出报告(SBML + 模型卡),供 dsh-bio-genie 消费工具加载使用 | Genome-scale metabolic model builder for dsh",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
package/python/benchmark.py
CHANGED
|
@@ -389,7 +389,8 @@ def fetch_bigg_model(model_id, dest_dir=None):
|
|
|
389
389
|
URL 策略(实测 2026-08-30):静态库 http://bigg.ucsd.edu/static/models/<id>.xml 返回标准 SBML;
|
|
390
390
|
`/api/v2/universal/models/<id>/download` 实为 404(universal 是 reactions 命名空间),
|
|
391
391
|
/api/v2/models/<id>/download 返回 200 但内容是 BiGG JSON(非 SBML)——两者均不采用。
|
|
392
|
-
|
|
392
|
+
直连失败时按环境变量代理(HTTP_PROXY/HTTPS_PROXY/ALL_PROXY)重试一次;
|
|
393
|
+
未配置环境代理或仍失败则抛错(调用方如实报告,不阻塞本地对比)。"""
|
|
393
394
|
import urllib.request
|
|
394
395
|
import shutil
|
|
395
396
|
urls = [f"http://bigg.ucsd.edu/static/models/{model_id}.xml"]
|
|
@@ -398,10 +399,11 @@ def fetch_bigg_model(model_id, dest_dir=None):
|
|
|
398
399
|
dest = os.path.join(dest_dir, f"bigg_{model_id}.xml")
|
|
399
400
|
if os.path.exists(dest) and os.path.getsize(dest) > 100000:
|
|
400
401
|
return dest, "cached(已有本地副本)"
|
|
402
|
+
env_proxies = {k: v for k, v in urllib.request.getproxies().items() if v}
|
|
403
|
+
fallbacks = [("direct", None)] + ([("env-proxy", env_proxies)] if env_proxies else [])
|
|
401
404
|
last_err = None
|
|
402
405
|
for url in urls:
|
|
403
|
-
for tag, proxies in
|
|
404
|
-
"https": "http://127.0.0.1:27890"})):
|
|
406
|
+
for tag, proxies in fallbacks:
|
|
405
407
|
try:
|
|
406
408
|
t0 = time.time()
|
|
407
409
|
req = urllib.request.Request(url, headers={"User-Agent": "dsh-bio-gem benchmark/1.0"})
|
|
@@ -417,7 +419,7 @@ def fetch_bigg_model(model_id, dest_dir=None):
|
|
|
417
419
|
last_err = f"{type(e).__name__}: {str(e)[:200]}"
|
|
418
420
|
if os.path.exists(dest + ".tmp"):
|
|
419
421
|
os.remove(dest + ".tmp")
|
|
420
|
-
raise RuntimeError(f"bigg download failed
|
|
422
|
+
raise RuntimeError(f"bigg download failed(直连与代理回退均失败): {last_err}")
|
|
421
423
|
|
|
422
424
|
|
|
423
425
|
def medium_adaptation_hints(model_path, medium, max_hints=5, progress=None):
|
package/python/biomass_tools.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# biomass_tools.py — biomass 精修工具链(
|
|
1
|
+
# biomass_tools.py — biomass 精修工具链(inspect / apply)
|
|
2
2
|
# inspect(只读): biomass 组分表 + 类别分布(氨基酸/核酸/脂质/辅因子/金属/其他)+ 原子总量
|
|
3
3
|
# + 可选参考对照(内置 iML1515 biomass;iNX1344_v4 按代谢物名同义尽力翻译,翻不了明示 unmapped)
|
|
4
4
|
# apply(显式): biomass_profile 覆盖表(op=set|add|remove)→ 副本替换 biomass → 强制 G1-G6 重验
|
|
@@ -16,8 +16,14 @@ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
16
16
|
import cobra
|
|
17
17
|
|
|
18
18
|
EX_PREFIX = ("EX_", "DM_", "SK_")
|
|
19
|
-
DEFAULT_UNIVERSAL =
|
|
20
|
-
|
|
19
|
+
DEFAULT_UNIVERSAL = os.environ.get(
|
|
20
|
+
"GEM_UNIVERSAL_MODEL",
|
|
21
|
+
os.path.join(os.path.expanduser("~"), ".dsh", "dsh-bio-gem", "models", "iML1515.xml"),
|
|
22
|
+
)
|
|
23
|
+
DEFAULT_INX = os.environ.get(
|
|
24
|
+
"GEM_INX_MODEL",
|
|
25
|
+
os.path.join(os.path.expanduser("~"), ".dsh", "dsh-bio-gem", "models", "iNX1344_v4.xml"),
|
|
26
|
+
)
|
|
21
27
|
GROWTH_UNITS = "1/h"
|
|
22
28
|
EPS = 1e-6
|
|
23
29
|
|
package/python/budget.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# budget.py —
|
|
1
|
+
# budget.py — 防过补第五闸门(全局预算)
|
|
2
2
|
# 规格: PROMPT-L3 §2「单模型补洞历史累计新增反应数 ≤ max(5, 模型总反应数*5%);
|
|
3
3
|
# 超限返回 budget_exceeded + confirm_required,需显式 confirm_budget=true 才能继续」。
|
|
4
4
|
# 计数口径: 反应 notes["source"] ∈ {gem-gapfill, gem-l3fix}(两代补洞的 provenance 约定)。
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
# build_whitelist.py —
|
|
1
|
+
# build_whitelist.py — 反应白名单构建(B0/B1 两级):gapseq rxn 库 → 反应白名单(本地基准,license 守则:不分发)
|
|
2
2
|
# B0: 聚合 rxn/*.fasta(非空)→ rxn_proteins.fa + mapping(序列header -> 反应ID)
|
|
3
3
|
# B1: diamond makedb + blastp 目标物种 faa → 命中反应集(EVIDENCE_sequence 候选池)
|
|
4
4
|
import os
|
|
5
5
|
import sys
|
|
6
6
|
import time
|
|
7
7
|
|
|
8
|
-
SEQDB = os.environ.get("GEM_GAPSEQ_DB",
|
|
9
|
-
DIAMOND =
|
|
8
|
+
SEQDB = os.environ.get("GEM_GAPSEQ_DB", "")
|
|
9
|
+
DIAMOND = os.environ.get(
|
|
10
|
+
"GEM_DIAMOND",
|
|
11
|
+
os.path.join(os.path.expanduser("~"), ".dsh", "dsh-bio-gem", "venv-carveme", "Scripts", "diamond.exe"),
|
|
12
|
+
)
|
|
10
13
|
|
|
11
14
|
|
|
12
15
|
def build_rxn_fasta(out_fa, out_map=None, min_size=100):
|
|
@@ -115,7 +118,10 @@ def subprocess_run(cmd, timeout=3600):
|
|
|
115
118
|
|
|
116
119
|
if __name__ == "__main__":
|
|
117
120
|
import json
|
|
118
|
-
fa = sys.argv[1] if len(sys.argv) > 1 else
|
|
121
|
+
fa = sys.argv[1] if len(sys.argv) > 1 else os.path.join(
|
|
122
|
+
os.path.expanduser("~"), ".dsh", "dsh-bio-gem", "whitelist", "rxn_all.fa")
|
|
123
|
+
if not SEQDB or not os.path.isdir(os.path.join(SEQDB, "rxn")):
|
|
124
|
+
sys.exit("GEM_GAPSEQ_DB 未设置或无效:请指向 gapseq 序列库目录(<db>/Bacteria,内含 rxn/ 子目录)")
|
|
119
125
|
out_dir = os.path.dirname(fa) or "."
|
|
120
126
|
os.makedirs(out_dir, exist_ok=True)
|
|
121
127
|
map_p = os.path.join(out_dir, "rxn_map.tsv")
|
package/python/essential_scan.py
CHANGED
|
@@ -63,7 +63,7 @@ def scan_essentiality(m, gene_subset=None, progress=None, return_candidates=Fals
|
|
|
63
63
|
print(f"[scan] 候选基因(关联可通量反应){len(cand_genes)}", file=sys.stderr)
|
|
64
64
|
print(f"[scan] 预计免敲 {max(0, len(m.genes) - len(cand_genes))} 个({max(0, len(m.genes)-len(cand_genes))/max(1,len(m.genes))*100:.0f}%)", file=sys.stderr)
|
|
65
65
|
|
|
66
|
-
# 2)
|
|
66
|
+
# 2) 手工敲除循环(不用 single_gene_deletion)
|
|
67
67
|
t0 = time.time()
|
|
68
68
|
essential = []
|
|
69
69
|
for gid in sorted(cand_genes):
|
|
@@ -149,7 +149,7 @@ def essential_scan(model_path, medium=None, gene_subset=None, progress=None, led
|
|
|
149
149
|
result.update({
|
|
150
150
|
"medium_preset": preset,
|
|
151
151
|
"medium_unresolved": unresolved,
|
|
152
|
-
"note": "必需判定=A 培养基下敲除生长<1e-6;evidence 分级按基因支撑反应是否含 EVIDENCE_math
|
|
152
|
+
"note": "必需判定=A 培养基下敲除生长<1e-6;evidence 分级按基因支撑反应是否含 EVIDENCE_math",
|
|
153
153
|
# 阶段A-M4 口径声明(只增):wt_growth 为单点 FBA 值
|
|
154
154
|
"units": "1/h",
|
|
155
155
|
"point_value_note": "单点 FBA 值,非解空间硬结论;条件对比请用 gem_fluxscan 区间分离判定",
|
package/python/gapseq_wsl.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# gapseq_wsl.py — dsh-bio-gem M2:gapseq 引擎的 WSL 桥(Windows → WSL2)
|
|
2
2
|
# 实测背景(农杆菌 C58 项目 2026-08):gapseq 2.1.0 部署于 WSL2 Ubuntu-22.04
|
|
3
|
-
# conda env "gapseq"(TUNA
|
|
3
|
+
# conda env "gapseq"(TUNA 渠道)+ 本地序列库(路径见文件内常量,换机器需相应调整)。
|
|
4
4
|
# 关键实测(2026-08-29):
|
|
5
5
|
# - 新版 wsl.exe(Win11)输出 UTF-8;旧版 UTF-16LE —— decode 双兼容(UTF-8 strict 优先)
|
|
6
6
|
# - wsl.exe 命令行传含空格路径 + 引号必坏 -> 一切路径进脚本文件,脚本用 base64 传输
|
package/python/gem_ops.py
CHANGED
|
@@ -243,7 +243,7 @@ def op_media_resolve(args):
|
|
|
243
243
|
|
|
244
244
|
|
|
245
245
|
# ---------------------------------------------------------------------------
|
|
246
|
-
# op: l3_fix —
|
|
246
|
+
# op: l3_fix — L3 内部路径补洞(L3a 模型内连通性 + L3b 白名单/BiGG 反应式)
|
|
247
247
|
# 证据分级 EVIDENCE_sequence/math;防过补第五闸门(budget.py);补后 G1-G6 重验 + G6 失败回滚
|
|
248
248
|
# ---------------------------------------------------------------------------
|
|
249
249
|
def op_l3_fix(args):
|
|
@@ -371,7 +371,7 @@ OPS = {
|
|
|
371
371
|
|
|
372
372
|
|
|
373
373
|
# ---------------------------------------------------------------------------
|
|
374
|
-
# op: biomass_inspect / biomass_apply —
|
|
374
|
+
# op: biomass_inspect / biomass_apply — biomass 精修(可选 profile,不默认替换)
|
|
375
375
|
# ---------------------------------------------------------------------------
|
|
376
376
|
def op_biomass_inspect(args):
|
|
377
377
|
from biomass_tools import inspect_biomass
|
package/python/l3_fix.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# l3_fix.py —
|
|
1
|
+
# l3_fix.py — L3 内部路径补洞(两级)
|
|
2
2
|
# L3a 模型内连通性: 先"全内部反应放开方向"LP 预检(快速严谨判负),可行才用 cobra GapFiller
|
|
3
3
|
# universal=模型自身反应池(放开方向副本,NEW id),MILP 选最小集 → 对原反应放宽 bounds(不复制反应)。
|
|
4
4
|
# 注: cobra 0.32.1 GapFiller(universal=None) 语义是"空反应池"(只加 demand),不是"模型自身反应池"
|
|
@@ -43,8 +43,14 @@ COMP_MAP = {"c": "c0", "e": "e0", "p": "p0"} # BiGG 区室后缀 -> gapseq 区
|
|
|
43
43
|
|
|
44
44
|
WHITELIST_DIR = os.path.join(os.path.expanduser("~"), ".dsh", "dsh-bio-gem", "whitelist")
|
|
45
45
|
# 本地白名单数据库(license 守则: 仅本地留存,不进 git/发布包;GEM_WHITELIST_DB_DIR 可覆盖)
|
|
46
|
-
RXN_DB_DIR = os.environ.get(
|
|
47
|
-
|
|
46
|
+
RXN_DB_DIR = os.environ.get(
|
|
47
|
+
"GEM_WHITELIST_DB_DIR",
|
|
48
|
+
os.path.join(os.path.expanduser("~"), ".dsh", "dsh-bio-gem", "whitelist-db"),
|
|
49
|
+
)
|
|
50
|
+
DEFAULT_UNIVERSAL = os.environ.get(
|
|
51
|
+
"GEM_UNIVERSAL_MODEL",
|
|
52
|
+
os.path.join(os.path.expanduser("~"), ".dsh", "dsh-bio-gem", "models", "iML1515.xml"),
|
|
53
|
+
)
|
|
48
54
|
|
|
49
55
|
PTS_RE = re.compile(r"(?i)\bpts\b|phosphotransferase|pep:pyr")
|
|
50
56
|
|
package/python/model_card.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# model_card.py — 模型卡 schema v2
|
|
1
|
+
# model_card.py — 模型卡 schema v2 统一写入器(工程质量件)
|
|
2
2
|
# 职责: init_card(build 起卡)/ load / save / append_operation(lineage 版本递增 + changelog)
|
|
3
3
|
# / set_verified_phenotypes(phenotype 结果)/ set_essential_genes(必需基因 + 证据分级)
|
|
4
4
|
# 纪律: 各工具完成后**仅当产物模型旁已有 card** 才向后追加;无卡不动(不凭空造卡)。
|
package/python/sensitivity.py
CHANGED
|
@@ -128,7 +128,7 @@ def find_biomass_gam(m):
|
|
|
128
128
|
|
|
129
129
|
def _apply_biomass_scale(m, bio_id, f, gam_info):
|
|
130
130
|
"""biomass 组分缩放 ×f(排除 GAM stub 与 Biomass 产物——正交化)。
|
|
131
|
-
cobra add_metabolites 是增量语义:绝对设定必须用 delta =
|
|
131
|
+
cobra add_metabolites 是增量语义:绝对设定必须用 delta = 目标-现值(实测教训),回读校验。
|
|
132
132
|
注意:原始系数必须在 add 之前快照(add 后 bio.metabolites 已是新值)。"""
|
|
133
133
|
bio = m.reactions.get_by_id(bio_id)
|
|
134
134
|
skip = set((gam_info.get("gam_mets") or {}).values()) | \
|
package/python/validate.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# validate.py — dsh-bio-gem
|
|
1
|
+
# validate.py — dsh-bio-gem 五道验证关卡
|
|
2
2
|
# G1 加载统计 / G2 内部反应元素平衡 / G3 生长真实性 / G4 底物表型(条件) / G5 必需基因抽检(条件)
|
|
3
3
|
# 规格: docs/ARCHITECTURE.md §5;判据口径 = FBA objective_value(biomass 归一化 → 比生长速率 μ,单位 1/h)
|
|
4
|
-
#
|
|
4
|
+
# 五道关卡协议产品化(农杆菌项目验证过的逻辑)
|
|
5
5
|
import re
|
|
6
6
|
import os
|
|
7
7
|
import json
|
|
@@ -262,7 +262,7 @@ class Validator:
|
|
|
262
262
|
# ------------------------------------------------------------------ G4
|
|
263
263
|
def g4_phenotype(self, table_path=None, substrates=None, medium=None, carbon_mode="supplement"):
|
|
264
264
|
"""条件执行:需参照表(TSV: substrate<TAB>published 0/1)或 substrates+published。
|
|
265
|
-
carbon_mode: supplement=基准培养基不变+底物-10
|
|
265
|
+
carbon_mode: supplement=基准培养基不变+底物-10(对齐关卡4 基线 16/19→17/19);
|
|
266
266
|
sole=去含碳交换后底物-10(唯一碳源严格语义,氮源类测试会误判)。"""
|
|
267
267
|
if table_path and os.path.exists(table_path):
|
|
268
268
|
rows = []
|
package/skills/gem-expert.md
CHANGED
|
@@ -63,7 +63,7 @@ language: mixed
|
|
|
63
63
|
|
|
64
64
|
0. **外部事实断言必须带证据**(2026-08-29 采纳):凡涉及"某物种/文献/工具是否存在、是否已发表"等**模型外事实断言**,agent 必须真实检索并附来源(如 PubMed/PMC 链接);无法检索时降级表述为"未验证假设 [假设]",不得由记忆下断言。此项与 EVIDENCE 分级同位:**事实断言也有证据分级**(检索+来源=high;仅记忆=unverified)。
|
|
65
65
|
1. **培养基一律用自然名成分**:`{"D-Glucose": -5, "NH3": -10, "O2": -12.5, ...}`。插件跨引擎自动解析(gapseq EX_cpdXXXXXX_e0 与 CarveMe/BiGG EX_glc__D_e 命名空间不同,硬编码 ID 会失配)。
|
|
66
|
-
2. **数字必须来自工具输出**:agent 报告生长值/基因数/复制子数时引用工具 result
|
|
66
|
+
2. **数字必须来自工具输出**:agent 报告生长值/基因数/复制子数时引用工具 result,不要凭模型知识猜测(防幻觉铁律)。**生长值单位以工具返回的 `units` 字段为准**:归一化 biomass 反应(产物系数=1)的生长值为 **1/h(比生长速率 μ)**;一般反应通量为 mmol/gDW/h。汇报时不得混用口径。
|
|
67
67
|
3. **CarveMe 模型的介质边界**:`gem_build` 默认在 M9 最小培养基验证(生长阳性);**AB 等自定义培养基若 FAIL 且 gapfind 判定 L3(内部路径),规则补洞修不了**——此时如实报告「模型可用介质=M9,目标介质需要 L3 级文献补充」,绝不要假装自愈。
|
|
68
68
|
4. **缺口 90% 是 L1/L2**(缺交换/转运,非缺分解酶)——先诊断再补,别直接加反应。
|
|
69
69
|
5. **多复制子正常**:质粒/多染色体基因都在同一模型内(C58 实测 4 复制子:967/434/65/18 基因分布于 ChrⅠ/ChrⅡ/pTi/pAt)。
|
package/src/tools.js
CHANGED
|
@@ -260,7 +260,7 @@ export function registerTools(ctx) {
|
|
|
260
260
|
timeoutMs: 120_000,
|
|
261
261
|
})))
|
|
262
262
|
|
|
263
|
-
// gem_l3_fix:L3 内部路径补洞(
|
|
263
|
+
// gem_l3_fix:L3 内部路径补洞(L3a 模型内连通性 + L3b 白名单/BiGG 反应式 + 证据分级)
|
|
264
264
|
disposers.push(ctx.tools.register(gemTool({
|
|
265
265
|
name: 'gem_l3_fix',
|
|
266
266
|
description:
|
|
@@ -288,7 +288,7 @@ export function registerTools(ctx) {
|
|
|
288
288
|
timeoutMs: 900_000,
|
|
289
289
|
})))
|
|
290
290
|
|
|
291
|
-
// gem_biomass:biomass 精修(
|
|
291
|
+
// gem_biomass:biomass 精修(inspect 只读 / apply 显式覆盖表 + 三联对照)
|
|
292
292
|
disposers.push(ctx.tools.register(defineTool({
|
|
293
293
|
name: 'gem_biomass',
|
|
294
294
|
description:
|
|
@@ -417,7 +417,7 @@ export function registerTools(ctx) {
|
|
|
417
417
|
name: 'gem_benchmark',
|
|
418
418
|
description:
|
|
419
419
|
'通用基准对比(benchmark):任何两个代谢模型跑规范对比表,产出论文级对比。model_a/model_b 支持本地 SBML 绝对路径' +
|
|
420
|
-
'或 "bigg:<model_id>" URI(如 bigg:iML1515,BiGG 静态库下载到 ~/.dsh/dsh-bio-gem/models
|
|
420
|
+
'或 "bigg:<model_id>" URI(如 bigg:iML1515,BiGG 静态库下载到 ~/.dsh/dsh-bio-gem/models/,直连失败时按环境变量代理(HTTP_PROXY/HTTPS_PROXY)重试,下载后缓存)。' +
|
|
421
421
|
'输出:ID 体系探测 / 六道关卡 G1-G6 逐项并列 / 声明介质生长(含介质层两级策略——无 EX_ 层的模型自动回退 ' +
|
|
422
422
|
'boundary 单代谢物反应解析,boundary_style 标注)/ biomass 可行性探针(逐组分净产测试,结构性断供清单)/ ' +
|
|
423
423
|
'必需性对比(复用 essential_scan;任一侧 wt<=EPS 判退化只报结构信息不做垃圾对比,基因映射尽力而为如实报覆盖率,' +
|