@Author: 张博文 @email:bowen.zhang@xtalpi.com
@Proofread: 吴炜坤 @email:weikun.wu@xtalpi.com
在第一章第五节中,我们学习了有关蛋白质几何构象的处理方式的各种概念及处理方式。在蛋白质构象设计的过程中,我们需要针对这些几何关系对蛋白质结构进行计算。此时,就会涉及到计算过程中坐标的处理方式。这一章将介绍的就是Rosetta中坐标的处理方式。
# 初始化pyrosetta,使用pyrosetta必须要做的一件事情
from pyrosetta import *
from pyrosetta.rosetta import *
from pyrosetta.teaching import *
init()
PyRosetta-4 2021 [Rosetta PyRosetta4.conda.mac.cxx11thread.serialization.python37.Release 2021.26+release.b308454c455dd04f6824cc8b23e54bbb9be2cdd7 2021-07-02T13:01:54] retrieved from: http://www.pyrosetta.org (C) Copyright Rosetta Commons Member Institutions. Created in JHU by Sergey Lyskov and PyRosetta Team. core.init: {0} Checking for fconfig files in pwd and ./rosetta/flags core.init: {0} Rosetta version: PyRosetta4.conda.mac.cxx11thread.serialization.python37.Release r288 2021.26+release.b308454c455 b308454c455dd04f6824cc8b23e54bbb9be2cdd7 http://www.pyrosetta.org 2021-07-02T13:01:54 core.init: {0} command: PyRosetta -ex1 -ex2aro -database /opt/miniconda3/lib/python3.7/site-packages/pyrosetta/database basic.random.init_random_generator: {0} 'RNG device' seed mode, using '/dev/urandom', seed=1689727216 seed_offset=0 real_seed=1689727216 thread_index=0 basic.random.init_random_generator: {0} RandomGenerator:init: Normal mode, seed=1689727216 RG_type=mt19937
PDB文件中,大多数的表示都是笛卡尔坐标(X,Y,Z),当改变或设置这3个值时,该原子的位置也就确定了,此时每个原子都具有三个自由度,但三个自由度对于计算来说复杂度过高。
在进行计算的时候,坐标的表示方式是这样的:
1 使用了内坐标来进行表示。内坐标定义如下:如下图所示,对于一个原子,其位置坐标通过其与临近原子的键长、键角、二面角来进行表示。此个原子来说,构象的改变是通过改变键长、键角和二面角来完成的,但此时的自由度仍为3。(二面角 dihedral,扭转角 = 180度 - 二面角,互补关系)
举例: 如果想知道原子j的坐标,我们可以通过从原点和原子i的信息来计算,此处已知原点到原子i键长以及原子i到原子j的键长。此时只要再加上原点-原子i-原子j之间的键角。就可以推算出原子j的具体坐标(xyz),因此内坐标和笛卡尔坐标是可以轻易被转换的。
2 减少自由度降低计算复杂度:
尽管此时对于一个原子来说自由度仍为3,但这三个自由度在蛋白质设计中的重要程度并不相同。往往在蛋白质建模的过程中,键长、键角的变化相对来说设计很微小的,这时候若设置将此两者设置为理想值(固定值),只以二面角的变化来表示构象变化。此时自由度就降为1了!。同时,对于特定的原子(例如大多数的氢)其二面角受其化学环境的影响是固定的,此时自由度就变为0了。
在Rosseta中, FoldTree即对蛋白质主链内部及主链之间表示其上下游关系的方式,它定义了在蛋白质结构中,哪些残基是上游或是母节点、哪些残基是下游或是子节点,并为其贴上了标签,并且约定当内坐标自由度发生变换时,只有FoldTree下游的氨基酸xyz坐标会发生改变,而上游氨基酸的构象保持不变。
此处举一个最简单的例子: FoldTree的顺序是从N端到C端,仅有一条链。因此1号残基是此树结构的"根"(上游),8号残基是最末端的"支"(下游)。
如果此时对4号残基的骨架的二面角做出改变。只有处于树结构下游(5->6->7->8)的氨基酸会发生坐标变换。
FoldTree共有四种特性:
杠杆效应本质即当遵守如上所说约定时,当内坐标变化时,约定只对处于树下游区域的氨基酸xyz坐标进行变换所产生的现象。
举例,首先得到了一个由五个残基组成的多肽。
pose = pose_from_sequence('KPALN') # 根据序列生成一个示例的多肽序列
pose.dump_pdb('./data/example.pdb') # 保存该pose为pdb文件
core.chemical.GlobalResidueTypeSet: {0} Finished initializing fa_standard residue type set. Created 984 residue types core.chemical.GlobalResidueTypeSet: {0} Total time to initialize 0.695354 seconds.
True
# 更改示例多肽序列的3号残基的phi角
pose.set_phi(3,70) # 修改3号ALA残基的phi角
pose.dump_pdb('./data/example_change.pdb') # 保存修改后的pose为pdb文件
True
# 打印foldtree信息:
print(pose.fold_tree())
FOLD_TREE EDGE 1 5 -1
从foldtree的信息来看,目前的设置是树顺序是1->2->3->4->5,因此当3号氨基酸phi角发生变化时,3,4,5号氨基酸都属于下游区域,理应发生坐标变换。
因此在内坐标体系中,通过内坐标和笛卡尔坐标的换算,可以高效地表示由于杠杠效应带来的3N*atom_number个自由度的变化。
Edge是FoldTree的基本组成部分,一个FoldTree是由1个或多个Edge组成。在Pyrosetta中Fold_Tree通过fold_tree方法来进行调用
# PDB:1v74的例子
pose_1v74 = pose_from_pdb('./data/1v74.pdb') #读入蛋白质的pdb文件
pose_1v74_foldtree = pose_1v74.fold_tree() #得到该pose的foldtree实例
core.import_pose.import_pose: {0} File './data/1v74.pdb' automatically determined to be of type PDB core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue LEU:CtermProteinFull 107 core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue LEU:CtermProteinFull 194
# 输出PDB:1V74的信息
print(pose_1v74.pdb_info())
PDB file name: ./data/1v74.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0107 A 0591 -- 0697 | 0107 residues; 01728 atoms 0108 -- 0194 B 0001 -- 0087 | 0087 residues; 01425 atoms TOTAL | 0194 residues; 03153 atoms
如同上面的输出所示,示例pose具有2条多肽链,分别是1-107号残基,以及108-194号残基的肽链。
# 输出PDB:1V74的fold tree表示
print("1v74 Fold Tree:\n", pose_1v74_foldtree)
1v74 Fold Tree: FOLD_TREE EDGE 1 107 -1 EDGE 1 108 1 EDGE 108 194 -1
FoldTree的表示方式一般如下。有四个字段组成:EDGE、Start、End、Define 如上面输出所示:
对于FoldTree的Jump,我们可以通过foldtree实例的一些方法得到他的信息。(关于Jump点的信息我们将在3.2章节中进行介绍)
print(f"The size of the foldtree (number of edges) is {pose_1v74_foldtree.size()}") #Foldtree 的尺寸(edge的个数)
print(f"The number of the jump is {pose_1v74_foldtree.num_jump()}") #Foldtree 的jump点的个数
The size of the foldtree (number of edges) is 3 The number of the jump is 1
基本的操作方式:
# 从序列创建一个Pose对象
seq_pose = pose_from_sequence('AAAAAAA') #读入PDB文件
print(seq_pose.fold_tree())
FOLD_TREE EDGE 1 7 -1
可见,在创建Pose的同时FoldTree也会同时被自动创建,但这个foldtree默认是从N到C端的顺序进行创建。
# 设置一个foldtree对象的实例,并将它读回pose中更新foldtree
ft = FoldTree() #设置一个空的foldtree对象
print(ft)
ft.check_fold_tree() # 检查foldtree的有效性;
FOLD_TREE
False
可见,通过check_fold_tree函数,可以快速检测你的foldtree是否有效。
#增加一个5号残基到1号残基的共价连接的edge
ft.add_edge(start=5, stop=1, label=-1) # label代表egde类型,-1=多肽链,1=jump
ft.check_fold_tree() # 检查foldtree的有效性;
True
上面我们仅定义了1-5号氨基酸的foldtree,但是我们创建的pose却有7个氨基酸。此时将这个foldtree加载到pose中会发生什么?
seq_pose.fold_tree(ft) #更新pose的fold_tree
core.conformation.Conformation: {0} [ ERROR ] Error in assigning a FoldTree to a Conformation - size mismatch. core.conformation.Conformation: {0} [ ERROR ] Conformation of length 7: A[ALA:NtermProteinFull]AAAAAA[ALA:CtermProteinFull] core.conformation.Conformation: {0} [ ERROR ] FoldTree of length 5: FOLD_TREE EDGE 5 1 -1
--------------------------------------------------------------------------- RuntimeError Traceback (most recent call last) <ipython-input-12-cb53977f0fef> in <module> ----> 1 seq_pose.fold_tree(ft) #更新pose的fold_tree RuntimeError: File: /Volumes/MacintoshHD3/benchmark/W.fujii.release/rosetta.Fujii.release/_commits_/main/source/src/core/conformation/Conformation.cc:829 [ ERROR ] UtilityExitException ERROR: Conformation: fold_tree nres should match conformation nres. conformation nres: 7 fold_tree nres: 5
运行结果表示,foldtree中必须完整定义整个pose的所有氨基酸上下游关系时,才是一个完整的tree!
# 完整定义试试:
ft = FoldTree() #设置一个空的foldtree对象
ft.add_edge(start=5, stop=1, label=-1)
ft.add_edge(start=5, stop=7, label=-1)
ft.check_fold_tree() # 检查foldtree的有效性;
seq_pose.fold_tree(ft) #更新pose的fold_tree
print(seq_pose.fold_tree())
在FoldTree中,Start和End字段是顺序敏感的,包括N->C顺序以及C->N顺序。不同顺序,代表EDGE内氨基酸所对应的上下游关系不同。
还是以原本的的五肽为例,原本是以N->C的顺序来进行排列的。我们将其人为修改为C->N后,由于FoldTree上下游关系的改变,修改二面角后构象造成的变化也不再相同。
#观察原本五肽的FoldTree
pose = pose_from_sequence('KPALN') # 根据一个序列得到一个五肽序列的pose
pose.dump_pdb('./data/example_5_1.pdb') #保存五肽的构象
print("The Fold Tree of the pose:\n", pose.fold_tree()) # 输出该pose的FoldTree
# 设置一个foldtree对象的实例,并将它读回pose中更新foldtree
ft = FoldTree() #设置一个空的foldtree对象
ft.add_edge(start=5, stop=1, label=-1) #增加一个5号残基到1号残基的共价连接的edge
pose.fold_tree(ft) #更新pose的fold_tree
print(pose.fold_tree()) #输出foldtree
pose.set_phi(3,70) #更改肽链的3号残基的phi角
pose.dump_pdb('./data/example_5_1_change.pdb') #保存更改后的五肽的构象
如图,黄色的是初始的五肽,蓝色的是原本的多肽在修改3号残基的phi角后的多肽构象,可以发现出现构象改变的是4、5号残基;而在修改该多肽的FoldTree为从5到1的顺序后,发生构象变化的就是1、2号残基。而这,就是foldtree的顺序性,即在改变选定残基的构象时,随之而改变的只有选定残基下游的氨基酸的构象