python格式化读取解析PDB文件 字符串指定宽度格式化分割
描述:
pdb蛋白质文件是一类高度格式化的文本文件,每行中每一个字段都有着固定宽度和位置,无法使用常见的split()
函数来分割字段。
在处理蛋白质模型pdb文件时,可能会遇到字符串中 随机两列数据连着(如下图中的365315行以后的原子坐标值Y列和Z列连在一起),使用split()
函数无法处理,所以想以文件本身的格式来格式化读取。
我的方法:
# 将每行的字符串转换成多个单字符的数组,按照给定的格式数组(可自行定义)重组字符,形成最终的对应PDB格式的数组
def formatStr2List(string,formatList):
# 第一步 先把字符串转成数组,一个字符对应一个数组元素
atom=[]
for s in string:
atom.append(s)
# 第二步 把字符串数组按formatList格式宽度,组建成新的数组
i=1
fal=[]
for li in formatList:
mid=[]
for l in range(li):
mid.append(atom[i-1])
i+=1
iter="".join(mid)
fal.append(iter)
return fal
string="ATOM 125 C TYR 19 244.604 249.2491515.330 1.00110.97 C"
# 按照PDB文件的格式 写一个格式数组,数组里的元素代表 所分割字符的宽度
formatList=[4,2,5,1,4,1,3,1,1,4,1,3,8,8,8,6,6,6,4,2]
print(formatStr2List(string,formatList))
输出效果:
['ATOM', ' ', ' 125', ' ', ' C ', ' ', 'TYR', ' ', ' ', ' 19', ' ', ' ', ' 244.604', ' 249.249', '1515.330', ' 1.00', '110.97', ' ', ' ', ' C']
方法二:
通常每个字段的位置是固定的,因此可以通过截取字符串的方式来提取数据,而不是依赖于split
函数。
在PDB文件中,每一行的结构是有规律的,比如ATOM记录的行的结构如下:
ATOM 1 N ASN A 1 11.962 53.349 44.812 1.00 20.46 N
示例代码块:
def parse_pdb_line(line):
record_name = line[0:6].strip()
atom_number = int(line[6:11].strip())
atom_name = line[12:16].strip()
residue_name = line[17:20].strip()
chain_id = line[21]
residue_number = int(line[22:26].strip())
x = float(line[30:38].strip())
y = float(line[38:46].strip())
z = float(line[46:54].strip())
return {
"record_name": record_name,
"atom_number": atom_number,
"atom_name": atom_name,
"residue_name": residue_name,
"chain_id": chain_id,
"residue_number": residue_number,
"x": x,
"y": y,
"z": z
}
line = "ATOM 1 N ASN A 1 11.962 53.349 44.812 1.00 20.46 N"
parsed_data = parse_pdb_line(line)
print(parsed_data)
方法三:
当然,结合Python的一些库,可以更简洁地处理PDB文件。一个常用的库是Biopython,它提供了处理生物信息学数据的功能,包括解析PDB文件的工具。
from Bio.PDB import PDBParser
def parse_pdb(file_path):
parser = PDBParser()
structure = parser.get_structure('pdb', file_path)
atom_data = []
for model in structure:
for chain in model:
for residue in chain:
for atom in residue:
atom_data.append({
"atom_name": atom.get_name(),
"residue_name": residue.get_resname(),
"chain_id": chain.get_id(),
"residue_number": residue.get_id()[1],
"coordinates": atom.get_coord()
})
return atom_data
file_path = 'your_pdb_file.pdb'
parsed_data = parse_pdb(file_path)
print(parsed_data)