Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
PRF: only check some artists on mousemove
Instead of walking the full hitlist of the Axes, only check artists
that ask to be part of the mouseover events.

This is still missing logic to remove the artist from the mouseover_set
when removing the artist from the Axes.
  • Loading branch information
tacaswell committed Aug 7, 2015
commit 0def4c50f2c6c84d62c4b2c6629c3bb2c2ec6eab
17 changes: 16 additions & 1 deletion lib/matplotlib/artist.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def __init__(self):
self._contains = None
self._rasterized = None
self._agg_filter = None

self._mouseover = False
self.eventson = False # fire events only if eventson
self._oid = 0 # an observer id
self._propobservers = {} # a dict from oids to funcs
Expand Down Expand Up @@ -961,6 +961,21 @@ def format_cursor_data(self, data):
data = [data]
return ', '.join('{:0.3g}'.format(item) for item in data)

@property
def mouseover(self):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just wondering, have you ever measured the performance of descriptor access vs attribute lookup. You might be quite shocked 😱

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I have not, but I made this a property for the setter functionality.

return self._mouseover

@mouseover.setter
def mouseover(self, val):
val = bool(val)
self._mouseover = val
ax = self.axes
if ax:
if val:
ax.mouseover_set.add(self)
else:
ax.mouseover_set.discard(self)


class ArtistInspector(object):
"""
Expand Down
3 changes: 3 additions & 0 deletions lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,8 @@ def _set_artist_props(self, a):
a.set_transform(self.transData)

a.axes = self
if a.mouseover:
self.mouseover_set.add(a)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Alarm bells... 🔔
What if the artist is subsequently removed from the axes? This redundancy is problematic.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The remove method takes care of this.


def _gen_axes_patch(self):
"""
Expand Down Expand Up @@ -916,6 +918,7 @@ def cla(self):
self.tables = []
self.artists = []
self.images = []
self.mouseover_set = set()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not a huge fan of the name. Is this really "artists who have mouseover enabled"? Can we come up with a better name?

self._current_image = None # strictly for pyplot via _sci, _gci
self.legend_ = None
self.collections = [] # collection.Collection instances
Expand Down
4 changes: 3 additions & 1 deletion lib/matplotlib/backend_bases.py
Original file line number Diff line number Diff line change
Expand Up @@ -2815,9 +2815,11 @@ def mouse_move(self, event):
except (ValueError, OverflowError):
pass
else:
artists = event.inaxes.hitlist(event)
artists = [a for a in event.inaxes.mouseover_set
if a.contains(event)]

if artists:

a = max(enumerate(artists), key=lambda x: x[1].zorder)[1]
if a is not event.inaxes.patch:
data = a.get_cursor_data(event)
Expand Down
2 changes: 1 addition & 1 deletion lib/matplotlib/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def __init__(self, ax,
"""
martist.Artist.__init__(self)
cm.ScalarMappable.__init__(self, norm, cmap)

self._mouseover = True
if origin is None:
origin = rcParams['image.origin']
self.origin = origin
Expand Down