Delete (Deep lead optimization enveloped in protein pocket) 是一个基于口袋的,3D分子生成的,应用于lead优化过程中侧链修饰、骨架跃迁,linker设计,片段生长的几何深度学习模型。
一、模型介绍
Delete 模型是浙江大学侯廷军老师发表2023年8月4日在arXiv上的文章,文章名:Delete: Deep Lead Optimization Enveloped in Protein Pocket。第一作者是Haotian Zhang。Haotian Zhang也是之前介绍的ResGen的第一作者,是一位非常高产的,AI4Science工作者。侯廷军老师在AI药物设计的模型非常丰富,效果也不错,值得好好应用与研究。
Delete模型通过几何神经网络融合口袋-配体相互作用学习口袋残基和小分子之间的相互作用,进一步利用掩码 (mask) 策略,处理先导化合物优化的所有子任务,包括:片段生长、连接和替换,在口袋内直接生成3D的分子。
之前介绍的分子生成、片段生长、linker设计等方法,都是单一功能的,一个模型仅有一种功能,不能同时满足lead化合物优化的片段生长、连接和替换三种应用场景。但是,Delete模型可以,是先导化合物优化的整合模型。
对于linker设计任务,使用MMP切割烷基单键。对于片段生长任务,切割功能片段的烷基单键。对于骨架跃迁任务,使用Bemis-Murcko提取骨架。对于侧链修饰任务,使切割侧链的单键。
Delete在生成分子时,逐步经过锚点枚举打分,原子放置,连接键预测三个过程,一直重复,直到分子中所有原子预测的分数低于锚点阈值,停止生长。
在模型训练时,Deletet会随机mask原子,分为7种模式,其中3种(random mask, spatial mask, 和 topological mask)用于模型的预训练,剩下4种(linker mask, fragment mask, scaffold mask, and side-chain mask)分别对应Delete的linker设计,骨架跃迁,片段生长,侧链修饰4种应用。
二、模型性能
Delete模型训练使用的数据集是CrossDock和BindingMoad,分别含有10W和3.5W分子-口袋对。作者训练三个版本,分别是:使用CrossDock数据集训练的 Delete-C, 使用BindingMoad数据集训练的Delete-M,以及先使用CrossDock数据集训练后再使用BindingMoad数据集微调的Delete-CM。
Delete-CM在 linker 设计的任务中,生成的分子Docking Energy, Scoring Energy均低于数据集平均值,也低于之前介绍的Difflinker。
作者在文章中,给出了一些案例。
下图是Delete应用与linker设计的案例。
使用的体系是IMPDH,晶体结构为:5OU2。D图为Detele的输入结构,红色部分为Delete需要设计的Linker部分。图E给出了4个生成的分子,及其类药性质。图F给出Docking score的分布,图G给出 scoring energy 的分布。
文中介绍,生成了76个不同的化合物,2D分子相似性为0.5,而3D分子相似性高达0.92。65.7%生成的分子docking score 优于参考分子。
PROTAC linker设计案例,如下图。Delete生成了106个分子,其中,88.7%具有更好的vina score,在docking下,有98.1%的分子的docking score优于参考分子。3D相似性高达0.891,SA分数均值为0.5446。
三、模型测评
3.1 环境安装
复制项目代码
git clone https://github.com/HaotianZhangAI4Science/Delete.git
创建conda环境
作者提供了两种环境安装方法,一种是mamba安装,一种是直接下载conda环境包安装。我首先测试了mamba安装,因为作者提供的yml文件有问题,所以安装失败。
因此这里采用第二种安装方式,下载作者提供的conda环境包。网址是:
Delete environment
按照作者的提示,解压到conda的环境目录。先新建env,然后上传delete.tar.gz
到env目录,然后解压,然后移动到conda环境中,我这里是 /home/anaconda3/envs/
mkdir env
tar -zxcf delete.tar.gz env
mv env /home/anaconda3/envs/Delete
# 激活环境
conda activate Delete
我环境安装完成后,使用conda导出了环境的yml文件,如下。大家可以通过conda自行安装。
channels:
- pyg
- <unknown>
- https://mirrors.ustc.edu.cn/anaconda/cloud/bioconda
- pytorch
- https://mirrors.ustc.edu.cn/anaconda/pkgs/free
- https://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge
- conda-forge
- defaults
dependencies:
- _libgcc_mutex=0.1=conda_forge
- _openmp_mutex=4.5=2_kmp_llvm
- alsa-lib=1.2.6.1=h7f98852_0
- argon2-cffi=21.3.0=pyhd8ed1ab_0
- argon2-cffi-bindings=21.2.0=py38h0a891b7_2
- asttokens=2.0.8=pyhd8ed1ab_0
- attr=2.5.1=h166bdaf_1
- attrs=22.1.0=pyh71513ae_1
- backcall=0.2.0=pyh9f0ad1d_0
- backports=1.0=py_2
- backports.functools_lru_cache=1.6.4=pyhd8ed1ab_0
- beautifulsoup4=4.11.1=pyha770c72_0
- biopython=1.79=py38h0a891b7_2
- blas=1.0=mkl
- bleach=5.0.1=pyhd8ed1ab_0
- boost=1.74.0=py38h2b96118_5
- boost-cpp=1.74.0=h75c5d50_8
- brotli=1.0.9=h166bdaf_7
- brotli-bin=1.0.9=h166bdaf_7
- brotlipy=0.7.0=py38h0a891b7_1004
- bzip2=1.0.8=h7f98852_4
- ca-certificates=2024.2.2=hbcca054_0
- cairo=1.16.0=ha61ee94_1014
- certifi=2024.2.2=pyhd8ed1ab_0
- cffi=1.15.1=py38h4a40e3a_0
- charset-normalizer=2.1.1=pyhd8ed1ab_0
- colorama=0.4.5=pyhd8ed1ab_0
- contourpy=1.0.5=py38h43d8883_0
- cryptography=37.0.4=py38h2b5fc30_0
- cudatoolkit=11.3.1=h9edb442_10
- cycler=0.11.0=pyhd8ed1ab_0
- dbus=1.13.6=h5008d03_3
- debugpy=1.6.3=py38hfa26641_0
- decorator=5.1.1=pyhd8ed1ab_0
- defusedxml=0.7.1=pyhd8ed1ab_0
- easydict=1.9=py_0
- entrypoints=0.4=pyhd8ed1ab_0
- executing=1.0.0=pyhd8ed1ab_0
- expat=2.4.8=h27087fc_0
- ffmpeg=4.3=hf484d3e_0
- fftw=3.3.4=0
- flit-core=3.7.1=pyhd8ed1ab_0
- font-ttf-dejavu-sans-mono=2.37=hab24e00_0
- font-ttf-inconsolata=3.000=h77eed37_0
- font-ttf-source-code-pro=2.038=h77eed37_0
- font-ttf-ubuntu=0.83=hab24e00_0
- fontconfig=2.14.0=hc2a2eb6_1
- fonts-conda-ecosystem=1=0
- fonts-conda-forge=1=0
- fonttools=4.37.3=py38h0a891b7_0
- freetype=2.12.1=hca18f0e_0
- gettext=0.19.8.1=h73d1719_1008
- glib=2.72.1=h6239696_0
- glib-tools=2.72.1=h6239696_0
- gmp=6.2.1=h58526e2_0
- gnutls=3.6.13=h85f3911_1
- greenlet=1.1.3=py38hfa26641_0
- gst-plugins-base=1.20.3=hf6a322e_0
- gstreamer=1.20.3=hd4edc92_2
- icu=70.1=h27087fc_0
- idna=3.4=pyhd8ed1ab_0
- importlib-metadata=4.11.4=py38h578d9bd_0
- importlib_resources=5.9.0=pyhd8ed1ab_0
- ipykernel=6.15.3=pyh210e3f2_0
- ipython=8.5.0=pyh41d4057_1
- ipython_genutils=0.2.0=py_1
- ipywidgets=8.0.2=pyhd8ed1ab_1
- jack=1.9.18=h8c3723f_1002
- jedi=0.18.1=pyhd8ed1ab_2
- jinja2=3.1.2=pyhd8ed1ab_1
- joblib=1.2.0=pyhd8ed1ab_0
- jpeg=9e=h166bdaf_2
- json-c=0.16=hc379101_0
- jsonschema=4.16.0=pyhd8ed1ab_0
- jupyter=1.0.0=py38h578d9bd_7
- jupyter_client=7.3.5=pyhd8ed1ab_0
- jupyter_console=6.4.4=pyhd8ed1ab_0
- jupyter_core=4.11.1=py38h578d9bd_0
- jupyterlab_pygments=0.2.2=pyhd8ed1ab_0
- jupyterlab_widgets=3.0.3=pyhd8ed1ab_0
- keyutils=1.6.1=h166bdaf_0
- kiwisolver=1.4.4=py38h43d8883_0
- krb5=1.19.3=h3790be6_0
- lame=3.100=h7f98852_1001
- lcms2=2.12=hddcbb42_0
- ld_impl_linux-64=2.36.1=hea4e1c9_2
- lerc=4.0.0=h27087fc_0
- libbrotlicommon=1.0.9=h166bdaf_7
- libbrotlidec=1.0.9=h166bdaf_7
- libbrotlienc=1.0.9=h166bdaf_7
- libcap=2.64=ha37c62d_0
- libclang=14.0.6=default_h2e3cab8_0
- libclang13=14.0.6=default_h3a83d3e_0
- libcups=2.3.3=h3e49a29_2
- libdb=6.2.32=h9c3ff4c_0
- libdeflate=1.14=h166bdaf_0
- libedit=3.1.20191231=he28a2e2_2
- libevent=2.1.10=h9b69904_4
- libffi=3.4.2=h7f98852_5
- libflac=1.3.4=h27087fc_0
- libgcc-ng=12.1.0=h8d9b700_16
- libgfortran-ng=7.5.0=h14aa051_20
- libgfortran4=7.5.0=h14aa051_20
- libglib=2.72.1=h2d90d5f_0
- libiconv=1.16=h516909a_0
- libllvm14=14.0.6=he0ac6c6_0
- libnsl=2.0.0=h7f98852_0
- libogg=1.3.4=h7f98852_1
- libopus=1.3.1=h7f98852_1
- libpng=1.6.38=h753d276_0
- libpq=14.5=hd77ab85_0
- libsndfile=1.0.31=h9c3ff4c_1
- libsodium=1.0.18=h36c2ea0_1
- libsqlite=3.39.3=h753d276_0
- libstdcxx-ng=12.1.0=ha89aaad_16
- libtiff=4.4.0=h55922b4_4
- libtool=2.4.6=h9c3ff4c_1008
- libuuid=2.32.1=h7f98852_1000
- libuv=1.44.2=h166bdaf_0
- libvorbis=1.3.7=h9c3ff4c_0
- libwebp-base=1.2.4=h166bdaf_0
- libxcb=1.13=h7f98852_1004
- libxkbcommon=1.0.3=he3ba5ed_0
- libxml2=2.9.14=h22db469_4
- libxslt=1.1.35=h8affb1d_0
- libzlib=1.2.12=h166bdaf_3
- llvm-openmp=14.0.4=he0ac6c6_0
- lxml=4.9.1=py38h0a891b7_0
- markupsafe=2.1.1=py38h0a891b7_1
- matplotlib-base=3.6.0=py38hb021067_0
- matplotlib-inline=0.1.6=pyhd8ed1ab_0
- mistune=2.0.4=pyhd8ed1ab_0
- mkl=2021.4.0=h8d4b97c_729
- mkl-service=2.4.0=py38h95df7f1_0
- mkl_fft=1.3.1=py38h8666266_1
- mkl_random=1.2.2=py38h1abd341_0
- munkres=1.0.7=py_1
- mysql-common=8.0.30=haf5c9bc_1
- mysql-libs=8.0.30=h28c427c_1
- nbclient=0.6.8=pyhd8ed1ab_0
- nbconvert=7.0.0=pyhd8ed1ab_0
- nbconvert-core=7.0.0=pyhd8ed1ab_0
- nbconvert-pandoc=7.0.0=pyhd8ed1ab_0
- nbformat=5.5.0=pyhd8ed1ab_0
- ncurses=6.3=h27087fc_1
- nest-asyncio=1.5.5=pyhd8ed1ab_0
- nettle=3.6=he412f7d_0
- networkx=2.8.6=pyhd8ed1ab_0
- notebook=6.4.12=pyha770c72_0
- nspr=4.32=h9c3ff4c_1
- nss=3.78=h2350873_0
- numpy=1.23.1=py38h6c91a56_0
- numpy-base=1.23.1=py38ha15fc14_0
- openh264=2.1.1=h780b84a_0
- openjpeg=2.5.0=h7d73246_1
- openssl=1.1.1w=hd590300_0
- packaging=21.3=pyhd8ed1ab_0
- pandas=1.5.0=py38h8f669ce_0
- pandoc=2.19.2=ha770c72_0
- pandocfilters=1.5.0=pyhd8ed1ab_0
- parso=0.8.3=pyhd8ed1ab_0
- pcre=8.45=h9c3ff4c_0
- pexpect=4.8.0=pyh9f0ad1d_2
- pickleshare=0.7.5=py_1003
- pillow=9.2.0=py38ha3b2c9c_2
- pip=22.2.2=pyhd8ed1ab_0
- pixman=0.40.0=h36c2ea0_0
- pkgutil-resolve-name=1.3.10=pyhd8ed1ab_0
- ply=3.11=py_1
- plyfile=0.7.4=pyhd8ed1ab_0
- portaudio=19.6.0=h57a0ea0_5
- prometheus_client=0.14.1=pyhd8ed1ab_0
- prompt-toolkit=3.0.31=pyha770c72_0
- prompt_toolkit=3.0.31=hd8ed1ab_0
- psutil=5.9.2=py38h0a891b7_0
- pthread-stubs=0.4=h36c2ea0_1001
- ptyprocess=0.7.0=pyhd3deb0d_0
- pulseaudio=14.0=h583eb01_5
- pure_eval=0.2.2=pyhd8ed1ab_0
- pycairo=1.21.0=py38h9c00e7a_1
- pycparser=2.21=pyhd8ed1ab_0
- pyg=2.0.4=py38_torch_1.11.0_cu113
- pygments=2.13.0=pyhd8ed1ab_0
- pyopenssl=22.0.0=pyhd8ed1ab_0
- pyparsing=3.0.9=pyhd8ed1ab_0
- pyqt=5.15.7=py38h7492b6b_0
- pyqt5-sip=12.11.0=py38hfa26641_0
- pyrsistent=0.18.1=py38h0a891b7_1
- pysocks=1.7.1=pyha2e5f31_6
- python=3.8.13=h582c2e5_0_cpython
- python-dateutil=2.8.2=pyhd8ed1ab_0
- python-fastjsonschema=2.16.2=pyhd8ed1ab_0
- python-louvain=0.15=pyhd8ed1ab_1
- python_abi=3.8=2_cp38
- pytorch=1.11.0=py3.8_cuda11.3_cudnn8.2.0_0
- pytorch-cluster=1.6.0=py38_torch_1.11.0_cu113
- pytorch-mutex=1.0=cuda
- pytorch-scatter=2.0.9=py38_torch_1.11.0_cu113
- pytorch-sparse=0.6.14=py38_torch_1.11.0_cu113
- pytorch-spline-conv=1.2.1=py38_torch_1.11.0_cu113
- pytz=2022.2.1=pyhd8ed1ab_0
- pyyaml=6.0=py38h0a891b7_4
- pyzmq=24.0.0=py38hfc09fa9_0
- qt-main=5.15.4=ha5833f6_2
- qtconsole=5.3.2=pyhd8ed1ab_0
- qtconsole-base=5.3.2=pyha770c72_0
- qtpy=2.2.0=pyhd8ed1ab_0
- rdkit=2022.09.1=py38h28c1a8d_0
- readline=8.1.2=h0f457ee_0
- reportlab=3.5.68=py38hadf75a6_1
- requests=2.28.1=pyhd8ed1ab_1
- scikit-learn=1.1.1=py38h6a678d5_0
- scipy=1.7.1=py38h292c36d_2
- send2trash=1.8.0=pyhd8ed1ab_0
- setuptools=65.3.0=pyhd8ed1ab_1
- sip=6.6.2=py38hfa26641_0
- six=1.16.0=pyh6c4a22f_0
- soupsieve=2.3.2.post1=pyhd8ed1ab_0
- sqlalchemy=1.4.41=py38h0a891b7_0
- sqlite=3.39.3=h4ff8645_0
- stack_data=0.5.0=pyhd8ed1ab_0
- system=5.8=2
- tbb=2021.5.0=h924138e_2
- terminado=0.15.0=py38h578d9bd_0
- threadpoolctl=3.1.0=pyh8a188c0_0
- tinycss2=1.1.1=pyhd8ed1ab_0
- tk=8.6.12=h27826a3_0
- toml=0.10.2=pyhd8ed1ab_0
- torchaudio=0.11.0=py38_cu113
- torchvision=0.12.0=py38_cu113
- tornado=6.2=py38h0a891b7_0
- tqdm=4.64.1=pyhd8ed1ab_0
- traitlets=5.4.0=pyhd8ed1ab_0
- typing_extensions=4.3.0=pyha770c72_0
- unicodedata2=14.0.0=py38h0a891b7_1
- urllib3=1.26.11=pyhd8ed1ab_0
- wcwidth=0.2.5=pyh9f0ad1d_2
- webencodings=0.5.1=py_1
- wheel=0.37.1=pyhd8ed1ab_0
- widgetsnbextension=4.0.3=pyhd8ed1ab_0
- xcb-util=0.4.0=h166bdaf_0
- xcb-util-image=0.4.0=h166bdaf_0
- xcb-util-keysyms=0.4.0=h166bdaf_0
- xcb-util-renderutil=0.3.9=h166bdaf_0
- xcb-util-wm=0.4.1=h166bdaf_0
- xorg-kbproto=1.0.7=h7f98852_1002
- xorg-libice=1.0.10=h7f98852_0
- xorg-libsm=1.2.3=hd9c2040_1000
- xorg-libx11=1.7.2=h7f98852_0
- xorg-libxau=1.0.9=h7f98852_0
- xorg-libxdmcp=1.1.3=h7f98852_0
- xorg-libxext=1.3.4=h7f98852_1
- xorg-libxrender=0.9.10=h7f98852_1003
- xorg-renderproto=0.11.1=h7f98852_1002
- xorg-xextproto=7.3.0=h7f98852_1002
- xorg-xproto=7.0.31=h7f98852_1007
- xz=5.2.6=h166bdaf_0
- yacs=0.1.8=pyhd8ed1ab_0
- yaml=0.2.5=h7f98852_2
- zeromq=4.3.4=h9c3ff4c_1
- zipp=3.8.1=pyhd8ed1ab_0
- zlib=1.2.12=h166bdaf_3
- zstd=1.5.2=h6239696_4
- pip:
- lmdb==1.3.0
prefix: /home/anaconda3/envs/Delete
3.2 下载checkpoint
作者提供了训练好的checkpoint,下载链接:Delete pretrained checkpoint
下载完成后,需要新建并将checkpoint放置在目录 ./checkpoint/ckpt下。
有趣的是,按照文章的说法,Delete有4中应用,对应着在预训练之后的四种不同的mask方式。但是作者只给出了一个checkpoint。
3.3 使用作者提供的案例,进行测试
在GitHub的代码中,作者提供了几个测试案例。这里我对2VT4体系进行了测试。2VT4的小分子以及口袋如下图所示,其中,黄色的吲哚环,是属于要替换的部分:
Delete需要提供口袋表面的ply文件,以及分子片段。其中,2VT4的口袋表面的ply文件作者已经准备好,放置在./example/adrb1/adrb_pocket_8.0.ply 路径中。Delete的起点分子片段,作者放置在./example/adrb1/2VT4_frag.sdf。Delete的起点分子片段如下图:
在./目录,运行如下代码生成分子:
python -u Delete.py \
--surf_path ./example/adrb1/adrb_pocket_8.0.ply \
--frag_path ./example/adrb1/2VT4_frag.sdf \
--check_point ./checkpoint/ckpt/delete.pt \
--outdir ./outputs \
--suboutdir adrb1
运行输出:
/home/anaconda3/envs/Delete/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.1
warnings.warn(f"A NumPy version >={np_minversion} and <{np_maxversion}"
Num of parameters is 37.06M
Start to generate!
/home/anaconda3/envs/Delete/lib/python3.8/site-packages/torch/functional.py:568: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at /opt/conda/conda-bld/pytorch_1646755903507/work/aten/src/ATen/native/TensorShape.cpp:2228.)
return _VF.meshgrid(tensors, **kwargs) # type: ignore[attr-defined]
Success: CC(=O)NCOCC(O)CNC(C)(C)C
Success: CC(C)(C)NCC(O)COc1ccccc1
... ...
生成的分子保存在.//outputs/adrb1/delete路径中,每个分子是一个sdf文件,默认生成了175个分子,如下图。
Delete_2VT4_case
看起来,生成的分子还不错,大多数为并环和三并环结构,与原来的参考分子有较高的相似性。
3.4 使用自己的测试案例
3.4.1 环境准备
使用自己的案例,需要先生成口袋表面的ply文件。
创建Surface conda 环境:
conda create -n Surface \
pymesh2 jupyter scipy joblib biopython \
rdkit plyfile -c conda-forge
apbs和pdb2pqr 安装需要另外下载安装包。
其中,apbs版本要选择3.0.0,下载链接:Releases · Electrostatics/apbs · GitHub 为了简单,我下载是预编译编版本,如下图:
下载完成后,进行解压,例如:/home/AI_Methods/Delete/APBS-3.0.0.Linux,然后修改~/.bashrc文件,新增一行:(需要根据解压目录,进行修改路径)
export LD_LIBRARY_PATH=/home/AI_Methods/Delete/APBS-3.0.0.Linux/lib
pdb2pqr选择2.1.0,下载链接是:https://github.com/Electrostatics/apbs-pdb2pqr/releases ,同样下载的是预编译版本。
下载完成后解压,我这里的解压路径:为:/home/AI_Methods/Delete/pdb2pqr-linux-bin64-2.1.0
3.4.2 修改代码
在代码中,作者调用了msms, apbs, pdb2pqr 和 multivalue模块,因此需要根据上述的两个解压路径,修改./data/surface_maker_test.py文件内容:
msms_bin="/home/haotian/Molecule_Generation/SurfBP/dataset/install_software/APBS-3.0.0.Linux/bin/msms"
apbs_bin = '/home/haotian/Molecule_Generation/SurfBP/dataset/install_software/APBS-3.0.0.Linux/bin/apbs'
pdb2pqr_bin="/home/haotian/Molecule_Generation/SurfBP/dataset/install_software/pdb2pqr-linux-bin64-2.1.1/pdb2pqr"
multivalue_bin="/home/haotian/Molecule_Generation/SurfBP/dataset/install_software/APBS-3.0.0.Linux/share/apbs/tools/bin/multivalue"
修改为:
msms_bin="/home/AI_Methods/Delete/APBS-3.0.0.Linux/bin/msms"
apbs_bin = '/home/AI_Methods/Delete/APBS-3.0.0.Linux/bin/apbs'
pdb2pqr_bin="/home/AI_Methods/Delete/pdb2pqr-linux-bin64-2.1.0/pdb2pqr"
multivalue_bin="/home/AI_Methods/Delete/APBS-3.0.0.Linux/share/apbs/tools/bin/multivalue"
注意,如果下载不同版本的pdb2pqr,需要去相应的路径检查,是否存在msms, multivalue两个模块。一些版本,缺失这两个模块。
同时./data/surface_maker_test.py还需要做以下修改,以便对不同的体系做表面:
prot_path = './1z6e_protein.pdb'
lig_path = './1z6e_ligand.mol2'
修改为:
lig_path = args.lig_file # wufeil
prot_path = args.pdb_file # wufeil
除此之外,由于作者提供的./utils/masif/computeAPBS.py部分代码,由于版本或者其他原因,无法运行,也需要修改。直接替换computeAPBS函数如下:
def computeAPBS(vertices, pdb_file, apbs_bin, pdb2pqr_bin, multivalue_bin, workdir="."):
"""
Calls APBS, pdb2pqr, and multivalue and returns the charges per vertex
"""
cmd = pdb2pqr_bin + " --ff=PARSE --whitespace --noopt --apbs-input %s temp1"%(pdb_file)
# p = subprocess.Popen([cmd], shell=True, cwd=workdir)
p = subprocess.Popen([cmd], shell=True, cwd='./') # wufeil
p.wait()
cmd = apbs_bin + " temp1.in"
# p = subprocess.Popen([cmd], shell=True, cwd=workdir)
p = subprocess.Popen([cmd], shell=True, cwd='./') # wufeil
p.wait()
vertfile = open("%s/temp1.csv"%workdir, "w")
for vert in vertices:
vertfile.write("{},{},{}\n".format(vert[0], vert[1], vert[2]))
vertfile.close()
# cmd = multivalue_bin + " temp1.csv temp1.dx temp1_out.csv"
cmd = multivalue_bin + " temp1.csv ../temp1.dx temp1_out.csv" # wufeil
p = subprocess.Popen([cmd], shell=True, cwd=workdir)
# p = subprocess.Popen([cmd], shell=True, cwd='./') # wufeil
p.wait()
# Read the charge file
chargefile = open("%s/temp1_out.csv"%workdir)
charges = np.array([0.0] * len(vertices))
for ix, line in enumerate(chargefile.readlines()):
charges[ix] = float(line.split(",")[3])
#os.system("rm " + tmp_file_base + "*")
#os.system("rm io.mc")
return charges
3.4.3 生成surface ply文件
在./data目录下运行如下命令:
python surface_maker_test.py --check_software True
默认是对./data目录下的3cl.pdb体系的3cl_ligand.sdf口袋生成surface文件。重要输出如下:
... ...
Parsing input file temp1.in...
rank 0 size 1...
Parsed input file.
Got paths for 1 molecules
Reading PQR-format atom data from temp1.
1394 atoms
Centered at (-1.636e+01, 1.749e+01, 6.603e+01)
Net charge 3.33e-16 e
Preparing to run 2 PBE calculations.
----------------------------------------
CALCULATION #1: MULTIGRID
Setting up problem...
Vpbe_ctor: Using max ion radius (0 A) for exclusion function
Debye length: 0 A
Current memory usage: 292.214 MB total, 292.214 MB high water
Using cubic spline charge discretization.
Grid dimensions: 97 x 129 x 97
Grid spacings: 0.615 x 0.534 x 0.633
Grid lengths: 59.027 x 68.342 x 60.807
Grid center: (-16.364, 17.491, 66.026)
Multigrid levels: 4
Molecule ID: 1
Linearized traditional PBE
Single Debye-Huckel sphere boundary conditions
0 ion species (0.000 M ionic strength):
Solute dielectric: 2.000
Solvent dielectric: 78.540
Using "molecular" surface definition;harmonic average smoothing
Solvent probe radius: 1.400 A
Temperature: 298.150 K
Electrostatic energies will be calculated
Total electrostatic energy = 4.681582329937E+04 kJ/mol
Calculating forces...
----------------------------------------
CALCULATION #2: MULTIGRID
Setting up problem...
Vpbe_ctor: Using max ion radius (0 A) for exclusion function
Debye length: 0 A
Current memory usage: 292.214 MB total, 581.598 MB high water
Using cubic spline charge discretization.
Grid dimensions: 97 x 129 x 97
Grid spacings: 0.570 x 0.470 x 0.581
Grid lengths: 54.722 x 60.201 x 55.769
Grid center: (-16.364, 17.491, 66.026)
Multigrid levels: 4
Molecule ID: 1
Linearized traditional PBE
Boundary conditions from focusing
0 ion species (0.000 M ionic strength):
Solute dielectric: 2.000
Solvent dielectric: 78.540
Using "molecular" surface definition;harmonic average smoothing
Solvent probe radius: 1.400 A
Temperature: 298.150 K
Electrostatic energies will be calculated
Potential to be written to temp1.dx
Total electrostatic energy = 5.558845164011E+04 kJ/mol
Calculating forces...
Writing potential to temp1.dx
----------------------------------------
PRINT STATEMENTS
print energy 1 end
Local net energy (PE 0) = 5.558845164011E+04 kJ/mol
Global net ELEC energy = 5.558845164011E+04 kJ/mol
----------------------------------------
CLEANING UP AND SHUTTING DOWN...
Destroying force arrays.
No energy arrays to destroy.
Destroying multigrid structures.
Destroying finite element structures.
Destroying 1 molecules
Final memory usage: 0.001 MB total, 581.598 MB high water
Thanks for using APBS!
... ...
3cl_pocket_8.0.ply就是我们需要的文件。
3.4.4 生成分子
使用上述生成的3cl_pocket_8.0.ply继续生成分子:
python -u Delete.py \
--surf_path ./example/3lc/3cl_pocket_8.0.ply \
--frag_path ./example/3lc/3cl_frag.sdf \
--check_point ./checkpoint/ckpt/delete.pt \
--outdir ./outputs_3lc \
--suboutdir 3lc
注意,需要先创建3lc目录,里面放置3cl_pocket_8.0.ply, 3cl_frag.sdf文件。
与之前的案例不同,3cl_frag.sdf是我自己创建的,切除了中间的酯键的linker,如下图:
原先的参考分子为:
以下是Delete生成的小分子的2D结构示例:
感觉生成分子的质量一般,在上述生成的分子中,除了正常的linker连接分子以外,还有一些多并环的分子,以及一些大环的分子。
生成分子的3D pose如下动画:
Delete_3cl_case
虽然,生成的分子比较奇怪,但是酯基的骨架跃迁位置,Delete生成的分子大部分都有酰胺,酯基结构,侧面说明,Delete模型对于口袋和分子的相互作用识别较好。
四、测评总结
作者提出了一种应用关于Lead优化过程中骨架跃迁、linker设计,片段延伸,和侧链修饰的统一模型 Delete 。
Delete 模型基于mask策略,按照作者的描述,首先是随机掩码预训练模型,然后是应用于骨架跃迁、linker设计,片段延伸、侧链修饰的四个微调模型。通过,vina energy等分析,发现 Delete 模型生成的分子可能具有更好的活性。
复测了作者github中的测试体系 2VT4,测试片段延伸,生成的分子还不错,大多数为并环和三并环结构,与原来的参考分子有较高的相似性。
当使用 3lc 体系,自定义做骨架跃迁测试时,发现生成的分子质量一般,且有大量的手性分子,可合成性比较困难。但是,Delete 模型对于口袋-分子的相互作用识别能力较好。
此外,虽然作者提供了训练模型的代码和预处理好的数据集,但是未提供数据的处理方法,即使能训练模型,但是也无法使用自己的数据集进行从头训练。
按照文章的描述,针对4种不同的Lead优化过程中的应用,应该有四个checkpoint模型的,但是作者仅仅提供了一种。
另外,在生长过程中,生长位点不能指定。
总结来说,Delete 属于概念性研究,实用性不强,代码完整性差。可以直接使用,但是需要好好挑挑分子。