6.6 KiB
6.6 KiB
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 --shortgit pull --ff-only
- 将当前直接放在顶层
src/下的运行时代码,改成标准包布局:src/macro_lactone_toolkit/ - 不保留
src.*兼容层;README、测试、脚本、入口点全部切到新导入路径 pyproject.toml改为标准 setuptoolssrclayout 配置,修正:- 包发现
- 项目名与版本元数据
- console scripts
- pytest 配置
pixi.toml统一为 Python 3.12,并支持至少:osx-arm64linux-64
pixi.toml补齐测试依赖和常用任务:testlint(只做检查,不自动改写文件)smoke-import
- README 中所有
from src...示例全部替换为from macro_lactone_toolkit...
2. 统一核心领域模型与 API
以 ring_visualization.py 的通用逻辑和参考脚本的编号思路为基础,重构出清晰边界的核心模块,避免“16 元环专用”和“12-20 元环通用”并存。
公开 API 统一为:
macro_lactone_toolkit.MacroLactoneAnalyzermacro_lactone_toolkit.MacrolactoneFragmentermacro_lactone_toolkit.RingNumberingResultmacro_lactone_toolkit.SideChainFragmentmacro_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- 至少包含:母分子信息、选定环尺寸、编号结果、所有碎片、错误/警告信息
异常策略固定为:
MacrolactoneErrorMacrolactoneDetectionErrorAmbiguousMacrolactoneErrorRingNumberingErrorFragmentationError
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 作为唯一结构解析与序列化基础