# `psychopy.tools.mathtools`¶

Assorted math functions for working with vectors, matrices, and quaternions. These functions are intended to provide basic support for common mathematical operations associated with displaying stimuli (e.g. animation, posing, rendering, etc.)

For tools related to view transformations, see `viewtools`.

## Performance and Optimization¶

Most functions listed here are very fast, however they are optimized to work on arrays of values (vectorization). Calling functions repeatedly (for instance within a loop), should be avoided as the CPU overhead associated with each function call (not to mention the loop itself) can be considerable.

For example, one may want to normalize a bunch of randomly generated vectors by calling `normalize()` on each row:

```v = np.random.uniform(-1.0, 1.0, (1000, 4,))  # 1000 length 4 vectors
vn = np.zeros((1000, 4))  # place to write values

# don't do this!
for i in range(1000):
vn[i, :] = normalize(v[i, :])
```

The same operation is completed in considerably less time by passing the whole array to the function like so:

```normalize(v, out=vn)  # very fast!
vn = normalize(v)  # also fast if `out` is not provided
```

Specifying an output array to out will improve performance by reducing overhead associated with allocating memory to store the result (functions do this automatically if out is not provided). However, out should only be provided if the output array is reused multiple times. Furthermore, the function still returns a value if out is provided, but the returned value is a reference to out, not a copy of it. If out is not provided, the function will return the result with a freshly allocated array.

## Data Types¶

Sub-routines used by the functions here will perform arithmetic using 64-bit floating-point precision unless otherwise specified via the dtype argument. This functionality is helpful in certain applications where input and output arrays demand a specific type (eg. when working with data passed to and from OpenGL functions).

If a dtype is specified, input arguments will be coerced to match that type and all floating-point arithmetic will use the precision of the type. If input arrays have the same type as dtype, they will automatically pass-through without being recast as a different type. As a performance consideration, all input arguments should have matching types and dtype set accordingly.

Most functions have an out argument, where one can specify an array to write values to. The value of dtype is ignored if out is provided, and all input arrays will be converted to match the dtype of out (if not already). This ensures that the type of the destination array is used.

Various math functions for working with vectors, matrices, and quaternions.

## Overview¶

 `length`(v[, squared, out, dtype]) Get the length of a vector. `normalize`(v[, out, dtype]) Normalize a vector or quaternion. `orthogonalize`(v, n[, out, dtype]) Orthogonalize a vector relative to a normal vector. `reflect`(v, n[, out, dtype]) Reflection of a vector. `dot`(v0, v1[, out, dtype]) Dot product of two vectors. `cross`(v0, v1[, out, dtype]) Cross product of 3D vectors. `project`(v0, v1[, out, dtype]) Project a vector onto another. `lerp`(v0, v1, t[, out, dtype]) Linear interpolation (LERP) between two vectors/coordinates. `distance`(v0, v1[, out, dtype]) Get the distance between vectors/coordinates. `angleTo`(v, point[, degrees, out, dtype]) Get the relative angle to a point from a vector. `surfaceNormal`(tri[, norm, out, dtype]) Compute the surface normal of a given triangle. `surfaceBitangent`(tri, uv[, norm, out, dtype]) Compute the bitangent vector of a given triangle. `surfaceTangent`(tri, uv[, norm, out, dtype]) Compute the tangent vector of a given triangle. `vertexNormal`(faceNorms[, norm, out, dtype]) Compute a vertex normal from shared triangles. `slerp`(q0, q1, t[, shortest, out, dtype]) Spherical linear interpolation (SLERP) between two quaternions. `quatToAxisAngle`(q[, degrees, dtype]) Convert a quaternion to axis and angle representation. `quatFromAxisAngle`(axis, angle[, degrees, dtype]) Create a quaternion to represent a rotation about axis vector by angle. `quatMagnitude`(q[, squared, out, dtype]) Get the magnitude of a quaternion. `multQuat`(q0, q1[, out, dtype]) Multiply quaternion q0 and q1. `invertQuat`(q[, out, dtype]) Get tht multiplicative inverse of a quaternion. `applyQuat`(q, points[, out, dtype]) Rotate points/coordinates using a quaternion. `matrixFromQuat` `scaleMatrix`(s[, out, dtype]) Create a scaling matrix. `rotationMatrix`(angle[, axis, out, dtype]) Create a rotation matrix. `translationMatrix`(t[, out, dtype]) Create a translation matrix. `invertMatrix`(m[, homogeneous, out, dtype]) Invert a 4x4 matrix. `concatenate`(matrices[, out, dtype]) Concatenate matrix transformations. `applyMatrix`(m, points[, out, dtype]) Apply a transformation matrix over a 2D array of points. `posOriToMatrix`(pos, ori[, out, dtype]) Convert a rigid body pose to a 4x4 transformation matrix. `transform`(pos, ori, points[, out, dtype]) Transform points using a position and orientation.

