合成容易性スコア（SASCore）をGoogleColabで計算するぞい

# はじめに
ChatGPTの画像生成がつよつよになったので、それで遊んでいたら一日終わりますよね？
そしたら全然記事を書く時間がありませんでした。~~嘘です、すいませんサボってました~~

タイトルだけ書いた下書きが積んであるので少しずつ処理していきたい・・・(;'∀')

さて、私の本業は実は化学者です。ある化合物がどれくらい合成しやすいのかって定量的に評価できたらいいですよね。そうでもないですか。正直、熟練した研究者なら見た瞬間にわかります。
じゃあ何がいいって、マテリアルズ・インフォマティクスに応用できるってことですよね。

例えば、①機械学習で高性能が予想された複数の化合物を合成容易性スコアでさらに絞り込む（スクリーニング）、②合成容易性スコア自体を機械学習モデルの特徴量として使う、③ベイズ最適化などで「合成しやすい領域」に制約をかけられる、とか考えられます。

そんなことで、ファーストステップとして、GoogleColabで合成容易性スコア（SAScore）を計算してみます。


# 合成容易性スコア
実装に入る前に、合成容易性スコアに関して少し深堀しておきましょう。

繰り返しになりますが、合成容易性スコアとは、ある分子がどれくらい「作りやすい」かを評価する指標です。

合成容易性スコアに関係するところで、有名どころで言えば、SASCore（Synthetic Accessibility Score）、RAScore（Retrosynthetic Accessibility Score）、SCScore（Synthetic Complexity Score）、SYBA（Bayesian estimation of synthetic accessibility）などがあります。それぞれ意味合いが異なりますので、表で整理しておきましょう。

| 指標                                                     | 評価対象     | スコア範囲            | 特徴                                                                                      | 
| -------------------------------------------------------- | ------------ | --------------------- | ----------------------------------------------------------------------------------------- | 
| **SA Score**<br>(Synthetic Accessibility Score)              | 合成容易性   | 1～10 (低いほど良い)  | サブストラクチャー頻度やトポロジーに基づく伝統的なスコア。RDKitベース。                       | 
| **SC Score**<br>(Synthetic Complexity Score)                 | 合成複雑性   | 0～5 (低いほど良い)   | 深層学習（Reaxysデータ1200万件）を用いた複雑性評価。ニューラルネット。                    | 
| **RA Score**<br>(Retrosynthetic Accessibility Score)         | 逆合成容易性 | 0～1 (高いほど良い)   | 逆合成解析のシミュレーションを活用<br>ASKCOS / AiZynthFinder                              | 
| **SYBA**<br>(Bayesian estimation of synthetic accessibility) | 合成容易性   | -1～1（高いほど良い） | ベイズ分類器（Naive Bayes）で合成可能性を判定。反応ベースでなく構造ベース。データ駆動型。 | 
|                                                          | 

SAScoreとSYBAはどちらも構造ベースで視点は同じなので、SAScore、SCScore、RAScoreに関してさらに詳細に表にしました。

| 項目             | SAScore                                                            | SCScore                                                              | RAScore                                                                | 
| ---------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------- | ---------------------------------------------------------------------- | 
| 目的             | 合成の容易さを定量化                                               | 合成の複雑さを定量化                                                 | 実際の逆合成可能性を定量化                                             | 
| スコア範囲       | 1（容易）～10（困難）                                              | 1（単純）～5（複雑）                                                 | 0（困難）～1（容易）                                                   | 
| アプローチ       | 部分構造の出現頻度 + 分子構造の複雑さ                              | ニューラルネットによる構造の複雑性評価                               | 逆合成モデル（機械学習ベース）による可合成性予測                       | 
| 元データ         | PubChem（~100万件）                                                | Reaxys（1200万件の反応）                                             | 逆合成ツール（AiZynthFinderなど）の出力                                | 
| 評価対象         | 合成しやすさの「見た目」                                           | 合成経路に必要なステップ数に相関する複雑さ                           | 合成可能性（逆合成が成功するか）                                       | 
| 主な長所         | ・高速で大規模スクリーニングに最適<br>・RDKitで簡単に導入可        | ・合成ルート上の複雑性を非線形に表現<br>・直感的な構造の難易度と合致 | ・最新の合成手法を反映<br>・実際の合成可能性との相関が高い             | 
| 主な短所         | ・合成経路を考慮しない<br>・新規構造に弱い                         | ・合成可能性ではなく複雑性評価<br>・計算がやや重い                   | ・計算負荷が高い<br>・逆合成精度に依存<br>・新規構造には弱いことも     | 
| 見落としがちな点 | ・分子サイズペナルティが強く出る<br>・実際は合成可能でも高スコアに | ・立体化学や官能基の難しさを過小評価しがち                           | ・逆合成ツールの限界で「本当は作れる」分子が困難と判断される可能性     | 
| 向いている用途   | ・第一段階の化合物スクリーニング<br>・スピード重視のプロジェクト   | ・構造の設計段階での複雑性比較<br>・合成経路設計の補助               | ・逆合成シミュレーションを伴う創薬・材料設計<br>・AIベースのルート探索 | 
|                  | 

