Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: 3D Transforms #28098

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file modified doc/_static/transforms.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions doc/api/next_api_changes/deprecations/28098-AT.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
``Affine2DBase``, ``BlendedAffine2D`` and ``CompositeAffine2D``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

...are deprecated and replaced with ``AffineImmutable``, ``BlendedAffine``, and
``CompositeAffine`` respectively.
8 changes: 4 additions & 4 deletions doc/api/transformations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

.. automodule:: matplotlib.transforms
:members: TransformNode, BboxBase, Bbox, TransformedBbox, Transform,
TransformWrapper, AffineBase, Affine2DBase, Affine2D, IdentityTransform,
BlendedGenericTransform, BlendedAffine2D, blended_transform_factory,
CompositeGenericTransform, CompositeAffine2D,
composite_transform_factory, BboxTransform, BboxTransformTo,
TransformWrapper, AffineBase, AffineImmutable, Affine2DBase, Affine2D,
IdentityTransform, BlendedGenericTransform, BlendedAffine, BlendedAffine2D,
blended_transform_factory, CompositeGenericTransform, CompositeAffine,
CompositeAffine2D, composite_transform_factory, BboxTransform, BboxTransformTo,
BboxTransformFrom, ScaledTranslation, TransformedPath, nonsingular,
interval_contains, interval_contains_open
:show-inheritance:
Expand Down
16 changes: 16 additions & 0 deletions doc/users/next_whats_new/non_2d_transforms.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Added support for Non 2-dimensional transforms
----------------------------------------------

Support has been added for transforms in matplotlib that aren't 2D.

``AffineImmutable`` directly replaces ``Affine2DBase``, and introduces a ``dims``
keyword that specifies the dimension of the transform, defaulting to 2.

``BlendedAffine`` directly replaces ``BlendedAffine2D``, and can blend more than
two transforms, with each transform handling a different axis.

``CompositeAffine`` directly replaces ``CompositeAffine2D``, and composes two Affine
transforms, as long as they have the same dimensions.

``IdentityTransform`` can create identity matrices of any dimension, through the use of
the ``dims`` keyword.
9 changes: 5 additions & 4 deletions doc/users/prev_whats_new/whats_new_1.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,11 @@ every subplot and you need to make some space for legend's labels.
Support for skewed transformations
``````````````````````````````````
The :class:`~matplotlib.transforms.Affine2D` gained additional methods
`.skew` and `.skew_deg` to create skewed transformations. Additionally,
matplotlib internals were cleaned up to support using such transforms in
`~matplotlib.axes.Axes`. This transform is important for some plot types,
specifically the Skew-T used in meteorology.
:func:`~matplotlib.transforms.Affine2D.skew` and
:func:`~matplotlib.transforms.Affine2D.skew_deg` to create skewed transformations.
Additionally, matplotlib internals were cleaned up to support using such transforms in
`~matplotlib.axes.Axes`. This transform is important for some plot types, specifically
the Skew-T used in meteorology.

.. figure:: ../../gallery/specialty_plots/images/sphx_glr_skewt_001.png
:target: ../../gallery/specialty_plots/skewt.html
Expand Down
8 changes: 4 additions & 4 deletions galleries/tutorials/artists.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,15 +463,15 @@ class in the Matplotlib API, and the one you will be working with most
# In [268]: print(rect.get_data_transform())
# CompositeGenericTransform(
# TransformWrapper(
# BlendedAffine2D(
# BlendedAffine(
# IdentityTransform(),
# IdentityTransform())),
# CompositeGenericTransform(
# BboxTransformFrom(
# TransformedBbox(
# Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0),
# TransformWrapper(
# BlendedAffine2D(
# BlendedAffine(
# IdentityTransform(),
# IdentityTransform())))),
# BboxTransformTo(
Expand All @@ -489,15 +489,15 @@ class in the Matplotlib API, and the one you will be working with most
# In [269]: print(ax.transData)
# CompositeGenericTransform(
# TransformWrapper(
# BlendedAffine2D(
# BlendedAffine(
# IdentityTransform(),
# IdentityTransform())),
# CompositeGenericTransform(
# BboxTransformFrom(
# TransformedBbox(
# Bbox(x0=0.0, y0=0.0, x1=1.0, y1=1.0),
# TransformWrapper(
# BlendedAffine2D(
# BlendedAffine(
# IdentityTransform(),
# IdentityTransform())))),
# BboxTransformTo(
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,10 +439,10 @@ def draw_image(self, gc, x, y, im, transform=None):
im : (N, M, 4) array of `numpy.uint8`
An array of RGBA pixels.

transform : `~matplotlib.transforms.Affine2DBase`
transform : `~matplotlib.transforms.AffineImmutable`
If and only if the concrete backend is written such that
`option_scale_image` returns ``True``, an affine transformation
(i.e., an `.Affine2DBase`) *may* be passed to `draw_image`. The
(i.e., an `.AffineImmutable`) *may* be passed to `draw_image`. The
translation vector of the transformation is given in physical units
(i.e., dots or pixels). Note that the transformation does not
override *x* and *y*, and has to be applied *before* translating
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/backend_bases.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class RendererBase:
x: float,
y: float,
im: ArrayLike,
transform: transforms.Affine2DBase | None = ...,
transform: transforms.AffineImmutable | None = ...,
) -> None: ...
def option_image_nocomposite(self) -> bool: ...
def option_scale_image(self) -> bool: ...
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/backends/backend_svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from matplotlib.dates import UTC
from matplotlib.path import Path
from matplotlib import _path
from matplotlib.transforms import Affine2D, Affine2DBase
from matplotlib.transforms import Affine2D, AffineImmutable


_log = logging.getLogger(__name__)
Expand Down Expand Up @@ -255,7 +255,7 @@ def _generate_transform(transform_list):
or type == 'translate' and value == (0, 0)
or type == 'rotate' and value == (0,)):
continue
if type == 'matrix' and isinstance(value, Affine2DBase):
if type == 'matrix' and isinstance(value, AffineImmutable):
value = value.to_values()
parts.append('{}({})'.format(
type, ' '.join(_short_float_fmt(x) for x in value)))
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -1062,10 +1062,10 @@ def get_path_collection_extents(
master_transform : `~matplotlib.transforms.Transform`
Global transformation applied to all paths.
paths : list of `Path`
transforms : list of `~matplotlib.transforms.Affine2DBase`
transforms : list of `~matplotlib.transforms.AffineImmutable`
If non-empty, this overrides *master_transform*.
offsets : (N, 2) array-like
offset_transform : `~matplotlib.transforms.Affine2DBase`
offset_transform : `~matplotlib.transforms.AffineImmutable`
Transform applied to the offsets before offsetting the path.

Notes
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/projections/polar.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def inverted(self):
)


class PolarAffine(mtransforms.Affine2DBase):
class PolarAffine(mtransforms.AffineImmutable):
r"""
The affine part of the polar projection.

Expand All @@ -181,7 +181,7 @@ def __init__(self, scale_transform, limits):
View limits of the data. The only part of its bounds that is used
is the y limits (for the radius limits).
"""
super().__init__()
super().__init__(dims=2)
self._scale_transform = scale_transform
self._limits = limits
self.set_children(scale_transform, limits)
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/projections/polar.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class PolarTransform(mtransforms.Transform):
) -> None: ...
def inverted(self) -> InvertedPolarTransform: ...

class PolarAffine(mtransforms.Affine2DBase):
class PolarAffine(mtransforms.AffineImmutable):
def __init__(
self, scale_transform: mtransforms.Transform, limits: mtransforms.BboxBase
) -> None: ...
Expand Down