In [2]:
from rdkit import Chem
import pubchempy as pcp
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, SVG
RDKit WARNING: [20:12:18] Enabling RDKit 2019.09.3 jupyter extensions

Часть 1 - Найти формулу ибупрофена и предложить способ изменения его SMILES для эмуляции продукта Click Chemistry

Посмотрим как выглядит ибупрофен

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

Если мы хотим присоединить к нему азиды с помощью клик химии, то самый простой и понятный способ это сделать - добавить к ибупрофену алкильную группу https://en.wikipedia.org/wiki/Click_chemistry#Copper(I)-catalyzed_azide-alkyne_cycloaddition_(CuAAC) Такая реакция циклоприсоединения азидов к алкинам, катализируемая ионами меди по другому называется CuAAC (изображена ниже)

Забавно что аналоги ибупрофена интересны мировой науке не только как новые NSAID (https://www.future-science.com/doi/abs/10.4155/fmc-2018-0467?journalCode=fmc) но и как новые антибиотики (https://www.sciencedirect.com/science/article/abs/pii/S0960894X16310083)

In [3]:
display(Image("https://upload.wikimedia.org/wikipedia/commons/c/c0/CuAAC_Catalytic_Cycle.png",width=700,height=700))

Я предложу немного запутанный вариант получения терминального алкина из ибупрофена

1) Получаем ацилхлорид вот таким лабораторным способом

https://en.wikipedia.org/wiki/Acyl_chloride

In [4]:
display(SVG(url="https://upload.wikimedia.org/wikipedia/commons/7/76/Formation_of_acyl_chloride.svg"))
image/svg+xml R O OH R O Cl SOCl2 - HCl, - SO2

Как же вылядит на этой стадии модифицированный ибупрофен

In [34]:
ibu1=Chem.MolFromSmiles('CC(C)CC1=CC=C(C=C1)C(C)C(=O)Cl')
AllChem.Compute2DCoords(ibu1)
display(ibu1)

2)

Получаем альдегид из ацилхлорида при помощи восстановления по Розенмунду

https://en.wikipedia.org/wiki/Rosenmund_reduction

In [30]:
display(Image("https://upload.wikimedia.org/wikipedia/commons/e/e1/Rosenmund_Reduction_Scheme.png"))

Как выглядит теперь модифицированный ибупрофен?

In [39]:
ibu2=Chem.MolFromSmiles('CC(C)CC1=CC=C(C=C1)C(C)C=O')
AllChem.Compute2DCoords(ibu2)
display(ibu2)

3)

Получаем терминальный алкин из альдегида при помощи реакции Кори-Фукса

https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%BA%D0%B8%D0%BD%D1%8B#cite_note-17

In [33]:
display(Image("https://upload.wikimedia.org/wikipedia/commons/b/b7/Corefuchs.png"))
display(Image("https://upload.wikimedia.org/wikipedia/commons/5/5d/Corey-Fuchs_carbene.png"))

Изобразим превращения ибупрофена после первой и второй стадии реакции Кори-Фукса

In [40]:
ibu3=Chem.MolFromSmiles('CC(C)CC1=CC=C(C=C1)C(C)C=C(Br)Br')
AllChem.Compute2DCoords(ibu3)
display(ibu3)
In [42]:
ibu4=Chem.MolFromSmiles('CC(C)CC1=CC=C(C=C1)C(C)C#C')
AllChem.Compute2DCoords(ibu4)
display(ibu4)

Вот то что изображено выше это и есть конечный вариант модифицированного ибупрофена к корому мы будем присоединять найденные азиды из PubChem

Как же выглядит сама реакция циклоприсоединения азидов к алкинам?

Изобразим продукт реакции азида и модифицированного азидобензена(ниже)

Изобразим продукт реакции азида и модифицированного ибупрофена на примере азидобензена(ниже)

In [46]:
protoazid=Chem.MolFromSmiles('[N-]=[N+]=[N]C1=CC=CC=C1')
AllChem.Compute2DCoords(protoazid)
display(protoazid)
In [80]:
ibumod=Chem.MolFromSmiles('C1=CC=CC=C1N2N=NC(C(C)C3=CC(C(C)C)=CC=C3)=C2')
AllChem.Compute2DCoords(ibumod)
display(ibumod)

Правда таким образом из ибупрофена исчезла карбоксильная группа, которая, конечно, важная функциональная часть молекулы и тем не менее часто при модификациях карбоксильная руппа пропадает

Часть 2 на сайте PubChem найти все радикалы c азидом для Click Chemistry и скачать их SMILES нотации или используйте pubchempy

Найти все радикалы с азидом Я придумала три способа записать азид, учитывая их мезомерию, некоторые из способов при поиске вручную в PubChem явно дают похожие результаты так что хорошо бы убрать одинаковые резултаты поиска. Правда pubchempy - вредный и не хочет обрабатывать любые мои запросы, но вроде бы три нижеперечисленные получились довольно адекватными и принимаются pubchempy

[N-;D1;H0;!R]=[N+;D2;H0;!R]=[N]

[N-;H0;D1;!R]=[N][N-] (вообще конечно максимально странный мезомер тут два '-' заряда но теоретически возможно и при ручном поиске дает что то адекватное)

[N;D1;!R;H0]#[N+][N-]