## Details¶

`psychopy.tools.mathtools.``length`(v, squared=False, out=None, dtype=None)[source]

Get the length of a vector.

Parameters: v (array_like) – Vector to normalize, can be Nx2, Nx3, or Nx4. If a 2D array is specified, rows are treated as separate vectors. squared (bool, optional) – If `True` the squared length is returned. The default is `False`. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If None is specified, the data type of out is used. If out is not provided, ‘float64’ is used by default. Length of vector v. float or ndarray
`psychopy.tools.mathtools.``normalize`(v, out=None, dtype=None)[source]

Normalize a vector or quaternion.

v : array_like
Vector to normalize, can be Nx2, Nx3, or Nx4. If a 2D array is specified, rows are treated as separate vectors.
out : ndarray, optional
Optional output array. Must be same shape and dtype as the expected output if out was not specified.
dtype : dtype or str, optional
Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’.
Returns: Normalized vector v. ndarray

Notes

• If the vector is degenerate (length is zero), a vector of all zeros is returned.

Examples

Normalize a vector:

```v = [1., 2., 3., 4.]
vn = normalize(v)
```

The normalize function is vectorized. It’s considerably faster to normalize large arrays of vectors than to call normalize separately for each one:

```v = np.random.uniform(-1.0, 1.0, (1000, 4,))  # 1000 length 4 vectors
vn = np.zeros((1000, 4))  # place to write values
normalize(v, out=vn)  # very fast!

# don't do this!
for i in range(1000):
vn[i, :] = normalize(v[i, :])
```
`psychopy.tools.mathtools.``orthogonalize`(v, n, out=None, dtype=None)[source]

Orthogonalize a vector relative to a normal vector.

This function ensures that v is perpendicular (or orthogonal) to n.

Parameters: v (array_like) – Vector to orthogonalize, can be Nx2, Nx3, or Nx4. If a 2D array is specified, rows are treated as separate vectors. n (array_like) – Normal vector, must have same shape as v. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Orthogonalized vector v relative to normal vector n. ndarray

Warning

If v and n are the same, the direction of the perpendicular vector is indeterminate. The resulting vector is degenerate (all zeros).

`psychopy.tools.mathtools.``reflect`(v, n, out=None, dtype=None)[source]

Reflection of a vector.

Get the reflection of v relative to normal n.

Parameters: v (array_like) – Vector to reflect, can be Nx2, Nx3, or Nx4. If a 2D array is specified, rows are treated as separate vectors. n (array_like) – Normal vector, must have same shape as v. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Reflected vector v off normal n. ndarray
`psychopy.tools.mathtools.``dot`(v0, v1, out=None, dtype=None)[source]

Dot product of two vectors.

The behaviour of this function depends on the format of the input arguments:

• If v0 and v1 are 1D, the dot product is returned as a scalar and out is ignored.
• If v0 and v1 are 2D, a 1D array of dot products between corresponding row vectors are returned.
• If either v0 and v1 are 1D and 2D, an array of dot products between each row of the 2D vector and the 1D vector are returned.
Parameters: v1 (v0,) – Vector(s) to compute dot products of (e.g. [x, y, z]). v0 must have equal or fewer dimensions than v1. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Dot product(s) of v0 and v1. ndarray
`psychopy.tools.mathtools.``cross`(v0, v1, out=None, dtype=None)[source]

Cross product of 3D vectors.

The behavior of this function depends on the dimensions of the inputs:

• If v0 and v1 are 1D, the cross product is returned as 1D vector.
• If v0 and v1 are 2D, a 2D array of cross products between corresponding row vectors are returned.
• If either v0 and v1 are 1D and 2D, an array of cross products between each row of the 2D vector and the 1D vector are returned.
Parameters: v1 (v0,) – Vector(s) in form [x, y, z] or [x, y, z, 1]. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Cross product of v0 and v1. ndarray

Notes

