Source code for py3dframe.matrix.O3_project
import numpy
[docs]
def O3_project(matrix: numpy.ndarray) -> numpy.ndarray:
r"""
Project a matrix to the orthogonal group :math:`O(3)` using SVD and minimisation of the frobenius norm.
The orthogonal group `O(3)` is the set of 3x3 orthonormal matrices with determinant equal to 1 or -1.
To project a matrix to `O(3)`, the SVD is computed and the orthogonal matrix is obtained by:
.. math::
\mathbf{O} = \mathbf{U} \mathbf{V}^T
where :math:`\mathbf{U}` and :math:`\mathbf{V}` are the left and right singular vectors of the matrix such as:
.. math::
\mathbf{M} = \mathbf{U} \mathbf{\Sigma} \mathbf{V}^T
.. seealso::
- function :func:`py3dframe.matrix.is_O3` for the check of orthonormality.
- function :func:`py3dframe.matrix.SO3_project` for the projection of a matrix to the special orthogonal group :math:`SO(3)`.
Parameters
----------
matrix : array_like
A 3x3 matrix to be projected.
Returns
-------
numpy.ndarray
The `O(3)` projection of the matrix.
Raises
------
ValueError
If the matrix is not 3x3.
Examples
--------
>>> import numpy
>>> from py3dframe import O3_project
>>> e1 = numpy.array([1, 1, 0])
>>> e2 = numpy.array([-1, 1, 0])
>>> e3 = numpy.array([0, 0, 1])
>>> matrix = numpy.column_stack((e1, e2, e3))
>>> print(O3_project(matrix))
[[ 0.70710678 -0.70710678 0. ]
[ 0.70710678 0.70710678 0. ]
[ 0. 0. 1. ]]
"""
matrix = numpy.array(matrix).astype(numpy.float64)
if matrix.shape != (3, 3):
raise ValueError("The matrix must be 3x3.")
U, _, Vt = numpy.linalg.svd(matrix)
orthogonal_matrix = U @ Vt
return orthogonal_matrix