Skip to content

Fix for #9608: RectangleSelector now reports mouse button press and release events correctly #20611

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

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

rowlesmr
Copy link

@rowlesmr rowlesmr commented Jul 9, 2021

PR Summary

Fix for #9608

"Normalisation" of the click and release mouse button events for the RectangleSelector is removed. The click and release mouse button events reported by the onselect function now reflect the actual press and release coordinates, and not the extent of the rectangle.

If the extent of the rectangle is required, then extent should be explicitly called.

The test_widgets test was updated to reflect the change in behaviour of the release event. Previously, the extent was used, now the actual release coordinates are used.

PR Checklist

  • Has pytest style unit tests (and pytest passes).
  • Is Flake 8 compliant (run flake8 on changed files to check).
  • [N/A] New features are documented, with examples if plot related.
  • [N/A] Documentation is sphinx and numpydoc compliant (the docs should build without error).
  • Conforms to Matplotlib style conventions (install flake8-docstrings and run flake8 --docstring-convention=all).
  • [N/A] 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).

widgets.py definitely needs work on style conventions - about 200 lines of output on python -m flake8 --docstring-convention=all C:\Users_____\Documents\GitHub\matplotlib\lib\matplotlib\widgets.py

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.

rowlesmr added 3 commits July 9, 2021 17:20
Mouse release is now taken as the coordinates of the actual mouse button release. Previously, the onmove set the extent of rectangle, and the extent was used as the mouse press and release coordinates. Now they are decoupled, and the test must be updated.
Comment on lines 2702 to 2703
x = self._eventpress.xdata
y = self._eventpress.ydata
Copy link
Member

Choose a reason for hiding this comment

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

Please keep this using event; I might remove _eventpress as a state.

Copy link
Author

Choose a reason for hiding this comment

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

Removing _eventpress might be a little difficult, as _release(event) refers to _eventpress to calculate span, and also for calling onselect. The reference for the span calculation might be able to be gotten around, but we'd then need to reconstruct the press event to send to onselect.

Copy link
Member

Choose a reason for hiding this comment

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

I'm aware, but at this point event == self._eventpress, so it should be fine to go back.

Copy link
Author

Choose a reason for hiding this comment

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

Done. Also updated _release to refer to event instead of _eventrelease. _release still needs _eventpress to properly calculate the span.

Copy link
Member

@ericpre ericpre left a comment

Choose a reason for hiding this comment

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

Would it be more useful to change the docstring rather than returning the eventpress and eventrelease position? Mainly, because otherwise, it will be useless with interactive=True - typically when dragging or resizing the selector. With interactive=False, the eventpress and eventrelease will match the extents the selector.
What would be the benefit of returning the eventpress and eventrelease position? I guess the docstring was correct before the interactive functionality was added.

event == self._eventpress in _press and event == self._eventrelease in _release, so this makes sure the _release and _press functions refer to the event that is passed to them.
@rowlesmr
Copy link
Author

@ericpre - the extents of the selector always refer to the bottom left and top right of the rectangle, regardless of the order of the actual clicking. Sometimes you need to know the direction in which the rectangle was drawn, so you need to differentiate between click and release. If you want the extent, call extent.

@ericpre
Copy link
Member

ericpre commented Jul 20, 2021

@ericpre - the extents of the selector always refer to the bottom left and top right of the rectangle, regardless of the order of the actual clicking. Sometimes you need to know the direction in which the rectangle was drawn, so you need to differentiate between click and release. If you want the extent, call extent.

Yes, the issue is that onselect now has to use eventpress and eventrelease and this is what is useless when using the handles. With this is PR, it is not possible to use extents in the onselect callback function.

@jklymak
Copy link
Member

jklymak commented Jul 20, 2021

This is not passing the doc build. Also please rebase on master if you know how to do that.

@QuLogic
Copy link
Member

QuLogic commented Jul 20, 2021

Yes, the issue is that onselect now has to use eventpress and eventrelease and this is what is useless when using the handles. With this is PR, it is not possible to use extents in the onselect callback function.

I don't understand the problem. Just sort the coordinates if you need them strictly increasing in the callback? Sorting them before passing to the callback reduces the possible usage.

@rowlesmr
Copy link
Author

