Example #1
0
def alignRotation(XA, XB):
    """
    Align structure XB with XA

    Align structure XB to be as similar as possible to structure XA.
    To be precise, rotate XB, so as to minimize the distance |XA - XB|.

    Rotations will be done around the origin, not the center of mass
    """
    nsites = len(XA) / 3

    dist, Q2 = getAlignRotation(XA, XB)
    ###################################################################
    # Q2 contains the quaternion which rotates XB to best align with X1.
    # rotate XB according to Q2
    ###################################################################

    rot_mx = rot.q2mx(Q2)
    #print rot_mx
    for j in range(nsites):
        i = 3 * j
        XB[i:i + 3] = np.dot(rot_mx, XB[i:i + 3])

    dist = np.linalg.norm(XA - XB)  #more precise than what it returned

    return dist, XB
Example #2
0
def alignRotation(XA, XB):
    """
    Align structure XB with XA

    Align structure XB to be as similar as possible to structure XA.
    To be precise, rotate XB, so as to minimize the distance |XA - XB|.

    Rotations will be done around the origin, not the center of mass
    """
    nsites = len(XA)/3

    dist, Q2 = getAlignRotation(XA, XB)
    ###################################################################
    # Q2 contains the quaternion which rotates XB to best align with X1.
    # rotate XB according to Q2
    ###################################################################

    rot_mx = rot.q2mx( Q2 )
    #print rot_mx
    for j in range(nsites):
        i = 3*j
        XB[i:i+3] = np.dot( rot_mx, XB[i:i+3] )
    
    dist = np.linalg.norm(XA - XB) #more precise than what it returned

    return dist, XB
def _optimizePermRot(X1, X2, niter, permlist, verbose=False, use_quench=True):
    if use_quench:
        pot = MinPermDistPotential(X1, X2.copy(), permlist=permlist)

    distbest = getDistxyz(X1, X2)
    mxbest = np.identity(3)
    X20 = X2.copy()
    for i in range(niter):
        #get and apply a random rotation
        aa = random_aa()
        if not use_quench:
            mx = aa2mx(aa)
            mxtot = mx
            #print "X2.shape", X2.shape
        else:
            #optimize the rotation using a permutationally invariand distance metric
            ret = defaults.quenchRoutine(aa, pot.getEnergyGradient, tol=0.01)
            aa1 = ret[0]
            mx1 = aa2mx(aa1)
            mxtot = mx1
        X2 = applyRotation(mxtot, X20)

        #optimize the permutations
        dist, X1, X2 = findBestPermutation(X1, X2, permlist)
        if verbose:
            print "dist", dist, "distbest", distbest
        #print "X2.shape", X2.shape

        #optimize the rotation
        dist, Q2 = getAlignRotation(X1, X2)
        #        print "dist", dist, "Q2", Q2
        mx2 = q2mx(Q2)
        mxtot = np.dot(mx2, mxtot)

        if dist < distbest:
            distbest = dist
            mxbest = mxtot
    return distbest, mxbest
Example #4
0
def _optimizePermRot(X1, X2, niter, permlist, verbose=False, use_quench=True):
    if use_quench:
        pot = MinPermDistPotential(X1, X2.copy(), permlist=permlist)

    distbest = getDistxyz(X1, X2)
    mxbest = np.identity(3)
    X20 = X2.copy()
    for i in range(niter):
        #get and apply a random rotation
        aa = random_aa()
        if not use_quench:
            mx = aa2mx(aa)
            mxtot = mx
            #print "X2.shape", X2.shape
        else:
            #optimize the rotation using a permutationally invariand distance metric
            ret = defaults.quenchRoutine(aa, pot.getEnergyGradient, tol=0.01)
            aa1 = ret[0]
            mx1 = aa2mx(aa1)
            mxtot = mx1
        X2 = applyRotation(mxtot, X20)
        
        #optimize the permutations
        dist, X1, X2 = findBestPermutation(X1, X2, permlist)
        if verbose:
            print "dist", dist, "distbest", distbest
        #print "X2.shape", X2.shape
        
        #optimize the rotation
        dist, Q2 = getAlignRotation(X1, X2)
#        print "dist", dist, "Q2", Q2
        mx2 = q2mx(Q2)
        mxtot = np.dot(mx2, mxtot)
        
        if dist < distbest:
            distbest = dist
            mxbest = mxtot
    return distbest, mxbest
Example #5
0
        # now find best rotational alignment, this is more reliable than just
        # aligning the 2 reference atoms
        rot2 = rmsfit.findrotation_kabsch(x1n, x2n)
        x1n = np.dot(rot2, x1n.transpose()).transpose()

        # use the maximum distance, not rms as cutoff criterion
        max_dist = np.sqrt(np.sum((x1n - x2n) * (x1n - x2n), axis=1)).max()
        if max_dist < self.accuracy:
            self.best_rotation = np.dot(rot2, rot)
            return True
        return False


