Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c56e3c5

Browse files
authored
Merge pull request #20237 from timhoffm/quadmesh-init
Make QuadMesh arguments with defaults keyword_only
2 parents 185a298 + ed036db commit c56e3c5

File tree

4 files changed

+172
-21
lines changed

4 files changed

+172
-21
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
QuadMesh signature
2+
~~~~~~~~~~~~~~~~~~
3+
The ``QuadMesh`` signature ::
4+
5+
def __init__(meshWidth, meshHeight, coordinates,
6+
antialiased=True, shading=False, **kwargs)
7+
8+
is deprecated and replaced by the new signature ::
9+
10+
def __init__(coordinates, *, antialiased=True, shading=False, **kwargs)
11+
12+
In particular:
13+
14+
- *coordinates* must now be a (M, N, 2) array-like. Previously, the grid
15+
shape was separately specified as (*meshHeight* + 1, *meshWidth* + 1) and
16+
*coordinates* could be an array-like of any shape with M * N * 2 elements.
17+
- all parameters except *coordinates* are keyword-only now.

lib/matplotlib/axes/_axes.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6115,16 +6115,12 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
61156115

61166116
X, Y, C, shading = self._pcolorargs('pcolormesh', *args,
61176117
shading=shading, kwargs=kwargs)
6118-
Ny, Nx = X.shape
6119-
X = X.ravel()
6120-
Y = Y.ravel()
6121-
6122-
# convert to one dimensional arrays
6118+
coords = np.stack([X, Y], axis=-1)
6119+
# convert to one dimensional array
61236120
C = C.ravel()
6124-
coords = np.column_stack((X, Y)).astype(float, copy=False)
6125-
collection = mcoll.QuadMesh(Nx - 1, Ny - 1, coords,
6126-
antialiased=antialiased, shading=shading,
6127-
**kwargs)
6121+
6122+
collection = mcoll.QuadMesh(
6123+
coords, antialiased=antialiased, shading=shading, **kwargs)
61286124
snap = kwargs.get('snap', rcParams['pcolormesh.snap'])
61296125
collection.set_snap(snap)
61306126
collection.set_alpha(alpha)
@@ -6134,6 +6130,8 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
61346130
collection._scale_norm(norm, vmin, vmax)
61356131
self._pcolor_grid_deprecation_helper()
61366132

