@dsh-bio/dsh-bio-gem 0.1.1 → 0.1.3

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 CHANGED
@@ -6,7 +6,7 @@ Genome-scale metabolic model builder for dsh: genome in, validated SBML out.
6
6
 
7
7
  ## 📦 安装
8
8
 
9
- 本插件以 **GitHub 源**分发(纯 ESM,无构建步骤,可直接加载);npm 包尚未发布。
9
+ 本插件已发布为 npm **`@dsh-bio/dsh-bio-gem`**(纯 ESM,无构建步骤),也可直接从 GitHub 源或本地目录安装。
10
10
 
11
11
  ### 0. 环境要求
12
12
 
@@ -24,16 +24,20 @@ Genome-scale metabolic model builder for dsh: genome in, validated SBML out.
24
24
  ### 1. 安装插件
25
25
 
26
26
  ```sh
27
- # GitHub 安装(推荐)
27
+ # 方式一:从 npm 安装(推荐,已发布预置包)
28
+ npx -y @deepseek-ai/dsh plugin --profile web add @dsh-bio/dsh-bio-gem
29
+
30
+ # 方式二:从 GitHub 安装(拉源码;本插件纯 ESM 无构建步骤,可直接加载)
28
31
  npx -y @deepseek-ai/dsh plugin --profile web add github:moonbowterfly/dsh-bio-gem
29
32
 
30
- # 从本地目录安装(开发调试)
33
+ # 方式三:从本地目录安装(开发调试)
31
34
  npx -y @deepseek-ai/dsh plugin --profile web add ./dsh-bio-gem
32
35
  ```
33
36
 
34
37
  - 本机若已全局安装 dsh CLI,把 `npx -y @deepseek-ai/dsh` 换成 `dsh` 即可。
35
38
  - `--profile <name>` 是**必填选项**(不传报 `required option '--profile <name>' not specified`);Web 端固定用 `web`。
36
39
  - 安装完**重启 dsh web 服务**(关掉原窗口,重新双击启动入口)。
40
+ - 版本刚发布时可能短时间拉不到:registry 首次分发有几分钟延迟,`pnpm` 还可能缓存住 404。遇到 `ERR_PNPM_FETCH_404 ... is not in the npm registry` 时等几分钟重试,或在命令末尾追加 `--registry https://registry.npmjs.org/` 绕过缓存。
37
41
 
38
42
  验证插件层已生效(不用启动服务):
39
43
 
@@ -122,7 +126,8 @@ npx -y @deepseek-ai/dsh plugin --profile web remove dsh-bio-gem
122
126
 
