quaternions

Functions to operate on, or return, quaternions

The module also includes functions for the closely related angle, axis pair as a specification for rotation.

Quaternions here consist of 4 values w, x, y, z, where w is the real (scalar) part, and x, y, z are the complex (vector) part.

Note - rotation matrices here apply to column vectors, that is, they are applied on the left of the vector. For example:

>>> import numpy as np
>>> from nibabel.quaternions import quat2mat
>>> q = [0, 1, 0, 0] # 180 degree rotation around axis 0
>>> M = quat2mat(q) # from this module
>>> vec = np.array([1, 2, 3]).reshape((3,1)) # column vector
>>> tvec = np.dot(M, vec)

angle_axis2mat(theta, vector[, is_normalized])

Rotation matrix of angle theta around vector

angle_axis2quat(theta, vector[, is_normalized])

Quaternion for rotation of angle theta around vector

conjugate(q)

Conjugate of quaternion

eye()

Return identity quaternion

fillpositive(xyz[, w2_thresh])

Compute unit quaternion from last 3 values

inverse(q)

Return multiplicative inverse of quaternion q

isunit(q)

Return True is this is very nearly a unit quaternion

mat2quat(M)

Calculate quaternion corresponding to given rotation matrix

mult(q1, q2)

Multiply two quaternions

nearly_equivalent(q1, q2[, rtol, atol])

Returns True if q1 and q2 give near equivalent transforms

norm(q)

Return norm of quaternion

quat2angle_axis(quat[, identity_thresh])

Convert quaternion to rotation of angle around axis

quat2mat(q)

Calculate rotation matrix corresponding to quaternion

rotate_vector(v, q)

Apply transformation in quaternion q to vector v

angle_axis2mat

nibabel.quaternions.angle_axis2mat(theta, vector, is_normalized=False)

Rotation matrix of angle theta around vector

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:
matarray shape (3,3)

rotation matrix for specified rotation

Notes

From: https://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle

angle_axis2quat

nibabel.quaternions.angle_axis2quat(theta, vector, is_normalized=False)

Quaternion for rotation of angle theta around vector

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:
quat4 element sequence of symbols

quaternion giving specified rotation

Notes

Formula from http://mathworld.wolfram.com/EulerParameters.html

Examples

>>> q = angle_axis2quat(np.pi, [1, 0, 0])
>>> np.allclose(q, [0, 1, 0,  0])
True

conjugate

nibabel.quaternions.conjugate(q)

Conjugate of quaternion

Parameters:
q4 element sequence

w, i, j, k of quaternion

Returns:
conjqarray shape (4,)

w, i, j, k of conjugate of q

eye

nibabel.quaternions.eye()

Return identity quaternion

fillpositive

nibabel.quaternions.fillpositive(xyz, w2_thresh=None)

Compute unit quaternion from last 3 values

Parameters:
xyziterable

iterable containing 3 values, corresponding to quaternion x, y, z

w2_threshNone or float, optional

threshold to determine if w squared is non-zero. If None (default) then w2_thresh set equal to 3 * np.finfo(xyz.dtype).eps, if possible, otherwise 3 * np.finfo(np.float64).eps

Returns:
wxyzarray shape (4,)

Full 4 values of quaternion

Notes

If w, x, y, z are the values in the full quaternion, assumes w is positive.

Gives error if w*w is estimated to be negative

w = 0 corresponds to a 180 degree rotation

The unit quaternion specifies that np.dot(wxyz, wxyz) == 1.

If w is positive (assumed here), w is given by:

w = np.sqrt(1.0-(x*x+y*y+z*z))

w2 = 1.0-(x*x+y*y+z*z) can be near zero, which will lead to numerical instability in sqrt. Here we use the system maximum float type to reduce numerical instability

Examples

>>> import numpy as np
>>> wxyz = fillpositive([0,0,0])
>>> np.all(wxyz == [1, 0, 0, 0])
True
>>> wxyz = fillpositive([1,0,0]) # Corner case; w is 0
>>> np.all(wxyz == [0, 1, 0, 0])
True
>>> np.dot(wxyz, wxyz)
1.0

inverse

nibabel.quaternions.inverse(q)

Return multiplicative inverse of quaternion q

Parameters:
q4 element sequence

w, i, j, k of quaternion

Returns:
invqarray shape (4,)

w, i, j, k of quaternion inverse

isunit

nibabel.quaternions.isunit(q)

