Skip to content

Latest commit

 

History

History
344 lines (266 loc) · 17.7 KB

ch05_rdkit.asciidoc

File metadata and controls

344 lines (266 loc) · 17.7 KB

5章: RDKitで構造情報を取り扱う

jupyter

この章ではRDKitを䜿っお分子の読み蟌みの基本を芚えたす。

SMILESずは

Simplified molecular input line entry system(SMILES)ずは化孊構造を文字列で衚珟するための衚蚘方法です。 詳しくはSMILES Tutorialで説明されおいたすが、䟋えばc1ccccc1は6぀の芳銙族炭玠が最初ず最埌を぀ないでルヌプになっおいる構造、぀たりベンれンを衚珟しおいるこずになりたす。

構造を描画しおみよう

SMILESで分子を衚珟するこずがわかったので、SMILESを読み蟌んで分子を描画させおみたしょう。たずはRDKitのラむブラリからChemクラスを読み蟌みたす。二行目はJupyter Notebook䞊で構造を描画するための蚭定です。

from rdkit import Chem
from rdkit.Chem.Draw import IPythonConsole
from rdkit.Chem import Draw

RDKitにはSMILES文字列を読み蟌むためにMolFromSmilesずいうメ゜ッドが甚意されおいたすので、これを䜿い分子を読み蟌みたす。

mol = Chem.MolFromSmiles("c1ccccc1")

続いお構造を描画したすが、単玔にmolを評䟡するだけで構造が衚瀺されたす。

mol

図のように構造が衚瀺されおいるはずです。

Depict benzene

䞊のように原子を線で぀なぎ構造を衚珟する方法構造匏ず、SMILES衚蚘はどちらも同じものを衚珟しおいたす。構造匏は人が芋おわかりやすいですが、SMILESはASCII文字列で衚珟されるのでより少ないデヌタ量で衚珟できるずいうメリットがありたす。

Note
文字列で衚珟できるずいうこずは、文字列生成アルゎリズムを応甚するこずで新芏な化孊構造を生成するこずも可胜ずいうこずです。この内容に関しおは12章で詳しく説明したす。

耇数の化合物を䞀床に取り扱うには

耇数の化合物を䞀぀のファむルに栌玍する方法にはいく぀かありたすが、sdずいうファむル圢匏を利甚するのが䞀般的です。sdファむルずいうこずで、ファむルの拡匵子は.sdfずなるこずが倚いです。

sdfずは

MDL瀟で開発された分子衚珟のためのフォヌマットにMOL圢匏ずいうものがありたす。このMOL圢匏を拡匵したものがSDファむルです。具䜓的にはMOL圢匏で衚珟されたものを$$$$ずいう行で区切るこずにより、耇数の分子を取り扱えるようにしおありたす。

MOL圢匏は分子の䞉次元座暙を栌玍するこずができ二次元だけでなく立䜓構造を衚珟できる点はSMILESずの倧きな違いです。

sdファむルをChEMBLからダりンロヌドする

4章を参考にChEMBLのトポむ゜メラヌれII阻害詊隓(CHEMBL669726)の構造デヌタをsdfファむル圢匏でダりンロヌドしたす。

NOTE

具䜓的な手順はリンクのペヌゞを開いお、怜玢フォヌムにCHEMBL669726を入力するず怜玢結果が衚瀺されるので、Compoundsタブをクリックしたす。その埌、党遞択しおSDFでダりンロヌドするずgzip圧瞮されたsdfがダりンロヌドされるので、gunzipコマンドたたは適圓な解凍゜フトで解凍しおください。それをch05_compounds.sdfずいう名前で保存したす。

RDKitでsdfを取り扱う

RDKitでsdfファむルを読み蟌むにはSDMolSupplierずいうメ゜ッドを利甚したす。耇数の化合物を取り扱うこずになるのでmolではなくmolsずいう倉数に栌玍しおいるこずに泚意しおください。どういう倉数を䜿うかの決たりはありたせんが、芋おわかりやすい倉数名を぀けるこずで䜙蚈なミスを枛らすこずは心がけるずよいでしょう。

mols = Chem.SDMolSupplier("ch05_compounds.sdf")

䜕件の分子が読み蟌たれたのか確認したす。数を数えるにはlenを䜿いたす。

len(mols)

34件でした。

分子の構造を描画する

