Skip to content

include max value in pcolormesh output when levels are requested#10954

Open
JJFlorian wants to merge 6 commits intopydata:mainfrom
JJFlorian:include-max-value
Open

include max value in pcolormesh output when levels are requested#10954
JJFlorian wants to merge 6 commits intopydata:mainfrom
JJFlorian:include-max-value

Conversation

@JJFlorian
Copy link
Copy Markdown
Contributor

@JJFlorian JJFlorian commented Nov 28, 2025

image

Not the most elegant solution, but it works and I couldn't figure out another way of solving this for now. The test_discrete_colormap_list_of_levels test fails now, but I would say that it is safe to use numpy's assert_array_almost_equal.

If its not, I'll try to find another solution.

@welcome
Copy link
Copy Markdown

welcome Bot commented Nov 28, 2025

Thank you for opening this pull request! It may take us a few days to respond here, so thank you for being patient.
If you have questions, some answers may be found in our contributing guidelines.

@kkollsga
Copy link
Copy Markdown
Contributor

kkollsga commented Feb 8, 2026

Nice find — the nextafter nudge is the right idea. I think the fix can be made a bit more targeted though, which would avoid weakening the existing test.

The root cause is in _build_discrete_cmap, not _determine_cmap_params — it's specifically BoundaryNorm's half-open intervals [a, b) that exclude vmax. If we nudge the norm's boundaries there instead of the levels themselves, cmap_params["levels"] stays clean and the existing assert_array_equal test still passes:

def _build_discrete_cmap(cmap, levels, extend, filled):
    ...
    new_cmap, cnorm = mpl.colors.from_levels_and_colors(levels, pal, extend=extend)

    # BoundaryNorm uses half-open intervals [a, b), so values exactly at the
    # last boundary are excluded. When there's no "over" extension, nudge the
    # upper boundary so vmax is included in the last bin. (GH10911)
    if extend in ("neither", "min"):
        boundaries = cnorm.boundaries.copy()
        boundaries[-1] = np.nextafter(boundaries[-1], np.inf)
        cnorm = mpl.colors.BoundaryNorm(boundaries, cnorm.Ncmap)

    ...

The condition checks extend rather than comparing against calc_data — when extend has no "over" handling, there's no color assigned for values beyond the last boundary, so we need the last bin to be inclusive. When extend is "max" or "both", values above the last boundary already get the over-color, so the nudge isn't needed.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Maximum value not always included in pcolormesh output when levels are requested

2 participants