def test_can_transform_a_4_x_3_45degreezrotation(self):
     theta = numpy.pi/4.0        
     ans = array([[numpy.cos(theta), -1*numpy.sin(theta), 0.0000],
                  [numpy.sin(theta), numpy.cos(theta), 0.0000],
                  [0.0000, 0.0000, 1.0000]])
     a = array([[3.0000, 7.0000, 1.0000],
                [5.0000, 9.0000, 2.0000],
                [7.0000, 4.0000, 6.0000],
                [1.0000, 1.0000, 1.0000]])
     J = numpy.ones((4, 4))
     meana = numpy.dot(J,a)/4.0
     b = numpy.dot(a-meana,ans)
     rotation, _, _, _, _ = besttransformation(a, b)
     assert_almost_equal(ans, rotation)
     angle = angle_of_rotation(rotation)
     assert_almost_equal(angle, 45.0*numpy.pi/180.)
Beispiel #2
0
def discrepancy(ntlist1, ntlist2, centers=['base'], base_weights=1.0,
                P_weights=1.0, C1star_weights = 1.0, angleweight=1.0):
    """Compute the geometric discrepancy between two lists of components.

    :ntlist1: The first list of components.
    :ntlist2: The second list of components.
    :centers: A list of center names to use, such as
        ['base', 'P', 'C1*', 'ribose']
    :base_weights: The base weights to use. If only one weight is given
    it is used for all centers.  Otherwise, provide list of base weights with
    same length as the length of ntlist1
    :P_weigths: The phosphate weights to use. If only one weight is given
    it is used for all.  Otherwise, provide list of phosphate weights
    with same length as the length of ntlist1
    :C1star_weights: The C1* weights to use. If only one weight is given
    it is used for all.  Otherwise, provide list of C1* weights with
    same length as the length of ntlist1
    :angleweight: The weighting for angles to use.
    :returns: The geometric discrepancy.
    """

    assert len(ntlist1) == len(ntlist2)

    # TODO: Should we allow users to pass a tuple too?
    if not isinstance(centers, list):
        centers = [centers]

    if not isinstance(base_weights, list):
        base_weights = [base_weights] * len(ntlist1)

    if len(base_weights)!= len(ntlist1):
        raise LengthofBaseWeightError('Weight length does not match # of nucl.')

    if not isinstance(P_weights, list):
        P_weights = [P_weights] * len(ntlist1)

    if len(P_weights)!= len(ntlist1):
        raise LengthofPWeightError('Weight length does not match # of nucl.')

    if not isinstance(C1star_weights, list):
        C1star_weights = [C1star_weights] * len(ntlist1)

    if len(C1star_weights)!= len(ntlist1):
        raise LengthofC1starWeightError('Weight length does not match # of nucl.')

    R = []
    S = []
    W = []

    for i in xrange(len(ntlist1)):
        nt1 = ntlist1[i]
        nt2 = ntlist2[i]
        for c in centers:
            if c=='base':
                if c in nt1.centers:
                    R.append(nt1.centers[c])
                    S.append(nt2.centers[c])
                    W.append(base_weights[i])
                else:
                    if c=='base':
                        raise MissingBaseException(centers)
            if c=='P':
                if nt1.coordinates(type = 'P')!=[]:
                    R.append(nt1.coordinates(type = 'P')[0])
                    S.append(nt2.coordinates(type = 'P')[0])
                    l=len(nt1.coordinates(type = 'P'))
                    for z in range(0,l):
                        W.append(P_weights[i])
                else:
                    raise MissingPhosphateException(centers)
            if c=='C1*':
                if nt1.coordinates(type = 'C1*')!=[] and nt2.coordinates(type = 'C1*')!=[]:
                    R.append(nt1.coordinates(type = 'C1*')[0])
                    S.append(nt2.coordinates(type = 'C1*')[0])
                    l=len(nt1.coordinates(type = 'C1*'))
                    for q in range(0,l):
                        W.append(C1star_weights[i])
                else:
                    raise MissingPhosphateException(centers)
    #rotation_matrix, _, _, RMSD = besttransformation(R, S)
    # Superimpose R and S with weights? I need to make changes.
    rotation_matrix, new1, mean1, RMSD, sse = besttransformation_weighted(R, S, W)
    rotation_matrix = np.transpose(rotation_matrix)
    #The rotation_matrix that is outputted from besttransformation is the
    #transpose of the one you want.

    # loop through the bases and calculate angles between them
    orientationerror = 0
    if 'base' in centers:
        for i in xrange(len(ntlist1)):
            R1 = ntlist1[i].rotation_matrix
            R2 = ntlist2[i].rotation_matrix
            # calculate angle in radians
            angle = angle_of_rotation(np.dot(np.dot(rotation_matrix,R1), np.transpose(R2)))
            orientationerror += np.square(angle)
    discrepancy = np.sqrt(sse + angleweight*orientationerror) / len(ntlist1)
    return discrepancy