# MacFrag **Repository Path**: coding_playground/MacFrag ## Basic Information - **Project Name**: MacFrag - **Description**: 在李洪林教授课题组的MacFrag上增加了一些新的功能。核心算法未改变。 - **Primary Language**: Python - **License**: Not specified - **Default Branch**: 0.2.0 - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-12-18 - **Last Updated**: 2026-07-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: 分子片段 ## README # MacFrag MacFrag 是一种高效的分子片段化方法,能够快速分割大规模分子,并生成更符合 "Rule of Three"(三规则)的多样化片段。 **参考文献:** Yanyan Diao, Feng Hu, Zihao Shen, Honglin Li*. MacFrag: segmenting large-scale molecules to obtain diverse fragments with high qualities. Bioinformatics, 2023. 39(1) : btad012 **开发维护团队:** 华东理工大学药学院 李洪林教授课题组,中国上海 200237 **课题组网站:** http://lilab-ecust.cn/ **Github地址:** https://github.com/yydiao1025/MacFrag **原项目协议:** 未知 **修改版协议:** MIT License(仅适用于本次修改部分,原项目代码的版权归原作者所有) --- ## 贡献说明 ### 原作者(MacFrag核心算法) MacFrag 分子片段化算法及其核心代码由以下作者开发: - **Yanyan Diao, Feng Hu, Zihao Shen, Honglin Li*** - **论文发表:** Bioinformatics, 2023. 39(1) : btad012 - **核心贡献:** - BRICS 键断裂规则定义 - 分子片段化核心算法实现 - 大规模分子快速分割能力 ### 后续改进(本次修改) 以下功能为后续添加,非原作者实现: - **Excel / CSV 文件输入支持**:`MacFrag.py` 新增对 `.xlsx` 和 `.csv` 文件的支持,交互式选择 Project、Compound ID、Molecular Formula、Molecular Weight 的来源字段(可选择表格中任意列或自定义输入),使用 RDKit 生成规范化 SMILES 进行去重(忽略盐/溶剂),保留同位素差异,输出到 `.smi` 和 `.csv` 文件 - **SMI 文件去重支持**:`.smi` 文件输入时也执行相同的去重步骤(规范化 SMILES、去除盐/溶剂、保留同位素差异) - **片段库CSV生成**:片段分割后自动生成 `fragments.csv`,片段命名为 `{Project}_frag{序号}`(序号零对齐),并自动去重 - **并行计算优化**:使用 `concurrent.futures.ThreadPoolExecutor()` 并行处理 SMILES 规范化,加速处理速度 - **流式/分批处理**:Excel 文件使用 `openpyxl` 流式读取,CSV 文件使用 `pandas` 分批读取(`chunksize`),SMI 文件逐行读取,分批处理,内存占用可控,支持处理超大文件 - **详细日志输出**:在 Excel / CSV 处理、去重、片段库生成、交互式字段选择等关键步骤增加详细日志,便于排查命名或去重问题 - **CSV 格式修复**:修复了 Windows 环境下 CSV 文件每行之间出现空行的问题(统一使用 `\n` 换行符) - **片段可视化工具**:新增 `visualize_fragments.py`,可将片段结构渲染为 HTML 可视化页面 - **匹配算法修复**:修复 `match_fragments.py` 中直接匹配算法的错误匹配问题,使用 SMARTS 模式保留连接点通配符,确保多连接点片段(如 `[14*]c1cc([14*])cc(F)c1`)能正确识别取代位置,避免误匹配 - **代码结构优化**:提取公共工具函数(日志输出、安全文件操作),为所有函数添加类型注解和文档字符串,修复 PEP8 格式问题 - **统一错误处理和日志输出**:三个脚本(`MacFrag.py`、`match_fragments.py`、`visualize_fragments.py`)统一使用 `logging` 模块,添加文件 I/O 异常捕获和详细上下文日志,便于排查问题 - **代码区域标注**:在源代码中标明原作者代码和后续改进代码的界限,区分版权归属 - **核心分支详细日志**:`write_file` 函数添加完整的参数日志、分支路由标记、分子处理进度日志、后处理流程日志,便于定位报错位置 - **README 文档更新**:补充新增功能说明 --- ## 1. 使用方法 ### 基本命令格式: ```bash python MacFrag.py -i 输入文件 -o 输出路径 -maxBlocks 最大块数 -maxSR 最大环大小 -asMols 是否输出分子对象 -minFragAtoms 最小原子数 ``` ### 使用示例: #### 输入 SMILES 文件(.smi): 当输入为 `.smi` 文件时,脚本会自动执行以下流程: 1. 读取 SMILES 文件 2. 使用 RDKit 生成规范化 SMILES 并去重(忽略盐/溶剂,保留同位素差异) 3. 进行片段分割,生成 `{Project}_fragment.smi`(含连接点标记) 4. 将连接点替换为H原子,生成规范化SMILES并去重,输出 `{Project}_fragment_h.smi` 5. 基于 `_fragment_h.smi` 生成片段库 CSV 文件(片段命名规则为 `{Project}_frag{序号}`) ```bash python MacFrag.py -i examp.smi -o ./ -maxBlocks 6 -maxSR 8 -asMols False -minFragAtoms 1 ``` #### 输入 Excel 文件(.xlsx): 当输入为 `.xlsx` 文件时,脚本会自动执行以下流程: 1. 使用 `openpyxl` 流式读取 Excel 文件(每批 1000 行) 2. 交互式选择 Project、Compound ID、Molecular Formula、Molecular Weight 的来源字段(可选择 Excel 中任意列或自定义输入,显示列名和示例数据) 3. 使用 RDKit 将 SMILES 转换为分子对象,去除盐/溶剂片段,生成规范化 SMILES(并行处理) 4. 基于规范化 SMILES 去重(忽略盐/溶剂,保留同位素差异,保留最后出现的记录) 5. 保存规范化 SMILES 到同名 `.smi` 文件 6. 保存完整信息(Project、Compound ID、规范化 SMILES、Molecular Formula、Molecular Weight)到同名 `.csv` 文件 7. 进行片段分割,生成 `{Project}_fragment.smi`(含连接点标记) 8. 将连接点替换为H原子,生成规范化SMILES并去重,输出 `{Project}_fragment_h.smi` 9. 基于 `_fragment_h.smi` 生成片段库 CSV 文件(片段命名规则为 `{Project}_frag{序号}`) ```bash python MacFrag.py -i .xlsx -o ./ -maxBlocks -maxSR -asMols -minFragAtoms ``` #### 输入 CSV 文件(.csv): 当输入为 `.csv` 文件时(需包含 `SMILES` 列,逗号分隔,UTF-8 / UTF-8-BOM 编码),脚本会自动执行以下流程: 1. 读取 CSV 文件头部前 4 行作为示例数据,交互式选择 Project、Compound ID、Molecular Formula、Molecular Weight 的来源字段(可选择表格中任意列或自定义输入,显示列名和示例数据) 2. 使用 `pandas` 分批读取 CSV 文件(每批 1000 行,`chunksize`) 3. 使用 RDKit 将 SMILES 转换为分子对象,去除盐/溶剂片段,生成规范化 SMILES(并行处理) 4. 基于规范化 SMILES 去重(忽略盐/溶剂,保留同位素差异,保留最后出现的记录) 5. 保存规范化 SMILES 到同名 `.smi` 文件 6. 保存完整信息(Project、Compound ID、规范化 SMILES、Molecular Formula、Molecular Weight)到同名 `_normalized.csv` 文件(避免覆盖输入文件) 7. 进行片段分割,生成 `{Project}_fragment.smi`(含连接点标记) 8. 将连接点替换为H原子,生成规范化SMILES并去重,输出 `{Project}_fragment_h.smi` 9. 基于 `_fragment_h.smi` 生成片段库 CSV 文件(片段命名规则为 `{Project}_frag{序号}`) ```bash python MacFrag.py -i .csv -o ./ -maxBlocks -maxSR -asMols -minFragAtoms ``` > **说明:** CSV 输入的交互式字段选择、去重规则、并行计算、增量写入等特性与 Excel 输入完全一致,详见下方说明。 **性能优化特性:** | 特性 | 说明 | |------|------| | **流式读取** | Excel 使用 `openpyxl` 的 `read_only=True` 模式;CSV 使用 `pandas` 的 `chunksize` 分批读取,内存占用可控 | | **分批处理** | 每批处理 1000 行,处理完释放内存,支持处理超大文件 | | **并行计算** | 使用线程池并行处理 SMILES 规范化,充分利用多核 CPU | | **增量写入** | 输出 CSV 文件采用追加模式写入,避免一次性加载所有数据 | **CSV 输出列说明:** CSV 文件包含以下列,各列的来源可通过交互式界面选择: | CSV 列名 | 说明 | |----------|------| | `Project` | 项目编号,可选择表格中任意列或自定义输入相同值 | | `Compound ID` | 化合物编号,可选择表格中任意列或自定义输入相同值 | | `SMILES` | 规范化后的 SMILES(去除盐/溶剂) | | `Molecular Formula` | 分子式,可选择表格中任意列或自定义输入相同值 | | `Molecular Weight` | 分子量,可选择表格中任意列或自定义输入相同值 | **交互式字段选择说明:** 处理 Excel / CSV 文件时,脚本会依次询问每个字段的来源,交互界面如下: ``` ================================================== 请选择项目编号(Project)的来源: -------------------------------------------------- [0] 自定义输入(所有行使用相同值) [1] 项目名称/项目编号 示例: test/XY9876, test/XY9876 [2] 结构式 [3] 自定义编号 示例: AB12345, AB54321 ... -------------------------------------------------- 请输入序号选择字段,或直接输入项目编号(Project)值: ``` **操作方式:** - 输入数字 `0`:自定义输入(所有行使用相同值) - 输入数字 `1-n`:选择对应列作为字段来源 - 直接输入文字:作为自定义值(所有行使用相同值) **片段库输出说明:** 片段分割完成后,自动生成三个文件: | 文件类型 | 文件命名规则 | 说明 | |----------|-------------|------| | 原始 SMI | `{项目名称}_fragment.smi` | 原始片段库,包含连接点标记(如 `[4*]`、`[14*]`) | | H替换 SMI | `{项目名称}_fragment_h.smi` | 连接点替换为H原子后的片段库,规范化SMILES并去重 | | CSV 文件 | `{项目名称}_fragment.csv` | 基于 `_fragment_h.smi` 生成的片段库CSV | **生成流程:** 1. 片段分割生成 `{项目名称}_fragment.smi`(含连接点标记) 2. 将连接点替换为H原子,生成规范化SMILES并去重,输出 `{项目名称}_fragment_h.smi` 3. 基于 `_fragment_h.smi` 生成CSV文件,片段命名为 `{Project}_frag{序号}` **项目名称处理规则:** - 项目名称中的无效文件名字符(`\ / : * ? " < > |`)和空白字符统一替换为下划线 `_` - 首尾下划线自动去除 - 若项目名称为空,使用 `unknown` 作为默认名称 | CSV 列名 | 说明 | |----------|------| | `Fragment Name` | 片段名称,格式为 `{Project}_frag{序号}`,序号从 1 开始,根据片段总数零对齐 | | `SMILES` | 连接点替换为H原子后的规范化SMILES | **命名示例:** - 输入 `__excel.xlsx`(Project: ``),生成 `` 个片段 - 输出文件:`_fragment.smi`、`_fragment_h.smi`、`_fragment.csv` - 片段命名范围:`_frag0001` ~ `_frag` **Project 名称获取规则:** - 输入为 `.xlsx` 或 `.csv`:从生成的分子 CSV 中读取 Project 列 - 输入为 `.smi`:使用输入文件名(不含扩展名)作为 Project 名称 **去重规则:** | 规则 | 说明 | |------|------| | 基于规范化 SMILES | 使用 RDKit 的 `MolToSmiles(mol, canonical=True)` 生成规范化 SMILES,相同分子的不同表示形式会生成相同的规范化 SMILES | | 忽略盐/溶剂 | 使用 RDKit 的 `GetMolFrags()` 提取最大片段,去除盐离子和溶剂分子 | | 保留同位素差异 | 氘代等同位素标记会在规范化 SMILES 中保留,不同同位素形式视为不同分子 | | 保留最后出现 | 重复的规范化 SMILES 保留最后一条记录 | ### 参数说明: | 参数 | 缩写 | 必填 | 说明 | |------|------|------|------| | `-input_file` | `-i` | 是 | 输入文件路径,支持 `.smi`、`.sdf`、`.xlsx` 和 `.csv` 格式 | | `-output_path` | `-o` | 是 | 输出片段文件的路径(必须以 `/` 结尾) | | `-maxBlocks` | - | 是 | 片段包含的最大构建块数量 | | `-maxSR` | - | 是 | 仅切割最小 SSSR 环大小大于此值的环键 | | `-asMols` | - | 是 | `True` 或 `False`;若为 `True`,输出 `fragments.sdf` 文件;若为 `False`,输出 `fragments.smi` 文件 | | `-minFragAtoms` | - | 是 | 片段包含的最小原子数 | ### 日志输出: 脚本运行时会输出详细的处理日志,包括: - **函数入口参数**:`write_file` 函数记录所有输入参数(input_file, output_dir, maxBlocks, maxSR, asMols, minFragAtoms) - **分支路由标记**:每个文件类型分支(.xlsx/.csv/.smi/.sdf)入口都有明确的 `[分支路由]` 标记,未知文件类型使用 `ERROR` 级别日志 - **Excel / CSV 文件读取统计**(行数、列数、列名) - **交互式字段选择日志**(用户输入、选择的字段、字段来源配置) - **批次处理进度**(每批处理行数、有效/无效数量、当前唯一数量) - **分子处理进度**:每处理 100 个分子打印进度,记录累计片段数和 None 分子警告 - **SMILES 列统计**(空值数量、非空值数量、有效 SMILES 数量) - **去重统计**(去重前/后数量、删除重复数量) - **后处理流程**:H替换SMI生成、片段库CSV生成的开始/成功/失败状态 - **异常日志**:文件 I/O 异常、Project 提取失败、片段写入失败等均记录详细错误信息 - **输出文件信息**(路径、文件大小) ## 2. 源代码 `MacFrag.py` 是主程序源代码。用户可以自定义片段化规则或进行其他修改。 ### 代码区域划分: | 区域 | 范围 | 说明 | |------|------|------| | **后续改进代码** | 文件开头至第 723 行 | 新增功能:Excel / CSV 支持、交互式字段选择、SMILES 去重、片段库 CSV 生成、并行计算、流式处理等 | | **原作者代码** | 第 724 行至第 1091 行 | MacFrag 核心算法:BRICS 键断裂规则定义、分子片段化算法实现(版权归原作者所有) | | **后续改进代码** | 第 1092 行之后 | 片段库 CSV 生成、主函数入口等 | **代码区域标记:** - `【原作者代码开始】`:标记核心算法开始位置 - `【原作者代码结束】`:标记核心算法结束位置 ### 主要功能模块: 1. **SMILES 处理函数** (`process_smiles`):单个 SMILES 的规范化处理(解析、去盐、去氢、规范化) 2. **交互式字段选择函数** (`select_column_source`):通用交互式字段来源选择(支持选择表格列或自定义输入,显示示例数据) 3. **并行去重函数** (`deduplicate_smiles`):批量 SMILES 的并行规范化和去重 4. **分批处理函数** (`process_chunk`):批次 SMILES 的并行处理和增量去重 5. **Excel 处理模块** (`extract_smiles_from_excel`):从 Excel 文件中流式提取 SMILES 并去重,支持交互式字段选择 6. **CSV 处理模块** (`extract_smiles_from_csv`):从 CSV 文件中分批提取 SMILES 并去重,交互逻辑与 Excel 模块一致 7. **片段化核心** (`MacFrag`):基于 BRICS 算法进行分子片段化 8. **连接点H替换** (`generate_fragments_h_smi`):将片段中的连接点(如 `[4*]`、`[14*]`)替换为H原子,生成规范化SMILES并去重 9. **片段库CSV生成** (`generate_fragments_csv`):基于 `_fragment_h.smi` 将片段库转换为 CSV,自动去重并命名 10. **文件写入** (`write_file`):支持 `.smi`、`.sdf`、`.xlsx` 和 `.csv` 格式输入,`.smi` 和 `.sdf` 格式输出 ## 3. 其他文件说明 | 文件 | 说明 | |------|------| | `chembl28_mw500.smi` | 从 ChEMBL 数据库收集的分子量小于 500 的分子 | | `chembl28_mw500-1000.smi` | 从 ChEMBL 数据库收集的分子量在 500-1000 之间的分子 | | `time_compare.py` | 用于计算不同片段化程序运行时间的 Python 脚本 | | `test_sample.xlsx` | 示例 Excel 文件 | | `match_fragments.py` | 计算片段与化合物匹配关系的 Python 脚本 | | `visualize_fragments.py` | 生成片段-化合物关系卡片可视化 HTML 的 Python 脚本 | ### ChEMBL 数据集说明: 合并 `chembl28_mw500.smi` 和 `chembl28_mw500-1000.smi` 两个文件后,可获得 1,921,745 个分子量小于 1000 的分子,这些分子曾用于评估三种片段化程序生成的片段质量。 --- ## 4. 片段-化合物匹配与可视化 ### 4.1 匹配关系计算 `match_fragments.py` 用于计算片段库中每个片段来源于哪些化合物(一个片段可能来源多个化合物): ```bash python match_fragments.py \ --fragment-csv .csv \ --compound-csv .csv \ --output .json \ --algorithm direct ``` **参数说明:** | 参数 | 缩写 | 必填 | 说明 | |------|------|------|------| | `--fragment-csv` | `-f` | 是 | 片段库 CSV 文件路径 | | `--compound-csv` | `-c` | 是 | 化合物库 CSV 文件路径 | | `--output` | `-o` | 是 | 输出 JSON 文件路径 | | `--algorithm` | `-a` | 否 | 匹配算法:`direct`(直接匹配,使用SMARTS保留连接点通配符)或 `fingerprint`(指纹预过滤+SMARTS精确匹配),默认 `direct` | | `--threshold` | `-t` | 否 | fingerprint 算法的相似度阈值,默认 0.3 | **算法原理:** 匹配算法使用 SMARTS 模式保留片段中的连接点通配符(如 `[*]`),确保多连接点片段能正确识别取代位置: | 算法 | 说明 | |------|------| | **direct** | 直接对每个片段使用 SMARTS 模式进行子结构匹配,保留连接点的空间位置约束,避免错误匹配 | | **fingerprint** | 先使用 Morgan 指纹进行快速预过滤(移除连接点后的分子指纹),再对候选化合物使用 SMARTS 精确匹配,兼顾速度和准确性 | **连接点处理示例:** | 片段类型 | 原始 SMILES | 处理后 | 匹配效果 | |----------|-------------|--------|----------| | 单连接点 | `[4*]N1CC(O)(C(F)(F)F)c2cc(F)ccc21` | `[*]N1CC(O)(C(F)(F)F)c2cc(F)ccc21` | 正确匹配含该结构的化合物 | | 双连接点 | `[14*]c1cc([14*])cc(F)c1` | `[*]c1cc([*])cc(F)c1` | 仅匹配1,3-二取代氟苯,而非任意氟苯 | **输出 JSON 格式:** ```json { "metadata": { "total_fragments": , "total_compounds": , "total_matches": }, "fragments": [ { "id": "", "smiles": "", "smiles_normalized": "", "compound_count": } ], "compounds": [ { "id": "", "smiles": "", "molecular_formula": "", "molecular_weight": } ], "links": [ { "fragment_id": "", "compound_id": "" } ] } ``` ### 4.2 卡片可视化 `visualize_fragments.py` 基于匹配关系 JSON 文件生成 HTML 可视化页面: ```bash python visualize_fragments.py \ -i fragment_compound_matches.json \ -o fragment_cards.html ``` **参数说明:** | 参数 | 缩写 | 必填 | 说明 | |------|------|------|------| | `-input` | `-i` | 是 | 输入匹配关系 JSON 文件路径 | | `-output` | `-o` | 否 | 输出 HTML 文件路径,默认 `fragment_cards.html` | **可视化特性:** | 特性 | 说明 | |------|------| | **卡片布局** | 网格布局展示所有片段,每张卡片包含片段ID、分子结构、SMILES、关联化合物数 | | **分子结构渲染** | 使用 RDKit 预渲染为 SVG,凯库勒式显示(芳香环展开为交替单双键),零延迟加载 | | **分页功能** | 支持每页 10、20、50、100 个片段 | | **排序功能** | 支持按关联化合物数(多→少、少→多)或片段ID(A→Z、Z→A)排序 | | **搜索功能** | 输入片段ID关键词实时过滤卡片 | | **详情页面** | 点击卡片进入详情页面,展示大型分子结构、完整 SMILES、关联化合物列表(含结构、分子式、分子量) | **使用示例:** ```bash # 生成可视化页面 python visualize_fragments.py -i fragment_compound_matches.json -o fragment_cards.html # 在浏览器中打开 start fragment_cards.html ```