第3章:分子数据库构建——ChEMBL、PubChem、ZINC、PDB等公共资源
做虚拟筛选,说白了第一步就是找数据。没有好数据,后面算法再牛也白搭。我个人习惯把这一步叫做“数据地基”——地基打不牢,上面的pipeline再花哨,结果也经不起推敲。
市面上公开的分子数据库不少,但真正能在生产环境里直接用的,其实就那几个。我这些年折腾下来,最常用的就是ChEMBL、PubChem、ZINC和PDB。每个库的脾气秉性都不一样,得摸透了才能用好。
嗯,咱们一个一个来看。
3.1 ChEMBL——生物活性数据的首选
ChEMBL是欧洲生物信息学研究所(EBI)维护的。它最厉害的地方在于,数据是人工从文献里抠出来的,质量非常高。我记得有一次做靶点验证,从ChEMBL拉出来的IC50数据跟后续实验的吻合度超过90%。
ChEMBL提供两种获取方式:一是直接下载MySQL dump,二是通过REST API查询。我个人更推荐API,省去建库的折腾。
举个例子,你想查某个靶点对应的活性分子,可以这样调API:
# 获取与靶点CHEMBL ID关联的化合物列表
curl -X GET "https://www.ebi.ac.uk/chembl/api/data/activity.json?target_chembl_id=CHEMBL203&limit=10"
返回的是JSON格式,解析起来很方便。但是要注意,API有访问频率限制——好像是每秒最多3次请求。我曾经有个同事没注意这个,一把梭子发了上千个并发请求,直接被封了IP。
3.2 PubChem——数据量最大,但最“脏”
PubChem由美国NIH维护。它是目前最大的免费化学数据库,化合物数量超过1亿。但说实话,数据质量参差不齐。
为什么?因为PubChem的数据来源太杂了——有科研机构提交的,有专利里挖的,还有供应商的库存。同一分子在不同来源里结构表示可能都不一样。
所以用PubChem的时候,我强烈建议你先做个去重和标准化。比如用RDKit对分子进行规范:
from rdkit import Chem
from rdkit.Chem import SaltRemover
# 读取PubChem的SDF文件
mol = Chem.MolFromMolFile("pubchem_example.sdf")
# 去除盐和溶剂
remover = SaltRemover.SaltRemover()
mol_clean = remover.StripMol(mol, dontRemoveEverything=True)
# 标准化为规范SMILES
canonical_smiles = Chem.MolToSmiles(mol_clean)
print(canonical_smiles)
你想想看,如果这一步不做,后面跑的对接结果很可能因为分子表示不一致而出现偏差。我在项目里就吃过这个亏,花了三天时间排查,最后发现是PubChem里同一个分子有两种SMILES表示。
3.3 ZINC——虚拟筛选的“主力军”
ZINC是专门为虚拟筛选设计的数据库。它最大的卖点是——所有分子都经过了“类药性”过滤。这意味着你不用再重复做Lipinski五规则检查了。
ZINC把分子分成了几个档次:
| 分子集 | 数量(约) | 特点 | 典型用途 |
|---|---|---|---|
| ZINC-20 | 2.3亿 | 商品化/可采购分子 | 虚拟筛选后直接购买 |
| ZINC-22 | 16亿 | 包含虚拟分子 | 大规模虚拟筛选 |
| ZINC-FDA | ~3000 | 已批准药物 | 药物重定位 |
下载ZINC数据时,我通常用他们的官方工具zinc-downloader。你指定想要的分组和格式,它会自动切分:
# 下载ZINC-20中的“Lead-like”分子集,格式为mol2
zinc-downloader --subset lead-like --format mol2 --output ./zinc_data/
说实话,ZINC的目录结构一开始看着有点晕——它按tranche(分片)来组织。每个分片包含约10万个分子,方便并行处理。这一点在设计pipeline时特别重要。
3.4 PDB——蛋白质结构的“仓库”
PDB(Protein Data Bank)是结构数据的老祖宗。做分子对接时,你是拿它存的小分子配体,还是拿它存的蛋白受体?答案通常是后者。
PDB里一个关键概念是分辨率。分辨率小于2.0 Å的结构才算靠谱。我个人的筛选标准是:
- 分辨率 ≤ 2.0 Å —— 可用
- 分辨率 ≤ 1.5 Å —— 优质
- 分辨率 > 2.5 Å —— 慎用
通过PDB的API获取结构信息很简单:
# 获取4AGN(一个激酶结构)的元数据
curl -X GET "https://data.rcsb.org/rest/v1/core/entry/4AGN"
但要注意,PDB里很多结构是有缺陷的——比如缺失的侧链、不合理的键长、或者水分子没处理好。所以下载后一定要做结构准备,像加氢、修复侧链、分配电荷这些步骤,一个都不能省。
3.5 构建本地数据库的最佳实践
说到这里,你可能会问:那这四类数据到底怎么整合到pipeline里?
我个人建议的做法是:建立一个本地分子数据库。把所有数据拉下来,存到你熟悉的关系型或非关系型数据库里。
比如,我用PostgreSQL建过这样一个schema:
CREATE TABLE molecules (
id SERIAL PRIMARY KEY,
source_db TEXT NOT NULL, -- 来源: chembl/pubchem/zinc/pdb
source_id TEXT NOT NULL, -- 原始ID
smiles TEXT, -- 规范SMILES
inchi TEXT, -- InChI字符串
molecular_weight DOUBLE PRECISION,
logp DOUBLE PRECISION,
num_h_donors INTEGER,
num_h_acceptors INTEGER,
num_rotatable_bonds INTEGER,
data JSONB, -- 扩展属性,灵活存储
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_molecules_smiles ON molecules USING hash (smiles);
CREATE INDEX idx_molecules_source ON molecules (source_db);
为什么要用JSONB存扩展属性?因为不同数据库的元数据差异太大了。ChEMBL有pChEMBL值,PubChem有XlogP,ZINC有采购价格——统一放在JSONB里最灵活。
下面这张图,总结了我构建分子数据库时的核心流程和思考路径:
3.6 数据更新的节奏
数据库不是一次建完就完事了。ChEMBL每两个月更新一次,PubChem不定期更新,ZINC三个月左右出一次快照。这设计pipeline时需要考虑进去。
我的做法是:写一个cron job,每月初自动检查各数据源的版本号。如果有更新,就增量下载差异部分,然后触发pipeline重新跑一遍筛选。
# 0 0 1 * * /opt/scripts/update_db.sh --check-version --download-diff
当然,如果你的筛选目标是做一个静态数据集的分析,那不用这么频繁。但如果是长期运行的筛选服务,数据同步就是必修课了。
好了,关于分子数据库构建这块,核心就是这些。记住:数据库本身不产生价值,真正值钱的是你从中筛选出那些有活性的分子。而这一步能不能做好,很大程度上取决于你数据的质量和组织方式。