In [1]:
from rdkit import Chem
from rdkit.Chem import AllChem
from rdkit import RDConfig
from rdkit.Chem.Draw import IPythonConsole 
from rdkit.Chem import Draw
import numpy as np
from IPython.display import display,Image

Ибупрофен

Нотация SMILES ибупрофена: CC(C)CC1=CC=C(C=C1)C(C)C(=O)O. Используя ее, нарисуем ибупрофен.

In [2]:
ibuprophenSmiles = 'CC(C)CC1=CC=C(C=C1)C(C)C(=O)O'
ibuprophen=Chem.MolFromSmiles(ibuprophenSmiles)
AllChem.Compute2DCoords(ibuprophen)
display(ibuprophen)

Модификация ибупрофена

Модифицируем ибупрофена, с помощью замены изопропила на этин: CC(C) на C#.

In [3]:
mod_ibuprophenSmiles = ibuprophenSmiles.replace('CC(C)','C#')
mod_ibuprophen=Chem.MolFromSmiles(mod_ibuprophenSmiles)
AllChem.Compute2DCoords(mod_ibuprophen)
display(mod_ibuprophen)

Эмуляция реагента Click Chemistry

Проведем Copper(I)-catalyzed azide-alkyne cycloaddition (CuAAC). Для начала построим template с радикалом R1, которым будем модифицированный ибупрофен.

In [4]:
template = 'N1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O'
ibu_cycle=Chem.MolFromSmiles(template)
AllChem.Compute2DCoords(ibu_cycle)
display(ibu_cycle)

Теперь загрузим скачанные SMILES для радикалов с азидом и отфильтруем их.

In [5]:
strings=np.genfromtxt('873774121219644625.txt',dtype=np.str)
r_smiles=[]

for line in strings:
    if len(line[1]) < 30 and not '.' in line[1]:
        r_smiles.append(line[1])
print(len(r_smiles))
10747

И заменим в них азид на построенный template.

In [6]:
res_smiles=[]
azid = 'N=[N+]=[N-]'
for r_smi in r_smiles[:10747]:
    if azid in r_smi:
        res_smi=r_smi.replace(azid, template)
        res_smiles.append(res_smi)
    else:
        continue

Правило пяти Лепински:

  • No more than 5 hydrogen bond donors
  • No more than 10 hydrogen bond acceptors
  • A molecular mass less than 500 daltons
  • An octanol-water partition coefficient log(P) not greater than 5
In [7]:
import rdkit.Chem.Lipinski as Lipinksy
In [8]:
print(Lipinksy.NumHDonors(ibuprophen))
print(Lipinksy.NumHAcceptors(ibuprophen))
print(Lipinksy.rdMolDescriptors.CalcExactMolWt(ibuprophen))
print(Lipinksy.rdMolDescriptors.CalcCrippenDescriptors(ibuprophen)[0])
1
1
206.130679816
3.073200000000001

Отберем SMILES, удовлетворяющие правилу:

In [11]:
analog_smiles=[]
for smi in res_smiles:
    try:
        newmol=Chem.MolFromSmiles(smi)
        if ((Lipinksy.NumHDonors(newmol) <= 5) and (Lipinksy.NumHAcceptors(newmol) <= 10) and (Lipinksy.rdMolDescriptors.CalcExactMolWt(newmol) <= 500) and (Lipinksy.rdMolDescriptors.CalcCrippenDescriptors(newmol)[0] <= 5)):
            analog_smiles.append(smi)
            AllChem.Compute2DCoords(newmol)
    except:
        pass
In [12]:
len(analog_smiles)
Out[12]:
7206

Построим стурктуры первых 10 полученных SMILES:

In [16]:
for analog in analog_smiles[:10]:
    print(analog)
    mol=Chem.MolFromSmiles(analog)
    AllChem.Compute2DCoords(mol)
    display(mol)
C1C(COC1=O)CN1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O
CCCNCN1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O
CC(CN)CN1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O
C(CN=N)CN1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O
CC1CN([C@@H]1N1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O)N=N
C1COC[C@@H](C1N1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O)O
C1[C@@H](C(CO1)N1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O)O
CCOC(=O)C(CN1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O)NI
CCOC(=C)COCCOC(C)N1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O
CC1(CCC1)N1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O

Построим 3D структуру одной из молекул.

In [17]:
smile_3d=analog_smiles[20]
mol_3d=Chem.MolFromSmiles(smile_3d)
m3d=Chem.AddHs(mol_3d)
Chem.AllChem.EmbedMolecule(m3d)
AllChem.MMFFOptimizeMolecule(m3d,maxIters=500,nonBondedThresh=200)
Out[17]:
0
In [22]:
import nglview as nv
nv.show_rdkit(m3d)
m3d
Out[22]: