158 lines
6.6 KiB
Markdown
158 lines
6.6 KiB
Markdown
# `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 作为唯一结构解析与序列化基础
|