mascado.utility.affine module

Provide 2D affine transformations.

Interface follows a functional paradigm. Runs on plain NumPy arrays and functions with suffix _cat munch Pandas DataFrames.

mascado.utility.affine.affine_lstsq(origin, target)[source]

Calculate optimal affine transformation in the least-squares sense.

Parameters:
  • origin ((n,2)-shaped array) – x,y points in the domain of the transformation.
  • target ((n,2)-shaped array) – x,y points in the target of the transformation.
Returns:

Matrix representation of affine trafo.

Return type:

(3,3)-shaped array

Notes

The affine transformation is expressed as matrix \(A\) in homogeneous coordinates:

\[\begin{split}\mathtt{target} &= A\cdot\mathtt{origin} \\ \mathbf x^\prime &= A\cdot \mathbf x \\ \begin{bmatrix} x' \\ y' \\ 1 \end{bmatrix} &= \begin{bmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x \\ y \\ 1 \end{bmatrix}\end{split}\]

Rewrite as

\[\begin{split}\begin{bmatrix} x_1' \\ \vdots \\ x_n' \\ y_1' \\ \vdots \\ y_n' \end{bmatrix} = \begin{bmatrix} x_1 & y_1 & 1 & {} & {} & {} \\ {} & \vdots & {} & {} & \mathbf{0} & {} \\ x_n & y_n & 1 & {} & {} & {} \\ {} & {} & {} & x_1 & y_1 & 1 \\ {} & \mathbf{0} & {} & {} & \vdots & {} \\ {} & {} & {} & x_n & y_n & 1 \\ \end{bmatrix} \begin{bmatrix} a_{11} \\ a_{12} \\ a_{13} \\ a_{21} \\ a_{22} \\ a_{23} \\ \end{bmatrix}\end{split}\]

or for short

\[\mathbf y = X \cdot \mathbf a\,.\]

Use pseudo-inverse \(X^+\) for least-squares solution:

\[\mathbf a = X^+ \cdot \mathbf y\]
mascado.utility.affine.affine_lstsq_cat(origin, target, x='x', y='y', ignore_index=False)[source]

Like affine_lstsq with pandas DataFrame.

Parameters:
  • origin ((n,2)-shaped array)
  • target ((n,2)-shaped array)
  • x (string) – Column name of x components of data points.
  • y (string) – Column name of y components of data points.
  • ignore_index (bool) – By default, data points are referenced by their index. Set to True to associate by row position.
Raises:

ValueError – If the catalogs are not of the same length or the indices don’t match.

mascado.utility.affine.affine_trafo(points, trafo)[source]

Apply affine transformation.

Parameters:
  • points ((N,2)-shaped array) – x,y points in the domain of the transformation.
  • trafo ((3,3)-shaped array) – Affine transformation in matrix form.
Returns:

Transformed points.

Return type:

(N,2)-shaped array

mascado.utility.affine.affine_trafo_cat(cat, trafo, x='x', y='y')[source]

Like affine_trafo with pandas DataFrame.

Parameters:
  • cat (pandas.DataFrame) – Catalog with points.
  • trafo ((3,3)-shaped array) – Affine transformation in matrix form.
  • x (string) – Column name of x components of data points.
  • y (string) – Column name of y components of data points.
Returns:

DataFrame with same index and two columns named like input columns.

Return type:

pandas.DataFrame

Examples

>>> trafo = np.array([[1, 0, 3], [2, 1, 0], [0, 0, 1]])
>>> trafo
array([[1, 0, 3],
       [2, 1, 0],
       [0, 0, 1]])
>>> cat = pd.DataFrame(
...     [[0, 0, 'Anja'], [1, 0, 'Bert'], [2, 2, 'Chris']],
...     index=['A', 'B', 'C'], columns=['x', 'y', 'extra'])
>>> cat
   x  y  extra
A  0  0   Anja
B  1  0   Bert
C  2  2  Chris
>>> cat2 = affine_trafo_cat(cat, trafo)
>>> cat2
   x  y
A  3  0
B  4  1
C  5  4

To integrate back into the original catalog do

>>> cat1[cat2.columns] = cat2
>>> cat1
   x  y  extra
A  3  0   Anja
B  4  1   Bert
C  5  4  Chris