11# MFSL 数据库架构设计 v2.0
22
33> 确认日期:2026-03-24
4+ > 最后更新:2026-03-24(注释流程修正 + MetaboFlow 对口 + 最终数据统计)
45> 状态:待确认
56> 替代:2026-03-23-mfsl-architecture-upgrade-design.md(v1,已过时)
67
@@ -15,7 +16,7 @@ MFSL(MetaboFlow Spectral Library)是一个独立的数据资产,由两个
1516```
1617Layer 1: 数据层
1718 ├── deduplicated/*.msp 质谱库:60 万条 MS2 谱图峰数据(标签内嵌)
18- └── compound_metadata.csv 化合物库:96 万条化合物属性(= Level 3 数据)
19+ └── compound_metadata.csv 化合物库:127 万条化合物属性(= Level 3 数据)
1920
2021Layer 2: 索引层
2122 └── spectral_metadata.csv 质谱库的只读快速索引(从 MSP 自动生成)
@@ -29,7 +30,7 @@ Layer 3: 文档层
2930```
3031质谱库 (Level 2) 化合物库 (Level 3)
3132deduplicated/*.msp compound_metadata.csv
32- 60 万条谱图 96 万条化合物
33+ 60 万条谱图 127 万条化合物(覆盖所有谱图化合物)
3334 每条内嵌 8 维标签 每条有 8 维标签
3435 数据:peaks(碎裂谱图) 数据:exact_mass(精确质量)
3536 用途:MS2 谱图匹配 用途:MS1 精确质量匹配
@@ -44,29 +45,59 @@ deduplicated/*.msp compound_metadata.csv
4445- 标签内嵌 MSP 文件——行业标准做法(MassBank/GNPS/MoNA/FragHub 均如此)
4546- spectral_metadata.csv 是 MSP 的衍生物——从 MSP 文件自动生成,不是数据源
4647
47- ### 1.3 注释匹配流程
48+ ### 1.3 注释匹配流程(matchms 真实工作逻辑)
4849
4950```
50- 用户选标签过滤(如 chemical_class=pfas, application=environmental_monitoring)
51- │
52- ├─→ Level 2: 在 spectral_metadata.csv 按标签过滤
53- │ → 拿到目标谱图 ID 列表
54- │ → 只加载对应 MSP 条目做 MS2 余弦匹配
55- │ → 命中的 feature 标注 msi_level=2
56- │
57- ├─→ Level 2.5: SIRIUS/CSI:FingerID(Level 2 未命中的 features)
58- │ → 结构预测,msi_level=3
59- │
60- ├─→ Level 3: 在 compound_metadata.csv 按标签过滤
61- │ → 只对 Level 2 未命中的 features 做精确质量匹配
62- │ → 命中的标注 msi_level=3
63- │
64- └─→ Level 4: 分子式推算(纯算法,无需库)
65- → 仍未注释的标注 msi_level=4
66-
67- 用户不选标签 → 不过滤,搜全库
51+ Step 1: annot-worker 启动时加载 MSP 文件
52+ → refs = matchms.load_from_msp("deduplicated/*.msp")
53+ → 60 万条 Spectrum 对象全部加载到内存
54+ → 每条的 metadata 包含内嵌的 8 维标签字段
55+ → MetaboFlow 对口:annot-worker/app/matchms_engine.py
56+
57+ Step 2: 用户选标签过滤(可选)
58+ → filtered = [r for r in refs if r.metadata.get("chemical_class") == "pfas"]
59+ → Python 层面的内存过滤,不涉及文件 IO
60+ → 不选标签则 filtered = refs(全库)
61+ → MetaboFlow 对口:AnnotationParams.tag_filter
62+
63+ Step 3: Level 2 — MS2 谱图匹配
64+ → 对每个 query spectrum(来自用户 mzML 的 MS2 数据)
65+ → matchms.CosineGreedy.pair(query, ref) 逐一计算余弦相似度
66+ → score >= 0.7 的标注为 Level 2 命中
67+ → 命中结果:InChIKey + compound_name + score(来自 MSP metadata)
68+ → MetaboFlow 对口:annotation_orchestrator.py Line 65-117
69+
70+ Step 4: 元数据富集(compound_metadata.csv)
71+ → Level 2 命中的化合物,用 InChIKey(前 14 位)查 compound_metadata
72+ → 补充:KEGG ID、HMDB ID、通路信息、详细化学分类
73+ → 这是行业痛点——多数工具需要用户手动做 ID 转换
74+ → MetaboFlow 自动完成,无需用户操作
75+ → MetaboFlow 对口:annotation_orchestrator.py Step 5(待实现)
76+
77+ Step 5: Level 2.5 — SIRIUS 结构预测(可选)
78+ → 对 Level 2 未命中且有 MS2 数据的 features
79+ → SIRIUS/CSI:FingerID 计算预测
80+ → MetaboFlow 对口:annotation_orchestrator.py Line 123-171
81+
82+ Step 6: Level 3 — MS1 精确质量匹配
83+ → 对仍未注释的 features
84+ → 在 compound_metadata.csv 中按 exact_mass ± ppm 匹配
85+ → 如果用户选了标签,compound_metadata 同样做标签过滤
86+ → 命中结果:compound_name + exact_mass + 化合物标签
87+ → MetaboFlow 对口:annotation_orchestrator.py Line 173-191
88+
89+ Step 7: Level 4 — 分子式推算
90+ → 仍未注释的 features,纯算法推算可能的分子式
91+ → 无需外部库
92+ → MetaboFlow 对口:annotation_orchestrator.py Line 193-203
6893```
6994
95+ ** 关键说明:**
96+ - spectral_metadata.csv 不参与此流程——matchms 直接读 MSP 文件
97+ - InChIKey 关联发生在 Step 4(元数据富集),不在搜索阶段
98+ - Level 2 和 Level 3 是完全独立的代码路径,只共享标签过滤逻辑
99+ - compound_metadata.csv 承担两个角色:Level 3 数据源 + 元数据富集来源
100+
70101---
71102
72103## 2. 八维标签体系
@@ -291,7 +322,7 @@ MFSL 是独立数据资产,MetaboFlow 和 PonylabASMS 各自复制一份使用
291322| ---| ---| ---|
292323| 搜索引擎 | matchms (cosine) | Flash Entropy Search |
293324| 复制内容 | deduplicated/* .msp + compound_metadata.csv | 同左 |
294- | 标签过滤 | annot-worker 读 spectral_metadata → 过滤 ID → 加载 MSP | spectral_search.py 读 Tags 字段 |
325+ | 标签过滤 | annot-worker 加载 MSP → 按 metadata 字段过滤 → 余弦匹配 | spectral_search.py 读 metadata 字段过滤 |
295326| 自有扩展 | 无 | eCPIN CFM-ID 预测库 |
296327
297328MFSL 的架构与搜索引擎无关——它只负责存储、索引、标签,不绑定匹配算法。
@@ -331,6 +362,88 @@ MFSL 的架构与搜索引擎无关——它只负责存储、索引、标签,
331362| 8 维标签全部适用所有化合物 | reg_lists 对非环境化合物为空值,但保留维度的统一性 |
332363| InChIKey 前 14 位跨库匹配 | 前 14 位是分子骨架,立体异构体共享,跨库匹配率从 35% 提升到 65% |
333364| 标签只用可信来源填充 | 不猜、不推测——原始库字段、库级别确定性标注、ClassyFire API |
334- | 两个库各自独立标签 | 质谱库 65% 谱图的化合物不在化合物库里,依赖查询会导致大量标签缺失 |
365+ | 两个库各自独立标签 | 质谱库原有 65% 谱图的化合物不在化合物库里(已通过合并解决) |
366+ | compound_metadata 覆盖所有谱图化合物 | 从 MSP 提取 13.6 万"谱图独有"化合物合并到 compound_metadata,实现 100% InChIKey 覆盖 |
335367| registry.csv 并入 DATABASE_MANUAL | spectral_metadata.csv 已覆盖其索引功能,registry 降为文档 |
336368| 去重保留来源追溯 | Sources 字段记录所有数据库来源,去重不丢信息 |
369+ | MSP 标签用独立字段行(非 Tags 单行) | matchms 实测:独立字段行自动解析为 metadata 字典,零适配成本 |
370+
371+ ---
372+
373+ ## 9. 最终数据统计
374+
375+ ### 9.1 质谱库(deduplicated/* .msp)
376+
377+ | 指标 | 数值 |
378+ | ------| ------|
379+ | 总谱图数 | 602,899 |
380+ | MSP 文件数 | 50 |
381+ | InChIKey 覆盖率 | 95.8%(577,625 条) |
382+ | 无 InChIKey(保留) | 25,274 条(glycan/ReSpect/HMDB predicted/NIST EPA) |
383+ | 质量评分范围 | 0-100(8 维加权) |
384+
385+ ### 9.2 化合物元数据库(compound_metadata.csv)
386+
387+ | 字段 | 覆盖率 | 数量 |
388+ | ------| --------| ------|
389+ | ** 总量** | — | ** 1,269,678** |
390+ | name | 100.0% | 1,269,678 |
391+ | formula | 99.8% | 1,267,247 |
392+ | exact_mass | 99.7% | 1,266,259 |
393+ | smiles | 80.7% | 1,025,074 |
394+ | chemical_class | 78.2%(NPClassifier 补充中,预计→84%) | 992,391 |
395+ | application | 40.0% | 508,343 |
396+ | sample | 73.8% | 937,190 |
397+ | reg_lists | 6.8% | 85,774 |
398+ | kegg_id | 2.1% | 27,007 |
399+ | hmdb_id | 17.2% | 217,895 |
400+
401+ ### 9.3 InChIKey 覆盖关系
402+
403+ | 指标 | 数值 |
404+ | ------| ------|
405+ | compound_metadata 唯一 InChIKey | 1,068,604 |
406+ | MSP 谱图唯一 InChIKey | 483,861 |
407+ | MSP → compound_metadata 匹配率(前 14 位) | ** 100%** |
408+
409+ ---
410+
411+ ## 10. 与 MetaboFlow 代码对口
412+
413+ ### 10.1 关键文件映射
414+
415+ | MFSL 数据 | MetaboFlow 代码 | 说明 |
416+ | -----------| -----------------| ------|
417+ | deduplicated/* .msp | ` annot-worker/app/matchms_engine.py ` | matchms 加载 MSP,按 metadata 标签过滤,计算余弦相似度 |
418+ | compound_metadata.csv | ` xcms-worker/R/annotation_ms1.R ` | Level 3 精确质量匹配 |
419+ | compound_metadata.csv | ` annotation_orchestrator.py ` Step 4 | 元数据富集(InChIKey → KEGG/HMDB/通路) |
420+ | MSP 标签字段 | ` AnnotationParams.tag_filter ` | 前端标签过滤传给后端 |
421+ | spectral_metadata.csv | 前端统计展示 | 不参与 E2E 搜索流程 |
422+
423+ ### 10.2 标签字段名对齐
424+
425+ MSP 文件中的字段名必须与 matchms 解析后的 metadata key 一致:
426+
427+ | MSP 字段行 | matchms metadata key | MetaboFlow 模型字段 |
428+ | -----------| ---------------------| -------------------|
429+ | ` Chemical_class: alkaloid ` | ` spectrum.metadata["chemical_class"] ` | ` TagFilter.compound_class ` (需改名对齐) |
430+ | ` Application: pharmaceutical ` | ` spectrum.metadata["application"] ` | ` TagFilter.application ` (新增) |
431+ | ` Sample: human ` | ` spectrum.metadata["sample"] ` | ` TagFilter.organism ` (需改名对齐) |
432+ | ` Confidence: experimental ` | ` spectrum.metadata["confidence"] ` | ` TagFilter.confidence ` |
433+ | ` Instrument: orbitrap ` | ` spectrum.metadata["instrument"] ` | ` TagFilter.instrument ` |
434+ | ` Reg_lists: eu_watch_list ` | ` spectrum.metadata["reg_lists"] ` | ` TagFilter.reg_lists ` (新增) |
435+
436+ ** 需要修改 MetaboFlow 的 ` TagFilter ` 模型** :将 ` compound_class ` 改为 ` chemical_class ` ,` organism ` 改为 ` sample ` ,新增 ` application ` 和 ` reg_lists ` 。
437+
438+ ### 10.3 compound_metadata.csv 字段与 AnnotationHit 对齐
439+
440+ | compound_metadata 字段 | AnnotationHit 模型字段 | 说明 |
441+ | ----------------------| ---------------------| ------|
442+ | name | compound_name | ✅ 已对齐 |
443+ | inchikey | inchikey | ✅ 已对齐 |
444+ | formula | formula | ✅ 已对齐 |
445+ | smiles | (缺失,需新增) | 结构展示需要 |
446+ | kegg_id | kegg_id | ✅ 已对齐 |
447+ | hmdb_id | hmdb_id | ✅ 已对齐 |
448+ | chemical_class | (缺失,需新增) | 结果标签展示 |
449+ | application | (缺失,需新增) | 结果标签展示 |
0 commit comments