2012-07-27 302 views
3

我想从pdb文件中提取链。我有一个名为pdb.txt的文件,其中包含pdb ID,如下所示。前四个字符代表PDB ID,最后一个字符代表链ID。如何从PDB文件中提取链?

1B68A 
1BZ4B 
4FUTA 

我想1)读出由线 2将文件线)从相应的PDB文件下载每个链的原子坐标。
3)将输出保存到一个文件夹。

我用下面的脚本来提取链。但是这个代码只打印来自pdb文件的链。

for i in 1B68 1BZ4 4FUT 
do 
wget -c "http://www.pdb.org/pdb/download/downloadFile.do?fileFormat=pdb&compression=NO&structureId="$i -O $i.pdb 
grep ATOM $i.pdb | grep 'A' > $i\_A.pdb 
done 

回答

10

下面的BioPython代码应该很好地满足您的需求。

它使用PDB.Select只选择所需的链(在你的情况下,一个链)和PDBIO()创建一个只包含链的结构。

import os 
from Bio import PDB 


class ChainSplitter: 
    def __init__(self, out_dir=None): 
     """ Create parsing and writing objects, specify output directory. """ 
     self.parser = PDB.PDBParser() 
     self.writer = PDB.PDBIO() 
     if out_dir is None: 
      out_dir = os.path.join(os.getcwd(), "chain_PDBs") 
     self.out_dir = out_dir 

    def make_pdb(self, pdb_path, chain_letters, overwrite=False, struct=None): 
     """ Create a new PDB file containing only the specified chains. 

     Returns the path to the created file. 

     :param pdb_path: full path to the crystal structure 
     :param chain_letters: iterable of chain characters (case insensitive) 
     :param overwrite: write over the output file if it exists 
     """ 
     chain_letters = [chain.upper() for chain in chain_letters] 

     # Input/output files 
     (pdb_dir, pdb_fn) = os.path.split(pdb_path) 
     pdb_id = pdb_fn[3:7] 
     out_name = "pdb%s_%s.ent" % (pdb_id, "".join(chain_letters)) 
     out_path = os.path.join(self.out_dir, out_name) 
     print "OUT PATH:",out_path 
     plural = "s" if (len(chain_letters) > 1) else "" # for printing 

     # Skip PDB generation if the file already exists 
     if (not overwrite) and (os.path.isfile(out_path)): 
      print("Chain%s %s of '%s' already extracted to '%s'." % 
        (plural, ", ".join(chain_letters), pdb_id, out_name)) 
      return out_path 

     print("Extracting chain%s %s from %s..." % (plural, 
       ", ".join(chain_letters), pdb_fn)) 

     # Get structure, write new file with only given chains 
     if struct is None: 
      struct = self.parser.get_structure(pdb_id, pdb_path) 
     self.writer.set_structure(struct) 
     self.writer.save(out_path, select=SelectChains(chain_letters)) 

     return out_path 


class SelectChains(PDB.Select): 
    """ Only accept the specified chains when saving. """ 
    def __init__(self, chain_letters): 
     self.chain_letters = chain_letters 

    def accept_chain(self, chain): 
     return (chain.get_id() in self.chain_letters) 


if __name__ == "__main__": 
    """ Parses PDB id's desired chains, and creates new PDB structures. """ 
    import sys 
    if not len(sys.argv) == 2: 
     print "Usage: $ python %s 'pdb.txt'" % __file__ 
     sys.exit() 

    pdb_textfn = sys.argv[1] 

    pdbList = PDB.PDBList() 
    splitter = ChainSplitter("/home/steve/chain_pdbs") # Change me. 

    with open(pdb_textfn) as pdb_textfile: 
     for line in pdb_textfile: 
      pdb_id = line[:4].lower() 
      chain = line[4] 
      pdb_fn = pdbList.retrieve_pdb_file(pdb_id) 
      splitter.make_pdb(pdb_fn, chain) 

