10000 Expire QuadMesh old signature deprecation by oscargus · Pull Request #24356 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Expire QuadMesh old signature deprecation #24356

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

Merged
merged 1 commit into from
Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions doc/api/next_api_changes/removals/24356-OG.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
``QuadMesh`` signature
~~~~~~~~~~~~~~~~~~~~~~

The `.QuadMesh` signature ::

def __init__(meshWidth, meshHeight, coordinates,
antialiased=True, shading='flat', **kwargs)

is removed and replaced by the new signature ::

def __init__(coordinates, *, antialiased=True, shading='flat', **kwargs)

In particular:

- The *coordinates* argument must now be a (M, N, 2) array-like. Previously,
the grid shape was separately specified as (*meshHeight* + 1, *meshWidth* +
1) and *coordinates* could be an array-like of any shape with M * N * 2
elements.
- All parameters except *coordinates* are keyword-only now.
70 changes: 8 additions & 62 deletions lib/matplotlib/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
line segments).
"""

import inspect
import math
from numbers import Number
import warnings
Expand Down Expand Up @@ -1923,62 +1922,15 @@ class QuadMesh(Collection):
i.e. `~.Artist.contains` checks whether the test point is within any of the
mesh quadrilaterals.

There exists a deprecated API version ``QuadMesh(M, N, coords)``, where
the dimensions are given explicitly and ``coords`` is a (M*N, 2)
array-like. This has been deprecated in Matplotlib 3.5. The following
describes the semantics of this deprecated API.

A quadrilateral mesh consists of a grid of vertices.
The dimensions of this array are (*meshWidth* + 1, *meshHeight* + 1).
Each vertex in the mesh has a different set of "mesh coordinates"
representing its position in the topology of the mesh.
For any values (*m*, *n*) such that 0 <= *m* <= *meshWidth*
and 0 <= *n* <= *meshHeight*, the vertices at mesh coordinates
(*m*, *n*), (*m*, *n* + 1), (*m* + 1, *n* + 1), and (*m* + 1, *n*)
form one of the quadrilaterals in the mesh. There are thus
(*meshWidth* * *meshHeight*) quadrilaterals in the mesh. The mesh
need not be regular and the polygons need not be convex.

A quadrilateral mesh is represented by a (2 x ((*meshWidth* + 1) *
(*meshHeight* + 1))) numpy array *coordinates*, where each row is
the *x* and *y* coordinates of one of the vertices. To define the
function that maps from a data point to its corresponding color,
use the :meth:`set_cmap` method. Each of these arrays is indexed in
row-major order by the mesh coordinates of the vertex (or the mesh
coordinates of the lower left vertex, in the case of the colors).

For example, the first entry in *coordinates* is the coordinates of the
vertex at mesh coordinates (0, 0), then the one at (0, 1), then at (0, 2)
.. (0, meshWidth), (1, 0), (1, 1), and so on.
"""

def __init__(self, *args, **kwargs):
# signature deprecation since="3.5": Change to new signature after the
# deprecation has expired. Also remove setting __init__.__signature__,
# and remove the Notes from the docstring.
params = _api.select_matching_signature(
[
lambda meshWidth, meshHeight, coordinates, antialiased=True,
shading='flat', **kwargs: locals(),
lambda coordinates, antialiased=True, shading='flat', **kwargs:
locals()
],
*args, **kwargs).values()
*old_w_h, coords, antialiased, shading, kwargs = params
if old_w_h: # The old signature matched.
_api.warn_deprecated(
"3.5",
message="This usage of Quadmesh is deprecated: Parameters "
"meshWidth and meshHeights will be removed; "
"coordinates must be 2D; all parameters except "
"coordinates will be keyword-only.")
w, h = old_w_h
coords = np.asarray(coords, np.float64).reshape((h + 1, w + 1, 2))
def __init__(self, coordinates, *, antialiased=True, shading='flat',
**kwargs):
kwargs.setdefault("pickradius", 0)
# end of signature deprecation code

_api.check_shape((None, None, 2), coordinates=coords)
self._coordinates = coords
_api.check_shape((None, None, 2), coordinates=coordinates)
self._coordinates = coordinates
self._antialiased = antialiased
self._shading = shading
self._bbox = transforms.Bbox.unit()
Expand All @@ -1988,11 +1940,6 @@ def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
self.set_mouseover(False)

# Only needed during signature deprecation
__init__.__signature__ = inspect.signature(
lambda self, coordinates, *,
antialiased=True, shading='flat', pickradius=0, **kwargs: None)

def get_paths(self):
if self._paths is None:
self.set_paths()
Expand Down Expand Up @@ -2036,11 +1983,10 @@ def set_array(self, A):
faulty_data = True

