def normalize_pts(self, pts1, pts2):
        #print pts1
        A = pts1[:, 0:2]
        B = pts2[:, 0:2]

        assert len(A) == len(B)

        N = A.shape[0]  # total points

        # find centroids
        centroid_A = rmsd.centroid(A)
        centroid_B = rmsd.centroid(B)

        # centre the points
        AA = A - centroid_A
        BB = B - centroid_B

        #get optimal rotation matrix
        R = rmsd.kabsch(AA, BB)
        # Apply transformation
        AA1 = np.dot(AA, R)
        angle1 = math.atan2(R[1][0], R[1][1])

        pts1[:, 0:2] = AA1 + centroid_B
        # rotate the rotations
        pts1[:, 2] -= angle1
        return rmsd.rmsd(AA1, BB)
Exemple #2
0
def test_pdb(example_path="examples", threshold=0.001):
    """
    A simple test for the PDB functionality
    :return: True if all test passed
    """
    p_atoms, P = rmsd.get_coordinates(example_path+'/ci2_1.pdb', 'pdb')
    q_atoms, Q = rmsd.get_coordinates(example_path+'/ci2_2.pdb', 'pdb')

    n_rmsd = rmsd.rmsd(P, Q)
    Pc = rmsd.centroid(P)
    Qc = rmsd.centroid(Q)
    P -= Pc
    Q -= Qc

    k_rmsd = rmsd.kabsch_rmsd(P, Q)
    q_rmsd = rmsd.quaternion_rmsd(P, Q)

    if abs(n_rmsd - 26.975) > threshold:
        print('Failed to calculate normal RMSD, result: {0}'.format(n_rmsd))
        return False
    if abs(k_rmsd - 11.777) > threshold:
        print('Failed to calculate Kabsch RMSD, result: {0}'.format(k_rmsd))
        return False
    if abs(q_rmsd - 11.777) > threshold:
        print('Failed to calculate quaternion RMSD, result: {0}'.format(q_rmsd))
        return False
    if abs(q_rmsd - k_rmsd) > threshold ** 2:
        print('Failed to yield similar Kabsch and quaternion RMSD, result: {0} vs {1}'.format(k_rmsd, q_rmsd))
        return False
    return True
Exemple #3
0
def rmsd_distance(atoms_list,
                  coordinates_list,
                  translation=False,
                  rotation=False):

    N = len(atoms_list)

    kernel = np.zeros((N, N))

    # Lower triangular

    for i in range(N):
        for j in range(i):

            coord_i = coordinates_list[i]
            coord_j = coordinates_list[j]

            # unique pairs
            if translation:
                coord_i = coord_i - rmsd.centroid(coord_i)
                coord_j = coord_j - rmsd.centroid(coord_j)

            if rotation:
                kernel[i, j] = rmsd.kabsch_rmsd(coord_i, coord_j)
            else:
                kernel[i, j] = rmsd.rmsd(coord_i, coord_j)

            kernel[j, i] = kernel[i, j]

    # np.fill_diagonal(kernel, 0.0)
    # iu2 = np.triu_indices(N, 1)
    # il2 = np.tril_indices(N, -1)
    # kernel[iu2] = kernel[il2]

    return kernel
Exemple #4
0
def alin(A,B):
	A -= rmsd.centroid(A)
	B -= rmsd.centroid(B)
	#print (B)
	U = rmsd.kabsch(A, B)
	A = np.dot(A, U)

	return A, B, rmsd.rmsd(A,B)
Exemple #5
0
def calc_rmsd(mol1, mol2):
    mol_coord1 = mol_to_coord_mat(mol1)
    mol_coord2 = mol_to_coord_mat(mol2)

    #Localize on centroid
    mol_coord1 -= rmsd.centroid(mol_coord1)
    mol_coord2 -= rmsd.centroid(mol_coord2)

    return rmsd.quaternion_rmsd(mol_coord1, mol_coord2)
Exemple #6
0
def CalRmsdFrame(coor_frame, ref_coor_frame):
    """
    Calculate the rmsd between two frames.
    """
    coor_tmp = coor_frame.reshape(-1, 3)
    ref_tmp = ref_coor_frame.reshape(-1, 3)
    coor_tmp -= rmsd.centroid(coor_tmp)
    ref_tmp -= rmsd.centroid(ref_tmp)
    return rmsd.kabsch_rmsd(coor_tmp, ref_tmp)
def KabschTransform(MAT_B, MAT_R):
    C_road = rmsd.centroid(MAT_R)  # centreroid of the road points
    C_back = rmsd.centroid(MAT_B)  # centreroid of the back points
    XYZroad_centered = MAT_R - C_road  #XYZ of road after centering
    XYZback_centered = MAT_B - C_back  #XYZ of back after centering
    R = rmsd.kabsch(
        XYZroad_centered, XYZback_centered
    )  # the optimal rotation matrix to rotate road points to back coordinates
    return C_road, C_back, R
