Skip to content
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

Make it possible to initialize and update regions based on interactive Matplotlib widgets #317

Merged
merged 11 commits into from
Aug 6, 2020

Conversation

astrofrog
Copy link
Member

@astrofrog astrofrog commented May 21, 2020

This is a proof of concept of initializing and updating regions based on interactive Matplotlib widgets (which are now a think in matplotlib.widgets). The idea is that regions could have a as_mpl_selector method that takes the axes and returns a Matplotlib selector. The selector is then active and the region is updated as the selector is moved around and adjusted (provided sync is set to True, which is the default). Here's an example in action:

import numpy as np
import matplotlib.pyplot as plt
from regions import RectanglePixelRegion, PixCoord

data = np.random.random((16, 16))
mask = np.zeros_like(data)

plt.ion()

ax1 = plt.subplot(1, 2, 1)
ax1.imshow(data)
ax2 = plt.subplot(1, 2, 2)
im_mask = ax2.imshow(mask, vmin=0, vmax=1)


def update_mask(region):
    mask = region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape)
    im_mask.set_data(mask)


region = RectanglePixelRegion(PixCoord(3, 5), 2, 3)
selector = region.as_mpl_selector(ax1, callback=update_mask, sync=True)

plt.show(block=True)

Peek 2020-05-21 13-41

The Matplotlib widgets included in Matplotlib don't (yet) have everything we need, in particular they don't have the ability to support rotation. However, I'm going to investigate whether the Matplotlib developers would be happy to have this additional functionality. Also moving regions around is a bit obnoxious as it requires clicking on the center of the region. I'm going to see if I can patch it to allow the whole region to be clicked and dragged. But in any case, we can either improve the widgets in Matplotlib or fork it here if they won't accept improvements upstream (which I doubt).

@keflavich @larrybradley - what do you think about this approach and API?

TODOs if we agree on the approach:

  • Use the region's visual properties for the selector
  • Changelog entry
  • Tests
  • Expand approach to other region types
  • Investigate how to deal with Sky regions and WCSAxes
  • Improve Matplotlib selectors to support e.g. rotation (could potentially be done as part of another PR since we can just raise a NotImplementedError in the mean time)

@keflavich
Copy link
Contributor

Sounds like a great approach. I very much like the mpl upstream push too, though that is likely to slow adoption as mpl had historically been one of the slower packages to update.

@larrybradley
Copy link
Member

@astrofrog, that looks great. How would ellipses be drawn? If we add rotation, we'll also need a way to do that with the cursor (the usual API is to select and drag box corners). For ellipses, I assume there would be something to select on the major (and minor) axes?

@astrofrog
Copy link
Member Author

@larrybradley - the ellipse selector is very similar (just added):

ellipse

For rotation, as in some other programs, I would envision pressing a modifier key and selecting any of the anchors and dragging it around. Or we could make one of the corners be a rotation one.

@keflavich keflavich mentioned this pull request Jul 16, 2020
4 tasks
@astrofrog astrofrog changed the title POC: Make it possible to initialize and update regions based on interactive Matplotlib widgets Make it possible to initialize and update regions based on interactive Matplotlib widgets Jul 25, 2020
@codecov
Copy link

codecov bot commented Aug 3, 2020

Codecov Report

Merging #317 into master will increase coverage by 0.13%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #317      +/-   ##
==========================================
+ Coverage   92.80%   92.94%   +0.13%     
==========================================
  Files          32       32              
  Lines        2420     2468      +48     
==========================================
+ Hits         2246     2294      +48     
  Misses        174      174              
Impacted Files Coverage Δ
regions/shapes/ellipse.py 99.26% <100.00%> (+0.15%) ⬆️
regions/shapes/rectangle.py 99.34% <100.00%> (+0.12%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8c50827...0874e8f. Read the comment docs.

@astrofrog
Copy link
Member Author

I’m chasing down the remaining CI failures

@astrofrog
Copy link
Member Author

@keflavich @larrybradley - this is now ready for review!

@keflavich
Copy link
Contributor

keflavich commented Aug 5, 2020

lgtm! awesome! It deserves some documentation, but this is great!

(I reviewed, saw nothing that needed change, and I verified that the selector works as expected in a test session)

@keflavich keflavich merged commit 4b11689 into master Aug 6, 2020
@larrybradley larrybradley deleted the interactive-mpl-selections branch May 14, 2021 21:36
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.

3 participants