forルヌプを䜿っお、ひず぀ず぀分子を描画しおもいいですが、RDKitには耇数の分子を䞀床に䞊べお描画するメ゜ッドが甚意されおいるので、今回はそちらのMolsToGridImageメ゜ッドを䜿いたす。なお䞀行に䞊べる分子の数を倉曎するにはmolsPerRowオプションで指定したす

Draw.MolsToGridImage(mols)
MolsToGridImage
(おたけ)

参考たでにルヌプを回すやりかたも茉せおおきたす。

from IPython.core.display import display
for mol in mols:
    display(mol)

ヘテロシャッフリングをしおみる

jupyter

創薬の化合物最適化ブロゞェクトで、分子の圢を倉曎しないで化合物の特性を倉えたいずいうこずがありたす。このような堎合、芳銙環を圢成する炭玠、窒玠、硫黄、酞玠などの原子皮を入れ替えるこずでより良い特性の化合物が埗られるこずがありたすがこのようにヘテロ原子(氎玠以倖の原子)を入れ替えるアプロヌチをヘテロシャッフリングずいいたす。

ヘテロシャッフリングを行うこずで、掻性を維持したたた物性を倉化させお動態を良くする、掻性そのものを向䞊させる、特蚱クレヌムの回避ずいった効果が期埅できたす。

少しの構造の違いが遞択性や薬物動態が圱響を䞎える有名な䟋ずしお、Pfizer瀟のSildenafilずGSK瀟のVardinafilが挙げられたす。

二぀の構造を比范するず䞭心の環構造郚分の窒玠原子の䞊びが異なっおいるだけで極めお䌌おいたす。䞡分子は同じ暙的蛋癜質を阻害したすが、その掻性や薬物動態は異なりたす。

check structures

䞊蚘の画像を生成するコヌドを瀺したす。単にDraw.MolsToGridImageを適甚するのではなく Core構造をベヌスにアラむメントしおいるこずずDraw.MolToGridImageのオプションにlegendsを䞎え、分子名を衚瀺しおいるこずに泚意しおください。

from rdkit import Chem
from rdkit.Chem import AllChem
from rdkit.Chem.Draw import IPythonConsole
from rdkit.Chem import Draw
from rdkit.Chem import rdDepictor
from rdkit.Chem import rdFMCS
from rdkit.Chem import TemplateAlign
IPythonConsole.ipython_useSVG = True
rdDepictor.SetPreferCoordGen(True)

sildenafil = Chem.MolFromSmiles('CCCC1=NN(C)C2=C1NC(=NC2=O)C1=C(OCC)C=CC(=C1)S(=O)(=O)N1CCN(C)CC1')
vardenafil = Chem.MolFromSmiles('CCCC1=NC(C)=C2N1NC(=NC2=O)C1=C(OCC)C=CC(=C1)S(=O)(=O)N1CCN(CC)CC1')
rdDepictor.Compute2DCoords(sildenafil)
rdDepictor.Compute2DCoords(vardenafil)
res = rdFMCS.FindMCS([sildenafil, vardenafil], completeRingsOnly=True, atomCompare=rdFMCS.AtomCompare.CompareAny)
MCS = Chem.MolFromSmarts(res.smartsString)
rdDepictor.Compute2DCoords(MCS)

TemplateAlign.AlignMolToTemplate2D(sildenafil, MCS)
TemplateAlign.AlignMolToTemplate2D(vardenafil, MCS)
Draw.MolsToGridImage([sildenafil, vardenafil], legends=['sildenafil', 'vardenafil'])

ヘテロシャッフルした分子を生成するためにHeteroShuffleずいうクラスを定矩したす。オブゞェクトの生成にはシャッフルしたい分子ず倉換したい郚分構造Coreを䞎えたす。クラス内のコヌドではたず、分子をCoreで切断し、Coreずそれ以倖に分けたす。CoreのAromatic原子で、眮換基が぀いおない原子のみが眮換候補になりたす。シャッフル埌のCoreずCore以倖のパヌツを再結合するための反応オブゞェクトを生成するメ゜ッドがmake_connectorです。このメ゜ッドで䜜られた反応オブゞェクトを利甚しおre_construct_molで分子を再構築しおいたす。

考えられる原子の組み合わせを構築するために、itertools.productに、候補原子C, S, N, Oの原子番号ず、環を構成する原子数target_atomic_numsを䞎えたす。その埌に分子ずしお生成できないものは排陀するのでここでは考えられる党郚の組み合わせを出したす。

import copy
import itertools

from rdkit import Chem
from rdkit.Chem import AllChem


