Quaternions

The submodule GWFrames.Quaternions provides the Quaternion class and functions acting on single quaternions and on arrays of them. Unit quaternions (rotors) represent the rotations between frames. The class is also available as GWFrames.Quaternion.

Wherever a Quaternion is expected, a sequence of four numbers is also accepted, and wherever an array of quaternions is expected, a sequence of Quaternion objects, a sequence of length-4 sequences, or an array of shape (N, 4) is accepted. Arrays of quaternions are returned as one-dimensional numpy arrays of Quaternion objects.

The Quaternion class

class GWFrames.Quaternions.Quaternion

A quaternion, used mainly to represent rotations.

A quaternion is stored as its four components [w, x, y, z], where w is the scalar part and (x, y, z) is the vector part. The components are read and written by index, from Q[0] (the scalar part) to Q[3], and negative indices count from the end, as for a list; len(Q) is 4. Quaternions may be copied, deep-copied, and pickled.

The arithmetic operators +, -, *, and / act between two quaternions, and between a quaternion and a float, which is treated as a quaternion with only a scalar part. The product * is the quaternion product, and P / Q is P * Q.inverse(). The power Q ** t is Quaternions.Quaternion.pow. The comparisons == and != compare all four components exactly.

A unit quaternion (a rotor) R represents the rotation that takes a vector v, written as a quaternion with zero scalar part, to R * v * R.inverse(). A sequence of three or four floats is accepted wherever a Quaternion is expected, and is converted as in the constructor Quaternion(q) below. The module also defines the constants Quaternions.Zero, Quaternions.One, Quaternions.xHat, Quaternions.yHat, and Quaternions.zHat.

A Quaternion may be constructed in any of these ways:

Quaternion()

The zero quaternion.

Quaternion(Q)

A copy of the quaternion Q.

Quaternion(vartheta, varphi)

The rotor \(e^{\varphi \hat{z}/2}\, e^{\vartheta \hat{y}/2}\), which rotates the z axis onto the point with polar angle vartheta and azimuthal angle varphi.

Quaternion(alpha, beta, gamma)

The rotor \(e^{\alpha \hat{z}/2}\, e^{\beta \hat{y}/2}\, e^{\gamma \hat{z}/2}\) for the Euler angles alpha, beta, and gamma in the z-y-z convention: a rotation by gamma about the z axis, followed by a rotation by beta about the fixed y axis, and finally a rotation by alpha about the fixed z axis.

Quaternion(w, x, y, z)

The quaternion with the given components.

Quaternion(q)

The quaternion with components taken from the sequence q of floats. Four elements are the components [w, x, y, z]; three elements are the vector part [x, y, z] of a quaternion with zero scalar part. Any other length raises an error.

Quaternion(angle, axis)

The rotor \(\cos(\theta/2) + \sin(\theta/2)\, \hat{n}\) for a rotation through angle \(\theta\) about the three-vector axis \(\hat{n}\), which is assumed to be normalized.

classmethod __new__(*args, **kwargs)
Quaternion.abs() → float

Return the magnitude of this quaternion.

The magnitude is the square root of the sum of the squares of all four components; see also Quaternions.Quaternion.normsquared.

Returns:

float – The magnitude.

Quaternion.normsquared() → float

Return the squared magnitude of this quaternion.

This is the sum of the squares of all four components.

Returns:

float – The squared magnitude.

Quaternion.angle() → float

Return the full angle of the rotation that this rotor represents.

The result is 2 * abs(self.logRotor()). For a unit quaternion \(e^{\theta \hat{n}/2}\) this is the full rotation angle \(\theta\), not half of it, and lies between 0 and \(2\pi\); a rotor and its negative give angles that add to \(2\pi\). For a quaternion that is not normalized, the logarithm of its magnitude also contributes.

Returns:

float – The rotation angle.

Quaternion.conjugate() → Quaternion

Return the conjugate of this quaternion.

The conjugate has the same scalar part and the negated vector part.

Returns:

Quaternion – The conjugate.

Quaternion.inverse() → Quaternion

Return the multiplicative inverse of this quaternion.

The inverse is the conjugate divided by Quaternions.Quaternion.normsquared; for a unit quaternion, it equals the conjugate.

Returns:

Quaternion – The inverse.

Quaternion.normalized() → Quaternion

Return this quaternion divided by its magnitude.

Returns:

Quaternion – The unit quaternion in the same direction.

Quaternion.vec() → ndarray

Return the vector part of this quaternion.

Returns:

ndarray of float, shape (3,) – The components [x, y, z].

Quaternion.log() → Quaternion

Return the natural logarithm of this quaternion.

For a quaternion with magnitude \(|Q|\), vector part \(\vec{v}\), and scalar part \(w\), the logarithm has scalar part \(\ln |Q|\) and vector part \(\operatorname{atan2}(|\vec{v}|, w)\, \vec{v}/|\vec{v}|\). For a rotor \(e^{\theta \hat{n}/2}\) with \(0 \le \theta \le 2\pi\), it is therefore \(\theta \hat{n}/2\).

The logarithm of a negative real number has infinitely many values, so this function raises an error for one; Quaternions.Quaternion.logRotor returns a value instead.

Returns:

Quaternion – The logarithm.

Quaternion.logRotor() → Quaternion

Return the natural logarithm, choosing a value for negative real numbers.