結局どれがベストとか精度がいいとかではなく、視点が違うのでそれぞれのスコアを見て総合的に判断しましょうってことです。

# GoogleColab
実際にSASCoreをGoogleColabで動かしてみましょう。
※前提知識としてRDkitの扱いは心得ているものとします。

まずはrdkitとsascore（はgithubから）インストールしましょう。
```python:
!pip install rdkit
!wget https://raw.githubusercontent.com/rdkit/rdkit/master/Contrib/SA_Score/sascorer.py -O sascorer.py
!wget https://github.com/rdkit/rdkit/raw/master/Contrib/SA_Score/fpscores.pkl.gz -O fpscores.pkl.gz
```

続いて必要なモジュールをimportしておきましょう。
```python:
import rdkit
from rdkit import Chem
from rdkit.Chem import Descriptors
from rdkit.Chem import Draw
import matplotlib.pyplot as plt
import sascorer
import pickle
import gzip

with gzip.open("fpscores.pkl.gz", "rb") as f:
    sascorer.scoreFuncs = pickle.load(f)
```

試しにアスピリンのSAScoreを計算してみます。
流れとしては、化合物のSMILESをrdkitでMolオブジェクトに変換し、sascore.calculateScore()に渡せばオーケーです。
```python:
# アスピリンのSMILES
smiles = "CC(=O)OC1=CC=CC=C1C(=O)O"

# SMILES を RDKit の Mol オブジェクトに変換
mol = Chem.MolFromSmiles(smiles)

# SA スコアを計算
if mol:
    sa_score = sascorer.calculateScore(mol)

    # 画像を描画
    fig, ax = plt.subplots(figsize=(3, 3))
    img = Draw.MolToImage(mol)
    ax.imshow(img)
    ax.axis("off")
    ax.set_title(f"SA Score: {sa_score:.2f}")
    plt.show()
```

> 出力
> ![{AA6E18AD-482C-4138-8470-B312726C0607}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/bddfecbb-d2cb-4a05-b908-3effeb3399ae.png)

簡単ですね。

複数の分子を同時に計算してみます。
```python:
# SMILES のリスト
smiles_list = [
    "CC(=O)OC1=CC=CC=C1C(=O)O",  # アスピリン
    "Cn1cnc2c1c(=O)n(c(=O)n2C)C",  # カフェイン
    "CC(C)CC1=CC=C(C=C1)C(C)C(=O)O",  # イブプロフェン
    "CCC(CC)OC1C=C(CC(C1NC(=O)C)N)C(=O)OCC",  # オルセタミブル
    "O=C(OC1C2C3(OC(=O)C)COC3CC(O)C2(C(=O)C(OC(=O)C)C4=C(C)C(OC(=O)C(O)C(NC(=O)C=5C=CC=CC5)C=6C=CC=CC6)CC1(O)C4(C)C)C)C=7C=CC=CC7" # タキソール
]

# SA スコアの計算
sa_scores = []
valid_mols = []

for smiles in smiles_list:
    mol = Chem.MolFromSmiles(smiles)
    if mol:
        sa_score = sascorer.calculateScore(mol)
        sa_scores.append(sa_score)
        valid_mols.append(mol)

# 分子画像をリストで作成
img_list = []
for mol, score in zip(valid_mols, sa_scores):
    img_list.append(Draw.MolToImage(mol, legend=f"SA: {score:.2f}"))

# 画像をまとめて表示
fig, axes = plt.subplots(1, len(img_list), figsize=(len(img_list) * 3, 3))

for ax, img in zip(axes, img_list):
    ax.imshow(img)
    ax.axis("off")

plt.show()
```

> 出力
> ![{F01378BA-4DA7-40B7-A8D7-BA4384BE7B33}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493004/c575f757-bdf5-4c6d-a500-f09e85abf506.png)


タキソールやオルセタミブル（タミフル）はスコアが比較的高いので合成しにくいことが伺えます。
（まぁタミフルは研究が大変進んでいて、今では[ワンポット](https://chemistry-europe.onlinelibrary.wiley.com/doi/abs/10.1002/chem.201302371 "One-Pot Synthesis of (−)-Oseltamivir and Mechanistic Insights into the Organocatalyzed Michael Reaction")で合成できたりするんですが。）
いろんな分子を試してみると面白いですね。

簡単ですが、今回はここまでです。

# おわりに
今回はSAScoreをGoogleColabで計算しました。
現在はSMILESを打ち込む or CSVで渡すとSAScoreとSCScoreを同時に計算して比較することができるアプリを開発しましたので、次回の記事で紹介します。

それではまた('ω')ノ

-----
参考

https://jcheminf.biomedcentral.com/articles/10.1186/1758-2946-1-8

https://github.com/rdkit/rdkit/tree/master/Contrib/SA_Score

https://future-chem.com/rdkit-sa-score/