if __name__ == "__main__":
    natoms = 35
    from pygmin.utils import rotations

    for i in xrange(100):
        xx1 = np.random.random(3 * natoms) * 5
        xx1 = xx1.reshape([-1, 3])
        mx = rotations.q2mx(rotations.random_q())
        xx2 = np.dot(mx, xx1.transpose()).transpose()
        xx2 += 2.0 * (np.random.random(xx2.shape) - 0.5) * 0.003
        # xx2 = xx1.copy()
        tmp = xx2[1].copy()
        xx2[1] = xx2[4]
        xx2[4] = tmp
        # dist, x1n, x2n = findBestPermutation(xx1.flatten(), xx2.flatten())
        # print dist
        print i, ExactMatchCluster()(xx1, xx2)
Example #6
0
def findrotation_kearsley(coords1, coords2, align_com=True):
    """
    Return the quaternion which aligns XB with XA
    
    Return the matrix which
    aligns structure XB to be as similar as possible to structure XA.
    To be precise, rotate XB, so as to minimize the distance |XA - XB|.

    Rotations will be done around the origin, not the center of mass

    Rotational alignment follows the prescription of
    Kearsley, Acta Cryst. A, 45, 208-210, 1989
    http://dx.doi.org/10.1107/S0108767388010128
    """

    if(coords1.size != coords2.size):
        raise BaseException("dimension of arrays does not match")
    
    # reshape the arrays
    x1 = coords1.flatten()
    x2 = coords2.flatten()
    
    x1 = x1.reshape([-1,3])
    x2 = x2.reshape([-1,3])
#    
#    # determine number of atoms
    natoms = x1.shape[0]
    
    # set both com to zero
    if(align_com):
        com1 = np.sum(x1,axis=0) / float(natoms)
        com2 = np.sum(x2,axis=0) / float(natoms)
        x1 = x1.copy() - com1
        x2 = x2.copy() - com2

    x1 = x1.flatten() 
    x2 = x2.flatten()
    
    # TODO: this is very dirty!
    #########################################
    #Create matrix QMAT
    #########################################

    QMAT = np.zeros([4,4], np.float64)
    for J1 in xrange(natoms):
        J2 = 3*(J1) -1
        XM = x1[J2+1] - x2[J2+1]
        YM = x1[J2+2] - x2[J2+2]
        ZM = x1[J2+3] - x2[J2+3]
        XP = x1[J2+1] + x2[J2+1]
        YP = x1[J2+2] + x2[J2+2]
        ZP = x1[J2+3] + x2[J2+3]
        QMAT[0,0] = QMAT[0,0] + XM**2 + YM**2 + ZM**2
        QMAT[0,1] = QMAT[0,1] - YP*ZM + YM*ZP
        QMAT[0,2] = QMAT[0,2] - XM*ZP + XP*ZM
        QMAT[0,3] = QMAT[0,3] - XP*YM + XM*YP
        QMAT[1,1] = QMAT[1,1] + YP**2 + ZP**2 + XM**2
        QMAT[1,2] = QMAT[1,2] + XM*YM - XP*YP
        QMAT[1,3] = QMAT[1,3] + XM*ZM - XP*ZP
        QMAT[2,2] = QMAT[2,2] + XP**2 + ZP**2 + YM**2
        QMAT[2,3] = QMAT[2,3] + YM*ZM - YP*ZP
        QMAT[3,3] = QMAT[3,3] + XP**2 + YP**2 + ZM**2

    QMAT[1,0] = QMAT[0,1]
    QMAT[2,0] = QMAT[0,2]
    QMAT[2,1] = QMAT[1,2]
    QMAT[3,0] = QMAT[0,3]
    QMAT[3,1] = QMAT[1,3]
    QMAT[3,2] = QMAT[2,3]

    ###########################################
    """
    Find eigenvalues and eigenvectors of QMAT.  The eigenvector corresponding
    to the smallest eigenvalue is the quaternion which rotates XB into best
    alignment with XA.  The smallest eigenvalue is the squared distance between
    the resulting structures.
    """
    ###########################################
    (eigs, vecs) = np.linalg.eig(QMAT)
    #print "eigenvalues", eigs

    imin = np.argmin(eigs)
    eigmin = eigs[imin] #the minimum eigenvector
    Q2 = vecs[:,imin]  #the eigenvector corresponding to the minimum eigenvalue
    if eigmin < 0.:
        if abs(eigmin) < 1e-6:
            eigmin = 0.
        else:
            print 'minDist> WARNING minimum eigenvalue is ',eigmin,' change to absolute value'
            eigmin = -eigmin

    dist = np.sqrt(eigmin) #this is the minimized distance between the two structures
    #print "dist from eigenvalue", dist
    #print "Q2", Q2, "norm", np.linalg.norm(Q2)
    #aa = rot.q2aa( Q2)
    #print "aa ", aa, "norm", np.linalg.norm(aa)

    return dist, rotations.q2mx(Q2)
