feat(validation): add SQLModel database models and fix relationships

This commit is contained in:
2026-03-19 10:27:20 +08:00
parent d0cdf50ed5
commit d18133ce16
6 changed files with 2091 additions and 13 deletions

157
PLAN-.md Normal file
View File

@@ -0,0 +1,157 @@
# `macro_split` 重构为可安装包 `macro_lactone_toolkit` 的实施计划
## Summary
采用“渐进式重构,不推倒重写”的方案:保留仓库里已经可用的 12-20 元环识别、通用编号、侧链 BFS 提取和 dummy 原子思路,删除或降级 16 元环专用路径,把核心能力统一收敛到一个正式可安装、可测试、可 CLI 调用的包。
本次重构完成后,项目要满足这几个结果:
- 可以作为正式 Python 包安装和导入,主包名为 `macro_lactone_toolkit`
- 默认自动识别 12-20 元有效大环内酯;也允许显式传 `ring_size`
- 支持环编号和侧链裂解
- 裂解结果同时提供“带位置编号 dummy”与“普通 `*` dummy”两套 SMILES且都能被 RDKit 读取保存
-`pixi` 管理环境和测试
- 先执行 `git pull --ff-only` 同步远端,再开始任何代码改动
## Key Changes
### 1. 仓库与包结构正规化
- 第一动作不是改代码,而是在仓库根目录执行:
- `git status --short`
- `git pull --ff-only`
- 将当前直接放在顶层 `src/` 下的运行时代码,改成标准包布局:`src/macro_lactone_toolkit/`
- 不保留 `src.*` 兼容层README、测试、脚本、入口点全部切到新导入路径
- `pyproject.toml` 改为标准 setuptools `src` layout 配置,修正:
- 包发现
- 项目名与版本元数据
- console scripts
- pytest 配置
- `pixi.toml` 统一为 Python 3.12,并支持至少:
- `osx-arm64`
- `linux-64`
- `pixi.toml` 补齐测试依赖和常用任务:
- `test`
- `lint`(只做检查,不自动改写文件)
- `smoke-import`
- README 中所有 `from src...` 示例全部替换为 `from macro_lactone_toolkit...`
### 2. 统一核心领域模型与 API
`ring_visualization.py` 的通用逻辑和参考脚本的编号思路为基础重构出清晰边界的核心模块避免“16 元环专用”和“12-20 元环通用”并存。
公开 API 统一为:
- `macro_lactone_toolkit.MacroLactoneAnalyzer`
- `macro_lactone_toolkit.MacrolactoneFragmenter`
- `macro_lactone_toolkit.RingNumberingResult`
- `macro_lactone_toolkit.SideChainFragment`
- `macro_lactone_toolkit.FragmentationResult`
行为约定固定如下:
- `MacroLactoneAnalyzer`
- 负责识别 12-20 元环
- 验证环上是否存在有效内酯酯键
- 返回所有命中的有效环尺寸
- `MacrolactoneFragmenter`
- 默认自动识别有效环尺寸
- 若检测到 0 个有效环,抛出明确异常
- 若检测到多个有效环尺寸,默认抛出“歧义异常”,要求调用者显式传 `ring_size`
- 若调用者传了 `ring_size`,则只处理该环
- `RingNumberingResult`
- 至少包含:`ring_size``ring_atoms``ordered_atoms``carbonyl_carbon_idx``ester_oxygen_idx``atom_to_position``position_to_atom`
- `SideChainFragment`
- 至少包含:`parent_id``cleavage_position``attachment_atom_idx``fragment_smiles_labeled``fragment_smiles_plain``atom_count``molecular_weight`
- `FragmentationResult`
- 至少包含:母分子信息、选定环尺寸、编号结果、所有碎片、错误/警告信息
异常策略固定为:
- `MacrolactoneError`
- `MacrolactoneDetectionError`
- `AmbiguousMacrolactoneError`
- `RingNumberingError`
- `FragmentationError`
### 3. 编号与裂解算法收敛
编号逻辑以“通用 12-20 元环”作为唯一正式实现,不再让旧的 16 元环 `ring_numbering.py` 充当主入口。
- 编号规则固定:
- 位置 1 = 环上的内酯羰基碳
- 位置 2 = 环上的酯键氧
- 位置 3-N = 沿确定方向依次编号剩余环原子
- 编号实现使用统一入口,不能再出现批处理脚本内部偷偷调用 `[r16]` 专用函数的情况
- 自动识别时,先找所有 12-20 元环,再验证该环是否为有效大环内酯
- 侧链识别统一用“环原子邻居中不在环内的原子即侧链起点”
- 侧链提取统一用 BFS只沿非环原子扩展
- dummy 原子输出固定两套:
- `fragment_smiles_labeled`:带位置编号 dummy例如 `[5*]`
- `fragment_smiles_plain`:普通 `*`
- dummy 与连接原子的键型必须保留原始键型,不能强制都变成单键
- 所有裂解结果必须通过 RDKit round-trip
- `Chem.MolFromSmiles(...)` 成功
- `Chem.MolToSmiles(...)` 可再次序列化
### 4. CLI、批处理与现有脚本归并
交付范围包含正式 CLI不再依赖散乱脚本作为主要入口。
CLI 设计固定为 3 个命令:
- `macro-lactone-toolkit analyze`
- 输入单个 SMILES 或 CSV
- 输出有效环尺寸、是否歧义、选中的环尺寸
- `macro-lactone-toolkit number`
- 输入单个 SMILES
- 输出编号结果 JSON
- `macro-lactone-toolkit fragment`
- 输入单个 SMILES 或 CSV
- 输出碎片 JSON/CSV包含 labeled/plain 两套 SMILES
批处理行为固定为:
- CSV 默认读取 `smiles`
- 可选 `id` 列;未提供则自动生成
- 自动识别歧义分子时:
- 默认跳过并记录错误
- 显式传 `--ring-size` 时按指定环处理
-`scripts/` 中保留价值的逻辑迁入正式 CLI剩余脚本改成薄封装或标记为 legacy不再承担核心实现
## Test Plan
必须用 `pixi` 跑完整验证,至少覆盖下面这些场景:
- 包安装与导入
- `pixi run python -c "import macro_lactone_toolkit"`
- `pixi run pytest`
- 环识别
- 单一有效环尺寸的 12、14、16、20 元环样例
- 无效分子
- 无内酯键分子
- 多有效环尺寸分子,确认抛出 `AmbiguousMacrolactoneError`
- 编号
- 位置 1 必须是羰基碳
- 位置 2 必须是酯键氧
- 编号范围必须连续覆盖 `1..N`
- 同一分子多次运行结果一致
- 裂解
- 无侧链位置返回空列表
- 有侧链位置返回碎片
- `fragment_smiles_labeled``fragment_smiles_plain` 都能被 RDKit 成功读取
- labeled dummy 保留位置号
- dummy 键型与原键型一致
- CLI
- `analyze``number``fragment` 的基本 smoke test
- CSV 批处理
- 歧义分子跳过与错误日志行为
- 回归
- 现有 splicing engine 若继续保留,至少保留一个 dummy 拼接回组装测试,确保 labeled dummy 方案可持续扩展
## Assumptions
- `git pull` 使用 `--ff-only`,避免在重构开始前引入不透明 merge commit
- 本次不保留 `src.*` 导入兼容层,全面切换到 `macro_lactone_toolkit`
- 本次把“正式库 API + 正式 CLI + pixi 测试”作为主交付notebooks 只做参考,不作为正式接口
- 发现多个有效大环尺寸时,默认视为歧义并失败,不自动猜测
- 继续使用 RDKit 作为唯一结构解析与序列化基础