Skip to content

Fix contour level color mapping with explicit limits#599

Merged
cvanelteren merged 12 commits intomainfrom
fix/issue-329-contour-color-mapping
Feb 26, 2026
Merged

Fix contour level color mapping with explicit limits#599
cvanelteren merged 12 commits intomainfrom
fix/issue-329-contour-color-mapping

Conversation

@cvanelteren
Copy link
Collaborator

@cvanelteren cvanelteren commented Feb 26, 2026

Closes #329
This PR fixes the contour normalization behavior when manual levels are provided. The core problem was that explicit vmin and vmax were being discarded in the level-parsing path and then effectively overridden again inside DiscreteNorm, so contourf(..., levels=..., vmin=..., vmax=...) did not respect the user’s intended range. In the same area, line contours were also being routed through discrete binning logic that is appropriate for filled contours but not for level lines, which could cause adjacent line levels to resolve to the same color even when explicit colors were supplied. The change preserves explicit normalization limits when they are provided, keeps the existing default level-driven stretching when they are not, and keeps line contours on a continuous mapping path so level colors remain one-to-one with the requested values. Regression tests were added to lock in all three behaviors.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes contour colormap normalization so that explicitly provided vmin/vmax are respected when manual levels are supplied, and ensures line contours use continuous normalization to keep level-to-color mapping one-to-one.

Changes:

  • Preserve explicit vmin/vmax through contour level parsing and into DiscreteNorm.
  • Update DiscreteNorm to only “stretch” bins to the full colormap range when vmin/vmax match the level bounds (default behavior), otherwise honor explicit limits.
  • Add regression tests covering explicit-limit behavior, default stretching, and explicit per-level contour line colors.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
ultraplot/axes/plot.py Thread vmin/vmax through level parsing and prevent DiscreteNorm binning for line contours (min_levels == 1).
ultraplot/colors.py Adjust DiscreteNorm to respect explicit normalization limits and only apply the prior level-driven stretching by default.
ultraplot/tests/test_2dplots.py Add regression tests for explicit limits with manual levels, default stretching, and line contour level color mapping.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 4825 to 4828
# Generate DiscreteNorm for filled-contour style bins. For line contours
# (`min_levels == 1`) levels represent contour values, so keep the
# continuous normalizer to preserve one-to-one value->color mapping.
center_levels = _not_none(center_levels, rc["colorbar.center_levels"])
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

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

The _parse_level_norm docstring says it returns a DiscreteNorm/BoundaryNorm, but with the new min_levels == 1 behavior it can return the original continuous Normalize (line contours). Please update the Returns section to reflect the possible return types so users don't rely on an incorrect contract.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

Copy link
Contributor

Copilot AI commented Feb 26, 2026

@cvanelteren I've opened a new pull request, #600, to work on those changes. Once the pull request is ready, I'll request review from you.

cvanelteren and others added 3 commits February 26, 2026 14:30
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…600)

* Initial plan

* Update _parse_level_norm docstring Returns section to reflect possible return types

Co-authored-by: cvanelteren <19485143+cvanelteren@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Casper van Elteren <caspervanelteren@gmail.com>
Co-authored-by: cvanelteren <19485143+cvanelteren@users.noreply.github.com>
@cvanelteren cvanelteren enabled auto-merge (squash) February 26, 2026 04:40
@cvanelteren cvanelteren disabled auto-merge February 26, 2026 05:15
@cvanelteren
Copy link
Collaborator Author

Hmmm something funky going on with some of the categorical colorbars -- will need to fix this another time.

@cvanelteren cvanelteren enabled auto-merge (squash) February 26, 2026 07:21
@cvanelteren cvanelteren merged commit 3378000 into main Feb 26, 2026
15 checks passed
@cvanelteren cvanelteren deleted the fix/issue-329-contour-color-mapping branch February 26, 2026 07:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Default norm when using levels in contour(f) produce non-intuitive behavior.

3 participants