| import numpy as np
|
| import torch
|
| import torch.nn.functional as F
|
| import joblib
|
| import pandas as pd
|
| import os
|
| import subprocess
|
| from pad_feature import parse_fasta_file
|
|
|
| def def_atom_features():
|
| A = {'N':[0,1,0], 'CA':[0,1,0], 'C':[0,0,0], 'O':[0,0,0], 'CB':[0,3,0]}
|
| V = {'N':[0,1,0], 'CA':[0,1,0], 'C':[0,0,0], 'O':[0,0,0], 'CB':[0,1,0], 'CG1':[0,3,0], 'CG2':[0,3,0]}
|
| F = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0],'CB':[0,2,0],
|
| 'CG':[0,0,1], 'CD1':[0,1,1], 'CD2':[0,1,1], 'CE1':[0,1,1], 'CE2':[0,1,1], 'CZ':[0,1,1] }
|
| P = {'N': [0, 0, 1], 'CA': [0, 1, 1], 'C': [0, 0, 0], 'O': [0, 0, 0],'CB':[0,2,1], 'CG':[0,2,1], 'CD':[0,2,1]}
|
| L = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0], 'CG':[0,1,0], 'CD1':[0,3,0], 'CD2':[0,3,0]}
|
| I = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,1,0], 'CG1':[0,2,0], 'CG2':[0,3,0], 'CD1':[0,3,0]}
|
| R = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0],
|
| 'CG':[0,2,0], 'CD':[0,2,0], 'NE':[0,1,0], 'CZ':[1,0,0], 'NH1':[0,2,0], 'NH2':[0,2,0] }
|
| D = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0], 'CG':[-1,0,0], 'OD1':[-1,0,0], 'OD2':[-1,0,0]}
|
| E = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0], 'CG':[0,2,0], 'CD':[-1,0,0], 'OE1':[-1,0,0], 'OE2':[-1,0,0]}
|
| S = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0], 'OG':[0,1,0]}
|
| T = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,1,0], 'OG1':[0,1,0], 'CG2':[0,3,0]}
|
| C = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0], 'SG':[-1,1,0]}
|
| N = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0], 'CG':[0,0,0], 'OD1':[0,0,0], 'ND2':[0,2,0]}
|
| Q = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0], 'CG':[0,2,0], 'CD':[0,0,0], 'OE1':[0,0,0], 'NE2':[0,2,0]}
|
| H = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0],
|
| 'CG':[0,0,1], 'ND1':[-1,1,1], 'CD2':[0,1,1], 'CE1':[0,1,1], 'NE2':[-1,1,1]}
|
| K = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0], 'CG':[0,2,0], 'CD':[0,2,0], 'CE':[0,2,0], 'NZ':[0,3,1]}
|
| Y = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0],
|
| 'CG':[0,0,1], 'CD1':[0,1,1], 'CD2':[0,1,1], 'CE1':[0,1,1], 'CE2':[0,1,1], 'CZ':[0,0,1], 'OH':[-1,1,0]}
|
| M = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0], 'CG':[0,2,0], 'SD':[0,0,0], 'CE':[0,3,0]}
|
| W = {'N': [0, 1, 0], 'CA': [0, 1, 0], 'C': [0, 0, 0], 'O': [0, 0, 0], 'CB':[0,2,0],
|
| 'CG':[0,0,1], 'CD1':[0,1,1], 'CD2':[0,0,1], 'NE1':[0,1,1], 'CE2':[0,0,1], 'CE3':[0,1,1], 'CZ2':[0,1,1], 'CZ3':[0,1,1], 'CH2':[0,1,1]}
|
| G = {'N': [0, 1, 0], 'CA': [0, 2, 0], 'C': [0, 0, 0], 'O': [0, 0, 0]}
|
|
|
| atom_features = {'A': A, 'V': V, 'F': F, 'P': P, 'L': L, 'I': I, 'R': R, 'D': D, 'E': E, 'S': S,
|
| 'T': T, 'C': C, 'N': N, 'Q': Q, 'H': H, 'K': K, 'Y': Y, 'M': M, 'W': W, 'G': G}
|
| for atom_fea in atom_features.values():
|
| for i in atom_fea.keys():
|
| i_fea = atom_fea[i]
|
| atom_fea[i] = [i_fea[0]/2+0.5,i_fea[1]/3,i_fea[2]]
|
| return atom_features
|
|
|
| def get_pdb_DF(file_path):
|
| atom_fea_dict = def_atom_features()
|
| res_dict = {'GLY': 'G', 'ALA': 'A', 'VAL': 'V', 'ILE': 'I', 'LEU': 'L', 'PHE': 'F', 'PRO': 'P', 'MET': 'M',
|
| 'TRP': 'W', 'CYS': 'C', 'SER': 'S', 'THR': 'T', 'ASN': 'N', 'GLN': 'Q', 'TYR': 'Y', 'HIS': 'H',
|
| 'ASP': 'D', 'GLU': 'E', 'LYS': 'K', 'ARG': 'R'}
|
| Relative_atomic_mass = {'H': 1, 'C': 12, 'O': 16, 'N': 14, 'S': 32, 'FE': 56, 'P': 31, 'BR': 80, 'F': 19,
|
| 'CO': 59, 'V': 51, 'I': 127, 'CL': 35.5, 'CA': 40, 'B': 10.8, 'ZN': 65.5, 'MG': 24.3,
|
| 'NA': 23, 'HG': 200.6, 'MN': 55, 'K': 39.1, 'AP': 31, 'AC': 227, 'AL': 27, 'W': 183.9,
|
| 'SE': 79, 'NI': 58.7}
|
|
|
| atom_count = -1
|
| res_count = -1
|
| res_id_list = []
|
| before_res_pdb_id = None
|
| atoms = []
|
|
|
| with open(file_path, 'r') as pdb_file:
|
| for line in pdb_file:
|
| if line.startswith('ATOM'):
|
| atom_type = line[76:78].strip()
|
| if atom_type not in Relative_atomic_mass:
|
| continue
|
|
|
| atom_count += 1
|
| res_pdb_id = int(line[22:26].strip())
|
| if res_pdb_id != before_res_pdb_id:
|
| res_count += 1
|
| before_res_pdb_id = res_pdb_id
|
|
|
| atom_name = line[12:16].strip()
|
| is_sidechain = 0 if atom_name in ['N', 'CA', 'C', 'O', 'H'] else 1
|
| res = res_dict.get(line[17:20].strip(), 'X')
|
| xyz = [float(line[30:38]), float(line[38:46]), float(line[46:54])]
|
|
|
| try:
|
| atom_fea = atom_fea_dict[res][atom_name]
|
| except KeyError:
|
| atom_fea = [0.5, 0.5, 0.5]
|
|
|
| try:
|
| bfactor = float(line[60:66])
|
| except ValueError:
|
| bfactor = 0.5
|
|
|
| atoms.append({
|
| 'ID': atom_count,
|
| 'atom': atom_name,
|
| 'atom_type': atom_type,
|
| 'res': res,
|
| 'res_id': res_pdb_id,
|
| 'xyz': xyz,
|
| 'B_factor': bfactor,
|
| 'mass': Relative_atomic_mass[atom_type],
|
| 'is_sidechain': is_sidechain,
|
| 'charge': atom_fea[0],
|
| 'num_H': atom_fea[1],
|
| 'ring': atom_fea[2]
|
| })
|
|
|
| if len(res_id_list) == 0 or res_id_list[-1] != res_pdb_id:
|
| res_id_list.append(res_pdb_id)
|
| elif line.startswith('TER'):
|
| break
|
|
|
| return atoms, res_id_list
|
|
|
| def PDBFeature(query_id, PDB_chain_dir, results_dir):
|
| pdb_path = f"{PDB_chain_dir}/{query_id}.pdb"
|
| atoms, res_id_list = get_pdb_DF(pdb_path)
|
|
|
|
|
|
|
|
|
| res_sidechain_centroid = []
|
| res_types = []
|
|
|
| for res_id in res_id_list:
|
| res_atoms = [atom for atom in atoms if atom['res_id'] == res_id]
|
| if not res_atoms:
|
| continue
|
|
|
| res_type = res_atoms[0]['res']
|
| res_types.append(res_type)
|
|
|
| xyz = np.array([atom['xyz'] for atom in res_atoms])
|
| masses = np.array([atom['mass'] for atom in res_atoms]).reshape(-1, 1)
|
| centroid = np.sum(masses * xyz, axis=0) / np.sum(masses)
|
|
|
| sidechain_atoms = [atom for atom in res_atoms if atom['is_sidechain'] == 1]
|
| if not sidechain_atoms:
|
| res_sidechain_centroid.append(centroid)
|
| else:
|
| xyz = np.array([atom['xyz'] for atom in sidechain_atoms])
|
| masses = np.array([atom['mass'] for atom in sidechain_atoms]).reshape(-1, 1)
|
| sidechain_centroid = np.sum(masses * xyz, axis=0) / np.sum(masses)
|
| res_sidechain_centroid.append(sidechain_centroid)
|
|
|
| res_sidechain_centroid = np.array(res_sidechain_centroid)
|
|
|
| with open(f"{results_dir}/{query_id}_psepos_SC.pkl", 'wb') as f:
|
| joblib.dump(res_sidechain_centroid, f)
|
|
|
| sequence = ''.join(res_types)
|
| with open(f"{results_dir}/{query_id}.seq", 'w') as f:
|
| f.write(f">{query_id}\n")
|
| f.write(sequence)
|
|
|
|
|
|
|
|
|