if misshapen_data:
_api.warn_deprecated(
"3.5", message=f"For X ({width}) and Y ({height}) "
f"with {self._shading} shading, the expected shape of "
f"A is ({h}, {w}). Passing A ({A.shape}) is deprecated "
"since %(since)s and will become an error %(removal)s.")
raise ValueError(
f"For X ({width}) and Y ({height}) with {self._shading} "
f"shading, the expected shape of A is ({h}, {w}), not "
f"{A.shape}")

if faulty_data:
raise TypeError(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that this should be a ValueError?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Expand Down
79 changes: 4 additions & 75 deletions lib/matplotlib/tests/test_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@
import matplotlib.path as mpath
import matplotlib.transforms as mtransforms
from matplotlib.collections import (Collection, LineCollection,
EventCollection, PolyCollection,
QuadMesh)
EventCollection, PolyCollection)
from matplotlib.testing.decorators import check_figures_equal, image_comparison
from matplotlib._api.deprecation import MatplotlibDeprecationWarning


def generate_EventCollection_plot():
Expand Down Expand Up @@ -811,77 +809,6 @@ def test_autolim_with_zeros(transform, expected):
np.testing.assert_allclose(ax.get_xlim(), expected)


@pytest.mark.parametrize('flat_ref, kwargs', [
(True, {}),
(False, {}),
(True, dict(antialiased=False)),
(False, dict(transform='__initialization_delayed__')),
])
@check_figures_equal(extensions=['png'])
def test_quadmesh_deprecated_signature(
fig_test, fig_ref, flat_ref, kwargs):
# test that the new and old quadmesh signature produce the same results
# remove when the old QuadMesh.__init__ signature expires (v3.5+2)
x = [0, 1, 2, 3.]
y = [1, 2, 3.]
X, Y = np.meshgrid(x, y)
X += 0.2 * Y
coords = np.stack([X, Y], axis=-1)
assert coords.shape == (3, 4, 2)
C = np.linspace(0, 2, 6).reshape(2, 3)

ax = fig_test.add_subplot()
ax.set(xlim=(0, 5), ylim=(0, 4))
if 'transform' in kwargs:
kwargs['transform'] = mtransforms.Affine2D().scale(1.2) + ax.transData
qmesh = QuadMesh(coords, **kwargs)
qmesh.set_array(C)
ax.add_collection(qmesh)
assert qmesh._shading == 'flat'

ax = fig_ref.add_subplot()
ax.set(xlim=(0, 5), ylim=(0, 4))
if 'transform' in kwargs:
kwargs['transform'] = mtransforms.Affine2D().scale(1.2) + ax.transData
with pytest.warns(MatplotlibDeprecationWarning):
qmesh = QuadMesh(4 - 1, 3 - 1,
coords.copy().reshape(-1, 2) if flat_ref else coords,
**kwargs)
qmesh.set_array(C.flatten() if flat_ref else C)
ax.add_collection(qmesh)
assert qmesh._shading == 'flat'


@check_figures_equal(extensions=['png'])
def test_quadmesh_deprecated_positional(fig_test, fig_ref):
# test that positional parameters are still accepted with the old signature
# and work correctly
# remove when the old QuadMesh.__init__ signature expires (v3.5+2)
from matplotlib.collections import QuadMesh

x = [0, 1, 2, 3.]
y = [1, 2, 3.]
X, Y = np.meshgrid(x, y)
X += 0.2 * Y
coords = np.stack([X, Y], axis=-1)
assert coords.shape == (3, 4, 2)
C = np.linspace(0, 2, 12).reshape(3, 4)

ax = fig_test.add_subplot()
ax.set(xlim=(0, 5), ylim=(0, 4))
qmesh = QuadMesh(coords, antialiased=False, shading='gouraud')
qmesh.set_array(C)
ax.add_collection(qmesh)

ax = fig_ref.add_subplot()
ax.set(xlim=(0, 5), ylim=(0, 4))
with pytest.warns(MatplotlibDeprecationWarning):
qmesh = QuadMesh(4 - 1, 3 - 1, coords.copy().reshape(-1, 2),
False, 'gouraud')
qmesh.set_array(C)
ax.add_collection(qmesh)


def test_quadmesh_set_array_validation():
x = np.arange(11)
y = np.arange(8)
Expand All @@ -890,7 +817,9 @@ def test_quadmesh_set_array_validation():
coll = ax.pcolormesh(x, y, z)

# Test deprecated warning when faulty shape is passed.
with pytest.warns(MatplotlibDeprecationWarning):
with pytest.raises(ValueError, match=r"For X \(11\) and Y \(8\) with flat "
r"shading, the expected shape of A is \(7, 10\), not "
r"\(10, 7\)"):
coll.set_array(z.reshape(10, 7))

z = np.arange(54).reshape((6, 9))
Expand Down
0