1

次のようなサンプルデータがあります。

ATOM    973  CG  ARG A  61     -21.593   8.884  69.770  1.00 25.13           C
ATOM    974  CD  ARG A  61     -21.610   7.433  69.314  1.00 23.44           C
ATOM    975  NE  ARG A  61     -21.047   7.452  67.937  1.00 12.13           N

オフセット値を追加して 6 列目と 6 列目のみを置き換えたいのですが、上記の場合は 308 です。

61+308 = 369 なので、6 列目の 61 は 369 に置き換える必要があります。

str.split()行間隔が非常に重要なので、行を作成できません。

使用してみstr.replace()ましたが、2列目の値が6列目と重複することもあります

行を逆にして使用しようとしstr.repalce()ましたが、列 7、8、9、10、および 11 の値が置換対象と重複する可能性がありstrます。

私がこれまでに持っている醜いコードは次のとおりです(列7、8、9、10および/または11で値が重複する場合とは別に部分的に機能します):

with open('2kqx.pdb', 'r') as inf, open('2kqx_renumbered.pdb', 'w') as outf:
    for line in inf:
        if line.startswith('ATOM'):
            segs = line.split()
            if segs[4] == 'A':
                offset = 308
                number = segs[5][::-1]
                replacement = str((int(segs[5])+offset))[::-1]
                print number[::-1],replacement
                line_rev = line[::-1]
                replaced_line = line_rev.replace(number,replacement,1)
                print line
                print replaced_line[::-1]
                outf.write(replaced_line[::-1])

上記のコードは、以下の出力を生成しました。2 行目でわかるように、6 列目は変更されていませんが、7 列目で変更されています。文字列を逆にすることで、2 列目との重複の可能性を回避できると考えましたが、他の列を忘れてしまい、よくわかりません。それを回避する方法。

ATOM    973  CG  ARG A  369     -21.593   8.884  69.770  1.00 25.13           C
ATOM    974  CD  ARG A  61     -21.3690   7.433  69.314  1.00 23.44           C
ATOM    975  NE  ARG A  369     -21.047   7.452  67.937  1.00 12.13           N
4

2 に答える 2

2

data = """\
ATOM    973  CG  ARG A  61     -21.593   8.884  69.770  1.00 25.13           C
ATOM    974  CD  ARG A  61     -21.610   7.433  69.314  1.00 23.44           C
ATOM    975  NE  ARG A  61     -21.047   7.452  67.937  1.00 12.13           N"""

offset = 308
for line in data.split('\n'):
    line = line[:22] + "  {:<5d}  ".format(int(line[22:31]) + offset) + line[31:]
    print line

空白の正確なカウントは行っていません。これは概算です。コードに22と31の数字を分散させるよりも柔軟性が必要な場合は、開始インデックスと終了インデックスを決定する方法が必要になります(ただし、データが固定列形式であるという私の仮定とは対照的です)。

于 2013-02-22T12:29:01.503 に答える
1

PDB自分で -filesを解析しようとしないほうがよいでしょう。

PDB パーサーを使用します。たとえば、さまざまな生物/計算化学パッケージ内で自由に利用できるものが多数あります。

バイオパイソン

入力が であると仮定して、biopython でそれを行う方法は次のraw.pdbとおりです。

from Bio.PDB import PDBParser, PDBIO
parser=PDBParser()
structure = parser.get_structure('some_id', 'raw.pdb')
for r in structure.get_residues():
    r.id = (r.id[0], r.id[1] + 308, r.id[2])
io = PDBIO()
io.set_structure(structure)
io.save('shifted.pdb')

私は少しグーグルで検索し、ここで特定の問題を解決するための簡単な解決策を見つけました(サードパーティの依存関係なし):

http://code.google.com/p/pdb-tools/

--他の多くの便利な pdb-python-script-tools の中に-- このスクリプトpdb_offset.pyがあります。

これはスタンドアロン スクリプトであり、そのメソッドをコピーしpdb_offsetて動作することを示しました。3 行のサンプル コードは次のraw.pdbとおりです。

def pdbOffset(pdb_file, offset):
    """
    Adds an offset to the residue column of a pdb file without touching anything
    else.
    """

    # Read in the pdb file
    f = open(pdb_file,'r')
    pdb = f.readlines()
    f.close()

    out = []
    for line in pdb:
        # For and ATOM record, update residue number
        if line[0:6] == "ATOM  " or line[0:6] == "TER   ":
            num = offset + int(line[22:26])
            out.append("%s%4i%s" % (line[0:22],num,line[26:]))
        else:
            out.append(line) 

    return "".join(out)


print pdbOffset('raw.pdb', 308)

印刷する

ATOM    973  CG  ARG A 369     -21.593   8.884  69.770  1.00 25.13           C
ATOM    974  CD  ARG A 369     -21.610   7.433  69.314  1.00 23.44           C
ATOM    975  NE  ARG A 369     -21.047   7.452  67.937  1.00 12.13           N
于 2013-02-22T13:24:48.607 に答える