Beispiel #1
0
def rmatrixu(u, theta):
    """Return a rotation matrix caused by a right hand rotation of theta
    radians around vector u.
    """
    if numpy.allclose(theta, 0.0) or numpy.allclose(numpy.dot(u, u), 0.0):
        return numpy.identity(3, float)

    x, y, z = normalize(u)
    sa = math.sin(theta)
    ca = math.cos(theta)

    R = numpy.array([[
        1.0 + (1.0 - ca) * (x * x - 1.0), -z * sa +
        (1.0 - ca) * x * y, y * sa + (1.0 - ca) * x * z
    ],
                     [
                         z * sa + (1.0 - ca) * x * y, 1.0 + (1.0 - ca) *
                         (y * y - 1.0), -x * sa + (1.0 - ca) * y * z
                     ],
                     [
                         -y * sa + (1.0 - ca) * x * z, x * sa +
                         (1.0 - ca) * y * z, 1.0 + (1.0 - ca) * (z * z - 1.0)
                     ]], float)

    try:
        assert numpy.allclose(linalg.determinant(R), 1.0)
    except AssertionError:
        print "rmatrixu(%s, %f) determinant(R)=%f" % (u, theta,
                                                      linalg.determinant(R))
        raise

    return R
Beispiel #2
0
def rmatrixz(vec):
    """Return a rotation matrix which transforms the coordinate system
    such that the vector vec is aligned along the z axis.
    """
    u, v, w = normalize(vec)

    d = math.sqrt(u*u + v*v)

    if d != 0.0:
        Rxz = numpy.array([ [  u/d, v/d,  0.0 ],
                            [ -v/d, u/d,  0.0 ],
                            [  0.0, 0.0,  1.0 ] ], float)
    else:
        Rxz = numpy.identity(3, float)


    Rxz2z = numpy.array([ [   w, 0.0,    -d],
                          [ 0.0, 1.0,   0.0],
                          [   d, 0.0,     w] ], float)

    R = numpy.dot(Rxz2z, Rxz)

    try:
        assert numpy.allclose(linalg.determinant(R), 1.0)
    except AssertionError:
        print "rmatrixz(%s) determinant(R)=%f" % (vec, linalg.determinant(R))
        raise

    return R
Beispiel #3
0
def rmatrixz(vec):
    """Return a rotation matrix which transforms the coordinate system
    such that the vector vec is aligned along the z axis.
    """
    u, v, w = normalize(vec)

    d = math.sqrt(u * u + v * v)

    if d != 0.0:
        Rxz = numpy.array(
            [[u / d, v / d, 0.0], [-v / d, u / d, 0.0], [0.0, 0.0, 1.0]],
            float)
    else:
        Rxz = numpy.identity(3, float)

    Rxz2z = numpy.array([[w, 0.0, -d], [0.0, 1.0, 0.0], [d, 0.0, w]], float)

    R = numpy.dot(Rxz2z, Rxz)

    try:
        assert numpy.allclose(linalg.determinant(R), 1.0)
    except AssertionError:
        print "rmatrixz(%s) determinant(R)=%f" % (vec, linalg.determinant(R))
        raise

    return R
Beispiel #4
0
def calc_inertia_tensor(atom_iter, origin):
    """Calculate a moment-of-inertia tensor at the given origin assuming all
    atoms have the same mass.
    """
    I = numpy.zeros((3, 3), float)

    for atm in atom_iter:
        x = atm.position - origin

        I[0, 0] += x[1]**2 + x[2]**2
        I[1, 1] += x[0]**2 + x[2]**2
        I[2, 2] += x[0]**2 + x[1]**2

        I[0, 1] += -x[0] * x[1]
        I[1, 0] += -x[0] * x[1]

        I[0, 2] += -x[0] * x[2]
        I[2, 0] += -x[0] * x[2]

        I[1, 2] += -x[1] * x[2]
        I[2, 1] += -x[1] * x[2]

    evals, evecs = linalg.eigenvectors(I)

    ## order the tensor such that the largest
    ## principal component is along the z-axis, and
    ## the second largest is along the y-axis
    if evals[0] >= evals[1] and evals[0] >= evals[2]:
        if evals[1] >= evals[2]:
            R = numpy.array((evecs[2], evecs[1], evecs[0]), float)
        else:
            R = numpy.array((evecs[1], evecs[2], evecs[0]), float)

    elif evals[1] >= evals[0] and evals[1] >= evals[2]:
        if evals[0] >= evals[2]:
            R = numpy.array((evecs[2], evecs[0], evecs[1]), float)
        else:
            R = numpy.array((evecs[0], evecs[2], evecs[1]), float)

    elif evals[2] >= evals[0] and evals[2] >= evals[1]:
        if evals[0] >= evals[1]:
            R = numpy.array((evecs[1], evecs[0], evecs[2]), float)
        else:
            R = numpy.array((evecs[0], evecs[1], evecs[2]), float)

    ## make sure the tensor is right-handed
    if numpy.allclose(linalg.determinant(R), -1.0):
        I = numpy.identity(3, float)
        I[0, 0] = -1.0
        R = numpy.dot(I, R)

    assert numpy.allclose(linalg.determinant(R), 1.0)
    return R
