You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Python自动化实现含不同蛋白质的大量mmCIF文件的结构叠加、RMSD计算与筛选

如何用Python自动化实现含不同蛋白质的大量mmCIF文件的结构叠加、RMSD计算与筛选

嗨,看起来你现在卡在两个关键问题上:一个是代码参数传递的低级错误,另一个是不同蛋白质结构原子不匹配的核心难题。我来一步步帮你搞定:

首先,先修复当前的TypeError错误

你现在的报错完全是参数传错了

  • 你调用calculate_rmsd(mmcif_list, mmcif_ref, mmcif_comp)时,第一个参数传的是文件名列表mmcif_list,但函数定义里第一个参数需要的是文件夹路径mmcif_dir(字符串类型)
  • 而且mmcif_comp是多个文件的列表,但你的函数里把它当成单个文件来解析,这肯定会炸锅

先把这个基础问题解决,我们先把函数改成能处理单个待比较文件,再用循环遍历所有待比较文件:

import os
from Bio.PDB import MMCIFParser, Selection, Superimposer
from Bio import AlignIO
from Bio.PDB.Polypeptide import PPBuilder

# 初始化路径
cur_dir = os.getcwd()
protein_name = "你的蛋白家族名称"  # 记得替换成实际名称
mmcif_dir = os.path.join(cur_dir, protein_name, "input", "cif_files")
output_dir = os.path.join(cur_dir, protein_name, "prep")
os.makedirs(output_dir, exist_ok=True)  # 确保输出文件夹存在

# 获取所有cif文件列表
mmcif_list = [f for f in os.listdir(mmcif_dir) if f.endswith('.cif')]
mmcif_ref = mmcif_list[0]
mmcif_comp_list = mmcif_list[1:]  # 待比较的文件列表

print(f"参考文件: {mmcif_ref}")
print(f"待比较文件数量: {len(mmcif_comp_list)}")

核心问题:不同蛋白质的原子匹配问题

你提到的“不同原子无法计算RMSD”是关键——BIO.PDB的Superimposer要求两个结构的原子列表完全一一对应(数量相同,顺序对应同源残基)。所以我们需要先做序列比对,找到两个结构的同源残基,再提取对应的骨架原子(N/CA/C)来计算。

下面是整合了序列比对+RMSD计算的完整函数,以及筛选逻辑:

def get_structure_sequence(structure):
    """从结构对象中提取氨基酸序列"""
    ppb = PPBuilder()
    sequences = []
    for pp in ppb.build_peptides(structure):
        sequences.append(str(pp.get_sequence()))
    # 假设我们取第一个链的序列(如果有多个链,你可能需要调整逻辑)
    return sequences[0]

def calculate_rmsd_between_structures(ref_structure, comp_structure):
    """计算两个结构之间的RMSD(先做序列比对匹配残基)"""
    # 提取两个结构的序列
    ref_seq = get_structure_sequence(ref_structure)
    comp_seq = get_structure_sequence(comp_structure)
    
    # 做全局序列比对(用Bio.Align的PairwiseAligner)
    from Bio.Align import PairwiseAligner
    aligner = PairwiseAligner()
    aligner.mode = 'global'
    aligner.match_score = 2
    aligner.mismatch_score = -1
    aligner.open_gap_score = -2
    aligner.extend_gap_score = -1
    
    # 得到最优比对结果
    alignments = aligner.align(ref_seq, comp_seq)
    best_alignment = alignments[0]
    ref_aln, comp_aln = best_alignment
    
    # 匹配同源残基:找到比对中没有gap的位置
    ref_residues = []
    comp_residues = []
    ref_idx = 0
    comp_idx = 0
    
    for r, c in zip(ref_aln, comp_aln):
        if r != '-' and c != '-':
            # 获取对应的残基对象(这里假设取第一个模型的A链,根据实际情况改)
            ref_chain = ref_structure[0]['A']
            comp_chain = comp_structure[0]['A']
            
            # 注意:残基的ID格式通常是(空格, 残基号, 空格),需正确索引
            ref_res = ref_chain[(' ', ref_idx+1, ' ')]
            comp_res = comp_chain[(' ', comp_idx+1, ' ')]
            
            ref_residues.append(ref_res)
            comp_residues.append(comp_res)
        
        if r != '-':
            ref_idx += 1
        if c != '-':
            comp_idx += 1
    
    # 提取对应残基的骨架原子(N/CA/C)
    ref_atoms = []
    comp_atoms = []
    for ref_res, comp_res in zip(ref_residues, comp_residues):
        for atom_name in ['N', 'CA', 'C']:
            if atom_name in ref_res and atom_name in comp_res:
                ref_atoms.append(ref_res[atom_name])
                comp_atoms.append(comp_res[atom_name])
    
    # 做结构叠加并计算RMSD
    super_imposer = Superimposer()
    super_imposer.set_atoms(ref_atoms, comp_atoms)
    super_imposer.apply(comp_structure.get_atoms())
    
    return super_imposer.rms

# 先解析参考结构
parser = MMCIFParser(QUIET=True)  # QUIET=True关闭解析时的冗余警告
ref_structure = parser.get_structure("reference", os.path.join(mmcif_dir, mmcif_ref))

# 设置RMSD阈值,比如只保留RMSD小于2.0的结构
rmsd_threshold = 2.0

# 遍历所有待比较文件,计算RMSD并筛选
for comp_file in mmcif_comp_list:
    try:
        comp_structure = parser.get_structure("comparison", os.path.join(mmcif_dir, comp_file))
        rmsd = calculate_rmsd_between_structures(ref_structure, comp_structure)
        print(f"文件 {comp_file} 与参考结构的RMSD: {rmsd:.2f} Å")
        
        # 如果符合阈值,保存到输出文件夹
        if rmsd <= rmsd_threshold:
            import shutil
            shutil.copy(os.path.join(mmcif_dir, comp_file), os.path.join(output_dir, comp_file))
            print(f"已保存符合条件的文件: {comp_file}")
    except Exception as e:
        print(f"处理文件 {comp_file} 时出错: {str(e)}")

一些需要注意的细节

  1. 链ID和模型的选择:上面的代码假设所有结构都是单模型、单链(链ID为'A'),如果你的文件有多模型或多链,需要调整ref_structure[0]['A']这部分的逻辑,比如遍历所有链或者指定目标链。
  2. 残基编号的处理:有些mmCIF文件的残基ID可能包含插入码(比如( ' ', 100, 'A' )),如果遇到这种情况,你需要在提取残基时做更灵活的匹配。
  3. 序列比对的参数:你可以根据你的蛋白家族调整PairwiseAligner的得分参数,比如gap罚分、匹配得分等,让比对结果更准确。
  4. 异常处理:加入了try-except块,避免某个文件解析失败导致整个程序崩溃。

备注:内容来源于stack exchange,提问作者y.a

火山引擎 最新活动