Author: bugman Date: Tue Sep 1 16:02:48 2009 New Revision: 9422 URL: http://svn.gna.org/viewcvs/relax?rev=9422&view=rev Log: Created the new maths_fns.rotation_matrix.R_to_euler_zyz() function and associated unit test. Added: 1.3/test_suite/unit_tests/_maths_fns/test_rotation_matrix.py Modified: 1.3/maths_fns/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=9422&r1=9421&r2=9422&view=diff ============================================================================== --- 1.3/maths_fns/rotation_matrix.py (original) +++ 1.3/maths_fns/rotation_matrix.py Tue Sep 1 16:02:48 2009 @@ -21,7 +21,7 @@ ############################################################################### # Python module imports. -from math import acos, atan2, cos, pi, sin +from math import acos, asin, atan2, cos, pi, sin from numpy import array, cross, dot, float64, hypot, zeros from numpy.linalg import norm from random import gauss, uniform @@ -296,6 +296,57 @@ matrix[2,2] = cos_b +def R_to_euler_zyz(matrix): + """Calculate the z-y-z Euler angles from the given rotation matrix. + + Unit vectors + ============ + + The unit mux vector is:: + + | -sin(alpha) * sin(gamma) + cos(alpha) * cos(beta) * cos(gamma) | + mux = | -sin(alpha) * cos(gamma) - cos(alpha) * cos(beta) * sin(gamma) |. + | cos(alpha) * sin(beta) | + + The unit muy vector is:: + + | cos(alpha) * sin(gamma) + sin(alpha) * cos(beta) * cos(gamma) | + muy = | cos(alpha) * cos(gamma) - sin(alpha) * cos(beta) * sin(gamma) |. + | sin(alpha) * sin(beta) | + + The unit muz vector is:: + + | -sin(beta) * cos(gamma) | + muz = | sin(beta) * sin(gamma) |. + | cos(beta) | + + Rotation matrix + =============== + + The rotation matrix is defined as the vector of unit vectors:: + + R = [mux, muy, muz]. + + + @param matrix: The 3x3 rotation matrix to update. + @type matrix: 3x3 numpy array + @return: The alpha, beta, and gamma Euler angles in the z-y-z convention. + @rtype: float, float, float + """ + + # The beta Euler angle. + beta = acos(matrix[2,2]) + + # The alpha Euler angle. + alpha = atan2(matrix[2,1], matrix[2,0]) + + # The gamma Euler angle. + gamma = atan2(matrix[1,2], -matrix[0,2]) + + # Return the angles. + return alpha, beta, gamma + + def R_random_axis(matrix, angle=0.0): """Generate a random rotation matrix of fixed angle via the axis-angle notation. Added: 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=9422&view=auto ============================================================================== --- 1.3/test_suite/unit_tests/_maths_fns/test_rotation_matrix.py (added) +++ 1.3/test_suite/unit_tests/_maths_fns/test_rotation_matrix.py Tue Sep 1 16:02:48 2009 @@ -1,0 +1,76 @@ +############################################################################### +# # +# Copyright (C) 2009 Edward d'Auvergne # +# # +# This file is part of the program relax. # +# # +# relax is free software; you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation; either version 2 of the License, or # +# (at your option) any later version. # +# # +# relax is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with relax; if not, write to the Free Software # +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # +# # +############################################################################### + +# Python module imports. +from math import pi +from numpy import float64, zeros +from random import uniform +from unittest import TestCase + +# relax module imports. +from generic_fns.angles import wrap_angles +from maths_fns.rotation_matrix import * + + +class Test_rotation_matrix(TestCase): + """Unit tests for the maths_fns.rotation_matrix relax module.""" + + def setUp(self): + """Set up data used by the unit tests.""" + + + def test_R_to_euler_zyz(self): + """Test the rotation matrix to zyz Euler angle conversion.""" + + # Starting angles. + alpha = uniform(0, 2*pi) + beta = uniform(0, pi) + gamma = uniform(0, 2*pi) + + # Print out. + print("Original angles:") + print("alpha: %s" % alpha) + print("beta: %s" % beta) + print("gamma: %s\n" % gamma) + + # Generate the rotation matrix. + R = zeros((3,3), float64) + R_euler_zyz(R, alpha, beta, gamma) + + # Get back the angles. + alpha_new, beta_new, gamma_new = R_to_euler_zyz(R) + + # Wrap the angles. + alpha_new = wrap_angles(alpha_new, 0, 2*pi) + beta_new = wrap_angles(beta_new, 0, 2*pi) + gamma_new = wrap_angles(gamma_new, 0, 2*pi) + + # Print out. + print("New angles:") + print("alpha: %s" % alpha_new) + print("beta: %s" % beta_new) + print("gamma: %s\n" % gamma_new) + + # Checks. + self.assertAlmostEqual(alpha, alpha_new) + self.assertAlmostEqual(beta, beta_new) + self.assertAlmostEqual(gamma, gamma_new)