8000 Fix boundary norm negative by jklymak · Pull Request #21676 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Fix boundary norm negative #21676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 20, 2021
Merged

Conversation

jklymak
Copy link
Member
@jklymak jklymak commented Nov 19, 2021

PR Summary

Closes #21671

Fixes an issue where the BoundaryNorm colorbar was broken if the boundaries were negative. Added new test to make sure this doesn't break again.

I'll be honest, I find this part of the colorbar code a bit inscrutable, and it doesn't have a lot of unit tests. So more bug reports to help get all the combinations down would be helpful.

PR Checklist

Tests and Styling

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (install flake8-docstrings and run flake8 --docstring-convention=all).

Documentation

  • New features are documented, with examples if plot related.
  • New features have an entry in doc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented in doc/api/next_api_changes/ (follow instructions in README.rst there).
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).

@jklymak jklymak added this to the v3.5.1 milestone Nov 19, 2021
Copy link
Contributor
@anntzer anntzer left a comment

Choose a reason for hiding this comment

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

Concerned this is not the right fix, as a variant (above) still fails.

@@ -1150,7 +1150,7 @@ def _mesh(self):

def _forward_boundaries(self, x):
b = self._boundaries
y = np.interp(x, b, np.linspace(0, b[-1], len(b)))
y = np.interp(x, b, np.linspace(0, np.abs(b[-1]), len(b)))
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you clarify what is being computed here? Without context, it seems wrong that only the last point of b is taken into account, in particular the example in #21671 fails again (with this PR) if b[-1] == 0 (e.g., clevs = list(range(-94, 1))), or rather the resulting plot is wrong.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch. Fixed. OTOH do we know if clevs=np.arange(1, -9, -1) should be allowed?

Copy link
Contributor

Choose a reason for hiding this comment

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

I would like decreasing levels to be allowed, but to be clear that's a separate issue that can be dealt with later; the problem here is with increasing levels where the last level is zero.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I can confirm that clev=np.arange(1, -9, -1) used to return nonsense on v3.4.3. It errors on this PR as of my latest push, which seems better than nonsense, but it can probably be made to work.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would it work to just set the second arg to range(len(b)) instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

though now that I look at it y[x > b[-1]+eps] = 2 can't possibly be right...

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I meant the third. I'm also a bit confused by the setting to -1/+2 for out-of-bounds values...

Copy link
Member Author

Choose a reason for hiding this comment

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

No thats clearly wrong. Fixed in the latest. However, I played with this, and there are no tests of this happening, so I'm not sure where this hedging came from. I think it may have been extra ticks in the extend region, but that can't really happen (because its just bounds mapping to bounds) so maybe we don't need all this...

Copy link
Contributor
@anntzer anntzer Nov 19, 2021

Choose a reason for hiding this comment

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

I see that in the new version you're mapping to np.linspace(0, db, len(b)), which, while not "wrong", still seems weird to me (I still think the mapped-to space should be either range(len(b)) or np.linspace(0, 1, len(b)) -- db doesn't have any particular meaning in that space). And then I'd map the out of bounds points to -1 and len(b) (first case) or -1/(len(b)-1) and 1+1/(len(b)-1) (second case) (which I guess argues that the first representation is simpler).

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, I think that works...

@jklymak jklymak force-pushed the fix-boundary-norm-negative branch from 6423cc5 to 6d329fa Compare November 19, 2021 11:54
@jklymak
Copy link
Member Author
jklymak commented Nov 19, 2021

Just to describe what this does so I'm not just hacking...

_forward_boundaries maps from boundaries = [-9, -8, -6, -1, 0] to [0, 2, 4, 6, 8] so that the levels are equally spaced and yielding a colorbar for the spacing='uniform' option of colorbar;

cbar

I don't think this needs an image test because we do visually test the boundary norm, just we weren't doing it with negative levels, so the proposed test should be adequate.

@jklymak jklymak requested a review from anntzer November 19, 2021 12:13
@jklymak jklymak force-pushed the fix-boundary-norm-negative branch from c0e7110 to 7ce4a7e Compare November 19, 2021 20:07
@jklymak
Copy link
Member Author
jklymak commented Nov 20, 2021

@anntzer This version (boundaries mapped from 0-1) fails on pixel snapping of ticks at test_contour/test_contourf_log_extension. If I change back to map the boundaries between 0-(b[-1]-b[0]) the pixel snapping is the same as on main. In my opinion the pixel snapping looks better that way, however, I don't think its correct to say its "better".

Image instability because of pixel snapping is pretty annoying...

@anntzer
Copy link
Contributor
anntzer commented Nov 20, 2021

Which one is "better" for you? (sorry, that was a bit unclear for me in your message) I looked at the images; it seems that the difference basically arises because the boundary between two color blocks occurs between two pixel rows, and it's just a matter of deciding whether the tick is drawn on the last row of the first block or the first row of the second block, which is a bit arbitrary?

I think I'd just stick a tol=... on that test (as we know where the discrepancy comes from) and be done with it?

@jklymak
Copy link
Member Author
jklymak commented Nov 20, 2021

Yep - if we just tested PDFs that might be better - bitmapping is done visually on the PDF, rather than with our numerically unstable snapping behaviour in the AGG backends. However, testing PDFs is slower...

@anntzer
Copy link
Contributor
anntzer commented Nov 20, 2021

Let's just live with what we have for now? :)

@jklymak
Copy link
Member Author
jklymak commented Nov 20, 2021

(Yes, but in general I've been favouring png-only tests a lot of time, whereas now I think maybe we should favour pdf-only... Though pdf sometimes has its own problems. )

Copy link
Contributor
@anntzer anntzer left a comment

Choose a reason for hiding this comment

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

lgtm, modulo CI and possibly squashing.

@jklymak jklymak force-pushed the fix-boundary-norm-negative branch from 34329d2 to 089430c Compare November 20, 2021 09:43
@jklymak
Copy link
Member Author
jklymak commented Nov 20, 2021

squashed....

@anntzer anntzer merged commit 3da111b into matplotlib:main Nov 20, 2021
meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Nov 20, 2021
@jklymak jklymak deleted the fix-boundary-norm-negative branch November 20, 2021 11:15
jklymak added a commit that referenced this pull request Nov 20, 2021
…676-on-v3.5.x

Backport PR #21676 on branch v3.5.x (Fix boundary norm negative)
@QuLogic
Copy link
< A5D7 /details>
Member
QuLogic commented Nov 22, 2021

Yep - if we just tested PDFs that might be better - bitmapping is done visually on the PDF, rather than with our numerically unstable snapping behaviour in the AGG backends. However, testing PDFs is slower...

'visually on the PDF' is just rasterizing at a different step, and is dependent on the rasterizer in use. I'm not sure this is any safer given PDFs sometimes break when updating Ghostscript, even if visually you see no difference.

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.

[Bug]: 3.5.0 colorbar ValueError: minvalue must be less than or equal to maxvalue
4 participants
0