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

Skip to content

Display cursor coordinates for all axes twinned with the current one. #25556

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 2 commits into from
Apr 3, 2024

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Mar 26, 2023

PR Summary

Closes #4284, closes #5506 (also: #2986 (comment)).

PR Checklist

Documentation and Tests

  • Has pytest style unit tests (and pytest passes)
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).
  • New plotting related features are documented with examples.

Release Notes

  • New features are marked with a .. versionadded:: directive in the docstring and documented in doc/users/next_whats_new/
  • API changes are marked with a .. versionchanged:: directive in the docstring and documented in doc/api/next_api_changes/
  • Release notes conform with instructions in next_whats_new/README.rst or next_api_changes/README.rst

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.

While I've not tested this i have some reservations concerning performance. format_coord is called on mouse move and should be fast. Likely a worst-case scenario are 10x10 Axes without twinning, but using a Cursor so that delays become more apparent.

we should at least have an early return if there are no twins.

@anntzer
Copy link
Contributor Author

anntzer commented Mar 27, 2023

Sure, I added an early return for the twinless case.
I agree the retrieval of twins is a bit awkward; I think the proper fix this would be to move the storage of twinning info into a better data structure that keeps the ordering info as well (OTOH we may not need the asymptotic complexity guarantees of a union-find in practice...).

Edit: done as a separate commit: I switched Grouper so that it handles the ordering.

efiring
efiring previously requested changes Jun 5, 2023
Copy link
Member

@efiring efiring left a comment

Choose a reason for hiding this comment

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

Just one typo.

This seems like a reasonable thing to do. I haven't tried to check the performance. Given that for a stream of mouse move events the twin lists and the transforms aren't going to change, there is considerable unnecessary work going on; but reducing it might be more trouble than it is worth.

Possible bike-shedding: change the joins from " / " to ", "? I think it would be more readable.

@anntzer
Copy link
Contributor Author

anntzer commented Jun 5, 2023

Did you try playing with it (e.g. plot(); twinx() and move the mouse around) with a ", " separator? I think " / " is more readable, but certainly that's subjective and I can go with whatever separator has the approval of most.

Reducing the "duplicate" work seems not so easy without introducing some layers of caching and cache invalidation, which I'm not particularly keen to do.

@greglucas
Copy link
Contributor

I just tested it out and it seemed pretty good performance wise to me.

I would vote for pipe "|" instead of the slant for the separator.

@anntzer
Copy link
Contributor Author

anntzer commented Jun 6, 2023

Sure, works for me.

Comment on lines 787 to 853
# For each item, we store (order_in_which_item_was_seen, group_of_item), which
# lets __iter__ and get_siblings return items in the order in which they have
# been seen.
Copy link
Member

Choose a reason for hiding this comment

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

Is this necessary? If I understand this correctly, you just encode the insertion order into the WeakKeyDictionary. Can't we rely on order preservation there? I've not tested this thoroughly but the internal data format WeakKeyDictionary.data is a plain dict, which preserves order. So it should work as is. While WeakKeyDictionary has no official documentation whehter it preserves order or not, I assume CPython would not drop that de-facto feature without deprecation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Order preservation isn't really sufficient.
The mapping is storing {ax: [sibling0, sibling1, ...], ...} and what matters is that the list of siblings is sorted by the order in which they themselves occur in the mapping. So we could not explicitly store the index and instead sort the siblings by key=list(self._mapping).index (taking advantage of order preservation) before returning them but that's less efficient.

Comment on lines 3930 to 3934
" | ".join(
ax.format_xdata(ax.transData.inverted().transform(screen_xy)[0])
for ax in sorted(y_twins, key=attrgetter("zorder"))),
" | ".join(
ax.format_xdata(ax.transData.inverted().transform(screen_xy)[1])
Copy link
Member

@timhoffm timhoffm Jun 6, 2023

Choose a reason for hiding this comment

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

Just realizing that this yield x=1 | 2 y=5, which is not very readable. In particular | creates a stronger visual separation than the space before y.

I suggest to regroup into x, y pairs (even if that means

I suggest to either: x=1 ; 2 | y=5.

Or regrouping into x, y pairs per Axes: x, y = (1, 5) | (2, 5)

Copy link
Member

Choose a reason for hiding this comment

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

on the call we like x, y = (1, 5) | (4, 5) best and lean to changing the non-twinned version to be x, y = (1, 3)

@tacaswell tacaswell added this to the v3.8.0 milestone Jun 8, 2023
@anntzer
Copy link
Contributor Author

anntzer commented Jun 8, 2023

This was discussed during the call today. Looks like the preferred option is Tim's last one ((x, y) = (x1, y1) | (x2, y2)), also changing for the non-twinned case and paying attention to make that also work for the 3d case.
Polar axes don't work too well with this format because they already display theta both in degrees and in radians, but we chose not to worry too much about them as twinned polar axes seem extremely rare.

@efiring
Copy link
Member

efiring commented Jun 8, 2023

Meeting consensus: switch everything (regular and twinned) to @timhoffm's last suggestion above.

@tacaswell
Copy link
Member

🤣 Three of us posting notes about the meeting consensus.

@anntzer
Copy link
Contributor Author

anntzer commented Aug 13, 2023

I implemented the (x, y) = (..., ...) | (..., ...) output format in the last commit, but it turns out that's quite wide and tends to overflow the toolbar (depending on the exact axes limits); perhaps the reviewers can give it a try.

@QuLogic
Copy link
Member

QuLogic commented Mar 13, 2024

Here is what it can look like for plt.plot([1, 2]); plt.twinx().plot([4, 3]):
Screenshot from 2024-03-13 17-17-58

@ksunden
Copy link
Member

ksunden commented Mar 14, 2024

Did a rebase, partially to rerun tests since logs were removed.

Test failures are real, and related to the change at hand.

@QuLogic
Copy link
Member

QuLogic commented Mar 22, 2024

Ping @anntzer on the above.

@anntzer
Copy link
Contributor Author

anntzer commented Mar 24, 2024

Fixed.

@QuLogic
Copy link
Member

QuLogic commented Mar 25, 2024

Python 3.12 error seems related.

@anntzer
Copy link
Contributor Author

anntzer commented Mar 26, 2024

Fixed for real this time? Sorry for the back and forth.

@anntzer
Copy link
Contributor Author

anntzer commented Apr 2, 2024

I also figured out that it would be much cleaner for Grouper to keep track of the ordering info in a separate dict rather than sticking everything in _mapping; moved that to a new _ordering dict instead.

@ksunden ksunden dismissed efiring’s stale review April 3, 2024 20:07

typo has been addressed

@ksunden ksunden merged commit a515fc5 into matplotlib:main Apr 3, 2024
@anntzer anntzer deleted the twincursor branch April 3, 2024 20:27
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.

Confusing status bar values in presence of multiple axes Twin axis message coordinates
7 participants