ミームの死骸を待ちながら

We are built as gene machines and cultured as meme machines, but we have the power to turn against our creators. We, alone on earth, can rebel against the tyranny of the selfish replicators. - Richard Dawkins "Selfish Gene"

We are built as gene machines and cultured as meme machines, but we have the power to turn against our creators.
We, alone on earth, can rebel against the tyranny of the selfish replicators.
- Richard Dawkins "Selfish Gene"

PDBファイルに変異を入れるプログラム(Ruby)。


研究室でちょっとしたプログラムを使う必要が出た。ので作った。

PDBファイルの特定の残基名を書き換えた後、AMBERパッケージを使って適切な構造に直して、分子動力学計算(MD計算)を行う。このPDBファイルの書き換えを自動でやってくれるプログラム(PDBも所詮はテキストファイルなので)。

BioRubyを使ってもいいんだが(というかその方が楽)、こんな時でもないとプログラム書かないから練習がてらに。まぁ何より、久しぶりにRubyってみたかった。...というわけで台風の土曜、家にこもって書き上げた変異体作成プログラム(不健康なので明日は出かけよう)。
100行足らずの短いプログラムだが、結構満足。次は変異入れたペプチドを組み合わせてダイマー化し、((20×20-20)/2)通りのヘテロ体を作る必要があるので、それも作ろうかな。

使い方。

引数として順に「変異を入れたいPDB」「残基番号」「変えたいアミノ酸」を指定する。

> pdbmutator.rb pdbfile target_residue_number mutation

mutationは大文字三字のアミノ酸略称を想定。
たとえば2zta.pdbというファイルの30残基目をグリシンにしたい場合は、

> pdbmutator.rb 2zta.pdb 30 GLY

一応変異と言っても非侵襲的で、元のPDBを残しながら新たなPDBファイルを作る。
変異体ファイルは、上の例で言うと2zta.pdb_30toGという表記になる。
自分の研究(数十残基のペプチドしか扱わない)用に作ったので、広く使うといろいろ問題も出そうだな。

#! /usr/bin/ruby
#
#   ---usage---
#
# > pdbmutator.rb PDBFILENAME TARGET_RSD MUTATION
#
#  <todo>  
#    - when raw pdb is loaded, strip header and footer...

Names = { 'ALA' => 'A', 'CYS' => 'C', 'ASP' => 'D', 'GLU' => 'E', 
          'PHE' => 'F', 'GLY' => 'G', 'HIS' => 'H', 'ILE' => 'I', 
          'LYS' => 'K', 'LEU' => 'L', 'MET' => 'M', 'ASN' => 'N', 
          'PRO' => 'P', 'GLN' => 'Q', 'ARG' => 'R', 'SER' => 'S', 
          'THR' => 'T', 'VAL' => 'V', 'TRP' => 'W', 'TYR' => 'Y' }

if ARGV[0] == nil || ARGV[1] == nil || ARGV[2] == nil
print("usage:"+"\n"+ 
 "> pdbmutator.rb PDBFILENAME TARGET_RSD MUTATION")
    exit    
end

require 'fileutils.rb'

filename = ARGV[0] 
workfile = filename + "_tmp"
FileUtils.cp(filename, workfile)

target_rsd = ARGV[1].to_i
mutation = ARGV[2] 

open(workfile){|a|

    residno = -1
    prev_residno = -2
    uni = File.open("#{filename}_#{target_rsd}to#{Names[mutation]}", "w")

########################    line loop start    ########################

    while line = a.gets
        column = line.split(/\s+/)

           ### a sample of read "column" ####
           ### ["ATOM", "12", "N", "MET", "A", "2", 
           ### "37.447", "16.947", "15.901", "1.00", "33.89", "N"]

        ### unless line is "TER" or "END"#
        if column[0] == "ATOM" then 
                
            ### Terminal resid names may be joined w/ the atom name.#
            ### In such a case, you need to fix it. #
            if column[2].length > 4 then
                tmpatom = column[2][0..2]
                tmpresidue = column[2][3..column[2].length]

                ### insert the "atom" in column[2] #
                ###  and replace column[3] to the real resid.#
                column[2,0] = tmpatom
                column[3] = tmpresidue
            end
        ### just a output ajustment.#
        ### inform the sequence now processing.#
        residno = column[5].to_i
        if residno != prev_residno
            print "#{residno}: #{column[3]}  "
            if (residno % 5 == 0) || residno == target_rsd
               print "\n"
            end
        end
#######################################################################
######################## when target resid No. ########################
#######################################################################

        if residno == target_rsd
             resid0 = column[3]
             line = line.sub(/#{resid0}/, "#{mutation}")
             puts "ATOM No. #{column[1]}: #{resid0} has been mutated to #{mutation}"
        end
#######################################################################

        end  # unless line is "TER" or "END"
        uni.puts <<-"EOB"
#{line.strip}
        EOB
        prev_residno = residno
    end
########################    line loop end     ########################
}