From 9909aeb43474d12e560695db7e3028623906389e Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 7 Apr 2020 03:26:34 -0400 Subject: [PATCH 1/2] Fix redundant dictionary update. The `for` loop is supposed to check all fields in `kw` here, but `kw` does not change, so doing `kwargs.update(kw)` in the loop is a waste. --- lib/matplotlib/axis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index d56af88b64f6..d826eee7f61f 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -879,7 +879,7 @@ def _translate_tick_kw(kw): raise ValueError( "keyword %s is not recognized; valid keywords are %s" % (key, kwkeys)) - kwtrans.update(kw) + kwtrans.update(kw) return kwtrans def set_clip_path(self, clippath, transform=None): From 222b3ba20dd51572ce30526f93fca1fb4329b3ca Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Tue, 7 Apr 2020 17:50:28 -0400 Subject: [PATCH 2/2] Avoid creating a Tick in Axis.get_tick_space. Doing so is expensive, and triggers the figure to be marked stale. We don't need a whole tick, just the font size that it will eventually use, so calculate that directly. --- lib/matplotlib/axis.py | 18 ++++++++++++++---- lib/matplotlib/tests/test_figure.py | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index d826eee7f61f..74ec577966e6 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -1315,6 +1315,18 @@ def _get_tick(self, major): """Return the default tick instance.""" raise NotImplementedError('derived must override') + def _get_tick_label_size(self, axis_name): + """ + Return the text size of tick labels for this Axis. + + This is a convenience function to avoid having to create a `Tick` in + `.get_tick_space`, since it is expensive. + """ + tick_kw = self._major_tick_kw + size = tick_kw.get('labelsize', + mpl.rcParams[f'{axis_name}tick.labelsize']) + return mtext.FontProperties(size).get_size_in_points() + def _copy_tick_props(self, src, dest): """Copy the properties from *src* tick to *dest* tick.""" if src is None or dest is None: @@ -2186,10 +2198,9 @@ def set_default_intervals(self): def get_tick_space(self): ends = self.axes.transAxes.transform([[0, 0], [1, 0]]) length = ((ends[1][0] - ends[0][0]) / self.axes.figure.dpi) * 72 - tick = self._get_tick(True) # There is a heuristic here that the aspect ratio of tick text # is no more than 3:1 - size = tick.label1.get_size() * 3 + size = self._get_tick_label_size('x') * 3 if size > 0: return int(np.floor(length / size)) else: @@ -2472,9 +2483,8 @@ def set_default_intervals(self): def get_tick_space(self): ends = self.axes.transAxes.transform([[0, 0], [0, 1]]) length = ((ends[1][1] - ends[0][1]) / self.axes.figure.dpi) * 72 - tick = self._get_tick(True) # Having a spacing of at least 2 just looks good. - size = tick.label1.get_size() * 2.0 + size = self._get_tick_label_size('y') * 2 if size > 0: return int(np.floor(length / size)) else: diff --git a/lib/matplotlib/tests/test_figure.py b/lib/matplotlib/tests/test_figure.py index 298924bf86a4..c279eaeff32e 100644 --- a/lib/matplotlib/tests/test_figure.py +++ b/lib/matplotlib/tests/test_figure.py @@ -1,6 +1,7 @@ from datetime import datetime from pathlib import Path import platform +from types import SimpleNamespace import warnings try: from contextlib import nullcontext @@ -533,3 +534,17 @@ def test_removed_axis(): fig, axs = plt.subplots(2, sharex=True) axs[0].remove() fig.canvas.draw() + + +@pytest.mark.style('mpl20') +def test_picking_does_not_stale(): + fig, ax = plt.subplots() + col = ax.scatter([0], [0], [1000], picker=True) + fig.canvas.draw() + assert not fig.stale + + mouse_event = SimpleNamespace(x=ax.bbox.x0 + ax.bbox.width / 2, + y=ax.bbox.y0 + ax.bbox.height / 2, + inaxes=ax, guiEvent=None) + fig.pick(mouse_event) + assert not fig.stale