This is not passing the doc build. Also please rebase on master if you know how to do that.

I haven't touched any of the docs for this function/file (afaik). How is it failing/where do I need to read about building docs? I don't know about rebasing on master.

@ericpre
Copy link
Member

ericpre commented Jul 21, 2021

Yes, the issue is that onselect now has to use eventpress and eventrelease and this is what is useless when using the handles. With this is PR, it is not possible to use extents in the onselect callback function.

I don't understand the problem. Just sort the coordinates if you need them strictly increasing in the callback? Sorting them before passing to the callback reduces the possible usage.

Sorry, I was not very clear. When using a selector on an axis, I would expect that in the callback that I get the current selection, as it is for example in the case of the SpanSelector with onselect(min, max). With this PR, the onselect signature will match the current selection only when used with interactive=False or for a new selection only when interactive=True. Any changes to the selection using handles will not provide the selection. See for example:

import matplotlib.pyplot as plt
from matplotlib.widgets import RectangleSelector


def onselect(eclick, erelease):
    print("onselect callback triggered")
    print("Press event: ", eclick.xdata, eclick.ydata)
    print("Release event: ", erelease.xdata, erelease.ydata)

fig = plt.figure()
ax = fig.add_subplot()
ax.plot([0, 10], [0, 20])

rs = RectangleSelector(ax, onselect, interactive=True)

Peek 2021-07-21 08-53

will give the following output:

onselect callback triggered
Press event:  2.493951612903226 15.32142857142857
Release event:  5.709677419354839 5.142857142857142
onselect callback triggered
Press event:  5.6875 10.261904761904761
Release event:  6.818548387096775 10.142857142857142

The last press and release events can't be used to retrieve the data selection.

@rowlesmr
Copy link
Author

This comes back to my initial question. To make it conditional on interactive, or to just expect users to have an explicit call to extents to get the size of the current selection?

@ericpre
Copy link
Member

ericpre commented Jul 26, 2021

In my opinion, using the extent makes more sense and is consistent with the SpanSelector. Please correct me if I am wrong, but I don't see what could be the advantage of using eventpress and eventrelease in favour of the extent: the extent will also reports the correct selection range while the events press/release will not.
The only sense I can make of the current implementation is that it was implementated before interactive and before that, it was behaving correctly. interactive has been implemented for a while now and I guess the behaviour of onselect has never been adjusted accordingly, i. e. to report correct selection range in any situation.

@tacaswell
Copy link
Member

Related to my comment in #9608 I am 👎🏻 on merging this as is.

I think @ericpre 's point about the interteractive case in very strong that in interactive mode you expect to get back the corners of rectangle, not necessarily the point the user just clicked on (eg, when they dragged on the edge) as the thing of interest is the "rectangle area". By just returning the point the user release on they won't get that anymore.

A case could be made for remembering the "first" corner and the "release" corner on the initial selection and then normalizing to that so onselect always gets to opposite corners of a rectangle at their full extent, however that seems like a fair amount of book-keeping / logic to get right and it would be changing behavior that has stood for 4+ years and runs the risk of breaking a different set of users.

As I mentioned in #9608 I think the best course of action here is to

  1. update the documentation to describe the behavior
  2. implement a VectorSelector with handles and the whole 9 yards to handle to use case that the original poster had

@rowlesmr Even though we are having a mostly critical response to your work, please do not be discouraged! We appreciate your time and effort and hopefully will end up someplace that is better than either the status quo or your initial proposal.

Copy link
Member

@tacaswell tacaswell left a comment

Choose a reason for hiding this comment

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

see long comment is inline.

The main concern is that the onselect calls from interactive usage (when the user drags the handles around) is still gives the full rectangle.

Anyone can dismiss this review.

@jklymak jklymak marked this pull request as draft September 15, 2021 13:01
@jklymak
Copy link
Member

jklymak commented Sep 15, 2021

I've moved to draft but feel free to move back...

@melissawm
Copy link
Member

Hi @rowlesmr - are you interested in continuing this work? If so, please mark the PR as ready for review and let us know if you need help with the rebase, we have instructions for that here. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Waiting for author
Development

Successfully merging this pull request may close these issues.

7 participants