Exemple #8
0
def count_rmsd(t1, t2):
    P = np.array([[float(v.x), float(v.y), float(v.z)] for v in t1.points])
    Q = np.array([[float(v.x), float(v.y), float(v.z)] for v in t2.points])

    # print("RMSD before translation: ", round(rmsd.kabsch_rmsd(P, Q), 6))
    P -= rmsd.centroid(P)
    Q -= rmsd.centroid(Q)
    # print("RMSD after translation: ", round(rmsd.kabsch_rmsd(P, Q), 6))
    return round(rmsd.kabsch_rmsd(P, Q), 4)  # round 6 in triangles_matrix
def get_transformation_matrix_kabsch(q, p):
    # compute centroids
    Pc = rmsd.centroid(p)
    Qc = rmsd.centroid(q)
    # Kabsch algorithm for estimating R and t
    T = np.identity(4)
    T[:3, :3] = rmsd.kabsch(p - Pc, q - Qc)
    T[:3, 3] = Pc - np.dot(T[:3, :3], Qc)

    return T
Exemple #10
0
def RMSDmetric(structure1, structure2):
    numParticles = len(structure1) / 3

    coords1 = structure1.reshape(int(numParticles), 3)
    coords2 = structure2.reshape(int(numParticles), 3)

    coords1 = coords1 - rmsd.centroid(coords1)
    coords2 = coords2 - rmsd.centroid(coords2)

    return rmsd.kabsch_rmsd(coords1, coords2)
Exemple #11
0
def crmsd_kabsch(A, B):
    # Translate
    A -= rmsd.centroid(A)
    B -= rmsd.centroid(B)

    # Rotate
    U = rmsd.kabsch(A, B)
    A = np.dot(A, U)

    return rmsd.rmsd(A, B)
Exemple #12
0
def compute_similarity(site_a, site_b):
    """
    Compute the similarity between two given ActiveSite instances.

    Input: two ActiveSite instances
    Output: the similarity between them (a floating point number)
    """
    # Get strings of single letter aa residues
    s_a = output_aa_string(site_a.residues)
    s_b = output_aa_string(site_b.residues)
    
    # Align strings using local alignment algorithm which relies
    # on dynamic programming to compute all possible alignments and
    # returns the highest scoring alignment. 
    
    # Local alignment aims to find the max alignment for substrings
    # of two larger strings.
    # Matches = +1
    # Mismatches, gaps = +0
    
    alignments = pairwise2.align.localxx(s_a, s_b) # perform alignment
    if len(alignments) == 0: return float("inf") # return INF if no alignment found
    align_a, align_b, s = alignments[0][:3] # extract first alignment
        
    # Output indices where nucleotides in alignment match
    inds_a, inds_b = match(align_a, align_b)
    
    if len(inds_a) < 2: return float("inf")
        
    # Create matrix of coordinates for atom CA
    V = create_coord_matrix(site_a, inds_a)
    W = create_coord_matrix(site_b, inds_b)
     
    # Center and rotate Ca matrices then calculate Root-Mean-Square-Deviation (RMSD)
    # It measures the average distance between backbone atoms of two
    # superimposed proteins.

    # The greater the RMSD, the less similar the proteins are.
    # A RMSD equal to 0 represents identical proteins.

    # Each protein is a matrix containing x, y, and z coordinates for each CA atom
    # The rows of the two matrices are matching residues obtained from the alignment

    # To minimize RMSD you must first center the coordinates on the origin so the
    # two vectors can be near each other.
    V -= rmsd.centroid(V)
    W -= rmsd.centroid(W)

    # Then find the optimal rotation for matrix W that aligns it best with V
    # This is the Kabasch algorithm which works by calculating a covariance matrix
    # and then finding the singular value decomposition (SVD) of the cov. matrix
    # Last, find the optimal rotation matrix which is the dot product of V and W
    # optimized by lowest RMSD
    return rmsd.kabsch_rmsd(V,W)
