Skip to content

ENH: Add centered-gouraud shading to pcolormesh#31362

Open
lucaznch wants to merge 4 commits intomatplotlib:mainfrom
lucaznch:centered-gouraud
Open

ENH: Add centered-gouraud shading to pcolormesh#31362
lucaznch wants to merge 4 commits intomatplotlib:mainfrom
lucaznch:centered-gouraud

Conversation

@lucaznch
Copy link

PR summary

This PR adds the centered-gouraud shading to Axes.pcolormesh. It is a variant of gouraud that adds support for grids that are one larger than the data in each dimension. In this situation, centered-gouraud automatically converts it to match the data by taking the centers of each quadrilateral, averaging its four corners, and then applies Gouraud shading.

  • Why is this change necessary / what problem does it solve?

    pcolormesh with shading='gouraud' requires the grid to match the shape of the data. If the user is working with a grid one larger in each dimension and tries to use gouraud, a TypeError is raised. centered-gouraud solves this by allowing such grids without requiring users to reshape them.

  • What is the reasoning for this implementation?

    Rather than modifying the existing gouraud shading, a new shading was added following a discussion with @timhoffm on the issue this PR addresses.

Example:

import matplotlib.pyplot as plt
import numpy as np

nrows = 3
ncols = 5
Z = np.arange(nrows * ncols).reshape(nrows, ncols)
x = np.arange(ncols + 1)
y = np.arange(nrows + 1)

fig, ax = plt.subplots()

ax.pcolormesh(x, y, Z, shading='flat')
ax.pcolormesh(x, y, Z, shading='gouraud') # doesn't work
ax.pcolormesh(x, y, Z, shading='centered-gouraud') # works

Closes #8422

AI Disclosure

I used AI tools to help proofread and improve the grammar of this PR description. The code logic and implementation are my own.

PR checklist

@github-actions github-actions bot added topic: rcparams Documentation: examples files in galleries/examples labels Mar 24, 2026
@github-actions
Copy link

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a week or so, please leave a new comment below and that should bring it to our attention. Most of our reviewers are volunteers and sometimes things fall through the cracks. We also ask that you please finish addressing any review comments on this PR and wait for it to be merged (or closed) before opening a new one, as it can be a valuable learning experience to go through the review process.

You can also join us on gitter for real-time discussion.

For details on testing, writing docs, and our review process, please see the developer guide.
Please let us know if (and how) you use AI, it will help us give you better feedback on your PR.

We strive to be a welcoming and open project. Please follow our Code of Conduct.

@lucaznch
Copy link
Author

I realized I forgot to run boilerplate.py to update pyplot.py, which is why some tests were failing. Ive just amended the commit and pushed the updated branch!

@melissawm melissawm moved this to Needs review in First Time Contributors Mar 25, 2026
@scottshambaugh
Copy link
Contributor

New docs:
image

Copy link
Contributor

@scottshambaugh scottshambaugh left a comment

Choose a reason for hiding this comment

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

I kind of prefer extending 'gouraud' rather than making a separate 'centered-gouraud', but can see @timhoffm rationale for keeping them separate.

Code and docs all look good to me!

@melissawm melissawm moved this from Needs review to Waiting for author in First Time Contributors Mar 25, 2026
@lucaznch
Copy link
Author

Thank you for the review and suggestion. I updated that part to use f-strings.

Copy link
Member

@timhoffm timhoffm left a comment

Choose a reason for hiding this comment

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

My mental model is that we need to primarily distinguish the data semantics: Are the values at the corners of the quadrilaterals (n_grid = n_data + 1) or at the centers (n_grid = ndata)?

Therefore switching should only work between "nearest" <-> "gouraud" and "flat" <-> "centered-gouraud"

discrete continuous
data at corners "nearest" "gouraud"
data at centers "flat" "centered-gouraud"

"auto" just selects between "flat" and "nearest" based on the geometry.

We probably should rewrite the whole shading logic more in these terms. While I don't require this to be part of this PR, the descriptions added here should be consistent with that logic.

Edit: I had mixed up "nearest" and "flat" above. Now corrected.

@jklymak
Copy link
Member

jklymak commented Mar 26, 2026

If you want to be completely parallel you could have "flat-gouraud" and "nearest-gouraud" and then have "gouraud" be like "auto" and just do the right thing.

@timhoffm
Copy link
Member

If you want to be completely parallel you could have "flat-gouraud" and "nearest-gouraud" and then have "gouraud" be like "auto" and just do the right thing.

Hm, while this would be structurally the same, the naming would be a bit awkward. "flat" stems from the idea that there is a constant value across the quadrilateral. "nearest" meas "take the color from the nearest grid node. Both do not rhyme with a continous shading that gouraud implies. I believe if we want more consistent naming we would need to rethink the the whole set of names "constant" and "gouraud" would be the automatic ones (and discourage "auto" in favor of "constant"). Not sure about the grid-specific ones; maybe "nodes-constant", "centered-condstant", "nodes-gouraud", "centered-gouraud".
There is also a slight semantic difference in that the gouraud variants define the colors at exactly the points and interpolate in between, whereas the constants can be interpreted either as directly meaning the whole area "the quadrilateral has as constant value" or as defining the color on a single point ("color at the quadrilateral center") and filling with constant extrapolation.

It's a bit the question whether we want to advertize/encourage automatic response to the shape constallations, or whether we prefer explicit specification that the data points are meant to be on the grid nodes or the quadrilateral centers.

@jklymak
Copy link
Member

jklymak commented Mar 26, 2026

Fair enough, that is awkward.

Just to review the context of the original changes: the old behaviour of flat if x and y matched the shape of Z was intolerable: it dropped a row and column of Z and shifted the data over by half a cell in x and y. Yet I'd bet the amount of data that is stored that way outnumbers data where x and y are the borders of the cell by 100:1. So matplotlib (and Matlab still) were actively dropping data and changing its spatial phase without even warning the user.

Here the problem is less, and the opposite. Occasional users who have x and y having one ore element than Z in each dimension cannot make a plot. I think we should just help those users by automatically plotting the data at the centres, and maybe emiting a warning. But I'm fine if we want to have a different named option to allow this.

Implement a variant of Gouraud shading that supports
grids with dimensions one greater than the data in each dimension.
Add tests and documentation.
Update type hints and rcParams validation.
Include a What's New entry.

Fixes matplotlib#8422
@lucaznch
Copy link
Author

Thanks for the feedback. Ive made the suggested changes and pushed everything. I noticed however that several automated tests are failing. I’m not sure if these are related to my changes or unrelated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Waiting for author

Development

Successfully merging this pull request may close these issues.

plt.pcolormesh shape mismatch when shading='gouraud'

5 participants