[英]Calculating the distance between atomic coordinates
我有一個文本文件,如下所示
ATOM 920 CA GLN A 203 39.292 -13.354 17.416 1.00 55.76 C
ATOM 929 CA HIS A 204 38.546 -15.963 14.792 1.00 29.53 C
ATOM 939 CA ASN A 205 39.443 -17.018 11.206 1.00 54.49 C
ATOM 947 CA GLU A 206 41.454 -13.901 10.155 1.00 26.32 C
ATOM 956 CA VAL A 207 43.664 -14.041 13.279 1.00 40.65 C
.
.
.
ATOM 963 CA GLU A 208 45.403 -17.443 13.188 1.00 40.25 C
我想計算兩個α碳原子之間的距離,即計算第一和第二原子之間的距離,然后計算第二和第三原子之間的距離等等......兩個原子之間的距離可以表示為: distance = sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2) .
列7,8和9分別代表x,y和z坐標。我需要打印距離和相應的殘差對(第4列),如下所示。(距離值不是真實的)
GLN-HIS 4.5
HIS-ASN 3.2
ASN-GLU 2.5
如何用perl或python進行計算?
如果您的數據由空格分隔,則可以執行簡單的split
。 緩沖線以順序地將它們相互比較。
use strict;
use warnings;
my @line;
while (<>) {
push @line, $_; # add line to buffer
next if @line < 2; # skip unless buffer is full
print proc(@line), "\n"; # process and print
shift @line; # remove used line
}
sub proc {
my @a = split ' ', shift; # line 1
my @b = split ' ', shift; # line 2
my $x = ($a[6]-$b[6]); # calculate the diffs
my $y = ($a[7]-$b[7]);
my $z = ($a[8]-$b[8]);
my $dist = sprintf "%.1f", # format the number
sqrt($x**2+$y**2+$z**2); # do the calculation
return "$a[3]-$b[3]\t$dist"; # return the string for printing
}
輸出(帶樣本數據):
GLN-HIS 3.8
HIS-ASN 3.8
ASN-GLU 3.9
GLU-VAL 3.8
如果您的數據以制表符分隔,則可以拆分/\\t/
而不是' '
。
這里給出的其他答案是一個有缺陷的假設 - 坐標將以空格分隔。 根據ATOM
的PDB規范 ,這不是必需的情況:PDB記錄值由列索引指定,並且可以相互流動。 例如,您的第一個ATOM
記錄為:
ATOM 920 CA GLN A 203 39.292 -13.354 17.416 1.00 55.76 C
但這也完全有效:
ATOM 920 CA GLN A 203 39.292-13.3540 17.416 1.00 55.76 C
由於列指定的索引以及PDB文件中可能出現的其他問題的數量,您不應編寫自己的解析器。 PDB格式很亂,並且有很多特殊情況和格式錯誤的文件需要處理。 相反,使用已經為您編寫的解析器。
我喜歡Biopython的PDB.PDBParser
。 它將為您解析Python對象的結構,並提供方便的功能。 如果您更喜歡Perl,請查看BioPerl 。
PDB.Residue
對象允許按名稱鍵入訪問Atoms, PDB.Atom
對象重載-
運算符以返回兩個PDB.Atom
之間的距離。 我們可以用它來編寫簡潔明了的代碼:
from Bio import PDB
parser = PDB.PDBParser()
# Parse the structure into a PDB.Structure object
pdb_code = "1exm"
pdb_path = "pdb1exm.ent"
struct = parser.get_structure(pdb_code, pdb_path)
# Grab the first two residues from the structure
residues = struct.get_residues()
res_one = residues.next()
res_two = residues.next()
try:
alpha_dist = res_one['CA'] - res_two['CA']
except KeyError:
print "Alpha carbon missing, computing distance impossible!"
假設您的數據位於“atoms.txt”中,它會逐行讀取並將條目拆分為一個列表:
import csv
with open("atoms.txt") as f:
reader = csv.reader(f)
for line, in reader:
entries = line.split()
print entries
現在為每個列表提取所需的列,並計算距離等(請記住,python中的列表是從零開始的)。
理想情況下,您應該使用MDAnalysis軟件包進行“切片”原子和段的pythonic方法,並計算它們之間的距離度量。 事實上,MDAnalysis支持多種MD模擬和化學結構格式。
有關更詳細的示例,請參閱Biostars.org上的以下條目 。
如果你對一對感興趣,bash工作得很好。 這是我使用的腳本,我將它設置為最后重新啟動(如果你願意,可以關閉它)。 它會提示你哪個原子。 PDB文件可以設置不同的列,因此對於awk行,請確保列匹配。 在使用新的pdb文件之前,請手動執行測試用例。 這是微不足道的,但是我的pdb文件中的腳本更改為你的。
#!/usr/bin/env bash
echo " "
echo "Use one letter abbreviations. Case doesn't matter."
echo "Example: A 17 CA or n 162 cg"
echo " - - - - - - - - - - - - - - - - - -"
#------------First Selection------------
read -e -p "What first atom? " sel1
# echo $sel1
sel1caps=${sel1^^}
# echo "sel1caps="$sel1caps
arr1=($sel1caps)
# echo "arr1[0]= "${arr1[0]}
# echo "arr1[1]= "${arr1[1]}
# echo "arr1[2]= "${arr1[2]}
#To convert one to three letters
if [ ${arr1[0]} = A ] ; then
SF1=ALA
elif [ ${arr1[0]} = H ] ; then
SF1=HIS
elif [ ${arr1[0]} = R ] ; then
SF1=ARG
elif [ ${arr1[0]} = K ] ; then
SF1=LYS
elif [ ${arr1[0]} = I ] ; then
SF1=ILE
elif [ ${arr1[0]} = F ] ; then
SF1=PHE
elif [ ${arr1[0]} = L ] ; then
SF1=LEU
elif [ ${arr1[0]} = W ] ; then
SF1=TRP
elif [ ${arr1[0]} = M ] ; then
SF1=MET
elif [ ${arr1[0]} = P ] ; then
SF1=PRO
elif [ ${arr1[0]} = C ] ; then
SF1=CYS
elif [ ${arr1[0]} = N ] ; then
SF1=ASN
elif [ ${arr1[0]} = V ] ; then
SF1=VAL
elif [ ${arr1[0]} = G ] ; then
SF1=GLY
elif [ ${arr1[0]} = S ] ; then
SF1=SER
elif [ ${arr1[0]} = Q ] ; then
SF1=GLN
elif [ ${arr1[0]} = Y ] ; then
SF1=TYR
elif [ ${arr1[0]} = D ] ; then
SF1=ASP
elif [ ${arr1[0]} = E ] ; then
SF1=GLU
elif [ ${arr1[0]} = T ] ; then
SF1=THR
else
echo "use one letter codes"
echo "exiting"
exit
fi
# echo "SF1 ="$SF1
#If there is nothing printing for line 1, check the expression for your pdb file. The spaces may need adjustment at the end.
line1=$(grep -E "${arr1[2]} *?${SF1}(.*?) ${arr1[1]} " 1A23.pdb)
# echo $line1
ar_l1=($line1)
# echo "ar_l1[1]="${ar_l1[1]}
echo " - - - - - - - - - - - - - - - - - -"
#------------Second Selection------------
read -e -p "What second atom? " sel2
# echo $sel2
sel2caps=${sel2^^}
# echo "sel2caps="$sel2caps
arr2=($sel2caps)
# echo "arr2[0]= "${arr2[0]}
# echo "arr2[1]= "${arr2[1]}
# echo "arr2[2]= "${arr2[2]}
#To convert one to three letters
if [ ${arr2[0]} = A ] ; then
SF2=ALA
elif [ ${arr2[0]} = H ] ; then
SF2=HIS
elif [ ${arr2[0]} = R ] ; then
SF2=ARG
elif [ ${arr2[0]} = K ] ; then
SF2=LYS
elif [ ${arr2[0]} = I ] ; then
SF2=ILE
elif [ ${arr2[0]} = F ] ; then
SF2=PHE
elif [ ${arr2[0]} = L ] ; then
SF2=LEU
elif [ ${arr2[0]} = W ] ; then
SF2=TRP
elif [ ${arr2[0]} = M ] ; then
SF2=MET
elif [ ${arr2[0]} = P ] ; then
SF2=PRO
elif [ ${arr2[0]} = C ] ; then
SF2=CYS
elif [ ${arr2[0]} = N ] ; then
SF2=ASN
elif [ ${arr2[0]} = V ] ; then
SF2=VAL
elif [ ${arr2[0]} = G ] ; then
SF2=GLY
elif [ ${arr2[0]} = S ] ; then
SF2=SER
elif [ ${arr2[0]} = Q ] ; then
SF2=GLN
elif [ ${arr2[0]} = Y ] ; then
SF2=TYR
elif [ ${arr2[0]} = D ] ; then
SF2=ASP
elif [ ${arr2[0]} = E ] ; then
SF2=GLU
elif [ ${arr2[0]} = T ] ; then
SF2=THR
else
echo "use one letter codes"
echo "exiting"
exit
fi
# echo "SF2 ="$SF2
line2=$(grep -E "${arr2[2]} *?${SF2}(.*?) ${arr2[1]} " 1A23.pdb)
# echo $line2
ar_l2=($line2)
# echo "ar_l2[1]="${ar_l2[1]}
# echo "ar_l2[1]="${ar_l2[1]}
atom1=${ar_l1[1]}
atom2=${ar_l2[1]}
echo "==========================="
echo ${arr1[0]}${arr1[1]}${arr1[2]}" to "${arr2[0]}${arr2[1]}${arr2[2]}":"
# 6, 7, 8 are column numbers in the pdb file.
# If there are multiple molecules it should be 7, 8, 9.
awk '$2=='$atom1'{x1=$7;y1=$8;z1=$9} # get the ATOM 1
$2=='$atom2'{x2=$7;y2=$8;z2=$9} # get the ATOM 2
END{print sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2))}' 1A23.pdb # calculate the distance.
echo "Angstroms"
echo "==========================="
echo " "
echo "-_-_-_-_Running Script Again_-_-_-_-"
./distance_soln.sh
一個簡單的Python代碼可以完成這項工作。 我假設你的所有內容都在文件“input.txt”中。
def process(line1, line2):
content1 = line1.split()
content2 = line2.split()
x1, y1, z1 = float(content1[6]), float(content1[7]), float(content1[8])
x2, y2, z2 = float(content2[6]), float(content2[7]), float(content2[8])
distance = math.sqrt(math.pow(x1-x2, 2) + math.pow(y1-y2, 2) + math.pow(z1-z2, 2))
return content1[3]+"-"+content2[3]+" "+ "{0:.2f}".format(distance)
with open("input.txt") as f:
line1 = f.readline()
for line in f:
line2 = line
print(process(line1, line2))
line1 = line2
如果您在使用此腳本時發現任何差異或問題,請告訴我們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.