In [3]:
azides=["[N-;D1;H0;!R]=[N+;D2;H0;!R]=[N]","[N-;H0;D1;!R]=[N][N-]","[N;D1;!R;H0]#[N+][N-]"]
In [4]:
#Таким способом конечно скачается далеко не все что найдется но для примера хватит
compounds = []
per_page = 10**5
for azide in azides:
    for i in range(2):
        try:
            a = pcp.get_properties(
              properties="CanonicalSMILES", 
              identifier=azide, namespace="smiles", 
              searchtype="substructure",
              RingsNotEmbedded=True,
              listkey_count=per_page, listkey_start=i*per_page
            )
        except:
            break
        print("Retrieved page {} of {} search".format(i+1, azide))
        compounds.extend(a)
Retrieved page 1 of [N-;D1;H0;!R]=[N+;D2;H0;!R]=[N] search
Retrieved page 2 of [N-;D1;H0;!R]=[N+;D2;H0;!R]=[N] search
Retrieved page 1 of [N-;H0;D1;!R]=[N][N-] search
Retrieved page 1 of [N;D1;!R;H0]#[N+][N-] search
Retrieved page 2 of [N;D1;!R;H0]#[N+][N-] search
In [20]:
len(compounds)
Out[20]:
200599

Часть 3 Присоединяем азиды к модифицированному ибупрофену и проверяем соответствие продукта правилу пяти Лепински

Проверим соответствие ибупрофена правилу пяти Лепински

In [8]:
import rdkit.Chem.Lipinski as Lipinksy
print(Lipinksy.NumHDonors(ibu))
print(Lipinksy.NumHAcceptors(ibu))
print(Lipinksy.rdMolDescriptors.CalcExactMolWt(ibu))
print(Lipinksy.rdMolDescriptors.CalcCrippenDescriptors(ibu)[0])
1
1
206.130679816
3.073200000000001

Видим что сам по себе ибупрофен удовлетворяет правилу, неудивительно что он такой популярный фармпрепарат

In [5]:
#формула для проверки удовлетворения правилу Лепински
def rule(mol):
    return((Lipinksy.NumHDonors(mol)<=5)&(Lipinksy.NumHAcceptors(mol)<=10)&(Lipinksy.rdMolDescriptors.CalcExactMolWt(mol)<500)&(Lipinksy.rdMolDescriptors.CalcCrippenDescriptors(mol)[0]<=5))

Промодифицируем ибупрофен скачанными азидами. Если у молекулы было два азида записанные как N=[N+]=[N-], то ибупрофен присоединится к обоим, но что поделать. Напишем как выглядит template то есть то что появится на месте азида после циклоприсоединения

In [11]:
template="N2N=NC(C(C)C3=CC(C(C)C)=CC=C3)=C2"
template_pic=Chem.MolFromSmiles('N2N=NC(C(C)C3=CC(C(C)C)=CC=C3)=C2')
AllChem.Compute2DCoords(template_pic)
display(template_pic)
#вместо водорода при азоте в кольце будет соединение из PubChem

При замещении будем проверять наличие в соединении хотя бы одного атома углерода чтобы избежать poly-N структур

In [45]:
good_derivatives=[]
good_azides=[]
for compound in compounds[:1500]:    
    if 'N=[N+]=[N-]' in compound["CanonicalSMILES"] and ("c" in compound["CanonicalSMILES"] or "C" in compound["CanonicalSMILES"]):
        new_compound=compound["CanonicalSMILES"].replace('N=[N+]=[N-]',template)
    else:
        continue
    try:
        newmol=Chem.MolFromSmiles(new_compound)
        if rule(newmol):
            good_azides.append(compound)
            good_derivatives.append(newmol)
    except:
        pass
RDKit ERROR: [19:02:09] Explicit valence for atom # 8 Cl, 3, is greater than permitted
In [46]:
len(good_azides)
Out[46]:
119

На всякий случай проверим, сколько среди них уникальных азидов

In [49]:
len(good_derivatives)-len(set(good_derivatives))
Out[49]:
0

Все в этой подвыборке уникальные)

In [47]:
display(Draw.MolsToGridImage(good_derivatives, maxMols=15, molsPerRow=3, subImgSize=(400, 600)))

Видим что не все возможные азидные группировки заменились, потому что не все они видимо были записаны как N=[N+]=[N-], но это в целом нормально, потому что мы хотим присоединить азид к ибупрофену а не ибупрофен ко всем азидным группам в молекуле. Конечно пространство поиска потенциальных противовоспалительных и антибиотиков таким образом несколько обедняется, что наверняка решается путем более внимательного перебора и аккуратного замещения всех возможных форм записи азидов.

Нарисуем карты сходства.

In [36]:
from rdkit.Chem.Draw import SimilarityMaps
weights=[]
for i in range(5):
    fig, maxweight = SimilarityMaps.GetSimilarityMapForFingerprint(ibu, good_derivatives[i], SimilarityMaps.GetMorganFingerprint)
    print(maxweight)
0.06325046507694909
0.056410256410256376
0.06597222222222221
0.05883401675878053
0.05429718875502007

Сходство не очень большое, что не удивительно, ведь мы присоединяем довольно большие куски органических молекул и изначальный ибупрофеновый фрагмент в составе соединения значит уже не так много.

Посмотрим на 3D структуру 5го производного

In [50]:
import nglview as nv
In [60]:
m3d=Chem.AddHs(good_derivatives[4])
Chem.AllChem.EmbedMolecule(m3d)
AllChem.MMFFOptimizeMolecule(m3d,maxIters=500,nonBondedThresh=200 )
pic=nv.show_rdkit(m3d)
nv.show_rdkit(m3d)

Действительно очень удобный способ быстро оценить 3d геометрию! (правда этого не видно в html), зато в html можно увидеть другое изображение

In [63]:
display(m3d)

Судя по правилу Лепински все полученные нами 119 модификаций ибупрофена, а в реальности и того больше (в полной базе данных) могут потенциально быть его аналогами