• If input vectors are 4D, the last value of cross product vectors is always set to one.
• If input vectors v0 and v1 are Nx3 and out is Nx4, the cross product is computed and the last column of out is filled with ones.

Examples

Find the cross product of two vectors:

```a = normalize([1, 2, 3])
b = normalize([3, 2, 1])
c = cross(a, b)
```

If input arguments are 2D, the function returns the cross products of corresponding rows:

```# create two 6x3 arrays with random numbers
shape = (6, 3,)
a = normalize(np.random.uniform(-1.0, 1.0, shape))
b = normalize(np.random.uniform(-1.0, 1.0, shape))
cprod = np.zeros(shape)  # output has the same shape as inputs
cross(a, b, out=cprod)
```

If a 1D and 2D vector are specified, the cross product of each row of the 2D array and the 1D array is returned:

```# create two 6x3 arrays with random numbers
a = normalize([1, 2, 3])
b = normalize(np.random.uniform(-1.0, 1.0, (6, 3,)))
cprod = np.zeros(a.shape)
cross(a, b, out=cprod)
```
`psychopy.tools.mathtools.``project`(v0, v1, out=None, dtype=None)[source]

Project a vector onto another.

Parameters: v0 (array_like) – Vector can be Nx2, Nx3, or Nx4. If a 2D array is specified, rows are treated as separate vectors. v1 (array_like) – Vector to project onto v0. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Projection of vector v0 on v1. ndarray or float
`psychopy.tools.mathtools.``lerp`(v0, v1, t, out=None, dtype=None)[source]

Linear interpolation (LERP) between two vectors/coordinates.

Parameters: v0 (array_like) – Initial vector/coordinate. Can be 2D where each row is a point. v1 (array_like) – Final vector/coordinate. Must be the same shape as v0. t (float) – Interpolation weight factor [0, 1]. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Vector at t with same shape as v0 and v1. ndarray

Examples

Find the coordinate of the midpoint between two vectors:

```u = [0., 0., 0.]
v = [0., 0., 1.]
midpoint = lerp(u, v, 0.5)  # 0.5 to interpolate half-way between points
```
`psychopy.tools.mathtools.``distance`(v0, v1, out=None, dtype=None)[source]

Get the distance between vectors/coordinates.

The behaviour of this function depends on the format of the input arguments:

• If v0 and v1 are 1D, the distance is returned as a scalar and out is ignored.
• If v0 and v1 are 2D, an array of distances between corresponding row vectors are returned.
• If either v0 and v1 are 1D and 2D, an array of distances between each row of the 2D vector and the 1D vector are returned.
Parameters: v1 (v0,) – Vectors to compute the distance between. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Distance between vectors v0 and v1. ndarray
`psychopy.tools.mathtools.``angleTo`(v, point, degrees=True, out=None, dtype=None)[source]

Get the relative angle to a point from a vector.

The behaviour of this function depends on the format of the input arguments:

• If v0 and v1 are 1D, the angle is returned as a scalar and out is ignored.
• If v0 and v1 are 2D, an array of angles between corresponding row vectors are returned.
• If either v0 and v1 are 1D and 2D, an array of angles between each row of the 2D vector and the 1D vector are returned.
Parameters: v (array_like) – Direction vector [x, y, z]. point (array_like) – Point(s) to compute angle to from vector v. degrees (bool, optional) – Return the resulting angles in degrees. If False, angles will be returned in radians. Default is True. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Distance between vectors v0 and v1. ndarray
`psychopy.tools.mathtools.``surfaceNormal`(tri, norm=True, out=None, dtype=None)[source]

Compute the surface normal of a given triangle.

Parameters: tri (array_like) – Triangle vertices as 2D (3x3) array [p0, p1, p2] where each vertex is a length 3 array [vx, xy, vz]. The input array can be 3D (Nx3x3) to specify multiple triangles. norm (bool, optional) – Normalize computed surface normals if `True`, default is `True`. out (ndarray, optional) – Optional output array. Must have one fewer dimensions than tri. The shape of the last dimension must be 3. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Surface normal of triangle tri. ndarray

Examples

Compute the surface normal of a triangle:

```vertices = [[-1., 0., 0.], [0., 1., 0.], [1, 0, 0]]
norm = surfaceNormal(vertices)
```

Find the normals for multiple triangles, and put results in a pre-allocated array:

```vertices = [[[-1., 0., 0.], [0., 1., 0.], [1, 0, 0]],  # 2x3x3
[[1., 0., 0.], [0., 1., 0.], [-1, 0, 0]]]
normals = np.zeros((2, 3))  # normals from two triangles triangles
surfaceNormal(vertices, out=normals)
```
`psychopy.tools.mathtools.``surfaceBitangent`(tri, uv, norm=True, out=None, dtype=None)[source]

Compute the bitangent vector of a given triangle.

Uses texture coordinates at each triangle vertex to determine the direction of the vector. This function can be used to generate bitangent vertex attributes for normal mapping. After computing bitangents, one may orthogonalize them with vertex normals using the `orthogonalize()` function, or within the fragment shader.

Parameters: tri (array_like) – Triangle vertices as 2D (3x3) array [p0, p1, p2] where each vertex is a length 3 array [vx, xy, vz]. The input array can be 3D (Nx3x3) to specify multiple triangles. uv (array_like) – Texture coordinates associated with each face vertex as a 2D array (3x2) where each texture coordinate is length 2 array [u, v]. The input array can be 3D (Nx3x2) to specify multiple texture coordinates if multiple triangles are specified. norm (bool, optional) – Normalize computed bitangents if `True`, default is `True`. out (ndarray, optional) – Optional output array. Must have one fewer dimensions than tri. The shape of the last dimension must be 3. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Surface bitangent of triangle tri. ndarray

Examples

Computing the bitangents for two triangles from vertex and texture coordinates (UVs):

```# array of triangle vertices (2x3x3)
tri = np.asarray([
[(-1.0, 1.0, 0.0), (-1.0, -1.0, 0.0), (1.0, -1.0, 0.0)],   # 1
[(-1.0, 1.0, 0.0), (-1.0, -1.0, 0.0), (1.0, -1.0, 0.0)]])  # 2

# array of triangle texture coordinates (2x3x2)
uv = np.asarray([
[(0.0, 1.0), (0.0, 0.0), (1.0, 0.0)],   # 1
[(0.0, 1.0), (0.0, 0.0), (1.0, 0.0)]])  # 2

bitangents = surfaceBitangent(tri, uv, norm=True)  # bitangets (2x3)
```
`psychopy.tools.mathtools.``surfaceTangent`(tri, uv, norm=True, out=None, dtype=None)[source]

Compute the tangent vector of a given triangle.

Uses texture coordinates at each triangle vertex to determine the direction of the vector. This function can be used to generate tangent vertex attributes for normal mapping. After computing tangents, one may orthogonalize them with vertex normals using the `orthogonalize()` function, or within the fragment shader.

Parameters: tri (array_like) – Triangle vertices as 2D (3x3) array [p0, p1, p2] where each vertex is a length 3 array [vx, xy, vz]. The input array can be 3D (Nx3x3) to specify multiple triangles. uv (array_like) – Texture coordinates associated with each face vertex as a 2D array (3x2) where each texture coordinate is length 2 array [u, v]. The input array can be 3D (Nx3x2) to specify multiple texture coordinates if multiple triangles are specified. If so N must be the same size as the first dimension of tri. norm (bool, optional) – Normalize computed tangents if `True`, default is `True`. out (ndarray, optional) – Optional output array. Must have one fewer dimensions than tri. The shape of the last dimension must be 3. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Surface normal of triangle tri. ndarray

Examples

Compute surface normals, tangents, and bitangents for a list of triangles:

```# triangle vertices (2x3x3)
vertices = [[[-1., 0., 0.], [0., 1., 0.], [1, 0, 0]],
[[1., 0., 0.], [0., 1., 0.], [-1, 0, 0]]]

# array of triangle texture coordinates (2x3x2)
uv = np.asarray([
[(0.0, 1.0), (0.0, 0.0), (1.0, 0.0)],   # 1
[(0.0, 1.0), (0.0, 0.0), (1.0, 0.0)]])  # 2

normals = surfaceNormal(vertices)
tangents = surfaceTangent(vertices, uv)
bitangents = cross(normals, tangents)  # or use `surfaceBitangent`
```

Orthogonalize a surface tangent with a vertex normal vector to get the vertex tangent and bitangent vectors:

```vertexTangent = orthogonalize(faceTangent, vertexNormal)
vertexBitangent = cross(vertexTangent, vertexNormal)
```

Ensure computed vectors have the same handedness, if not, flip the tangent vector (important for applications like normal mapping):

```# tangent, bitangent, and normal are 2D
tangent[dot(cross(normal, tangent), bitangent) < 0.0, :] *= -1.0
```
`psychopy.tools.mathtools.``vertexNormal`(faceNorms, norm=True, out=None, dtype=None)[source]

Compute a vertex normal from shared triangles.

This function computes a vertex normal by averaging the surface normals of the triangles it belongs to. If model has no vertex normals, first use `surfaceNormal()` to compute them, then run `vertexNormal()` to compute vertex normal attributes.

While this function is mainly used to compute vertex normals, it can also be supplied triangle tangents and bitangents.

Parameters: faceNorms (array_like) – An array (Nx3) of surface normals. norm (bool, optional) – Normalize computed normals if `True`, default is `True`. out (ndarray, optional) – Optional output array. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Vertex normal. ndarray

Examples

Compute a vertex normal from the face normals of the triangles it belongs to:

```normals = [[1., 0., 0.], [0., 1., 0.]]  # adjacent face normals
vertexNorm = vertexNormal(normals)
```
`psychopy.tools.mathtools.``slerp`(q0, q1, t, shortest=True, out=None, dtype=None)[source]

Spherical linear interpolation (SLERP) between two quaternions.

The behaviour of this function depends on the types of arguments:

• If q0 and q1 are both 1-D and t is scalar, the interpolation at t is returned.
• If q0 and q1 are both 2-D Nx4 arrays and t is scalar, an Nx4 array is returned with each row containing the interpolation at t for each quaternion pair at matching row indices in q0 and q1.
Parameters: q0 (array_like) – Initial quaternion in form [x, y, z, w] where w is real and x, y, z are imaginary components. q1 (array_like) – Final quaternion in form [x, y, z, w] where w is real and x, y, z are imaginary components. t (float) – Interpolation weight factor within interval 0.0 and 1.0. shortest (bool, optional) – Ensure interpolation occurs along the shortest arc along the 4-D hypersphere (default is True). out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Quaternion [x, y, z, w] at t. ndarray

Examples

Interpolate between two orientations:

```q0 = quatFromAxisAngle(90.0, degrees=True)
q1 = quatFromAxisAngle(-90.0, degrees=True)
# halfway between 90 and -90 is 0.0 or quaternion [0. 0. 0. 1.]
qr = slerp(q0, q1, 0.5)
```

Example of smooth rotation of an object with fixed angular velocity:

```degPerSec = 10.0  # rotate a stimulus at 10 degrees per second

# initial orientation, axis rotates in the Z direction
qr = quatFromAxisAngle([0., 0., -1.], 0.0, degrees=True)
# amount to rotate every second
qv = quatFromAxisAngle([0., 0., -1.], degPerSec, degrees=True)

# ---- within main experiment loop ----
# `frameTime` is the time elapsed in seconds from last `slerp`.
qr = multQuat(qr, slerp((0., 0., 0., 1.), qv, degPerSec * frameTime))
_, angle = quatToAxisAngle(qr)  # discard axis, only need angle

# myStim is a GratingStim or anything with an 'ori' argument which
# accepts angle in degrees
myStim.ori = angle
myStim.draw()
```
`psychopy.tools.mathtools.``quatToAxisAngle`(q, degrees=True, dtype=None)[source]

Convert a quaternion to axis and angle representation.

This allows you to use quaternions to set the orientation of stimuli that have an ori property.

Parameters: q (tuple, list or ndarray of float) – Quaternion in form [x, y, z, w] where w is real and x, y, z are imaginary components. degrees (bool, optional) – Indicate angle is to be returned in degrees, otherwise angle will be returned in radians. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Axis and angle of quaternion in form ([ax, ay, az], angle). If degrees is True, the angle returned is in degrees, radians if False. tuple

Examples

Using a quaternion to rotate a stimulus a fixed angle each frame:

```# initial orientation, axis rotates in the Z direction
qr = quatFromAxisAngle([0., 0., -1.], 0.0, degrees=True)
# rotation per-frame, here it's 0.1 degrees per frame
qf = quatFromAxisAngle([0., 0., -1.], 0.1, degrees=True)

# ---- within main experiment loop ----
# myStim is a GratingStim or anything with an 'ori' argument which
# accepts angle in degrees
qr = multQuat(qr, qf)  # cumulative rotation
_, angle = quatToAxisAngle(qr)  # discard axis, only need angle
myStim.ori = angle
myStim.draw()
```
`psychopy.tools.mathtools.``quatFromAxisAngle`(axis, angle, degrees=True, dtype=None)[source]

Create a quaternion to represent a rotation about axis vector by angle.

Parameters: axis (tuple, list or ndarray, optional) – Axis of rotation [x, y, z]. angle (float) – Rotation angle in radians (or degrees if degrees is True. Rotations are right-handed about the specified axis. degrees (bool, optional) – Indicate angle is in degrees, otherwise angle will be treated as radians. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, ‘float64’ is used. Quaternion [x, y, z, w]. ndarray

Examples

Create a quaternion from specified axis and angle:

```axis = [0., 0., -1.]  # rotate about -Z axis
angle = 90.0  # angle in degrees
ori = quatFromAxisAngle(axis, angle, degrees=True)  # using degrees!
```
`psychopy.tools.mathtools.``quatMagnitude`(q, squared=False, out=None, dtype=None)[source]

Get the magnitude of a quaternion.

A quaternion is normalized if its magnitude is 1.

Parameters: q (array_like) – Quaternion(s) in form [x, y, z, w] where w is real and x, y, z are imaginary components. squared (bool, optional) – If `True` return the squared magnitude. If you are just checking if a quaternion is normalized, the squared magnitude will suffice to avoid the square root operation. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Magnitude of quaternion q. float or ndarray
`psychopy.tools.mathtools.``multQuat`(q0, q1, out=None, dtype=None)[source]

Multiply quaternion q0 and q1.

The orientation of the returned quaternion is the combination of the input quaternions.

Parameters: q1 (q0,) – Quaternions to multiply in form [x, y, z, w] where w is real and x, y, z are imaginary components. If 2D (Nx4) arrays are specified, quaternions are multiplied row-wise between each array. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Combined orientations of q0 amd q1. ndarray

Notes

• Quaternions are normalized prior to multiplication.

Examples

Combine the orientations of two quaternions:

```a = quatFromAxisAngle([0, 0, -1], 45.0, degrees=True)
b = quatFromAxisAngle([0, 0, -1], 90.0, degrees=True)
c = multQuat(a, b)  # rotates 135 degrees about -Z axis
```
`psychopy.tools.mathtools.``invertQuat`(q, out=None, dtype=None)[source]

Get tht multiplicative inverse of a quaternion.

This gives a quaternion which rotates in the opposite direction with equal magnitude. Multiplying a quaternion by its inverse returns an identity quaternion as both orientations cancel out.

Parameters: q (ndarray, list, or tuple of float) – Quaternion to invert in form [x, y, z, w] where w is real and x, y, z are imaginary components. If q is 2D (Nx4), each row is treated as a separate quaternion and inverted. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Inverse of quaternion q. ndarray

Examples

Show that multiplying a quaternion by its inverse returns an identity quaternion where [x=0, y=0, z=0, w=1]:

```angle = 90.0
axis = [0., 0., -1.]
q = quatFromAxisAngle(axis, angle, degrees=True)
qinv = invertQuat(q)
qr = multQuat(q, qinv)
qi = np.array([0., 0., 0., 1.])  # identity quaternion
print(np.allclose(qi, qr))   # True
```

Notes

• Quaternions are normalized prior to inverting.
`psychopy.tools.mathtools.``applyQuat`(q, points, out=None, dtype=None)[source]

Rotate points/coordinates using a quaternion.

This is similar to using applyMatrix with a rotation matrix. However, it is computationally less intensive to use applyQuat if one only wishes to rotate points.

Parameters: q (array_like) – Quaternion to invert in form [x, y, z, w] where w is real and x, y, z are imaginary components. points (array_like) – 2D array of points/coordinates to transform, where each row is a single point. Only the x, y, and z components (the first three columns) are rotated. Additional columns are copied. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Transformed points. ndarray

Examples

Rotate points using a quaternion:

```points = [[1., 0., 0.], [0., -1., 0.]]
quat = quatFromAxisAngle(-90.0, [0., 0., -1.], degrees=True)
pointsRotated = applyQuat(quat, points)
# [[0. 1. 0.]
#  [1. 0. 0.]]
```

Show that you get the same result as a rotation matrix:

```axis = [0., 0., -1.]
angle = -90.0
rotMat = rotationMatrix(axis, angle)[:3, :3]  # rotation sub-matrix only
rotQuat = quatFromAxisAngle(axis, angle, degrees=True)
points = [[1., 0., 0.], [0., -1., 0.]]
isClose = np.allclose(applyMatrix(rotMat, points),  # True
applyQuat(rotQuat, points))
```

Specifying an array to q where each row is a quaternion transforms points in corresponding rows of points:

```points = [[1., 0., 0.], [0., -1., 0.]]
quats = [quatFromAxisAngle(-90.0, [0., 0., -1.], degrees=True),
quatFromAxisAngle(45.0, [0., 0., -1.], degrees=True)]
applyQuat(quats, points)
```
`psychopy.tools.mathtools.``scaleMatrix`(s, out=None, dtype=None)[source]

Create a scaling matrix.

The resulting matrix is the same as a generated by a glScale call.

Parameters: s (array_like, float or int) – Scaling factor(s). If s is scalar (float), scaling will be uniform. Providing a vector of scaling values [sx, sy, sz] will result in an anisotropic scaling matrix if any of the values differ. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. 4x4 scaling matrix in row-major order. ndarray
`psychopy.tools.mathtools.``rotationMatrix`(angle, axis=(0.0, 0.0, -1.0), out=None, dtype=None)[source]

Create a rotation matrix.

The resulting matrix will rotate points about axis by angle. The resulting matrix is similar to that produced by a glRotate call.

Parameters: angle (float) – Rotation angle in degrees. axis (ndarray, list, or tuple of float) – Axis vector components. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. 4x4 scaling matrix in row-major order. Will be the same array as out if specified, if not, a new array will be allocated. ndarray

Notes

• Vector axis is normalized before creating the matrix.
`psychopy.tools.mathtools.``translationMatrix`(t, out=None, dtype=None)[source]

Create a translation matrix.

The resulting matrix is the same as generated by a glTranslate call.

Parameters: t (ndarray, tuple, or list of float) – Translation vector [tx, ty, tz]. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. 4x4 translation matrix in row-major order. Will be the same array as out if specified, if not, a new array will be allocated. ndarray
`psychopy.tools.mathtools.``invertMatrix`(m, homogeneous=False, out=None, dtype=None)[source]

Invert a 4x4 matrix.

Parameters: m (array_like) – 4x4 matrix to invert. homogeneous (bool, optional) – Set as `True` if the input matrix specifies affine (homogeneous) transformations (scale, rotation, and translation) and is orthonormal. This will use a faster inverse method which handles such cases. Default is `False`. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not specified, the default is ‘float64’. 4x4 matrix which is the inverse of m ndarray
`psychopy.tools.mathtools.``concatenate`(matrices, out=None, dtype=None)[source]

Concatenate matrix transformations.

Combine 4x4 transformation matrices into a single matrix. This is similar to what occurs when building a matrix stack in OpenGL using glRotate, glTranslate, and glScale calls. Matrices are multiplied together from right-to-left, or the last item to first. Note that changing the order of the input matrices changes the final result.

The data types of input matrices are coerced to match that of out or dtype if out is None. For performance reasons, it is best that all arrays passed to this function have matching data types.

Parameters: matrices (list or tuple) – List of matrices to concatenate. All matrices must be 4x4. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Concatenation of input matrices as a 4x4 matrix in row-major order. ndarray

Examples

Create an SRT (scale, rotate, and translate) matrix to convert model-space coordinates to world-space:

```S = scaleMatrix([2.0, 2.0, 2.0])  # scale model 2x
R = rotationMatrix(-90., [0., 0., -1])  # rotate -90 about -Z axis
T = translationMatrix([0., 0., -5.])  # translate point 5 units away
SRT = concatenate([S, R, T])

# transform a point in model-space coordinates to world-space
pointModel = np.array([0., 1., 0., 1.])
pointWorld = np.matmul(SRT, pointModel.T)  # point in WCS
# ... or ...
pointWorld = matrixApply(SRT, pointModel)
```

Create a model-view matrix from a world-space pose represented by an orientation (quaternion) and position (vector). The resulting matrix will transform model-space coordinates to eye-space:

```# stimulus pose as quaternion and vector
stimOri = quatFromAxisAngle([0., 0., -1.], -45.0)
stimPos = [0., 1.5, -5.]

# create model matrix
R = matrixFromQuat(stimOri)
T = translationMatrix(stimPos)
M = concatenate(R, T)  # model matrix

# create a view matrix, can also be represented as 'pos' and 'ori'
eyePos = [0., 1.5, 0.]
eyeFwd = [0., 0., -1.]
eyeUp = [0., 1., 0.]
V = lookAt(eyePos, eyeFwd, eyeUp)  # from viewtools

# modelview matrix
MV = concatenate([M, V])
```

You can put the created matrix in the OpenGL matrix stack as shown below. Note that the matrix must have a 32-bit floating-point data type and needs to be loaded transposed since OpenGL takes matrices in column-major order:

```GL.glMatrixMode(GL.GL_MODELVIEW)

# pyglet
MV = np.asarray(MV, dtype='float32')  # must be 32-bit float!
ptrMV = MV.ctypes.data_as(ctypes.POINTER(ctypes.c_float))

# PyOpenGL
MV = np.asarray(MV, dtype='float32')
```

Furthermore, you can convert a point from model-space to homogeneous clip-space by concatenating the projection, view, and model matrices:

```# compute projection matrix, functions here are from 'viewtools'
screenWidth = 0.52
screenAspect = w / h
scrDistance = 0.55
frustum = computeFrustum(screenWidth, screenAspect, scrDistance)
P = perspectiveProjectionMatrix(*frustum)

# multiply model-space points by MVP to convert them to clip-space
MVP = concatenate([M, V, P])
pointModel = np.array([0., 1., 0., 1.])
pointClipSpace = np.matmul(MVP, pointModel.T)
```
`psychopy.tools.mathtools.``applyMatrix`(m, points, out=None, dtype=None)[source]

Apply a transformation matrix over a 2D array of points.

Parameters: m (array_like) – Transformation matrix. points (array_like) – 2D array of points/coordinates to transform, where each row is a single point and the number of columns should match the dimensions of the matrix. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for arrays, can either be ‘float32’ or ‘float64’. If None is specified, the data type is inferred by out. If out is not provided, the default is ‘float64’. Transformed points. ndarray

Examples

Transform an array of points by some transformation matrix:

```S = scaleMatrix([5.0, 5.0, 5.0])  # scale 2x
R = rotationMatrix(180., [0., 0., -1])  # rotate 180 degrees
T = translationMatrix([0., 1.5, -3.])  # translate point up and away
M = concatenate([S, R, T])  # create transform matrix

# points to transform, must be 2D!
points = np.array([[0., 1., 0., 1.], [-1., 0., 0., 1.]]) # [x, y, z, w]
newPoints = applyMatrix(M, points)  # apply the transformation
```

Extract the 3x3 rotation sub-matrix from a 4x4 matrix and apply it to points. Here the result is written to a pre-allocated array:

```points = np.array([[0., 1., 0.], [-1., 0., 0.]])  # [x, y, z]
outPoints = np.zeros(points.shape)
M = rotationMatrix(90., [1., 0., 0.])
M3x3 = M[:3, :3]  # extract rotation groups from the 4x4 matrix
# apply transformations, write to result to existing array
applyMatrix(M3x3, points, out=outPoints)
```
`psychopy.tools.mathtools.``transform`(pos, ori, points, out=None, dtype=None)[source]

Transform points using a position and orientation. Points are rotated then translated.

Parameters: pos (array_like) – Position vector in form [x, y, z] or [x, y, z, 1]. ori (array_like) – Orientation quaternion in form [x, y, z, w] where w is real and x, y, z are imaginary components. points (array_like) – Point(s) [x, y, z] to transform. out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If None is specified, the data type of out is used. If out is not provided, ‘float64’ is used by default. Transformed points. ndarray

Examples

Transform points by a position coordinate and orientation quaternion:

```# rigid body pose
ori = quatFromAxisAngle([0., 0., -1.], 90.0, degrees=True)
pos = [0., 1.5, -3.]
# points to transform
points = np.array([[0., 1., 0., 1.], [-1., 0., 0., 1.]])  # [x, y, z, 1]
outPoints = np.zeros_like(points)  # output array
transform(pos, ori, points, out=outPoints)  # do the transformation
```

You can get the same results as the previous example using a matrix by doing the following:

```R = rotationMatrix(90., [0., 0., -1])
T = translationMatrix([0., 1.5, -3.])
M = concatenate([R, T])
applyMatrix(M, points, out=outPoints)
```

If you are defining transformations with quaternions and coordinates, you can skip the costly matrix creation process by using transform.

Notes

• In performance tests, applyMatrix is noticeably faster than transform for very large arrays, however this is only true if you are applying the same transformation to all points.
• If the input arrays for points or pos is Nx4, the last column is ignored.