def svd_superimpose(coords_1: np.ndarray, coords_2: np.ndarray): """ Superimpose paired coordinates on each other using svd Parameters ---------- coords_1 numpy array of coordinate data for the first protein; shape = (n, 3) coords_2 numpy array of corresponding coordinate data for the second protein; shape = (n, 3) Returns ------- rotation matrix, translation matrix for optimal superposition """ centroid_1, centroid_2 = ( helper.nb_mean_axis_0(coords_1), helper.nb_mean_axis_0(coords_2), ) coords_1_c, coords_2_c = coords_1 - centroid_1, coords_2 - centroid_2 correlation_matrix = np.dot(coords_2_c.T, coords_1_c) u, s, v = np.linalg.svd(correlation_matrix) reflect = np.linalg.det(u) * np.linalg.det(v) < 0 if reflect: s[-1] = -s[-1] u[:, -1] = -u[:, -1] rotation_matrix = np.dot(u, v) translation_matrix = centroid_1 - np.dot(centroid_2, rotation_matrix) return rotation_matrix.astype(np.float64), translation_matrix.astype(np.float64)
def make_score_matrix( coords_1: np.ndarray, coords_2: np.ndarray, score_function, gamma, normalized=False ) -> np.ndarray: """ Makes matrix of scores of each coordinate in coords_1 to each coordinate in coords_2 Parameters ---------- coords_1 shape = (n, 3) coords_2 shape = (m, 3) score_function gamma normalized Returns ------- matrix; shape = (n, m) """ score_matrix = np.zeros((coords_1.shape[0], coords_2.shape[0])) if normalized: both = np.concatenate((coords_1, coords_2)) mean, std = helper.nb_mean_axis_0(both), helper.nb_std_axis_0(both) coords_1 = (coords_1 - mean) / std coords_2 = (coords_2 - mean) / std for i in range(coords_1.shape[0]): for j in range(coords_2.shape[0]): score_matrix[i, j] = score_function(coords_1[i], coords_2[j], gamma) return score_matrix
def write_superposed_pdbs(self, output_pdb_folder, alignments: dict = None): """ Superposes PDBs according to alignment and writes transformed PDBs to files (View with Pymol) Parameters ---------- alignments output_pdb_folder """ if alignments is None: alignments = self.alignment output_pdb_folder = Path(output_pdb_folder) if not output_pdb_folder.exists(): output_pdb_folder.mkdir() reference_name = self.structures[0].name reference_pdb = pd.parsePDB( str(self.output_folder / f"cleaned_pdb/{self.structures[0].name}.pdb") ) core_indices = np.array( [ i for i in range(len(alignments[reference_name])) if -1 not in [alignments[n][i] for n in alignments] ] ) aln_ref = alignments[reference_name] ref_coords_core = ( reference_pdb[helper.get_alpha_indices(reference_pdb)] .getCoords() .astype(np.float64)[np.array([aln_ref[c] for c in core_indices])] ) ref_centroid = helper.nb_mean_axis_0(ref_coords_core) ref_coords_core -= ref_centroid transformation = pd.Transformation(np.eye(3), -ref_centroid) reference_pdb = pd.applyTransformation(transformation, reference_pdb) pd.writePDB(str(output_pdb_folder / f"{reference_name}.pdb"), reference_pdb) for i in range(1, len(self.structures)): name = self.structures[i].name pdb = pd.parsePDB( str(self.output_folder / f"cleaned_pdb/{self.structures[i].name}.pdb") ) aln_name = alignments[name] common_coords_2 = ( pdb[helper.get_alpha_indices(pdb)] .getCoords() .astype(np.float64)[np.array([aln_name[c] for c in core_indices])] ) ( rotation_matrix, translation_matrix, ) = superposition_functions.svd_superimpose( ref_coords_core, common_coords_2 ) transformation = pd.Transformation(rotation_matrix.T, translation_matrix) pdb = pd.applyTransformation(transformation, pdb) pd.writePDB(str(output_pdb_folder / f"{name}.pdb"), pdb)
def superpose_with_pos(coords_1, coords_2, common_coords_1, common_coords_2): """ Superpose two sets of un-aligned coordinates using smaller subsets of aligned coordinates Parameters ---------- coords_1 coords_2 common_coords_1 common_coords_2 Returns ------- superposed coord_1, superposed coords_2, superposed common_coords_2 """ rot, tran = svd_superimpose(common_coords_1, common_coords_2) coords_1 = coords_1 - helper.nb_mean_axis_0(common_coords_1) coords_2 = np.dot(coords_2 - helper.nb_mean_axis_0(common_coords_2), rot) common_coords_2_rot = apply_rotran(common_coords_2, rot, tran) return coords_1, coords_2, common_coords_2_rot
def superpose_core(self, alignments: dict = None, core_indices: np.ndarray = None): """ Superposes structures to first structure according to core positions in alignment using Kabsch superposition """ if alignments is None: alignments = self.alignment reference_key = self.structures[self.reference_structure_index].name if core_indices is None: core_indices = np.array([ i for i in range(len(alignments[reference_key])) if "-" not in [alignments[n][i] for n in alignments] ]) aln_ref = alignments[reference_key] ref_coords = self.structures[ self.reference_structure_index].coordinates[np.array( [aln_ref[c] for c in core_indices])] ref_centroid = helper.nb_mean_axis_0(ref_coords) ref_coords -= ref_centroid for i in range(len(self.structures)): if i == self.reference_structure_index: self.structures[i].coordinates -= ref_centroid else: aln_c = alignments[self.structures[i].name] common_coords_2 = self.structures[i].coordinates[np.array( [aln_c[c] for c in core_indices])] ( rotation_matrix, translation_matrix, ) = superposition_functions.paired_svd_superpose( ref_coords, common_coords_2) self.structures[ i].coordinates = superposition_functions.apply_rotran( self.structures[i].coordinates, rotation_matrix, translation_matrix)