【RDKit】RWMol で分子(Mol instance) を編集する

RDKitを使っていると、扱っている分子を編集したい時がたまにあるかと思います。 RDKitにおける分子は通常Mol instance として扱われてますが、このままでは編集はできないため一度RWMol (read/write Mol) instance に変換してあげる必要があります。 そこで本記事では、RWMol instance での分子の編集についてまとめていこうと思います。

ここでは簡単な例として、アスピリン -> サリチル酸 -> アスピリン の変換を通してRWMolの使い方について記載していこうと思います。

ざっとした流れを先に書いておくと、

  1. Mol -> RWMol (rwmol = RWMol(Mol))
  2. RWMol で編集
  3. RWMol -> Mol (mol = RWMol.GetMol())

になります。それでは実際のコードの解説に進みます。

Mol instance・RWMol instance の準備

ここは通常通りChem.MolFromSmiles()等で分子を読み込めば良いのですが、ここで分子にAtom Mappingをしておくことが大切です。 原子の削除をする際にindex を指定するのですが、このindex は都度ズレてしまい期待通りの編集ができなくなるリスクがあります。 Atom Mapping をしておけば、編集前の分子における原子を正確に指定できるので安心です。

1
2
3
4
mol = Chem.MolFromSmiles("CC(=O)OC1=CC=CC=C1C(O)=O")  # aspirin
for i, atom in enumerate(mol.GetAtoms(), start=1):
atom.SetAtomMapNum(i)
Draw.MolsToGridImage([mol])

出力

原子の削除

「アスピリン -> サリチル酸」へ変換するため、C1, C2, O3の原子を削除します。

1
2
3
4
5
6
7
8
9
10
11
rwmol = RWMol(mol)

rm_map_num = [1, 2, 3]
for map_num in rm_map_num:
idx = [atom.GetIdx() for atom in rwmol.GetAtoms() if atom.GetAtomMapNum() == map_num][0]
rwmol.RemoveAtom(idx)

mol = rwmol.GetMol()
Chem.SanitizeMol(mol)

Draw.MolsToGridImage([mol], subImgSize=(250,250))

出力

削除対象の原子の指定にAtom Mapで指定ができないため、Atom Map から原子のindexを取得する面倒な処理をしています。

原子の追加

「サリチル酸 -> アスピリン」へ変換するため、O4に対してCC=Oを追加します。 (今回の例では無理やりループで回すこともできましたが、可読性が下がって理解しにくくなりそうなので書き下してます。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
rwmol = RWMol(mol)

# C2 -> O4 (single bond)
from_idx = rwmol.AddAtom(Chem.Atom(6))
to_idx = [atom.GetIdx() for atom in rwmol.GetAtoms() if atom.GetAtomMapNum() == 4][0]
rwmol.GetAtomWithIdx(from_idx).SetAtomMapNum(2)
rwmol.AddBond(from_idx, to_idx, Chem.BondType.SINGLE)
# C1 -> C2 (single bond)
from_idx = rwmol.AddAtom(Chem.Atom(6))
to_idx = [atom.GetIdx() for atom in rwmol.GetAtoms() if atom.GetAtomMapNum() == 2][0]
rwmol.GetAtomWithIdx(from_idx).SetAtomMapNum(1)
rwmol.AddBond(from_idx, to_idx, Chem.BondType.SINGLE)
# O3 -> C2 (double bond)
from_idx = rwmol.AddAtom(Chem.Atom(8))
to_idx = [atom.GetIdx() for atom in rwmol.GetAtoms() if atom.GetAtomMapNum() == 2][0]
rwmol.GetAtomWithIdx(from_idx).SetAtomMapNum(3)
rwmol.AddBond(from_idx, to_idx, Chem.BondType.DOUBLE)

mol = rwmol.GetMol()
Chem.SanitizeMol(mol)

Draw.MolsToGridImage([mol])

出力

原子の削除に比べて、原子の追加はマニュアルでやる必要に迫られることが多そうな印象です。 場合によっては自動化できるかと思いますが、ロジックを組むのは少し面倒そうです。

終わりに

RDKitで分子を編集したいという人がそもそも少ないからか、RWMol にパッと辿りつかず少し苦労したのでまとめた感じです。

私自身では原子の削除目的でしか利用したことがないためあまり気にしていませんでしたが、原子の追加はBondの追加もしないといけないのでだいぶ処理が煩雑になりますね。

ちなみに、Draw.MolToImage()を使わずに Draw.MolsToGridImage()をわざわざ使っているのは、出力される図が綺麗だからです。

それでは。

参照

class rdkit.Chem.rdchem.RWMol