This is the same as Quaternions.Quaternion.log, except for negative real numbers, for which the logarithm has infinitely many values. Instead of raising an error, this function prints a warning and returns \(\ln|w| + \pi \hat{x}\); for the rotor -1, which represents the identity rotation, that is \(\pi \hat{x}\).

Returns:

Quaternion – The logarithm.

Quaternion.exp() → Quaternion

Return the exponential of this quaternion.

For scalar part \(w\) and vector part \(\vec{v}\), the exponential is \(e^{w} \left[\cos|\vec{v}| + \sin|\vec{v}|\, \vec{v}/|\vec{v}|\right]\). In particular, the exponential of \(\theta \hat{n}/2\) is the rotor for a rotation through \(\theta\) about \(\hat{n}\).

Returns:

Quaternion – The exponential.

Quaternion.sqrt() → Quaternion

Return the principal square root of this quaternion.

The result is (self/abs(self) + 1) * sqrt(abs(self) / (2 + 2*w/abs(self))), where w is the scalar part. It is undefined (NaN) for a negative real number. For a unit quaternion, Quaternions.Quaternion.sqrtOfRotor gives the same result more cheaply, and handles the rotor -1.

Returns:

Quaternion – The square root.

Quaternion.sqrtOfRotor() → Quaternion

Return the square root of this quaternion, assuming that it is a rotor.

The result is (1 + self) / sqrt(2 + 2*w), where w is the scalar part, which is the principal square root only when this quaternion has unit magnitude. If w is within 1e-14 of -1, the result is xHat, one of the infinitely many square roots of -1.

Returns:

Quaternion – The square root.

Quaternion.pow(t: float) → Quaternion
Quaternion.pow(Q: Quaternion) → Quaternion

Return this quaternion raised to a real or quaternion power.

The power is computed as exp(log(self) * t) or exp(log(self) * Q), with the logarithm of Quaternions.Quaternion.log; it therefore raises an error when this quaternion is a negative real number. The same operation is written self ** t or self ** Q. Quaternions.pow applies it to arrays.

Parameters:
  • t (float) – The real exponent, in the form pow(t).

  • Q (Quaternion) – The quaternion exponent, in the form pow(Q). It multiplies the logarithm from the right.

Returns:

Quaternion – The power.

Quaternion.dot(Q: Quaternion) → float

Return the dot product of the vector parts of two quaternions.

The scalar parts are ignored, so this is self[1]*Q[1] + self[2]*Q[2] + self[3]*Q[3].

Parameters:

Q (Quaternion) – The second factor.

Returns:

float – The dot product of the vector parts.

Quaternion.cross(Q: Quaternion) → Quaternion

Return the cross product of the vector parts of two quaternions.

The scalar parts are ignored, and the result is a quaternion with zero scalar part whose vector part is the cross product of the vector part of this quaternion with that of Q.

Parameters:

Q (Quaternion) – The second factor.

Returns:

Quaternion – The cross product, as a quaternion with zero scalar part.

Quaternion.commutator(Q: Quaternion) → Quaternion

Return the commutator of this quaternion with another.

The commutator is self * Q - Q * self, which equals twice Quaternions.Quaternion.cross and has zero scalar part.

Parameters:

Q (Quaternion) – The second quaternion.

Returns:

Quaternion – The commutator.

Quaternion.IntrinsicDistance(Q: Quaternion) → float

Return the intrinsic (geodesic) distance between this rotor and another.

The distance is 2 * abs((self * Q.inverse()).logRotor()), which for unit quaternions is the angle of the rotation that takes Q to this rotor, as given by Quaternions.Quaternion.angle. It lies between 0 and \(2\pi\).

Parameters:

Q (Quaternion) – The other rotor.

Returns:

float – The intrinsic distance.

Quaternion.ChordalDistance(Q: Quaternion) → float

Return the chordal distance between this quaternion and another.

The distance is the magnitude of the difference, abs(self - Q).

Parameters:

Q (Quaternion) – The other quaternion.

Returns:

float – The chordal distance.

Quaternion.XParityConjugateSpinor() → Quaternion

Return the image of this rotor under the reflection that reverses the x axis.

Reflecting the space through the y-z plane takes the rotation through an angle about the axis \((n_x, n_y, n_z)\) to the rotation through the same angle about \((n_x, -n_y, -n_z)\), because a rotation axis is a pseudovector. The result is therefore Quaternion(w, x, -y, -z).

Returns:

Quaternion – The reflected rotor.

Quaternion.YParityConjugateSpinor() → Quaternion

Return the image of this rotor under the reflection that reverses the y axis.

Reflecting the space through the x-z plane takes the rotation through an angle about the axis \((n_x, n_y, n_z)\) to the rotation through the same angle about \((-n_x, n_y, -n_z)\), because a rotation axis is a pseudovector. The result is therefore Quaternion(w, -x, y, -z).

Returns:

Quaternion – The reflected rotor.

Quaternion.ZParityConjugateSpinor() → Quaternion

Return the image of this rotor under the reflection that reverses the z axis.

Reflecting the space through the x-y plane takes the rotation through an angle about the axis \((n_x, n_y, n_z)\) to the rotation through the same angle about \((-n_x, -n_y, n_z)\), because a rotation axis is a pseudovector. The result is therefore Quaternion(w, -x, -y, z).

Returns:

Quaternion – The reflected rotor.

Quaternion.ParityConjugateSpinor() → Quaternion

Return the image of this rotor under the parity transformation.

The parity transformation reverses all three axes. A rotation axis is a pseudovector, which parity leaves unchanged, so the result is a copy of this quaternion.

Returns:

Quaternion – A copy of this rotor.

Quaternion.str() → str

Return the four components separated by spaces.

The components appear in the order w x y z, with six significant digits.

Returns:

str – The components.

GWFrames.Quaternions.Zero
GWFrames.Quaternions.One
GWFrames.Quaternions.xHat
GWFrames.Quaternions.yHat
GWFrames.Quaternions.zHat

The quaternions 0 and 1, and the unit basis vectors \(\hat{x}\), \(\hat{y}\), and \(\hat{z}\) as pure-vector quaternions.

Functions of quaternions and arrays

GWFrames.Quaternions.abs(Q: Quaternion) → float
GWFrames.Quaternions.abs(Q: ndarray[Quaternion]) → ndarray

Return the magnitude of a quaternion or of each quaternion in an array.

See Quaternions.Quaternion.abs.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

float or ndarray of float – The magnitude or magnitudes.

GWFrames.Quaternions.normsquared(Q: Quaternion) → float
GWFrames.Quaternions.normsquared(Q: ndarray[Quaternion]) → ndarray

Return the squared magnitude of a quaternion or of each in an array.

The squared magnitude is the sum of the squares of all four components.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

float or ndarray of float – The squared magnitude or magnitudes.

GWFrames.Quaternions.angle(Q: Quaternion) → float
GWFrames.Quaternions.angle(Q: ndarray[Quaternion]) → ndarray

Return the full rotation angle of a rotor or of each rotor in an array.

The angle is 2 * abs(logRotor(Q)), which for a unit quaternion \(e^{\theta \hat{n}/2}\) is the full rotation angle \(\theta\), not half of it, between 0 and \(2\pi\); see Quaternions.Quaternion.angle.

Parameters:

Q (Quaternion or array_like of Quaternion) – The rotor or rotors.

Returns:

float or ndarray of float – The rotation angle or angles.

GWFrames.Quaternions.conjugate(Q: Quaternion) → Quaternion
GWFrames.Quaternions.conjugate(Q: ndarray[Quaternion]) → ndarray[Quaternion]

Return the conjugate of a quaternion or of each quaternion in an array.

The conjugate has the same scalar part and the negated vector part.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

Quaternion or ndarray of Quaternion – The conjugate or conjugates.

GWFrames.Quaternions.inverse(Q: Quaternion) → Quaternion
GWFrames.Quaternions.inverse(Q: ndarray[Quaternion]) → ndarray[Quaternion]

Return the inverse of a quaternion or of each quaternion in an array.

See Quaternions.Quaternion.inverse.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

Quaternion or ndarray of Quaternion – The inverse or inverses.

GWFrames.Quaternions.normalized(Q: Quaternion) → Quaternion
GWFrames.Quaternions.normalized(Q: ndarray[Quaternion]) → ndarray[Quaternion]

Return a quaternion, or each quaternion in an array, divided by its magnitude.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

Quaternion or ndarray of Quaternion – The unit quaternion or quaternions.

GWFrames.Quaternions.vec(Q: Quaternion) → ndarray
GWFrames.Quaternions.vec(Q: ndarray[Quaternion]) → ndarray

Return the vector part of a quaternion or of each quaternion in an array.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

ndarray of float, shape (3,) or (N, 3) – The components [x, y, z], with one row per quaternion if Q is an array of N quaternions.

GWFrames.Quaternions.log(Q: Quaternion) → Quaternion
GWFrames.Quaternions.log(Q: ndarray[Quaternion]) → ndarray[Quaternion]

Return the natural logarithm of a quaternion or of each in an array.

See Quaternions.Quaternion.log; an error is raised for a negative real number, for which Quaternions.logRotor returns a value instead.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

Quaternion or ndarray of Quaternion – The logarithm or logarithms.

GWFrames.Quaternions.logRotor(Q: Quaternion) → Quaternion
GWFrames.Quaternions.logRotor(Q: ndarray[Quaternion]) → ndarray[Quaternion]

Return the logarithm of quaternions, choosing a value for negative reals.

This is the same as Quaternions.log, except that a negative real number gives \(\ln|w| + \pi \hat{x}\), with a warning, instead of an error; see Quaternions.Quaternion.logRotor.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

Quaternion or ndarray of Quaternion – The logarithm or logarithms.

GWFrames.Quaternions.exp(Q: Quaternion) → Quaternion
GWFrames.Quaternions.exp(Q: ndarray[Quaternion]) → ndarray[Quaternion]

Return the exponential of a quaternion or of each quaternion in an array.

See Quaternions.Quaternion.exp.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

Quaternion or ndarray of Quaternion – The exponential or exponentials.

GWFrames.Quaternions.sqrt(Q: Quaternion) → Quaternion
GWFrames.Quaternions.sqrt(Q: ndarray[Quaternion]) → ndarray[Quaternion]

Return the principal square root of a quaternion or of each in an array.

See Quaternions.Quaternion.sqrt. For unit quaternions, Quaternions.sqrtOfRotor gives the same result more cheaply.

Parameters:

Q (Quaternion or array_like of Quaternion) – The quaternion or quaternions.

Returns:

Quaternion or ndarray of Quaternion – The square root or square roots.

GWFrames.Quaternions.sqrtOfRotor(Q: Quaternion) → Quaternion
GWFrames.Quaternions.sqrtOfRotor(Q: ndarray[Quaternion]) → ndarray[Quaternion]

Return the square root of a rotor or of each rotor in an array.

The result is the principal square root only for unit quaternions; see Quaternions.Quaternion.sqrtOfRotor.

Parameters:

Q (Quaternion or array_like of Quaternion) – The rotor or rotors.

Returns:

Quaternion or ndarray of Quaternion – The square root or square roots.

GWFrames.Quaternions.pow(Q: Quaternion, x: float) → Quaternion
GWFrames.Quaternions.pow(
Q: Quaternion,
P: Quaternion,
) → Quaternion
GWFrames.Quaternions.pow(Q: ndarray[Quaternion], x: float) → ndarray[Quaternion]
GWFrames.Quaternions.pow(Q: ndarray[Quaternion], P: Quaternion) → ndarray[Quaternion]
GWFrames.Quaternions.pow(Q: Quaternion, x: ndarray) → ndarray[Quaternion]
GWFrames.Quaternions.pow(Q: Quaternion, P: ndarray[Quaternion]) → ndarray[Quaternion]
GWFrames.Quaternions.pow(Q: ndarray[Quaternion], x: ndarray) → ndarray[Quaternion]
GWFrames.Quaternions.pow(Q: ndarray[Quaternion], P: ndarray[Quaternion]) → ndarray[Quaternion]

Raise quaternions to real or quaternion powers.

Each power is computed as exp(log(Q) * x) or exp(log(Q) * P), as in Quaternions.Quaternion.pow, so it raises an error when a base is a negative real number. Either argument may be a single value or an array. A single value is combined with every element of an array, and two arrays, which must have the same length, are combined element by element.

Parameters:
Returns:

Quaternion or ndarray of Quaternion – The power, or an array of powers if either argument is an array.

GWFrames.Quaternions.dot(Q: Quaternion, P: Quaternion) → float

Return the dot product of the vector parts of two quaternions.

The scalar parts are ignored; see Quaternions.Quaternion.dot.

Parameters:
Returns:

float – The dot product of the vector parts.

GWFrames.Quaternions.cross(
Q: Quaternion,
P: Quaternion,
) → Quaternion

Return the cross product of the vector parts of two quaternions.

The scalar parts are ignored, and the result has zero scalar part; see Quaternions.Quaternion.cross.

Parameters:
Returns:

Quaternion – The cross product, as a quaternion with zero scalar part.

GWFrames.Quaternions.commutator(
Q: Quaternion,
P: Quaternion,
) → Quaternion

Return the commutator of two quaternions.

The commutator is Q * P - P * Q, which equals twice Quaternions.cross.

Parameters:
Returns:

Quaternion – The commutator.

GWFrames.Quaternions.IntrinsicDistance(
R_A: Quaternion,
R_B: Quaternion,
) → float

Return the intrinsic (geodesic) distance between two rotors.

The distance is 2 * abs(logRotor(R_A * R_B.inverse())), which for unit quaternions is the angle of the rotation that takes R_B to R_A. It lies between 0 and \(2\pi\).

Parameters:
Returns:

float – The intrinsic distance.

GWFrames.Quaternions.ChordalDistance(R_A: Quaternion, R_B: Quaternion) → float

Return the chordal distance between two quaternions.

The distance is the magnitude of the difference, abs(R_A - R_B).

Parameters:
Returns:

float – The chordal distance.

GWFrames.Quaternions.Slerp(
tau: float,
Qa: Quaternion,
Qb: Quaternion,
) → Quaternion

Interpolate spherically and linearly between two rotors.

The result is pow(Qb / Qa, tau) * Qa, which moves from Qa at tau = 0 to Qb at tau = 1 along a geodesic. Values of tau outside that interval extrapolate along the same geodesic.

Parameters:
  • tau (float) – The interpolation parameter.

  • Qa (Quaternion) – The rotor at tau = 0.

  • Qb (Quaternion) – The rotor at tau = 1.

Returns:

Quaternion – The interpolated rotor.

GWFrames.Quaternions.XParityConjugateSpinor(Q: Quaternion) → Quaternion

Return the image of a rotor under the reflection that reverses the x axis.

The result is Quaternion(w, x, -y, -z); see Quaternions.Quaternion.XParityConjugateSpinor.

Parameters:

Q (Quaternion) – The rotor.

Returns:

Quaternion – The reflected rotor.

GWFrames.Quaternions.YParityConjugateSpinor(Q: Quaternion) → Quaternion

Return the image of a rotor under the reflection that reverses the y axis.

The result is Quaternion(w, -x, y, -z); see Quaternions.Quaternion.YParityConjugateSpinor.

Parameters:

Q (Quaternion) – The rotor.

Returns:

Quaternion – The reflected rotor.

GWFrames.Quaternions.ZParityConjugateSpinor(Q: Quaternion) → Quaternion

Return the image of a rotor under the reflection that reverses the z axis.

The result is Quaternion(w, -x, -y, z); see Quaternions.Quaternion.ZParityConjugateSpinor.

Parameters:

Q (Quaternion) – The rotor.