Exemple #13
0
def test_reorder_inertia_hungarian():

    # coordinates of scrambled and rotated butane
    atoms = np.array(
        ["C", "C", "C", "C", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H"]
    )

    p_coord = np.array(
        [
            [2.142e00, 1.395e00, -8.932e00],
            [3.631e00, 1.416e00, -8.537e00],
            [4.203e00, -1.200e-02, -8.612e00],
            [5.691e00, 9.000e-03, -8.218e00],
            [1.604e00, 7.600e-01, -8.260e00],
            [1.745e00, 2.388e00, -8.880e00],
            [2.043e00, 1.024e00, -9.930e00],
            [4.169e00, 2.051e00, -9.210e00],
            [3.731e00, 1.788e00, -7.539e00],
            [3.665e00, -6.470e-01, -7.940e00],
            [4.104e00, -3.840e-01, -9.610e00],
            [6.088e00, -9.830e-01, -8.270e00],
            [5.791e00, 3.810e-01, -7.220e00],
            [6.230e00, 6.440e-01, -8.890e00],
        ]
    )

    q_coord = np.array(
        [
            [6.71454, -5.53848, -3.50851],
            [6.95865, -6.22697, -2.15264],
            [8.16747, -5.57632, -1.45606],
            [5.50518, -6.19016, -4.20589],
            [5.33617, -5.71137, -5.14853],
            [7.58263, -5.64795, -4.12498],
            [6.51851, -4.49883, -3.35011],
            [6.09092, -6.11832, -1.53660],
            [5.70232, -7.22908, -4.36475],
            [7.15558, -7.26640, -2.31068],
            [8.33668, -6.05459, -0.51425],
            [7.97144, -4.53667, -1.29765],
            [4.63745, -6.08152, -3.58986],
            [9.03610, -5.68475, -2.07173],
        ]
    )

    p_coord -= rmsd.centroid(p_coord)
    q_coord -= rmsd.centroid(q_coord)

    review = rmsd.reorder_inertia_hungarian(atoms, atoms, p_coord, q_coord)

    result_rmsd = rmsd.kabsch_rmsd(p_coord, q_coord[review])

    np.testing.assert_almost_equal(0, result_rmsd, decimal=2)
Exemple #14
0
def kabsch(pointsCurrent, pointsRef):

    C_curr = rmsd.centroid(pointsCurrent)
    C_ref = rmsd.centroid(pointsRef)

    points_curr_norm = pointsCurrent - C_curr  # XYZ current after centering
    points_ref_norm = pointsRef - C_ref

    # the optimal rotation matrix to rotate XYZcurrent to XYZref
    R = rmsd.kabsch(points_curr_norm, points_ref_norm)

    return (R, C_curr, C_ref)
def test_icp(A, shuffle = 1):

    # Generate a random dataset
    
    for i in range(num_tests):
        print('test', i)
        B = np.copy(A)

        # Translate
        t = np.random.rand(dim)*translation
        B += t

        # Rotate
        R = rotation_matrix(np.random.rand(dim), np.random.rand() * rotation)
        B = np.dot(R, B.T).T

        # Add noise
        B += np.random.randn(N, dim) * noise_sigma

        # Shuffle to disrupt correspondence
        if (shuffle == 1):
            np.random.shuffle(B)

        #B[0:100] = 0
        #Bcenter = rmsd.centroid(B)
        #B[0:100] = Bcenter

        print("Normal squared_distance", squared_distance(A, B))
        plot3d(A, B)

        # Run ICP
        A -= rmsd.centroid(A)
        B -= rmsd.centroid(B)
        T, distances, iterations = icp.icp(B, A, tolerance=0.000001)

        print(T.shape)
        # Make C a homogeneous representation of B
        C = np.ones((N, 4))
        C[:,0:3] = np.copy(B)

        # Transform C
        C = np.dot(T, C.T).T
        C = C[:, 0:3]
        
        print("Rotated squared_distance", squared_distance(A, C))
        plot3d(A, C)

        #assert np.mean(distances) < 6*noise_sigma                   # mean error should be small
        #assert np.allclose(T[0:3,0:3].T, R, atol=6*noise_sigma)     # T and R should be inverses
        #assert np.allclose(-T[0:3,3], t, atol=6*noise_sigma)        # T and t should be inverses
    
    return 
def generate_set(A, B):
    Asize = A.shape[0]
    Bsize = B.shape[0]
    temp = np.zeros((max(Asize, Bsize), 3))
    if (Asize < Bsize):
        temp += rmsd.centroid(A)
        temp[0:Asize] = A
        A = temp
    else:
        temp += rmsd.centroid(B)
        temp[0:Bsize] = B
        B = temp
    return A, B
Exemple #17
0
def normalize_pts(pts1, pts2):
    #print pts1
    A = pts1[:, 0:2]
    B = pts2[:, 0:2]

    assert len(A) == len(B)

    N = A.shape[0]  # total points

    # find centroids
    centroid_A = rmsd.centroid(A)
    centroid_B = rmsd.centroid(B)

    # centre the points
    AA = A - centroid_A
    BB = B - centroid_B
    
    #get optimal rotation matrix
    R = rmsd.kabsch(AA, BB)
    # Apply transformation
    AA1 = np.dot(AA, R)
    angle1 = math.atan2(R[1][0], R[1][1])
    
    #try flippin' it
    AA[:, 1] *= -1
    #get optimal rotation matrix
    R = rmsd.kabsch(AA, BB)
    # Apply transformation
    AA2 = np.dot(AA, R)#get optimal rotation matrix
    angle2 = math.atan2(R[1][0], R[1][1])
    
    #go with whichever one is better
    a2diff = np.abs(pts2[:,2]-(pts1[:,2]-angle2))
    a1diff = np.abs(pts2[:,2]-(pts1[:,2]+angle1))
    #angle differences are fun!
    for i in range(0, len(a1diff)):
        while (a2diff[i] > np.pi):
            a2diff[i] -= 2*np.pi
        while (a1diff[i] > np.pi):
            a1diff[i] -= 2*np.pi
    print np.degrees(a2diff), np.degrees(a1diff)
    if (np.sum(np.abs(a1diff)) > np.sum(np.abs(a2diff))):
        pts1[:, 0:2] = AA2 + centroid_B
        # rotate the rotations (backwards, since we mirrored the thing)
        pts1[:, 2] -= angle2
        return rmsd.rmsd(AA2, BB)
    else:
        pts1[:, 0:2] = AA1 + centroid_B
        # rotate the rotations
        pts1[:, 2] += angle1
        return rmsd.rmsd(AA1, BB)
def center_and_kabsch(P, Q):
    """ returns centroid of P, Q and a rotational matrix (in subsequent analyses, you may want to subtract centroidP/Q from your point sets)
    that minimizes RMSD between corresponding points in P and Q, *when applied to P* """

    P = np.array(P)
    Q = np.array(Q)

    centroidP = rmsd.centroid(P)
    centroidQ = rmsd.centroid(Q)

    P = P - centroidP
    Q = Q - centroidQ

    return centroidP, centroidQ, rmsd.kabsch(P, Q)
Exemple #19
0
def calculate_rmsd(mol_id,
                   geometry_id1=None,
                   geometry_id2=None,
                   heavy_atoms_only=False):

    # These cause circular import errors if we put them at the top of the file
    from ._girder import GirderClient
    from ._calculation import GirderMolecule

    # Allow the user to pass in a GirderMolecule instead of an id
    if isinstance(mol_id, GirderMolecule):
        mol_id = mol_id._id

    if geometry_id1 is None:
        cjson1 = GirderClient().get('/molecules/%s/cjson' % mol_id)
    else:
        cjson1 = GirderClient().get('/molecules/%s/geometries/%s/cjson' %
                                    (mol_id, geometry_id1))

    if geometry_id2 is None:
        cjson2 = GirderClient().get('/molecules/%s/cjson' % mol_id)
    else:
        cjson2 = GirderClient().get('/molecules/%s/geometries/%s/cjson' %
                                    (mol_id, geometry_id2))

    coords1 = cjson1['atoms']['coords']['3d']
    coords1_triplets = zip(coords1[0::3], coords1[1::3], coords1[2::3])
    A = np.array([x for x in coords1_triplets])

    coords2 = cjson2['atoms']['coords']['3d']
    coords2_triplets = zip(coords2[0::3], coords2[1::3], coords2[2::3])
    B = np.array([x for x in coords2_triplets])

    if heavy_atoms_only:
        atomic_numbers = cjson1['atoms']['elements']['number']
        heavy_indices = [i for i, n in enumerate(atomic_numbers) if n != 1]

        A = A.take(heavy_indices, 0)
        B = B.take(heavy_indices, 0)

    # Translate
    A -= rmsd.centroid(A)
    B -= rmsd.centroid(B)

    # Rotate
    U = rmsd.kabsch(A, B)
    A = np.dot(A, U)

    return rmsd.rmsd(A, B)
Exemple #20
0
def xyz4a_position(i, lines):
    template1 = np.array([[-0.93454, 0.91954, 1.11786],
                          [-0.01675, 0.03488, 0.58954],
                          [1.10621, 0.72253, -0.004],
                          [1.6148, 1.14817, -0.57075]])
    template2 = np.array([[-0.93454, 0.91954, 1.11786],
                          [-0.01675, 0.03488, 0.58954],
                          [1.10621, 0.72253, -0.004],
                          [1.6148, 1.14817, -0.57075],
                          [-0.64719, -0.82998, -0.40926],
                          [-1.12252, -1.99515, -0.72338]])
    amino_acid_position = []
    for k in range(i, i + 4, 1):
        try:
            x = lines[k][30:38]
            y = lines[k][38:46]
            z = lines[k][46:54]
            amino_acid_position.append(np.asarray([x, y, z], dtype=float))
        except:
            sys.exit(
                "Error parsing input for the following line: \n{0:s}".format(
                    lines[k]))
    amino_acid_position = np.asarray(amino_acid_position)
    #print amino_acid_position
    a_acid_p = amino_acid_position - rmsd.centroid(amino_acid_position)
    template1 -= rmsd.centroid(template1)
    #centroid P2 into f
    template2 = template2 - rmsd.centroid(template2)
    #for debug
    print '*************8888888888888888'
    #print template1.shape#(4,3)
    #print a_acid_p.shape#(5,3)
    #print template2.shape#(6.3)
    rot = rmsd.kabsch(template1, a_acid_p)
    #pp is the rotated martix,Rotate matrix P2 unto Q
    new_position = np.dot(template2, rot)
    #translation the P2 into initial position after rotation
    new_position += rmsd.centroid(amino_acid_position)
    C = new_position.tolist()
    #print new_position
    #print lenthg
    #for n in range(0,6,1):
    position5 = ('%8s' % str(float('%.3f' % C[4][0]))) + ('%8s' % str(
        float('%.3f' % C[4][1]))) + ('%8s' % str(float('%.3f' % C[4][2])))
    position6 = ('%8s' % str(float('%.3f' % C[5][0]))) + ('%8s' % str(
        float('%.3f' % C[5][1]))) + ('%8s' % str(float('%.3f' % C[5][2])))
    print 'print the position of position 5 and position 6'
    return position5, position6
Exemple #21
0
def getkabschangle(Ac, Bc):

    # Ac = Ac[:,0:3:2]
    # Bc = Bc[:,0:3:2]
    # Manipulate

    A = Ac - rmsd.centroid(Ac)
    B = Bc - rmsd.centroid(Bc)

    U = rmsd.kabsch(A, B)
    # print(U)

    degvals = (rotationMatrixToEulerAngles(U))

    return degvals[1]
    """
Exemple #22
0
def get_rmsd(coords, reference):
    """
    Calculate the rmsd of the given coordinates compared to a reference.

    Input:
        > coords        list[np.array, np.array, ...]; coordinates to be compared
                        vs. the reference coordinates
        > reference     list[np.array, np.array, ...]; reference to compare
                        coordinates to

    Sources:   https://pypi.org/project/rmsd/
    """
    # translate center of geometry to the origin for reference and
    # current frame
    coords -= rmsd.centroid(coords)
    reference -= rmsd.centroid(reference)
    return rmsd.kabsch_rmsd(coords, reference)
Exemple #23
0
def calc_rmsd(coords1, coords2):
    """Calculate root-mean square deviation.

    Parameters
    ----------
    coords1 : list(list(str,int,int,int))
        The coordinates for the first
        molecule (conformer).
    coords2 : list(list(str,int,int,int))
        The coordinates for the second
        molecule (conformer).

    Notes
    -----
    The coordinates are given as follows:
    atom name, x coord, y coord, z coord
    Example for carbon monoxide:
    [[C, 0.0, 0.0, 0.0],[O, 1.0, 0.0, 0.0]]
    The distances are in Angstroms.

    Returns
    -------
    rmsd : float
        The rmsd between two molecular
        geometries. This rmsd is calculated
        after applying centering and a
        rotation matrix (calculated via
        the Kabsch algorithm).

    """
    # trivial check
    assert len(coords1) == len(coords2)
    # first turn lists into numpy arrays (otherwise
    # cannot perform some rmsd operations)
    # and excise atom names (not needed for rmsd)
    mol1 = np.array([[coords1[i][1], coords1[i][2], coords1[i][3]] for i in range(len(coords1))])
    mol2 = np.array([[coords2[i][1], coords2[i][2], coords2[i][3]] for i in range(len(coords2))])
    # first center each molecule
    mol1 -= rmsd.centroid(mol1)
    mol2 -= rmsd.centroid(mol2)
    # calculate the rotation matrix
    rot_matrix = rmsd.kabsch(mol1, mol2)
    # apply the rotation matrix
    mol1 = np.dot(mol1, rot_matrix)
    # finally get the rmsd
    return rmsd.rmsd(mol1, mol2)
def test_best_fit(A, shuffle = 1):

    # Generate a random dataset

    for i in range(num_tests):
        print('test', i)
        B = np.copy(A)

        # Translate
        t = np.random.rand(dim)*translation
        B += t

        # Rotate
        R = rotation_matrix(np.random.rand(dim), np.random.rand()*rotation)
        B = np.dot(R, B.T).T

        # Add noise
        B += np.random.randn(N, dim) * noise_sigma
        
        # Shuffle to disrupt correspondence
        if (shuffle == 1):
            np.random.shuffle(B)

        print("Normal squared_distance", squared_distance(A, B))
        plot3d(A, B)

        # Find best fit transform
        A -= rmsd.centroid(A)
        B -= rmsd.centroid(B)
        T, R1, t1 = icp.best_fit_transform(B, A)

        # Make C a homogeneous representation of B
        C = np.ones((N, 4))
        C[:,0:3] = B

        # Transform C
        C = np.dot(T, C.T).T
        C = C[:, 0:3]
        
        print("Rotated squared_distance", squared_distance(A, C))
        plot3d(A, C)
        #assert np.allclose(C[:,0:3], A, atol=6*noise_sigma) # T should transform B (or C) to A
        #assert np.allclose(-t1, t, atol=6*noise_sigma)      # t and t1 should be inverses
        #assert np.allclose(R1.T, R, atol=6*noise_sigma)     # R and R1 should be inverses

    return
Exemple #25
0
def test_quaternion_rmsd_pdb():

    filename_p = "ci2_1.pdb"
    filename_q = "ci2_2.pdb"
    filename_p = pathlib.PurePath(RESOURCE_PATH, filename_p)
    filename_q = pathlib.PurePath(RESOURCE_PATH, filename_q)

    p_atoms, p_coord = rmsd.get_coordinates_pdb(filename_p)
    q_atoms, q_coord = rmsd.get_coordinates_pdb(filename_q)

    p_center = rmsd.centroid(p_coord)
    q_center = rmsd.centroid(q_coord)
    p_coord -= p_center
    q_coord -= q_center

    result = rmsd.quaternion_rmsd(p_coord, q_coord)

    np.testing.assert_almost_equal(11.7768, result, decimal=3)
Exemple #26
0
def align_coordinates(coordinates):

    # Align everything to first coordinate

    coordinates = copy.deepcopy(coordinates)

    coordinate_ref = coordinates[0]
    coordinate_ref -= rmsd.centroid(coordinate_ref)
    coordinates[0] = coordinate_ref

    for i, coordinate in enumerate(coordinates[1:]):

        coordinate -= rmsd.centroid(coordinate)
        U = rmsd.kabsch(coordinate, coordinate_ref)
        coordinate = np.dot(coordinate, U)
        coordinates[i] = coordinate

    return coordinates
def calculate_transformation_kabsch(
        src_points: np.ndarray,
        dst_points: np.ndarray) -> Tuple[np.array, float]:
    """
    Calculates the optimal rigid transformation from src_points to
    dst_points
    (regarding the least squares error)
    Parameters:
    -----------
    src_points: array
        (3,N) matrix
    dst_points: array
        (3,N) matrix

    Returns:
    -----------
    rotation_matrix: array
        (3,3) matrix

    translation_vector: array
        (3,1) matrix
    rmsd_value: float
    """
    assert src_points.shape == dst_points.shape
    if src_points.shape[0] != 3:
        raise Exception(
            "The input data matrix had to be transposed in order to compute transformation."
        )

    src_points = src_points.transpose()
    dst_points = dst_points.transpose()

    src_points_centered = src_points - rmsd.centroid(src_points)
    dst_points_centered = dst_points - rmsd.centroid(dst_points)

    rotation_matrix = rmsd.kabsch(src_points_centered, dst_points_centered)
    rmsd_value = rmsd.kabsch_rmsd(src_points_centered, dst_points_centered)

    translation_vector = rmsd.centroid(dst_points) - np.matmul(
        rmsd.centroid(src_points), rotation_matrix)

    return create_homogenous(rotation_matrix.transpose(),
                             translation_vector.transpose()), rmsd_value
def myRMSDmetric(arr1, arr2):
    """
    This function is built under the assumption that the space dimension is 3!!!
    Requirement from sklearn radius_neighbors_graph: The callable should take two arrays as input and return one value indicating the distance between them.
     Input: One row from reshaped XYZ trajectory as number of steps times nDOF
     Inside: Reshape to XYZ format and apply rmsd as r=rmsd(X[i], X[j])
     Output: rmsd distance
    """

    nParticles = len(arr1) / 3
    assert (nParticles == int(nParticles))

    X1 = arr1.reshape(int(nParticles), 3)
    X2 = arr2.reshape(int(nParticles), 3)

    X1 = X1 - rmsd.centroid(X1)
    X2 = X2 - rmsd.centroid(X2)

    return rmsd.kabsch_rmsd(X1, X2)
Exemple #29
0
def normalize_pts_old(pts1, pts2, win):
    #print pts1
    A = pts1[:, 0:2]
    B = pts2[:, 0:2]

    assert len(A) == len(B)

    N = A.shape[0]  # total points

    # find centroids
    centroid_A = rmsd.centroid(A)
    centroid_B = rmsd.centroid(B)

    # centre the points
    AA = A - centroid_A
    BB = B - centroid_B
    
    #get optimal rotation matrix
    R = rmsd.kabsch(AA, BB)
    # Apply transformation
    AA1 = np.dot(AA, R)
    angle1 = math.atan2(R[1][0], R[1][1])
    
    i=0
    for pt in pts1:
        pt_graphics = Point(int(pt[0]-centroid_A[0]+centroid_B[0]), int(pt[1]-centroid_A[1]+centroid_B[1]))
        cir = Circle(pt_graphics, 8)
        cir.setOutline('green')
        cir.draw(win)
        line = Line(pt_graphics, Point(pt_graphics.x+8*np.cos(-pt[2]), pt_graphics.y+8*np.sin(-pt[2])))
        line.draw(win)
        text = Text(pt_graphics, str(i))
        i += 1
        text.draw(win)
    
    pts1[:, 0:2] = AA1 + centroid_B
    # rotate the rotations
    pts1[:, 2] -= angle1
    return rmsd.rmsd(AA1, BB)
Exemple #30
0
def test_centroid():
    a1 = np.array([-19.658, 17.18, 25.163], dtype=float)
    a2 = np.array([-20.573, 18.059, 25.88], dtype=float)
    a3 = np.array([-22.018, 17.551, 26.0], dtype=float)

    atms = np.asarray([a1, a2, a3])
    centroid = rmsd.centroid(atms)

    assert 3 == len(centroid)

    np.testing.assert_array_almost_equal([-20.7496, 17.5966, 25.6810],
                                         centroid,
                                         decimal=3)
Exemple #31
0
    def calc_rmsd(self):
        """
        Calculate normal, translated, and rotated RMSD.

        """
        tmp_1, tmp_2 = self.coord_1.copy(), self.coord_2.copy()

        self.rmsd_normal = rmsd.rmsd(self.coord_1, self.coord_2)

        # Manipulate recenter
        self.coord_1 -= rmsd.centroid(self.coord_1)
        self.coord_2 -= rmsd.centroid(self.coord_2)

        self.rmsd_translate = rmsd.rmsd(self.coord_1, self.coord_2)

        # Rotate
        rotation_matrix = rmsd.kabsch(self.coord_1, self.coord_2)
        self.coord_1 = np.dot(self.coord_1, rotation_matrix)

        self.rmsd_rotate = rmsd.rmsd(self.coord_1, self.coord_2)

        self.coord_1, self.coord_2 = tmp_1, tmp_2
Exemple #32
0
    def main(self):
        """
        main object to run DSR as command line program
        """
        dbatoms = []
        # The database content:
        import atomhandling
        basefilename = filename_wo_ending(self.res_file)
        if not basefilename:
            print('*** Illegal option ***')
            sys.exit()
        if len(self.reslist) == 0:
            print("*** The input file is empty. Can not proceed! ***")
            sys.exit()
        find_atoms = atomhandling.FindAtoms(self.reslist)
        rle = ResListEdit(self.reslist, find_atoms)
        dsrp = DSRParser(self.reslist)
        self.fragment = dsrp.fragment
        restraints = self.gdb.get_restraints(self.fragment)  # this is only executed once
        db_residue_string = self.gdb.get_resi(self.fragment)
        dbatoms = self.gdb.get_atoms(self.fragment, self.invert)  # only the atoms of the dbentry as list
        # the atomtypes of the dbentry as list e.g. ['C', 'N', ...]
        db_atom_types = atomhandling.get_atomtypes(dbatoms)
        sf = atomhandling.SfacTable(self.reslist, db_atom_types)
        sfac_table = sf.set_sfac_table()  # from now on this sfac table is set
        resi = Resi(dsrp, db_residue_string, find_atoms)
        # line where the dsr command is found in the resfile:
        if dsrp.cf3_active:
            from cf3fit import CF3
            cf3 = CF3(rle, find_atoms, self.reslist, self.fragment, sfac_table,
                      basefilename, dsrp, resi, self.res_file, self.options)
            if self.fragment == 'cf3':
                cf3.cf3(afix='130')
            if self.fragment == 'cf6':
                cf3.cf3(afix='120')
            if self.fragment == 'cf9':
                cf3.cf9()
            print('\nFinished...')
            sys.exit()
        # checks have to be after CF3, CF6 etc.
        self.gdb.check_consistency(self.fragment)
        self.gdb.check_db_atom_consistency(self.fragment)
        self.gdb.check_db_restraints_consistency(self.fragment)
        self.gdb.check_sadi_consistence(self.fragment)
        if dsrp.occupancy:
            rle.set_free_variables(dsrp.occupancy)
        restraints = remove_resi(restraints)
        # corrects the atom type according to the previous defined global sfac table:
        dbatoms = atomhandling.set_final_db_sfac_types(db_atom_types, dbatoms, sfac_table)
        if not dsrp.unit_line:
            print('*** No UNIT instruction in res file found! Can not proceed! ***')
        print('Inserting {} into res File.'.format(self.fragment))
        if self.invert:
            print('Fragment inverted.')
        print('Source atoms: {}'.format(', '.join(dsrp.source)))
        print('Target atoms: {}'.format(', '.join(dsrp.target)))
        shx = ShelxlRefine(self.reslist, basefilename, find_atoms, self.options)
        shx.backup_shx_file()
        # several checks if the atoms in the dsr command line are consistent
        atomhandling.check_source_target(dsrp.source, dsrp.target, dbatoms)
        num = atomhandling.NumberScheme(self.reslist, dbatoms, dsrp)
        # returns also the atom names if residue is active
        fragment_numberscheme = num.get_fragment_number_scheme()
        print('Fragment atom names: {}'.format(', '.join(fragment_numberscheme)))
        dfix_head = ''
        if dsrp.dfix:
            restr = Restraints(self.fragment, self.gdb)
            dfix_12 = restr.get_formated_12_dfixes()
            dfix_13 = restr.get_formated_13_dfixes()
            flats = restr.get_formated_flats()
            restraints = dfix_12 + dfix_13 + flats
        # ##########Not using SHELXL for fragment fit: ###########

        print("--- Using fast fragment fit ---")
        if self.options.target_coords:
            target_coords = chunks(self.options.target_coords, 3)
        else:
            # {'C1': ['1.123', '0.7456', '3.245']}
            target_coordinates = find_atoms.get_atomcoordinates(dsrp.target)
            target_coords = [target_coordinates[key] for key in dsrp.target]
        # Uppercase is important here to avoid KeyErrors in source_atoms generation
        atnames = self.gdb.get_atomnames(self.fragment, uppercase=True)
        source_atoms = dict(zip(atnames, self.gdb.get_coordinates(self.fragment, cartesian=True, invert=self.invert)))
        # Coordinates only from the source, not the entire fragment:
        source_coords = [source_atoms[x] for x in dsrp.source]
        target_coords = [frac_to_cart(x, rle.get_cell()) for x in target_coords]
        from rmsd import fit_fragment
        # The source and target atom coordinates are fitted first. Then The complete fragment
        # is rotated and translated to the target position as calculated before.
        # parameter cartiesian has to be false here:
        fragment_coords = self.gdb.get_coordinates(self.fragment, cartesian=False, invert=self.invert)
        fitted_fragment, rmsd = fit_fragment(fragment_coords,
                                             source_atoms=source_coords,
                                             target_atoms=target_coords)
        # Moving back to the position of the first atom to have a reference:
        import numpy as np
        from rmsd import centroid
        # I have to make sure that I use the centroid of the correct atoms from target and source,
        # otherwise the fragment is shifted to a wrong position.
        # The third atom from the fragment e.g. has to be the third from the fragment to get
        # the correct centroid:
        center_difference = centroid(np.array(target_coords)) - \
                            centroid(np.array([list(fitted_fragment)[atnames.index(dsrp.source[x])]
                                               for x in range(len(source_coords))]))
        # finishing shift to correct centroid:
        fitted_fragment += center_difference
        # Or even lower than 0.1?
        if rmsd < 0.1:
            print('Fragment fit successful with RMSD of: {:8.3}'.format(rmsd))
        else:
            print('*** Fragment fit might have failed with RMSD of: {:8.3} ***'.format(rmsd))
        fitted_fragment = [cart_to_frac(x, rle.get_cell()) for x in fitted_fragment]
        afix_entry = []
        e2s = Elem_2_Sfac(sfac_table)
        for at, coord, atype in zip(fragment_numberscheme, fitted_fragment, db_atom_types):
            sfac_num = str(e2s.elem_2_sfac(atype))
            if dsrp.occupancy:
                occ = float(dsrp.occupancy)
            else:
                occ = 11.0
            afix_entry.append(isoatomstr.format(at, sfac_num, coord[0], coord[1], coord[2], occ, 0.03))
        afix_entry = "\n".join(afix_entry)
        new_atomnames = list(reversed(fragment_numberscheme))
        same_resi = ''
        if not dsrp.resiflag:
            restraints = rename_restraints_atoms(new_atomnames, self.gdb.get_atomnames(self.fragment), restraints)
        else:
            restraints = resi.format_restraints(restraints)
            # SADI\n
            same_resi = ["SAME_{} {} > {}\n".format(resi.get_residue_class, new_atomnames[-1], new_atomnames[0])]
        # Adds a "SAME_resiclass firstatom > lastatom" to the afix:
        if not self.options.rigid_group:
            restraints += same_resi
            # if dsrp.resiflag:  # <- Or should I do this?
            restraints += ["SIMU 0.04 0.08 1"]
        if not options.external_restr:
            restraints = remove_duplicate_restraints(self.reslist, restraints, resi.get_residue_class)
        restraints = wrap_headlines(restraints)
        dfx_file_name = ''
        if dsrp.part:
            afix_entry = "PART {}  {}\n".format(dsrp.part, dsrp.occupancy) + afix_entry + "\nPART 0"
        if dsrp.resiflag:
            afix_entry = 'RESI {} {}\n{}\nRESI 0'.format(resi.get_residue_class, resi.get_resinumber, afix_entry)
        if self.options.rigid_group:
            afix_entry = 'AFIX 9\n' + afix_entry
        if options.external_restr and not self.rigid:
            pname, ext = os.path.splitext(basefilename + '.dfix')
            if dsrp.dfix:
                dfx_file_name = pname + "_dfx" + ext
            else:
                dfx_file_name = pname + ext
            dfx_file_name = write_dbhead_to_file(dsrp, dfx_file_name, restraints, resi.get_residue_class,
                                                 resi.get_resinumber)
            if dsrp.resiflag:
                restraints = 'REM Restraints for residue {}:\n+{}\n' \
                    .format(resi.get_residue_class, dfx_file_name)
            else:
                restraints = 'REM Restraints for DSR fragment:\n+{}\n' \
                    .format(dfx_file_name)
        if self.options.rigid_group:
            afix_entry += '\nAFIX 0\n'

        # Adds the origin of restraints and fragment to res file:
        import textwrap
        source = textwrap.wrap("REM Restraints for Fragment {}, {} from: {}. "
                               "Please cite https://doi.org/10.1107/S1600576718004508".format(
            self.fragment,
            self.gdb.get_fragment_name(self.fragment),
            self.gdb.get_src(self.fragment)),
            width=74, subsequent_indent='REM ')
        source = '\n'.join(source) + '\n'
        # check if restraints already inserted:
        for line in self.reslist:
            try:
                if line.split()[4] == self.fragment + ',':
                    source = ''
                    break
            except IndexError:
                continue
        # + 'AFIX 0\n' before hklf seems to be not needed after shelx-2013:
        self.reslist[dsrp.hklf_line - 1] = self.reslist[dsrp.hklf_line - 1] + afix_entry + '\n'
        if not self.rigid:
            self.reslist[dsrp.unit_line] = self.reslist[dsrp.unit_line] + source + ''.join(restraints)

        # write to file:
        self.rl.write_resfile(self.reslist, '.res')
        if dsrp.command == 'REPLACE':
            print("Replace mode active\n")
            self.rl = ResList(self.res_file)
            reslist = self.rl.get_res_list()
            self.reslist, find_atoms = atomhandling.replace_after_fit(self.rl, reslist, resi,
                                                                      fragment_numberscheme, rle.get_cell())
            self.rl.write_resfile(self.reslist, '.res')
        os.remove(shx.backup_file)
Exemple #33
0
              [2.0, 1.5]])

# Same "molecule"
B = np.array([[1.0, 1.0],
              [1.0, 2.0],
              [2.0, 1.5]])

B *= 1.4

# Translate
B -= 3

# Rotate
B = np.dot(B, rotation_matrix(90))

print("Normal RMSD", rmsd.rmsd(A, B))
save_plot(A, B, "plot_beginning.png")

# Manipulate
A -= rmsd.centroid(A)
B -= rmsd.centroid(B)

print("Centered RMSD", rmsd.rmsd(A, B))
save_plot(A, B, "plot_centered.png")

U = rmsd.kabsch(A, B)
A = np.dot(A, U)

print("Translated RMSD", rmsd.rmsd(A, B))
save_plot(A, B, "plot_translated.png")