Neuroimaging in Python — NiBabel 5.4.0.dev1+g3b1c7b37 documentation (original) (raw)

eulerangles

Module implementing Euler angle rotations and their conversions

See:

See also: Representing Attitude with Euler Angles and Quaternions: A Reference (2006) by James Diebel. A cached PDF link last found here:

http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.110.5134

Euler’s rotation theorem tells us that any rotation in 3D can be described by 3 angles. Let’s call the 3 angles the _Euler angle vector_and call the angles in the vector \(alpha\), \(beta\) and\(gamma\). The vector is [ \(alpha\),\(beta\). \(gamma\) ] and, in this description, the order of the parameters specifies the order in which the rotations occur (so the rotation corresponding to \(alpha\) is applied first).

In order to specify the meaning of an Euler angle vector we need to specify the axes around which each of the rotations corresponding to\(alpha\), \(beta\) and \(gamma\) will occur.

There are therefore three axes for the rotations \(alpha\),\(beta\) and \(gamma\); let’s call them \(i\) \(j\),\(k\).

Let us express the rotation \(alpha\) around axis i as a 3 by 3 rotation matrix A. Similarly \(beta\) around j becomes 3 x 3 matrix B and \(gamma\) around k becomes matrix G. Then the whole rotation expressed by the Euler angle vector [ \(alpha\),\(beta\). \(gamma\) ], R is given by:

R = np.dot(G, np.dot(B, A))

See http://mathworld.wolfram.com/EulerAngles.html

The order \(G B A\) expresses the fact that the rotations are performed in the order of the vector (\(alpha\) around axis i =A first).

To convert a given Euler angle vector to a meaningful rotation, and a rotation matrix, we need to define:

See: https://en.wikipedia.org/wiki/Rotation_matrix#Ambiguities

We are using the following conventions:

The convention of rotation around z, followed by rotation aroundy, followed by rotation around x, is known (confusingly) as “xyz”, pitch-roll-yaw, Cardan angles, or Tait-Bryan angles.

angle_axis2euler(theta, vector[, is_normalized]) Convert angle, axis pair to Euler angles
euler2angle_axis([z, y, x]) Return angle, axis corresponding to these Euler angles
euler2mat([z, y, x]) Return matrix for rotations around z, y and x axes
euler2quat([z, y, x]) Return quaternion corresponding to these Euler angles
mat2euler(M[, cy_thresh]) Discover Euler angle vector from 3x3 matrix
quat2euler(q) Return Euler angles corresponding to quaternion q

angle_axis2euler

nibabel.eulerangles.angle_axis2euler(theta, vector, is_normalized=False)

Convert angle, axis pair to Euler angles

Parameters:

thetascalar

angle of rotation

vector3 element sequence

vector specifying axis for rotation.

is_normalizedbool, optional

True if vector is already normalized (has norm of 1). Default False

Returns:

zscalar

yscalar

xscalar

Rotations in radians around z, y, x axes, respectively

Notes

It’s possible to reduce the amount of calculation a little, by combining parts of the angle_axis2mat and mat2eulerfunctions, but the reduction in computation is small, and the code repetition is large.

Examples

z, y, x = angle_axis2euler(0, [1, 0, 0]) np.allclose((z, y, x), 0) True

euler2angle_axis

nibabel.eulerangles.euler2angle_axis(z=0, y=0, x=0)

Return angle, axis corresponding to these Euler angles

Uses the z, then y, then x convention above

Parameters:

zscalar

Rotation angle in radians around z-axis (performed first)

yscalar

Rotation angle in radians around y-axis

xscalar

Rotation angle in radians around x-axis (performed last)

Returns:

thetascalar

angle of rotation

vectorarray shape (3,)

axis around which rotation occurs

Examples

theta, vec = euler2angle_axis(0, 1.5, 0) print(theta) 1.5 np.allclose(vec, [0, 1, 0]) True

euler2mat

nibabel.eulerangles.euler2mat(z=0, y=0, x=0)

Return matrix for rotations around z, y and x axes

Uses the z, then y, then x convention above

Parameters:

zscalar

Rotation angle in radians around z-axis (performed first)

yscalar

Rotation angle in radians around y-axis

xscalar

Rotation angle in radians around x-axis (performed last)

Returns:

Marray shape (3,3)

Rotation matrix giving same rotation as for given angles

Notes

The direction of rotation is given by the right-hand rule (orient the thumb of the right hand along the axis around which the rotation occurs, with the end of the thumb at the positive end of the axis; curl your fingers; the direction your fingers curl is the direction of rotation). Therefore, the rotations are counterclockwise if looking along the axis of rotation from positive to negative.

Examples

