内容
# unimodpy
[](https://github.com/tacular-omics/unimodpy/actions/workflows/ci.yml)
[](https://pypi.org/project/unimodpy/)
[](https://pypi.org/project/unimodpy/)
[](LICENSE)
用于解析和查询 [UNIMOD](http://www.unimod.org/) 质谱修改数据库的Python库。
- 零核心依赖
- 捆绑的UNIMOD数据(1,552条记录)-开箱即用
- 类型化、不可变的数据模型(`py.typed` / PEP 561)
- TSV/CSV导出和往返OBO写入
- 可选的FastAPI / [模型上下文协议](https://modelcontextprotocol.io)服务器(`pip install unimodpy[server]`)
## 在线查看
#### [点击我!](https://tacular-omics.github.io/unimodpy/)
相同的数据库也可以作为托管的REST + MCP服务访问 - 请参见下面的[HTTP API和MCP服务器](#http-api-and-mcp-server)。
## 安装
```bash
pip install unimodpy
```
或使用 [uv](https://docs.astral.sh/uv/):
```bash
uv add unimodpy
```
需要Python 3.12+。无第三方依赖。
## 快速入门
```python
import unimodpy
# 加载捆绑的UNIMOD数据库(无需文件路径)
db = unimodpy.load()
# 按ID查找
acetyl = db.get_by_id(1) # 整数
acetyl = db.get_by_id("UNIMOD:1") # UNIMOD访问字符串
acetyl = db["UNIMOD:1"] # 下标表示法
# 按名称查找(不区分大小写)
phospho = db.get_by_name("Phospho")
# 跨名称、定义和同义词进行全文搜索
hits = db.search("glycosyl")
print(acetyl)
# UNIMOD:1 乙酰基
# 乙酰化。
# 公式 : C2H2O
# 质量 : +42.010565 Da (单) +42.0373 Da (平均)
# 位点 (9):
# 1: K @ 任意位置 [翻译后]
# ...
```
### 从unimod.org刷新
```python
# 下载最新的OBO并立即使用
db = unimodpy.load(refresh=True)
# 或仅下载文件
path = unimodpy.download() # ~/.cache/unimodpy/UNIMOD.obo
path = unimodpy.download("/my/dir/UNIMOD.obo") # 自定义目标
```
### 加载自定义文件
```python
db = unimodpy.load("/path/to/UNIMOD.obo")
# 或底层:
db = unimodpy.parse_obo("/path/to/UNIMOD.obo")
```
### 处理条目
每个`UnimodEntry`都是一个冻结的数据类:
```python
entry = db.get_by_name("Carbamidomethyl")
entry.id # int — UNIMOD访问编号
entry.name # str
entry.delta_mono_mass # float — 单同位素质量偏移(Da)
entry.delta_avge_mass # float — 平均质量偏移(Da)
entry.proforma_formula # str — 希尔符号表示法,例如 "C3H5NO"
entry.dict_composition # dict[str, int] — {"C": 3, "H": 5, "N": 1, "O": 1}
entry.synonyms # tuple[str, ...] — 替代名称
entry.specificities # tuple[Specificity, ...] — 位点/位置规则
for spec in entry.specificities:
print(spec.site) # Site枚举,例如 Site.C ("C")
print(spec.position) # Position枚举,例如 Position.ANYWHERE
print(spec.classification) # Classification枚举
for nl in spec.neutral_losses:
print(nl.mono_mass, nl.proforma_formula)
```
### 枚举
位点、位置和分类值是类型化的`StrEnum`成员:
```python
from unimodpy import Site, Position, Classification
ptm_sites = [
spec for spec in entry.specificities
if spec.classification == Classification.POST_TRANSLATIONAL
and spec.position == Position.ANYWHERE
]
```
### 导出到TSV/CSV
```python
# 将所有条目写入制表符分隔的文件
db.write_tsv("unimod.tsv")
# 或CSV
db.write_tsv("unimod.csv", delimiter=",")
# 独立函数
from unimodpy import write_tsv
write_tsv(db, "unimod.tsv")
```
TSV包括每个条目的一行。特定性被序列化为紧凑的`site:position:classification`摘要(例如 `K:Anywhere:Post-translational`)。
### 写回OBO格式
```python
# 往返:写条目回UNIMOD OBO格式
db.write_obo("out/UNIMOD.obo")
# 再解析 — 相同的条目数和字段值(包括引用)
db2 = unimodpy.parse_obo("out/UNIMOD.obo")
# 独立函数;传递原始标题行以实现忠实往返
from unimodpy import write_obo
write_obo(db, "out/UNIMOD.obo", header_lines=db.header_lines)
```
## HTTP API 和 MCP 服务器
可选的 `[server]` 额外功能提供了一个 FastAPI 应用,该应用通过 JSON REST API 和 [模型上下文协议](https://modelcontextprotocol.io) 公开相同的数据库,以便语言模型工具可以直接查询 UNIMOD。
```bash
pip install unimodpy[server]
uvicorn unimodpy.server.app:app --reload
```
### REST 端点
| 方法 & 路径 | 返回值 |
|---------------|---------|
| `GET /api/health` | 服务元数据和条目数。 |
| `GET /api/entries?limit=&offset=&include_hidden=` | 分页完整条目。 |
| `GET /api/entries/{id}` | 按ID(`1` 或 `UNIMOD:1`)获取一个完整条目。 |
| `GET /api/entries/by-name/{name}` | 按确切名称获取一个完整条目。 |
| `GET /api/search?q=&limit=` | 搜索结果为轻量级摘要。 |
默认情况下,隐藏的特定性(UNIMOD的`hidden=true`位点)被过滤掉;传递 `?include_hidden=true` 以保留它们。
完整条目有效载荷包括从 `definition_ref` 解析为 `{type, accession, value}` 对象的 `references` 和 `parent_id`(条目的UNIMOD层次结构父级)。搜索响应仅包含 `{id, accession, name, delta_mono_mass, proforma_formula}` 以降低令牌成本;对任何命中调用 `/api/entries/{id}` 以获取完整记录。
### MCP 服务器
相同的FastAPI应用在`POST /mcp`上安装了一个MCP端点,带有三个工具:
| 工具 | 目的 |
|------|---------|
| `get_by_id(id, include_hidden=False)` | 查找单个条目。 |
| `get_by_name(name, include_hidden=False)` | 精确名称查找。 |
| `search(query, limit=25)` | 全文搜索返回摘要。 |
工具响应使用MCP的结构化输出机制:服务器在`tools/list`中发出每个工具的`outputSchema`,并在`tools/call`上返回`structuredContent`(类型化的Pydantic实例)和`content`(文本备用),以便LLM客户端可以解析响应而无需重新读取JSON字符串。
将您的MCP感知客户端配置为指向 `http://localhost:8000/mcp`(或您部署应用程序的任何位置)。 Anthropic CLI示例:
```bash
claude mcp add unimod http://localhost:8000/mcp --transport http
```
## API 概述
| 符号 | 描述 |
|--------|-------------|
| `load(source=None, *, refresh=False)` | 加载数据库。无参数 -> 捆绑文件。`refresh=True` -> 先下载。 |
| `download(dest=None)` | 从unimod.org下载最新的OBO;返回`Path`。 |
| `parse_obo(path)` | 底层:解析路径上的任何OBO文件。 |
| `write_tsv(entries, path, *, delimiter)` | 将条目写入TSV(或CSV)文件。 |
| `write_obo(entries, path, *, header_lines)` | 将条目写回UNIMOD OBO格式。 |
| `UnimodDatabase` | 可迭代集合,包含 `get_by_id`、`get_by_name`、`search`、`write_tsv()`、`write_obo()`、`__getitem__`。还公开 `header_lines`。 |
| `UnimodEntry` | 一个修改项的冻结数据类。包含 `definition_ref`。 |
| `Specificity` | 一个位点/位置规则的冻结数据类。 |
| `NeutralLoss` | 一个中性损失的冻结数据类。 |
| `Site` | 氨基酸残基和末端的 `StrEnum`。 |
| `Position` | 序列位置约束的 `StrEnum`。 |
| `Classification` | 修改类别的 `StrEnum`。 |
## 开发
```bash
just install # 使用uv安装依赖
just lint # ruff检查
just format # ruff格式
just ty # ty类型检查
just test # pytest
just check # lint + 类型检查 + 测试
```
## 相关项目
| 包 | 描述 |
|---------|-------------|
| [uniprotptmpy](https://github.com/tacular-omics/uniprotptmpy) | 解析和查询UniProt PTM受控词汇表 |
| [psimodpy](https://github.com/tacular-omics/psimodpy) | 解析和查询PSI-MOD蛋白质修饰本体 |
## 许可证
[MIT](LICENSE)