Contents
RDKitによる低分子のコンホメーション探索¶
ETKTG法を使ったコンホメーション生成、エネルギー最適化¶
研究室内用のメモです。Jupyter Lab形式ファイル(sample.ipynb)をダウンロードして自分で動かしてみてください。
結論を先に書いておくと、今回の方法ではテスト分子のコンホメーションのサンプリングをうまくできませんでした。
今回テストで使用した9員環ラクタム分子(Indolactam-V)ではトランスアミド型がほぼ生成されず(2000個発生させて1個だけ)、それも実験的に分かっている安定なトランスアミド型コンホメーション(Sofa型)ではありませんでした。以前紹介したGROMACSのSimulated Annealingを使った方法だとシスアミド型もトランスアミド型も満遍なくサンプリングできているのでそちらを使った方がまだ安心のようです。
以下のサイトを参考にさせていただきました:
LibraryのImport¶
import os
import numpy as np
print("NumPy version:", np.__version__)
import rdkit # RDKit 2019.09.3
from rdkit import Chem
from rdkit.Chem import AllChem, Draw, Descriptors, PandasTools, TorsionFingerprints
from rdkit.ML.Cluster import Butina
from rdkit.Chem.Draw import IPythonConsole
#IPythonConsole.ipython_3d=True
print("RDKit version:", rdkit.__version__)
import nglview # NGLView 2.7.1
print("NGLView version:", nglview.__version__)
import pandas as pd
print("Pandas version:", pd.__version__)
import pubchempy as pcp
print("PubChemPy version:", pcp.__version__)
SMILES stringの読み込み¶
Aplysiatoxin. Pubchem CID: 21672114.
Indolactam-V. Pubchem CID: 105000.
pubchemcid = 105000
smiles = pcp.get_properties('IsomericSMILES', pubchemcid)
print(smiles)
mol = Chem.MolFromSmiles(smiles[0]['IsomericSMILES'])
Draw.MolToImage(mol) # RDKitによる構造の表示
ps = AllChem.ETKDGv2() # AllChem.ETKDG() がデフォルト
ps.pruneRmsThresh = 0.2 # 0 だと枝刈りしない
ps.numThreads = 0 #並列実行数。0は最大のスレッド数を使用。
#生成するコンホマー数; 例: n = 100
n = 2000
def generateconformations(m, n):
m_h = Chem.AddHs(m) #水素原子の付加
ids = AllChem.EmbedMultipleConfs(m_h, n, ps)
AllChem.MMFFOptimizeMoleculeConfs(m_h, numThreads=0) #ETKDG法の場合は最適化されている
prop = AllChem.MMFFGetMoleculeProperties(m_h)
energies = []
for cid in ids:
ff = AllChem.MMFFGetMoleculeForceField(m_h, prop, confId=cid)
energy = ff.CalcEnergy()
energies.append((energy, cid))
return m_h, list(ids), energies
# 入力した分子はm, 生成したコンホマーはconformersとして返す。
コンホメーションをn個発生¶
%%time
m, ids, energies = generateconformations(mol,n)
print("Number of generated conformers:", len(ids))
#コンホマーのアラインメント
AllChem.AlignMolConformers(m)
sort = np.argsort([energy[0] for energy in energies]) #arsortは値ではなく並び替えたインデックスを返す
energy_sorted = np.sort([energy[0] for energy in energies])
# エネルギー順にコンホマーを並べ替えた新しい分子を作る。
m_sorted = Chem.Mol(m)
m_sorted.RemoveAllConformers()
conf_ids = [conf.GetId() for conf in m.GetConformers()]
for i in sort:
conf = m.GetConformer(conf_ids[i])
m_sorted.AddConformer(conf, assignId=True)
# 水素原子を削除
m_noh = Chem.RemoveHs(m_sorted)
# RMS行列(RMS matrix)
rmsmat = AllChem.GetConformerRMSMatrix(m_noh, prealigned=True)
# TFD行列(TFD matrix)
tfdmat = TorsionFingerprints.GetTFDMatrix(m_noh)
# クラスタリング
num = m_noh.GetNumConformers()
rms_clusters = Butina.ClusterData(rmsmat, num, 0.5, isDistData=True, reordering=True)
tfd_clusters = Butina.ClusterData(tfdmat, num, 0.04, isDistData=True, reordering=True)
print('Number of RMS clusters:', len(rms_clusters))
#for i in range(len(rms_clusters)):
# print('RMS cluster_{}:'.format(i), rms_clusters[i])
print('\nNumber of TFD clusters:', len(tfd_clusters))
SDFファイルに保存¶
writer = Chem.SDWriter("./conformers.sdf")
for i in range(m_sorted.GetNumConformers()):
writer.write(m_sorted, confId=i)
writer.close()
Pandasを使ってテーブルにする¶
df = PandasTools.LoadSDF('./conformers.sdf', removeHs=False) # 水素原子も読み込む
df['MMFF_Energy'] = [E for E in energy_sorted] # Dataframeに新たな列を追加
コンホメーションの可視化¶
NGLViewを使用して最安定コンホマーを表示
print([r[0] for r in rms_clusters])
confid = 0
view = nglview.show_rdkit(df.loc[confid, 'ROMol']) # MMFF力場での最安定コンホメーション
view
view.render_image()
QM計算による比較¶
手法: B97-3c: 2018年に発表されたDFT法の一種。
- B97: 1997年に発表された汎関数
- 3c: “three-fold corrected”
基底関数形はdef2-mTZVPが使われる。
- Brandenburg, J. G.; Bannwarth, C.; Hansen, A.; Grimme, S. B97-3c: A revised low-cost variant of the B97-D density functional method. J. Chem. Phys. 2018, 148, 064104. DOI: 10.1063/1.5012601
- Sure, R.; Grimme, S. Corrected small basis set Hartree‐Fock method for large systems. J. Comput. Chem. 2013, 34, 1672-1685. DOI: 10.1002/jcc.23317
Intel CPUはHyper-Threading Technologyを利用して1コア/2スレッドで動作しますが、mpirunは “–use-hwthread-cpus” オプションを付けて実行しなければ、物理的なコア数までしか並列計算をしてくれない。物理コア数以内でも、qsubからジョブを送ると止まる。コマンドラインからだと大丈夫な時もあるが、止まる時は止まる。理由不明。
ORCA finished by error termination in SCF
…. aborting the run
def GenOrcaInput(i, method='B97-3c', thread=4):
conf = df.at[i, 'ROMol']
molBlock = Chem.MolToMolBlock(conf)
# 原子数を取得
num = conf.GetNumAtoms()
# 全ての行をリストとして保存する
lst_molBlock = molBlock.split("\n")
# 4行目から(4+原子数)行目までの各行を抜き出す
coordinates_part = lst_molBlock[4 : 4 + num]
# 原子の種類と各座標をタプルとして保存
coordinates = [(atoms[31],atoms[0:30]) for atoms in coordinates_part]
os.makedirs('conf{}'.format(i), exist_ok=True)
with open('conf{}/conf{}_{}.inp'.format(i, i, method.replace(' ', '_')), 'w') as f:
print('#', file=f)
print('# conformer{}'.format(i), file=f)
print('#', file=f)
print('! {}'.format(method), file=f)
print('! OPT FREQ', file=f) # 構造最適化と振動計算
print('%pal', file=f) # 並列計算
print('nprocs {}'.format(thread), file=f) # スレッド数
print('end', file=f)
print('* xyz 0 1', file=f)
for atom, xyz in coordinates:
print('{}\t{}'.format(atom, xyz), file=f)
print('*', file=f)
num_calc = 4 #計算する上位コンホマー数
method = "B97-3c" # 汎関数 (functional), 基底関数系 (basis set)
#method="B3LYP def2-TZVP"
#method="wB97X-D3 def2-TZVP"
for i in range(num_calc):
GenOrcaInput(i, method=method, thread=8)
qsub用job scriptの作成¶
file=open("orca.sh","w")
file.write("""#!/bin/bash
#PBS -l nodes=1:ppn=8
cd $PBS_O_WORKDIR
source /opt/orca/mpivars.sh
cd $PBS_O_WORKDIR/conf0/
/opt/orca/orca_4_2_1_linux_x86-64_openmpi314/orca conf0_B97-3c.inp > conf0_B97-3c.out
""")
file.close()
#out=!{"/opt/orca/orca_4_2_1_linux_x86-64_openmpi314/orca conf0/conf0_B97-3c.inp > conf0/conf0_B97-3c.out"}
#out=!{"qsub orca.sh"}
#grepout = !{"grep 'Final\sGibbs\sfree\senergy' conf0/conf0.out"}
#print(grepout)
# out=!{"/opt/orca/orca_4_2_1_linux_x86-64_openmpi314/orca conf1.inp > conf1.out"}
# 15分弱かかった
#grepout = !{"grep 'Final\sGibbs\sfree\senergy' conf1.out"}
#print(grepout)