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
.
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.
Subroutines used by the functions here will perform arithmetic using 64bit floatingpoint 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 floatingpoint arithmetic will use the precision of the type. If input arrays have the same type as dtype, they will automatically passthrough 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 for all arithmetic.

Get the length of a vector. 

Normalize a vector or quaternion. 

Orthogonalize a vector relative to a normal vector. 

Reflection of a vector. 

Dot product of two vectors. 

Cross product of 3D vectors. 

Project a vector onto another. 

Project v to be a perpendicular axis of n. 

Linear interpolation (LERP) between two vectors/coordinates. 

Get the distance between vectors/coordinates. 

Get the relative angle to a point from a vector. 

Get the angle bisector. 

Compute the surface normal of a given triangle. 

Compute the bitangent vector of a given triangle. 

Compute the tangent vector of a given triangle. 

Compute a vertex normal from shared triangles. 

Ensure the handedness of tangent vectors are all the same. 

Fit an axisaligned bounding box around points. 

Get the corners of an axisaligned bounding box. 

Get the point which a ray intersects a plane. 

Calculate the points which a ray/line intersects a sphere (if any). 

Find the point a ray intersects an axisaligned bounding box (AABB). 

Find the point a ray intersects an oriented bounding box (OBB). 

Get the intersection of a ray and triangle(s). 

Get the planar coordinates of an orthogonal projection of a 3D point onto a 2D plane. 

Articulate an armature. 

Spherical linear interpolation (SLERP) between two quaternions. 

Convert a quaternion to axis and angle representation. 

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

Get the yaw, pitch, and roll of a quaternion’s orientation relative to the world Z axis. 

Compute a quaternion which rotates one vector to align with another. 

Get the magnitude of a quaternion. 

Multiply quaternion q0 and q1. 

Accumulate quaternion rotations. 

Get tht multiplicative inverse of a quaternion. 

Rotate points/coordinates using a quaternion. 

Create a 4x4 rotation matrix from a quaternion. 

Convert a rotation matrix to a quaternion. 

Construct a 4x4 rotation matrix from Euler angles. 

Create a scaling matrix. 

Create a rotation matrix. 

Get the rotation angle of an extant rotation matrix. 

Create a translation matrix. 

Invert a square matrix. 

Check if a square matrix is orthogonal. 

Check if a 4x4 square matrix describes an affine transformation. 

Chain multiplication of two or more matrices. 

Concatenate matrix transformations. 

Get the normal matrix from a model matrix. 

Project a point in a scene to a window coordinate. 

Unproject window coordinates into object or scene coordinates. 

Apply a matrix over a 2D array of points. 

Convert a rigid body pose to a 4x4 transformation matrix. 

Transform points using a position and orientation. 

Scale points by a factor. 

Lens correction (or distortion) using the division model with even polynomial terms. 

Fix zeros in an array. 
psychopy.tools.mathtools.
length
(v, squared=False, out=None, dtype=None)[source]¶Get the length of a vector.
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 out is specified, the data type of out is used and this argument is ignored. 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.
Vector to normalize, can be Nx2, Nx3, or Nx4. If a 2D array is specified, rows are treated as separate vectors. All vectors should have nonzero length.
Optional output array. Must be same shape and dtype as the expected output if out was not specified.
Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Normalized vector v.
ndarray
Notes
If the vector has length is zero, a vector of all zeros is returned after normalization.
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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 as a 2D array:
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Projection of vector v0 on v1.
ndarray or float
psychopy.tools.mathtools.
perp
(v, n, norm=True, out=None, dtype=None)[source]¶Project v to be a perpendicular axis of n.
v (array_like) – Vector to project [x, y, z], may be Nx3.
n (array_like) – Normal vector [x, y, z], may be Nx3.
norm (bool) – Normalize the resulting axis. 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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Perpendicular axis of n from v.
ndarray
Examples
Determine the local up (yaxis) of a surface or plane given normal:
normal = [0., 0.70710678, 0.70710678]
up = [1., 0., 0.]
yaxis = perp(up, normal)
Do a cross product to get the xaxis perpendicular to both:
xaxis = cross(yaxis, normal)
psychopy.tools.mathtools.
lerp
(v0, v1, t, out=None, dtype=None)[source]¶Linear interpolation (LERP) between two vectors/coordinates.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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 halfway 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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Distance between vectors v0 and v1.
ndarray
psychopy.tools.mathtools.
bisector
(v0, v1, norm=False, out=None, dtype=None)[source]¶Get the angle bisector.
Computes a vector which bisects the angle between v0 and v1. Input vectors v0 and v1 must be nonzero.
v1 (v0,) – Vectors to bisect [x, y, z]. Must be nonzero in length and have the same shape. Inputs can be Nx3 where the bisector for corresponding rows will be returned.
norm (bool, optional) – Normalize the resulting bisector. 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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Bisecting vector [x, y, z].
ndarray
psychopy.tools.mathtools.
surfaceNormal
(tri, norm=True, out=None, dtype=None)[source]¶Compute the surface normal of a given triangle.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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 preallocated 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.
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. Uses texture coordinates at each triangle vertex to determine the
direction of the vector.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
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. Uses texture coordinates at each triangle vertex to determine the
direction of the vector.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
fixTangentHandedness
(tangents, normals, bitangents, out=None, dtype=None)[source]¶Ensure the handedness of tangent vectors are all the same.
Often 3D computed tangents may not have the same handedness due to how texture coordinates are specified. This function takes input surface vectors are ensures that tangents have the same handedness. Use this function if you notice that normal mapping shading appears reversed with respect to the incident light direction. The output array of corrected tangents can be used inplace of the original.
normals, bitangents (tangents,) – Input Nx3 arrays of triangle tangents, normals and bitangents. All arrays must have the same size.
out (ndarray, optional) – Optional output array for tangents. If not specified, a new array of tangents will be allocated.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Array of tangents with handedness corrected.
ndarray
psychopy.tools.mathtools.
fitBBox
(points, dtype=None)[source]¶Fit an axisaligned bounding box around points.
This computes the minimum and maximum extents for a bounding box to completely enclose points. Keep in mind the the output in bounds are axisaligned and may not optimally fits the points (i.e. fits the points with the minimum required volume). However, this should work well enough for applications such as visibility testing (see ~psychopy.tools.viewtools.volumeVisible for more information..
points (array_like) – Nx3 or Nx4 array of points to fit the bounding box to.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Extents (mins, maxs) as a 2x3 array.
ndarray
See also
computeBBoxCorners()
Convert bounding box extents to corners.
psychopy.tools.mathtools.
computeBBoxCorners
(extents, dtype=None)[source]¶Get the corners of an axisaligned bounding box.
extents (array_like) – 2x3 array indicating the minimum and maximum extents of the bounding box.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
8x4 array of points defining the corners of the bounding box.
ndarray
psychopy.tools.mathtools.
intersectRayPlane
(rayOrig, rayDir, planeOrig, planeNormal, dtype=None)[source]¶Get the point which a ray intersects a plane.
rayOrig (array_like) – Origin of the line in space [x, y, z].
rayDir (array_like) – Direction vector of the line [x, y, z].
planeOrig (array_like) – Origin of the plane to test [x, y, z].
planeNormal (array_like) – Normal vector of the plane [x, y, z].
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Position (ndarray) in space which the line intersects the plane and the distance the intersect occurs from the origin (float). None is returned if the line does not intersect the plane at a single point or at all.
Examples
Find the point in the scene a ray intersects the plane:
# plane information
planeOrigin = [0, 0, 0]
planeNormal = [0, 0, 1]
planeUpAxis = perp([0, 1, 0], planeNormal)
# ray
rayDir = [0, 0, 1]
rayOrigin = [0, 0, 5]
# get the intersect and distance in 3D world space
pnt, dist = intersectRayPlane(rayOrigin, rayDir, planeOrigin, planeNormal)
psychopy.tools.mathtools.
intersectRaySphere
(rayOrig, rayDir, sphereOrig=(0.0, 0.0, 0.0), sphereRadius=1.0, dtype=None)[source]¶Calculate the points which a ray/line intersects a sphere (if any).
Get the 3D coordinate of the point which the ray intersects the sphere and the distance to the point from orig. The nearest point is returned if the line intersects the sphere at multiple locations. All coordinates should be in world/scene units.
rayOrig (array_like) – Origin of the ray in space [x, y, z].
rayDir (array_like) – Direction vector of the ray [x, y, z], should be normalized.
sphereOrig (array_like) – Origin of the sphere to test [x, y, z].
sphereRadius (float) – Sphere radius to test in scene units.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Coordinate in world space of the intersection and distance in scene units from orig. Returns None if there is no intersection.
psychopy.tools.mathtools.
intersectRayAABB
(rayOrig, rayDir, boundsOffset, boundsExtents, dtype=None)[source]¶Find the point a ray intersects an axisaligned bounding box (AABB).
rayOrig (array_like) – Origin of the ray in space [x, y, z].
rayDir (array_like) – Direction vector of the ray [x, y, z], should be normalized.
boundsOffset (array_like) – Offset of the bounding box in the scene [x, y, z].
boundsExtents (array_like) – Minimum and maximum extents of the bounding box.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Coordinate in world space of the intersection and distance in scene units from rayOrig. Returns None if there is no intersection.
Examples
Get the point on an axisaligned bounding box that the cursor is over and place a 3D stimulus there. The eye location is defined by RigidBodyPose object camera:
# get the mouse position onscreen
mx, my = mouse.getPos()
# find the point which the ray intersects on the box
result = intersectRayAABB(
camera.pos,
camera.transformNormal(win.coordToRay((mx, my))),
myStim.pos,
myStim.thePose.bounds.extents)
# if the ray intersects, set the position of the cursor object to it
if result is not None:
cursorModel.thePose.pos = result[0]
cursorModel.draw() # don't draw anything if there is no intersect
Note that if the model is rotated, the bounding box may not be aligned anymore with the axes. Use intersectRayOBB if your model rotates.
psychopy.tools.mathtools.
intersectRayOBB
(rayOrig, rayDir, modelMatrix, boundsExtents, dtype=None)[source]¶Find the point a ray intersects an oriented bounding box (OBB).
rayOrig (array_like) – Origin of the ray in space [x, y, z].
rayDir (array_like) – Direction vector of the ray [x, y, z], should be normalized.
modelMatrix (array_like) – 4x4 model matrix of the object and bounding box.
boundsExtents (array_like) – Minimum and maximum extents of the bounding box.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Coordinate in world space of the intersection and distance in scene units from rayOrig. Returns None if there is no intersection.
Examples
Get the point on an oriented bounding box that the cursor is over and place a 3D stimulus there. The eye location is defined by RigidBodyPose object camera:
# get the mouse position onscreen
mx, my = mouse.getPos()
# find the point which the ray intersects on the box
result = intersectRayOBB(
camera.pos,
camera.transformNormal(win.coordToRay((mx, my))),
myStim.thePose.getModelMatrix(),
myStim.thePose.bounds.extents)
# if the ray intersects, set the position of the cursor object to it
if result is not None:
cursorModel.thePose.pos = result[0]
cursorModel.draw() # don't draw anything if there is no intersect
psychopy.tools.mathtools.
intersectRayTriangle
(rayOrig, rayDir, tri, dtype=None)[source]¶Get the intersection of a ray and triangle(s).
This function can be used to achieve ‘pixelperfect’ ray picking/casting on meshes defined with triangles. However, highpoly meshes may lead to performance issues.
rayOrig (array_like) – Origin of the ray in space [x, y, z].
rayDir (array_like) – Direction vector of the ray [x, y, z], should be normalized.
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.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Coordinate in world space of the intersection, distance in scene units from rayOrig, and the barycentric coordinates on the triangle [x, y]. Returns None if there is no intersection.
psychopy.tools.mathtools.
ortho3Dto2D
(p, orig, normal, up, right=None, dtype=None)[source]¶Get the planar coordinates of an orthogonal projection of a 3D point onto a 2D plane.
This function gets the nearest point on the plane which a 3D point falls on the plane.
p (array_like) – Point to be projected on the plane.
orig (array_like) – Origin of the plane to test [x, y, z].
normal (array_like) – Normal vector of the plane [x, y, z], must be normalized.
up (array_like) – Normalized up (+Y) direction of the plane’s coordinate system. Must be perpendicular to normal.
right (array_like, optional) – Perpendicular right (+X) axis. If not provided, the axis will be computed via the cross product between normal and up.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Coordinates on the plane [X, Y] where the 3D point projects towards perpendicularly.
ndarray
Examples
This function can be used with intersectRayPlane()
to find the
location on the plane the ray intersects:
# plane information
planeOrigin = [0, 0, 0]
planeNormal = [0, 0, 1] # must be normalized
planeUpAxis = perp([0, 1, 0], planeNormal) # must also be normalized
# ray
rayDir = [0, 0, 1]
rayOrigin = [0, 0, 5]
# get the intersect in 3D world space
pnt = intersectRayPlane(rayOrigin, rayDir, planeOrigin, planeNormal)
# get the 2D coordinates on the plane the intersect occurred
planeX, planeY = ortho3Dto2D(pnt, planeOrigin, planeNormal, planeUpAxis)
psychopy.tools.mathtools.
articulate
(boneVecs, boneOris, dtype=None)[source]¶Articulate an armature.
This function is used for forward kinematics and posing by specifying a list of ‘bones’. A bone has a length and orientation, where sequential bones are linked endtoend. Returns the transformed origins of the bones in scene coordinates and their orientations.
There are many applications for forward kinematics such as posing armatures and stimuli for display (eg. mocap data). Another application is for getting the location of the end effector of coordinate measuring hardware, where encoders measure the joint angles and the length of linking members are known. This can be used for computing pose from “Sword of Damocles”[1]_ like hardware or some other haptic input devices which the participant wears (eg. a glove that measures joint angles in the hand). The computed pose of the joints can be used to interact with virtual stimuli.
boneVecs (array_like) – Bone lengths [x, y, z] as an Nx3 array.
boneOris (array_like) – Orientation of the bones as quaternions in form [x, y, z, w], relative to the previous bone.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Array of bone origins and orientations. The first origin is root
position which is always at [0, 0, 0]. Use transform()
to
reposition the armature, or create a transformation matrix and use
applyMatrix to translate and rotate the whole armature into position.
References
Sutherland, I. E. (1968). “A headmounted three dimensional display”. Proceedings of AFIPS 68, pp. 757764
Examples
Compute the orientations and origins of segments of an arm:
# bone lengths
boneLengths = [[0., 1., 0.], [0., 1., 0.], [0., 1., 0.]]
# create quaternions for joints
shoulder = mt.quatFromAxisAngle('y', 45.0)
elbow = mt.quatFromAxisAngle('+z', 45.0)
wrist = mt.quatFromAxisAngle('+z', 45.0)
# articulate the parts of the arm
boxPos, boxOri = mt.articulate(pos, [shoulder, elbow, wrist])
# assign positions and orientations to 3D objects
shoulderModel.thePose.posOri = (boxPos[0, :], boxOri[0, :])
elbowModel.thePose.posOri = (boxPos[1, :], boxOri[1, :])
wristModel.thePose.posOri = (boxPos[2, :], boxOri[2, :])
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 1D and t is scalar, the interpolation at t is returned.
If q0 and q1 are both 2D 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.
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 4D 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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Axis and angle of quaternion in form ([ax, ay, az], angle). If degrees is True, the angle returned is in degrees, radians if False.
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 perframe, 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.
axis (tuple, list, ndarray or str) – Axis vector components or axis name. If a vector, input must be length 3 [x, y, z]. A string can be specified for rotations about world axes (eg. ‘+x’, ‘z’, ‘+y’, etc.)
angle (float) – Rotation angle in radians (or degrees if degrees is True. Rotations are righthanded 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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
quatYawPitchRoll
(q, degrees=True, out=None, dtype=None)[source]¶Get the yaw, pitch, and roll of a quaternion’s orientation relative to the world Z axis.
You can multiply the quaternion by the inverse of some other one to make the returned values referenced to a local coordinate system.
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 angles are to be returned in degrees, otherwise they will be returned in radians.
out (ndarray) – Optional output array. Must have same shape and dtype as what is expected to be returned by this function of out was not specified.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Yaw, pitch and roll [yaw, pitch, roll] of quaternion q.
ndarray
psychopy.tools.mathtools.
alignTo
(v, t, out=None, dtype=None)[source]¶Compute a quaternion which rotates one vector to align with another.
v (array_like) – Vector [x, y, z] to rotate. Can be Nx3, but must have the same shape as t.
t (array_like) – Target [x, y, z] vector to align to. Can be Nx3, but must have the 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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Quaternion which rotates v to t.
ndarray
Examples
Rotate some vectors to align with other vectors, inputs should be normalized:
vec = [[1, 0, 0], [0, 1, 0], [1, 0, 0]]
targets = [[0, 1, 0], [0, 1, 0], [1, 0, 0]]
qr = alignTo(vec, targets)
vecRotated = applyQuat(qr, vec)
numpy.allclose(vecRotated, targets) # True
Get matrix which orients vertices towards a point:
point = [5, 6, 7]
vec = [0, 0, 1] # initial facing is Z (forward in GL)
targetVec = normalize(point  vec)
qr = alignTo(vec, targetVec) # get rotation to align
M = quatToMatrix(qr) # 4x4 transformation matrix
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
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 rowwise 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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
accumQuat
(qlist, out=None, dtype=None)[source]¶Accumulate quaternion rotations.
Chain multiplies an Nx4 array of quaternions, accumulating their rotations. This function can be used for computing the orientation of joints in an armature for forward kinematics. The first quaternion is treated as the ‘root’ and the last is the orientation of the end effector.
q (array_like) – Nx4 array of quaternions to accumulate, where each row is a quaternion.
out (ndarray, optional) – Optional output array. Must be same shape and dtype as the expected output if out was not specified. In this case, the same shape as qlist.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Nx4 array of quaternions.
ndarray
Examples
Get the orientation of joints in an armature if we know their relative angles:
shoulder = quatFromAxisAngle('x', 45.0) # rotate shoulder down 45 deg
elbow = quatFromAxisAngle('+x', 45.0) # rotate elbow up 45 deg
wrist = quatFromAxisAngle('x', 45.0) # rotate wrist down 45 deg
finger = quatFromAxisAngle('+x', 0.0) # keep finger inline with wrist
armRotations = accumQuat([shoulder, elbow, wrist, finger])
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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.
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 vectors or points 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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
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 submatrix 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.
quatToMatrix
(q, out=None, dtype=None)[source]¶Create a 4x4 rotation matrix from a quaternion.
q (tuple, list or ndarray of float) – Quaternion to convert in form [x, y, z, w] where w is real and x, y, z are imaginary components.
out (ndarray or None) – 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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
4x4 rotation matrix in rowmajor order.
ndarray or None
Examples
Convert a quaternion to a rotation matrix:
point = [0., 1., 0., 1.] # 4vector form [x, y, z, 1.0]
ori = [0., 0., 0., 1.]
rotMat = quatToMatrix(ori)
# rotate 'point' using matrix multiplication
newPoint = np.matmul(rotMat.T, point) # returns [1., 0., 0., 1.]
Rotate all points in an array (each row is a coordinate):
points = np.asarray([[0., 0., 0., 1.],
[0., 1., 0., 1.],
[1., 1., 0., 1.]])
newPoints = points.dot(rotMat)
Notes
Quaternions are normalized prior to conversion.
psychopy.tools.mathtools.
matrixToQuat
(m, out=None, dtype=None)[source]¶Convert a rotation matrix to a quaternion.
m (array_like) – 3x3 rotation matrix (rowmajor). A 4x4 affine transformation matrix may be provided, assuming the topleft 3x3 submatrix is orthonormal and is a rotation group.
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Rotation quaternion.
ndarray
Notes
Depending on the input, returned quaternions may not be exactly the same as the one used to construct the rotation matrix (i.e. by calling quatToMatrix), typically when a large rotation angle is used. However, the returned quaternion should result in the same rotation when applied to points.
Examples
Converting a rotation matrix from the OpenGL matrix stack to a quaternion:
glRotatef(45., 1, 0, 0)
m = np.zeros((4, 4), dtype='float32') # store the matrix
GL.glGetFloatv(
GL.GL_MODELVIEW_MATRIX,
m.ctypes.data_as(ctypes.POINTER(ctypes.c_float)))
qr = matrixToQuat(m.T) # must be transposed
Interpolation between two 4x4 transformation matrices:
interpWeight = 0.5
posStart = mStart[:3, 3]
oriStart = matrixToQuat(mStart)
posEnd = mEnd[:3, 3]
oriEnd = matrixToQuat(mEnd)
oriInterp = slerp(qStart, qEnd, interpWeight)
posInterp = lerp(posStart, posEnd, interpWeight)
mInterp = posOriToMatrix(posInterp, oriInterp)
psychopy.tools.mathtools.
matrixFromEulerAngles
(rx, ry, rz, degrees=True, out=None, dtype=None)[source]¶Construct a 4x4 rotation matrix from Euler angles.
Rotations are combined by first rotating about the X axis, then Y, and finally Z.
ry, rz (rx,) – Rotation angles (pitch, yaw, and roll).
degrees (bool, optional) – Rotation angles are specified in degrees. If False, they will be assumed as 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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
4x4 rotation matrix.
ndarray
Examples
Demonstration of how a combination of axisangle rotations is equivalent to a single call of matrixFromEulerAngles:
m1 = matrixFromEulerAngles(90., 45., 135.))
# construct rotation matrix from 3 orthogonal rotations
rx = rotationMatrix(90., (1, 0, 0)) # xaxis
ry = rotationMatrix(45., (0, 1, 0)) # yaxis
rz = rotationMatrix(135., (0, 0, 1)) # zaxis
m2 = concatenate([rz, ry, rx]) # note the order
print(numpy.allclose(m1, m2)) # True
Not only does matrixFromEulerAngles require less code, it also is considerably more efficient than constructing and multiplying multiple matrices.
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
4x4 scaling matrix in rowmajor 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.
angle (float) – Rotation angle in degrees.
axis (array_like or str) – Axis vector components or axis name. If a vector, input must be length 3. A string can be specified for rotations about world axes (eg. ‘+x’, ‘z’, ‘+y’, etc.)
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
4x4 scaling matrix in rowmajor 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.
matrixAngle
(r, degrees=True, dtype=None)[source]¶Get the rotation angle of an extant rotation matrix.
m (array_like) – Rotation matrix (2x2, 3x3, 4x4) with orthogonal rotation group.
degrees (bool) – Return rotation angle in degrees. If False, this function will return the angle in radians.
dtype (dtype or str, optional) – Data type for computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Rotation angle in degrees or radians.
Examples
Getting the angle of rotation from a rotation matrix:
r = rotationMatrix(90., normalize((1, 2, 3)))
angle = matrixAngle(r) # 90.0
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.
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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
4x4 translation matrix in rowmajor order. Will be the same array as out if specified, if not, a new array will be allocated.
ndarray
psychopy.tools.mathtools.
invertMatrix
(m, out=None, dtype=None)[source]¶Invert a square matrix.
m (array_like) – Square matrix to invert. Inputs can be 4x4, 3x3 or 2x2.
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Matrix which is the inverse of m
ndarray
psychopy.tools.mathtools.
isOrthogonal
(m)[source]¶Check if a square matrix is orthogonal.
If a matrix is orthogonal, its columns form an orthonormal basis and is nonsingular. An orthogonal matrix is invertible by simply taking the transpose of the matrix.
m (array_like) – Square matrix, either 2x2, 3x3 or 4x4.
True if the matrix is orthogonal.
psychopy.tools.mathtools.
isAffine
(m)[source]¶Check if a 4x4 square matrix describes an affine transformation.
m (array_like) – 4x4 transformation matrix.
True if the matrix is affine.
psychopy.tools.mathtools.
multMatrix
(matrices, reverse=False, out=None, dtype=None)[source]¶Chain multiplication of two or more matrices.
Multiply a sequence of matrices together, reducing to a single product matrix. For instance, specifying matrices the sequence of matrices (A, B, C, D) will return the product (((AB)C)D). If reverse=True, the product will be (A(B(CD))).
Alternatively, a 3D array can be specified to matrices as a stack, where an index along axis 0 references a 2D slice storing matrix values. The product of the matrices along the axis will be returned. This is a bit more efficient than specifying separate matrices in a sequence, but the difference is negligible when only a few matrices are being multiplied.
matrices (list, tuple or ndarray) – Sequence or stack of matrices to multiply. All matrices must have the same dimensions.
reverse (bool, optional) – Multiply matrices righttoleft. This is useful when dealing with
transformation matrices, where the order of operations for transforms
will appear the same as the order the matrices are specified. Default is
‘False’. When True, this function behaves similarly to
concatenate()
.
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Matrix product.
ndarray
Notes
You may use numpy.matmul when dealing with only two matrices instead of multMatrix.
If a single matrix is specified, the returned product will have the same values.
Examples
Chain multiplication of SRT matrices:
translate = translationMatrix((0.035, 0, 0.5))
rotate = rotationMatrix(90.0, (0, 1, 0))
scale = scaleMatrix(2.0)
SRT = multMatrix((translate, rotate, scale))
Same as above, but matrices are in a 3x4x4 array:
matStack = np.array((translate, rotate, scale))
# or ...
# matStack = np.zeros((3, 4, 4))
# matStack[0, :, :] = translate
# matStack[1, :, :] = rotate
# matStack[2, :, :] = scale
SRT = multMatrix(matStack)
Using reverse=True allows you to specify transformation matrices in the order which they will be applied:
SRT = multMatrix(np.array((scale, rotate, translate)), reverse=True)
psychopy.tools.mathtools.
concatenate
(matrices, out=None, dtype=None)[source]¶Concatenate matrix transformations.
Chain multiply matrices describing transform operations into a single matrix product, that when applied, transforms points and vectors with each operation in the order they’re specified.
matrices (list or tuple) – List of matrices to concatenate. All matrices must all have the same size, usually 4x4 or 3x3.
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Matrix product.
ndarray
See also
multMatrix : Chain multiplication of matrices.
Examples
Create an SRT (scale, rotate, and translate) matrix to convert modelspace coordinates to worldspace:
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
# product matrix when applied to points will scale, rotate and transform
# in that order.
SRT = concatenate([S, R, T])
# transform a point in modelspace coordinates to worldspace
pointModel = np.array([0., 1., 0., 1.])
pointWorld = np.matmul(SRT, pointModel.T) # point in WCS
# ... or ...
pointWorld = matrixApply(SRT, pointModel)
Create a modelview matrix from a worldspace pose represented by an orientation (quaternion) and position (vector). The resulting matrix will transform modelspace coordinates to eyespace:
# eye pose as quaternion and vector
stimOri = quatFromAxisAngle([0., 0., 1.], 45.0)
stimPos = [0., 1.5, 5.]
# create model matrix
R = quatToMatrix(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 32bit floatingpoint data type and needs to be loaded transposed since OpenGL takes matrices in columnmajor order:
GL.glMatrixMode(GL.GL_MODELVIEW)
# pyglet
MV = np.asarray(MV, dtype='float32') # must be 32bit float!
ptrMV = MV.ctypes.data_as(ctypes.POINTER(ctypes.c_float))
GL.glLoadTransposeMatrixf(ptrMV)
# PyOpenGL
MV = np.asarray(MV, dtype='float32')
GL.glLoadTransposeMatrixf(MV)
Furthermore, you can convert a point from modelspace to homogeneous clipspace 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 modelspace points by MVP to convert them to clipspace
MVP = concatenate([M, V, P])
pointModel = np.array([0., 1., 0., 1.])
pointClipSpace = np.matmul(MVP, pointModel.T)
psychopy.tools.mathtools.
normalMatrix
(modelMatrix, out=None, dtype=None)[source]¶Get the normal matrix from a model matrix.
modelMatrix (array_like) – 4x4 homogeneous model 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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Normal matrix.
ndarray
psychopy.tools.mathtools.
forwardProject
(objPos, modelView, proj, viewport=None, out=None, dtype=None)[source]¶Project a point in a scene to a window coordinate.
This function is similar to gluProject and can be used to find the window coordinate which a point projects to.
objPos (array_like) – Object coordinates (x, y, z). If an Nx3 array of coordinates is specified, where each row contains a window coordinate this function will return an array of projected coordinates with the same size.
modelView (array_like) – 4x4 combined model and view matrix for returned value to be object coordinates. Specify only the view matrix for a coordinate in the scene.
proj (array_like) – 4x4 projection matrix used for rendering.
viewport (array_like) – Viewport rectangle for the window [x, y, w, h]. If not specified, the returned values will be in normalized device coordinates.
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Normalized device or viewport coordinates [x, y, z] of the point. The z component is similar to the depth buffer value for the object point.
ndarray
psychopy.tools.mathtools.
reverseProject
(winPos, modelView, proj, viewport=None, out=None, dtype=None)[source]¶Unproject window coordinates into object or scene coordinates.
This function works like gluUnProject and can be used to find to an object
or scene coordinate at the point onscreen (mouse coordinate or pixel). The
coordinate can then be used to create a direction vector from the viewer’s
eye location. Another use of this function is to convert depth buffer
samples to object or scene coordinates. This is the inverse operation of
forwardProject()
.
winPos (array_like) – Window coordinates (x, y, z). If viewport is not specified, these should be normalized device coordinates. If an Nx3 array of coordinates is specified, where each row contains a window coordinate this function will return an array of unprojected coordinates with the same size. Usually, you only need to specify the x and y coordinate, leaving z as zero. However, you can specify z if sampling from a depth map or buffer to convert a depth sample to an actual location.
modelView (array_like) – 4x4 combined model and view matrix for returned value to be object coordinates. Specify only the view matrix for a coordinate in the scene.
proj (array_like) – 4x4 projection matrix used for rendering.
viewport (array_like) – Viewport rectangle for the window [x, y, w, h]. Do not specify one if winPos is in already in normalized device coordinates.
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Object or scene coordinates.
ndarray
psychopy.tools.mathtools.
applyMatrix
(m, points, out=None, dtype=None)[source]¶Apply a matrix over a 2D array of points.
This function behaves similarly to the following Numpy statement:
points[:, :] = points.dot(m.T)
Transformation matrices specified to m must have dimensions 4x4, 3x4, 3x3 or 2x2. With the exception of 4x4 matrices, input points must have the same number of columns as the matrix has rows. 4x4 matrices can be used to transform both Nx4 and Nx3 arrays.
m (array_like) – Matrix with dimensions 2x2, 3x3, 3x4 or 4x4.
points (array_like) – 2D array of points/coordinates to transform. Each row should have length appropriate for the matrix being used.
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Transformed coordinates.
ndarray
Notes
Input (points) and output (out) arrays cannot be the same instance for this function.
In the case of 4x4 input matrices, this function performs optimizations based on whether the input matrix is affine, greatly improving performance when working with Nx3 arrays.
Examples
Construct a matrix and transform a point:
# identity 3x3 matrix for this example
M = [[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0]]
pnt = [1.0, 0.0, 0.0]
pntNew = applyMatrix(M, pnt)
Construct an SRT matrix (scale, rotate, transform) and transform an array of points:
S = scaleMatrix([5.0, 5.0, 5.0]) # scale 5x
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
points = np.array([[0., 1., 0., 1.], [1., 0., 0., 1.]]) # [x, y, z, w]
newPoints = applyMatrix(M, points) # apply the transformation
Convert CIEXYZ colors to sRGB:
sRGBMatrix = [[3.2404542, 1.5371385, 0.4985314],
[0.969266, 1.8760108, 0.041556 ],
[0.0556434, 0.2040259, 1.0572252]]
colorsRGB = applyMatrix(sRGBMatrix, colorsXYZ)
psychopy.tools.mathtools.
posOriToMatrix
(pos, ori, out=None, dtype=None)[source]¶Convert a rigid body pose to a 4x4 transformation matrix.
A pose is represented by a position coordinate pos and orientation quaternion ori.
pos (ndarray, tuple, or list of float) – Position vector [x, y, z].
ori (tuple, list or ndarray of float) – Orientation quaternion in form [x, y, z, w] where w is real and x, y, z are imaginary 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 computations can either be ‘float32’ or ‘float64’. If out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
4x4 transformation matrix.
ndarray
psychopy.tools.mathtools.
transform
(pos, ori, points, out=None, dtype=None)[source]¶Transform points using a position and orientation. Points are rotated then translated.
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 out is specified, the data type of out is used and this argument is ignored. 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.
psychopy.tools.mathtools.
scale
(sf, points, out=None, dtype=None)[source]¶Scale points by a factor.
This is useful for converting points between units, and to stretch or compress points along a given axis. Scaling can be uniform which the same factor is applied along all axes, or anisotropic along specific axes.
sf (array_like or float) – Scaling factor. If scalar, all points will be scaled uniformly by that factor. If a vector, scaling will be anisotropic along an axis.
points (array_like) – Point(s) [x, y, z] to scale.
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Scaled points.
ndarray
Examples
Apply uniform scaling to points, here we scale to convert points in centimeters to meters:
CM_TO_METERS = 1.0 / 100.0
pointsCM = [[1, 2, 3], [4, 5, 6], [1, 1, 0]]
pointsM = scale(CM_TO_METERS, pointsCM)
Anisotropic scaling along the X and Y axis:
pointsM = scale((SCALE_FACTOR_X, SCALE_FACTOR_Y), pointsCM)
Scale only on the X axis:
pointsM = scale((SCALE_FACTOR_X,), pointsCM)
Apply scaling on the Z axis only:
pointsM = scale((1.0, 1.0, SCALE_FACTOR_Z), pointsCM)
psychopy.tools.mathtools.
lensCorrection
(xys, coefK=(1.0, ), distCenter=(0.0, 0.0), out=None, dtype=None)[source]¶Lens correction (or distortion) using the division model with even polynomial terms.
Calculate new vertex positions or texture coordinates to apply radial warping, such as ‘pincushion’ and ‘barrel’ distortion. This is to compensate for optical distortion introduced by lenses placed in the optical path of the viewer and the display (such as in an HMD).
xys (array_like) – Nx2 list of vertex positions or texture coordinates to distort. Works correctly only if input values range between 1.0 and 1.0.
coefK (array_like or float) – Distortion coefficients K_n. Specifying multiple values will add more polynomial terms to the distortion formula. Positive values will produce ‘barrel’ distortion, whereas negative will produce ‘pincushion’ distortion. In most cases, two or three coefficients are adequate, depending on the degree of distortion.
distCenter (array_like, optional) – X and Y coordinate of the distortion center (eg. (0.2, 0.4)).
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 out is specified, the data type of out is used and this argument is ignored. If out is not provided, ‘float64’ is used by default.
Array of distorted vertices.
ndarray
Notes
At this time tangential distortion (i.e. due to a slant in the display) cannot be corrected for.
References
Fitzgibbon, W. (2001). Simultaneous linear estimation of multiple view geometry and lens distortion. Proceedings of the 2001 IEEE Computer Society Conference on Computer Vision and Pattern Recognition (CVPR). IEEE.
Examples
Creating a lens correction mesh with barrel distortion (eg. for HMDs):
vertices, textureCoords, normals, faces = gltools.createMeshGrid(
subdiv=11, tessMode='center')
# recompute vertex positions
vertices[:, :2] = mt.lensCorrection(vertices[:, :2], coefK=(5., 5.))
psychopy.tools.mathtools.
zeroFix
(a, inplace=False, threshold=None)[source]¶Fix zeros in an array.
This function truncates very small numbers in an array to zero and removes any negative zeros.
a (ndarray) – Input array, must be a Numpy array.
inplace (bool) – Fix an array inplace. If True, the input array will be modified, otherwise a new array will be returned with same dtype and shape with the fixed values.
threshold (float or None) – Threshold for truncation. If None, the machine epsilon value for the input array dtype will be used. You can specify a custom threshold as a float.
Output array with zeros fixed.
ndarray