Author: bugman Date: Tue Sep 8 19:51:14 2009 New Revision: 9485 URL: http://svn.gna.org/viewcvs/relax?rev=9485&view=rev Log: Created the maths_fns.rotation_matrix.quaternion_to_axis_angle() function. This is accompanied by 2 unit tests. Modified: 1.3/maths_fns/rotation_matrix.py 1.3/test_suite/unit_tests/_maths_fns/test_rotation_matrix.py Modified: 1.3/maths_fns/rotation_matrix.py URL: http://svn.gna.org/viewcvs/relax/1.3/maths_fns/rotation_matrix.py?rev=9485&r1=9484&r2=9485&view=diff ============================================================================== --- 1.3/maths_fns/rotation_matrix.py (original) +++ 1.3/maths_fns/rotation_matrix.py Tue Sep 8 19:51:14 2009 @@ -325,6 +325,41 @@ axis[2] = cos(phi) +def quaternion_to_axis_angle(quat): + """Convert a quaternion into the axis-angle notation. + + Conversion equations + ==================== + + From Wolfram MathWorld (http://mathworld.wolfram.com/Quaternion.html), the conversion is given by:: + + q = (cos(angle/2), n * sin(angle/2)), + + where q is the quaternion and n is the unit vector representing the rotation axis. Therfore:: + + angle = 2*acos(w), + + axis = 2*asin([x, y, z]) + + @param quat: The quaternion. + @type quat: numpy 4D, rank-1 array + @return: The 3D rotation axis and angle. + @rtype: numpy 3D rank-1 array, float + """ + + # The angle. + angle = 2 * acos(quat[0]) + + # The axis. + if angle: + axis = quat[1:] / sin(angle/2) + else: + axis = quat[1:] * 0.0 + + # Return + return axis, angle + + def quaternion_to_R(quat, R): """Convert a quaternion into rotation matrix form. Modified: 1.3/test_suite/unit_tests/_maths_fns/test_rotation_matrix.py URL: http://svn.gna.org/viewcvs/relax/1.3/test_suite/unit_tests/_maths_fns/test_rotation_matrix.py?rev=9485&r1=9484&r2=9485&view=diff ============================================================================== --- 1.3/test_suite/unit_tests/_maths_fns/test_rotation_matrix.py (original) +++ 1.3/test_suite/unit_tests/_maths_fns/test_rotation_matrix.py Tue Sep 8 19:51:14 2009 @@ -353,6 +353,41 @@ self.assertAlmostEqual(gamma, gamma_new) + def test_quaternion_to_axis_angle_no_rot(self): + """Test the quaternion to rotation matrix conversion for a zero angle rotation.""" + + # Quaternion of zero angle. + quat = array([1, 0, 0, 0], float64) + + # The axis and angle. + axis, angle = quaternion_to_axis_angle(quat) + print("Axis: %s" % axis) + print("Angle: %s" % angle) + + # The correct result. + self.assertEqual(angle, 0.0) + for i in range(3): + self.assertEqual(axis[i], 0.0) + + + def test_quaternion_to_axis_angle_180_complex(self): + """Test the quaternion to axis-angle conversion for a 180 degree rotation about [1, 1, 1].""" + + # The quaternion. + quat = array([0, 1, 1, 1], float64) / sqrt(3) + + # The axis and angle. + axis, angle = quaternion_to_axis_angle(quat) + print("Axis: %s" % axis) + print("Angle: %s" % angle) + + # The correct result. + self.assertEqual(angle, pi) + for i in range(3): + self.assertEqual(axis[i], 1.0 / sqrt(3)) + + + def test_quaternion_to_R_no_rot(self): """Test the quaternion to rotation matrix conversion for a zero angle rotation."""