PDBFixer进行分子动力学模拟前处理

在分子动力学模拟之前,通常需要对蛋白的结构进行预处理,如补全残基等。使用斯坦福大学 Pande 课题组的小工具 PDBFixer 便能通过 GUI 或者命令行轻松解决这一问题。

PDBFixer 能够解决的问题包括: - 添加缺失的重原子 - 添加缺失的氢原子 - 添加缺失的 loop - 将非标准残基转换为对应的标准残基 - 对于某些原子,选择多个备选位置中的一个位置 - 删除不需要的蛋白质链 - 删除不需要的 heterogens - 添加水盒子和离子

Notes: - 补全 loop 时,缺失的残基序列是从 pdb 文件开头的 SEQRES records 中获取 - fixer.replaceNonstandardResidues() 用来突变氨基酸

安装

PDBFixer 可以通过 Omnia 套件进行安装,自动安装其它依赖条件。例如:

1
2
3
4
# Add conda-forge and omnia to your channel list
conda config --add channels omnia --add channels conda-forge
# Install the 'pdbfixer' a package
conda install pdbfixer

简单使用

PDBFixer 具有 GUI, Command Line 和 Python API 三种使用模式。

GUI 操作

在终端中输入 pdbfixer, 然后在浏览器中打开 http://localhost:8000 。之后按照提示进行操作即可。默认输出文件为 output.pdb

Command Line 操作

PDBFixer 也可以通过命令行进行操作,但部分功能受限。当在终端中输入 pdbfixer 且带有任意选项或参数,即可使用命令行形式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
pdbfixer --help

Usage: pdbfixer
pdbfixer [options] filename

Options:
-h, --help show this help message and exit
--pdbid=PDBID PDB id to retrieve from RCSB [default: None]
--url=URL URL to retrieve PDB from [default: None]
--output=FILENAME output pdb file [default: output.pdb]
--add-atoms=ATOMS which missing atoms to add: all, heavy, hydrogen, or
none [default: all]
--keep-heterogens=OPTION
which heterogens to keep: all, water, or none
[default: all]
--replace-nonstandard
replace nonstandard residues with standard equivalents
--add-residues add missing residues
--water-box=X Y Z add a water box. The value is the box dimensions in nm
[example: --water-box=2.5 2.4 3.0]
--ph=PH the pH to use for adding missing hydrogens [default:
7.0]
--positive-ion=ION positive ion to include in the water box: Cs+, K+,
Li+, Na+, or Rb+ [default: Na+]
--negative-ion=ION negative ion to include in the water box: Cl-, Br-,
F-, or I- [default: Cl-]
--ionic-strength=STRENGTH
molar concentration of ions to add to the water box
[default: 0.0]

1
pdbfixer myfile.pdb --keep-heterogens=water --replace-nonstandard --water-box=4.0 4.0 3.0 

以上命令会自动为输入文件添加缺失的氢原子和重原子(但不会添加缺失的残基),加氢使用默认的 pH 7.0。如果文件中包含非标准氨基酸或核酸,会转换为最接近的标准氨基酸。文件中的水分子会保留,而其它杂原子将会被清除。最后,会输出文件 'output.pdb'。 --add-residues选项会依据初始pdb中的SEQRES 字段来补全缺失的残基,故可以在此SEQRES字段中增加或减少残基来确定 --add-residues 参数要添加哪些残基。

Python API 操作

这种方式是 PDBFixer 最为复杂也是功能最为完善同时也便于控制每一个细节的使用方式。 PDBFixer 基于 OpenMM,同时也使用它的 API。所以最好是提前了解 OpenMM 的 API。(然而并不了解,那就先强学一波... ) 主要流程为导入结构,进行处理,之后再保存结构。所以脚本的框架为:

1
2
3
4
5
6
7
8
from pdbfixer import PDBFixer
from simtk.openmm.app import PDBFile

fixer = PDBFixer(filename='myfile.pdb')
# ...
# Call various methods on the PDBFixer
# ...
PDBFile.writeFile(fixer.topology, fixer.positions, open('output.pdb', 'w'))
Notes: - 以下所列处理步骤并不全是必需的,可以选用部分步骤。 - 不能改变这些步骤的顺序!

Remove Chains

1
2
3
fixer.remove(indices)

indices 为欲移除的链,是一个列表。

Identify Missing Residues

1
2
3
4
5
6
7
8
9
10
11
fixer.findMissingResidues()    # 确定缺失的残基(从 pdb 文件开头的 SEQRES records 中获取) 

结果保存在 fixer.missingResidues,为一个字典,字典的 key 为一个 tuple,包含链的 index,缺失残基在此链中应插入位置的index(会在这个 index 之前进行插入)。
对应的 value 是一个列表,包含缺失残基的 name。

此后,可以通过修改这个字典的内容来指定插入残基的名称。比如,可以通过删除一条记录来表明不添加这个残基。

如果不希望添加任何残基,只需:
fixer.missingResidues = {}

缺失的残基会在调用 addMissingAtoms() 之后才进行添加。

Replace Nonstandard Residues