Returns:

Quaternion – The reflected rotor.

GWFrames.Quaternions.ParityConjugateSpinor(Q: Quaternion) → Quaternion

Return the image of a rotor under the parity transformation.

Parity leaves a rotation axis unchanged, so the result is a copy of Q; see Quaternions.Quaternion.ParityConjugateSpinor.

Parameters:

Q (Quaternion) – The rotor.

Returns:

Quaternion – A copy of the rotor.

Constructing and taking apart arrays

GWFrames.Quaternions.QuaternionArray(vartheta: ndarray, varphi: ndarray) → ndarray[Quaternion]
GWFrames.Quaternions.QuaternionArray(
alpha: ndarray,
beta: ndarray,
gamma: ndarray,
) → ndarray[Quaternion]
GWFrames.Quaternions.QuaternionArray(
w: ndarray,
x: ndarray,
y: ndarray,
z: ndarray,
) → ndarray[Quaternion]
GWFrames.Quaternions.QuaternionArray(q: ndarray) → ndarray[Quaternion]
GWFrames.Quaternions.QuaternionArray(angle: ndarray, axis: ndarray) → ndarray[Quaternion]

Construct an array of quaternions from arrays of numbers.

The forms of this function match the constructors of Quaternions.Quaternion, applied element by element:

QuaternionArray(vartheta, varphi)

Rotors that rotate the z axis onto the points with polar angles vartheta and azimuthal angles varphi.

QuaternionArray(alpha, beta, gamma)

Rotors for the z-y-z Euler angles alpha, beta, and gamma.

QuaternionArray(w, x, y, z)

Quaternions with the given components.

QuaternionArray(q)

Quaternions whose components are the rows of q; each row has three elements (the vector part) or four (all components).

QuaternionArray(angle, axis)

Rotors for rotations through each angle about the corresponding row of axis, which is assumed to be normalized.

The length of the result is that of the first argument, and the other arguments must be at least as long.

Parameters:
Returns:

ndarray of Quaternion – The quaternions.

GWFrames.Quaternions.Component(Q: ndarray[Quaternion], i: int) → ndarray

Return one component of each quaternion in an array.

Parameters:
  • Q (array_like of Quaternion) – The quaternions.

  • i (int) – Index of the component: 0 for the scalar part, and 1, 2, or 3 for the x, y, or z component of the vector part. Any other value raises an error.

Returns:

ndarray of float – The i-th component of each quaternion.

GWFrames.Quaternions.Component0(Q: ndarray[Quaternion]) → ndarray

Return the scalar component of each quaternion in an array.

This is Component(Q, 0).

Parameters:

Q (array_like of Quaternion) – The quaternions.

Returns:

ndarray of float – The scalar component of each quaternion.

GWFrames.Quaternions.Component1(Q: ndarray[Quaternion]) → ndarray

Return the x component of each quaternion in an array.

This is Component(Q, 1).

Parameters:

Q (array_like of Quaternion) – The quaternions.

Returns:

ndarray of float – The x component of each quaternion.

GWFrames.Quaternions.Component2(Q: ndarray[Quaternion]) → ndarray

Return the y component of each quaternion in an array.

This is Component(Q, 2).

Parameters:

Q (array_like of Quaternion) – The quaternions.

Returns:

ndarray of float – The y component of each quaternion.

GWFrames.Quaternions.Component3(Q: ndarray[Quaternion]) → ndarray

Return the z component of each quaternion in an array.

This is Component(Q, 3).

Parameters:

Q (array_like of Quaternion) – The quaternions.

Returns:

ndarray of float – The z component of each quaternion.

Calculus and frames

GWFrames.Quaternions.FrameFromAngularVelocity(
Omega: ndarray[Quaternion],
T: ndarray,
) → ndarray[Quaternion]

Find the frame with the given angular velocity.

The frame starts as the identity at T[0]. The logarithm of its rotor is integrated in time, using Quaternions.FrameFromAngularVelocity_Integrand with Omega interpolated by cubic splines, and the result is exponentiated and passed through Quaternions.UnflipRotors. The logarithm is replaced by an equivalent one of smaller magnitude whenever its magnitude exceeds \(\pi/2\), much as a complex logarithm changes branch.

The accuracy is limited, because the integration cannot adapt its steps to anything finer than the interpolated data.

Parameters:
Returns:

ndarray of Quaternion – The rotors of the frame at the times T.

GWFrames.Quaternions.FrameFromAngularVelocity_2D(
Omega: ndarray[Quaternion],
T: ndarray,
) → ndarray[Quaternion]

Find a frame from an angular velocity, keeping its logarithm in the x-y plane.

This is like Quaternions.FrameFromAngularVelocity, except that the logarithm of each rotor is constrained to have no z component. The time derivative of the logarithm is given by Quaternions.FrameFromAngularVelocity_2D_Integrand, which adjusts the angular velocity to maintain that constraint. The frame starts as the identity at T[0].

Parameters:
Returns:

ndarray of Quaternion – The rotors of the frame at the times T.

GWFrames.Quaternions.FrameFromAngularVelocity_Integrand(r: ndarray, Omega: ndarray) → ndarray

Return the time derivative of the logarithm of a rotating frame’s rotor.