def calc_CCuij(U, V):
    """Calculate the cooralation coefficent for anisotropic ADP tensors U
    and V.
    """
    invU = linalg.inverse(U)
    invV = linalg.inverse(V)

    det_invU = linalg.determinant(invU)
    det_invV = linalg.determinant(invV)

    return (math.sqrt(math.sqrt(det_invU * det_invV)) / math.sqrt(
        (1.0 / 8.0) * linalg.determinant(invU + invV)))
Beispiel #6
0
def calc_inertia_tensor(atom_iter, origin):
    """Calculate a moment-of-inertia tensor at the given origin assuming all
    atoms have the same mass.
    """
    I = numpy.zeros((3,3), float)
    
    for atm in atom_iter:
        x = atm.position - origin

        I[0,0] += x[1]**2 + x[2]**2
        I[1,1] += x[0]**2 + x[2]**2
        I[2,2] += x[0]**2 + x[1]**2

        I[0,1] += - x[0]*x[1]
        I[1,0] += - x[0]*x[1]

        I[0,2] += - x[0]*x[2]
        I[2,0] += - x[0]*x[2]

        I[1,2] += - x[1]*x[2]
        I[2,1] += - x[1]*x[2]

    evals, evecs = linalg.eigenvectors(I)

    ## order the tensor such that the largest
    ## principal component is along the z-axis, and
    ## the second largest is along the y-axis
    if evals[0] >= evals[1] and evals[0] >= evals[2]:
        if evals[1] >= evals[2]:
            R = numpy.array((evecs[2], evecs[1], evecs[0]), float)
        else:
            R = numpy.array((evecs[1], evecs[2], evecs[0]), float)

    elif evals[1] >= evals[0] and evals[1] >= evals[2]:
        if evals[0] >= evals[2]:
            R = numpy.array((evecs[2], evecs[0], evecs[1]), float)
        else:
            R = numpy.array((evecs[0], evecs[2], evecs[1]), float)

    elif evals[2] >= evals[0] and evals[2] >= evals[1]:
        if evals[0] >= evals[1]:
            R = numpy.array((evecs[1], evecs[0], evecs[2]), float)
        else:
            R = numpy.array((evecs[0], evecs[1], evecs[2]), float)

    ## make sure the tensor is right-handed
    if numpy.allclose(linalg.determinant(R), -1.0):
        I = numpy.identity(3, float)
        I[0,0] = -1.0
        R = numpy.dot(I, R)

    assert numpy.allclose(linalg.determinant(R), 1.0)
    return R
Beispiel #7
0
def calc_CCuij(U, V):
    """Calculate the correlation coefficient for anisotropic ADP tensors U
    and V.
    """
    ## FIXME: Check for non-positive Uij's, 2009-08-19
    invU = linalg.inverse(U)
    invV = linalg.inverse(V)
    #invU = internal_inv3x3(U)
    #invV = internal_inv3x3(V)
    
    det_invU = linalg.determinant(invU)
    det_invV = linalg.determinant(invV)

    return ( math.sqrt(math.sqrt(det_invU * det_invV)) /
             math.sqrt((1.0/8.0) * linalg.determinant(invU + invV)) )
