同源建模-build loop

对于有残基缺失的晶体结构往往采用同源建模的方式补全,但常规的同源建模方法往往造成非缺失区域残基的挪动,有时我们并不想出现这种状况,尤其是涉及到多个截短体拼合的情况,这时就需要用到约束性同源建模的方法,只对缺失区域补全而尽可能少地改动非缺失区域。效果图如下所示:

1、准备建模序列文件

复制代码
>P1;Target
sequence:Target:::::::0.00: 0.00
TCFSGDDDSGLNLGFSTSFAEYNEFDGGEKALIGFSTSFAEFDAEAGDSDEQPIFPQHKLTCFS*

前两行格式严格遵守!!!

保存文件名为Target.ali

将模板结构文件存储为temp.pdb文件(单链,除去水和离子)

以下是从pdb文件中提取fasta序列的脚本:

python 复制代码
from Bio import PDB
from Bio.PDB import PDBParser, PDBIO
from Bio.PDB.Polypeptide import PPBuilder
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
import sys

def extract_fasta_from_pdb(pdb_file, type):
    parser = PDBParser(QUIET=True)
    if type == "pdb":
        structure = parser.get_structure('PDB', pdb_file)
    if type == "pdb.gz":
        with gzip.open(pdb_file, 'rb') as f_in:
            with open('temp.pdb', 'wb') as f_out:
                f_out.write(f_in.read())
        structure = parser.get_structure('PDB', 'temp.pdb')
    ppb = PPBuilder()
    fasta_records = []
    for model in structure:
        for chain in model:
            polypeptides = ppb.build_peptides(chain)
            for polypeptide in polypeptides:
                sequence = str(polypeptide.get_sequence())
                record = SeqRecord(Seq(sequence), id=chain.id)
                fasta_records.append(record)
    try:
        os.remove('temp.pdb')
    except:
        pass
    return fasta_records
    
def main():
    file = open("out.fasta", "w")
    sys.stdout = file
    print(">temp")
    pdb_file = "./temp.pdb"
    s = extract_fasta_from_pdb(pdb_file, "pdb")
    for record in s:
        print(record.seq)
    
    file.close()
    
if __name__ == "__main__":
    main()

2、与模板蛋白结构进行序列比对

准备align2d.py脚本文件:

python 复制代码
from modeller import *

env = Environ()
aln = Alignment(env)
# temp是模板结构名称,C指的是C链
mdl = Model(env, file='temp', model_segment=('FIRST:C','LAST:C'))	
aln.append_model(mdl, align_codes='temp', atom_files='temp.pdb')	
aln.append(file='Target.ali', align_codes='Target')
aln.align2d(max_gap_length=50)
aln.write(file='Target-temp.ali', alignment_format='PIR')	
aln.write(file='Target-temp.pap', alignment_format='PAP')	

执行后,当前路径下生成两个文件Target-temp.ali,Target-temp.pap

3、 建模

准备loop_modeling.py脚本文件:

python 复制代码
from modeller import *
from modeller.automodel import *    

log.verbose()
env = Environ()

# directories for input atom files
env.io.atom_files_directory = ['.', 'temp.pdb']

class MyModel(AutoModel):
    def select_atoms(self):
        #新建模蛋白链编码为A,编号从1开始,因此缺失残基编号要相应挪动
        #编号最好包含首尾各一个残基
        return Selection(self.residue_range('5:A', '13:A'))

a = MyModel(env, alnfile = 'Target-temp.ali',
            knowns = 'temp', sequence = 'Target')
a.starting_model= 1
a.ending_model  = 1

a.make()

4、如何方便地确定新建模型中插入loop的编号

准备脚本文件renumber_pro.py:

python 复制代码
import sys
from optparse import OptionParser

def initialize_options() :
    parser = OptionParser();
    parser.add_option( "-p", "--pdb", dest="pdbname", type="string", help="The input pdb that should be renumbered" );
    parser.add_option( "-o", "--output", dest="output", type="string", help="The output file to write the renumbered pdb to; stdout if not given", default="" );
    parser.add_option( "-a", "--chainA_begin", dest="chAbegin", type="int", help="The first residue in chain A", default=1 );
    parser.add_option( "-b", "--chainB_begin", dest="chBbegin", type="int", help="The first residue in chain B", default=1 );
    parser.add_option( "-c", "--chainC_begin", dest="chCbegin", type="int", help="The first residue in chain C", default=1 );
    parser.add_option( "-d", "--chainD_begin", dest="chDbegin", type="int", help="The first residue in chain D", default=1 );
    parser.add_option( "-e", "--chainE_begin", dest="chEbegin", type="int", help="The first residue in chain E", default=1 );
    return parser

def remap_resnum_for_line( line, mapping ):
    if line[0:4] != "ATOM": return line
    chain = line[21];
    if chain not in mapping: return line
    resstring = line[22:27]
    resnum, lastresstring = mapping[ chain ]
    if lastresstring == "" or resstring != lastresstring :
        if lastresstring != "" : resnum += 1
        mapping[ chain ] = (resnum, resstring )
    newresstring = str(resnum) + " "
    if len(newresstring) == 2: newresstring = "   " + newresstring
    elif len(newresstring) == 3: newresstring = "  " + newresstring
    elif len(newresstring) == 4: newresstring = " " + newresstring
    return line[0:22] + newresstring + line[27:]

if __name__ == "__main__":

    parser = initialize_options()
    (options, args) = parser.parse_args()

    pdblines = open( options.pdbname ).readlines()
    mapping = {}
    mapping["A"] = (options.chAbegin, "");
    mapping["B"] = (options.chBbegin, "");
    mapping["C"] = (options.chCbegin, "");
    mapping["D"] = (options.chDbegin, "");
    mapping["E"] = (options.chEbegin, "");
    newlines = []
    for line in pdblines:
        newlines.append( remap_resnum_for_line( line, mapping ))
    if options.output == "" :
        for line in newlines :
            print(line, end=' ')
    else :
        open( options.output, "w").writelines(newlines)

执行:

bash 复制代码
python renumber_pro.py -p temp.pdb -o output.pdb

用pymol打开原模板文件发现原序列在357-365之间的残基缺失

对应到重编号的文件中是5-13

因此对应上述脚本文件loop_modeling.py中对下方内容进行调整:

复制代码
return Selection(self.residue_range('5:A', '13:A'))
相关推荐
允许部分打工人先富起来20 分钟前
在node项目中执行python脚本
前端·python·node.js
IVEN_24 分钟前
Python OpenCV: RGB三色识别的最佳工程实践
python·opencv
haosend1 小时前
AI时代,传统网络运维人员的转型指南
python·数据网络·网络自动化
曲幽1 小时前
不止于JWT:用FastAPI的Depends实现细粒度权限控制
python·fastapi·web·jwt·rbac·permission·depends·abac
IVEN_19 小时前
只会Python皮毛?深入理解这几点,轻松进阶全栈开发
python·全栈
Ray Liang20 小时前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
AI攻城狮21 小时前
如何给 AI Agent 做"断舍离":OpenClaw Session 自动清理实践
python
千寻girling21 小时前
一份不可多得的 《 Python 》语言教程
人工智能·后端·python
AI攻城狮1 天前
用 Playwright 实现博客一键发布到稀土掘金
python·自动化运维