あなたのおっしゃる「タニモト係数」って、どれのことかしら？



化合物の類似性を語るにあたって、有名な指標に「タニモト係数」があります。ところが、「タニモト係数」とだけしか言わない人がけっこういて、「それだけでは説明不十分ですよね？」って悶々とする機会がけっこうあるわけです。

# たとえば次の化合物セットを使いましょう

化合物数は１０個です。

```python
smiles = [
    'C1=CC=C2C3CC(CNC3)CN2C1=O',
    'CN1c2c(C(N(C)C1=O)=O)[nH0](CC(CO)O)c[nH0]2',
    'CN1C2CC(CC1C1C2O1)OC(C(c1ccccc1)CO)=O',
    'CN1C2CC(CC1C1C2O1)OC(C(c1cccnc1)CO)=O', # 一つ上の化合物と類似
    'CN(C=1C(=O)N(c2ccccc2)N(C1C)C)C',
    'CN(C=1C(=O)N(C2CCCCC2)N(C1C)C)C', # 一つ上の化合物と類似
    'OCC1C(C(C(C(OCC2C(C(C(C(OC(c3ccccc3)C#N)O2)O)O)O)O1)O)O)O',
    'OCc1ccccc1OC1C(C(C(C(CO)O1)O)O)O',
    'OCc1cc(N)ccc1OC1C(C(C(C(CO)O1)O)O)O', # 一つ上の化合物と類似
    '[nH0]1c(OC)c2c([nH0]cc[nH0]2)[nH0]c1',
]
```

# SMILES表記からRDKitで化合物を生成


```python
from rdkit import Chem

mols = [Chem.MolFromSmiles(smile) for smile in smiles]
```

# Morgan fingerprint (の一種)を生成


```python
from rdkit.Chem import AllChem

fps = [AllChem.GetMorganFingerprint(mol, 3, useFeatures=True) for mol in mols]
```

# タニモト係数を計算


```python
from rdkit import DataStructs

sim_matrix = [DataStructs.BulkTanimotoSimilarity(fp, fps) for fp in fps]
```

# タニモト係数の分布

このようにすれば、タニモト係数の分布が見られます。タニモト係数 = 1 のものは同一分子だと思われますが、それ以外でタニモト係数が高めの分子対がありますね。それが何なのか、調べてみてください（あるいは想像してみてください）


```python
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

plt.hist(np.array(sim_matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_9_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/80e754f7-03b4-210d-f0a6-082ceebf4b1d.png)



# で、Morgan fingerprint にも色々ありまして

Morgan fingerprintもパラメータがいろいろあって、それを変えるとタニモト係数の数値も変わるわけです。


```python
fps = [AllChem.GetMorganFingerprint(mol, 2, useFeatures=True) for mol in mols]
sim_matrix = [DataStructs.BulkTanimotoSimilarity(fp, fps) for fp in fps]
plt.hist(np.array(sim_matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_11_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/921ec4b2-f7dc-4cde-afe0-4c7e0187d3ea.png)




```python
fps = [AllChem.GetMorganFingerprint(mol, 1, useFeatures=True) for mol in mols]
sim_matrix = [DataStructs.BulkTanimotoSimilarity(fp, fps) for fp in fps]
plt.hist(np.array(sim_matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_12_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/99ffed5d-b731-7f08-8e27-95172fafd032.png)




```python
fps = [AllChem.GetMorganFingerprintAsBitVect(mol, 3, 1024) for mol in mols]
sim_matrix = [DataStructs.BulkTanimotoSimilarity(fp, fps) for fp in fps]
plt.hist(np.array(sim_matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_13_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/b672bd25-9bdd-16ce-74c3-e5f7d5dbed45.png)




```python
fps = [AllChem.GetMorganFingerprintAsBitVect(mol, 3, 2048) for mol in mols]
sim_matrix = [DataStructs.BulkTanimotoSimilarity(fp, fps) for fp in fps]
plt.hist(np.array(sim_matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_14_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/3e815d73-4ae9-a7ae-fa38-51b7b92c5e88.png)



# で、フィンガープリントは他にもありまして

全部計算するのメンドくさいので２つだけ。重要なことの一つとして、下記の計算結果ではタニモト係数が1.0のものが１０件以上出てきます。つまり、同一分子でなくてもタニモト係数が1.0になる場合があることは知っておきましょう。


```python
fps = [AllChem.GetMACCSKeysFingerprint(mol) for mol in mols]
sim_matrix = [DataStructs.BulkTanimotoSimilarity(fp, fps) for fp in fps]
plt.hist(np.array(sim_matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_17_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/e9494460-d99d-0a3c-4b60-15158d6d3b95.png)




```python
fps = [Chem.RDKFingerprint(mol) for mol in mols]
sim_matrix = [DataStructs.BulkTanimotoSimilarity(fp, fps) for fp in fps]
plt.hist(np.array(sim_matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_18_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/f1813182-ed57-cdb8-a1f1-deef534d980f.png)


# MCSを用いたタニモト係数も定義できるわけでして


```python
from rdkit.Chem import rdFMCS

matrix = []
for mol1 in mols:
    for mol2 in mols:
        mcs = rdFMCS.FindMCS([mol1, mol2])
        a1 = len(mol1.GetAtoms())
        a2 = len(mol2.GetAtoms())
        matrix.append(mcs.numAtoms / (a1 + a2 - mcs.numAtoms) )

plt.hist(np.array(matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_20_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/9b8d655b-a38d-6e4c-995a-cfc9aa9263d4.png)



# MCSにもいろんなオプションがあるわけでして


```python
from rdkit.Chem import rdFMCS

matrix = []
for mol1 in mols:
    for mol2 in mols:
        mcs = rdFMCS.FindMCS([mol1, mol2], atomCompare=rdFMCS.AtomCompare.CompareAny)
        a1 = len(mol1.GetAtoms())
        a2 = len(mol2.GetAtoms())
        matrix.append(mcs.numAtoms / (a1 + a2 - mcs.numAtoms) )

plt.hist(np.array(matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_22_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/01c5175a-ad67-0a96-f0c1-b3a2be25b99f.png)




```python
from rdkit.Chem import rdFMCS

matrix = []
for mol1 in mols:
    for mol2 in mols:
        mcs = rdFMCS.FindMCS([mol1, mol2])
        a1 = len(mol1.GetBonds())
        a2 = len(mol2.GetBonds())
        matrix.append(mcs.numBonds / (a1 + a2 - mcs.numBonds) )

plt.hist(np.array(matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_23_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/cdb41050-f811-8974-7153-50ea3d6db0bb.png)




```python
from rdkit.Chem import rdFMCS

matrix = []
for mol1 in mols:
    for mol2 in mols:
        mcs = rdFMCS.FindMCS([mol1, mol2], bondCompare=rdFMCS.BondCompare.CompareOrderExact)
        a1 = len(mol1.GetBonds())
        a2 = len(mol2.GetBonds())
        matrix.append(mcs.numBonds / (a1 + a2 - mcs.numBonds) )

plt.hist(np.array(matrix).flatten(), bins=20)
plt.grid()
plt.show()
```

![output_24_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/d98c4d25-6014-acc9-749d-6f83151b86ed.png)



# で、あなたのおっしゃる「タニモト係数」って、どれのことかしら？