Beispiel #8
0
def calc_CCuij(U, V):
    """Calculate the correlation coefficient for anisotropic ADP tensors U
    and V.
    """
    ## FIXME: Check for non-positive Uij's, 2009-08-19
    invU = linalg.inverse(U)
    invV = linalg.inverse(V)
    #invU = internal_inv3x3(U)
    #invV = internal_inv3x3(V)

    det_invU = linalg.determinant(invU)
    det_invV = linalg.determinant(invV)

    return (math.sqrt(math.sqrt(det_invU * det_invV)) / math.sqrt(
        (1.0 / 8.0) * linalg.determinant(invU + invV)))
Beispiel #9
0
    def matrix_is_symplectic(self, m, tolerance=1.0e-12):
        """

        Confirm that a given matrix $M$ is symplectic to within
        numerical tolerance.

        This is done by taking the 4 submatrices:

         1. $A = M[0::2, 0::2]$, i.e., configuration coordinates only,

         2. $B = M[0::2, 1::2]$, i.e., configuration rows, momenta cols,

         3. $C = M[1::2, 0::2]$, i.e., momenta rows, configuration cols,

         4. $D = M[1::2, 1::2]$, i.e., momenta only,

        and verifying the following symplectic identities:-
        
         1. $MJM^{T} = J$, the $2n\\times 2n$ sympletic matrix,
        
         2. $AD^{T}-BC^{T} = I$, the $n\\times n$ identity,
            
         3. $AB^{T}-BA^{T} = Z$, the $n\\times n$ zero,
            
         4. $CD^{T}-DC^{T} = Z$.

        Finally, we confirm that $\\det{M} = 1$.

        """
        det = determinant(m)
        j = self.skew_symmetric_matrix()
        approx_j = matrixmultiply(m, matrixmultiply(j, transpose(m)))
        a = m[0::2, 0::2] #even, even
        b = m[0::2, 1::2] #even, odd
        c = m[1::2, 0::2] #odd, even
        d = m[1::2, 1::2] #odd, odd
        i = self.identity_matrix(self.dof())
        approx_i = matrixmultiply(a, transpose(d)) - matrixmultiply(b, transpose(c))
        approx_z0 = matrixmultiply(a, transpose(b)) - matrixmultiply(b, transpose(a))
        approx_z1 = matrixmultiply(c, transpose(d)) - matrixmultiply(d, transpose(c))
        norm = self.matrix_norm
        logger.info('Matrix from diagonal to equilibrium coordinates:')
        logger.info('[output supressed]') #logger.info(m)
        logger.info('error in determinant:            %s', abs(det-1.0))
        logger.info('error in symplectic identity #1: %s', norm(approx_j - j))
        logger.info('error in symplectic identity #2: %s', norm(approx_i - i))
        logger.info('error in symplectic identity #3: %s', norm(approx_z0))
        logger.info('error in symplectic identity #4: %s', norm(approx_z1))
        okay = True
        if not (abs(det-1.0) < tolerance):
            okay = False
        if not (norm(approx_j - j) < tolerance):
            okay = False
        if not (norm(approx_i - i) < tolerance):
            okay = False
        if not (norm(approx_z0) < tolerance):
            okay = False
        if not (norm(approx_z1) < tolerance):
            okay = False
        return okay
Beispiel #10
0
def rmatrixquaternion(q):
    """Create a rotation matrix from q quaternion rotation.
    Quaternions are typed as Numeric Python numpy.arrays of length 4.
    """
    assert numpy.allclose(math.sqrt(numpy.dot(q, q)), 1.0)

    x, y, z, w = q

    xx = x * x
    xy = x * y
    xz = x * z
    xw = x * w
    yy = y * y
    yz = y * z
    yw = y * w
    zz = z * z
    zw = z * w

    r00 = 1.0 - 2.0 * (yy + zz)
    r01 = 2.0 * (xy - zw)
    r02 = 2.0 * (xz + yw)

    r10 = 2.0 * (xy + zw)
    r11 = 1.0 - 2.0 * (xx + zz)
    r12 = 2.0 * (yz - xw)

    r20 = 2.0 * (xz - yw)
    r21 = 2.0 * (yz + xw)
    r22 = 1.0 - 2.0 * (xx + yy)

    R = numpy.array([[r00, r01, r02], [r10, r11, r12], [r20, r21, r22]], float)

    assert numpy.allclose(linalg.determinant(R), 1.0)
    return R