123
127
  ```sh
124
128
  # 1) install the plugin into the web profile, then restart dsh
125
- npx -y @deepseek-ai/dsh plugin --profile web add github:moonbowterfly/dsh-bio-gem
129
+ npx -y @deepseek-ai/dsh plugin --profile web add @dsh-bio/dsh-bio-gem
130
+ # (or from source: github:moonbowterfly/dsh-bio-gem)
126
131
 
127
132
  # 2) analysis Python needs cobra (+ pyrodigal for the annotation fallback)
128
133
  uv venv --python 3.11 "$HOME/.dsh/dsh-bio-gem/venv"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-bio/dsh-bio-gem",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "基因组尺度代谢模型(GEM)构建插件:输入细菌全基因组(蛋白FASTA,支持多质粒/多染色体),自动构建+验证+补洞+出报告(SBML + 模型卡),供 dsh-bio-genie 消费工具加载使用 | Genome-scale metabolic model builder for dsh",
5
5
  "repository": {
6
6
  "type": "git",
@@ -187,20 +187,37 @@ class Validator:
187
187
  全关交换后最大化 ATP 代谢物的净消耗(demand),通量 > 0.01 → WARN。
188
188
  补洞后必跑(context.post_gapfill 时不再跳过)。
189
189
  P1-5 修复(2026-08-31 LBA9402 会话实测):CarveMe 模型 ATP id 为 M_atp_c,
190
- 旧匹配只看 atp_c/cpd00002_c0 -> 误 SKIP「未找到 ATP」——扩展命名模式 + SKIP 时列出尝试模式与模型内候选。"""
190
+ 旧匹配只看 atp_c/cpd00002_c0 -> 误 SKIP「未找到 ATP」——扩展命名模式 + SKIP 时列出尝试模式与模型内候选。
191
+ P2-9 修复(2026-09-10 iNX1344 E2E 实测):MetaCyc/BioCyc 导出模型 ATP 为 M00002_c
192
+ (name='ATP',formula 为去质子化变体),仍不在模式表内 → 二次误 SKIP(G6 直接失效)。
193
+ 改为三级通用解析:id 模式 → name 匹配 → formula 匹配,跨 ID 体系自适应。"""
191
194
  m = self.m
192
- atp_patterns = ("atp_c", "cpd00002_c0", "m_atp_c", "atp_c0", "cpd00002", "atp")
195
+ atp_patterns = ("atp_c", "cpd00002_c0", "m_atp_c", "atp_c0", "cpd00002", "atp",
196
+ "m00002", "m00002_c", "m00002_c0")
193
197
  cands = [x for x in m.metabolites if (x.id or "").lower() in atp_patterns]
198
+ atp_source = "id_pattern"
199
+ if not cands:
200
+ # 回退 1:name 匹配(跨 ID 体系最稳的信号;排除 dATP 等衍生物)
201
+ cands = [x for x in m.metabolites
202
+ if (x.name or "").strip().upper() == "ATP"
203
+ or ("atp" in (x.name or "").lower() and "datp" not in (x.name or "").lower())]
204
+ atp_source = "name_match"
205
+ if not cands:
206
+ # 回退 2:分子式(含去质子化变体——部分模型 formula 非标准形式)
207
+ cands = [x for x in m.metabolites
208
+ if (x.formula or "").replace(" ", "") in ("C10H16N5O13P3", "C10H12N5O13P3")]
209
+ atp_source = "formula_match"
194
210
  cyto = [x for x in cands if x.compartment in ("c0", "c")]
195
211
  atp_c = (cyto or cands or [None])[0]
196
212
  if atp_c is None:
197
- atp_like = sorted({x.id for x in m.metabolites if "atp" in (x.id or "").lower()})[:10]
213
+ atp_like = sorted({x.id for x in m.metabolites
214
+ if "atp" in (x.id or "").lower() or "atp" in (x.name or "").lower()})[:10]
198
215
  return {"status": "SKIP",
199
- "reason": "未找到 ATP 代谢物(已尝试命名模式: " + ", ".join(atp_patterns) + ")",
216
+ "reason": "未找到 ATP 代谢物(id 模式 / name 匹配 / formula 匹配三级回退均未命中)",
200
217
  "tried_patterns": list(atp_patterns),
201
218
  "atp_like_ids_in_model": atp_like,
202
- "note": "SKIP 系命名口径未命中(非模型缺陷证明);若模型含 ATP 但 id 不在尝试模式中,"
203
- "补充模式或标注 atp 角色后重跑"}
219
+ "note": "SKIP 系命名口径未命中(非模型缺陷证明);若模型含 ATP 但三级回退均未命中,"
220
+ "请在模型内显式标注 atp 角色后重跑"}
204
221
  dm = cobra.Reaction("DM_gem_atp_leak", name="G6 ATP 泄漏检测 demand",
205
222
  lower_bound=0.0, upper_bound=1000.0)
206
223
  dm.add_metabolites({atp_c: -1})
@@ -216,7 +233,7 @@ class Validator:
216
233
  leak = abs(v)
217
234
  status = "PASS" if leak <= 0.01 else "WARN"
218
235
  return {"status": status, "atp_leak_flux": round(leak, 6),
219
- "atp_metabolite_found": atp_c.id,
236
+ "atp_metabolite_found": atp_c.id, "atp_resolved_by": atp_source,
220
237
  "threshold": 0.01, "post_gapfill": bool((context or {}).get("post_gapfill")),
221
238
  "note": "全关交换后 ATP demand 通量应≈0;>0.01 提示能量循环泄漏(L3 MILP 补洞最可能引入)"}
222
239