6133+
coords = coords.reshape(-1, 2) # flatten the grid structure; keep x, y
6134+
61376135
# Transform from native to data coordinates?
61386136
t = collection._transform
61396137
if (not isinstance(t, mtransforms.Transform) and
@@ -6310,7 +6308,7 @@ def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
63106308
else:
63116309
raise ValueError("C must be 2D or 3D")
63126310
collection = mcoll.QuadMesh(
6313-
nc, nr, coords, **qm_kwargs,
6311+
coords, **qm_kwargs,
63146312
alpha=alpha, cmap=cmap, norm=norm,
63156313
antialiased=False, edgecolors="none")
63166314
self.add_collection(collection, autolim=False)

lib/matplotlib/collections.py

Lines changed: 75 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@
99
line segments).
1010
"""
1111

12+
import inspect
1213
import math
1314
from numbers import Number
15+
import warnings
16+
1417
import numpy as np
1518

1619
import matplotlib as mpl
1720
from . import (_api, _path, artist, cbook, cm, colors as mcolors, docstring,
1821
hatch as mhatch, lines as mlines, path as mpath, transforms)
1922
from ._enums import JoinStyle, CapStyle
20-
import warnings
2123

2224

2325
# "color" is excluded; it is a compound setter, and its docstring differs
@@ -1931,6 +1933,35 @@ class QuadMesh(Collection):
19311933
"""
19321934
Class for the efficient drawing of a quadrilateral mesh.
19331935
1936+
A quadrilateral mesh is a grid of M by N adjacent qudrilaterals that are
1937+
defined via a (M+1, N+1) grid of vertices. The quadrilateral (m, n) is
1938+
defind by the vertices ::
1939+
1940+
(m+1, n) ----------- (m+1, n+1)
1941+
/ /
1942+
/ /
1943+
/ /
1944+
(m, n) -------- (m, n+1)
1945+
1946+
The mesh need not be regular and the polygons need not be convex.
1947+
1948+
Parameters
1949+
----------
1950+
coordinates : (M+1, N+1, 2) array-like
1951+
The vertices. ``coordinates[m, n]`` specifies the (x, y) coordinates
1952+
of vertex (m, n).
1953+
1954+
antialiased : bool, default: True
1955+
1956+
shading : {'flat', 'gouraud'}, default: 'flat'
1957+
1958+
Notes
1959+
-----
1960+
There exists a deprecated API version ``QuadMesh(M, N, coords)``, where
1961+
the dimensions are given explicitly and ``coords`` is a (M*N, 2)
1962+
array-like. This has been deprecated in Matplotlib 3.5. The following
1963+
describes the semantics of this deprecated API.
1964+
19341965
A quadrilateral mesh consists of a grid of vertices.
19351966
The dimensions of this array are (*meshWidth* + 1, *meshHeight* + 1).
19361967
Each vertex in the mesh has a different set of "mesh coordinates"
@@ -1954,22 +1985,55 @@ class QuadMesh(Collection):
19541985
vertex at mesh coordinates (0, 0), then the one at (0, 1), then at (0, 2)
19551986
.. (0, meshWidth), (1, 0), (1, 1), and so on.
19561987
1957-
*shading* may be 'flat', or 'gouraud'
19581988
"""
1959-
def __init__(self, meshWidth, meshHeight, coordinates,
1960-
antialiased=True, shading='flat', **kwargs):
1989+
def __init__(self, *args, **kwargs):
1990+
# signature deprecation since="3.5": Change to new signature after the
1991+
# deprecation has expired. Also remove setting __init__.__signature__,
1992+
# and remove the Notes from the docstring.
1993+
#
1994+
# We use lambdas to parse *args, **kwargs through the respective old
1995+
# and new signatures.
1996+
try:
1997+
# Old signature:
1998+
# The following raises a TypeError iif the args don't match.
1999+
w, h, coords, antialiased, shading, kwargs = (
2000+
lambda meshWidth, meshHeight, coordinates, antialiased=True,
2001+
shading=False, **kwargs:
2002+
(meshWidth, meshHeight, coordinates, antialiased, shading,
2003+
kwargs))(*args, **kwargs)
2004+
except TypeError as exc:
2005+
# New signature:
2006+
# If the following raises a TypeError (i.e. args don't match),
2007+
# just let it propagate.
2008+
coords, antialiased, shading, kwargs = (
2009+
lambda coordinates, antialiased=True, shading=False, **kwargs:
2010+
(coordinates, antialiased, shading, kwargs))(*args, **kwargs)
2011+
coords = np.asarray(coords, np.float64)
2012+
else: # The old signature matched.
2013+
_api.warn_deprecated(
2014+
"3.5",
2015+
message="This usage of Quadmesh is deprecated: Parameters "
2016+
"meshWidth and meshHeights will be removed; "
2017+
"coordinates must be 2D; all parameters except "
2018+
"coordinates will be keyword-only.")
2019+
coords = np.asarray(coords, np.float64).reshape((h + 1, w + 1, 2))
2020+
# end of signature deprecation code
2021+
19612022
super().__init__(**kwargs)
1962-
self._meshWidth = meshWidth
1963-
self._meshHeight = meshHeight
1964-
# By converting to floats now, we can avoid that on every draw.
1965-
self._coordinates = np.asarray(coordinates, float).reshape(
1966-
(meshHeight + 1, meshWidth + 1, 2))
2023+
_api.check_shape((None, None, 2), coordinates=coords)
2024+
self._coordinates = coords
2025+
self._meshWidth = self._coordinates.shape[1] - 1
2026+
self._meshHeight = self._coordinates.shape[0] - 1
19672027
self._antialiased = antialiased
19682028
self._shading = shading
19692029

19702030
self._bbox = transforms.Bbox.unit()
1971-
self._bbox.update_from_data_xy(coordinates.reshape(
1972-
((meshWidth + 1) * (meshHeight + 1), 2)))
2031+
self._bbox.update_from_data_xy(self._coordinates.reshape(-1, 2))
2032+
2033+
# Only needed during signature deprecation
2034+
__init__.__signature__ = inspect.signature(
2035+
lambda self, coordinates, *,
2036+
antialiased=True, shading='flat', **kwargs: None)
19732037

19742038
def get_paths(self):
19752039
if self._paths is None:

lib/matplotlib/tests/test_collections.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,78 @@ def test_singleton_autolim():
714714
np.testing.assert_allclose(ax.get_xlim(), [-0.06, 0.06])
715715

716716

717+
@pytest.mark.parametrize('flat_ref, kwargs', [
718+
(True, {}),
719+
(False, {}),
720+
(True, dict(antialiased=False)),
721+
(False, dict(transform='__initialization_delayed__')),
722+
])
723+
@check_figures_equal(extensions=['png'])
724+
def test_quadmesh_deprecated_signature(
725+
fig_test, fig_ref, flat_ref, kwargs):
726+
# test that the new and old quadmesh signature produce the same results
727+
# remove when the old QuadMesh.__init__ signature expires (v3.5+2)
728+
from matplotlib.collections import QuadMesh
729+
730+
x = [0, 1, 2, 3.]
731+
y = [1, 2, 3.]
732+
X, Y = np.meshgrid(x, y)
733+
X += 0.2 * Y
734+
coords = np.stack([X, Y], axis=-1)
735+
assert coords.shape == (3, 4, 2)
736+
C = np.linspace(0, 2, 12).reshape(3, 4)
737+
738+
ax = fig_test.add_subplot()
739+
ax.set(xlim=(0, 5), ylim=(0, 4))
740+
if 'transform' in kwargs:
741+
kwargs['transform'] = mtransforms.Affine2D().scale(1.2) + ax.transData
742+
qmesh = QuadMesh(coords, **kwargs)
743+
qmesh.set_array(C)
744+
ax.add_collection(qmesh)
745+
746+
ax = fig_ref.add_subplot()
747+
ax.set(xlim=(0, 5), ylim=(0, 4))
748+
if 'transform' in kwargs:
749+
kwargs['transform'] = mtransforms.Affine2D().scale(1.2) + ax.transData
750+
with pytest.warns(MatplotlibDeprecationWarning):
751+
qmesh = QuadMesh(4 - 1, 3 - 1,
752+
coords.copy().reshape(-1, 2) if flat_ref else coords,
753+
**kwargs)
754+
qmesh.set_array(C.flatten() if flat_ref else C)
755+
ax.add_collection(qmesh)
756+
757+
758+
@check_figures_equal(extensions=['png'])
759+
def test_quadmesh_deprecated_positional(fig_test, fig_ref):
760+
# test that positional parameters are still accepted with the old signature
761+
# and work correctly
762+
# remove when the old QuadMesh.__init__ signature expires (v3.5+2)
763+
from matplotlib.collections import QuadMesh
764+
765+
x = [0, 1, 2, 3.]
766+
y = [1, 2, 3.]
767+
X, Y = np.meshgrid(x, y)
768+
X += 0.2 * Y
769+
coords = np.stack([X, Y], axis=-1)
770+
assert coords.shape == (3, 4, 2)
771+
coords_flat = coords.copy().reshape(-1, 2)
772+
C = np.linspace(0, 2, 12).reshape(3, 4)
773+
774+
ax = fig_test.add_subplot()
775+
ax.set(xlim=(0, 5), ylim=(0, 4))
776+
qmesh = QuadMesh(coords, antialiased=False, shading='gouraud')
777+
qmesh.set_array(C)
778+
ax.add_collection(qmesh)
779+
780+
ax = fig_ref.add_subplot()
781+
ax.set(xlim=(0, 5), ylim=(0, 4))
782+
with pytest.warns(MatplotlibDeprecationWarning):
783+
qmesh = QuadMesh(4 - 1, 3 - 1, coords.copy().reshape(-1, 2),
784+
False, 'gouraud')
785+
qmesh.set_array(C)
786+
ax.add_collection(qmesh)
787+
788+
717789
def test_quadmesh_set_array():
718790
x = np.arange(4)
719791
y = np.arange(4)

0 commit comments

Comments
 (0)