RDKit入門⑧：反応式の取り扱い(後編)

今回もRDKitでの反応式の取り扱いに関して紹介します。
今回の内容は反応生成物の重複削除および自作関数による繰り返し反応です。

これまでの記事のシリーズは以下をご覧ください。

[RDKit入門①：まずは環境構築][1]
[RDKit入門②：1分子の読み込みと部分構造検索][2]
[RDKit入門③：複数分子の読み込み (前編)と分子群の描画][3]
[RDKit入門④：複数分子の読み込み (後編)とデータフレームの加工][4]
[RDKit入門⑤：データフレーム内の分子群に対する部分構造検索][5]
[RDKit入門⑥：Morganフィンガープリントの作成とそれを用いたタニモト係数の計算による分子類似性評価][6]
[RDKit入門⑦：反応式の取り扱い(前編)][7]
[RDKitで化学反応を扱った際の生成物群を整理し図示する方法][8]
[1]:https://qiita.com/Ru-PNP/items/ed5a8530611ef0d712b7
[2]:https://qiita.com/Ru-PNP/items/58d733ef327677d273fd
[3]:https://qiita.com/Ru-PNP/items/1cea34b864e993e4e1e1
[4]:https://qiita.com/Ru-PNP/items/62a108d92c1ddd522e58
[5]:https://qiita.com/Ru-PNP/items/b469ac1b907909a9d821
[6]:https://qiita.com/Ru-PNP/items/79873f0e3eab444f5bfe
[7]:https://qiita.com/Ru-PNP/items/49a080a015414553bbad
[8]:https://qiita.com/Ru-PNP/items/baebf99e269bd7fb2fb5

###環境
- Windows 10
- python 3.8.8
- RDKit 2021.03.1

---
##反応生成物の重複削除

まずはパッケージの読み込みを行います。

```python
from rdkit import Chem
from rdkit.Chem import AllChem, Draw
from itertools import chain
#パッケージの読み込み
```

続いて反応を定義します。今回は芳香環上のC-H結合をブロモ化する反応です。

```python
rxn = AllChem.ReactionFromSmarts("[ch:1]>>[ch0:1]Br")
#ブロモ化の反応を定義し、rxnと命名。
```
続いて基質としてトルエンを定義し、トルエンに対してrxnを適用し、描画します。

```python
toluene = Chem.MolFromSmiles("Cc1ccccc1")
#トルエンを定義した。
monobromides = list(chain.from_iterable(rxn.RunReactants([toluene])))
#トルエンのブロモ化を実施し、リストに生成物を並べてmonobromidesと定義した。

Draw.MolsToGridImage(monobromides, molsPerRow = 5)
#monobromides内の分子を描画した。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1144410/9f57514b-81d7-228d-2551-7f75b0547e78.png)

RDKitで化学反応を実施すると分子の対称性は考慮されません。
化学的には3種類の生成物しか考えられませんが、tolueneには5つの芳香族C-H結合があるため、
重複を含めて5種類のmolオブジェクトが出力されました。

続いて重複を削除します。重複削除には以下の方針を用います。

①monobomides内の分子をSMILESに変更する。
→SMILESに変更する際に同一分子からは同一のSMILESが生成される。
②SMILES構造式を集合に格納する。
→集合に格納することでSMILES構造式の重複が解消される。
③集合内のSMILES構造式をmolオブジェクトに変換する。

内包表記を二重に使用することで上記の処理を実施します。

```python
monobromides_unique = [Chem.MolFromSmiles(smile) for smile in {Chem.MolToSmiles(mol) for mol in monobromides}]
#SMILESに変換した際に集合に入れることで重複を削除し、再度molオブジェクトに変換した。
#処理後のmolオブジェクトを格納したリストをmonobromides_uniqueと定義した。

Draw.MolsToGridImage(monobromides_unique)
#monobromides_unique内の分子を描画した
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1144410/761b091a-94a5-88ce-43c4-a0497e6e962c.png)

---

##自作関数の作成による化学反応の繰り返し

RDKitの化学反応モジュールは反応を1回実施するのみですが、
同じ反応を繰り返した際に得られる化合物全てのリストが欲しい場合もあると思います。
そういった場合は自作関数を定義する必要があります。

```python
def multi_bromination(mol):
    rxn = AllChem.ReactionFromSmarts("[ch:1]>>[c:1]Br")
    #反応の定義。
    bromides = list(chain.from_iterable(rxn.RunReactants([mol])))
    #molに対して1回目のrxnを実施し、生成物の格納されたリストをbromidesと命名。
    for bromide in bromides:
        bromide.UpdatePropertyCache(strict = False)
        #価数などの更新作業。今回の反応では入れないとエラーが出る。
        if rxn.IsMoleculeReactant(bromide):
            bromides.extend(list(chain.from_iterable(rxn.RunReactants([bromide]))))
        #bromides内の分子がrxnの基質だった場合、さらに反応を実施して生成物をbromidesに追加。
    bromides_unique = [Chem.MolFromSmiles(smile) for smile in {Chem.MolToSmiles(mol) for mol in bromides}]
    #重複分子の削除
    return bromides_unique
```

反応を繰り返す際、反応の種類によっては価数等の更新が必要となります。
今回はUpdatePropertyCashe(strict = False)を加えることで更新を行い、エラーを回避しています。

実際にmulti_brominationをtolueneに対して適用してみましょう。

```python
products = multi_bromination(toluene)
#multi_brominationにtolueneを適用し、得られたリストをproductsと命名した。
Draw.MolsToGridImage(products, molsPerRow = 5, maxMols = len(products))
#products内の分子を描画した。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1144410/70940a94-b9d3-bb5a-d893-b27905097fa5.png)


###分子の整列

上記の分子群描画では分子の向きがバラバラなため少々分かりづらいです。
そこでtolueneをテンプレートとして分子を回転させてみます。
回転にはAllChem.GenerateDepictionMatching2DStructureを使用します。

```python
AllChem.Compute2DCoords(toluene)
#tolueneの二次元座標を計算した。
for mol in products:
    if mol.HasSubstructMatch(toluene):
        AllChem.GenerateDepictionMatching2DStructure(mol, toluene)
#tolueneをテンプレートとしてproducts_unique内のmolオブジェクトを整列させた。
```

この処理をおこなった跡に再度分子群の描画を行うと向きが統一されています。

```python
Draw.MolsToGridImage(products, molsPerRow = 5, maxMols = len(products))
#products内の分子を描画した。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1144410/fb21bf03-e43c-628f-5ac4-45fe1ead118a.png)

---

##おわりに

今回はRDKitを用いて以下の内容を実施いたしました。

- 反応生成物の重複削除
- 自作関数の作成による化学反応の繰り返し
- 分子の整列

###参考
[RDKitでケモインフォマティクスに入門][9]
[RDKitの分子Molオブジェクトを扱う][10]
[9]:https://future-chem.com/rdkit-intro/
[10]:https://future-chem.com/rdkit-mol/