If the frame’s rotor is \(R = e^{\mathfrak{r}}\), with angular velocity \(\vec{\Omega}\) defined by \(\dot{R} = \vec{\Omega} R/2\), this function returns \(\dot{\mathfrak{r}}\). Integrating it gives the logarithm of the frame, which can then be exponentiated to give the rotor.

Parameters:
  • r (array_like of float, shape (3,)) – The vector part of the logarithm of the current rotor.

  • Omega (array_like of float, shape (3,)) – The instantaneous angular-velocity vector of the frame.

Returns:

ndarray of float, shape (3,) – The time derivative of r.

GWFrames.Quaternions.FrameFromAngularVelocity_2D_Integrand(
r_x: float,
r_y: float,
Omega: ndarray,
) → tuple[float, float]

Return the time derivative of a two-dimensional rotor logarithm, as the tuple (rdot_x, rdot_y).

GWFrames.Quaternions.FrameAngularVelocity(f: ndarray[Quaternion], t: ndarray) → ndarray[Quaternion]

Return the angular velocity of a frame given by rotors.

The angular velocity is \(2 \dot{R} \bar{R}\), with the derivative computed by Quaternions.QuaternionDerivative. For unit rotors, each result has zero scalar part, and its vector part is the angular-velocity vector in the fixed frame.

Parameters:
Returns:

ndarray of Quaternion – The angular velocity at each time.

GWFrames.Quaternions.MinimalRotation(
R: ndarray[Quaternion],
T: ndarray,
NIterations: int = 5,
) → ndarray[Quaternion]

Return the minimal-rotation version of a frame.

The returned rotors take the z axis to the same direction as the rotors R do, but the rotation about that direction is adjusted to impose the minimal-rotation condition: the angular velocity of the frame has no component along its rotated z axis. The adjustment is computed by integrating the unwanted rotation rate over time and removing it, and the process is repeated NIterations times to refine the result.

Parameters:
Returns:

ndarray of Quaternion – The rotors of the minimal-rotation frame.

GWFrames.Quaternions.PrescribedRotation(
RotationRateAboutZ: ndarray,
R: ndarray[Quaternion],
T: ndarray,
NIterations: int = 5,
) → ndarray[Quaternion]

Return a frame with the same z axis as the input and a prescribed spin rate.

The returned rotors take the z axis to the same direction as the rotors R do, but the rotation about that direction is adjusted, as in Quaternions.MinimalRotation, so that the frame rotates about its rotated z axis at the rate given by RotationRateAboutZ. The process is repeated NIterations times to refine the result, and progress messages are printed to standard output.

Parameters:
  • RotationRateAboutZ (array_like of float) – Rate of rotation of the new frame about its rotated z axis at each time.

  • R (array_like of Quaternion) – The rotors of the input frame.

  • T (array_like of float) – The corresponding times.

  • NIterations (int, default 5) – Number of refinements.

Returns:

ndarray of Quaternion – The rotors of the new frame.

GWFrames.Quaternions.FrameFromXY(X: ndarray[Quaternion], Y: ndarray[Quaternion]) → ndarray[Quaternion]

Construct the frame with the given X and Y basis vectors.

At each time, the returned rotor rotates the fixed basis vectors \((\hat{x}, \hat{y}, \hat{z})\) onto the frame’s basis vectors \((\hat{X}, \hat{Y}, \hat{Z})\).

Parameters:
Returns:

ndarray of Quaternion – The rotors of the frame.

GWFrames.Quaternions.FrameFromZ(
Z: ndarray[Quaternion],
T: ndarray,
NIterations: int = 5,
) → ndarray[Quaternion]

Construct the minimal-rotation frame with the given Z basis vector.

At each time, the returned rotor rotates the fixed basis vectors \((\hat{x}, \hat{y}, \hat{z})\) onto the frame’s basis vectors \((\hat{X}, \hat{Y}, \hat{Z})\). The X and Y basis vectors are determined by the minimal-rotation condition of Quaternions.MinimalRotation, which leaves the initial rotation about the Z axis arbitrary.

Parameters:
Returns:

ndarray of Quaternion – The rotors of the frame.

GWFrames.Quaternions.FrameFromPrescribedRotation(
omega: ndarray[Quaternion],
T: ndarray,
NIterations: int = 5,
) → ndarray[Quaternion]

Construct the frame whose Z axis and spin rate follow an angular velocity.

At each time, the returned rotor rotates the fixed basis vectors \((\hat{x}, \hat{y}, \hat{z})\) onto the frame’s basis vectors \((\hat{X}, \hat{Y}, \hat{Z})\). The Z basis vector is parallel to omega, and the X and Y basis vectors are determined, with Quaternions.PrescribedRotation, by the condition that the frame rotates about its Z axis at the rate abs(omega). This leaves the initial rotation in the X-Y plane arbitrary. Progress messages are printed to standard output.

Parameters:
Returns:

ndarray of Quaternion – The rotors of the frame.

GWFrames.Quaternions.DifferentiateRotorByLogarithm(
RIn: ndarray[Quaternion],
tIn: ndarray,
) → ndarray[Quaternion]

Differentiate a rotor function of time by way of its logarithm.

The logarithm of each rotor is computed with Quaternions.logRotor and differentiated with Quaternions.QuaternionDerivative, and the derivative of the rotor is then found from the analytic formula for the derivative of the exponential. This is more complicated than differentiating the rotors directly with Quaternions.QuaternionDerivative, but it may be more accurate when the logarithm is smooth, and it serves as a test of the logarithm formula.

