|
|
import warnings |
|
|
import numpy as np |
|
|
import prody |
|
|
prody.confProDy(verbosity='none') |
|
|
from prody import parsePDB, ANM |
|
|
|
|
|
|
|
|
def pdb_to_normal_modes(pdb_file, num_modes=5, nmax=5000): |
|
|
""" |
|
|
Compute normal modes for a PDB file using an Anisotropic Network Model (ANM) |
|
|
http://prody.csb.pitt.edu/tutorials/enm_analysis/anm.html (accessed 01/11/2023) |
|
|
""" |
|
|
protein = parsePDB(pdb_file, model=1).select('calpha') |
|
|
|
|
|
if len(protein) > nmax: |
|
|
warnings.warn("Protein is too big. Returning zeros...") |
|
|
eig_vecs = np.zeros((len(protein), 3, num_modes)) |
|
|
|
|
|
else: |
|
|
|
|
|
anm = ANM('ANM analysis') |
|
|
anm.buildHessian(protein, cutoff=15.0, gamma=1.0) |
|
|
|
|
|
|
|
|
anm.calcModes(num_modes, zeros=False) |
|
|
|
|
|
|
|
|
eig_vecs = anm.getEigvecs() |
|
|
eig_vecs = eig_vecs.reshape(len(protein), 3, num_modes) |
|
|
|
|
|
|
|
|
nm_dict = {} |
|
|
for atom, nm_vec in zip(protein, eig_vecs): |
|
|
chain = atom.getChid() |
|
|
resi = atom.getResnum() |
|
|
name = atom.getName() |
|
|
nm_dict[(chain, resi, name)] = nm_vec.T |
|
|
|
|
|
return nm_dict |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
import argparse |
|
|
from pathlib import Path |
|
|
import torch |
|
|
from tqdm import tqdm |
|
|
|
|
|
parser = argparse.ArgumentParser() |
|
|
parser.add_argument('basedir', type=Path) |
|
|
parser.add_argument('--outfile', type=Path, default=None) |
|
|
args = parser.parse_args() |
|
|
|
|
|
|
|
|
split_path = Path(args.basedir, 'split_by_name.pt') |
|
|
data_split = torch.load(split_path) |
|
|
|
|
|
pockets = [x[0] for split in data_split.values() for x in split] |
|
|
|
|
|
all_normal_modes = {} |
|
|
for p in tqdm(pockets): |
|
|
pdb_file = Path(args.basedir, 'crossdocked_pocket10', p) |
|
|
|
|
|
try: |
|
|
nm_dict = pdb_to_normal_modes(str(pdb_file)) |
|
|
all_normal_modes[p] = nm_dict |
|
|
except AttributeError as e: |
|
|
warnings.warn(str(e)) |
|
|
|
|
|
np.save(args.outfile, all_normal_modes) |
|
|
|