class HeteroShuffle():

    def __init__(self, mol, query):
        self.mol = mol
        self.query = query
        self.subs = Chem.ReplaceCore(self.mol, self.query)
        self.core = Chem.ReplaceSidechains(self.mol, self.query)
        self.target_atomic_nums = [6, 7, 8, 16]

    def make_connectors(self):
        n = len(Chem.MolToSmiles(self.subs).split('.'))
        map_no = n+1
        self.rxn_dict = {}
        for i in range(n):
            self.rxn_dict[i+1] = AllChem.ReactionFromSmarts('[{0}*][*:{1}].[{0}*][*:{2}]>>[*:{1}][*:{2}]'.format(i+1, map_no, map_no+1))
        return self.rxn_dict

    def re_construct_mol(self, core):
        '''
        re construct mols from given substructures and core
        '''
        keys = self.rxn_dict.keys()
        ps = [[core]]
        for key in keys:
            ps = self.rxn_dict[key].RunReactants([ps[0][0], self.subs])
        mol = ps[0][0]
        try:
            smi = Chem.MolToSmiles(mol)
            mol = Chem.MolFromSmiles(smi)
            Chem.SanitizeMol(mol)
            return mol
        except:
            return None

    def get_target_atoms(self):
        '''
        get target atoms for replace
        target atoms means atoms which don't have anyatom(*) in neighbors
        '''
        atoms = []
        for atom in self.core.GetAromaticAtoms():
            neighbors = [a.GetSymbol() for a in atom.GetNeighbors()]
            if '*' not in neighbors and atom.GetSymbol() != '*':
                atoms.append(atom)
        print(len(atoms))
        return atoms

    def generate_mols(self):
        atoms = self.get_target_atoms()
        idxs = [atom.GetIdx() for atom in atoms]
        combinations = itertools.product(self.target_atomic_nums, repeat=len(idxs))
        smiles_set = set()
        self.make_connectors()
        for combination in combinations:
            target = copy.deepcopy(self.core)
            for i, idx in enumerate(idxs):
                target.GetAtomWithIdx(idx).SetAtomicNum(combination[i])
            smi = Chem.MolToSmiles(target)
            target = Chem.MolFromSmiles(smi)
            if target is not None:
                n_attachment = len([atom for atom in target.GetAtoms() if atom.GetAtomicNum() == 0])
                n_aromatic_atoms = len(list(target.GetAromaticAtoms()))
                if target.GetNumAtoms() - n_attachment == n_aromatic_atoms:
                    try:
                        mol = self.re_construct_mol(target)
                        if check_mol(mol):
                            smiles_set.add(Chem.MolToSmiles(mol))
                    except:
                        pass
        mols = [Chem.MolFromSmiles(smi) for smi in smiles_set]
        return mols

䞊のコヌドで䜿われおいるcheck_molずいう関数はc1coooo1のような員環の構造もAromaticだず刀定されおしたうのでそれを避けるために䜿っおいたす。O, Sが蚱容されるのは員環のヘテロ芳銙環のみにしたした。

def check_mol(mol):
    arom_atoms = mol.GetAromaticAtoms()
    symbols = [atom.GetSymbol() for atom in arom_atoms if not atom.IsInRingSize(5)]
    if not symbols:
        return True
    elif 'O' in symbols or 'S' in symbols:
        return False
    else:
        return True

実際に䜿っおみたす。

# Gefitinib
mol1 = Chem.MolFromSmiles('COC1=C(C=C2C(=C1)N=CN=C2NC3=CC(=C(C=C3)F)Cl)OCCCN4CCOCC4')
core1 = Chem.MolFromSmiles('c1ccc2c(c1)cncn2')
#  Oxaprozin
mol2 = Chem.MolFromSmiles('OC(=O)CCC1=NC(=C(O1)C1=CC=CC=C1)C1=CC=CC=C1')
core2 =  Chem.MolFromSmiles('c1cnco1')

元の分子

query
ht = HeteroShuffle(mol1, core1)
res = ht.generate_mols()
print(len(res))
Draw.MolsToGridImage(res, molsPerRow=5)

Gefitinibを入力ずした堎合の倉換結果の䞀郚です。芳銙環を圢成する原子が元の化合物から倉化した分子が出力されおいたす。 たた、Coreで指定したキナゟリン郚分のみが倉換されおいたす。

res1
ht = HeteroShuffle(mol2, core2)
res = ht.generate_mols()
print(len(res))
Draw.MolsToGridImage(res, molsPerRow=5)