Example #7
0
def findrotation_kearsley(coords1, coords2, align_com=True):
    """
    Return the quaternion which aligns XB with XA
    
    Return the matrix which
    aligns structure XB to be as similar as possible to structure XA.
    To be precise, rotate XB, so as to minimize the distance |XA - XB|.

    Rotations will be done around the origin, not the center of mass

    Rotational alignment follows the prescription of
    Kearsley, Acta Cryst. A, 45, 208-210, 1989
    http://dx.doi.org/10.1107/S0108767388010128
    """

    if (coords1.size != coords2.size):
        raise BaseException("dimension of arrays does not match")

    # reshape the arrays
    x1 = coords1.flatten()
    x2 = coords2.flatten()

    x1 = x1.reshape([-1, 3])
    x2 = x2.reshape([-1, 3])
    #
    #    # determine number of atoms
    natoms = x1.shape[0]

    # set both com to zero
    if (align_com):
        com1 = np.sum(x1, axis=0) / float(natoms)
        com2 = np.sum(x2, axis=0) / float(natoms)
        x1 = x1.copy() - com1
        x2 = x2.copy() - com2

    x1 = x1.flatten()
    x2 = x2.flatten()

    # TODO: this is very dirty!
    #########################################
    #Create matrix QMAT
    #########################################

    QMAT = np.zeros([4, 4], np.float64)
    for J1 in xrange(natoms):
        J2 = 3 * (J1) - 1
        XM = x1[J2 + 1] - x2[J2 + 1]
        YM = x1[J2 + 2] - x2[J2 + 2]
        ZM = x1[J2 + 3] - x2[J2 + 3]
        XP = x1[J2 + 1] + x2[J2 + 1]
        YP = x1[J2 + 2] + x2[J2 + 2]
        ZP = x1[J2 + 3] + x2[J2 + 3]
        QMAT[0, 0] = QMAT[0, 0] + XM**2 + YM**2 + ZM**2
        QMAT[0, 1] = QMAT[0, 1] - YP * ZM + YM * ZP
        QMAT[0, 2] = QMAT[0, 2] - XM * ZP + XP * ZM
        QMAT[0, 3] = QMAT[0, 3] - XP * YM + XM * YP
        QMAT[1, 1] = QMAT[1, 1] + YP**2 + ZP**2 + XM**2
        QMAT[1, 2] = QMAT[1, 2] + XM * YM - XP * YP
        QMAT[1, 3] = QMAT[1, 3] + XM * ZM - XP * ZP
        QMAT[2, 2] = QMAT[2, 2] + XP**2 + ZP**2 + YM**2
        QMAT[2, 3] = QMAT[2, 3] + YM * ZM - YP * ZP
        QMAT[3, 3] = QMAT[3, 3] + XP**2 + YP**2 + ZM**2

    QMAT[1, 0] = QMAT[0, 1]
    QMAT[2, 0] = QMAT[0, 2]
    QMAT[2, 1] = QMAT[1, 2]
    QMAT[3, 0] = QMAT[0, 3]
    QMAT[3, 1] = QMAT[1, 3]
    QMAT[3, 2] = QMAT[2, 3]

    ###########################################
    """
    Find eigenvalues and eigenvectors of QMAT.  The eigenvector corresponding
    to the smallest eigenvalue is the quaternion which rotates XB into best
    alignment with XA.  The smallest eigenvalue is the squared distance between
    the resulting structures.
    """
    ###########################################
    (eigs, vecs) = np.linalg.eig(QMAT)
    #print "eigenvalues", eigs

    imin = np.argmin(eigs)
    eigmin = eigs[imin]  #the minimum eigenvector
    Q2 = vecs[:,
              imin]  #the eigenvector corresponding to the minimum eigenvalue
    if eigmin < 0.:
        if abs(eigmin) < 1e-6:
            eigmin = 0.
        else:
            print 'minDist> WARNING minimum eigenvalue is ', eigmin, ' change to absolute value'
            eigmin = -eigmin

    dist = np.sqrt(
        eigmin)  #this is the minimized distance between the two structures
    #print "dist from eigenvalue", dist
    #print "Q2", Q2, "norm", np.linalg.norm(Q2)
    #aa = rot.q2aa( Q2)
    #print "aa ", aa, "norm", np.linalg.norm(aa)

    return dist, rotations.q2mx(Q2)
Example #8
0
    imin = np.argmin(eigs)
    eigmin = eigs[imin]  #the minimum eigenvector
    Q2 = vecs[:,
              imin]  #the eigenvector corresponding to the minimum eigenvalue
    if eigmin < 0.:
        if abs(eigmin) < 1e-6:
            eigmin = 0.
        else:
            print 'minDist> WARNING minimum eigenvalue is ', eigmin, ' change to absolute value'
            eigmin = -eigmin

    dist = np.sqrt(
        eigmin)  #this is the minimized distance between the two structures
    #print "dist from eigenvalue", dist
    #print "Q2", Q2, "norm", np.linalg.norm(Q2)
    #aa = rot.q2aa( Q2)
    #print "aa ", aa, "norm", np.linalg.norm(aa)

    return dist, rotations.q2mx(Q2)


findrotation = findrotation_kearsley

if __name__ == "__main__":
    from pygmin.utils import rotations
    x1 = np.random.random(24)
    mx = rotations.q2mx(rotations.random_q())

    x2 = np.dot(mx, x1.reshape(-1, 3).transpose()).transpose().reshape(-1)
    print x2 - x1
    print mx - findrotation_kabsch(x1, x2)