Parameters:
Returns:

ndarray of Quaternion – The time derivative of the rotors.

GWFrames.Quaternions.QuaternionDerivative(f: ndarray[Quaternion], t: ndarray) → ndarray[Quaternion]

Differentiate a quaternion function of time by finite differences.

The derivative is computed with the five-point formula of Eq. (A 5b) of Bowen and Smith, “Derivative formulas and errors for non-uniformly spaced points”, which is fourth-order accurate, as they explain in Eqs. (B 9b) and (B 10b). The times need not be uniformly spaced. With three or four points, the derivative uses three-point formulas, at interior points from Sundqvist and Veronis, Tellus XXII (1970), 1; with two points, it is the slope between them. Fewer than two points, or arrays of different lengths, raise an error.

Parameters:
Returns:

ndarray of Quaternion – The time derivative at each time.

GWFrames.Quaternions.IndefiniteIntegral(RIn: ndarray[Quaternion], tIn: ndarray) → ndarray[Quaternion]

Integrate a quaternion function of time, returning the integral at each time.

Each component is integrated separately by the trapezoidal rule, starting from zero at the first time.

Parameters:
Returns:

ndarray of Quaternion – The integral from tIn[0] to each time in tIn.

GWFrames.Quaternions.DefiniteIntegral(
RIn: ndarray[Quaternion],
tIn: ndarray,
) → Quaternion

Integrate a quaternion function of time over all of the given times.

Each component is integrated separately by the trapezoidal rule. The result equals the last element of Quaternions.IndefiniteIntegral.

Parameters:
Returns:

Quaternion – The integral from tIn[0] to tIn[-1].

GWFrames.Quaternions.UnflipRotors(
R: ndarray[Quaternion],
discont: float = 1.4142135623730951,
) → ndarray[Quaternion]

Remove sign flips from a time series of rotors.

A rotor and its negative represent the same rotation, so the sign of a rotor is often arbitrary, and discontinuous flips in that sign cause problems for rotor-valued functions of time. This function negates each rotor whose distance from the previous output rotor exceeds discont, so that successive rotors are within discont of each other.

Parameters:
  • R (array_like of Quaternion) – The rotors.

  • discont (float, default 1.4142135623730951) – The largest acceptable chordal distance between successive rotors; the default is \(\sqrt{2}\).

Returns:

ndarray of Quaternion – The rotors, with signs made continuous.

GWFrames.Quaternions.RDelta(
R1: ndarray[Quaternion],
R2: ndarray[Quaternion],
IndexOfFiducialTime: int = -1,
) → ndarray[Quaternion]

Return the rotors R1 * R2.inverse() relating two frames.

If IndexOfFiducialTime is not negative, the result is instead R1 * Offset * R2.inverse(), where Offset is R1[I].inverse() * R2[I] for I = IndexOfFiducialTime, which ensures that the result is 1 at that index.

Parameters:
  • R1 (array_like of Quaternion) – The first rotors.

  • R2 (array_like of Quaternion) – The second rotors, of the same length as R1.

  • IndexOfFiducialTime (int, default -1) – Index of the time at which the difference is set to the identity, or a negative number for no offset.

Returns:

ndarray of Quaternion – The difference rotors.

GWFrames.Quaternions.Squad(
RIn: ndarray[Quaternion],
tIn: ndarray,
tOut: ndarray,
) → ndarray[Quaternion]

Interpolate a time series of rotors with Squad.

Squad is a version of cubic-spline interpolation designed for unit quaternions, which gives more accurate, smoother, and more physical rotations than other forms of interpolation. The input rotors are assumed to have unit magnitude, and the output rotors are passed through Quaternions.UnflipRotors. Times in tOut outside the range of tIn raise an error.

Parameters:
Returns:

ndarray of Quaternion – The interpolated rotors.

GWFrames.Quaternions.BoostRotor(
ThreeVelocity: ndarray,
ThreeVectorToBeBoosted: ndarray,
) → Quaternion

Return a rotor taking a direction to its boosted version.

This function returns a rotor \(R_b\) that takes the input direction \(\hat{w}\), considered as a direction on the future null sphere, to the direction that it has after the boost. The rotor therefore depends on both the boost and the direction. It is the identity when the velocity is negligible or parallel to the direction.

Parameters:
  • ThreeVelocity (array_like of float, shape (3,)) – Velocity of the new frame relative to the current frame, in units where the speed of light is 1.

  • ThreeVectorToBeBoosted (array_like of float, shape (3,)) – The direction \(\hat{w}\) to be boosted, which is normalized first. A zero vector raises an error.

Returns:

Quaternion – The rotor \(R_b\).

Mean rotors and alignment

GWFrames.Quaternions.MeanRotor(R: ndarray[Quaternion]) → Quaternion
GWFrames.Quaternions.MeanRotor(
R: ndarray[Quaternion],
t: ndarray,
t1: float = -1e+300,
t2: float = 1e+300,
) → Quaternion

Return the mean of a set of rotors.

The mean minimizes the sum of the squared intrinsic distances between the rotors R and the mean or, if the times t are given, the integral of the squared intrinsic distance over the times from t1 to t2. The minimum is found with the Nelder-Mead simplex algorithm of GSL, starting from Quaternions.ApproximateMeanRotor. This mean is described in <https://arxiv.org/abs/1302.2919>.

