@dsh-bio/dsh-bio-gem 0.1.2 → 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/python/validate.py +24 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-bio/dsh-bio-gem",
3
- "version": "0.1.2",
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