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)
Exemple #2
0
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)