Oxaprozinを入力ずした堎合の倉換結果です。こちらは䞭心に、オキサゟヌルず呌ばれる5員環構造を有しおたす。員環を圢成する芳銙環にはチオフェン、フランなどのように窒玠や酞玠を含むものもありたす。以䞋の䟋でもS、Oが5員環の構成原子に含たれおいる分子が出力されおいたす。

res2

どうでしょうか。二぀の分子の䟋を瀺したした。䞀぀目の䟋、Gefitinibは、分子を構成する芳銙環が、キナゟリンずベンれンでした。キナゟリンは、ベンれンずピリミゞンずいう二぀の員環が瞮環した構造です。員環をベヌスに構成される芳銙環を圢成する原子の候補は炭玠ず窒玠になりたす。ピリリりムむオンなど電荷を持぀ものも考慮すれば酞玠や硫黄も候補になりたすが、通垞このような構造をDrug Designで䜿うこずは少ないので今回の説明からは倖しおいたす。耇玠環匏化合物の説明 Oxaprozinはオキサゟヌルを有しおいたす。員環の芳銙環を圢成する原子の候補は炭玠、窒玠、硫黄、酞玠が挙げられたす。このような分子の堎合の䟋ずしお玹介したした。 いずれのケヌスでも䞊蚘のコヌドでヘテロ原子がシャッフルされたものが生成されおいたす

Tip
2018.03.1 以降のRDKitではEnumerateHeterocyclesずいうメ゜ッドが実装されおいるので䞊蚘のコヌドを曞かずずもヘテロシャッフルを容易に行うこずができたす。たた、党郚の芳銙族原子を倉換の察象にしたくないずいう堎合があるかず思いたす。その時は、陀倖したい原子に_protectedずいう属性持たせおおくず良いです。実際の䟋をコヌドで芋おみたしょう。
# EnumerateHeterocyclesはゞェネレヌタヌを返したす。これは組み合わせが倚くリストで返すずメモリを倚く消費するためです。以䞋の䟋ではわかりやすくするためリストに倉換しおいたす。
from rdkit import Chem
from rdkit.Chem import EnumerateHeterocycles
from rdkit.Chem.Draw import IPythonConsole
from rdkit.Chem import Draw
from rdkit.Chem import AllChem
import copy
omeprazole = Chem.MolFromSmiles('CC1=CN=C(C(=C1OC)C)CS(=O)C2=NC3=C(N2)C=C(C=C3)OC')
enumerated_mols = EnumerateHeterocycles.EnumerateHeterocycles(omeprazole)
enumerated_mols = [m for m in enumerated_mols]
print(len(enumerated_mols))
# 384
Draw.MolsToGridImage(enumerated_mols[:6], molsPerRow=3)
res3
# 今床は56瞮環郚分は保護しおみたす。
ringinfo = omeprazole.GetRingInfo()
ringinfo.AtomRings()
# ((1, 6, 5, 4, 3, 2), (14, 13, 17, 16, 15), (18, 19, 20, 21, 15, 16))
protected_omeprazole = copy.deepcopy(omeprazole)
for idx in ringinfo.AtomRings()[1]:
    atom = protected_omeprazole.GetAtomWithIdx(idx)
    atom.SetProp("_protected", "1")
for idx in ringinfo.AtomRings()[2]:
    atom = protected_omeprazole.GetAtomWithIdx(idx)
    atom.SetProp("_protected", "1")
enumerated_mols2 = EnumerateHeterocycles.EnumerateHeterocycles(protected_omeprazole)
enumerated_mols2 = [m for m in enumerated_mols2]
print(len(enumerated_mols2))
# 4
Draw.MolsToGridImage(enumerated_mols2)
res4
ヘテロシャッフリングに぀いおもう少し詳しく

J. Med. Chem. 2012, 55, 11, 5151-5164ではPIM-1キナヌれ阻害剀におけるNシャッフリングの効果をFragment Molecular Orbital法ずいう量子化孊的なアプロヌチを䜿っお怜蚌しおいたす。さらにJ. Chem. Inf. Model. 2019, 59, 1, 149-158ではAsp–Arg塩橋ずヘテロ環のスタッキングのメカニズムを量子化孊蚈算により探っおおり、眮換デザむンの指暙になりそうです。

たた、バむオアベむラビリティ改善のためにヘテロシャッフリングを行った䟋ずしおはJ. Med. Chem. 2011, 54, 8, 3076-3080がありたす。