In [12]:
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
import rdkit.Chem.Lipinski as Lipinksy

from IPython.display import display,Image

Цель занятия — используя пакет модулей RDkit предложить аналог ибупрофена:

  • на сайте PubChem найти все радикалы c азидом для Click Chemistry и скачать их SMILES нотации
  • найти формулу ибупрофена и предложить способ изменения его SMILES для эмуляции реагента Click Chemistry (заменить изопропил на ацителен)
  • заменить в найденых радикалах азидную группу на модифцированный ибупрофен.
  • превратить новые SMILES в объекты-молекулы
  • отобрать те молекулы, которые удовлетворяют правилу пяти Lipinski
In [3]:
# Search canonical SMILES for azide with pubchempy: 

import pubchempy as pcp

# get_properties() allows the retrieval of specific properties without having to deal with entire compound records
# useful for retrieving the properties of a large number of compounds at once

# to avoid timeout_error use: 
# the listkey_count value specifies the number of results per page
# the listkey_start value specifies which page to return

# specify PubChem search parameters RingsNotEmbedded, MatchTautomers, MatchCharges from deafault false to true

azide_radicales = []
start_page = 1
for smile in ['[N-]=[N+]=[N-]', 
              '[N-][N+]#[N]', 
              '[N]#[N+][N-]', 
              '[N-][N]#[N+]', 
              '[N+]#[N][N-]'
             ]:
    start_page +=1 
    try:
        # avoid exceptions on the server side
        azide_radicales.append(pcp.get_properties('CanonicalSMILES', smile, 'smiles', searchtype='substructure', 
                                                  RingsNotEmbedded=True, MatchTautomers=True, 
                                                  listkey_count=100000, listkey_start=start_page))
    except:
        continue
In [4]:
# проверить количество найденных нотаций

azide_radicales = sum(azide_radicales, [])
azide_radicales = [x['CanonicalSMILES'] for x in azide_radicales]
len(azide_radicales)
Out[4]:
500000
In [5]:
# найти формулу ибупрофена

ibu=Chem.MolFromSmiles('CC(C)CC1=CC=C(C=C1)C(C)C(=O)O')
AllChem.Compute2DCoords(ibu)
display(ibu)
In [6]:
# измененить SMILES ибупрофена для эмуляции реагента Click Chemistry (азид-алкиновое циклоприсоединение): 
# замена изопропила на ацетилен

ibu_edited=Chem.MolFromSmiles('C#CCC1=CC=C(C=C1)C(C)C(=O)O')
AllChem.Compute2DCoords(ibu_edited)
display(ibu_edited)
In [7]:
# отфильтровать нотации найденных радикалов
smiles = []
for smile in set(azide_radicales):
    if len(smile) < 30 and not '.' in smile:
        smiles.append(smile)
In [8]:
# подготовить шаблон для построения новых молекул: соединение ибупрофена с азидом 
template = 'N1C=C(N=N1)C1=CC=C(C=C1)C(C)C(=O)O'

# построить из каждой нотации молекулу и проверить ее качество по правилу Липински
good_structures = []
for smile in smiles:
    if 'N=[N+]=[N-]' in smile:
        merged_structure = smile.replace('N=[N+]=[N-]', template)
        try:
            molecule = Chem.MolFromSmiles(merged_structure)
            if(Lipinksy.NumHDonors(molecule) <= 5 and
               Lipinksy.NumHAcceptors(molecule) <= 10 and
               Lipinksy.rdMolDescriptors.CalcExactMolWt(molecule) < 500 and
               Lipinksy.rdMolDescriptors.CalcCrippenDescriptors(molecule)[0] <= 5):
                good_structures.append(merged_structure)
        except:
            continue
    else:
        continue

print('Passed the test: %s good structures' % len(good_structures))   
RDKit ERROR: [10:13:21] Explicit valence for atom # 4 Cl, 3, is greater than permitted
RDKit ERROR: [10:13:30] Explicit valence for atom # 22 Cl, 3, is greater than permitted
RDKit ERROR: [10:13:31] Explicit valence for atom # 1 Cl, 2, is greater than permitted
Passed the test: 7974 good structures
In [9]:
# отобразить несколько первых структур из найденных 7680
for molecule in good_structures[:10]:
    display(Chem.MolFromSmiles(molecule))
In [10]:
# выбрать лиганд и показать его конформацию

m3d=Chem.AddHs(Chem.MolFromSmiles(good_structures[7]))
Chem.AllChem.EmbedMolecule(m3d)
AllChem.MMFFOptimizeMolecule(m3d,maxIters=500,nonBondedThresh=200 )

import nglview as nv
nv.show_rdkit(m3d)

Failed to display Jupyter Widget of type NGLWidget.

If you're reading this message in Jupyter Notebook or JupyterLab, it may mean that the widgets JavaScript is still loading. If this message persists, it likely means that the widgets JavaScript library is either not installed or not enabled. See the Jupyter Widgets Documentation for setup instructions.

If you're reading this message in another notebook frontend (for example, a static rendering on GitHub or NBViewer), it may mean that your frontend doesn't currently support widgets.

In [14]:
%%bash
jupyter nbconvert --to html hw3_filippova.ipynb
[NbConvertApp] Converting notebook hw3_filippova.ipynb to html
[NbConvertApp] ERROR | Notebook JSON is invalid: {u'model_id': u'2738046f06384c60b67f54a9bc22eaed', u'version_minor': 0, u'version_major': 2} is not valid under any of the given schemas

Failed validating u'oneOf' in display_data[u'properties'][u'data'][u'patternProperties'][u'^(?!application/json$)[a-zA-Z0-9]+/[a-zA-Z0-9\\-\\+\\.]+$']:

On instance[u'cells'][9][u'outputs'][0][u'data'][u'application/vnd.jupyter.widget-view+json']:
{u'model_id': u'2738046f06384c60b67f54a9bc22eaed',
 u'version_major': 2,
 u'version_minor': 0}
[NbConvertApp] Writing 434897 bytes to hw3_filippova.html
In [ ]:
 
In [ ]: