Welcome to rasterio/affine’s documentation!

This is the documentation of the latest development version at https://github.com/rasterio/affine .

Affine

Matrices describing 2D affine transformation of the plane.

https://github.com/rasterio/affine/actions/workflows/ci.yml/badge.svg?branch=main https://codecov.io/gh/rasterio/affine/branch/main/graph/badge.svg Documentation Status

The Affine package is derived from Casey Duncan’s Planar package. Please see the copyright statement in affine/__init__.py.

Usage

The 3x3 augmented affine transformation matrix for transformations in two dimensions is illustrated below.

| x' |   | a  b  c | | x |
| y' | = | d  e  f | | y |
| 1  |   | 0  0  1 | | 1 |

Matrices can be created by passing the values a, b, c, d, e, f to the affine.Affine constructor or by using its identity(), translation(), scale(), shear(), and rotation() class methods.

>>> from affine import Affine
>>> Affine.identity()
Affine(1.0, 0.0, 0.0,
       0.0, 1.0, 0.0)
>>> Affine.translation(1.0, 5.0)
Affine(1.0, 0.0, 1.0,
       0.0, 1.0, 5.0)
>>> Affine.scale(2.0)
Affine(2.0, 0.0, 0.0,
       0.0, 2.0, 0.0)
>>> Affine.shear(45.0, 45.0)  # decimal degrees
Affine(1.0, 0.9999999999999999, 0.0,
       0.9999999999999999, 1.0, 0.0)
>>> Affine.rotation(45.0)     # decimal degrees
Affine(0.7071067811865476, -0.7071067811865475, 0.0,
       0.7071067811865475, 0.7071067811865476, 0.0)

These matrices can be applied to (x, y) tuples to obtain transformed coordinates (x', y').

>>> Affine.translation(1.0, 5.0) * (1.0, 1.0)
(2.0, 6.0)
>>> Affine.rotation(45.0) * (1.0, 1.0)
(1.1102230246251565e-16, 1.414213562373095)

They may also be multiplied together to combine transformations.

>>> Affine.translation(1.0, 5.0) * Affine.rotation(45.0)
Affine(0.7071067811865476, -0.7071067811865475, 1.0,
       0.7071067811865475, 0.7071067811865476, 5.0)

Usage with GIS data packages

Georeferenced raster datasets use affine transformations to map from image coordinates to world coordinates. The affine.Affine.from_gdal() class method helps convert GDAL GeoTransform, sequences of 6 numbers in which the first and fourth are the x and y offsets and the second and sixth are the x and y pixel sizes.

Using a GDAL dataset transformation matrix, the world coordinates (x, y) corresponding to the top left corner of the pixel 100 rows down from the origin can be easily computed.

>>> geotransform = (-237481.5, 425.0, 0.0, 237536.4, 0.0, -425.0)
>>> fwd = Affine.from_gdal(*geotransform)
>>> col, row = 0, 100
>>> fwd * (col, row)
(-237481.5, 195036.4)

The reverse transformation is obtained using the ~ operator.

>>> rev = ~fwd
>>> rev * fwd * (col, row)
(0.0, 99.99999999999999)

Module documentation

Affine transformation matrices

The Affine package is derived from Casey Duncan’s Planar package. See the copyright statement below.

class affine.Affine(a: float, b: float, c: float, d: float, e: float, f: float, g: float = 0.0, h: float = 0.0, i: float = 1.0)[source]

Two dimensional affine transform for 2D linear mapping.

Parameters

a, b, c, d, e, ffloat

Coefficients of an augmented affine transformation matrix

x’ | | a b c | | x |
y’ | = | d e f | | y |
1 | | 0 0 1 | | 1 |

a, b, and c are the elements of the first row of the matrix. d, e, and f are the elements of the second row.

Attributes

a, b, c, d, e, f, g, h, ifloat

The coefficients of the 3x3 augmented affine transformation matrix

x’ | | a b c | | x |
y’ | = | d e f | | y |
1 | | g h i | | 1 |

g, h, and i are always 0, 0, and 1.

The Affine package is derived from Casey Duncan’s Planar package. See the copyright statement below. Parallel lines are preserved by these transforms. Affine transforms can perform any combination of translations, scales/flips, shears, and rotations. Class methods are provided to conveniently compose transforms from these operations.

Internally the transform is stored as a 3x3 transformation matrix. The transform may be constructed directly by specifying the first two rows of matrix values as 6 floats. Since the matrix is an affine transform, the last row is always (0, 0, 1).

N.B.: multiplication of a transform and an (x, y) vector always returns the column vector that is the matrix multiplication product of the transform and (x, y) as a column vector, no matter which is on the left or right side. This is obviously not the case for matrices and vectors in general, but provides a convenience for users of this class.

almost_equals(other, precision: float = 1e-05) bool[source]

Compare transforms for approximate equality.

Parameters:

other (Affine) – Transform being compared.

Returns:

True if absolute difference between each element of each respective transform matrix < self.precision.

property column_vectors

The values of the transform as three 2D column vectors

property determinant

The determinant of the transform matrix.

This value is equal to the area scaling factor when the transform is applied to a shape.

property eccentricity: float

The eccentricity of the affine transformation.

This value represents the eccentricity of an ellipse under this affine transformation.

Raises NotImplementedError for improper transformations.

classmethod from_gdal(c: float, a: float, b: float, f: float, d: float, e: float)[source]

Use same coefficient order as GDAL’s GetGeoTransform().

Parameters:

e (c, a, b, f, d,) – 6 floats ordered by GDAL.

Return type:

Affine

classmethod identity()[source]

Return the identity transform.

Return type:

Affine

property is_conformal: bool

True if the transform is conformal.

i.e., if angles between points are preserved after applying the transform, within rounding limits. This implies that the transform has no effective shear.

property is_degenerate

True if this transform is degenerate.

Which means that it will collapse a shape to an effective area of zero. Degenerate transforms cannot be inverted.

property is_identity: bool

True if this transform equals the identity matrix, within rounding limits.

property is_orthonormal: bool

True if the transform is orthonormal.

Which means that the transform represents a rigid motion, which has no effective scaling or shear. Mathematically, this means that the axis vectors of the transform matrix are perpendicular and unit-length. Applying an orthonormal transform to a shape always results in a congruent shape.

property is_proper

True if this transform is proper.

Which means that it does not include reflection.

property is_rectilinear: bool

True if the transform is rectilinear.

i.e., whether a shape would remain axis-aligned, within rounding limits, after applying the transform.

itransform(seq) None[source]

Transform a sequence of points or vectors in place.

Parameters:

seq – Mutable sequence of Vec2 to be transformed.

Returns:

None, the input sequence is mutated in place.

classmethod permutation(*scaling)[source]

Create the permutation transform

For 2x2 matrices, there is only one permutation matrix that is not the identity.

Return type:

Affine

classmethod rotation(angle: float, pivot=None)[source]

Create a rotation transform at the specified angle.

A pivot point other than the coordinate system origin may be optionally specified.

Parameters:
  • angle (float) – Rotation angle in degrees, counter-clockwise about the pivot point.

  • pivot (sequence) – Point to rotate about, if omitted the rotation is about the origin.

Return type:

Affine

property rotation_angle: float

The rotation angle in degrees of the affine transformation.

This is the rotation angle in degrees of the affine transformation, assuming it is in the form M = R S, where R is a rotation and S is a scaling.

Raises UndefinedRotationError for improper and degenerate transformations.

classmethod scale(*scaling)[source]

Create a scaling transform from a scalar or vector.

Parameters:

scaling (float or sequence) – The scaling factor. A scalar value will scale in both dimensions equally. A vector scaling value scales the dimensions independently.

Return type:

Affine

classmethod shear(x_angle: float = 0, y_angle: float = 0)[source]

Create a shear transform along one or both axes.

Parameters:
  • x_angle (float) – Shear angle in degrees parallel to the x-axis.

  • y_angle (float) – Shear angle in degrees parallel to the y-axis.

Return type:

Affine

to_gdal()[source]

Return same coefficient order as GDAL’s SetGeoTransform().

Return type:

tuple

to_shapely()[source]

Return an affine transformation matrix compatible with shapely

Shapely’s affinity module expects an affine transformation matrix in (a,b,d,e,xoff,yoff) order.

Return type:

tuple

classmethod translation(xoff: float, yoff: float)[source]

Create a translation transform from an offset vector.

Parameters:
  • xoff (float) – Translation x offset.

  • yoff (float) – Translation y offset.

Return type:

Affine

property xoff: float

Alias for ‘c’

property yoff: float

Alias for ‘f’

CHANGES

2.4.0 (2023-01-19)

  • Package is marked as Python 3 only, two instances of “%” string formatting are replaced by f-strings (#96).

2.4b1 (2023-01-18)

  • Elimination of Python 2/3 compatibility code in __gt__ (#94).

  • Addition of optional keyword arguments for __new__, solving an issue with Dask (#92).

  • Addition of some type hints for float arguments and return types (#87).

  • Python version support is now 3.7-3.11 (#82).

  • Faster __new__ and from_gdal methods (#78).

2.3.1 (2022-03-24)

Bug fixes:

  • Return NotImplemented for both ValueError and TypeError in __mul__ to support fallback to __rmul__ in more cases (gh-71).

2.3.0 (2019-09-04)

Deprecations:

  • Right multiplication like vector * matrix is deprecated and will raise AffineError in version 3.0.0.

Bug fixes:

  • Change signature of Affine constructor to help users of PyCharm (#45).

  • The Affine class docstring has been improved.

2.2.2 (2018-12-20)

  • Affine.itransform computed the wrong results for arrays with rotation or shear (#40). This is fixed (#41).

2.2.1 (2018-06-04)

  • Docstring improvements (#37).

2.2.0 (2018-03-20)

  • Addition of permutation matrix (#35).

2.1.0 (2017-07-12)

  • Addition of new eccentricity and rotation_angle properties (#28).

2.0.0.post1 (2016-05-20)

  • This is the final 2.0.0 release. The post-release version segment is used because we accidentally uploaded a 2.0.0 to PyPI before the beta releases below.

2.0b2 (2016-05-16)

  • Bug fix: restore Affine __rmul__ even though it permits dubious vector * matrix expressions (#27).

2.0b1 (2016-05-16)

  • Breaking change: precision used in properties like is_conformal is no longer a global module attribute, but an Affine class or instance attribute (#19, #20).

  • Breaking change: is_degenerate property is now exact and not subject to a level of precision (#23).

  • Breaking change: we have reversed our sense of rotation, a positive angle now rotates a point counter-clockwise about the pivot point (#25).

  • Bug fix: a bug in matrix-vector multiplication had been reversing the direction of rotation and is now fixed (#25).

1.3.0 (2016-04-08)

  • is_degenerate predicate is precise, not approximate (#22).

1.2.0 (2015-06-01)

  • Enable pickling of Affine objects (#14).

  • Sort out the mixed up shearing parameters (#12).

1.1.0 (2014-11-13)

  • Add loadsw/dumpsw world file utilities (#6).

  • Travis-CI and Coveralls config and web hooks added (#10).

1.0.1 (2014-10-20)

  • set_epsilon() now actually sets module EPSILON (#4).

  • add AUTHORS.txt.

1.0 (2014-05-27)

  • Code ported from Casey Duncan’s Planar package.

  • from_gdal() class method added.

Authors

License

Copyright (c) 2014, Sean C. Gillies
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of Sean C. Gillies nor the names of
      its contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

Indices and tables