def test_is_almost_parallel_vs_antiparallel(self): self.assertEqual(ftuv.is_almost_parallel( np.array([0, 0, 2]), np.array([0., 0., 3.])), 1) self.assertTrue(ftuv.is_almost_parallel( np.array([3, 6, 7]), np.array([-9., -18., -21.])), -1) self.assertTrue(ftuv.is_almost_parallel( np.array([3, 6, 0]), np.array([9., 18., 0.])), 1) self.assertTrue(ftuv.is_almost_parallel( np.array([-3, 0, -8]), np.array([-9., 0., -24.])), -1)
def test_get_double_alignment_matrix(self): vec1 = np.array([0.5, 0.7, 0.9]) vec1b = np.array([9., 0, -5.]) vec2 = np.array([0.345, 3.5, 0.55]) vec2b = np.array([0., 0.55, -3.5]) rotMat = ftuv.get_double_alignment_matrix((vec1, vec1b), (vec2, vec2b)) self.assertTrue(ftuv.is_almost_parallel(vec2, np.dot(vec1, rotMat))) self.assertTrue(ftuv.is_almost_parallel(np.dot(rotMat, vec2), vec1)) self.assertTrue(ftuv.is_almost_parallel(vec2b, np.dot(vec1b, rotMat)), msg="{} not colinear with {}".format(vec2b, np.dot(vec1b, rotMat))) self.assertTrue(ftuv.is_almost_parallel(np.dot(rotMat, vec2b), vec1b), msg="{} not colinear with {}".format(np.dot(rotMat, vec2b), vec1b))
def test_is_almost_parallel_vs_antiparallel(self): self.assertEqual( ftuv.is_almost_parallel(np.array([0, 0, 2]), np.array([0., 0., 3.])), 1) self.assertTrue( ftuv.is_almost_parallel(np.array([3, 6, 7]), np.array([-9., -18., -21.])), -1) self.assertTrue( ftuv.is_almost_parallel(np.array([3, 6, 0]), np.array([9., 18., 0.])), 1) self.assertTrue( ftuv.is_almost_parallel(np.array([-3, 0, -8]), np.array([-9., 0., -24.])), -1)
def test_init_projection2(self): cg, = ftmc.CoarseGrainRNA.from_pdb('test/forgi/threedee/data/2X1F.pdb') cg.project_from = [1., 1., 1.] proj = fpp.Projection2D(cg) self.assertTrue(ftuv.is_almost_parallel(proj.proj_direction, np.array([1., 1., 1.])), msg="The projection direction was not stored correctly. Should be coliniar" " with {}, got {}".format(np.array([1., 1., 1.]), proj.proj_direction))
def test_init_projection(self): cg, = ftmc.CoarseGrainRNA.from_pdb('test/forgi/threedee/data/2X1F.pdb') proj = fpp.Projection2D(cg, [1., 1., 1.]) self.assertTrue( ftuv.is_almost_parallel(proj.proj_direction, np.array([1., 1., 1.])), msg= "The projection direction was not stored correctly. Should be coliniar" " with {}, got {}".format(np.array([1., 1., 1.]), proj.proj_direction))
def test_create_orthonormal_basis(self): basis1 = ftuv.create_orthonormal_basis(np.array([0.0, 0.0, 2.0])) self.assertTrue( ftuv.is_almost_parallel(basis1[0], np.array([0., 0., 2.]))) basis2 = ftuv.create_orthonormal_basis(np.array([0.0, 0.0, 2.0]), np.array([0.0, 3.6, 0.])) self.assertTrue( ftuv.is_almost_parallel(basis2[0], np.array([0., 0., 2.]))) self.assertTrue( ftuv.is_almost_parallel(basis2[1], np.array([0., 3.6, 0]))) basis3 = ftuv.create_orthonormal_basis(np.array([0.0, 0.0, 2.0]), np.array([0.0, 3.6, 0.]), np.array([1., 0, 0])) self.assertTrue( ftuv.is_almost_parallel(basis3[0], np.array([0., 0., 2.]))) self.assertTrue( ftuv.is_almost_parallel(basis3[1], np.array([0., 3.6, 0]))) self.assertTrue( ftuv.is_almost_parallel(basis3[2], np.array([1., 0, 0]))) for basis in [basis1, basis2, basis3]: self.assertAlmostEqual(np.dot(basis[0], basis[1]), 0) self.assertAlmostEqual(np.dot(basis[0], basis[2]), 0) self.assertAlmostEqual(np.dot(basis[2], basis[1]), 0) for b in basis: self.assertAlmostEqual(ftuv.magnitude(b), 1)
def test_get_stem_rotation_matrix(self): stem1 = fbm.StemModel(mids=(np.array([0., 0., 0.]), np.array([0., 0., 10.])), twists=(np.array([0., 1., 0.]), np.array([0., -1., 0.]))) stem2 = fbm.StemModel(mids=(np.array([0., 0., 0.]), np.array([10., 0., 0.])), twists=(np.array([0., 1., 1.]), np.array([0., -1., -1.]))) rot_mat = fbm.get_stem_rotation_matrix(stem1, stem2) #RotMat to euler-angles: nghiaho.com/?page_id=846 theta_x = math.atan2(rot_mat[2, 1], rot_mat[2, 2]) theta_y = math.atan2(-rot_mat[2, 0], math.sqrt(rot_mat[2, 1]**2 + rot_mat[2, 2]**2)) theta_z = math.atan2(rot_mat[1, 0], rot_mat[0, 0]) self.assertTrue( ftuv.is_almost_parallel(np.dot(stem1.vec(), rot_mat), np.array([10, 0, 0.]))) self.assertAlmostEqual(theta_x, 0) self.assertAlmostEqual(theta_y, -math.pi / 2) self.assertAlmostEqual(theta_z, -math.pi / 4)
def test_create_orthonormal_basis(self): basis1 = ftuv.create_orthonormal_basis(np.array([0.0, 0.0, 2.0])) self.assertTrue(ftuv.is_almost_parallel( basis1[0], np.array([0., 0., 2.]))) basis2 = ftuv.create_orthonormal_basis( np.array([0.0, 0.0, 2.0]), np.array([0.0, 3.6, 0.])) self.assertTrue(ftuv.is_almost_parallel( basis2[0], np.array([0., 0., 2.]))) self.assertTrue(ftuv.is_almost_parallel( basis2[1], np.array([0., 3.6, 0]))) basis3 = ftuv.create_orthonormal_basis( np.array([0.0, 0.0, 2.0]), np.array([0.0, 3.6, 0.]), np.array([1., 0, 0])) self.assertTrue(ftuv.is_almost_parallel( basis3[0], np.array([0., 0., 2.]))) self.assertTrue(ftuv.is_almost_parallel( basis3[1], np.array([0., 3.6, 0]))) self.assertTrue(ftuv.is_almost_parallel( basis3[2], np.array([1., 0, 0]))) for basis in [basis1, basis2, basis3]: self.assertAlmostEqual(np.dot(basis[0], basis[1]), 0) self.assertAlmostEqual(np.dot(basis[0], basis[2]), 0) self.assertAlmostEqual(np.dot(basis[2], basis[1]), 0) for b in basis: self.assertAlmostEqual(ftuv.magnitude(b), 1)
def test_get_alignment_matrix(self): vec1 = np.array([0.5, 0.7, 0.9]) vec2 = np.array([0.345, 3.4347, 0.55]) rotMat = ftuv.get_alignment_matrix(vec1, vec2) self.assertTrue(ftuv.is_almost_parallel(vec2, np.dot(vec1, rotMat))) self.assertTrue(ftuv.is_almost_parallel(np.dot(rotMat, vec2), vec1))
def test_is_almost_parallel(self): # Zero-vector is colinear to nothing self.assertFalse( ftuv.is_almost_parallel(np.array([0, 0, 0]), np.array([0., 0., 0.]))) self.assertFalse( ftuv.is_almost_parallel(np.array([0.4, 0, 0]), np.array([0., 0., 0.]))) self.assertFalse( ftuv.is_almost_parallel(np.array([0, 0, 0]), np.array([0, 20, 10]))) # 10*-8 is treated as zero self.assertTrue( ftuv.is_almost_parallel(np.array([0, 1, 1]), np.array([10**-10, 2, 2]))) self.assertTrue( ftuv.is_almost_parallel(np.array([1, 0, 1]), np.array([2, 10**-10, 2]))) self.assertTrue( ftuv.is_almost_parallel(np.array([1, 1, 0]), np.array([2, 2, 10**-10]))) self.assertTrue( ftuv.is_almost_parallel(np.array([10**-10, 2, 2]), np.array([0, 1, 1]))) self.assertTrue( ftuv.is_almost_parallel(np.array([2, 10**-10, 2]), np.array([1, 0, 1]))) self.assertTrue( ftuv.is_almost_parallel(np.array([2, 2, 10**-10]), np.array([1, 1, 0]))) self.assertTrue( ftuv.is_almost_parallel( [6.13714577e-16, 3.68203114, 1.66697272e-15], [0., 15.302, 0.])) # Real world example, where 10**-9 is not working self.assertTrue( ftuv.is_almost_parallel( [6.22374626e+00, -6.47794687e-01, -3.29655380e-06], [7.61983623e+00, -7.93105828e-01, -4.03602575e-06])) # Colinear self.assertTrue( ftuv.is_almost_parallel(np.array([0, 0, 2]), np.array([0., 0., 3.]))) self.assertTrue( ftuv.is_almost_parallel(np.array([3, 6, 7]), np.array([9., 18., 21.]))) self.assertTrue( ftuv.is_almost_parallel(np.array([3, 6, 0]), np.array([9., 18., 0.]))) self.assertTrue( ftuv.is_almost_parallel(np.array([3, 0, 8]), np.array([9., 0., 24. + 10**-12]))) # Not colinear self.assertFalse( ftuv.is_almost_parallel(np.array([0, 0, 3.]), np.array([2., 0, 0]))) self.assertFalse( ftuv.is_almost_parallel(np.array([0, 3., 0]), np.array([0, 0, 3.]))) self.assertFalse( ftuv.is_almost_parallel(np.array([1, 2, 3]), np.array([2., 4., -6.]))) self.assertFalse( ftuv.is_almost_parallel(np.array([1, 2, 3]), np.array([3., 4., 6.]))) self.assertFalse( ftuv.is_almost_parallel(np.array([1, 2, 3]), np.array([2., 5., 6.])))
def get_relative_orientation(cg, loop, stem): ''' Return how loop is related to stem in terms of three parameters. The stem is the receptor of a potential A-Minor interaction, whereas the loop is the donor. The 3 parameters are: 1. Distance between the closest points of the two elements 2. The angle between the stem and the vector between the two 3. The angle between the minor groove of l2 and the projection of the vector between stem and loop onto the plane normal to the stem direction. ''' point_on_stem, point_on_loop = ftuv.line_segment_distance( cg.coords[stem][0], cg.coords[stem][1], cg.coords[loop][0], cg.coords[loop][1]) conn_vec = point_on_loop - point_on_stem dist = ftuv.magnitude(conn_vec) angle1 = ftuv.vec_angle(cg.coords.get_direction(stem), conn_vec) # The direction of the stem vector is irrelevant, so # choose the smaller of the two angles between two lines if angle1 > np.pi / 2: angle1 = np.pi - angle1 tw = cg.get_twists(stem) if dist == 0: angle2 = float("nan") else: if stem[0] != 's': raise ValueError( "The receptor needs to be a stem, not {}".format(stem)) else: stem_len = cg.stem_length(stem) # Where along the helix our A-residue points to the minor groove. # This can be between residues. We express it as floating point nucleotide coordinates. # So 0.0 means at the first basepair, while 1.5 means between the second and the third basepair. pos = ftuv.magnitude( point_on_stem - cg.coords[stem][0]) / ftuv.magnitude( cg.coords.get_direction(stem)) * (stem_len - 1) # The vector pointing to the minor groove, even if we are not at a virtual residue (pos is a float value) virt_twist = ftug.virtual_res_3d_pos_core(cg.coords[stem], cg.twists[stem], pos, stem_len)[1] # The projection of the connection vector onto the plane normal to the stem conn_proj = ftuv.vector_rejection(conn_vec, cg.coords.get_direction(stem)) try: # Note: here the directions of both vectors are well defined, # so angles >90 degrees make sense. angle2 = ftuv.vec_angle(virt_twist, conn_proj) except ValueError: if np.all(virt_twist == 0): angle2 = float("nan") else: raise # Furthermore, the direction of the second angle is meaningful. # We call use a positive angle, if the cross-product of the two vectors # has the same sign as the stem vector and a negative angle otherwise cr = np.cross(virt_twist, conn_proj) sign = ftuv.is_almost_parallel(cr, cg.coords.get_direction(stem)) #assert sign != 0, "{} vs {} not (anti) parallel".format( # cr, cg.coords.get_direction(stem)) angle2 *= sign return dist, angle1, angle2
def get_relative_orientation(cg, loop, stem): ''' Return how loop is related to stem in terms of three parameters. The stem is the receptor of a potential A-Minor interaction, whereas the loop is the donor. The 3 parameters are: 1. Distance between the closest points of the two elements 2. The angle between the stem and the vector between the two 3. The angle between the minor groove of l2 and the projection of the vector between stem and loop onto the plane normal to the stem direction. ''' point_on_stem, point_on_loop = ftuv.line_segment_distance(cg.coords[stem][0], cg.coords[stem][1], cg.coords[loop][0], cg.coords[loop][1]) conn_vec = point_on_loop - point_on_stem dist = ftuv.magnitude(conn_vec) angle1 = ftuv.vec_angle(cg.coords.get_direction(stem), conn_vec) # The direction of the stem vector is irrelevant, so # choose the smaller of the two angles between two lines if angle1 > np.pi / 2: angle1 = np.pi - angle1 tw = cg.get_twists(stem) if dist == 0: angle2 = float("nan") else: if stem[0] != 's': raise ValueError( "The receptor needs to be a stem, not {}".format(stem)) else: stem_len = cg.stem_length(stem) # Where along the helix our A-residue points to the minor groove. # This can be between residues. We express it as floating point nucleotide coordinates. # So 0.0 means at the first basepair, while 1.5 means between the second and the third basepair. pos = ftuv.magnitude(point_on_stem - cg.coords[stem][0]) / ftuv.magnitude( cg.coords.get_direction(stem)) * (stem_len - 1) # The vector pointing to the minor groove, even if we are not at a virtual residue (pos is a float value) virt_twist = ftug.virtual_res_3d_pos_core( cg.coords[stem], cg.twists[stem], pos, stem_len)[1] # The projection of the connection vector onto the plane normal to the stem conn_proj = ftuv.vector_rejection( conn_vec, cg.coords.get_direction(stem)) try: # Note: here the directions of both vectors are well defined, # so angles >90 degrees make sense. angle2 = ftuv.vec_angle(virt_twist, conn_proj) except ValueError: if np.all(virt_twist == 0): angle2 = float("nan") else: raise # Furthermore, the direction of the second angle is meaningful. # We call use a positive angle, if the cross-product of the two vectors # has the same sign as the stem vector and a negative angle otherwise cr = np.cross(virt_twist, conn_proj) sign = ftuv.is_almost_parallel(cr, cg.coords.get_direction(stem)) #assert sign != 0, "{} vs {} not (anti) parallel".format( # cr, cg.coords.get_direction(stem)) angle2 *= sign return dist, angle1, angle2
def test_is_almost_parallel(self): # Zero-vector is colinear to nothing self.assertFalse(ftuv.is_almost_parallel( np.array([0, 0, 0]), np.array([0., 0., 0.]))) self.assertFalse(ftuv.is_almost_parallel( np.array([0.4, 0, 0]), np.array([0., 0., 0.]))) self.assertFalse(ftuv.is_almost_parallel( np.array([0, 0, 0]), np.array([0, 20, 10]))) # 10*-8 is treated as zero self.assertTrue(ftuv.is_almost_parallel( np.array([0, 1, 1]), np.array([10**-10, 2, 2]))) self.assertTrue(ftuv.is_almost_parallel( np.array([1, 0, 1]), np.array([2, 10**-10, 2]))) self.assertTrue(ftuv.is_almost_parallel( np.array([1, 1, 0]), np.array([2, 2, 10**-10]))) self.assertTrue(ftuv.is_almost_parallel( np.array([10**-10, 2, 2]), np.array([0, 1, 1]))) self.assertTrue(ftuv.is_almost_parallel( np.array([2, 10**-10, 2]), np.array([1, 0, 1]))) self.assertTrue(ftuv.is_almost_parallel( np.array([2, 2, 10**-10]), np.array([1, 1, 0]))) self.assertTrue(ftuv.is_almost_parallel( [6.13714577e-16, 3.68203114, 1.66697272e-15], [0., 15.302, 0.])) # Real world example, where 10**-9 is not working self.assertTrue(ftuv.is_almost_parallel( [6.22374626e+00, -6.47794687e-01, -3.29655380e-06], [7.61983623e+00, -7.93105828e-01, -4.03602575e-06])) # Colinear self.assertTrue(ftuv.is_almost_parallel( np.array([0, 0, 2]), np.array([0., 0., 3.]))) self.assertTrue(ftuv.is_almost_parallel( np.array([3, 6, 7]), np.array([9., 18., 21.]))) self.assertTrue(ftuv.is_almost_parallel( np.array([3, 6, 0]), np.array([9., 18., 0.]))) self.assertTrue(ftuv.is_almost_parallel( np.array([3, 0, 8]), np.array([9., 0., 24. + 10**-12]))) # Not colinear self.assertFalse(ftuv.is_almost_parallel( np.array([0, 0, 3.]), np.array([2., 0, 0]))) self.assertFalse(ftuv.is_almost_parallel( np.array([0, 3., 0]), np.array([0, 0, 3.]))) self.assertFalse(ftuv.is_almost_parallel( np.array([1, 2, 3]), np.array([2., 4., -6.]))) self.assertFalse(ftuv.is_almost_parallel( np.array([1, 2, 3]), np.array([3., 4., 6.]))) self.assertFalse(ftuv.is_almost_parallel( np.array([1, 2, 3]), np.array([2., 5., 6.])))