Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix BoundaryNorm cursor data output #22835

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 5 commits into from
Jun 23, 2022

Conversation

yumasheta
Copy link
Contributor

@yumasheta yumasheta commented Apr 12, 2022

PR Summary

This should fix #21915 with an isinstance(norm, BoundaryNorm) check and special logic to figure out the delta for calculating the value for the significant digits to show as cursor data output.
I opted to use the boundaries of the BoundaryNorm directly, instead of calculating the midpoints of neighboring regions (midpoint is done in the non-BoundaryNorm cases).
I also added tests in lib/matplotlib/tests/test_artist.py::test_format_cursor_data_BoundaryNorm. For the tests I compare the cursor data output to identically formatted strings with fixed delta taken as the stepping of np.linspace that is used to create the boundaries for BoundarNorm. The fixed delta values are not identical to what this PR computed, but should give identical output for the strings.

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

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

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a while, please feel free to ping @matplotlib/developers or anyone who has commented on the PR. Most of our reviewers are volunteers and sometimes things fall through the cracks.

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

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

@tacaswell tacaswell added this to the v3.6.0 milestone Apr 13, 2022
@oscargus oscargus added the status: needs workflow approval For PRs from new contributors, from which GitHub blocks workflows by default. label Apr 13, 2022
@yumasheta
Copy link
Contributor Author

I don't have tests for inhomogeneously spaced boundaries. Shall I include some?

@tacaswell
Copy link
Member

I don't have tests for inhomogeneously spaced boundaries. Shall I include some?

On one hand you could argue that more tests are always better (because tests are better than on tests), but that fails in the same way that "if 1 apple is good, then N+1 apples is always better!" fails. More tests take more time to run, more places that things unrelated to the test can go wrong etc.

So, the judgement is if the non-uniform test will exercise something important that is not exercised in the uniform case?

@yumasheta
Copy link
Contributor Author

Not that I can think of.

# map range -1..1 to 0..256 in 0.01 steps
fig, ax = plt.subplots()
fig.suptitle("-1..1 to 0..256 in 0.001")
cmap = cm.get_cmap('RdBu_r', 2000)
Copy link
Member

@oscargus oscargus Apr 21, 2022

Choose a reason for hiding this comment

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

Looks like you are not using this variable? (And therefore not the cm import.) Nor the similar in the previous section.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right. Fixed it! (Though, I think resampling the colormap to match the number of regions only makes a difference when viewing the plots.)

Copy link
Member

Choose a reason for hiding this comment

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

I also think so, so the alternate fix of just removing the cmap may have been preferred. But now these tests will also serve as examples, so I am not strongly in favor in removing it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Me too, that's why I left them in. The tests are more complete this way and produce expected results if anyone decided to look at the plots, or took my tests as examples.

@yumasheta yumasheta requested a review from oscargus May 7, 2022 11:48
Copy link
Member

@oscargus oscargus left a comment

Choose a reason for hiding this comment

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

I think the fix looks good!

One could possibly consider simplifying/shortening the test code a bit:

  • Direct creation of test data (instead of assigning separate elements)
  • Removing cmap (as discussed earlier)
  • Skipping figure titles
  • No need to close as next plot is created in a new fig

However, apart from the first point, the rest are useful when running the code in a terminal. Not sure what the consensus is on this (although I guess no one would object if they weren't there).

@oscargus oscargus added topic: collections and mappables and removed status: needs workflow approval For PRs from new contributors, from which GitHub blocks workflows by default. labels May 17, 2022
@jklymak
Copy link
Member

jklymak commented May 18, 2022

Is there some reason to not just use this approximation to make BoundaryNorm (non-uniquely) invertible?

@jklymak jklymak modified the milestones: v3.6.0, v3.5.3 May 22, 2022
@jklymak
Copy link
Member

jklymak commented May 22, 2022

This actually is a regression and should be fixed ASAP...

@yumasheta
Copy link
Contributor Author

Is there some reason to not just use this approximation to make BoundaryNorm (non-uniquely) invertible?

My PR doesn't include this functionality. It depends on the data being available and works around the inversion by using argmin.
If I'm not mistaken...

@@ -372,3 +374,117 @@ class MyArtist4(MyArtist3):
pass

assert MyArtist4.set is MyArtist3.set


def test_format_cursor_data_BoundaryNorm():
Copy link
Member

Choose a reason for hiding this comment

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

Why are you testing this in test_artist? are there other format tests in test_artist?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because my changes are in artist.py. What's a better place?

Copy link
Member

Choose a reason for hiding this comment

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

... fair!

norm = mcolors.BoundaryNorm(np.linspace(-1, 1, 20), 256)
img = ax.imshow(X, cmap='RdBu_r', norm=norm)
for v in X.flat:
label = "[{:-#.{}g}]".format(v, cbook._g_sig_digits(v, 0.1))
Copy link
Member

Choose a reason for hiding this comment

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

This test just tests that the code is called, not that the resulting labels are correct. Please consider writing out explicitly what the labels should be and comparing those.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, but I do this fixture for all the tests. Yes, I do in principle only test, if the cbook._g_sig_digits is called. But the important check is, if it is called with the correct arguments. My PR only prepares the values for the arguments.

Instead of comparing the output of Artist.format_cursor_data I could also just test if the delta argument is correct. But as it is now, I also test if the output for the cursor data is actually generated correctly. I do compare with a predefined label, though not written out explicitly but generated via a custom cbook call.

So I don't know what to do? Do you want me to just replace l. 398 with the verbatim output of the format call?

Copy link
Member

Choose a reason for hiding this comment

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

So I don't know what to do? Do you want me to just replace l. 398 with the verbatim output of the format call?

Yes, I think so. In general it is bad for the tests to include private methods, though that is a rule meant to be broken...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, it is more understandable that way. But I left the original lines with the cbook as comments.

@jklymak jklymak marked this pull request as draft June 23, 2022 08:26
@jklymak
Copy link
Member

jklymak commented Jun 23, 2022

the fix looks good. The tests are circular, and I'm not sure ware in correct place. Moved to draft, feel free to mark "ready" when addressed Thanks!

@yumasheta yumasheta marked this pull request as ready for review June 23, 2022 11:54
@jklymak
Copy link
Member

jklymak commented Jun 23, 2022

I'll merge once CI is done - feel free to squash, or we will squash for you at merge....

@jklymak jklymak merged commit 6e5a541 into matplotlib:main Jun 23, 2022
@jklymak
Copy link
Member

jklymak commented Jun 23, 2022

Thanks @yumasheta !

meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Jun 23, 2022
tacaswell added a commit that referenced this pull request Jun 23, 2022
…835-on-v3.5.x

Backport PR #22835 on branch v3.5.x (Fix BoundaryNorm cursor data output)
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]: scalar mappable format_cursor_data crashes on BoundarNorm
4 participants