Return True is this is very nearly a unit quaternion

mat2quat

nibabel.quaternions.mat2quat(M)

Calculate quaternion corresponding to given rotation matrix

Parameters:
Marray-like

3x3 rotation matrix

Returns:
q(4,) array

closest quaternion to input matrix, having positive q[0]

Notes

Method claimed to be robust to numerical errors in M

Constructs quaternion by calculating maximum eigenvector for matrix K (constructed from input M). Although this is not tested, a maximum eigenvalue of 1 corresponds to a valid rotation.

A quaternion q*-1 corresponds to the same rotation as q; thus the sign of the reconstructed quaternion is arbitrary, and we return quaternions with positive w (q[0]).

References

Examples

>>> import numpy as np
>>> q = mat2quat(np.eye(3)) # Identity rotation
>>> np.allclose(q, [1, 0, 0, 0])
True
>>> q = mat2quat(np.diag([1, -1, -1]))
>>> np.allclose(q, [0, 1, 0, 0]) # 180 degree rotn around axis 0
True

mult

nibabel.quaternions.mult(q1, q2)

Multiply two quaternions

Parameters:
q14 element sequence
q24 element sequence
Returns:
q12shape (4,) array

Notes

See : https://en.wikipedia.org/wiki/Quaternions#Hamilton_product

nearly_equivalent

nibabel.quaternions.nearly_equivalent(q1, q2, rtol=1e-05, atol=1e-08)

Returns True if q1 and q2 give near equivalent transforms

q1 may be nearly numerically equal to q2, or nearly equal to q2 * -1 (because a quaternion multiplied by -1 gives the same transform).

Parameters:
q14 element sequence

w, x, y, z of first quaternion

q24 element sequence

w, x, y, z of second quaternion

Returns:
equivbool

True if q1 and q2 are nearly equivalent, False otherwise

Examples

>>> q1 = [1, 0, 0, 0]
>>> nearly_equivalent(q1, [0, 1, 0, 0])
False
>>> nearly_equivalent(q1, [1, 0, 0, 0])
True
>>> nearly_equivalent(q1, [-1, 0, 0, 0])
True

norm

nibabel.quaternions.norm(q)

Return norm of quaternion

Parameters:
q4 element sequence

w, i, j, k of quaternion

Returns:
nscalar

quaternion norm

quat2angle_axis

nibabel.quaternions.quat2angle_axis(quat, identity_thresh=None)

Convert quaternion to rotation of angle around axis

Parameters:
quat4 element sequence

w, x, y, z forming quaternion

identity_threshNone or scalar, optional

threshold below which the norm of the vector part of the quaternion (x, y, z) is deemed to be 0, leading to the identity rotation. None (the default) leads to a threshold estimated based on the precision of the input.

Returns:
thetascalar

angle of rotation

vectorarray shape (3,)

axis around which rotation occurs

Notes

A quaternion for which x, y, z are all equal to 0, is an identity rotation. In this case we return a 0 angle and an arbitrary vector, here [1, 0, 0]

Examples

>>> theta, vec = quat2angle_axis([0, 1, 0, 0])
>>> np.allclose(theta, np.pi)
True
>>> vec
array([1., 0., 0.])

If this is an identity rotation, we return a zero angle and an arbitrary vector

>>> quat2angle_axis([1, 0, 0, 0])
(0.0, array([1., 0., 0.]))

quat2mat

nibabel.quaternions.quat2mat(q)

Calculate rotation matrix corresponding to quaternion

Parameters:
q4 element array-like
Returns:
M(3,3) array

Rotation matrix corresponding to input quaternion q

Notes

Rotation matrix applies to column vectors, and is applied to the left of coordinate vectors. The algorithm here allows non-unit quaternions.

References

Algorithm from https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion

Examples

>>> import numpy as np
>>> M = quat2mat([1, 0, 0, 0]) # Identity quaternion
>>> np.allclose(M, np.eye(3))
True
>>> M = quat2mat([0, 1, 0, 0]) # 180 degree rotn around axis 0
>>> np.allclose(M, np.diag([1, -1, -1]))
True

rotate_vector

nibabel.quaternions.rotate_vector(v, q)

Apply transformation in quaternion q to vector v

Parameters:
v3 element sequence

3 dimensional vector

q4 element sequence

w, i, j, k of quaternion

Returns:
vdasharray shape (3,)

v rotated by quaternion q

Notes

See: https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Describing_rotations_with_quaternions