Beispiel #11
0
def calc_DP2uij(U, V):
    """Calculate the square of the volumetric difference in the probability
    density function of anisotropic ADP tensors U and V.
    """
    invU = linalg.inverse(U)
    invV = linalg.inverse(V)

    det_invU = linalg.determinant(invU)
    det_invV = linalg.determinant(invV)

    Pu2 = math.sqrt( det_invU / (64.0 * Constants.PI3) )
    Pv2 = math.sqrt( det_invV / (64.0 * Constants.PI3) )
    Puv = math.sqrt(
        (det_invU * det_invV) / (8.0*Constants.PI3 * linalg.determinant(invU + invV)))

    dP2 = Pu2 + Pv2 - (2.0 * Puv)
    
    return dP2
Beispiel #12
0
def calc_DP2uij(U, V):
    """Calculate the square of the volumetric difference in the probability
    density function of anisotropic ADP tensors U and V.
    """
    invU = linalg.inverse(U)
    invV = linalg.inverse(V)

    det_invU = linalg.determinant(invU)
    det_invV = linalg.determinant(invV)

    Pu2 = math.sqrt(det_invU / (64.0 * Constants.PI3))
    Pv2 = math.sqrt(det_invV / (64.0 * Constants.PI3))
    Puv = math.sqrt((det_invU * det_invV) /
                    (8.0 * Constants.PI3 * linalg.determinant(invU + invV)))

    dP2 = Pu2 + Pv2 - (2.0 * Puv)

    return dP2
Beispiel #13
0
def rmatrixu(u, theta):
    """Return a rotation matrix caused by a right hand rotation of theta
    radians around vector u.
    """
    if numpy.allclose(theta, 0.0) or numpy.allclose(numpy.dot(u,u), 0.0):
        return numpy.identity(3, float)

    x, y, z = normalize(u)
    sa = math.sin(theta)
    ca = math.cos(theta)

    R = numpy.array(
        [[1.0+(1.0-ca)*(x*x-1.0), -z*sa+(1.0-ca)*x*y,     y*sa+(1.0-ca)*x*z],
         [z*sa+(1.0-ca)*x*y,      1.0+(1.0-ca)*(y*y-1.0), -x*sa+(1.0-ca)*y*z],
         [-y*sa+(1.0-ca)*x*z,     x*sa+(1.0-ca)*y*z,      1.0+(1.0-ca)*(z*z-1.0)]], float)

    try:
        assert numpy.allclose(linalg.determinant(R), 1.0)
    except AssertionError:
        print "rmatrixu(%s, %f) determinant(R)=%f" % (
            u, theta, linalg.determinant(R))
        raise
    
    return R
 def _gaussian(self, mean, cvm, x):
     m = len(mean)
     assert cvm.shape == (m, m), \
         'bad sized covariance matrix, %s' % str(cvm.shape)
     try:
         det = LinearAlgebra.determinant(cvm)
         inv = LinearAlgebra.inverse(cvm)
         a = det ** -0.5 * (2 * Numeric.pi) ** (-m / 2.0) 
         dx = x - mean
         b = -0.5 * Numeric.matrixmultiply( \
                 Numeric.matrixmultiply(dx, inv), dx)
         return a * Numeric.exp(b) 
     except OverflowError:
         # happens when the exponent is negative infinity - i.e. b = 0
         # i.e. the inverse of cvm is huge (cvm is almost zero)
         return 0
Beispiel #15
0
def rmatrix(alpha, beta, gamma):
    """Return a rotation matrix based on the Euler angles alpha,
    beta, and gamma in radians.
    """
    cosA = math.cos(alpha)
    cosB = math.cos(beta)
    cosG = math.cos(gamma)

    sinA = math.sin(alpha)
    sinB = math.sin(beta)
    sinG = math.sin(gamma)
    
    R = numpy.array(
        [[cosB*cosG, cosG*sinA*sinB-cosA*sinG, cosA*cosG*sinB+sinA*sinG],
         [cosB*sinG, cosA*cosG+sinA*sinB*sinG, cosA*sinB*sinG-cosG*sinA ],
         [-sinB,     cosB*sinA,                cosA*cosB ]], float)

    assert numpy.allclose(linalg.determinant(R), 1.0)
    return R