zrot = 1.3 # radians yrot = -0.1 xrot = 0.2 M = euler2mat(zrot, yrot, xrot) M.shape == (3, 3) True

The output rotation matrix is equal to the composition of the individual rotations

M1 = euler2mat(zrot) M2 = euler2mat(0, yrot) M3 = euler2mat(0, 0, xrot) composed_M = np.dot(M3, np.dot(M2, M1)) np.allclose(M, composed_M) True

You can specify rotations by named arguments

np.all(M3 == euler2mat(x=xrot)) True

When applying M to a vector, the vector should column vector to the right of M. If the right hand side is a 2D array rather than a vector, then each column of the 2D array represents a vector.

vec = np.array([1, 0, 0]).reshape((3,1)) v2 = np.dot(M, vec) vecs = np.array([[1, 0, 0],[0, 1, 0]]).T # giving 3x2 array vecs2 = np.dot(M, vecs)

Rotations are counter-clockwise.

zred = np.dot(euler2mat(z=np.pi/2), np.eye(3)) np.allclose(zred, [[0, -1, 0],[1, 0, 0], [0, 0, 1]]) True yred = np.dot(euler2mat(y=np.pi/2), np.eye(3)) np.allclose(yred, [[0, 0, 1],[0, 1, 0], [-1, 0, 0]]) True xred = np.dot(euler2mat(x=np.pi/2), np.eye(3)) np.allclose(xred, [[1, 0, 0],[0, 0, -1], [0, 1, 0]]) True

euler2quat

nibabel.eulerangles.euler2quat(z=0, y=0, x=0)

Return quaternion corresponding to these Euler angles

Uses the z, then y, then x convention above

Parameters:

zscalar

Rotation angle in radians around z-axis (performed first)

yscalar

Rotation angle in radians around y-axis

xscalar

Rotation angle in radians around x-axis (performed last)

Returns:

quatarray shape (4,)

Quaternion in w, x, y z (real, then vector) format

Notes

We can derive this formula in Sympy using:

  1. Formula giving quaternion corresponding to rotation of theta radians about arbitrary axis:http://mathworld.wolfram.com/EulerParameters.html
  2. Generated formulae from 1.) for quaternions corresponding to theta radians rotations about x, y, z axes
  3. Apply quaternion multiplication formula -https://en.wikipedia.org/wiki/Quaternions#Hamilton_product - to formulae from 2.) to give formula for combined rotations.

mat2euler

nibabel.eulerangles.mat2euler(M, cy_thresh=None)

Discover Euler angle vector from 3x3 matrix

Uses the conventions above.

Parameters:

Marray-like, shape (3,3)

cy_threshNone or scalar, optional

threshold below which to give up on straightforward arctan for estimating x rotation. If None (default), estimate from precision of input.

Returns:

zscalar

yscalar

xscalar

Rotations in radians around z, y, x axes, respectively

Notes

If there was no numerical error, the routine could be derived using Sympy expression for z then y then x rotation matrix, which is:

[ cos(y)*cos(z), -cos(y)*sin(z), sin(y)], [cos(x)*sin(z) + cos(z)*sin(x)*sin(y), cos(x)*cos(z) - sin(x)*sin(y)*sin(z), -cos(y)*sin(x)], [sin(x)*sin(z) - cos(x)*cos(z)*sin(y), cos(z)*sin(x) + cos(x)*sin(y)*sin(z), cos(x)*cos(y)]

with the obvious derivations for z, y, and x

z = atan2(-r12, r11) y = asin(r13) x = atan2(-r23, r33)

Problems arise when cos(y) is close to zero, because both of:

z = atan2(cos(y)*sin(z), cos(y)*cos(z)) x = atan2(cos(y)*sin(x), cos(x)*cos(y))

will be close to atan2(0, 0), and highly unstable.

The cy fix for numerical instability below is from: Graphics Gems IV, Paul Heckbert (editor), Academic Press, 1994, ISBN: 0123361559. Specifically it comes from EulerAngles.c by Ken Shoemake, and deals with the case where cos(y) is close to zero:

See: http://www.graphicsgems.org/

The code appears to be licensed (from the website) as “can be used without restrictions”.

quat2euler

nibabel.eulerangles.quat2euler(q)

Return Euler angles corresponding to quaternion q

Parameters:

q4 element sequence

w, x, y, z of quaternion

Returns:

zscalar

Rotation angle in radians around z-axis (performed first)

yscalar

Rotation angle in radians around y-axis

xscalar

Rotation angle in radians around x-axis (performed last)

Notes

It’s possible to reduce the amount of calculation a little, by combining parts of the quat2mat and mat2euler functions, but the reduction in computation is small, and the code repetition is large.