最近在项目中需要将SMILES转成InChiKey,通常可以在OpenBabelGUI中操作完成,但是对于大量数据在OpenBabelGUI中操作就有些不方便且容易失误。这里记录一下我解决这个问题的过程。
安装相关包
先建立一个虚拟环境,安装RDKit:
1
| conda create -c rdkit -n my-rdkit-env rdkit
|
然后在虚拟环境下安装OpenBabel:
1
| conda install -n my-rdkit-env -c openbabel openbabel
|
出现的问题
最初想用Pybel实现,然而发现Pybel并不支持输出格式为InChiKey,既然这条路走不通,就换个方案吧。于是想查看OpenBabel的文档看看能不能实现,然而发现这玩意的python接口只是寥寥几言,也没有具体的文档。不过Google到了一个轮子写了如何将SMILES转成InChiKey,代码如下:
1 2 3 4 5 6 7
| import openbabel as ob conv = ob.OBConversion() conv.SetInAndOutFormats("smi", "inchi") conv.SetOptions("K", conv.OUTOPTIONS) mol = ob.OBMol() conv.ReadString(mol, "CC(=O)Cl") inchikey = conv.WriteString(mol):
|
本想着问题解决了,不过试了一下发现并不能用。而且可耻的找不到原因……
不过也问题不大,RDKit可以把SMILES转成InChi,然后再把InChi变成InChiKey就行了,于是写了个函数实现:
1 2 3 4 5 6 7
| from rdkit import Chem from rdkit.Chem.inchi import rdinchi def smiletoinchikey(smile): mol = Chem.MolFromSmiles(smile) inchi = rdinchi.MolToInchi(mol) inchikey = rdinchi.InchiToInchiKey(inchi[0]) return inchikey
|
然而在处理项目文件时发现,有些SMILES式RDKit不能识别,导致程序出错。如Clc1c([C@@H]2[C@@H]([N+H3])CC(CN3CCC(C(=O)O)CC3)=CC2)ccc(Cl)c1
,于是写了个函数利用Pybel将其转成Canonical SMILES。最后还是有一些剩余问题,比如Oc1ccc([C+2]2345[B-2]678[B-3]9%10%11([C-3])[C+]%12%13%14[B-2]%15%169[B-2]26%10[B-2]23%15[B-2]364[B-2]457[B-2]8%11%12[B-2]%1334[B-2]%14%1626)cc1
转成Canonical SMILES依然无法读取,又或者O=BOB(OB(OB=O)[O-])[O-]
没转换前能读取,转换后不能读取,只能按例外处理。
最后代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
import pybel from rdkit import Chem from rdkit.Chem.inchi import rdinchi
def smitosmile(smi): mol = pybel.readstring("smi", smi) smile = mol.write('can') smile = smile.replace('\t\n', '') return smile def smiletoinchikey(smile): mol = Chem.MolFromSmiles(smile) if mol is None: smi = smitosmile(smile) mol = Chem.MolFromSmiles(smi) inchi = rdinchi.MolToInchi(mol) inchikey = rdinchi.InchiToInchiKey(inchi[0]) return inchikey
|
用OpenBabel同样也可以把SMILES转成Canonical SMILES:
1 2 3 4 5 6 7 8 9 10
| import openbabel as ob def obsmitosmile(smi): conv = ob.OBConversion() conv.SetInAndOutFormats("smi", "can") conv.SetOptions("K", conv.OUTOPTIONS) mol = ob.OBMol() conv.ReadString(mol, smi) smile = conv.WriteString(mol) smile = smile.replace('\t\n', '') return smile
|