Beispiel #16
0
def quaternionrmatrix(R):
    """Return a quaternion calculated from the argument rotation matrix R.
    """
    assert numpy.allclose(linalg.determinant(R), 1.0)

    t = numpy.trace(R) + 1.0

    if t > 1e-5:
        w = math.sqrt(1.0 + numpy.trace(R)) / 2.0
        w4 = 4.0 * w

        x = (R[2, 1] - R[1, 2]) / w4
        y = (R[0, 2] - R[2, 0]) / w4
        z = (R[1, 0] - R[0, 1]) / w4

    else:
        if R[0, 0] > R[1, 1] and R[0, 0] > R[2, 2]:
            S = math.sqrt(1.0 + R[0, 0] - R[1, 1] - R[2, 2]) * 2.0
            x = 0.25 * S
            y = (R[0, 1] + R[1, 0]) / S
            z = (R[0, 2] + R[2, 0]) / S
            w = (R[1, 2] - R[2, 1]) / S
        elif R[1, 1] > R[2, 2]:
            S = math.sqrt(1.0 + R[1, 1] - R[0, 0] - R[2, 2]) * 2.0
            x = (R[0, 1] + R[1, 0]) / S
            y = 0.25 * S
            z = (R[1, 2] + R[2, 1]) / S
            w = (R[0, 2] - R[2, 0]) / S
        else:
            S = math.sqrt(1.0 + R[2, 2] - R[0, 0] - R[1, 1]) * 2
            x = (R[0, 2] + R[2, 0]) / S
            y = (R[1, 2] + R[2, 1]) / S
            z = 0.25 * S
            w = (R[0, 1] - R[1, 0]) / S

    q = numpy.array((x, y, z, w), float)
    assert numpy.allclose(math.sqrt(numpy.dot(q, q)), 1.0)
    return q
Beispiel #17
0
def quaternionrmatrix(R):
    """Return a quaternion calculated from the argument rotation matrix R.
    """
    assert numpy.allclose(linalg.determinant(R), 1.0)

    t = numpy.trace(R) + 1.0

    if t>1e-5:
        w = math.sqrt(1.0 + numpy.trace(R)) / 2.0
        w4 = 4.0 * w

        x = (R[2,1] - R[1,2]) / w4
        y = (R[0,2] - R[2,0]) / w4
        z = (R[1,0] - R[0,1]) / w4
        
    else:
        if R[0,0]>R[1,1] and R[0,0]>R[2,2]: 
            S = math.sqrt(1.0 + R[0,0] - R[1,1] - R[2,2]) * 2.0
            x = 0.25 * S
            y = (R[0,1] + R[1,0]) / S 
            z = (R[0,2] + R[2,0]) / S 
            w = (R[1,2] - R[2,1]) / S
        elif R[1,1]>R[2,2]: 
            S = math.sqrt(1.0 + R[1,1] - R[0,0] - R[2,2]) * 2.0; 
            x = (R[0,1] + R[1,0]) / S; 
            y = 0.25 * S;
            z = (R[1,2] + R[2,1]) / S; 
            w = (R[0,2] - R[2,0]) / S;
        else:
            S = math.sqrt(1.0 + R[2,2] - R[0,0] - R[1,1]) * 2; 
            x = (R[0,2] + R[2,0]) / S; 
            y = (R[1,2] + R[2,1]) / S; 
            z = 0.25 * S;
            w = (R[0,1] - R[1,0] ) / S;

    q = numpy.array((x, y, z, w), float)
    assert numpy.allclose(math.sqrt(numpy.dot(q,q)), 1.0)    
    return q
Beispiel #18
0
def rmatrix(alpha, beta, gamma):
    """Return a rotation matrix based on the Euler angles alpha,
    beta, and gamma in radians.
    """
    cosA = math.cos(alpha)
    cosB = math.cos(beta)
    cosG = math.cos(gamma)

    sinA = math.sin(alpha)
    sinB = math.sin(beta)
    sinG = math.sin(gamma)

    R = numpy.array([[
        cosB * cosG, cosG * sinA * sinB - cosA * sinG,
        cosA * cosG * sinB + sinA * sinG
    ],
                     [
                         cosB * sinG, cosA * cosG + sinA * sinB * sinG,
                         cosA * sinB * sinG - cosG * sinA
                     ], [-sinB, cosB * sinA, cosA * cosB]], float)

    assert numpy.allclose(linalg.determinant(R), 1.0)
    return R