Parameters:
  • R (array_like of Quaternion) – The rotors to be averaged.

  • t (array_like of float, optional) – The corresponding times. If omitted, the rotors are weighted equally.

  • t1 (float, default -1e300) – Earliest time included in the average; the default means t[0].

  • t2 (float, default 1e300) – Latest time included in the average; the default means t[-1].

Returns:

Quaternion – The mean rotor.

GWFrames.Quaternions.ApproximateMeanRotor(R: ndarray[Quaternion]) → Quaternion
GWFrames.Quaternions.ApproximateMeanRotor(
R: ndarray[Quaternion],
t: ndarray,
t1: float = -1e+300,
t2: float = 1e+300,
) → Quaternion

Return an approximate mean of a set of rotors.

The mean is the normalized sum of the rotors R or, if the times t are given, the normalized trapezoidal integral of R over the times from t1 to t2. This minimizes the sum, or integral, of the squared chordal distance to the mean, rather than of the squared intrinsic distance that Quaternions.MeanRotor minimizes. The two agree in the limit that the rotors are all equal, and this function requires no numerical optimization. The rotors should be continuous in sign, as Quaternions.UnflipRotors makes them.

Parameters:
  • R (array_like of Quaternion) – The rotors to be averaged.

  • t (array_like of float, optional) – The corresponding times. If omitted, the rotors are weighted equally.

  • t1 (float, default -1e300) – Earliest time included in the average.

  • t2 (float, default 1e300) – Latest time included in the average.

Returns:

Quaternion – The mean rotor.

References

The discrete formula is from Moakher, “Means and averaging in the group of rotations”, SIAM J. Matrix Anal. Appl. 24, 1 (2002); the version with times is its continuous limit.

GWFrames.Quaternions.ApproximateOptimalAlignmentRotor(
Ra: ndarray[Quaternion],
Rb: ndarray[Quaternion],
t: ndarray,
t1: float = -1e+300,
t2: float = 1e+300,
) → Quaternion

Return the rotor R_delta for which R_delta * Rb best matches Ra.

The result is the Quaternions.ApproximateMeanRotor of RDelta(Ra, Rb), averaged over the times from t1 to t2. Multiplying Rb on the left by it gives a new time series that is approximately as close to Ra as possible.

Parameters:
Returns:

Quaternion – The rotor R_delta.

GWFrames.Quaternions.ApproximateOptimalAlignment(
t1: float,
t2: float,
Ra: ndarray[Quaternion],
ta: ndarray,
Rb: ndarray[Quaternion],
tb: ndarray,
) → tuple[float, Quaternion]

Find a time shift and rotor that approximately align two rotor time series.

The time offset deltat is optimized numerically, and for each trial offset the rotor R_delta is found analytically by Quaternions.ApproximateOptimalAlignmentRotor. Together they make R_delta * Rb, with its times shifted to tb + deltat, as close as possible to Ra over the interval from t1 to t2, as measured by the integral of the squared intrinsic distance. The times t1 and t2 are fixed with respect to ta, and must lie within the ranges of both ta and tb. Quaternions.OptimalAlignment refines the result.

Parameters:
Returns:

  • deltat (float) – The optimal time offset.

  • R_delta (Quaternion) – The optimal rotor.

GWFrames.Quaternions.OptimalAlignment(
t1: float,
t2: float,
Ra: ndarray[Quaternion],
ta: ndarray,
Rb: ndarray[Quaternion],
tb: ndarray,
) → tuple[float, Quaternion]

Find the time shift and rotor that best align two rotor time series.

Starting from the result of Quaternions.ApproximateOptimalAlignment, the time offset deltat and all three rotational degrees of freedom of the rotor R_delta are optimized together, with the Nelder-Mead simplex algorithm of GSL. The quantity minimized is the integral, over the interval from t1 to t2, of the squared intrinsic distance between Ra and R_delta * Rb, with the times of Rb shifted to tb + deltat. The times t1 and t2 are fixed with respect to ta, and must lie within the ranges of both ta and tb.

Parameters:
Returns:

  • deltat (float) – The optimal time offset.

  • R_delta (Quaternion) – The optimal rotor.

Searching sorted arrays

GWFrames.Quaternions.hunt(x: ndarray, x_i: float, i: int = 0) → int

Return the largest index j with x[j] <= x_i in a sorted array.

The search starts from the guess i and expands outward, as in the Numerical Recipes routine of the same name, so it is fast when the guess is close. If x_i is less than x[0], the result is 0, and if x_i is at least x[-1], the result is len(x) - 1. An empty array raises an error.

Parameters:
  • x (array_like of float) – The sorted array.

  • x_i (float) – The value to locate.

  • i (int, default 0) – Initial guess for the index.

Returns:

int – The index.

GWFrames.Quaternions.huntRight(x: ndarray, x_i: float, i: int = 0) → int

Return one more than the index found by Quaternions.hunt.

For x[0] <= x_i < x[-1], this is the smallest index j with x[j] > x_i. If x_i is less than x[0], the result is 1, and if x_i is at least x[-1], the result is len(x).

Parameters:
  • x (array_like of float) – The sorted array.

  • x_i (float) – The value to locate.

  • i (int, default 0) – Initial guess for the index.

Returns:

int – The index.