1
2
3
4
5
6
7
fixer.findNonstandardResidues()
fixer.replaceNonstandardResidues()

findNonstandardResidues() 会将结果保存在 nonstandardResidues field(一个列表)。
每一条记录都是一个 tuple,其第一个元素是一个 Residue object,第二个元素是替换之后的 Residue name。我们也可以修改这个列表。

比如,如果不希望某个非标准氨基酸被替换,只需要修改其对应的目标氨基酸即可。同理,我们也可以突变其它的氨基酸。

Remove Heterogens

1
2
3
fixer.removeHeterogens(False)

参数 False 表示移除包括水在内的所有杂原子, True 表示保留水但移除其它所有杂原子。

Add Missing Heavy Atoms

1
2
3
4
5
6
7
8
9
10
fixer.findMissingAtoms()
fixer.addMissingAtoms()

findMissingAtoms() 确定所有缺失的重原子,然后保存在 missingAtoms 和 missingTerminals 中。
二者的类型都是字典,key 是 Residue objects,value 是 atom names 构成的列表。

missingAtoms 包括在标准氨基酸中应当存在的原子,missingTerminals 包含在端基中应当存在的原子,可以在 addMissingAtoms() 之前进行修改。

addMissingAtoms() 调用之后,会添加之前确定的所有重原子,包括 findMissingAtoms() 和 findMissingResidues() 所确定的。
此外,当你调用 replaceNonstandardResidues() 的时候,只是删去了不属于目标残基的原子,并没有实时添加新的原子。只有在调用 addMissingAtoms() 之后才会真正的进行添加。

Add Missing Hydrogens

1
2
3
fixer.addMissingHydrogens(7.0)

会基于对应的 pH 值来进行质子化。

Add Water

1
2
3
4
5
6
7
addSolvent()    # 添加水盒子 

addSolvent(self, boxSize, positiveIon='Na+', negativeIon='Cl-', ionicStrength=0*molar) # 完整调用

boxSize 是一个 Vec3 object,用来指定水盒子的维度。阳离子和阴离子分别包括Cs+, K+, Li+, Na+, and Rb+; Cl-, Br-, F-, and I-

fixer.addSolvent(Vec3(5, 5, 5)*nanometer, positiveIon='K+', ionicStrength=0.1*molar) # builds a 5 nm cube of 0.1 molar potassium chloride:

Examples

添加所有缺失的原子(包括缺失的重原子,缺失的残基,和氢原子),将非标准氨基酸全部替换为对应的标准氨基酸,然后删去除了水以外的所有杂原子。再添加与 crystallographic unit cell 匹配的水盒子。最后,保存为 output.pdb:

1
2
3
4
5
6
7
8
9
10
11
12
13
from pdbfixer import PDBFixer
from simtk.openmm.app import PDBFile

fixer = PDBFixer(filename='myfile.pdb')
fixer.findMissingResidues()
fixer.findNonstandardResidues()
fixer.replaceNonstandardResidues()
fixer.removeHeterogens(True)
fixer.findMissingAtoms()
fixer.addMissingAtoms()
fixer.addMissingHydrogens(7.0)
fixer.addSolvent(fixer.topology.getUnitCellDimensions())
PDBFile.writeFile(fixer.topology, fixer.positions, open('output.pdb', 'w'))

只保留第一条链,删除其它所有链:

1
2
3
4
fixer = PDBFixer(filename='myfile.pdb')
numChains = len(list(fixer.topology.chains()))
fixer.removeChains(range(1, numChains))
fixer.findMissingResidues()

只添加链中间缺失的残基,而不添加链两端缺失的残基。通过在调用 findMissingResidues() 之后修改 missingResidues 来实现:

1
2
3
4
5
6
7
8
fixer.findMissingResidues()
chains = list(fixer.topology.chains())
keys = fixer.missingResidues.keys()
for key in keys:
chain = chains[key[0]]
if key[1] == 0 or key[1] == len(list(chain.residues())):
del fixer.missingResidues[key]
fixer.findNonstandardResidues()

不添加与 crystallographic unit cell 相匹配的水盒子,而是添加足够大的水盒子。比如,先计算蛋白在每个坐标轴上的投影,设置盒子的长度与最大的投影一致:

1
2
3
4
5
fixer.addMissingHydrogens(7.0)
maxSize = max(max((pos[i] for pos in fixer.positions))-min((pos[i] for pos in fixer.positions)) for i in range(3))
boxSize = maxSize*Vec3(1, 1, 1)
fixer.addSolvent(boxSize)
PDBFile.writeFile(fixer.topology, fixer.positions, open('output.pdb', 'w'))

将所有非标准氨基酸突变为丙氨酸:

1
2
3
fixer.findNonstandardResidues()
fixer.nonstandardResidues = [(residue, 'ALA') for residue, replacement in fixer.nonstandardResidues]
fixer.replaceNonstandardResidues()

Others

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
###################################
fixer.sequences

fixer.templates

fixer.source

fixer.topology
fixer.positions

##########

fixer.modifiedResidues
fixer.applyMutations

###################################

Ref: - PDBFixer Manual