最后一点:不写自己的解析器为PDB文件。格式规范是丑陋的(真的很难看),并有错误的PDB文件的数量是惊人的。使用像BioPython这样的工具来处理你的分析!

此外,您应该使用与PDB数据库进行交互的工具,而不是使用wget。他们考虑到FTP连接限制,PDB数据库性质的变化等等。我应该知道 - 我updated Bio.PDBList来说明数据库中的变化。 =)

+0

非常感谢您的代码和解释。但我不知道,如何运行你的代码?你可以帮帮我吗? – user1545114 2012-07-27 22:50:18

+0

当然可以。我添加了一个特别适合你的目标的方法。将主体中的行更改为您希望文件转到的目录。 [安装Python](http://www.python.org/getit/)(你可能已经拥有它了,试试'$ which python'),然后安装[BioPython](http://biopython.org/wiki/Download #安装说明)。用'.py'扩展名(例如'extract.py')保存上述文件,然后运行'$ python extract.py pdb.txt'。而已! – 2012-07-28 03:42:04

+0

如果你正在做更多生物信息学相关的事情,我强烈建议你学习Python。它在该领域非常受欢迎([BioPython](http://biopython.org)和[PyMOL](http://pymol.org),是两个很好的例子),它是一个很好的通用语言。 [Python文档](http://docs.python.org)和[Think Python](http://www.greenteapress.com/thinkpython/)都是开始的好地方。 – 2012-07-28 04:57:23

0

比方说你具有以下文件pdb_structures

1B68A 
1BZ4B 
4FUTA 

然后让你的代码load_pdb.sh

while read name 
do 
    chain=${name:4:1} 
    name=${name:0:4} 
    wget -c "http://www.pdb.org/pdb/download/downloadFile.do?fileFormat=pdb&compression=NO&structureId="$name -O $name.pdb 
    awk -v chain=$chain '$0~/^ATOM/ && substr($0,20,1)==chain {print}' $name.pdb > $name\_$chain.pdb 
    # rm $name.pdb 
done 

取消对最后一行,如果你不需要原始PDB的。
执行

cat pdb_structures | ./load_pdb.sh 
+0

这很简单有效,但它忽略了[HETATM](http://deposit.rcsb.org/adit/docs/pdb_atom_format.html#HETATM)记录,它们是链中的一部分。为什么在有大量已经存在的解析器时,为复杂的文件格式编写自己的解析器? – 2012-07-27 11:52:20

+0

此外,使用PDB检索程序比使用wget和手动检索URL更好。自动处理压缩以及其他功能。查看我答案的最后一段。 – 2012-07-27 12:13:54

+0

@zelleke,非常感谢您的回答。我尝试了您的代码。我不需要来自pdb文件的所有链。我在文本文件中提到了链ID。例如,我只需要'1B68'的'A'链。 – user1545114 2012-07-27 12:31:21

0

这可能是对asnwering这个问题有点晚,但我会说出我的意见。 Biopython有一些非常方便的功能,可以帮助您轻松实现这样的想法。你可以使用类似自定义选择类的东西,然后为每个想要在原始pdb文件的for循环中选择的链调用它。

from Bio.PDB import Select, PDBIO 
    from Bio.PDB.PDBParser import PDBParser 

    class ChainSelect(Select): 
     def __init__(self, chain): 
      self.chain = chain 

     def accept_chain(self, chain): 
      if chain.get_id() == self.chain: 
       return 1 
      else:   
       return 0 

    chains = ['A','B','C'] 
    p = PDBParser(PERMISSIVE=1)  
    structure = p.get_structure(pdb_file, pdb_file) 

    for chain in chains: 
     pdb_chain_file = 'pdb_file_chain_{}.pdb'.format(chain)         
     io_w_no_h = PDBIO()    
     io_w_no_h.set_structure(structure) 
     io_w_no_h.save('{}'.format(pdb_chain_file), ChainSelect(chain))