Skip to content

Commit 45849df

Browse files
committed
Handle grids one larger than C in gouraud shading
Allow pcolormesh to accept X and Y with dimensions one greater than C when shading='gouraud' by emitting a warning and automatically converting the grid to match the shape of C. Add tests and update documentation.
1 parent 851034a commit 45849df

2 files changed

Lines changed: 46 additions & 10 deletions

File tree

lib/matplotlib/axes/_axes.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6454,9 +6454,18 @@ def _pcolorargs(self, funcname, *args, shading='auto', **kwargs):
64546454
f" see help({funcname})")
64556455
else: # ['nearest', 'gouraud']:
64566456
if (Nx, Ny) != (ncols, nrows):
6457-
raise TypeError('Dimensions of C %s are incompatible with'
6458-
' X (%d) and/or Y (%d); see help(%s)' % (
6459-
C.shape, Nx, Ny, funcname))
6457+
if shading == 'gouraud' and (Nx, Ny) == (ncols + 1, nrows + 1):
6458+
_api.warn_external(f"Dimensions of C {C.shape} should"
6459+
f" be the same as X({Nx}) and Y({Ny})"
6460+
f" while using shading='gouraud'."
6461+
f" X and Y will be modified to match"
6462+
f" dimensions of C. see help({funcname})")
6463+
# the center of each quad is the average of its four corners
6464+
X = 0.25 * (X[:-1, :-1] + X[:-1, 1:] + X[1:, 1:] + X[1:, :-1])
6465+
Y = 0.25 * (Y[:-1, :-1] + Y[:-1, 1:] + Y[1:, 1:] + Y[1:, :-1])
6466+
else:
6467+
raise TypeError(f"Dimensions of C {C.shape} are incompatible with"
6468+
f" X ({Nx}) and/or Y ({Ny}); see help({funcname})")
64606469
if shading == 'nearest':
64616470
# grid is specified at the center, so define corners
64626471
# at the midpoints between the grid centers and then use the
@@ -6751,11 +6760,16 @@ def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
67516760
greater than those of *C*, otherwise a ValueError is raised. The
67526761
quadrilateral is colored due to the value at ``C[i, j]``.
67536762
6754-
If ``shading='nearest'`` or ``'gouraud'``, the dimensions of *X*
6755-
and *Y* should be the same as those of *C* (if not, a ValueError
6756-
will be raised). For ``'nearest'`` the color ``C[i, j]`` is
6757-
centered on ``(X[i, j], Y[i, j])``. For ``'gouraud'``, a smooth
6758-
interpolation is carried out between the quadrilateral corners.
6763+
If ``shading='nearest'`` the dimensions of *X* and *Y* should be
6764+
the same as those of *C*, otherwise a ValueError is raised. The
6765+
color ``C[i, j]`` is centered on ``(X[i, j], Y[i, j])``.
6766+
6767+
If ``shading='gouraud'`` the dimensions of *X* and *Y* should be
6768+
the same as those of *C*; if they are one greater, a warning is
6769+
raised and *X* and *Y* will be modified to match the dimensions
6770+
of *C* by replacing each quadrilateral with a single point at its
6771+
center; otherwise, a ValueError is raised. A smooth interpolation
6772+
is carried out between the quadrilateral corners.
67596773
67606774
If *X* and/or *Y* are 1-D arrays or column vectors they will be
67616775
expanded as needed into the appropriate 2D arrays, making a

lib/matplotlib/tests/test_axes.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,24 @@ def test_pcolor_log_scale(fig_test, fig_ref):
15961596
ax.set_xscale('log')
15971597

15981598

1599+
@check_figures_equal()
1600+
def test_pcolormesh_gouraud_grid_conversion(fig_test, fig_ref):
1601+
Z = np.arange(6).reshape(2, 3)
1602+
1603+
x_test = np.array([0, 2, 8, 12])
1604+
y_test = np.array([0, 2, 6])
1605+
ax_test = fig_test.subplots()
1606+
with pytest.warns(UserWarning,
1607+
match='X and Y will be modified'
1608+
' to match dimensions of C'):
1609+
ax_test.pcolormesh(x_test, y_test, Z, shading='gouraud')
1610+
1611+
x_ref = np.array([1, 5, 10])
1612+
y_ref = np.array([1, 4])
1613+
ax_ref = fig_ref.subplots()
1614+
ax_ref.pcolormesh(x_ref, y_ref, Z, shading='gouraud')
1615+
1616+
15991617
def test_pcolorargs():
16001618
n = 12
16011619
x = np.linspace(-1.5, 1.5, n)
@@ -1609,9 +1627,13 @@ def test_pcolorargs():
16091627
with pytest.raises(TypeError):
16101628
ax.pcolormesh(X, Y, Z.T)
16111629
with pytest.raises(TypeError):
1612-
ax.pcolormesh(x, y, Z[:-1, :-1], shading="gouraud")
1630+
ax.pcolormesh(x, y, Z[:-2, :-2], shading='gouraud')
16131631
with pytest.raises(TypeError):
1614-
ax.pcolormesh(X, Y, Z[:-1, :-1], shading="gouraud")
1632+
ax.pcolormesh(X, Y, Z[:-2, :-2], shading='gouraud')
1633+
with pytest.warns(UserWarning,
1634+
match='X and Y will be modified'
1635+
' to match dimensions of C'):
1636+
ax.pcolormesh(x, y, Z[:-1, :-1], shading='gouraud')
16151637
x[0] = np.nan
16161638
with pytest.raises(ValueError):
16171639
ax.pcolormesh(x, y, Z[:-1, :-1])

0 commit comments

Comments
 (0)