Skip to content

Repository files navigation

chem_summarizer v0.1.0alpha

从 Office 文档(PPT/PPTX/DOCX)和 ChemDraw 文件(CDX/CDXML)中提取化学结构,生成带分子表与反应步骤的 Markdown 摘要。

Extract chemical structures from Office documents and ChemDraw files, then generate Markdown summaries with molecule tables and reaction steps.

⚠️ 声明

  1. 本项目包含 AI 生成的代码。
  2. 部分功能正在开发中,敬请期待。

License: MIT Python 3.9+ Development Status


概述

chem_summarizer 是一个面向化学/药物研发工作者的命令行工具,用于把含有 ChemDraw 嵌入对象的 Office 文档以及独立的 ChemDraw 文件批量转换成结构化的 Markdown 摘要。它直接解析 ChemDraw 的私有二进制格式(CDX),无需安装 ChemDraw、无需调用 COM 组件或 obabel,因此可以在没有 Chemistry 软件的环境下运行。

支持的输入格式

格式 处理路径 依赖
.cdx CDX 二进制解析器 → RDKit SMILES rdkit
.cdxml XML 解析 → RDKit SMILES rdkit
.pptx ZIP 解压 → OLE 提取嵌入 CDX rdkit + olefile
.docx ZIP 解压 → OLE 提取嵌入 CDX rdkit + olefile
.ppt PowerPoint COM 转 PPTX → 同 .pptx Windows + PowerPoint(见 .ppt 文件支持

主要特性

  • 自带 CDX 二进制解析器:直接读取 ChemDraw 二进制流(VjCD 标识),解码 Document / Page / Fragment / Node / Bond / Text / Graphic / Scheme / Step 等对象与属性标签,不依赖 ChemDraw COM。
  • 零外部化学软件依赖:除 Python + RDKit + olefile 外不需要任何化学软件;CDX/CDXML 解析全部在进程内完成。
  • 反应识别:解析 ChemDraw 的 Scheme / Step 结构,提取原料、产物、箭头上方条件、下方产率,并通过箭头图形属性判断反应类型(done / retro / design / failed)。
  • Morgan 指纹相似度过滤:对多片段反应使用 Morgan 半径 2、2048 位的 Tanimoto 相似度筛选最优原料-产物对,过滤标签展开产生的伪片段。
  • 标签展开三级优先级:① 手工 LABEL_EXPAND_SMILES 表(权威)→ ② CDX 内嵌 Fragment → ③ ChemDraw 官方 nicknames.json(甲基帽约定)→ ④ 元素解析。
  • 文献引用识别:基于 Endnote 风格期刊缩写关键词 + 4 位年份双重信号检测,自动插入 [引用] 标签并汇总到“参考文献”小节。
  • 跨平台路径处理:支持 WSL2 与 Windows 原生路径互转,.ppt 文件可从 WSL2 调用 powershell.exe 完成转换。

环境要求

  • Python ≥ 3.9(支持 3.9 / 3.10 / 3.11 / 3.12 / 3.13)
  • rdkit ≥ 2022.03 — 分子图构建、SMILES/InChI 生成、Morgan 指纹
  • olefile ≥ 0.46 — 从 Office ZIP 中解析 OLE 复合文档以提取嵌入的 CDX
  • .ppt 转换(可选):需要 Windows + 已安装 PowerPoint,通过 powershell.exe 调用 PowerPoint COM 自动化(Presentations.Open / SaveAs(..., 24))完成 .ppt → .pptx 转换

非 Windows 环境(纯 Linux / macOS)不支持 .ppt 输入;.cdx / .cdxml / .pptx / .docx 均可正常使用。


安装

源码托管于 GitHub。下面给出 Windows 原生与 WSL2 两种环境的安装方式。

Windows(native)

在 PowerShell 或 cmd 中:

# 1. 克隆仓库
git clone https://github.com/HX0922/chem_summarizer.git
cd chem_summarizer

# 2. 创建虚拟环境(推荐)
python -m venv .venv
.venv\Scripts\activate

# 3. 安装 rdkit(rdkit 在 PyPI 上由 rdkit 轮子提供)
pip install rdkit>=2022.03 olefile>=0.46

# 4. 以可编辑模式安装本包(同时注册 chem-summarizer 命令)
pip install -e .

安装完成后可直接调用:

chem-summarizer --version

WSL2(Windows Subsystem for Linux)

在 WSL2 的 bash 中:

# 1. 克隆仓库
git clone https://github.com/HX0922/chem_summarizer.git
cd chem_summarizer
# 若在 WSL2 ext4 开发(推荐,性能更好):
# cd ~/projects/chem_summarizer

# 2. 创建虚拟环境
python3 -m venv .venv
source .venv/bin/activate

# 3. 安装依赖与本包
pip install rdkit>=2022.03 olefile>=0.46
pip install -e .

在 WSL2 中处理 .ppt 文件时,本工具会自动通过 wslpath -w / UNC 路径 (\\wsl.localhost\<distro>\...) 把 Linux 路径转换为 Windows 路径,再调用 powershell.exe 启动 PowerPoint COM。要求 WSL2 所在的 Windows 主机已安装 PowerPoint。


使用方法

CLI

通过 pyproject.toml 声明的 console_scripts,安装后提供 chem-summarizer 命令:

chem-summarizer file1.pptx file2.cdxml file3.docx file4.cdx

也可以用模块方式调用(无需安装步骤,适合开发期):

python -m chem_summarizer.summarizer file.pptx

命令行参数:

参数 说明
files 一个或多个输入文件路径(.ppt / .pptx / .docx / .cdx / .cdxml
--version 打印版本号 chem_summarizer 0.1.0 后退出

每个输入文件会在其同目录下生成 {原名}_summary.md(后缀由 config.py 中的 OUTPUT_SUFFIX 控制)。运行时会在临时目录 chem_summarizer_* 中暂存提取出的 CDX,处理完成后自动清理。

控制台示例输出:

=== report.pptx ===
  → /path/to/report_summary.md
  Locations: 12, SMILES: 34 (unique: 21), Reactions: 5

作为 Python 库使用

核心函数均在 chem_summarizer 包中导出:

from chem_summarizer import (
    process_file,            # 处理单个文件并生成 Markdown
    parse_cdx_binary,        # 解析 CDX 二进制数据(返回文档对象树)
    parse_cdxml,             # 解析 CDXML 文件(返回 dict: text/molecules/reactions/fragment_count)
    parse_reaction_steps,    # 从 CDXML ElementTree 提取反应步骤
    extract_cdx_from_zip,    # 从 Office ZIP 中提取嵌入的 CDX 到指定目录
    build_fragment_smiles,   # 把单个 <fragment> 节点转换为 SMILES
)

一键处理示例:

from chem_summarizer import process_file

# 在同目录下生成 report_summary.md
process_file("report.pptx")

直接解析 CDX 二进制并拿到分子/反应:

from chem_summarizer import parse_cdx_binary
from chem_summarizer.summarizer import process_cdx_via_parser

result = process_cdx_via_parser("drawing.cdx")
print(result["molecules"])     # OrderedDict: {canonical_smiles: {"inchi": "..."}}
print(result["reactions"])     # list[dict]: reactants/products/conditions/yield_text/arrow_type
print(result["text"])          # 排除原子标签后的文本
print(result["fragment_count"])

.ppt 文件支持

.ppt(旧版二进制格式)无法直接解析,需要先转换为 .pptx,由 ppt_to_pptx()chem_summarizer/summarizer.py:779)完成:

  • Windows:原生支持。直接调用本机的 powershell.exe 启动 PowerPoint COM:$ppt = New-Object -ComObject PowerPoint.Application,打开后 SaveAs($out, 24) 另存为 PPTX,转换超时 120 秒。
  • WSL2:支持。自动通过 wsl_to_win() 把 WSL 路径转为 Windows 路径(/mnt/c/...C:\...,必要时通过 wslpath -w\\wsl.localhost\<distro>\... UNC 路径),再调用宿主 Windows 上的 powershell.exe
  • 非 Windows(纯 Linux / macOS):不支持 .ppt。请先在 Windows/PowerPoint 中另存为 .pptx,或用 LibreOffice 等工具转换后再处理。

尝试在纯 Linux 上处理 .ppt 会得到 PPT conversion failed 的提示。


配置

所有可调参数集中在 chem_summarizer/config.py,可直接编辑该文件,或通过环境变量覆盖 Nicknames 路径。

环境变量

变量 作用 默认值
CHEM_SUMMARIZER_NICKNAMES_DIR 覆盖 ChemDraw Nicknames 目录搜索路径(用于 generate_nicknames.py 重新生成 nicknames.json 未设置时使用 NICKNAMES_SEARCH_PATHS 中的两条默认路径

默认 Nicknames 搜索路径(config.py):

NICKNAMES_SEARCH_PATHS = [
    Path("C:/ProgramData/RevvitySignalsSoftware/ChemDrawApplications/ChemDraw/ChemDraw Items/Nicknames"),
    Path("/mnt/c/ProgramData/RevvitySignalsSoftware/ChemDrawApplications/ChemDraw/ChemDraw Items/Nicknames"),
]

config.py 中的阈值

参数 默认值 作用
SIM_THRESHOLD_MULTI 0.25 多对多反应步骤中,Morgan Tanimoto 相似度低于此值的原料-产物对会被丢弃
SIM_THRESHOLD_SINGLE 0.15 1:1 反应步骤的结构相似度下限,低于此值视为误识别
HA_RATIO_MAX 3.0 原料/产物重原子数比值上限,比值超过此值或低于 1/3 的反应被跳过
MIN_CARBONS 6 碳原子数低于此值的片段不计入有效分子(过滤小分子/离子)
OUTPUT_SUFFIX "_summary.md" 输出 Markdown 文件名的后缀
CITATION_JOURNAL_KEYWORDS 见源码 用于文献检测的 Endnote 风格期刊缩写关键词列表(ACS / RSC / Wiley / Nature / Cell / Elsevier / Springer / 中国化学期刊等)

label_tables.py 中的标签表

  • ELEMENT_SYMBOLS:周期表元素集合(大小写不敏感匹配)。
  • EXPANDABLE_LABELS:标签 → 主元素映射(如 OMe → ONHBoc → N),用于 CDXML 解析器回退与 CDX 元素解析。包含占位符 R/R1/R2/R3 → CX/Y/Z → OPG → CLG → O
  • LABEL_EXPAND_SMILES:手工核对的标签 → SMILES 展开表(权威优先级最高),覆盖常见羰基/含硫/含硅/卤代/烷基/芳基/含氧/含氮/保护基/有机金属等缩写。
  • nicknames.json:由 generate_nicknames.py 从 ChemDraw 官方 Nicknames 目录生成,运行时由 get_nickname_table() 懒加载。

输出格式

生成的 *_summary.md 按以下顺序组织:

  1. 文件头:文件名、类型、大小、提取日期、CDX 对象数、分子片段数、有效分子数。
  2. 📄 文本内容(按位置):按 Slide / 段落 分组,包含 Office 原文与每个 CDX 对象的 [CDX] 文本及 [分子] SMILES 列表;文本中的文献会自动加 [引用] 标签。
  3. ⚗️ 反应 (N 步):四列表格,箭头类型映射为 done / retro / design / failed / -
  4. ⚛️ 全分子对照表 (N 个)SMILES | InChI 两列表,按 SMILES 排序去重。
  5. 📚 参考文献 (N 条):从全部 [引用] 文本中用正则抽取“期刊名 + 年份 + 卷 + 页码”,去重排序。

示例输出片段

# report.pptx — 化学信息摘要

**文件类型**: .pptx  |  **大小**: 342 KB  |  **提取日期**: 2026-07-15
**CDX 对象**: 8  |  **识别分子片段**: 23  |  **有效分子**: 15

---
## 📄 文本内容(按位置)

### Slide 1

Suzuki 偶联合成苯联吡啶 [引用] J. Am. Chem. Soc. 2021, 143, 1024

  [CDX] Pd(PPh3)4, K2CO3, dioxane/H2O, 80 °C
  产率: 85%

  [分子]
  `c1ccc(-c2ccccc2)cc1`

---
## ⚗️ 反应 (2 步)

| 原料 | 条件 / 产率 | 产物 | 反应类型 |
|:--|:--|:--|:--:|
| `Brc1ccccc1` | Pd(PPh3)4, K2CO3<br>产率: 85% | `c1ccc(-c2ccccc2)cc1` | done |

---
## ⚛️ 全分子对照表 (15 个)

| SMILES | InChI |
|:--|:--|
| `Brc1ccccc1` | InChI=1S/C6H5Br/c7-6-4-2-1-3-5-6/h1-5H |
| `c1ccc(-c2ccccc2)cc1` | InChI=1S/C12H10/c1-3-7-11(8-4-1)12-9-5-2-6-10-12/h1-10H |

---
## 📚 参考文献 (1 条)

- J. Am. Chem. Soc. 2021, 143, 1024

箭头类型映射:Solid/FullHead/Bold → doneHollow/RetroSynthetic → retroAngle/Dashed/NoHead/Wavy/Equilibrium → designCrossed → failedDipole → -


项目结构

chem_summarizer/
├── chem_summarizer/                # 主包
│   ├── __init__.py                 # 包入口,导出公共 API 与 __version__
│   ├── summarizer.py               # 主逻辑:CDX 二进制解析、Office 提取、Markdown 生成、CLI main()
│   ├── config.py                   # 配置:Nicknames 路径、阈值、引用期刊关键词、OUTPUT_SUFFIX
│   ├── label_tables.py             # 标签查找表(周期表、缩写→元素、缩写→SMILES、nickname 加载)
│   └── nicknames.json              # ChemDraw 官方 nickname → SMILES 映射(运行时懒加载)
├── generate_nicknames.py           # 从 ChemDraw Nicknames 目录重新生成 nicknames.json
├── pyproject.toml                  # 包元数据、依赖、console_scripts 入口
├── requirements.txt                # pip 依赖(rdkit>=2022.03, olefile>=0.46)
├── LICENSE                         # MIT (Copyright (c) 2026 HX0922)
├── .gitignore                      # 忽略 __pycache__/、*_summary*.md 等
└── README.md

限制

  • CDX 解析:仅解码已知对象标签与属性(0x0402 元素、0x0600 键级、0x0604/0x0605 键端点、0x0700 文本、0x0C0x 反应引用、0x8021 箭头等)。未知属性会被跳过;嵌套深度超过 1000 层会报错以防损坏文件。
  • .ppt 输入:必须依赖 Windows + PowerPoint COM;纯 Linux/macOS 不支持。
  • 占位符标签回退EXPANDABLE_LABELS 中的通用占位符 X / Y / Z 默认解析为 OR / R1 / R2 / R3 / PG 默认解析为 CLG 默认 O。这些是启发式默认值,可能与作者本意不符。
  • 反应识别:仅识别 ChemDraw 中显式绘制的 Scheme/Step;未绘制箭头/未分组到 Step 的结构不会进入反应表。重原子数比 > 3.0 或 Morgan 相似度 < 阈值的反应会被过滤。
  • 最小分子过滤:碳原子数 < 6 的片段(MIN_CARBONS)不计入分子表,可能导致小分子试剂/溶剂被忽略。
  • 引用抽取:依赖正则 期刊名 + 4 位年份 + 卷 + 页码 格式;不符合该格式的引用可能被遗漏或截断。

开发

重新生成 nickname 表

nicknames.jsongenerate_nicknames.py 从 ChemDraw 安装目录下的官方 Nicknames 文件夹(每个 .cdxml 对应一个 nickname 的 SMILES 定义)生成:

# 方式 A:使用 config.py 中的 NICKNAMES_SEARCH_PATHS 自动定位
python generate_nicknames.py

# 方式 B:显式指定 Nicknames 目录
python generate_nicknames.py "C:\ProgramData\RevvitySignalsSoftware\ChemDrawApplications\ChemDraw\ChemDraw Items\Nicknames"

# 方式 C:用环境变量覆盖搜索路径
CHEM_SUMMARIZER_NICKNAMES_DIR="/mnt/c/ProgramData/.../Nicknames" python generate_nicknames.py

脚本会遍历目录下所有 *.cdxml,解析其中的 <fragment> 节点,调用 build_fragment_smiles() 生成 SMILES,写入 chem_summarizer/nicknames.json(与运行时 get_nickname_table() 读取的路径一致)。无法解析的条目会打印到 stderr(默认仅显示前 5 条错误)。

直接查看标签表统计

python -m chem_summarizer.label_tables
# LABEL_EXPAND_SMILES: N entries
# EXPANDABLE_LABELS:   M entries
# NICKNAME_TABLE:      K entries
# ELEMENT_SYMBOLS:     118 elements

License

MIT License — Copyright (c) 2026 HX0922。详见 LICENSE

仓库地址:https://github.com/HX0922/chem_summarizer

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages