Pose中储存了非常多的信息,同时还提供了接口可以让用户方便的对其中的信息进行修改(采样)。 本章节将着重介绍Pose的基本操作方式。
# 首先依然是从PDB中读入Pose
from pyrosetta import init, pose_from_pdb
init()
pose = pose_from_pdb('./data/4R80.clean.pdb')
PyRosetta-4 2021 [Rosetta PyRosetta4.conda.mac.cxx11thread.serialization.python37.Release 2021.31+release.c7009b3115c22daa9efe2805d9d1ebba08426a54 2021-08-07T10:04:12] 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 r292 2021.31+release.c7009b3115c c7009b3115c22daa9efe2805d9d1ebba08426a54 http://www.pyrosetta.org 2021-08-07T10:04:12 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=-1249606663 seed_offset=0 real_seed=-1249606663 thread_index=0 basic.random.init_random_generator: {0} RandomGenerator:init: Normal mode, seed=-1249606663 RG_type=mt19937 core.chemical.GlobalResidueTypeSet: {0} Finished initializing fa_standard residue type set. Created 983 residue types core.chemical.GlobalResidueTypeSet: {0} Total time to initialize 0.695115 seconds. core.import_pose.import_pose: {0} File './data/4R80.clean.pdb' automatically determined to be of type PDB core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue SER:CtermProteinFull 76 core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue SER:CtermProteinFull 152
前几节中提及过,pose是一个容器,理所当然我们可以创建一个空的容器,里面什么都不放。
很多时候,我们需要创建空的Pose对象,便于保存当前pose的实例化状态,可作为可回溯点或初始状态,方便反复调用。
# 通过创建一个新的Pose
from pyrosetta import Pose
copy_pose1 = Pose()
copy_pose2 = None
此处通过两种方法,将已有的Pose信息放入新的容器里,一种是通过assign函数复制,一种是通过python赋值符号来赋值。
# 方法1:通过assign复制新的构象
copy_pose1.assign(pose)
# 方法2:通过python的直接赋值符号
copy_pose2 = pose
print(copy_pose1)
print('\n')
print(copy_pose2)
PDB file name: ./data/4R80.clean.pdb Total residues: 152 Sequence: PSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGS Fold tree: FOLD_TREE EDGE 1 76 -1 EDGE 1 77 1 EDGE 77 152 -1 PDB file name: ./data/4R80.clean.pdb Total residues: 152 Sequence: PSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGS Fold tree: FOLD_TREE EDGE 1 76 -1 EDGE 1 77 1 EDGE 77 152 -1
可见,两种方式“看”起来里面都有了新的pose信息。但真的如此么?
# 尝试调整初始pose中的24号氨基酸phi值:
pose.set_phi(24, 170.0)
# 查看对starting_pose以及starting_pose2的影响:
print(f'copy_pose1 24 residue phi:{copy_pose1.phi(24)}')
print(f'copy_pose2 24 residue phi:{copy_pose2.phi(24)}')
copy_pose1 24 residue phi:-91.24043946940483 copy_pose2 24 residue phi:170.0
结果表明:
先前章节中描述的都是对蛋白质的几何空间做参数的调整,而并不涉及到拓扑结构的改变。在PyRosetta中,对蛋白的结构域进行修改本质上就是对氨基酸的插入和删除。
# 链交换, 注意链号会变成AB.
from pyrosetta.rosetta.protocols.simple_moves import SwitchChainOrderMover
exchange_pose = pose_from_pdb('./data/6LZ9_H_L.pdb')
print(exchange_pose.pdb_info())
core.import_pose.import_pose: {0} File './data/6LZ9_H_L.pdb' automatically determined to be of type PDB core.conformation.Conformation: {0} Found disulfide between residues 21 94 core.conformation.Conformation: {0} current variant for 21 CYS core.conformation.Conformation: {0} current variant for 94 CYS core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} Found disulfide between residues 141 206 core.conformation.Conformation: {0} current variant for 141 CYS core.conformation.Conformation: {0} current variant for 206 CYS core.conformation.Conformation: {0} current variant for 141 CYD core.conformation.Conformation: {0} current variant for 206 CYD PDB file name: ./data/6LZ9_H_L.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0081 H 0002 -- 0082 | 0081 residues; 01283 atoms 0082 -- 0082 H 0082A -- 0082A | 0001 residues; 00011 atoms 0083 -- 0083 H 0082B -- 0082B | 0001 residues; 00011 atoms 0084 -- 0084 H 0082C -- 0082C | 0001 residues; 00019 atoms 0085 -- 0102 H 0083 -- 0100 | 0018 residues; 00271 atoms 0103 -- 0103 H 0100A -- 0100A | 0001 residues; 00010 atoms 0104 -- 0104 H 0100B -- 0100B | 0001 residues; 00021 atoms 0105 -- 0105 H 0100C -- 0100C | 0001 residues; 00021 atoms 0106 -- 0106 H 0100D -- 0100D | 0001 residues; 00010 atoms 0107 -- 0107 H 0100E -- 0100E | 0001 residues; 00017 atoms 0108 -- 0119 H 0101 -- 0112 | 0012 residues; 00171 atoms 0120 -- 0223 L 0002 -- 0105 | 0104 residues; 01588 atoms TOTAL | 0223 residues; 03433 atoms
switch_chains = SwitchChainOrderMover()
switch_chains.chain_order("LH")
switch_chains.apply(exchange_pose)
print(exchange_pose.pdb_info())
core.scoring.ScoreFunctionFactory: {0} SCOREFUNCTION: ref2015
core.scoring.etable: {0} Starting energy table calculation
core.scoring.etable: {0} smooth_etable: changing atr/rep split to bottom of energy well
core.scoring.etable: {0} smooth_etable: spline smoothing lj etables (maxdis = 6)
core.scoring.etable: {0} smooth_etable: spline smoothing solvation etables (max_dis = 6)
core.scoring.etable: {0} Finished calculating energy tables.
basic.io.database: {0} Database file opened: scoring/score_functions/hbonds/ref2015_params/HBPoly1D.csv
basic.io.database: {0} Database file opened: scoring/score_functions/hbonds/ref2015_params/HBFadeIntervals.csv
basic.io.database: {0} Database file opened: scoring/score_functions/hbonds/ref2015_params/HBEval.csv
basic.io.database: {0} Database file opened: scoring/score_functions/hbonds/ref2015_params/DonStrength.csv
basic.io.database: {0} Database file opened: scoring/score_functions/hbonds/ref2015_params/AccStrength.csv
basic.io.database: {0} Database file opened: scoring/score_functions/rama/fd/all.ramaProb
basic.io.database: {0} Database file opened: scoring/score_functions/rama/fd/prepro.ramaProb
basic.io.database: {0} Database file opened: scoring/score_functions/omega/omega_ppdep.all.txt
basic.io.database: {0} Database file opened: scoring/score_functions/omega/omega_ppdep.gly.txt
basic.io.database: {0} Database file opened: scoring/score_functions/omega/omega_ppdep.pro.txt
basic.io.database: {0} Database file opened: scoring/score_functions/omega/omega_ppdep.valile.txt
basic.io.database: {0} Database file opened: scoring/score_functions/P_AA_pp/P_AA
basic.io.database: {0} Database file opened: scoring/score_functions/P_AA_pp/P_AA_n
core.scoring.P_AA: {0} shapovalov_lib::shap_p_aa_pp_smooth_level of 1( aka low_smooth ) got activated.
basic.io.database: {0} Database file opened: scoring/score_functions/P_AA_pp/shapovalov/10deg/kappa131/a20.prop
protocols.simple_moves.SwitchChainOrderMover: {0} Number of chains in pose: 2
protocols.simple_moves.SwitchChainOrderMover: {0} Now at chain: 2
protocols.simple_moves.SwitchChainOrderMover: {0} Now at chain: 1
core.conformation.Conformation: {0} Found disulfide between residues 22 87
core.conformation.Conformation: {0} current variant for 22 CYD
core.conformation.Conformation: {0} current variant for 87 CYD
core.conformation.Conformation: {0} current variant for 22 CYD
core.conformation.Conformation: {0} current variant for 87 CYD
core.conformation.Conformation: {0} Found disulfide between residues 125 198
core.conformation.Conformation: {0} current variant for 125 CYD
core.conformation.Conformation: {0} current variant for 198 CYD
core.conformation.Conformation: {0} current variant for 125 CYD
core.conformation.Conformation: {0} current variant for 198 CYD
basic.io.database: {0} Database file opened: scoring/score_functions/elec_cp_reps.dat
core.scoring.elec.util: {0} Read 40 countpair representative atoms
core.pack.dunbrack.RotamerLibrary: {0} shapovalov_lib_fixes_enable option is true.
core.pack.dunbrack.RotamerLibrary: {0} shapovalov_lib::shap_dun10_smooth_level of 1( aka lowest_smooth ) got activated.
core.pack.dunbrack.RotamerLibrary: {0} Binary rotamer library selected: /opt/miniconda3/lib/python3.7/site-packages/pyrosetta/database/rotamer/shapovalov/StpDwn_0-0-0/Dunbrack10.lib.bin
core.pack.dunbrack.RotamerLibrary: {0} Using Dunbrack library binary file '/opt/miniconda3/lib/python3.7/site-packages/pyrosetta/database/rotamer/shapovalov/StpDwn_0-0-0/Dunbrack10.lib.bin'.
core.pack.dunbrack.RotamerLibrary: {0} Dunbrack 2010 library took 0.181558 seconds to load from binary
protocols.simple_moves.SwitchChainOrderMover: {0} New pose's foldtree FOLD_TREE EDGE 1 104 -1 EDGE 1 105 1 EDGE 105 223 -1
PDB file name:
Pose Range Chain PDB Range | #Residues #Atoms
0001 -- 0104 A 0001 -- 0104 | 0104 residues; 01588 atoms
0105 -- 0223 B 0105 -- 0223 | 0119 residues; 01845 atoms
TOTAL | 0223 residues; 03433 atoms
注意,这种方法虽然可以进行链交换,但是其中的PDB_info被强制更新为A链和B链了,如果需要保留原有的PDB信息系统,就不应该用这种快捷修改的方式!
Pose中的链是可以被整条删除的。(反之也可以添加)
# 链删除
from pyrosetta.rosetta.protocols.simple_moves import DeleteChainMover
delete_chain = DeleteChainMover()
delete_chain.chain_num(1)
delete_chain.apply(pose)
print(pose.pdb_info())
protocols.simple_moves.DeleteChainMover: {0} Removing chain 1 from pose with 2 chains PDB file name: ./data/4R80.clean.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0076 B 0001 -- 0076 | 0076 residues; 01251 atoms TOTAL | 0076 residues; 01251 atoms
可见A链已经在Pose中消失,而B链还存在。
尽管pose的氨基酸编号是忽略多肽链的分隔的,pose中的链依然是根据多肽链的物理结构进行编号的,同理也是从1开始编号。 如一个蛋白中有2条链A和B,那么链编号结果即为1和2。其中A对应1号链,B对应2号链,与PDB的链顺序有关(当然A链的顺序如果在后面,那么B链就是1号链)。 Pose类中许多的方法可以很方便对链的增减进行操作, 以下2个举例进行说明:
# 将Pose按照链的数量进行切割
pose = pose_from_pdb('./data/6LZ9_H_L.pdb')
pose_list = pose.split_by_chain()
pose_list
core.import_pose.import_pose: {0} File './data/6LZ9_H_L.pdb' automatically determined to be of type PDB core.conformation.Conformation: {0} Found disulfide between residues 21 94 core.conformation.Conformation: {0} current variant for 21 CYS core.conformation.Conformation: {0} current variant for 94 CYS core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} Found disulfide between residues 141 206 core.conformation.Conformation: {0} current variant for 141 CYS core.conformation.Conformation: {0} current variant for 206 CYS core.conformation.Conformation: {0} current variant for 141 CYD core.conformation.Conformation: {0} current variant for 206 CYD core.conformation.Conformation: {0} Found disulfide between residues 21 94 core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} Found disulfide between residues 22 87 core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD
vector1_std_shared_ptr_core_pose_Pose_t[0x7ff14f8106a8, 0x7ff14e6a6a18]
此处的pose_list中存放了2个数据,说明链已经被切割成2个独立的pose对象了。
通过python的索引,可以获得具体的pose:
# 获取只含有第一个链的pose
chain1_pose = pose.split_by_chain()[1] # 直接切片索引链号。
chain2_pose = pose.split_by_chain()[2] # 直接切片索引链号。
# check
print(chain1_pose.pdb_info())
print(chain2_pose.pdb_info())
core.conformation.Conformation: {0} Found disulfide between residues 21 94 core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} Found disulfide between residues 22 87 core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD core.conformation.Conformation: {0} Found disulfide between residues 21 94 core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} Found disulfide between residues 22 87 core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD PDB file name: ./data/6LZ9_H_L.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0081 H 0002 -- 0082 | 0081 residues; 01283 atoms 0082 -- 0082 H 0082A -- 0082A | 0001 residues; 00011 atoms 0083 -- 0083 H 0082B -- 0082B | 0001 residues; 00011 atoms 0084 -- 0084 H 0082C -- 0082C | 0001 residues; 00019 atoms 0085 -- 0102 H 0083 -- 0100 | 0018 residues; 00271 atoms 0103 -- 0103 H 0100A -- 0100A | 0001 residues; 00010 atoms 0104 -- 0104 H 0100B -- 0100B | 0001 residues; 00021 atoms 0105 -- 0105 H 0100C -- 0100C | 0001 residues; 00021 atoms 0106 -- 0106 H 0100D -- 0100D | 0001 residues; 00010 atoms 0107 -- 0107 H 0100E -- 0100E | 0001 residues; 00017 atoms 0108 -- 0119 H 0101 -- 0112 | 0012 residues; 00171 atoms TOTAL | 0119 residues; 01845 atoms PDB file name: ./data/6LZ9_H_L.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0104 L 0002 -- 0105 | 0104 residues; 01588 atoms TOTAL | 0104 residues; 01588 atoms
除了索引操作,用户还可以通过一些简单的方式把链合并到一个pose中,此处使用append_pose_to_pose函数就可以达到目的。但需要注意,pose中的氨基酸、链的数量变化后,都需要对PDBinfo进行更新。否则PDBinfo的信息与Pose信息不对称。
添加新的链
# 将chain2加载到chain1 pose的最后一个氨基酸的后面。
chain1_pose_last_residue = chain1_pose.total_residue()
chain1_pose.append_pose_by_jump(chain2_pose, jump_anchor_residue=chain1_pose_last_residue)
chain1_pose.update_residue_neighbors()
chain1_pose.update_pose_chains_from_pdb_chains()
chain1_pose.conformation().detect_disulfides()
core.conformation.Conformation: {0} Found disulfide between residues 21 94 core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} Found disulfide between residues 141 206 core.conformation.Conformation: {0} current variant for 141 CYD core.conformation.Conformation: {0} current variant for 206 CYD core.conformation.Conformation: {0} current variant for 141 CYD core.conformation.Conformation: {0} current variant for 206 CYD
print(chain1_pose.pdb_info())
# 检查Pose的PDB_info是否是奇怪的:
print(f'PDBinfo是否需要被更新:{chain1_pose.pdb_info().obsolete()}')
PDB file name: ./data/6LZ9_H_L.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0081 H 0002 -- 0082 | 0081 residues; 01283 atoms 0082 -- 0082 H 0082A -- 0082A | 0001 residues; 00011 atoms 0083 -- 0083 H 0082B -- 0082B | 0001 residues; 00011 atoms 0084 -- 0084 H 0082C -- 0082C | 0001 residues; 00019 atoms 0085 -- 0102 H 0083 -- 0100 | 0018 residues; 00271 atoms 0103 -- 0103 H 0100A -- 0100A | 0001 residues; 00010 atoms 0104 -- 0104 H 0100B -- 0100B | 0001 residues; 00021 atoms 0105 -- 0105 H 0100C -- 0100C | 0001 residues; 00021 atoms 0106 -- 0106 H 0100D -- 0100D | 0001 residues; 00010 atoms 0107 -- 0107 H 0100E -- 0100E | 0001 residues; 00017 atoms 0108 -- 0119 H 0101 -- 0112 | 0012 residues; 00171 atoms 0120 -- 0223 L 0002 -- 0105 | 0104 residues; 01588 atoms TOTAL | 0223 residues; 03433 atoms PDBinfo是否需要被更新:True
# update pdbinfo; 别忘了更新pdbinfo;
from pyrosetta.rosetta.core.pose import renumber_pdbinfo_based_on_conf_chains
renumber_pdbinfo_based_on_conf_chains(chain1_pose)
print(f'PDBinfo是否需要被更新:{chain1_pose.pdb_info().obsolete()}')
PDBinfo是否需要被更新:False
# 如果你非常确定,新的pose中不会有PDB的编号冲突等问题。可以直接修改obsolete的检查结果:
chain1_pose.pdb_info().obsolete(False)
合并为一条多肽链的case
# 链的延伸; 合并成一条链的意思;
from pyrosetta.rosetta.core.pose import append_pose_to_pose
pose = pose_from_pdb('./data/6LZ9_H_L.pdb')
chain1_pose = pose.split_by_chain()[1]
chain2_pose = pose.split_by_chain()[2]
new_chain = False
combine_pose = Pose()
combine_pose.assign(chain1_pose)
append_pose_to_pose(combine_pose, chain2_pose, new_chain)
# update pdbinfo; 别忘了更新pdbinfo;
renumber_pdbinfo_based_on_conf_chains(combine_pose)
print(f'append之后的chain1_pose中的氨基酸总数:{combine_pose.total_residue()}')
combine_pose.sequence()
print(f'append之后chain的总数:{combine_pose.num_chains()}')
print(combine_pose.pdb_info())
core.import_pose.import_pose: {0} File './data/6LZ9_H_L.pdb' automatically determined to be of type PDB core.conformation.Conformation: {0} Found disulfide between residues 21 94 core.conformation.Conformation: {0} current variant for 21 CYS core.conformation.Conformation: {0} current variant for 94 CYS core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} Found disulfide between residues 141 206 core.conformation.Conformation: {0} current variant for 141 CYS core.conformation.Conformation: {0} current variant for 206 CYS core.conformation.Conformation: {0} current variant for 141 CYD core.conformation.Conformation: {0} current variant for 206 CYD core.conformation.Conformation: {0} Found disulfide between residues 21 94 core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} Found disulfide between residues 22 87 core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD core.conformation.Conformation: {0} Found disulfide between residues 21 94 core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} current variant for 21 CYD core.conformation.Conformation: {0} current variant for 94 CYD core.conformation.Conformation: {0} Found disulfide between residues 22 87 core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD core.conformation.Conformation: {0} current variant for 22 CYD core.conformation.Conformation: {0} current variant for 87 CYD append之后的chain1_pose中的氨基酸总数:223 append之后chain的总数:1 PDB file name: ./data/6LZ9_H_L.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0223 H 0002 -- 0224 | 0223 residues; 03433 atoms TOTAL | 0223 residues; 03433 atoms
pose = pose_from_pdb('./data/4R80.clean.pdb')
print('删除前的PDB_info:')
print(pose.pdb_info())
from pyrosetta.rosetta.protocols.grafting import delete_region
delete_region_mover = delete_region(pose, 1, 50) # 此处是pose number;
# update pdbinfo; 别忘了更新pdbinfo;
renumber_pdbinfo_based_on_conf_chains(pose)
# 打印查看信息, 一整个区域都被删除【比一个个氨基酸删除快得多】:
print('删除后的PDB_info:')
print(pose.pdb_info())
core.import_pose.import_pose: {0} File './data/4R80.clean.pdb' automatically determined to be of type PDB core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue SER:CtermProteinFull 76 core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue SER:CtermProteinFull 152 删除前的PDB_info: PDB file name: ./data/4R80.clean.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0076 A 0001 -- 0076 | 0076 residues; 01251 atoms 0077 -- 0152 B 0001 -- 0076 | 0076 residues; 01251 atoms TOTAL | 0152 residues; 02502 atoms protocols.grafting.util: {0} Deleting 50 residues from 1 to 50 删除后的PDB_info: PDB file name: ./data/4R80.clean.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0026 A 0051 -- 0076 | 0026 residues; 00412 atoms 0027 -- 0102 B 0001 -- 0076 | 0076 residues; 01251 atoms TOTAL | 0102 residues; 01663 atoms
从pdb_info中可见,A链的1-50号氨基酸消失了。
除了对链的合并之外,我们还可以对链中的氨基酸进行添加、删除的操作!具体的过程是用户需要创建一个独立的氨基酸(residue object),并将这个氨基酸加载到现有的构像中。 加载的方式可以是前置或后置,根据使用的函数不同而定。
# 获取初始信息
from pyrosetta.rosetta.core.conformation import ResidueFactory
from pyrosetta.rosetta.core.chemical import ChemicalManager
# print
pose = pose_from_pdb('./data/4R80.clean.pdb')
print(f'原始氨基酸总数:{pose.total_residue()}')
print(f'原始氨基酸序列:{pose.sequence()}\n')
core.import_pose.import_pose: {0} File './data/4R80.clean.pdb' automatically determined to be of type PDB core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue SER:CtermProteinFull 76 core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue SER:CtermProteinFull 152 原始氨基酸总数:152 原始氨基酸序列:PSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGS
# 通过ResidueFactory创建一个新的Residue(ALA)对象:
chm = ChemicalManager.get_instance()
rts = chm.residue_type_set("fa_standard")
new_rsd = ResidueFactory.create_residue(rts.name_map('ALA')) # 创建一个residue object
# 在第一个氨基酸前添加一个ALA
pose.prepend_polymer_residue_before_seqpos(new_rsd, 1, True)
print(f'Pose的残基数量:{pose.total_residue()}')
print(f'氨基酸序列:{pose.sequence()}\n')
Pose的残基数量:153 氨基酸序列:APSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGS
# 向后添加氨基酸
last_residue = pose.total_residue()
pose.append_polymer_residue_after_seqpos(new_rsd, last_residue, True) # 在最后一个氨基酸后添加一个ALA
print(f'Pose的残基数量:{pose.total_residue()}')
print(f'氨基酸序列:{pose.sequence()}\n')
Pose的残基数量:154 氨基酸序列:APSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSA
# 删除氨基酸
pose.delete_polymer_residue(1) # 删除第一个氨基酸
print(f'删除之后氨基酸总数:{pose.total_residue()}')
print(f'删除之后氨基酸序列:{pose.sequence()}\n')
删除之后氨基酸总数:153 删除之后氨基酸序列:PSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSA
# 还可以范围性的删除氨基酸
pose.delete_residue_range_slow(1,5) # 删除第一个至第五个氨基酸
print(f'删除之后氨基酸总数:{pose.total_residue()}')
print(f'删除之后氨基酸序列:{pose.sequence()}\n')
删除之后氨基酸总数:148 删除之后氨基酸序列:EKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSPSEEEEKRRAKQVAKEKILEQNPSSKVQVRRVQKQGNTIRVELEITENGKKTNITVEVEKQGNTFTVKRITETVGSA
对拓扑结构操作完后,千万记得PBDinfo更新!!
# 更新pdb_info; [别忘了!]
from pyrosetta.rosetta.core.pose import renumber_pdbinfo_based_on_conf_chains
renumber_pdbinfo_based_on_conf_chains(pose) # 更新PDBinfo.
# 检查PDBinfo是否正确: Returns true if PDBInfo is obsolete and needs updating
print(f'PDBinfo是否需要被更新:{pose.pdb_info().obsolete()}')
print(pose.pdb_info())
PDBinfo是否需要被更新:False PDB file name: ./data/4R80.clean.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0071 A 0006 -- 0076 | 0071 residues; 01177 atoms 0072 -- 0148 B 0001 -- 0077 | 0077 residues; 01260 atoms TOTAL | 0148 residues; 02437 atoms
在之前的章节里面我们提过,Pose中的每个氨基酸都是独立的构象,我们可以使用这个机制将Pose中一些连续的片段进行提取。
# 读取pose
pose = pose_from_pdb('./data/4R80.clean.pdb')
print(pose.pdb_info())
core.import_pose.import_pose: {0} File './data/4R80.clean.pdb' automatically determined to be of type PDB core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue SER:CtermProteinFull 76 core.conformation.Conformation: {0} [ WARNING ] missing heavyatom: OXT on residue SER:CtermProteinFull 152 PDB file name: ./data/4R80.clean.pdb Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0076 A 0001 -- 0076 | 0076 residues; 01251 atoms 0077 -- 0152 B 0001 -- 0076 | 0076 residues; 01251 atoms TOTAL | 0152 residues; 02502 atoms
# 新建一个空的Pose
sub_region_pose = Pose()
# 添加第一个氨基酸:
residue = pose.residue(1)
sub_region_pose.append_residue_by_jump(new_rsd=residue, jump_anchor_residue=1)
print(sub_region_pose.sequence())
P
# 添加第2-5个氨基酸:
for i in range(2, 6):
residue = pose.residue(i) # 索引原pose中的residue
last_residue_pose_id = sub_region_pose.total_residue() # 获取sub_region_pose中的最后一个氨基酸;
sub_region_pose.append_polymer_residue_after_seqpos(new_rsd=residue, seqpos=last_residue_pose_id, build_ideal_geometry=False) # 将氨基酸添加
print(sub_region_pose.sequence())
sub_region_pose.dump_pdb('./data/sub_region.pdb')
PSEEE
True
# 这种非官方的操作方法,默认没有创建pdb_info!
print(sub_region_pose.pdb_info())
None
# 通过AddPDBInfoMover可以创建对应的pdb_info给到当前的Pose
from pyrosetta.rosetta.protocols.simple_moves import AddPDBInfoMover
pdb_mover = AddPDBInfoMover()
pdb_mover.apply(sub_region_pose)
print(sub_region_pose.pdb_info())
PDB file name: Pose Range Chain PDB Range | #Residues #Atoms 0001 -- 0005 A 0001 -- 0005 | 0005 residues; 00074 atoms TOTAL | 0005 residues; 00074 atoms
除了具体的化学键数据的调整,在PyRosetta中进行氨基酸的类型调整也是很方便的
# 调整氨基酸的类型
from pyrosetta.toolbox import mutate_residue
print(f'原始氨基酸类型:{pose.residue(1).name()}')
原始氨基酸类型:PRO:NtermProteinFull
print('突变氨基酸中...')
mutate_residue(pose, 1, 'C', 9.0) # 1 代表氨基酸突变的pose编号,9.0代表对氨基酸附近9埃范围内的氨基酸进行侧链优化,适应新的突变。
突变氨基酸中...
core.scoring.ScoreFunctionFactory: {0} SCOREFUNCTION: ref2015
core.pack.task: {0} Packer task: initialize from command line()
core.pack.pack_rotamers: {0} built 161 rotamers at 8 positions.
core.pack.pack_rotamers: {0} Requesting all available threads for interaction graph computation.
core.pack.interaction_graph.interaction_graph_factory: {0} Instantiating PDInteractionGraph
basic.thread_manager.RosettaThreadManager: {?} Creating a thread pool of 1 threads.
basic.thread_manager.RosettaThreadPool: {?} Launched 0 new threads.
core.pack.rotamer_set.RotamerSets: {0} Completed interaction graph pre-calculation in 1 available threads (1 had been requested).
print(f'突变后氨基酸类型:{pose.residue(1).name()}')
突变后氨基酸类型:CYS:NtermProteinFull
Pose中含有让用户自定义写入任何信息的功能,比如在程序设计过程中,中间生成的临时数值或字符都可以写入到PoseExtraScore中,这些信息会随着Pose一并输出到PDB或则Silent文件中,在后续的分析和处理的过程中非常方便。
# 给pose加入额外的信息: 比如filter计算的值就可以储存.
from pyrosetta.rosetta.core.pose import setPoseExtraScore, getPoseExtraScore
setPoseExtraScore(pose, "distance", 1.0)
setPoseExtraScore(pose, "angle", 120.5)
# 提取信息
print(getPoseExtraScore(pose, 'distance'))
print(getPoseExtraScore(pose, 'angle'))
1.0 120.5