Source code for oddt.toolkits.common

"""Code common to all toolkits"""
from collections import deque
import numpy as np

from oddt.spatial import dihedral, distance


[docs]def detect_secondary_structure(res_dict): """Detect alpha helices and beta sheets in res_dict by phi and psi angles""" first = res_dict[:-1] second = res_dict[1:] psi = dihedral(first['N'], first['CA'], first['C'], second['N']) phi = dihedral(first['C'], second['N'], second['CA'], second['C']) d = second['id'] - first['id'] # Alpha helices res_mask_alpha = (((phi > -145) & (phi < -35) & (psi > -70) & (psi < 50) & (d == 1))) # alpha res_mask_alpha = np.union1d(np.argwhere(res_mask_alpha), np.argwhere(res_mask_alpha)) # Ignore groups smaller than 3 for mask_group in np.split(res_mask_alpha, np.argwhere(np.diff(res_mask_alpha) != 1).flatten() + 1): if len(mask_group) >= 3: res_dict['isalpha'][mask_group] = True # Alpha helices have to form H-Bonds hbond_dist_mask = np.abs(res_dict[res_dict['isalpha']]['resnum'] - res_dict[res_dict['isalpha']]['resnum'][:, np.newaxis]) >= 3 hbond_mask = distance(res_dict[res_dict['isalpha']]['N'], res_dict[res_dict['isalpha']]['O']) < 3.5 p_mask = ((hbond_mask & hbond_dist_mask).any(axis=0) | (hbond_mask & hbond_dist_mask).any(axis=1)) res_dict['isalpha'][np.argwhere(res_dict['isalpha']).flatten()[~p_mask]] = False # Ignore groups smaller than 3 res_mask_alpha = np.argwhere(res_dict['isalpha']).flatten() for mask_group in np.split(res_mask_alpha, np.argwhere(np.diff(res_mask_alpha) != 1).flatten() + 1): if 0 < len(mask_group) < 3: res_dict['isalpha'][mask_group] = False # Beta sheets res_mask_beta = (((phi >= -180) & (phi < -40) & (psi <= 180) & (psi > 90) & (d == 1)) | ((phi >= -180) & (phi < -70) & (psi <= -165) & (d == 1))) # beta res_mask_beta = np.union1d(np.argwhere(res_mask_beta), np.argwhere(res_mask_beta)) # Ignore groups smaller than 3 for mask_group in np.split(res_mask_beta, np.argwhere(np.diff(res_mask_beta) != 1).flatten() + 1): if len(mask_group) >= 3: res_dict['isbeta'][mask_group] = True # Beta strands have to be alongside eachother res_dist_mask = np.abs(res_dict[res_dict['isbeta']]['resnum'] - res_dict[res_dict['isbeta']]['resnum'][:, np.newaxis]) >= 4 hbond_mask = distance(res_dict[res_dict['isbeta']]['N'], res_dict[res_dict['isbeta']]['O']) < 3.5 ca_mask = distance(res_dict[res_dict['isbeta']]['CA'], res_dict[res_dict['isbeta']]['CA']) < 4.5 p_mask = ((hbond_mask & res_dist_mask).any(axis=0) | (hbond_mask & res_dist_mask).any(axis=1) | (ca_mask & res_dist_mask).any(axis=0)) res_dict['isbeta'][np.argwhere(res_dict['isbeta']).flatten()[~p_mask]] = False # Ignore groups smaller than 3 res_mask_beta = np.argwhere(res_dict['isbeta']).flatten() for mask_group in np.split(res_mask_beta, np.argwhere(np.diff(res_mask_beta) != 1).flatten() + 1): if 0 < len(mask_group) < 3: res_dict['isbeta'][mask_group] = False return res_dict
[docs]def canonize_ring_path(path): """Make a canonic path - list of consecutive atom IDXs bonded in a ring sorted in an uniform fasion. 1) Move the smallest index to position 0 2) Look for the smallest first step (delta IDX) 3) Ff -1 is smallest, inverse the path and move min IDX to position 0 Parameters ---------- path : list of integers A list of consecutive atom indices in a ring Returns ------- canonic_path : list of integers Sorted list of atoms """ if isinstance(path, deque): path_deque = path path = list(path) elif isinstance(path, list): path_deque = deque(path) else: raise ValueError('Path must be a list or deque.') # FIXME: Py2 deque does not have deque.index() path_deque.rotate(-path.index(min(path))) if path_deque[1] - path_deque[0] > path_deque[-1] - path_deque[0]: path_deque.reverse() path_deque.rotate(1) return list(path_deque)