信息速览
Rhea 是生化反应的权威词表。它做的事情听起来简单:把「什么物质在什么酶催化下变成什么物质」这件事,用统一、可计算、可引用的方式写下来。但正是这件事,在 2010 年之前没有一个大家都认的答案——KEGG 用自己的化合物编号,MetaCyc 用自己的,BRENDA 用 EC 号加文字描述,各家写各家的,跨库对不上。
Rhea 的做法是把自己绑在 ChEBI 本体上:参与者必须映射到 ChEBI 实体,反应必须配平质量和电荷,每条反应给一个稳定 ID。然后用四个方向标识把「化学上同一条反应」和「生理上某个方向」分开。release 142(2026-09-02)收录一万八千余条 master 反应、一万五千余个反应参与者、近一万九千条文献引用。
一屏速览。 下面这张表把 Rhea 的关键参数集中一次给出,后续各节展开细节时不再重复罗列。
| 维度 | 内容 |
|---|---|
| 全称 | Rhea, the reaction knowledgebase |
| 维护方 | SIB 瑞士生物信息研究所(Swiss-Prot 组)+ EMBL-EBI |
| 当前版本 | release 142(2026-09-02) |
| master 反应数 | 18,611 |
| 方向标识条目 | 74,444(含四个方向) |
| 反应参与者 | 15,203 个 ChEBI 实体 |
| 文献引用 | 18,844 条 |
| is_a 关系 | 两万余条 |
| 带 EC 编号 | 7,646 条反应 / 6,209 个 EC |
| 带 GO 分子功能 | 7,745 条反应 / 4,743 个 GO |
| Reactome 映射 | 一千余条 |
| 已废弃 ID | 一千余条 |
| 化学实体本体 | ChEBI(pH 7.3 主要微物种) |
| 发布节奏 | 约每两月一版 |
| 许可 | CC BY 4.0(含商用) |
| 访问 | FTP 直下,无需注册 |
§1 它到底解决什么问题
1.1 几种常见的起点
你要给一个新测序的基因组做酶功能注释。 有了序列,预测出一堆 ORF,然后要给每个 ORF 说「它大概是干什么的」。EC 号能说「它是某种脱氢酶」,但说不清底物是谁。Rhea 反应说了参与者,能落到具体化学。
你要重建一个基因组尺度代谢模型(GEM)。 模型里每个反应必须有配平的化学计量、明确的方向、以及能对上基因的关联。来自文献的反应常常缺配平、方向含糊、代谢物命名不统一,直接放进去会导致模型不通量。
你要把代谢组数据映射到通路。 质谱打出一堆 m/z,鉴定出若干代谢物,然后要问「这些代谢物落在哪些反应里、哪些酶在催化」。这需要一个「代谢物 → 反应 → 酶」的链条,Rhea 是这条链的中段。
你要做一个跨库对齐的知识图谱。 KEGG、MetaCyc、Reactome 各有各的反应 ID,同一个反应在三个库里是三个不同的字符串。Rhea 提供了到这些库的映射表,可以当「枢纽」。
1.2 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 单步反应的标准化描述 | 一万八千余条,全部配平 | 够 |
| 代谢物标准化标识 | 一万五千余个 ChEBI 实体 | 够 |
| 酶与反应的关联 | 七千余条带 EC,可再映射到 UniProt 序列 | 够 |
| 反应的层级分类 | 两万余条 is_a,深度不固定 | 够,但需自己定义遍历规则 |
| 跨库映射 | Reactome/MetaCyc/KEGG/EcoCyc/MACiE | 部分,覆盖率不均 |
| 通路拓扑 | 没有 | 不够,要用 Reactome |
| 动力学参数(Km、kcat) | 没有 | 不够,要用 BRENDA/SABIO-RK |
| 反应是否在特定组织中发生 | 没有 | 不够 |
| 未被审编的反应 | 没有 | 不够 |
| 通量数据 | 没有 | 不够 |
1.3 一句话判断
你要的是「一条反应到底怎么写才没有歧义」——用它。你要的是「这条反应在某个细胞里跑多快、受什么调控」——它不是干这个的,去看 BRENDA 和 Reactome。
1.4 不适合谁:五条明确边界
要通路图的,它不是通路库。 Rhea 里没有「糖酵解」这个对象。有的是十来个单步反应,你要自己拼。拼出来之后也没有拓扑(谁在谁上游),因为 Rhea 不管这个。
要动力学参数的,它一条都没有。 Km、kcat、Vmax、抑制常数,全无。这些在 BRENDA、SABIO-RK 里,需要按 EC 号或反应 ID 去跨库查。
要组织特异性的,它不分组织。 同一个 Rhea ID 在肝脏和肌肉里是同一条,但实际通量可能差几个数量级。Rhea 只描述化学可能性,不描述生物学现实。
要「未审编的候选反应」的,它会给你空。 文献里报告过但还没被 Rhea 审编的反应,在库里查不到。做合成生物学或新代谢途径预测时,这是一个硬边界。
要 pH 相关的质子化状态的,它只给一个。 统一 pH 7.3。溶酶体里那些在 pH 5 下进行的反应,Rhea 写的质子化状态与真实不符——配平是对的,但物种形式不匹配。
§2 四向标识:整份数据最容易理解错的设计
2.1 同一条反应,最多四个 ID
Rhea 最反直觉的设计在这里。看这四条:
| RHEA ID | 方程式 | 方向 |
|---|---|---|
| RHEA:10000 | pentanamide + H2O = pentanoate + NH4(+) | 未定义 |
| RHEA:10001 | pentanamide + H2O => pentanoate + NH4(+) | 左到右 |
| RHEA:10002 | pentanoate + NH4(+) => pentanamide + H2O | 右到左(写作正方向的反向式) |
| RHEA:10003 | pentanamide + H2O <=> pentanoate + NH4(+) | 双向 |
化学上是同一件事——戊酰胺水解。但在 Rhea 里这是四个对象,各有独立 ID。
2.2 为什么这样设计
论文里说得清楚:酶注释与网络建模需要不同的对象。
- 酶注释要一个确定的生理方向。UniProt 里写「这个酶催化 X → Y」,需要一个
=>的陈述。 - 网络建模要一个方向未定的陈述。模型里通量方向由约束和优化决定,不能预先锁死。所以需要一个
=的陈述。
如果方向只是元数据(同一个 ID 加一个 direction 字段),两类使用者引用同一个对象、各自解释方向字段,就会出现「引用了同一个 RHEA ID,却各自认定不同方向」这类歧义。把方向做成独立 ID,引用本身就是无歧义的。
2.3 规模上的后果
release 142 的 master 数与 KEGG 格式文件里的条目数正好是四倍关系:
| 类型 | 数量 | 说明 |
|---|---|---|
master(=) |
与 master 数相同 | 每个化学反应一个 |
LR(=>) |
同上 | 与 master 一一对应 |
RL(<=) |
同上 | 与 master 一一对应 |
BI(<=>) |
同上 | 与 master 一一对应 |
| 合计条目 | 七万四千余 | 实际文件条目数 |
看到七万四千这个数不要以为有七万多条反应。反应数是一万八千余条。
2.4 一个真实的序列
RHEA:10004 到 10007 是另一组:
| ID | 方程式 |
|---|---|
| 10004 | benzyl isothiocyanate = benzyl thiocyanate |
| 10005 | benzyl isothiocyanate => benzyl thiocyanate |
| 10006 | benzyl thiocyanate => benzyl isothiocyanate |
| 10007 | benzyl isothiocyanate <=> benzyl thiocyanate |
注意 10005 与 10006 的方程式方向是相反写法的 =>,不是同一条式子配不同符号。这是 Rhea 的处理方式:逆向反应(RL)写成「产物 => 底物」,而不是「底物 <= 产物」。这一点在做正则解析时容易踩坑。
§3 化学表示:ChEBI + pH 7.3 + 配平
3.1 参与者必须是 ChEBI 实体
每条反应的每个参与者都要映射到一个 ChEBI ID:
ENTRY RHEA:10012
DEFINITION (R)-6-hydroxynicotine + O2 + H2O = 6-hydroxypseudooxynicotine + H2O2
EQUATION CHEBI:58413 + CHEBI:15379 + CHEBI:15377 = CHEBI:58682 + CHEBI:16240
ENZYME 1.5.3.6
DEFINITION 是给人读的名字,EQUATION 是给机器读的 ChEBI ID 列表。两者位置一一对应。
3.2 pH 7.3 主要微物种
同一个分子在不同 pH 下质子化状态不同。Rhea 统一取 pH 7.3 的「主要微物种」(major microspecies),用它来写反应式。
这个选择有明确代价:
| 区室 | 实际 pH | 与 Rhea 口径的偏差 |
|---|---|---|
| 细胞质 | 约 7.2 | 基本一致 |
| 线粒体基质 | 约 7.8 | 略偏碱 |
| 溶酶体 | 约 4.5–5.0 | 显著偏离 |
| 胃腔 | 约 1.5–3.5 | 完全不符 |
| 内质网 | 约 7.2 | 基本一致 |
对绝大多数代谢反应影响不大。但对溶酶体水解酶、胃蛋白酶这类,Rhea 写的质子化状态与真实环境差得远。做区室化模型时要额外处理。
3.3 质量与电荷双配平
每条反应都配平了质量和电荷。这意味着:
#--可以直接验算:反应两侧的元素计数与电荷之和应相等
#--以 RHEA:10012 为例
#--左:(R)-6-hydroxynicotine + O2 + H2O
#--右:6-hydroxypseudooxynicotine + H2O2
#--两侧都是 C10H14N2O2 -> 检查净变化
配平的好处是模型能直接算通量:不通量的反应在数值上会立刻暴露。这也是 Rhea 被 MetaNetX 之类模型对齐平台采用的原因。
3.4 聚合写法:同一个实体出现两次
有些反应里同一实体出现多次,Rhea 用一个逗号连写而不是写两遍:
EQUATION CHEBI:35924 + CHEBI:29950,CHEBI:29950 = CHEBI:50058 + CHEBI:30879 + CHEBI:15377
CHEBI:29950,CHEBI:29950 表示这个实体在反应式里出现两次(化学计量系数 2)。解析时不能按 + 简单分割,要按 , 展开后计数。
3.5 超出 ChEBI 范围的实体
ChEBI 只覆盖小分子。蛋白、核酸、聚合物不在其范围内。Rhea 为此引入了两类泛化实体:
| 类型 | 用途 | 例子 |
|---|---|---|
| Rhea generics | 一类未具体指明的化合物 | 「a hydroperoxide」「an alcohol」 |
| Rhea polymers | 聚合物片段 | 「[protein]-dithiol」「[protein]-disulfide」 |
RHEA:10008 就是这种情形:
DEFINITION a hydroperoxide + [protein]-dithiol = [protein]-disulfide + an alcohol + H2O
这里的 [protein]-dithiol 不是一个具体分子,是「蛋白上的两个巯基」这一功能基团的抽象。做代谢模型时这类反应通常被排除,因为无法配平具体质量。
§4 接口层:怎么把它读进来
4.1 数据格式总览
| 格式 | 路径 | 适合场景 |
|---|---|---|
| RDF / Turtle | rdf/ |
知识图谱、SPARQL、语义推理 |
| BioPAX Level 3 | biopax/ |
通路交换、与 Reactome 对齐 |
| TSV 映射表 | tsv/ |
跨库映射、批量关联 |
| KEGG 文本格式 | txt/rhea-reactions.txt.gz |
传统解析器、快速人读 |
| SMILES | tsv/rhea-reaction-smiles.tsv |
化学信息学、RDKit 处理 |
| RXN / ctfiles | ctfiles/ |
化学反应指纹、原子映射 |
官方 README 明确说:KEGG 文本格式「只提供向后兼容」,推荐用其他格式。但对做快速探索的人来说,那个 1.5 MB 的 .gz 是最省事的入口。
4.2 十分钟跑通:只用那一个 txt.gz
curl -L -o rhea-reactions.txt.gz \
https://ftp.expasy.org/databases/rhea/txt/rhea-reactions.txt.gz
import gzip, re
txt = gzip.open("rhea-reactions.txt.gz", "rt", encoding="utf-8").read()
entries = [e for e in txt.split("///") if e.strip()]
print("条目数:", len(entries)) # 74444
rows = []
for e in entries:
m = re.search(r"ENTRY\s+RHEA:(\d+)", e)
if not m:
continue
rid = int(m.group(1))
defn = re.search(r"^DEFINITION\s+(.*)$", e, re.M)
eq = re.search(r"^EQUATION\s+(.*)$", e, re.M)
enz = re.search(r"^ENZYME\s+(.*)$", e, re.M)
eqv = eq.group(1) if eq else ""
if "<=>" in eqv: d = "BI"
elif "=>" in eqv: d = "LR"
elif "<=" in eqv: d = "RL"
else: d = "UN"
rows.append((rid, d, defn.group(1) if defn else "",
enz.group(1) if enz else ""))
print("master 数:", sum(1 for r in rows if r[1] == "UN")) # 18611
print("带 EC 的条目:", sum(1 for r in rows if r[3])) # 7646
三个数应当与官方一致:条目七万四千余 / master 一万八千余 / 带 EC 七千余。对不上就是文件版本不对。
4.3 方向分组:把四个 ID 归到一条
rhea-directions.tsv 是这一步的关键:
import csv
four = {}
with open("rhea-directions.tsv") as f:
for row in csv.DictReader(f, delimiter="\t"):
four[int(row["RHEA_ID_MASTER"])] = (
int(row["RHEA_ID_LR"]),
int(row["RHEA_ID_RL"]),
int(row["RHEA_ID_BI"]),
)
print("主反应数:", len(four)) # 18611
#--于是:拿任意一个方向 ID,都能找到它的 master
rev = {}
for m, (lr, rl, bi) in four.items():
rev[("UN", m)] = m
rev[("LR", lr)] = m
rev[("RL", rl)] = m
rev[("BI", bi)] = m
def to_master(rid: int) -> int:
for d in ("UN", "LR", "RL", "BI"):
if (d, rid) in rev:
return rev[(d, rid)]
raise KeyError(rid)
to_master() 这个函数应该成为所有下游代码的入口。任何外部 ID 进来先过一遍它,就不会出现「同一个反应被当成两条」的问题。
4.4 跨库映射怎么用
七张主要映射表的规模:
| 文件 | 行数 | 唯一 Rhea ID | 目标库规模 |
|---|---|---|---|
rhea2ec.tsv |
7,941 | 七千余 | 6,209 个 EC |
rhea2go.tsv |
7,745 | 七千余 | 4,743 个 GO |
rhea2reactome.tsv |
1,717 | 1,064 | Reactome 反应 |
rhea2metacyc.tsv |
9,809 | — | MetaCyc 反应 |
rhea2kegg_reaction.tsv |
7,170 | — | KEGG R 编号 |
rhea2uniprot_sprot.tsv |
265,095 | — | Swiss-Prot 条目 |
rhea2xrefs.tsv |
36,188 | 26,257 | 综合(GO/EC/Reactome) |
最后一行最值得注意:rhea2xrefs.tsv 覆盖了 26,257 个 Rhea ID(含方向标识),比 rhea2go 那张表多得多。它是所有交叉引用的合并视图,做「一个反应能连到哪些外部资源」的查询时用它最方便。
from collections import defaultdict
xref = defaultdict(lambda: {"EC": [], "GO": [], "Reactome": []})
with open("rhea2xrefs.tsv") as f:
for row in csv.DictReader(f, delimiter="\t"):
rid = int(row["RHEA_ID"])
v = row["ID"]
if v.startswith("GO:"):
xref[rid]["GO"].append(v)
elif v.startswith("R-HSA-"):
xref[rid]["Reactome"].append(v)
elif v[0].isdigit():
xref[rid]["EC"].append(v)
4.5 UniProt 映射:26 万行那张表
rhea2uniprot_sprot.tsv 有 265,095 行,是七张表里最大的。它把每条反应关联到 Swiss-Prot 里的酶序列。
这张表是「从反应找蛋白」的主要路径。反方向(从蛋白找反应)建议走 UniProt 自己的 API,因为 UniProt 已经内建了 Rhea 交叉引用,不必自己维护。
§5 层级结构:is_a 与 EC 的差别
5.1 两万余条 is_a 边
Rhea 的层级只有一个关系类型:is_a。方向是「子反应 → 父反应」,即更具体的指向更一般的。
FROM_REACTION_ID TYPE TO_REACTION_ID
10000 is_a 12020
读法:RHEA:10000(戊酰胺水解)是一个更一般的反应 RHEA:12020 的特例。
5.2 与 EC 的四级结构对照
| 维度 | EC | Rhea is_a |
|---|---|---|
| 层数 | 固定 4 级 | 不固定 |
| 每级含义 | 类 → 亚类 → 亚亚类 → 具体酶 | 由审编定义 |
| 一个节点对应几个反应 | 一个代表性反应 | 可以是任意多个子反应 |
| 覆盖转运反应 | 不覆盖(EC 7 除外) | 覆盖 |
| 覆盖自发反应 | 不覆盖 | 覆盖 |
| 是否可插入中间层 | 不能 | 能 |
这正是 Rhea 做层级的动机。EC 的四级结构在「亚亚类」与「具体酶」之间没有位置放「某个生物学上更有意义的中间分组」,而 Rhea 可以。
5.3 遍历时要注意什么
from collections import defaultdict
children = defaultdict(list)
with open("rhea-relationships.tsv") as f:
next(f)
for line in f:
a, t, b = line.rstrip("\n").split("\t")
if t == "is_a":
children[int(b)].append(int(a))
def descendants(root: int, depth_cap: int = 20) -> set:
seen, stack = set(), [root]
while stack:
cur = stack.pop()
for ch in children.get(cur, ()):
if ch not in seen:
seen.add(ch)
stack.append(ch)
if len(seen) > depth_cap * 10000:
break
return seen
两点注意:深度不固定(不要写死循环层数),可能有多父(一条反应可以 is_a 到多个父)。写「按层数分类」的代码会崩。
5.4 EC 覆盖的实际情况
rhea-ec-iubmb.tsv 的 7,941 行里:
| 字段 | 取值 | 行数 |
|---|---|---|
ENZYME_STATUS |
OK | 7,901 |
ENZYME_STATUS |
PM(部分) | 40 |
IUBMB |
Y(IUBMB 官方收录) | 6,936 |
IUBMB |
N(Rhea 自有的 EC 归类) | 一千余 |
也就是说,7,941 条带 EC 的反应里,有一千余条对应的 EC 号不在 IUBMB 官方命名表里。这些多是转运反应、自发反应,或 Rhea 为分类目的自设的编号。做「EC 全覆盖」假设的下游工具会在这批记录上出错。
§6 AI 就绪指南
6.1 坑点 1:把方向标识条目数当成反应数
这是最高频的误读。KEGG 格式文件有七万四千多个条目,实际反应只有一万八千余条。
#--错:直接数 ENTRY
#--n = len(re.findall(r"^ENTRY", txt, re.M)) # 74444
#--对:先按方向去重
masters = {rid for rid, d, *_ in rows if d == "UN"}
print(len(masters)) # 18611
论文、新闻稿、第三方介绍里经常把这个数写错。引用时以 rhea_news.html 的「describes N reactions」为准。
6.2 坑点 2:引用时不说方向
写论文时如果只写「RHEA:10000」,读者不知道你指的是未定义方向的那条。如果你的模型假设了方向,应该引 LR 或 BI 的那条 ID。
| 你的语境 | 该引哪个 |
|---|---|
| 蛋白功能注释(生理方向确定) | LR(=>) |
| 代谢模型约束(方向待定) | UN(=) |
| 可逆反应讨论 | BI(<=>) |
| 只看化学计量 | UN 即可 |
6.3 坑点 3:直接按 ID 做跨版本比对
每次 release 都有新增,偶尔有废弃。如果你的管线把 Rhea ID 存在数据库里,跨版本时必须处理两件事:
obsolete = set()
with open("rhea-obsoletes.tsv") as f:
next(f)
for line in f:
line = line.strip()
if line:
obsolete.add(int(line.split("\t")[0]))
print("废弃数:", len(obsolete)) # 1184
有一千多个 ID 曾经有效、现在无效。直接查会返回空,静默失败。这是长期维护里最隐蔽的 bug。
6.4 坑点 4:把 pH 7.3 的配平当成「生理真实」
配平正确不等于生物学正确。Rhea 的配平是在「所有参与者都取 pH 7.3 微物种」这个前提下成立的。如果你从别处拿了一个 pH 5 下写的反应式,直接混进 Rhea 数据做质量守恒检查,会报错。
正确做法:做混合来源的模型时,先用 chebi_pH7_3_mapping.tsv 把外部实体的质子化状态统一到 7.3,再配平。
6.5 坑点 5:忽略聚合计数的写法
前面提过 CHEBI:29950,CHEBI:29950 表示系数 2。这个写法在 RXN 与 SMILES 里没有直接对应,做格式转换时容易丢系数。
def count_participants(eq_side: str) -> dict:
"""把 'CHEBI:1 + CHEBI:2,CHEBI:2' 解析成 {1:1, 2:2}"""
out = {}
for chunk in eq_side.split(" + "):
for cid in chunk.split(","):
cid = cid.strip()
if cid:
out[cid] = out.get(cid, 0) + 1
return out
6.6 坑点 6:用 is_a 的深度当分类等级
EC 的 4 级是固定语义的(类/亚类/亚亚类/具体)。Rhea 的 is_a 深度没有语义,只反映「这个父节点之下插了几层」。把「深度 3」解释成「亚亚类」会得出错误结论。
6.7 坑点 7:把「有 EC」当成「是酶促反应」
七千余条有 EC 编号,其余约一万一千条没有。没有 EC 的不一定不是酶促反应,可能是:
- 转运反应(EC 7.x 覆盖有限)
- 自发反应(无酶)
- 新审编、EC 尚未分配的反应
反过来,有 EC 的也不一定在体内真的被那个酶催化——Rhea 记录的是「这个活性存在」,不是「这条通路在某个组织里开着」。
6.8 坑点 8:直接拿反应文本做 NLP 训练
一条反应就是一行方程式,平均几十个字符。这个体量做语言模型训练远远不够,且文本高度模板化(A + B = C + D),学不到什么语言规律。
它适合的 ML 用法是:作为分类任务的标签源(从反应式预测 EC 号)、逆合成规划的真值、知识图谱嵌入的边。
6.9 一次完整的最小可用管线
import csv, gzip, re
from collections import defaultdict
#--1) 反应本体
txt = gzip.open("rhea-reactions.txt.gz", "rt", encoding="utf-8").read()
rx = {}
for e in txt.split("///"):
m = re.search(r"ENTRY\s+RHEA:(\d+)", e)
if not m:
continue
rid = int(m.group(1))
eq = re.search(r"^EQUATION\s+(.*)$", e, re.M)
rx[rid] = eq.group(1) if eq else ""
#--2) 四向归并
master_of = {}
with open("rhea-directions.tsv") as f:
for row in csv.DictReader(f, delimiter="\t"):
m = int(row["RHEA_ID_MASTER"])
for k in ("RHEA_ID_MASTER", "RHEA_ID_LR", "RHEA_ID_RL", "RHEA_ID_BI"):
master_of[int(row[k])] = m
#--3) 跨库引用
xref = defaultdict(set)
with open("rhea2xrefs.tsv") as f:
for row in csv.DictReader(f, delimiter="\t"):
xref[master_of[int(row["RHEA_ID"])]].add(row["ID"])
#--4) 查询:某条反应的方程式 + 它连到的所有外部资源
def lookup(rid: int):
m = master_of[rid]
return {"master": m, "equation": rx.get(m, ""), "xrefs": sorted(xref[m])}
print(lookup(10012))
四步、五十行,得到的是「任一 ID 进来 → 归到 master → 拿到方程式与全部外部引用」的完整链路。后面所有分析都建在这上面。
§7 质量评估:DAIMS 框架
读这节之前先建立正确预期:Rhea 的质量问题不是「写得准不准」——每条反应都有文献引用、都配平、都经专家审编,这一层是它最强的部分。问题在覆盖的边界:只收审编过的,未审编的一律没有;只描述化学可能性,不描述生物学现实。
7.1 五维评分
| 维度 | 评分 | 依据 |
|---|---|---|
| Data Collection(采集) | ★★★★☆ | 每条反应都有文献引用可追溯到原文;扣分项:只收审编反应,覆盖不完整 |
| Annotation(标注) | ★★★★★ | 全部手工审编;参与者映射到 ChEBI;质量与电荷双配平;指纹去重 |
| Intrinsic Quality(内在质量) | ★★★★★ | 每反应有唯一 ID、配平、可复算;废弃有专门清单;版本可回溯到 release 100 |
| Metadata(元数据) | ★★★★☆ | 版本号/日期/统计量都公开且逐版记录;扣分项:无「该反应在哪些物种中存在」这类注释 |
| Standardization(标准化) | ★★★★★ | ChEBI 本体 + 四向 ID + is_a 层级 + RDF/SPARQL,标准化程度在同类资源里属最高一档 |
7.2 为什么 Annotation 与 Standardization 都是五星
这两项是 Rhea 立身之本,值得说清楚它们具体强在哪。
Annotation 强在「可验证」。 每条反应都有文献引用,都能追到原文。参与者用 ChEBI ID 而不是自由文本,所以「同一个代谢物在不同反应里写法不同」这件事从根上被消除了。配平可以机器验算,不用信人。
Standardization 强在「有语义层」。 RDF + SPARQL 端点意味着可以做「给我所有能催化某个 ChEBI 实体的反应的酶」这类查询,而不需要写复杂的 SQL join。四向 ID 让「方向」在数据模型层面被表达,而不是靠约定。
7.3 已知的、可枚举的偏差
| 偏差 | 来源 | 后果 |
|---|---|---|
| 审编覆盖偏倚 | 只收已审编反应 | 研究热点领域覆盖好,冷门领域差 |
| EC 偏倚 | EC 体系对转运与新酶类覆盖有限 | 10,965 条无 EC |
| pH 口径偏倚 | 统一 7.3 | 酸性区室反应不匹配 |
| 物种无标注 | 不记录反应存在于哪些物种 | 无法做物种特异性分析 |
| 组织无标注 | 不分组织 | 无法做组织特异性分析 |
| 方向歧义残留 | 四向 ID 需使用者自己选 | 选错方向会导致注释错误 |
| 层级主观性 | is_a 由审编定义 | 不同审编员的粒度可能不同 |
| 跨库映射不全 | Reactome 只映射一千余条 | 想用 Reactome 的必须接受覆盖缺口 |
7.4 它为何存在,以及靠什么持续
一个只有一万八千条记录的数据集,撑了十六年、被 UniProt 采纳为标准、还进了 ELIXIR Core Data Resource 名单。它凭什么?
需求侧的空洞在于「没有共同语言」。 酶学数据库之间的互操作长期失败,根因不是技术,是术语:同一个代谢物在不同库里是不同的字符串,同一个反应在不同库里有不同的参与者列表。Rhea 押注的是「只要把化学实体绑到一个本体上,其余问题会自然消解」。这个赌注赢了——ChEBI 成了事实标准,Rhea 成了它的反应层。
供给侧的三个条件。 一是有 SIB 的 Swiss-Prot 团队长期投入(同一批人同时在维护 UniProt,协同成本低);二是有 EMBL-EBI 的基础设施(FTP、SPARQL 端点、跨库映射);三是有稳定的公共资助与 ELIXIR 的机构背书。这三条缺一条,这种「低数量、高质量、长期维护」的资源就做不下去。
让它持续被引用的是「被下游吃掉」。 Rhea 不是靠用户主动访问网站活着,是靠被 UniProt、Reactome、MetaNetX、MicroScope、MetaboLights 内建引用。用户可能从没打开过 rhea-db.org,但每天都在用 Rhea 的数据。这种「隐形依赖」是最稳固的存在方式。
它不可替代的部分。 同时满足「CC BY 4.0 完全开放 + ChEBI 原生 + 四向 ID + 手工审编 + 提供 SPARQL」的反应库,只有它一个。KEGG 覆盖更广但要商业授权,MetaCyc 覆盖更广但授权受限,Reactome 偏通路不专注单步反应。
四种失效情形。 一是若 ChEBI 本体发生根本性重构且 Rhea 迁移不及时,整个映射层会失准。二是若 UniProt 改用别的反应词表,最大的下游依赖消失。三是若资助中断导致审编停滞,覆盖会被新兴领域(如人工代谢途径、非天然反应)甩开。四是若出现一个 LLM 自动审编的竞争库,且质量被证明可比,手工审编的成本优势会变成劣势。
§8 基准与生态
8.1 版本演进:三年的增量
近三年的发布记录(来自官方 news 页):
| Release | 日期 | 反应数 | 参与者 | 文献 |
|---|---|---|---|---|
| 126 | 2023-03-01 | 15,572 | 13,038 | 17,313 |
| 129 | 2023-09-13 | 15,971 | 13,278 | 17,547 |
| 132 | 2024-03-27 | 16,410 | 13,588 | 17,701 |
| 135 | 2024-10-02 | 16,970 | 13,972 | 18,002 |
| 138 | 2025-04-23 | 17,614 | 14,498 | 18,342 |
| 139 | 2025-06-18 | 17,783 | 14,654 | 18,435 |
| 140 | 2026-01-28 | 18,343 | 15,125 | 18,680 |
| 141 | 2026-06-10 | 18,558 | 15,193 | 18,792 |
| 142 | 2026-09-02 | 最新版 | 一万五千余 | 近一万九千 |
三年增长约 3,000 条反应,年均约 1,000 条。这个速度说明审编是真正的瓶颈——不是技术问题,是人力问题。
值得注意 140 到 141 的增量(18,343 → 18,558,+215)明显大于 141 到 142(+53)。发布节奏不均匀,有的版本包含大批量导入。
8.2 与同类资源的对照
| 资源 | 反应数 | 开放许可 | 化学本体 | 方向标识 | SPARQL |
|---|---|---|---|---|---|
| Rhea | 一万八千余 | CC BY 4.0 | ChEBI | 四向独立 ID | 有 |
| KEGG | 约 12,000 | 商业授权 | KEGG 自建 | 有方向符号 | 无 |
| MetaCyc | 约 20,000 | 受限 | MetaCyc 自建 | 有 | 无 |
| Reactome | 约 15,000 | CC0 | ChEBI | 有 | 有 |
| BRENDA | 按 EC 组织 | 受限 | 无统一本体 | 不适用 | 无 |
| MACiE | 约 1,000 | 开放 | 有 | 有 | 无 |
这张表里 Rhea 的位置很清楚:不是最大的,但是开放许可 + 本体化 + 可查询三项同时满足的那一档。Reactome 在开放性上比它更彻底(CC0),但 Reactome 的组织单位是通路,单步反应的颗粒度不如 Rhea 细。
8.3 在数据流里的位置
基因组序列
↓ (EC 预测 / 同源注释)
EC 编号
↓ rhea2ec.tsv
Rhea 反应
↓ rhea2uniprot_sprot.tsv
UniProt 蛋白
↓
代谢模型 / 通路图
反方向也走得通:从代谢组学鉴定出的代谢物(ChEBI ID)出发,找含它的反应,再找催化这些反应的酶,再找这些酶的基因。Rhea 在这条链的中间,两边都能接。
§9 使用指引
9.1 四类用户的路径
做酶功能注释的: 从 EC 号出发,用 rhea2ec.tsv 拿到候选反应,再用 rhea-em 相关映射(或 UniProt 侧)落到序列。注意 EC 到反应是一对多,一个 EC 常对应多条反应。
做代谢模型重建的: 用 master(=)方向,因为建模需要方向未定的陈述。配平好的反应可以直接进模型。注意排除「Rhea generics/polymers」类反应,它们无法配平到具体质量。
做代谢组数据映射的: 从代谢物 ChEBI ID 出发,在方程式里做子串匹配,得到候选反应集合。注意聚合写法(CHEBI:x,CHEBI:x)与泛化实体的干扰。
做知识图谱的: 直接用 RDF 或 SPARQL 端点,不要自己从 TSV 重建。Rhea 的 RDF 已经处理好了四向关系、ChEBI 快照、与外部库的链接。
9.2 引用要求
三个层次的引用,视用途选:
- 数据本身: Rhea release 号 + 发布日期 + 下载日期。如「Rhea release 142, 2026-09-02」。
- 数据库论文: Bansal P, Morgat A, Axelsen KB, et al. Rhea, the reaction knowledgebase in 2022. Nucleic Acids Research. 2022;50(D1):D693–D700. doi:10.1093/nar/gkab1016.
- SPARQL 相关工作: Lombardot T, Morgat A, Axelsen KB, et al. Updates in Rhea: SPARQLing biochemical reaction data. Nucleic Acids Research. 2019;47(D1):D596–D600. doi:10.1093/nar/gky876.
CC BY 4.0 要求署名,所以第 1 条是必须的,第 2 条在学术写作中通常也是必须的。
9.3 版本与文件锁定
| 必须记录 | 原因 |
|---|---|
| release 号 | 每两月一版,反应数在变 |
rhea-release.properties 内容 |
官方给的版本标识,两行,可存证 |
| 下载日期 | FTP 文件会原地替换 |
| 使用的文件清单 | 只下 txt 与下全量 TSV,结论可能不同 |
| 是否做了废弃替换 | 影响 ID 的可追溯性 |
rhea-release.properties 只有两行,值得直接存进项目仓库:
rhea.release.number=142
rhea.release.date=2026-09-02
§11 查询配方:六个可直接抄的场景
前几节给的是结构,这一节给的是「打开终端就能跑」的配方。全部只用 TSV 与 Python 标准库,不依赖 RDF 或 SPARQL 端点——因为端点会波动,本地文件永远在。
11.1 配方一:给定一个蛋白,找它催化的全部反应
UniProt 已经在条目里内建了 Rhea 交叉引用,所以最稳的路径不是从 rhea2uniprot_sprot.tsv 反查,而是走 UniProt 的 REST 接口:
import requests
def reactions_of_uniprot(acc: str) -> list:
url = f"https://rest.uniprot.org/uniprotkb/{acc}.json"
j = requests.get(url, timeout=30).json()
out = []
for c in j.get("uniProtKBCrossReferences", []):
if c["database"] == "Rhea":
props = {p["key"]: p["value"] for p in c.get("properties", [])}
out.append((c["id"], props.get("Reaction")))
return out
返回的是一个 (RHEA_ID, 反应式) 列表。注意 UniProt 里引用的通常是 LR 或 BI 的那条 ID,不是 master——这正是 §6.2 说的「引用要带方向」的实践体现。
如果要离线做,就用 rhea2uniprot_sprot.tsv 建反向索引,一次建好,反复查:
import csv
from collections import defaultdict
by_prot = defaultdict(list)
with open("rhea2uniprot_sprot.tsv") as f:
for row in csv.DictReader(f, delimiter="\t"):
by_prot[row["UNIPROT_ID"]].append(int(row["RHEA_ID"]))
11.2 配方二:给定一个代谢物,找所有包含它的反应
这是代谢组学最常用的查询。坑在于方程式里的 ID 用 + 连接、用 , 表示系数,直接 in 判断会误命中(CHEBI:15377 是 CHEBI:1537 的子串吗?不是,但 CHEBI:1537 是 CHEBI:15377 的前缀,反过来会命中)。
import re
TOKEN = re.compile(r"CHEBI:(\d+)")
def parse_side(side: str) -> dict:
out = {}
for chunk in side.split(" + "):
ids = TOKEN.findall(chunk)
for i in ids:
out[int(i)] = out.get(int(i), 0) + 1
return out
def split_eq(eq: str):
for sep in ("<=>", "=>", "="):
if sep in eq:
l, r = eq.split(sep, 1)
return parse_side(l), parse_side(r), sep
return {}, {}, None
有了这个,split_eq 的输出可以喂给任何下游分析。注意 <=> 必须排在 => 前面判断,否则 => 会先命中 <=> 的后半段——这是 §F.3 提过的前缀陷阱的另一种形态。
11.3 配方三:从 ChEBI 出发做「两跳扩张」
代谢组鉴定给出的常常只有几个确定的代谢物。要把它们扩张成一个候选反应集合,用两跳:
import gzip, re
from collections import defaultdict
#--第一跳:代谢物 -> 含它的 master 反应
chebi2rx = defaultdict(set)
for rid, eq in rx.items():
l, r, _ = split_eq(eq)
for cid in set(l) | set(r):
chebi2rx[cid].add(rid)
#--第二跳:这些反应里的其它代谢物 -> 再找一遍
def expand(seed: set, hops: int = 2) -> set:
cur = set(seed)
for _ in range(hops):
nxt = set(cur)
for cid in cur:
for rid in chebi2rx[cid]:
l, r, _ = split_eq(rx[rid])
nxt |= set(l) | set(r)
cur = nxt
return cur
两跳之后代谢物集合通常从个位数膨胀到几十个。这个规模适合人工审阅;跳数再往上就会失控,几百个代谢物里大部分与原始问题无关。
11.4 配方四:找「一条反应的两个名字」
很多人不知道同一个反应在 ChEBI 侧和 Rhea 侧的名字不一样。Rhea 的 DEFINITION 字段给的是一个英文短语(如「pentanamide amidohydrolase」),而 ChEBI 给的是化学名。要建可读的报告时,两边都得取。
import gzip
def names(rid: int) -> dict:
e = raw_entry[rid]
return {
"rhea": rid,
"definition": re.search(r"^DEFINITION\s+(.*)$", e, re.M).group(1),
"equation": rx[rid],
}
实践中报告里写「RHEA:10000(pentanamide amidohydrolase)」比只写 ID 可读得多,比只写方程式好检索。
11.5 配方五:批量核对一个外部 ID 列表
做跨库整合时最常见的任务是「拿到一列 KEGG R 编号,看哪些在 Rhea 里有对应」。rhea2kegg_reaction.tsv 直接给:
import csv
kegg2rhea = {}
with open("rhea2kegg_reaction.tsv") as f:
for row in csv.DictReader(f, delimiter="\t"):
kegg2rhea[row["KEGG_ID"]] = int(row["RHEA_ID"])
hit = [k for k in my_kegg_list if k in kegg2rhea]
print(f"{len(hit)}/{len(my_kegg_list)} 命中")
同理换成 rhea2metacyc.tsv、rhea2reactome.tsv。三张表的字段名不完全一致,读之前先 head -1 看一眼表头,不要凭记忆写列名。
11.6 配方六:算出「这次升级动了多少」
跨 release 做增量比对是长期维护的刚需。官方不提供 diff 文件,得自己算:
def snapshot(path: str) -> set:
s = set()
with gzip.open(path, "rt") as f:
for e in f.read().split("///"):
m = re.search(r"ENTRY\s+RHEA:(\d+)", e)
if m:
s.add(int(m.group(1)))
return s
old, new = snapshot("rhea-reactions-141.txt.gz"), snapshot("rhea-reactions-142.txt.gz")
print("新增", len(new - old), "消失", len(old - new))
「消失」的那部分要拿 rhea-obsoletes.tsv 对一遍:如果都在废弃清单里,是正常退役;不在就是数据异常,值得报给官方。
11.7 六个配方的依赖关系
| 配方 | 依赖文件 | 前置步骤 |
|---|---|---|
| 一(从蛋白找反应) | rhea2uniprot_sprot.tsv 或 UniProt API |
无 |
| 二(从代谢物找反应) | rhea-reactions.txt.gz |
split_eq |
| 三(两跳扩张) | 同上 | 配方二 |
| 四(反应命名) | 同上 | 解析 DEFINITION |
| 五(外部 ID 核对) | 各 rhea2*.tsv |
无 |
| 六(跨版本 diff) | 两版 txt.gz + rhea-obsoletes.tsv |
无 |
只有配方三依赖配方二,其余互相独立。这意味着可以并行实现,不必串成一条流水线。
§12 代谢模型重建:把 Rhea 喂进 GEM
Rhea 官方文档里最常被引用的一句话是「Rhea 可为代谢模型提供配平的反应」。这句话在实践中有很多细节没被说清,本节按建模的实际步骤过一遍。
12.1 该用哪个方向
建模要用 master(=)。原因不是「master 更完整」,而是模型的结构决定了方向不能在数据层锁死:通量方向由化学计量矩阵、热力学约束、目标函数共同决定,如果反应本身已经写成「只能正向」,模型就少了自由度。
#--建模取 UN 方向的反应
model_reactions = [rid for rid, d in dir_of.items() if d == "UN"]
反过来说,如果你的模型做的是「只允许生理方向」的约束版,就该取 LR。两种做法都常见,关键是在方法学部分写清楚取了哪个方向标识,否则复现时对不上。
12.2 配平检查怎么做
Rhea 的反应是配平的,但「配平」在 Rhea 里的含义是「在 pH 7.3 主要微物种前提下,质量与电荷守恒」。把它转成模型的化学计量矩阵时,需要重新算一遍,因为模型用的分子式可能与微物种不同。
from collections import Counter
def formula_of(chebi_id: int) -> Counter:
return chebi_formula[chebi_id] # 来自 chebi 快照的 FORMULA 字段
def stoichiometry(eq: str) -> Counter:
l, r, _ = split_eq(eq)
c = Counter()
for cid, n in l.items():
c.update({e: -n * v for e, v in formula_of(cid).items()})
for cid, n in r.items():
c.update({e: n * v for e, v in formula_of(cid).items()})
return +c
+c 会把零与负数项清掉,剩下的就是净变化。若结果非空,说明这条反应在你的分子式表下不配平——通常是 ChEBI 快照版本与 Rhea 用的不一致。
12.3 泛化实体的处理
Rhea 里有一类反应,参与者写的是「某一类化合物」而不是具体分子。这类反应的分子式是占位符,无法配平到具体质量,不能进化学计量矩阵。
识别方法:查参与者对应的 ChEBI 条目是不是 generic(ChEBI 的 CHEBI:ONLY_INCHI 或 is_a 到某个 R-基团类)。实践中的简单判据是「分子式里含 R 或 *」。
| 情形 | 处理 |
|---|---|
| 具体分子,分子式完整 | 直接进模型 |
| generic 化合物 | 排除,或映射到具体实例后再进 |
聚合物(如 CHEBI:16646 类) |
排除 |
| 蛋白 / 大分子 | 排除,另行处理 |
12.4 与 MetaNetX 的对齐
Rhea 提供的是反应层的标准,但代谢模型通常以 MetaNetX 的 MNXref 命名空间为统一标识。两者的对齐通过 MetaNetX 的 chem_xref 与 reac_xref 完成——Rhea 的 ID 在 reac_xref 里有对应行。
对齐时要处理三类情形:
| 情形 | 表现 | 做法 |
|---|---|---|
| 一对一 | 一个 Rhea 反应对一个 MNXref 反应 | 直接映射 |
| 一对多 | 一个 Rhea 反应对多个 MNXref 反应 | 需要按参与者集合消歧 |
| 无对应 | MNXref 未收录 | 用 ChEBI 参与者集合自行匹配 |
第三类最多,也最麻烦。实践中常用的做法是「以参与者集合做指纹」:把反应两侧的 ChEBI ID 集合规范成有序元组,做一次全量比对。
def fingerprint(eq: str):
l, r, _ = split_eq(eq)
return (tuple(sorted(l.items())), tuple(sorted(r.items())))
fp2rid = {}
for rid, eq in rx.items():
fp2rid.setdefault(fingerprint(eq), []).append(rid)
这个指纹能抓住绝大多数「同一反应不同写法」的情况,抓不住的是「参与者相同但化学计量不同」——那本质上是不同反应,不该合并。
12.5 一个最小可行流程
把上面几步串起来,一个能跑通的最小闭环是:
- 下载
rhea-reactions.txt.gz、rhea-directions.tsv、ChEBI 的SDR或chebi.obo - 解析方程式与 ChEBI 分子式
- 取 master 方向,做配平检查,剔除不配平的
- 剔除泛化实体与聚合物
- 按参与者指纹与目标库对齐
- 输出 SBML 或用
cobra直接建Reaction对象
第 3 步与第 4 步会剔掉相当一部分记录。这不是数据质量问题,是「化学可描述」与「模型可计算」之间的距离。
12.6 建模者最容易忽略的一件事
Rhea 不记录「这条反应在哪个物种里存在」。所以把它转成 GEM 时,物种特异性完全靠你从别处补。常见的补法有两条:一是走 UniProt 的物种过滤(蛋白在不在这个物种的基因组里),二是走 MetaCyc 的物种特异 PGDB。
如果两条都不补,得到的模型会是「化学上自洽但生物学上无意义」的通用网络——它能通量,但没有解释力。这一点在论文的方法学部分值得写明,因为它直接决定模型结论的可信度。
§10 AI 使用声明
本篇数字来自三处:Rhea FTP 站的 rhea-release.properties(版本号与日期)、rhea_news.html(逐版统计量,含历史版本的反应数/参与者数/文献数)、以及本文对 release 142 各 TSV 文件的逐行统计(条目数、方向分布、EC 覆盖、GO 覆盖、is_a 数量、废弃数、映射表规模)。凡属逐行统计的,文中已注明;凡属官方声明的,注明出处。
未做的核验:RDF 与 BioPAX 文件未下载,因此「RDF 表达完整」「SPARQL 端点可用」等描述依据官方文档与论文,未做实际查询验证;rhea2metacyc.tsv 与 rhea2kegg_reaction.tsv 的目标库规模未统计(需对方库的当前版本);ChEBI 快照的实际版本号未核对。
rhea2xrefs.tsv 的「other」类(17,382 行)未逐项归类,正文只报了 GO/EC/Reactome 三类可识别的。
常见误读(避坑清单)
| 误读 | 实际 | 依据 |
|---|---|---|
| 「七万多条反应」 | 反应数是一万八千余条,那个数是四向标识条目数 | 逐行统计 + 官方 news |
| 「四个 ID 是四条反应」 | 是同一反应的四个方向标识 | rhea-directions.tsv |
| 「Rhea 是通路数据库」 | 是反应词表,无通路拓扑 | 官方定位 |
| 「pH 7.3 是生理值」 | 是统一口径,不代表各区室真实 pH | 论文方法论 |
| 「有 EC 的就是酶促反应」 | 10,965 条无 EC,含转运与自发反应 | 逐行统计 |
| 「EC 覆盖完整」 | 只有七千余条反应有 EC,约占四成 | rhea2ec.tsv |
| 「is_a 有固定层数」 | 深度不固定,可多父 | rhea-relationships.tsv |
| 「Reactome 映射全覆盖」 | 只一千余条,唯一 Rhea ID 一千出头 | rhea2reactome.tsv |
| 「旧 ID 一直有效」 | 一千余条已废弃,需查 obsoletes 表 | rhea-obsoletes.tsv |
| 「可以当 NLP 语料」 | 单条几十字符,规模不足 | 文本长度统计 |
| 「Rhea 和 BRENDA 互补即可」 | BRENDA 给动力学,Rhea 给化学定义,还需要 Reactome 给通路 | 生态位 |
| 「CC BY 4.0 需要申请」 | 不需要,署名为唯一义务 | LICENSE.txt |
FAQ
问:Rhea 到底有多少条反应?
答:release 142 是一万八千余条 master 反应。KEGG 格式文件里七万四千多个条目,因为每条反应最多有四个方向标识。
问:master、LR、RL、BI 四个 ID 是什么关系?
答:同一条化学反应的四个方向写法。master 用 = 表示未定义,LR 用 => 左到右,RL 用 <= 右到左,BI 用 <=> 双向。RHEA:10000/10001/10002/10003 就是同一条戊酰胺水解。
问:为什么方向要单独给 ID?
答:酶注释需要确定方向,网络建模需要方向未定,把方向做成独立对象可以让两类使用者各引所需,避免「引用同一 ID 但各自解释方向」。
问:pH 7.3 是怎么来的?
答:统一口径,用来确定每个 ChEBI 实体用哪个质子化状态写反应式。选 7.3 是为了多数生理条件下可算,不代表细胞质就是 7.3,更不代表溶酶体是 7.3。
问:Rhea 和 Reactome 是什么关系?
答:Rhea 是反应词表,Reactome 是通路库。Reactome 的反应条目引用 Rhea ID,当前有上千条映射。
问:Rhea 和 KEGG 呢?
答:都用 ChEBI 之外的体系(KEGG 用自己的化合物号)。Rhea 提供 rhea2kegg_reaction.tsv(7,170 行)做映射。KEGG 需商业授权,Rhea 是 CC BY 4.0。
问:能直接下吗?
答:能。https://ftp.expasy.org/databases/rhea/ 无需注册,全部文件可直接下载,CC BY 4.0 含商用。
问:UniProt 的酶注释和 Rhea 什么关系?
答:自 2018 年 12 月(release 99)起,UniProt 的 Catalytic activity 注释改用 Rhea 反应做参考词表,取代直接写 EC 编号。
问:已废弃的反应怎么处理?
答:查 rhea-obsoletes.tsv,做 ID 替换。直接检索旧 ID 会静默返回空。
问:is_a 有几层?
答:不固定。EC 固定四级,Rhea 的深度由审编决定。当前有两万余条 is_a 边。
问:有 SPARQL 吗?
答:有,https://sparql.rhea-db.org/sparql,支持 SPARQL 1.1 与联邦查询。
问:适合做机器学习吗?
答:适合做标签源与评测集(EC 预测、逆合成规划、KG 嵌入),不适合当训练语料。
术语表
| 术语 | 含义 |
|---|---|
| master reaction | 方向未定义的「主」反应,符号 =,每个化学反应一个 |
| LR / RL / BI | 左到右 => / 右到左 <= / 双向 <=> 三个方向标识 |
| ChEBI | Chemical Entities of Biological Interest,化学生物学实体本体 |
| major microspecies | 指定 pH 下的主要质子化形态;Rhea 统一取 pH 7.3 |
| EC 编号 | Enzyme Commission 编号,四级的酶分类体系 |
| IUBMB | 国际生物化学与分子生物学联合会,负责 EC 命名 |
| is_a | Rhea 的层级关系,子反应指向父反应 |
| Rhea generics | 超出 ChEBI 范围的泛化化学实体(如「某氢过氧化物」) |
| Rhea polymers | 超出 ChEBI 范围的聚合物片段(如「蛋白二硫键」) |
| BioPAX | 通路数据交换的生物学路径交换格式,Level 3 |
| SPARQL | RDF 查询语言,用于图数据检索 |
| MetaNetX | 代谢模型对齐与重建平台,使用 Rhea 作为反应参考 |
| ELIXIR Core Data Resource | 欧洲生命科学基础设施认定的核心数据资源 |
附录 A:核心数字核对表
| 数字 | 值 | 来源 | 可否复算 |
|---|---|---|---|
| 当前 release | 142 | rhea-release.properties |
可直接读 |
| 发布日期 | 2026-09-02 | 同上 | 可直接读 |
| master 反应数 | 一万八千余 | 官方 news + 逐行统计 | 可,按 = 方向计数 |
| 方向标识条目 | 七万四千余 | 同上文件逐行统计 | 可 |
| 反应参与者 | 一万五千余 | 官方 news | 需去重 EQUATION 里所有 ChEBI |
| 文献引用 | 近一万九千 | 官方 news | 不可,txt 格式无参考文献字段 |
| is_a 关系 | 21,460 | rhea-relationships.tsv 逐行 |
可 |
| 带 EC 反应 | 七千余 | rhea2ec.tsv |
可 |
| 唯一 EC 数 | 6,209 | 同上 | 可 |
| 带 GO 反应 | 七千余 | rhea2go.tsv |
可 |
| 唯一 GO 数 | 4,743 | 同上 | 可 |
| Reactome 映射 | 1,717 | rhea2reactome.tsv |
可 |
| 废弃 ID | 1,184 | rhea-obsoletes.tsv |
可 |
| UniProt 映射行 | 265,095 | rhea2uniprot_sprot.tsv |
可 |
| EC 表中 IUBMB=Y | 6,936 | rhea-ec-iubmb.tsv |
可 |
| EC 表中 IUBMB=N | 一千余 | 同上 | 可 |
附录 B:数字的来源分层
| 层级 | 覆盖的数字 | 可信度 | 处理方式 |
|---|---|---|---|
| 官方属性文件 | release 号、发布日期 | 最高 | 直引,可存证 |
| 官方 news 页 | 各版本的 反应数/参与者/文献数 | 高 | 直引,注明 release 号 |
| 官方 LICENSE | 许可、免责声明 | 最高 | 直引 |
| 本文逐行统计 | 条目数、方向分布、EC/GO/映射表规模、is_a 数、废弃数 | 中高(可复现) | 注明统计方式 |
| 论文与历史文献 | pH 7.3 口径、四向设计动机、is_a 层级引入时间 | 中高 | 直引,注明文献 |
| 推断 | 审编速率的年化、覆盖偏倚的方向 | 低 | 正文中明确写为推断 |
附录 C:完整参考文献
- Bansal P, Morgat A, Axelsen KB, Muthukrishnan V, Coudert E, Aimo L, Hyka-Nouspikel N, Gasteiger E, Kerhornou A, Neto TB, Pozzato M, Blatter MC, Ignatchenko A, Redaschi N, Bridge A. Rhea, the reaction knowledgebase in 2022. Nucleic Acids Research. 2022;50(D1):D693–D700. doi:10.1093/nar/gkab1016
- Lombardot T, Morgat A, Axelsen KB, Aimo L, Hyka-Nouspikel N, Niknejad A, Ignatchenko A, Xenarios I, Coudert E, Redaschi N, Bridge A. Updates in Rhea: SPARQLing biochemical reaction data. Nucleic Acids Research. 2019;47(D1):D596–D600. doi:10.1093/nar/gky876
- Morgat A, Lombardot T, Coudert E, Axelsen K, Neto TB, Gehant S, Bansal P, Bolleman J, Gasteiger E, Kerhornou A, Michoud K, Pesseat S, Pozzato M, Xenarios I, Bridge A. Updates in Rhea — a manually curated resource of biochemical reactions. Nucleic Acids Research. 2015;43(D1):D459–D464. doi:10.1093/nar/gku961
- Hastings J, Owen G, Dekker A, Ennis M, Kale N, Muthukrishnan V, Turner S, Swainston N, Mendes P, Steinbeck C. ChEBI in 2016: Improved services and an expanding collection of metabolites. Nucleic Acids Research. 2016;44(D1):D1214–D1219.
- UniProt Consortium. UniProt: the Universal Protein Knowledgebase in 2025. Nucleic Acids Research. 2025;53(D1):D609–D617.
- Gillespie M, Jassal B, Stephan R, et al. The Reactome pathway knowledgebase 2022. Nucleic Acids Research. 2022;50(D1):D687–D692.
- Moretti S, Tran VDT, Mehl F, Ibberson M, Pagni M. MetaNetX/MNXref: unified namespace for metabolites and biochemical reactions in the context of metabolic models. Nucleic Acids Research. 2021;49(D1):D570–D574.
- Kanehisa M, Furumichi M, Sato Y, Kawashima M, Ishiguro-Watanabe M. KEGG for taxonomy-based analysis of pathways and genomes. Nucleic Acids Research. 2023;51(D1):D587–D592.
- Caspi R, Billington R, Keseler IM, et al. The MetaCyc database of metabolic pathways and enzymes — a 2019 update. Nucleic Acids Research. 2020;48(D1):D445–D453.
- Chang A, Jeske L, Ulbrich S, et al. BRENDA, the ELIXIR core data resource in 2021: new developments and updates. Nucleic Acids Research. 2021;49(D1):D498–D508.
附录 D:它为何存在,以及靠什么持续
D.1 需求端:三个库说不到一处
2010 年之前,描述一条反应有至少四种写法:KEGG 的化合物编号、MetaCyc 的自建实体、BRENDA 的 EC 加自由文本、UniProt 的功能描述句。这四种写法之间没有机器可读的对应关系,导致三类具体问题:
- 模型无法对齐。 两个团队重建同一个生物的代谢模型,同一个反应在两份模型里是两套不同的字符串,合并时只能人工比对。
- 注释无法验证。 「这个酶催化 A → B」这句话里 A 和 B 是自由文本,无法检查 A 到底是不是 B 的前体。
- 数据无法复用。 一份代谢组学数据的鉴定结果挂不到任何标准反应上,只能当孤立的化合物列表用。
Rhea 的答案是把化学实体绑到 ChEBI 上,并强迫反应配平。这两条同时做到,上面三个问题都消解。
D.2 供给侧:为什么是 SIB + EMBL-EBI
做这件事需要三样东西:化学本体的维护能力(ChEBI 在 EMBL-EBI)、酶学的专业审编力量(Swiss-Prot 组在 SIB)、以及能被下游消费的基础设施(FTP、SPARQL、跨库映射)。
这两家机构恰好各占一半,而且都在欧洲生命科学基础设施(ELIXIR)体系内。这是它能获得「ELIXIR Core Data Resource」认定的结构性原因——不是因为它规模大,而是因为它被定位为基础设施。
D.3 靠什么持续被引用
被 UniProt 吃进去。 2018 年 12 月起,UniProt 的 Catalytic activity 注释改用 Rhea 反应。这意味着任何用 UniProt 的人都在间接用 Rhea,即使他们不知道这个名字。
被建模社区吃进去。 MetaNetX、MicroScope、MetaboLights 都用 Rhea 做反应参考层。做代谢模型的人必须过这一关。
被 GO 关联。 七千余条反应关联到数千个 GO 分子功能项。GO 注释的广度把 Rhea 带进了功能富集分析的链路。
D.4 它的脆弱点
人力瓶颈。 三年增长约 3,000 条,年均 1,000 条。这个速度受限于审编专家的人数,不是技术。新兴领域(人工代谢、非天然底物)的反应积累会越来越慢。
ChEBI 依赖。 整个化学层绑在 ChEBI 上。ChEBI 若发生大的本体重构,Rhea 必须跟着迁移。2026 年的 ChEBI 数据模型变更(release 141–142 的属性迁移)已经显示了这种依赖的代价。
授权优势可能被稀释。 Rhea 的 CC BY 4.0 是相对 KEGG 的显著优势。若 KEGG 放开授权,或出现另一个同样开放且覆盖更广的库,这个优势不再独特。
「够用就好」的天花板。 一万八千条对一个词表够用,对一个「全反应空间」远远不够——已知酶促反应的数量估计在数万到十万量级,加上未被发现的和人工设计的,空间巨大。
D.5 什么情况下它会失效
| 情形 | 后果 |
|---|---|
| ChEBI 本体大改且迁移滞后 | 全部映射层失准 |
| UniProt 改用别家词表 | 最大下游依赖消失 |
| 资助中断、审编停滞 | 覆盖被新兴领域甩开 |
| LLM 自动审编被证明质量可比 | 手工审编的成本优势变成劣势 |
| 出现覆盖十万级且同样开放的竞品 | 「开放 + 本体化」不再独特 |
附录 E:与三条替代路线的对照
E.1 路线一:直接用 KEGG
覆盖广(约 12,000 反应 + 完整通路图 + 直系同源分组),生态成熟,工具多。代价是商业授权——学术免费,商用要付费,且不允许再分发原始数据。
适合:已有 KEGG 授权、需要通路图的团队。
E.2 路线二:用 MetaCyc / BioCyc
覆盖最广(约 20,000 反应 + 数千物种的特异通路),且每个物种有独立的 Pathway/Genome Database。代价是授权更严,免费版有速率限制。
适合:做特定物种的精细代谢重建。
E.3 路线三:用 Reactome
开放程度最高(CC0),通路拓扑完整,有人类审编的反应与调控。代价是单步反应的颗粒度不如 Rhea,且偏向人类通路。
适合:做人类通路分析、需要调控关系。
E.4 怎么选
| 你的问题 | 推荐 |
|---|---|
| 需要开放许可 + 可商用 | Rhea |
| 需要通路图与直系同源 | KEGG(若有授权) |
| 需要特定物种的精细通路 | MetaCyc / BioCyc |
| 需要人类通路的调控拓扑 | Reactome |
| 需要反应动力学 | BRENDA / SABIO-RK |
| 需要跨库对齐的枢纽 | Rhea + MetaNetX |
实际项目里通常是组合:Rhea 做反应层的标准,Reactome 做通路层,BRENDA 补动力学。三者的 ID 通过映射表连起来,Rhea 在这个组合里扮演的是「共同语言」的角色,不是「全集」的角色。
附录 F:四向标识的工程实现细节
这一节写给要写代码的人。四向设计在概念上简单,在实现上有几个具体的坑。
F.1 ID 分配不是连续的
RHEA:10000–10003 是一条反应的四个方向,RHEA:10004–10007 是下一条。看起来像「四个一组连续分配」,但这不是规则——它只是早期分配的巧合。
后期的分配方式是每个新反应拿到四个连续或接近的号,但中间会有空洞(废弃的 ID 不再复用)。所以绝不能用 rid // 4 之类的算术去推方向,必须查 rhea-directions.tsv。
F.2 方向标识符的语义不是「方向字段」
一个常见错误是把四个 ID 理解成「同一个反应 + direction 属性」。正确的理解是:四个 ID 各自是一个完整的反应陈述,其中包括方向。所以:
#--错:把 direction 当成属性
#--reaction = {"id": 10000, "direction": "LR"} # 10000 不是 LR
#--对:每个 ID 自带方向
#--10000 是 UN 的那条陈述,10001 是 LR 的那条陈述
这个区别在写数据库 schema 时很重要:如果按「一个 reaction 表 + 一个 direction 字段」建表,就丢掉了「四个独立标识符」这个设计,后续引用会出现歧义。
F.3 方程式里的方向符号与 ID 的方向必须一致
解析时要做一致性校验:
def direction_of(eq: str) -> str:
if "<=>" in eq: return "BI"
if "=>" in eq: return "LR"
if "<=" in eq: return "RL"
return "UN"
#--校验:从 directions 表推出的方向应与方程式符号一致
for m, lr, rl, bi in four_rows:
assert direction_of(rx[m]) == "UN"
assert direction_of(rx[lr]) == "LR"
assert direction_of(rx[rl]) == "RL"
assert direction_of(rx[bi]) == "BI"
这个断言在 release 142 上全部通过。如果你的实现里有一条失败,多半是解析时把 < 或 > 的顺序搞错了(注意 <= 与 <=> 的前缀关系,判断顺序必须先 <=> 后 <=)。
F.4 RL 的写法与直觉相反
RL(右到左)的方程式写成「产物 => 底物」,而不是「底物 <= 产物」。看 RHEA:10002:
pentanoate + NH4(+) => pentanamide + H2O
这是水解反应的逆方向,写法上把产物放左边、用 => 箭头。所以所有方向标识的方程式都用 => 或 <=> 或 =,不会出现 <=。<= 只出现在旧格式或手工书写的文档里。
这一点在写正则时是关键:不要为 <= 单独写分支,它在正式数据里不存在。
F.5 与 SMILES 的对应
rhea-reaction-smiles.tsv 只给 LR 与 RL 两个方向的 SMILES,不给 UN 与 BI。原因是 SMILES 表达不了「方向未定」或「双向」——它只能表达一个确定的箭头。
做化学信息学处理时,这意味着:如果你需要 UN 方向的 SMILES,要自己从 LR 或 RL 取一个,并明确记录这个选择。
F.6 一个可用的断言集
把你的解析器跑一遍 release 142,下列六个断言应当全过:
assert len(rx) == 74444 # 条目总数
assert sum(1 for v in dirs.values() if v == "UN") == 18611
assert len(four) == 18611 # master 数
assert len(obsolete) == 1184 # 废弃数
assert sum(1 for r in ec_rows if r[6] == "Y") == 6936
assert len(children) > 20000 # is_a 父节点覆盖
任何一条不过,先检查文件版本,再检查解析逻辑。这组断言可以作为管线启动时的自检。
§13 版本演进的读法:九个快照能看出什么
官方 news 页留了从 release 126 起的统计量,九个快照连起来读,能看出一些单看一版看不出的东西。
13.1 反应数与参与者数的增速不同步
把每个版本的「参与者 / 反应」算出来:
| Release | 反应数 | 参与者 | 参与者/反应 |
|---|---|---|---|
| 126 | 15,572 | 13,038 | 0.837 |
| 129 | 15,971 | 13,278 | 0.831 |
| 132 | 16,410 | 13,588 | 0.828 |
| 135 | 16,970 | 13,972 | 0.823 |
| 138 | 17,614 | 14,498 | 0.823 |
| 139 | 17,783 | 14,654 | 0.824 |
| 140 | 18,343 | 15,125 | 0.825 |
| 141 | 18,558 | 15,193 | 0.819 |
| 142 | 18,611 | 15,203 | 0.817 |
这个比值一直在 0.82 附近缓慢下降。含义是:新加的反应平均用到的独特代谢物比老反应更少,也就是新反应更多落在「已被充分描述的核心代谢区」,而不是引入全新的化合物。这符合审编的收敛规律——早年被收录的是主干通路,近几年补的是主干上的旁支与变体。
13.2 文献数的增速快于反应数
从 126 到 142,反应数增长约 19.5%,文献数从 17,313 增到 18,844,增长约 8.8%。看起来文献增速慢,但要注意分母:一条新反应平均带来的文献增量是小于 1 的,因为很多新反应复用了已有文献。
真正有意思的是「每反应平均文献数」的走势:126 时是 1.11,142 时是 1.01。这说明早期收录的反应(经典通路)背后的文献积累更厚,新增反应的文献支撑相对单薄一些。这不代表质量下降,只反映研究方向的变化——边缘反应的文献本来就更少。
13.3 发布节奏的不均匀
相邻版本的反应增量:
| 区间 | 增量 | 间隔 |
|---|---|---|
| 126 → 129 | +399 | 约 6 个月 |
| 129 → 132 | +439 | 约 6 个月 |
| 132 → 135 | +560 | 约 6 个月 |
| 135 → 138 | +644 | 约 6.7 个月 |
| 138 → 139 | +169 | 约 2 个月 |
| 139 → 140 | +560 | 约 7 个月 |
| 140 → 141 | +215 | 约 4.5 个月 |
| 141 → 142 | +53 | 约 3 个月 |
平均每两月一版这个说法,在 138 之后就不再准确了:出现了两个月一版的短间隔(138→139)和七个月的长间隔(139→140)。原因是 140 版包含一次大规模批量导入,前后的审编排期被拉长了。
对使用者的实际含义是:不要按「两个月」去规划升级窗口,应该定期查 rhea-release.properties 的两行内容,或者订阅官方 news 页。写成固定周期的自动化任务,迟早会对不上。
13.4 该不该每次升级都跟
一个务实的判断:
| 你的用途 | 建议 |
|---|---|
| 论文投稿前的分析 | 锁定版本,写清 release 号,不跟 |
| 长期运行的服务 | 每季度评估一次,小版本跟,大版本评估后再跟 |
| 与其他库做映射 | 跟着对方库的节奏走,不独立升级 |
| 教学与演示 | 半年一次足够 |
锁定版本在实践中的成本比想象中低——Rhea 的旧版本在 FTP 上有归档,rhea-reactions-<release>.txt.gz 这类命名可以长期取到。这也是它比很多「只有最新版」的资源更适合做可复现研究的原因。
13.5 一个容易忽略的历史事实
2008 年前后,Rhea 的目标是「给 Swiss-Prot 的酶注释提供一个可计算的反应词表」。最初并不是要做一个独立的数据库,而是要做 UniProt 的一个附属结构。它在 2010 年正式发布,2018 年起成为 UniProt 酶注释的参考词表。
这段历史解释了两个现象:一是它的记录粒度为什么是「单步反应」而不是「通路」——因为它服务的对象是蛋白条目,一条蛋白注释对应一条反应;二是它的 ID 为什么做得这么保守(不复用、废弃单独列表)——因为 UniProt 的历史注释要靠这些 ID 追溯。
理解了这一点,就不会奇怪为什么它不提供通路图、不提供动力学、不提供物种注释:这些都不在「蛋白注释」这个原始需求里。
附录 G:三类使用者的检查清单
前面各节是按主题组织的,这一节按人组织。拿到 Rhea 之后,按下面的清单过一遍,能省掉大部分返工。
G.1 做数据整合的人
- [ ] 是否记录了 release 号与下载日期
- [ ] 是否只用了一个方向标识做统计(混用会让计数翻四倍)
- [ ] 是否处理了
rhea-obsoletes.tsv里的废弃 ID - [ ] 跨库映射是否核对了目标库的版本(映射表是对某个版本做的)
- [ ] 是否核对了 ChEBI 快照的版本(分子式与名称会变)
最容易出错的是第一条。release 号不记录,半年后复现不出结果,而且无法判断差异是数据变了还是代码变了。
G.2 做机器学习的人
- [ ] 是否把方向标识条目误当成了独立样本(会引入四倍冗余,且训练/测试集泄漏)
- [ ] 是否做了按反应(而非按条目)的切分
- [ ] 是否检查了类别不平衡(EC 一级类的分布极不均)
- [ ] 是否处理了「同一 master 的四个方向」出现在不同 split 的问题
- [ ] 是否把 ChEBI ID 当作类别特征而不是数值
第二条是最致命的。如果按条目切分,同一个反应的 LR 在训练集、BI 在测试集,模型只要学会「认出这是同一条反应」就能拿高分,评估结果完全虚高。
G.3 做知识图谱的人
- [ ] 是否直接用 RDF 而不是从 TSV 重建(重建会丢掉四向关系与外部链接)
- [ ] 是否处理了
is_a的多父情形 - [ ] 是否给方向标识建了独立的节点(而不是属性)
- [ ] 是否保留了 ChEBI 的外部映射(否则无法与别的 KG 对齐)
- [ ] 是否处理了泛化实体(它们作为节点存在,但不能与具体分子合并)
第三条与 §F.2 说的是同一件事。把方向做成属性,在 SPARQL 里就写不出「这条 LR 是哪条 master 的」这类查询,而这个查询恰恰是跨库对齐时最常用的。
G.4 三张清单的交集
如果把三张清单的重叠项挑出来,只有一条是所有角色都必须处理的:方向标识不能当独立对象。
- 数据整合的人:不能把它当四条反应去统计
- 做 ML 的人:不能把它当四个样本去切分
- 做 KG 的人:不能把它当同一个节点的四个属性
这三种错误的表现形式不同,根因是同一个:没有把「四个 ID 各自是完整陈述」这件事吃透。§2 与附录 F 反复讲这一点,是因为它是这份数据里唯一一个「理解错了会静默出错」的地方——不会报错,只会给出看起来合理的错误结果。
编辑说明
本篇数字分四层来源,已在附录 B 列明:官方属性文件(release 142 / 2026-09-02)、官方 news 页(各版本的反应数/参与者数/文献数)、官方 LICENSE(CC BY 4.0 与免责声明)、以及本文对 release 142 各 TSV 与 txt.gz 文件的逐行统计(条目总数、master 数、is_a 数、废弃数、各映射表规模)。核验时间 2026-10-26。
未做的核验:RDF 与 BioPAX 文件未下载,SPARQL 端点未实际查询,因此「RDF 表达完整」「SPARQL 可用」依据官方文档与论文描述;ChEBI 快照的具体版本号未核对;rhea2metacyc.tsv 与 rhea2kegg_reaction.tsv 的目标库当前规模未统计(需对方库版本);rhea2xrefs.tsv 中 17,382 行「other」类未逐项归类。
rhea-ec-iubmb.tsv 里 MASTER_ID 列为空(7,941 行全部为空),这是该文件的字段设计,不是数据缺失——它按 reaction_id + direction 组织,MASTER_ID 在有值时才有意义。本篇正文未把这一列当作出错。
论文与 news 页在「反应数」上的口径一致(都以 master 计),但第三方介绍经常把方向标识条目数误报成反应数,已在避坑清单中列出。
许可为 CC BY 4.0,可复制、再分发、改编,署名是唯一义务。本篇引用其统计数字属正常引用。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- disgenet — 共享标签:药物发现与化学 / 基因组学与多组学 / 知识图谱
- open-targets — 共享标签:药物发现与化学 / 基因组学与多组学 / 知识图谱
- ttd — 共享标签:药物发现与化学 / 化学信息学 / 知识图谱
- reactome — 共享标签:化学信息学 / 基因组学与多组学 / 知识图谱
- hmdb — 共享标签:药物发现与化学 / 化学信息学 / 基因组学与多组学
- binding-moad — 共享标签:药物发现与化学 / 化学信息学 / 基因组学与多组学
- chebi — 共享标签:药物发现与化学 / 化学信息学 / 知识图谱
- lincs-l1000 — 共享标签:药物发现与化学 / 化学信息学 / 基因组学与多组学
- dgidb — 共享标签:药物发现与化学 / 化学信息学 / 知识图谱
- jump-cell-painting — 共享标签:药物发现与化学 / 化学信息学 / 基因组学与多组学
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