Beispiel #19
0
def rmatrixquaternion(q):
    """Create a rotation matrix from q quaternion rotation.
    Quaternions are typed as Numeric Python numpy.arrays of length 4.
    """
    assert numpy.allclose(math.sqrt(numpy.dot(q,q)), 1.0)
    
    x, y, z, w = q

    xx = x*x
    xy = x*y
    xz = x*z
    xw = x*w
    yy = y*y
    yz = y*z
    yw = y*w
    zz = z*z
    zw = z*w

    r00 = 1.0 - 2.0 * (yy + zz)
    r01 =       2.0 * (xy - zw)
    r02 =       2.0 * (xz + yw)

    r10 =       2.0 * (xy + zw)
    r11 = 1.0 - 2.0 * (xx + zz) 
    r12 =       2.0 * (yz - xw)

    r20 =       2.0 * (xz - yw)
    r21 =       2.0 * (yz + xw)
    r22 = 1.0 - 2.0 * (xx + yy)

    R = numpy.array([[r00, r01, r02],
               [r10, r11, r12],
               [r20, r21, r22]], float)
    
    assert numpy.allclose(linalg.determinant(R), 1.0)
    return R
Beispiel #20
0
    def matrix_is_symplectic(self, m, tolerance=1.0e-12):
        """

        Confirm that a given matrix $M$ is symplectic to within
        numerical tolerance.

        This is done by taking the 4 submatrices:

         1. $A = M[0::2, 0::2]$, i.e., configuration coordinates only,

         2. $B = M[0::2, 1::2]$, i.e., configuration rows, momenta cols,

         3. $C = M[1::2, 0::2]$, i.e., momenta rows, configuration cols,

         4. $D = M[1::2, 1::2]$, i.e., momenta only,

        and verifying the following symplectic identities:-
        
         1. $MJM^{T} = J$, the $2n\\times 2n$ sympletic matrix,
        
         2. $AD^{T}-BC^{T} = I$, the $n\\times n$ identity,
            
         3. $AB^{T}-BA^{T} = Z$, the $n\\times n$ zero,
            
         4. $CD^{T}-DC^{T} = Z$.

        Finally, we confirm that $\\det{M} = 1$.

        """
        det = determinant(m)
        j = self.skew_symmetric_matrix()
        approx_j = matrixmultiply(m, matrixmultiply(j, transpose(m)))
        a = m[0::2, 0::2]  #even, even
        b = m[0::2, 1::2]  #even, odd
        c = m[1::2, 0::2]  #odd, even
        d = m[1::2, 1::2]  #odd, odd
        i = self.identity_matrix(self.dof())
        approx_i = matrixmultiply(a, transpose(d)) - matrixmultiply(
            b, transpose(c))
        approx_z0 = matrixmultiply(a, transpose(b)) - matrixmultiply(
            b, transpose(a))
        approx_z1 = matrixmultiply(c, transpose(d)) - matrixmultiply(
            d, transpose(c))
        norm = self.matrix_norm
        logger.info('Matrix from diagonal to equilibrium coordinates:')
        logger.info('[output supressed]')  #logger.info(m)
        logger.info('error in determinant:            %s', abs(det - 1.0))
        logger.info('error in symplectic identity #1: %s', norm(approx_j - j))
        logger.info('error in symplectic identity #2: %s', norm(approx_i - i))
        logger.info('error in symplectic identity #3: %s', norm(approx_z0))
        logger.info('error in symplectic identity #4: %s', norm(approx_z1))
        okay = True
        if not (abs(det - 1.0) < tolerance):
            okay = False
        if not (norm(approx_j - j) < tolerance):
            okay = False
        if not (norm(approx_i - i) < tolerance):
            okay = False
        if not (norm(approx_z0) < tolerance):
            okay = False
        if not (norm(approx_z1) < tolerance):
            okay = False
        return okay